From f80b5ea1605c9f9408c5aa386ba71c16d918ebbf Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Wed, 22 Apr 2015 10:21:45 +0000 Subject: Imported from /home/lorry/working-area/delta_gcc-tarball/gcc-5.1.0.tar.bz2. --- libgo/MERGE | 4 +- libgo/Makefile.am | 274 +- libgo/Makefile.in | 545 +-- libgo/README | 17 +- libgo/VERSION | 1 + libgo/config.h.in | 6 +- libgo/config/libtool.m4 | 38 +- libgo/config/ltmain.sh | 2 +- libgo/configure | 249 +- libgo/configure.ac | 118 +- libgo/go/archive/tar/common.go | 3 + libgo/go/archive/tar/reader.go | 470 ++- libgo/go/archive/tar/reader_test.go | 368 +- libgo/go/archive/tar/stat_atim.go | 2 +- libgo/go/archive/tar/stat_unix.go | 2 +- libgo/go/archive/tar/tar_test.go | 4 + libgo/go/archive/tar/testdata/sparse-formats.tar | Bin 0 -> 17920 bytes libgo/go/archive/tar/testdata/writer-big-long.tar | Bin 0 -> 4096 bytes libgo/go/archive/tar/testdata/xattrs.tar | Bin 0 -> 5120 bytes libgo/go/archive/tar/writer.go | 29 +- libgo/go/archive/tar/writer_test.go | 98 + libgo/go/archive/zip/reader.go | 11 +- libgo/go/archive/zip/reader_test.go | 51 +- libgo/go/archive/zip/register.go | 41 +- libgo/go/archive/zip/struct.go | 4 +- libgo/go/archive/zip/testdata/zip64-2.zip | Bin 0 -> 266 bytes libgo/go/archive/zip/writer.go | 6 + libgo/go/archive/zip/writer_test.go | 37 + libgo/go/bufio/bufio.go | 171 +- libgo/go/bufio/bufio_test.go | 362 +- libgo/go/bufio/scan.go | 33 +- libgo/go/bufio/scan_test.go | 134 +- libgo/go/bytes/bytes.go | 22 +- libgo/go/bytes/bytes_test.go | 42 +- libgo/go/bytes/compare_test.go | 4 + libgo/go/bytes/reader.go | 52 +- libgo/go/bytes/reader_test.go | 82 +- libgo/go/cmd/cgo/ast.go | 463 +++ libgo/go/cmd/cgo/doc.go | 748 ++++ libgo/go/cmd/cgo/gcc.go | 1753 +++++++++ libgo/go/cmd/cgo/godefs.go | 294 ++ libgo/go/cmd/cgo/main.go | 382 ++ libgo/go/cmd/cgo/out.go | 1334 +++++++ libgo/go/cmd/cgo/util.go | 84 + libgo/go/cmd/go/bootstrap.go | 30 + libgo/go/cmd/go/build.go | 2691 +++++++++++++ libgo/go/cmd/go/clean.go | 248 ++ libgo/go/cmd/go/context.go | 36 + libgo/go/cmd/go/discovery.go | 83 + libgo/go/cmd/go/doc.go | 1131 ++++++ libgo/go/cmd/go/env.go | 112 + libgo/go/cmd/go/fix.go | 30 + libgo/go/cmd/go/fmt.go | 38 + libgo/go/cmd/go/generate.go | 403 ++ libgo/go/cmd/go/generate_test.go | 54 + libgo/go/cmd/go/get.go | 460 +++ libgo/go/cmd/go/go11.go | 10 + libgo/go/cmd/go/go_windows_test.go | 55 + libgo/go/cmd/go/help.go | 362 ++ libgo/go/cmd/go/http.go | 87 + libgo/go/cmd/go/list.go | 209 + libgo/go/cmd/go/main.go | 723 ++++ libgo/go/cmd/go/match_test.go | 88 + libgo/go/cmd/go/mkdoc.sh | 9 + libgo/go/cmd/go/pkg.go | 969 +++++ libgo/go/cmd/go/pkg_test.go | 73 + libgo/go/cmd/go/run.go | 143 + libgo/go/cmd/go/script | 23 + libgo/go/cmd/go/script.txt | 352 ++ libgo/go/cmd/go/signal.go | 31 + libgo/go/cmd/go/signal_notunix.go | 17 + libgo/go/cmd/go/signal_unix.go | 18 + libgo/go/cmd/go/tag_test.go | 100 + libgo/go/cmd/go/test.bash | 820 ++++ libgo/go/cmd/go/test.go | 1412 +++++++ libgo/go/cmd/go/testdata/cgocover/p.go | 19 + libgo/go/cmd/go/testdata/cgocover/p_test.go | 7 + libgo/go/cmd/go/testdata/dep_test.go | 7 + libgo/go/cmd/go/testdata/example1_test.go | 23 + libgo/go/cmd/go/testdata/example2_test.go | 21 + libgo/go/cmd/go/testdata/generate/test1.go | 13 + libgo/go/cmd/go/testdata/generate/test2.go | 10 + libgo/go/cmd/go/testdata/generate/test3.go | 9 + libgo/go/cmd/go/testdata/importcom/bad.go | 3 + libgo/go/cmd/go/testdata/importcom/conflict.go | 3 + libgo/go/cmd/go/testdata/importcom/src/bad/bad.go | 1 + .../go/cmd/go/testdata/importcom/src/conflict/a.go | 1 + .../go/cmd/go/testdata/importcom/src/conflict/b.go | 1 + .../go/cmd/go/testdata/importcom/src/works/x/x.go | 1 + .../go/cmd/go/testdata/importcom/src/works/x/x1.go | 1 + .../cmd/go/testdata/importcom/src/wrongplace/x.go | 1 + libgo/go/cmd/go/testdata/importcom/works.go | 3 + libgo/go/cmd/go/testdata/importcom/wrongplace.go | 3 + libgo/go/cmd/go/testdata/local/easy.go | 7 + libgo/go/cmd/go/testdata/local/easysub/easysub.go | 7 + libgo/go/cmd/go/testdata/local/easysub/main.go | 9 + libgo/go/cmd/go/testdata/local/hard.go | 7 + libgo/go/cmd/go/testdata/local/sub/sub.go | 12 + libgo/go/cmd/go/testdata/local/sub/sub/subsub.go | 7 + .../cmd/go/testdata/norunexample/example_test.go | 11 + libgo/go/cmd/go/testdata/norunexample/test_test.go | 10 + .../go/cmd/go/testdata/shadow/root1/src/foo/foo.go | 1 + .../cmd/go/testdata/shadow/root1/src/math/math.go | 1 + .../go/cmd/go/testdata/shadow/root2/src/foo/foo.go | 1 + libgo/go/cmd/go/testdata/src/badc/x.go | 1 + libgo/go/cmd/go/testdata/src/badpkg/x.go | 1 + .../cmd/go/testdata/src/badtest/badexec/x_test.go | 5 + .../go/cmd/go/testdata/src/badtest/badsyntax/x.go | 1 + .../go/testdata/src/badtest/badsyntax/x_test.go | 3 + libgo/go/cmd/go/testdata/src/badtest/badvar/x.go | 1 + .../cmd/go/testdata/src/badtest/badvar/x_test.go | 5 + libgo/go/cmd/go/testdata/src/cgotest/m.go | 5 + .../cmd/go/testdata/src/go-cmd-test/helloworld.go | 5 + libgo/go/cmd/go/testdata/src/main_test/m.go | 4 + libgo/go/cmd/go/testdata/src/main_test/m_test.go | 10 + libgo/go/cmd/go/testdata/src/notest/hello.go | 6 + libgo/go/cmd/go/testdata/src/syntaxerror/x.go | 1 + libgo/go/cmd/go/testdata/src/syntaxerror/x_test.go | 4 + libgo/go/cmd/go/testdata/src/testcycle/p1/p1.go | 7 + .../go/cmd/go/testdata/src/testcycle/p1/p1_test.go | 6 + libgo/go/cmd/go/testdata/src/testcycle/p2/p2.go | 7 + libgo/go/cmd/go/testdata/src/testcycle/p3/p3.go | 5 + .../go/cmd/go/testdata/src/testcycle/p3/p3_test.go | 10 + libgo/go/cmd/go/testdata/src/vetpkg/a_test.go | 1 + libgo/go/cmd/go/testdata/src/vetpkg/b.go | 7 + libgo/go/cmd/go/testdata/src/xtestonly/f.go | 3 + libgo/go/cmd/go/testdata/src/xtestonly/f_test.go | 12 + libgo/go/cmd/go/testdata/standalone_test.go | 6 + libgo/go/cmd/go/testdata/testimport/p.go | 3 + libgo/go/cmd/go/testdata/testimport/p1/p1.go | 3 + libgo/go/cmd/go/testdata/testimport/p2/p2.go | 3 + libgo/go/cmd/go/testdata/testimport/p_test.go | 13 + libgo/go/cmd/go/testdata/testimport/x_test.go | 15 + libgo/go/cmd/go/testdata/testinternal/p.go | 3 + libgo/go/cmd/go/testdata/testinternal2/p.go | 3 + .../testdata/testinternal2/x/y/z/internal/w/w.go | 1 + libgo/go/cmd/go/testdata/testonly/p_test.go | 1 + libgo/go/cmd/go/testflag.go | 319 ++ libgo/go/cmd/go/testgo.go | 21 + libgo/go/cmd/go/tool.go | 146 + libgo/go/cmd/go/vcs.go | 855 +++++ libgo/go/cmd/go/vcs_test.go | 124 + libgo/go/cmd/go/version.go | 25 + libgo/go/cmd/go/vet.go | 50 + libgo/go/cmd/gofmt/doc.go | 93 + libgo/go/cmd/gofmt/gofmt.go | 387 ++ libgo/go/cmd/gofmt/gofmt_test.go | 173 + libgo/go/cmd/gofmt/long_test.go | 159 + libgo/go/cmd/gofmt/rewrite.go | 303 ++ libgo/go/cmd/gofmt/simplify.go | 161 + libgo/go/cmd/gofmt/testdata/comments.golden | 9 + libgo/go/cmd/gofmt/testdata/comments.input | 9 + libgo/go/cmd/gofmt/testdata/composites.golden | 204 + libgo/go/cmd/gofmt/testdata/composites.input | 204 + libgo/go/cmd/gofmt/testdata/crlf.golden | 13 + libgo/go/cmd/gofmt/testdata/crlf.input | 13 + libgo/go/cmd/gofmt/testdata/import.golden | 126 + libgo/go/cmd/gofmt/testdata/import.input | 131 + libgo/go/cmd/gofmt/testdata/old.golden | 9 + libgo/go/cmd/gofmt/testdata/old.input | 8 + libgo/go/cmd/gofmt/testdata/rewrite1.golden | 14 + libgo/go/cmd/gofmt/testdata/rewrite1.input | 14 + libgo/go/cmd/gofmt/testdata/rewrite2.golden | 12 + libgo/go/cmd/gofmt/testdata/rewrite2.input | 12 + libgo/go/cmd/gofmt/testdata/rewrite3.golden | 14 + libgo/go/cmd/gofmt/testdata/rewrite3.input | 14 + libgo/go/cmd/gofmt/testdata/rewrite4.golden | 76 + libgo/go/cmd/gofmt/testdata/rewrite4.input | 76 + libgo/go/cmd/gofmt/testdata/rewrite5.golden | 17 + libgo/go/cmd/gofmt/testdata/rewrite5.input | 17 + libgo/go/cmd/gofmt/testdata/rewrite6.golden | 17 + libgo/go/cmd/gofmt/testdata/rewrite6.input | 17 + libgo/go/cmd/gofmt/testdata/rewrite7.golden | 17 + libgo/go/cmd/gofmt/testdata/rewrite7.input | 17 + libgo/go/cmd/gofmt/testdata/rewrite8.golden | 12 + libgo/go/cmd/gofmt/testdata/rewrite8.input | 12 + libgo/go/cmd/gofmt/testdata/slices1.golden | 66 + libgo/go/cmd/gofmt/testdata/slices1.input | 66 + libgo/go/cmd/gofmt/testdata/slices2.golden | 63 + libgo/go/cmd/gofmt/testdata/slices2.input | 63 + libgo/go/cmd/gofmt/testdata/stdin1.golden | 5 + libgo/go/cmd/gofmt/testdata/stdin1.input | 5 + libgo/go/cmd/gofmt/testdata/stdin2.golden | 11 + libgo/go/cmd/gofmt/testdata/stdin2.input | 11 + libgo/go/cmd/gofmt/testdata/stdin3.golden | 7 + libgo/go/cmd/gofmt/testdata/stdin3.input | 5 + libgo/go/cmd/gofmt/testdata/stdin4.golden | 5 + libgo/go/cmd/gofmt/testdata/stdin4.input | 5 + libgo/go/cmd/gofmt/testdata/typeswitch.golden | 60 + libgo/go/cmd/gofmt/testdata/typeswitch.input | 60 + libgo/go/compress/bzip2/bzip2.go | 23 +- libgo/go/compress/bzip2/bzip2_test.go | 68 +- libgo/go/compress/bzip2/huffman.go | 32 +- libgo/go/compress/bzip2/move_to_front.go | 79 +- .../bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 | Bin 0 -> 124744 bytes libgo/go/compress/bzip2/testdata/e.txt.bz2 | Bin 0 -> 43149 bytes libgo/go/compress/flate/fixedhuff.go | 6 +- libgo/go/compress/flate/flate_test.go | 2 +- libgo/go/compress/flate/gen.go | 55 +- libgo/go/compress/flate/inflate.go | 41 +- libgo/go/compress/flate/inflate_test.go | 39 + libgo/go/compress/flate/reader_test.go | 2 +- libgo/go/compress/gzip/gunzip.go | 51 +- libgo/go/compress/gzip/gunzip_test.go | 77 +- libgo/go/compress/gzip/gzip.go | 11 +- libgo/go/compress/gzip/gzip_test.go | 2 +- libgo/go/compress/lzw/reader.go | 14 +- libgo/go/compress/lzw/reader_test.go | 4 +- libgo/go/compress/lzw/writer.go | 4 +- libgo/go/compress/zlib/reader.go | 80 +- libgo/go/compress/zlib/reader_test.go | 2 +- libgo/go/compress/zlib/writer.go | 7 +- libgo/go/compress/zlib/writer_test.go | 2 +- libgo/go/container/heap/heap.go | 4 +- libgo/go/container/list/list.go | 10 +- libgo/go/container/list/list_test.go | 56 + libgo/go/container/ring/ring_test.go | 8 + libgo/go/crypto/aes/aes_test.go | 28 + libgo/go/crypto/aes/cipher.go | 12 + libgo/go/crypto/aes/cipher_asm.go | 2 + libgo/go/crypto/cipher/benchmark_test.go | 139 + libgo/go/crypto/cipher/cbc.go | 55 +- libgo/go/crypto/cipher/cbc_aes_test.go | 46 +- libgo/go/crypto/cipher/cfb.go | 60 +- libgo/go/crypto/cipher/cfb_test.go | 85 +- libgo/go/crypto/cipher/cipher.go | 10 - libgo/go/crypto/cipher/ctr.go | 55 +- libgo/go/crypto/cipher/example_test.go | 4 +- libgo/go/crypto/cipher/gcm.go | 27 +- libgo/go/crypto/cipher/gcm_test.go | 16 - libgo/go/crypto/cipher/ofb.go | 42 +- libgo/go/crypto/cipher/xor.go | 84 + libgo/go/crypto/cipher/xor_test.go | 28 + libgo/go/crypto/crypto.go | 45 +- libgo/go/crypto/dsa/dsa.go | 12 +- libgo/go/crypto/ecdsa/ecdsa.go | 36 +- libgo/go/crypto/hmac/hmac_test.go | 66 +- libgo/go/crypto/md5/gen.go | 32 +- libgo/go/crypto/md5/md5.go | 2 + libgo/go/crypto/md5/md5_test.go | 13 + libgo/go/crypto/md5/md5block.go | 10 +- libgo/go/crypto/md5/md5block_decl.go | 2 +- libgo/go/crypto/md5/md5block_generic.go | 9 + libgo/go/crypto/rand/rand_linux.go | 39 + libgo/go/crypto/rand/rand_unix.go | 13 +- libgo/go/crypto/rand/util.go | 8 +- libgo/go/crypto/rand/util_test.go | 65 + libgo/go/crypto/rc4/rc4.go | 17 + libgo/go/crypto/rc4/rc4_asm.go | 2 +- libgo/go/crypto/rc4/rc4_ref.go | 11 +- libgo/go/crypto/rc4/rc4_test.go | 19 +- libgo/go/crypto/rsa/pkcs1v15.go | 55 +- libgo/go/crypto/rsa/pkcs1v15_test.go | 42 + libgo/go/crypto/rsa/pss.go | 21 +- libgo/go/crypto/rsa/rsa.go | 33 +- libgo/go/crypto/rsa/rsa_test.go | 2 +- libgo/go/crypto/sha1/sha1.go | 10 +- libgo/go/crypto/sha1/sha1_test.go | 27 + libgo/go/crypto/sha1/sha1block.go | 10 +- libgo/go/crypto/sha1/sha1block_decl.go | 2 +- libgo/go/crypto/sha1/sha1block_generic.go | 9 + libgo/go/crypto/sha256/sha256.go | 12 +- libgo/go/crypto/sha256/sha256_test.go | 18 + libgo/go/crypto/sha256/sha256block.go | 2 + libgo/go/crypto/sha256/sha256block_decl.go | 11 + libgo/go/crypto/sha512/sha512.go | 10 +- libgo/go/crypto/sha512/sha512_test.go | 18 + libgo/go/crypto/sha512/sha512block.go | 2 + libgo/go/crypto/sha512/sha512block_decl.go | 11 + libgo/go/crypto/subtle/constant_time.go | 16 +- libgo/go/crypto/subtle/constant_time_test.go | 2 + libgo/go/crypto/tls/alert.go | 2 + libgo/go/crypto/tls/cipher_suites.go | 5 + libgo/go/crypto/tls/common.go | 226 +- libgo/go/crypto/tls/conn.go | 175 +- libgo/go/crypto/tls/conn_test.go | 22 +- libgo/go/crypto/tls/generate_cert.go | 75 +- libgo/go/crypto/tls/handshake_client.go | 439 ++- libgo/go/crypto/tls/handshake_client_test.go | 3400 +++-------------- libgo/go/crypto/tls/handshake_messages.go | 209 +- libgo/go/crypto/tls/handshake_messages_test.go | 9 +- libgo/go/crypto/tls/handshake_server.go | 123 +- libgo/go/crypto/tls/handshake_server_test.go | 3972 +++----------------- libgo/go/crypto/tls/handshake_test.go | 167 + libgo/go/crypto/tls/key_agreement.go | 85 +- .../testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA | 129 + .../testdata/Client-TLSv10-ClientCert-ECDSA-RSA | 125 + .../testdata/Client-TLSv10-ClientCert-RSA-ECDSA | 128 + .../tls/testdata/Client-TLSv10-ClientCert-RSA-RSA | 124 + .../tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES | 87 + .../tls/testdata/Client-TLSv10-ECDHE-RSA-AES | 97 + libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4 | 83 + .../tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES | 89 + .../tls/testdata/Client-TLSv11-ECDHE-RSA-AES | 99 + libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4 | 83 + libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN | 97 + .../crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch | 95 + .../testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA | 134 + .../testdata/Client-TLSv12-ClientCert-ECDSA-RSA | 127 + .../testdata/Client-TLSv12-ClientCert-RSA-ECDSA | 133 + .../tls/testdata/Client-TLSv12-ClientCert-RSA-RSA | 126 + .../tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES | 89 + .../tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM | 84 + .../tls/testdata/Client-TLSv12-ECDHE-RSA-AES | 99 + libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4 | 83 + libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES | 83 + libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES | 84 + libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4 | 79 + .../tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES | 84 + .../go/crypto/tls/testdata/Server-TLSv10-RSA-3DES | 79 + libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES | 82 + libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4 | 76 + .../crypto/tls/testdata/Server-TLSv11-FallbackSCSV | 17 + libgo/go/crypto/tls/testdata/Server-TLSv11-RSA-RC4 | 76 + libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN | 122 + .../crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch | 121 + .../Server-TLSv12-CipherSuiteCertPreferenceECDSA | 91 + .../Server-TLSv12-CipherSuiteCertPreferenceRSA | 101 + .../Server-TLSv12-ClientAuthRequestedAndECDSAGiven | 122 + .../Server-TLSv12-ClientAuthRequestedAndGiven | 121 + .../Server-TLSv12-ClientAuthRequestedNotGiven | 81 + .../tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES | 89 + .../crypto/tls/testdata/Server-TLSv12-IssueTicket | 87 + .../testdata/Server-TLSv12-IssueTicketPreDisable | 87 + .../go/crypto/tls/testdata/Server-TLSv12-RSA-3DES | 83 + libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES | 87 + .../crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM | 93 + libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4 | 79 + libgo/go/crypto/tls/testdata/Server-TLSv12-Resume | 36 + .../tls/testdata/Server-TLSv12-ResumeDisabled | 87 + libgo/go/crypto/tls/testdata/Server-TLSv12-SNI | 76 + libgo/go/crypto/tls/ticket.go | 3 +- libgo/go/crypto/tls/tls.go | 86 +- libgo/go/crypto/tls/tls_test.go | 175 + libgo/go/crypto/x509/pem_decrypt_test.go | 4 +- libgo/go/crypto/x509/pkix/pkix.go | 9 +- libgo/go/crypto/x509/root_cgo_darwin.go | 79 + libgo/go/crypto/x509/root_darwin.go | 78 +- libgo/go/crypto/x509/root_nocgo_darwin.go | 11 + libgo/go/crypto/x509/root_stub.go | 14 - libgo/go/crypto/x509/root_unix.go | 29 +- libgo/go/crypto/x509/verify.go | 11 +- libgo/go/crypto/x509/verify_test.go | 367 +- libgo/go/crypto/x509/x509.go | 619 ++- libgo/go/crypto/x509/x509_test.go | 317 +- libgo/go/crypto/x509/x509_test_import.go | 53 + libgo/go/database/sql/convert.go | 50 +- libgo/go/database/sql/convert_test.go | 67 + libgo/go/database/sql/driver/driver.go | 2 +- libgo/go/database/sql/fakedb_test.go | 56 +- libgo/go/database/sql/sql.go | 354 +- libgo/go/database/sql/sql_test.go | 209 +- libgo/go/debug/dwarf/const.go | 35 +- libgo/go/debug/dwarf/entry.go | 16 +- libgo/go/debug/dwarf/open.go | 10 + libgo/go/debug/dwarf/testdata/typedef.elf4 | Bin 0 -> 9496 bytes libgo/go/debug/dwarf/type.go | 160 +- libgo/go/debug/dwarf/type_test.go | 2 + libgo/go/debug/dwarf/typeunit.go | 166 + libgo/go/debug/dwarf/unit.go | 2 +- libgo/go/debug/elf/elf.go | 246 +- libgo/go/debug/elf/elf_test.go | 2 +- libgo/go/debug/elf/file.go | 273 +- libgo/go/debug/elf/file_test.go | 26 +- libgo/go/debug/elf/symbols_test.go | 834 ++++ .../elf/testdata/go-relocation-test-clang-x86.obj | Bin 0 -> 1900 bytes .../testdata/go-relocation-test-gcc482-aarch64.obj | Bin 0 -> 3392 bytes .../testdata/go-relocation-test-gcc482-ppc64le.obj | Bin 0 -> 3016 bytes .../elf/testdata/go-relocation-test-gcc5-ppc.obj | Bin 0 -> 2356 bytes libgo/go/debug/elf/testdata/hello.c | 7 + libgo/go/debug/gosym/pclntab.go | 27 + libgo/go/debug/gosym/symtab.go | 9 +- libgo/go/debug/macho/fat.go | 146 + libgo/go/debug/macho/file.go | 23 +- libgo/go/debug/macho/file_test.go | 43 + libgo/go/debug/macho/macho.go | 23 +- .../macho/testdata/fat-gcc-386-amd64-darwin-exec | Bin 0 -> 28992 bytes libgo/go/debug/pe/file.go | 60 +- libgo/go/debug/pe/file_test.go | 146 +- libgo/go/debug/pe/pe.go | 72 + libgo/go/debug/pe/testdata/gcc-amd64-mingw-exec | Bin 0 -> 273083 bytes libgo/go/debug/pe/testdata/gcc-amd64-mingw-obj | Bin 0 -> 736 bytes libgo/go/debug/plan9obj/file.go | 328 ++ libgo/go/debug/plan9obj/file_test.go | 81 + libgo/go/debug/plan9obj/plan9obj.go | 36 + libgo/go/debug/plan9obj/testdata/386-plan9-exec | Bin 0 -> 37232 bytes libgo/go/debug/plan9obj/testdata/amd64-plan9-exec | Bin 0 -> 34279 bytes libgo/go/debug/plan9obj/testdata/hello.c | 8 + libgo/go/encoding/ascii85/ascii85.go | 13 +- libgo/go/encoding/ascii85/ascii85_test.go | 21 +- libgo/go/encoding/asn1/asn1.go | 73 +- libgo/go/encoding/asn1/asn1_test.go | 128 + libgo/go/encoding/asn1/marshal.go | 75 +- libgo/go/encoding/asn1/marshal_test.go | 16 + libgo/go/encoding/base32/base32.go | 58 +- libgo/go/encoding/base32/base32_test.go | 24 +- libgo/go/encoding/base64/base64.go | 65 +- libgo/go/encoding/base64/base64_test.go | 43 +- libgo/go/encoding/binary/binary.go | 78 +- libgo/go/encoding/binary/binary_test.go | 51 +- libgo/go/encoding/binary/varint_test.go | 8 +- libgo/go/encoding/csv/reader.go | 6 - libgo/go/encoding/csv/writer.go | 16 +- libgo/go/encoding/csv/writer_test.go | 13 + libgo/go/encoding/gob/codec_test.go | 389 +- libgo/go/encoding/gob/debug.go | 6 +- libgo/go/encoding/gob/dec_helpers.go | 468 +++ libgo/go/encoding/gob/decgen.go | 240 ++ libgo/go/encoding/gob/decode.go | 731 ++-- libgo/go/encoding/gob/decoder.go | 57 +- libgo/go/encoding/gob/enc_helpers.go | 414 ++ libgo/go/encoding/gob/encgen.go | 218 ++ libgo/go/encoding/gob/encode.go | 484 ++- libgo/go/encoding/gob/encoder.go | 11 +- libgo/go/encoding/gob/encoder_test.go | 102 +- libgo/go/encoding/gob/gobencdec_test.go | 26 +- libgo/go/encoding/gob/timing_test.go | 258 +- libgo/go/encoding/gob/type.go | 76 +- libgo/go/encoding/hex/hex.go | 3 + libgo/go/encoding/hex/hex_test.go | 6 +- libgo/go/encoding/json/decode.go | 60 +- libgo/go/encoding/json/decode_test.go | 61 +- libgo/go/encoding/json/encode.go | 59 +- libgo/go/encoding/json/encode_test.go | 109 +- libgo/go/encoding/json/fold.go | 143 + libgo/go/encoding/json/fold_test.go | 116 + libgo/go/encoding/json/indent.go | 5 +- libgo/go/encoding/json/scanner_test.go | 22 +- libgo/go/encoding/json/stream.go | 6 +- libgo/go/encoding/xml/marshal.go | 11 +- libgo/go/encoding/xml/marshal_test.go | 115 + libgo/go/encoding/xml/read.go | 11 +- libgo/go/encoding/xml/read_test.go | 27 + libgo/go/encoding/xml/typeinfo.go | 3 + libgo/go/encoding/xml/xml.go | 12 + libgo/go/encoding/xml/xml_test.go | 31 +- libgo/go/expvar/expvar.go | 62 +- libgo/go/expvar/expvar_test.go | 32 +- libgo/go/flag/flag.go | 33 +- libgo/go/flag/flag_test.go | 10 + libgo/go/fmt/doc.go | 95 +- libgo/go/fmt/fmt_test.go | 411 +- libgo/go/fmt/format.go | 223 +- libgo/go/fmt/print.go | 279 +- libgo/go/fmt/scan.go | 11 +- libgo/go/fmt/scan_test.go | 32 + libgo/go/go/ast/ast.go | 6 +- libgo/go/go/ast/commentmap.go | 2 +- libgo/go/go/ast/scope.go | 2 +- libgo/go/go/ast/walk.go | 4 +- libgo/go/go/build/build.go | 263 +- libgo/go/go/build/build_test.go | 52 +- libgo/go/go/build/deps_test.go | 26 +- libgo/go/go/build/doc.go | 23 +- libgo/go/go/build/syslist.go | 4 +- libgo/go/go/build/testdata/multi/file.go | 5 + libgo/go/go/build/testdata/multi/file_appengine.go | 5 + libgo/go/go/doc/comment.go | 49 +- libgo/go/go/doc/comment_test.go | 106 +- libgo/go/go/doc/example.go | 15 +- libgo/go/go/doc/exports.go | 26 +- libgo/go/go/doc/headscan.go | 15 +- libgo/go/go/doc/testdata/blank.0.golden | 37 + libgo/go/go/doc/testdata/blank.1.golden | 46 + libgo/go/go/doc/testdata/blank.2.golden | 37 + libgo/go/go/doc/testdata/blank.go | 38 + libgo/go/go/format/format.go | 221 +- libgo/go/go/format/format_test.go | 6 +- libgo/go/go/parser/error_test.go | 24 +- libgo/go/go/parser/interface.go | 7 + libgo/go/go/parser/parser.go | 145 +- libgo/go/go/parser/parser_test.go | 41 +- libgo/go/go/parser/short_test.go | 31 +- libgo/go/go/printer/nodes.go | 109 +- libgo/go/go/printer/printer.go | 125 +- libgo/go/go/printer/printer_test.go | 19 +- libgo/go/go/printer/testdata/comments.golden | 13 +- libgo/go/go/printer/testdata/comments.input | 12 +- libgo/go/go/printer/testdata/comments2.golden | 26 + libgo/go/go/printer/testdata/comments2.input | 28 +- libgo/go/go/printer/testdata/declarations.golden | 43 +- libgo/go/go/printer/testdata/declarations.input | 46 +- libgo/go/go/printer/testdata/expressions.golden | 5 + libgo/go/go/printer/testdata/expressions.input | 5 + libgo/go/go/printer/testdata/expressions.raw | 5 + libgo/go/go/printer/testdata/statements.golden | 11 +- libgo/go/go/printer/testdata/statements.input | 5 + libgo/go/go/scanner/scanner.go | 118 +- libgo/go/go/scanner/scanner_test.go | 103 +- libgo/go/go/token/position.go | 51 +- libgo/go/go/token/position_test.go | 101 +- libgo/go/go/types/testdata/builtins.src | 302 -- libgo/go/go/types/testdata/const0.src | 215 -- libgo/go/go/types/testdata/conversions.src | 18 - libgo/go/go/types/testdata/decls0.src | 177 - libgo/go/go/types/testdata/decls1.src | 132 - libgo/go/go/types/testdata/decls2a.src | 67 - libgo/go/go/types/testdata/decls2b.src | 28 - libgo/go/go/types/testdata/decls3.src | 231 -- libgo/go/go/types/testdata/expr0.src | 151 - libgo/go/go/types/testdata/expr1.src | 7 - libgo/go/go/types/testdata/expr2.src | 23 - libgo/go/go/types/testdata/expr3.src | 367 -- libgo/go/go/types/testdata/stmt0.src | 274 -- libgo/go/hash/crc32/crc32.go | 4 +- libgo/go/hash/crc32/crc32_amd64.go | 25 - libgo/go/hash/crc32/crc32_amd64x.go | 27 + libgo/go/hash/fnv/fnv.go | 3 +- libgo/go/html/escape_test.go | 18 + libgo/go/html/template/attr.go | 4 +- libgo/go/html/template/content.go | 3 +- libgo/go/html/template/context.go | 4 +- libgo/go/html/template/error.go | 16 +- libgo/go/html/template/escape.go | 116 +- libgo/go/html/template/escape_test.go | 55 +- libgo/go/html/template/html.go | 4 +- libgo/go/html/template/js.go | 2 +- libgo/go/html/template/js_test.go | 2 +- libgo/go/html/template/template.go | 48 +- libgo/go/html/template/transition.go | 12 +- libgo/go/image/color/palette/gen.go | 96 +- libgo/go/image/color/palette/generate.go | 8 + libgo/go/image/color/palette/palette.go | 7 +- libgo/go/image/gif/reader.go | 29 +- libgo/go/image/gif/reader_test.go | 68 +- libgo/go/image/gif/writer.go | 18 +- libgo/go/image/gif/writer_test.go | 25 +- libgo/go/image/image.go | 32 + libgo/go/image/jpeg/huffman.go | 253 +- libgo/go/image/jpeg/reader.go | 210 +- libgo/go/image/jpeg/reader_test.go | 72 +- libgo/go/image/jpeg/scan.go | 78 +- libgo/go/image/jpeg/writer.go | 133 +- libgo/go/image/jpeg/writer_test.go | 28 + libgo/go/image/png/paeth.go | 41 +- libgo/go/image/png/paeth_test.go | 8 +- libgo/go/image/png/reader.go | 215 +- libgo/go/image/png/reader_test.go | 16 +- libgo/go/image/png/testdata/benchGray.png | Bin 0 -> 14709 bytes .../go/image/png/testdata/benchNRGBA-gradient.png | Bin 0 -> 58831 bytes libgo/go/image/png/testdata/benchNRGBA-opaque.png | Bin 0 -> 44237 bytes libgo/go/image/png/testdata/benchPaletted.png | Bin 0 -> 13397 bytes libgo/go/image/png/testdata/benchRGB.png | Bin 0 -> 39571 bytes libgo/go/image/png/writer.go | 62 +- libgo/go/image/png/writer_test.go | 29 +- .../video-001.separate.dc.progression.jpeg | Bin 0 -> 14288 bytes ...eo-001.separate.dc.progression.progressive.jpeg | Bin 0 -> 14312 bytes libgo/go/image/testdata/video-005.gray.gif | Bin 0 -> 14505 bytes libgo/go/image/ycbcr.go | 4 + libgo/go/index/suffixarray/suffixarray_test.go | 2 +- libgo/go/internal/syscall/dummy.go | 5 + libgo/go/internal/syscall/getrandom_linux.go | 56 + libgo/go/io/io.go | 14 +- libgo/go/io/io_test.go | 20 + libgo/go/io/ioutil/blackhole.go | 23 - libgo/go/io/ioutil/ioutil.go | 14 +- libgo/go/io/multi.go | 11 +- libgo/go/io/multi_test.go | 27 + libgo/go/log/syslog/syslog.go | 5 +- libgo/go/log/syslog/syslog_test.go | 4 +- libgo/go/log/syslog/syslog_unix.go | 4 +- libgo/go/math/all_test.go | 77 +- libgo/go/math/big/arith.go | 14 +- libgo/go/math/big/int.go | 91 +- libgo/go/math/big/int_test.go | 117 +- libgo/go/math/big/nat.go | 11 +- libgo/go/math/big/nat_test.go | 27 +- libgo/go/math/big/rat.go | 201 +- libgo/go/math/big/rat_test.go | 261 +- libgo/go/math/cmplx/cmath_test.go | 13 + libgo/go/math/cmplx/pow.go | 18 + libgo/go/math/cmplx/sqrt.go | 1 + libgo/go/math/ldexp.go | 10 - libgo/go/math/nextafter.go | 32 +- libgo/go/math/rand/rand.go | 52 +- libgo/go/math/rand/rand_test.go | 39 + libgo/go/math/rand/regress_test.go | 355 ++ libgo/go/math/sqrt.go | 2 +- libgo/go/mime/mediatype.go | 10 +- libgo/go/mime/mediatype_test.go | 1 + libgo/go/mime/multipart/formdata_test.go | 3 +- libgo/go/mime/multipart/multipart.go | 11 +- libgo/go/mime/multipart/quotedprintable_test.go | 2 +- libgo/go/mime/multipart/writer_test.go | 15 + libgo/go/mime/type.go | 84 +- libgo/go/mime/type_plan9.go | 2 +- libgo/go/mime/type_test.go | 42 +- libgo/go/mime/type_unix.go | 4 +- libgo/go/mime/type_windows.go | 2 +- libgo/go/net/cgo_android.go | 14 + libgo/go/net/cgo_bsd.go | 2 +- libgo/go/net/cgo_linux.go | 2 +- libgo/go/net/cgo_unix_test.go | 24 + libgo/go/net/conn_test.go | 39 +- libgo/go/net/dial.go | 42 +- libgo/go/net/dial_test.go | 105 +- libgo/go/net/dialgoogle_test.go | 26 +- libgo/go/net/dnsclient.go | 8 +- libgo/go/net/dnsclient_test.go | 69 + libgo/go/net/dnsclient_unix.go | 392 +- libgo/go/net/dnsclient_unix_test.go | 235 +- libgo/go/net/dnsconfig_unix.go | 54 +- libgo/go/net/dnsconfig_unix_test.go | 69 + libgo/go/net/fd_mutex_test.go | 27 +- libgo/go/net/fd_plan9.go | 115 +- libgo/go/net/fd_poll_nacl.go | 94 + libgo/go/net/fd_poll_runtime.go | 7 +- libgo/go/net/fd_unix.go | 80 +- libgo/go/net/fd_unix_test.go | 2 +- libgo/go/net/fd_windows.go | 43 +- libgo/go/net/file_plan9.go | 10 +- libgo/go/net/file_stub.go | 38 + libgo/go/net/file_test.go | 10 +- libgo/go/net/file_unix.go | 4 +- libgo/go/net/hosts.go | 2 +- libgo/go/net/hosts_test.go | 2 +- libgo/go/net/http/cgi/host.go | 27 + libgo/go/net/http/cgi/matryoshka_test.go | 137 +- libgo/go/net/http/chunked.go | 183 - libgo/go/net/http/chunked_test.go | 93 - libgo/go/net/http/client.go | 137 +- libgo/go/net/http/client_test.go | 312 +- libgo/go/net/http/cookie.go | 62 +- libgo/go/net/http/cookie_test.go | 139 +- libgo/go/net/http/cookiejar/jar.go | 2 +- libgo/go/net/http/export_test.go | 54 +- libgo/go/net/http/fcgi/child.go | 19 +- libgo/go/net/http/fs.go | 61 +- libgo/go/net/http/fs_test.go | 129 +- libgo/go/net/http/header.go | 19 +- libgo/go/net/http/header_test.go | 9 +- libgo/go/net/http/httptest/server.go | 2 +- libgo/go/net/http/httputil/chunked.go | 185 - libgo/go/net/http/httputil/chunked_test.go | 95 - libgo/go/net/http/httputil/dump.go | 45 +- libgo/go/net/http/httputil/dump_test.go | 115 +- libgo/go/net/http/httputil/httputil.go | 39 + libgo/go/net/http/httputil/persist.go | 21 +- libgo/go/net/http/httputil/reverseproxy.go | 20 +- libgo/go/net/http/httputil/reverseproxy_test.go | 16 + libgo/go/net/http/internal/chunked.go | 202 + libgo/go/net/http/internal/chunked_test.go | 156 + libgo/go/net/http/main_test.go | 109 + libgo/go/net/http/pprof/pprof.go | 4 + libgo/go/net/http/proxy_test.go | 19 +- libgo/go/net/http/race.go | 11 + libgo/go/net/http/readrequest_test.go | 41 +- libgo/go/net/http/request.go | 199 +- libgo/go/net/http/request_test.go | 203 +- libgo/go/net/http/requestwrite_test.go | 104 +- libgo/go/net/http/response.go | 68 +- libgo/go/net/http/response_test.go | 51 +- libgo/go/net/http/responsewrite_test.go | 123 +- libgo/go/net/http/serve_test.go | 838 ++++- libgo/go/net/http/server.go | 348 +- libgo/go/net/http/transfer.go | 172 +- libgo/go/net/http/transfer_test.go | 33 +- libgo/go/net/http/transport.go | 506 ++- libgo/go/net/http/transport_test.go | 716 +++- libgo/go/net/http/z_last_test.go | 97 - libgo/go/net/interface.go | 10 +- libgo/go/net/interface_linux.go | 58 +- libgo/go/net/interface_stub.go | 2 +- libgo/go/net/ip.go | 41 +- libgo/go/net/ip_test.go | 27 + libgo/go/net/ipraw_test.go | 9 +- libgo/go/net/iprawsock_posix.go | 22 +- libgo/go/net/ipsock.go | 6 +- libgo/go/net/ipsock_plan9.go | 66 +- libgo/go/net/ipsock_posix.go | 13 +- libgo/go/net/lookup.go | 51 +- libgo/go/net/lookup_plan9.go | 46 +- libgo/go/net/lookup_stub.go | 49 + libgo/go/net/lookup_test.go | 164 +- libgo/go/net/lookup_unix.go | 2 +- libgo/go/net/lookup_windows.go | 79 +- libgo/go/net/mail/message.go | 33 +- libgo/go/net/mail/message_test.go | 27 + libgo/go/net/multicast_test.go | 8 +- libgo/go/net/net.go | 16 +- libgo/go/net/net_test.go | 25 +- libgo/go/net/packetconn_test.go | 32 +- libgo/go/net/parse.go | 24 +- libgo/go/net/parse_test.go | 4 +- libgo/go/net/port_test.go | 6 + libgo/go/net/port_unix.go | 12 +- libgo/go/net/protoconn_test.go | 6 +- libgo/go/net/rpc/client.go | 22 +- libgo/go/net/rpc/client_test.go | 91 + libgo/go/net/rpc/debug.go | 2 +- libgo/go/net/rpc/jsonrpc/all_test.go | 35 + libgo/go/net/rpc/jsonrpc/server.go | 6 +- libgo/go/net/rpc/server.go | 30 +- libgo/go/net/rpc/server_test.go | 38 +- libgo/go/net/sendfile_dragonfly.go | 2 +- libgo/go/net/sendfile_freebsd.go | 2 +- libgo/go/net/sendfile_stub.go | 2 +- libgo/go/net/server_test.go | 86 +- libgo/go/net/singleflight.go | 66 +- libgo/go/net/smtp/smtp.go | 8 +- libgo/go/net/smtp/smtp_test.go | 144 + libgo/go/net/sock_cloexec.go | 47 +- libgo/go/net/sock_posix.go | 70 +- libgo/go/net/sock_solaris.go | 18 - libgo/go/net/sock_stub.go | 15 + libgo/go/net/sockopt_bsd.go | 13 + libgo/go/net/sockopt_plan9.go | 13 + libgo/go/net/sockopt_posix.go | 2 +- libgo/go/net/sockopt_solaris.go | 32 + libgo/go/net/sockopt_stub.go | 37 + libgo/go/net/sockoptip_stub.go | 39 + libgo/go/net/sys_cloexec.go | 18 +- libgo/go/net/tcp_test.go | 53 +- libgo/go/net/tcpsock_plan9.go | 29 +- libgo/go/net/tcpsock_posix.go | 29 +- libgo/go/net/tcpsockopt_darwin.go | 12 +- libgo/go/net/tcpsockopt_dragonfly.go | 26 + libgo/go/net/tcpsockopt_openbsd.go | 17 +- libgo/go/net/tcpsockopt_plan9.go | 18 + libgo/go/net/tcpsockopt_posix.go | 2 +- libgo/go/net/tcpsockopt_solaris.go | 27 + libgo/go/net/tcpsockopt_stub.go | 20 + libgo/go/net/tcpsockopt_unix.go | 10 +- libgo/go/net/tcpsockopt_windows.go | 21 +- libgo/go/net/testdata/domain-resolv.conf | 5 + libgo/go/net/testdata/empty-resolv.conf | 1 + libgo/go/net/testdata/resolv.conf | 8 + libgo/go/net/testdata/search-resolv.conf | 5 + libgo/go/net/textproto/reader.go | 112 +- libgo/go/net/textproto/reader_test.go | 29 +- libgo/go/net/timeout_test.go | 25 +- libgo/go/net/udp_test.go | 45 + libgo/go/net/udpsock.go | 4 - libgo/go/net/udpsock_plan9.go | 3 +- libgo/go/net/udpsock_posix.go | 16 +- libgo/go/net/unicast_posix_test.go | 10 +- libgo/go/net/unix_test.go | 84 +- libgo/go/net/unixsock_posix.go | 33 +- libgo/go/net/url/url.go | 31 +- libgo/go/net/url/url_test.go | 67 + libgo/go/net/z_last_test.go | 99 + libgo/go/os/dir_unix.go | 4 +- libgo/go/os/doc.go | 3 + libgo/go/os/env.go | 5 + libgo/go/os/env_test.go | 26 + libgo/go/os/env_unix_test.go | 2 +- libgo/go/os/error_plan9.go | 3 +- libgo/go/os/error_unix.go | 2 +- libgo/go/os/exec/exec.go | 101 +- libgo/go/os/exec/exec_test.go | 166 +- libgo/go/os/exec/lp_unix.go | 2 +- libgo/go/os/exec/lp_unix_test.go | 2 +- libgo/go/os/exec_plan9.go | 9 +- libgo/go/os/exec_posix.go | 2 +- libgo/go/os/exec_unix.go | 15 +- libgo/go/os/exec_windows.go | 3 + libgo/go/os/file.go | 17 + libgo/go/os/file_plan9.go | 44 +- libgo/go/os/file_posix.go | 29 +- libgo/go/os/file_unix.go | 92 +- libgo/go/os/getwd.go | 52 +- libgo/go/os/os_test.go | 337 +- libgo/go/os/os_unix_test.go | 40 +- libgo/go/os/path.go | 16 +- libgo/go/os/path_test.go | 14 +- libgo/go/os/path_unix.go | 2 +- libgo/go/os/pipe_bsd.go | 2 +- libgo/go/os/proc.go | 15 +- libgo/go/os/signal/signal_test.go | 8 +- libgo/go/os/signal/signal_unix.go | 2 +- libgo/go/os/stat_nacl.go | 62 + libgo/go/os/stat_solaris.go | 7 +- libgo/go/os/sys_bsd.go | 2 +- libgo/go/os/sys_darwin.go | 31 + libgo/go/os/sys_freebsd.go | 23 + libgo/go/os/sys_nacl.go | 9 + libgo/go/os/sys_unix.go | 11 + libgo/go/os/types_windows.go | 3 + libgo/go/os/user/lookup_stubs.go | 2 +- libgo/go/os/user/lookup_unix.go | 2 +- libgo/go/path/filepath/export_test.go | 7 + libgo/go/path/filepath/match.go | 10 +- libgo/go/path/filepath/match_test.go | 58 +- libgo/go/path/filepath/path.go | 49 +- libgo/go/path/filepath/path_plan9.go | 4 + libgo/go/path/filepath/path_test.go | 96 +- libgo/go/path/filepath/path_unix.go | 6 +- libgo/go/path/filepath/path_windows.go | 5 + libgo/go/path/filepath/symlink.go | 19 +- libgo/go/path/filepath/symlink_unix.go | 7 + libgo/go/path/filepath/symlink_windows.go | 5 + libgo/go/path/path.go | 10 +- libgo/go/reflect/all_test.go | 541 ++- libgo/go/reflect/deepequal.go | 3 - libgo/go/reflect/export_test.go | 9 + libgo/go/reflect/makefunc.go | 87 +- libgo/go/reflect/makefunc_386.S | 230 -- libgo/go/reflect/makefunc_amd64.S | 177 - libgo/go/reflect/makefunc_dummy.c | 12 - libgo/go/reflect/makefunc_ffi.go | 63 + libgo/go/reflect/makefunc_ffi_c.c | 93 + libgo/go/reflect/makefuncgo_386.go | 143 - libgo/go/reflect/makefuncgo_amd64.go | 493 --- libgo/go/reflect/type.go | 356 +- libgo/go/reflect/value.go | 1061 +++--- libgo/go/regexp/all_test.go | 76 + libgo/go/regexp/exec.go | 121 +- libgo/go/regexp/onepass.go | 581 +++ libgo/go/regexp/onepass_test.go | 208 + libgo/go/regexp/regexp.go | 22 +- libgo/go/regexp/syntax/doc.go | 46 +- libgo/go/regexp/syntax/parse.go | 44 +- libgo/go/regexp/syntax/parse_test.go | 17 +- libgo/go/regexp/syntax/perl_groups.go | 4 + libgo/go/regexp/syntax/prog.go | 54 +- libgo/go/regexp/syntax/prog_test.go | 4 +- libgo/go/regexp/syntax/regexp.go | 2 +- libgo/go/runtime/append_test.go | 19 + libgo/go/runtime/arch_386.go | 8 + libgo/go/runtime/arch_amd64.go | 8 + libgo/go/runtime/arch_amd64p32.go | 8 + libgo/go/runtime/arch_arm.go | 8 + libgo/go/runtime/atomic.go | 51 + libgo/go/runtime/cgocall.go | 279 ++ libgo/go/runtime/cgocallback.go | 40 + libgo/go/runtime/chan.go | 655 ++++ libgo/go/runtime/chan_test.go | 747 +++- libgo/go/runtime/complex.go | 52 + libgo/go/runtime/cpuprof.go | 425 +++ libgo/go/runtime/crash_cgo_test.go | 146 +- libgo/go/runtime/crash_test.go | 249 +- libgo/go/runtime/debug/garbage.go | 20 +- libgo/go/runtime/debug/heapdump_test.go | 33 + libgo/go/runtime/debug/stack.go | 6 + libgo/go/runtime/env_posix.go | 58 + libgo/go/runtime/error.go | 7 +- libgo/go/runtime/export_test.go | 34 +- libgo/go/runtime/extern.go | 37 +- libgo/go/runtime/gc_test.go | 139 + libgo/go/runtime/gcinfo_test.go | 194 + libgo/go/runtime/hashmap.go | 960 +++++ libgo/go/runtime/hashmap_fast.go | 379 ++ libgo/go/runtime/lfstack_test.go | 12 +- libgo/go/runtime/lock_futex.go | 205 + libgo/go/runtime/lock_sema.go | 270 ++ libgo/go/runtime/malloc.go | 837 +++++ libgo/go/runtime/malloc1.go | 26 - libgo/go/runtime/mallocrand.go | 93 - libgo/go/runtime/mallocrep.go | 72 - libgo/go/runtime/mallocrep1.go | 144 - libgo/go/runtime/map_test.go | 145 +- libgo/go/runtime/mapspeed_test.go | 34 +- libgo/go/runtime/mem.go | 7 +- libgo/go/runtime/memmove_test.go | 231 +- libgo/go/runtime/mfinal_test.go | 201 +- libgo/go/runtime/mgc0.go | 137 + libgo/go/runtime/mprof.go | 668 ++++ libgo/go/runtime/netpoll.go | 455 +++ libgo/go/runtime/netpoll_epoll.go | 97 + libgo/go/runtime/netpoll_kqueue.go | 101 + libgo/go/runtime/netpoll_nacl.go | 26 + libgo/go/runtime/noasm_arm.go | 54 + libgo/go/runtime/norace_test.go | 36 +- libgo/go/runtime/os_darwin.go | 24 + libgo/go/runtime/os_dragonfly.go | 20 + libgo/go/runtime/os_freebsd.go | 17 + libgo/go/runtime/os_linux.go | 17 + libgo/go/runtime/os_nacl.go | 39 + libgo/go/runtime/os_netbsd.go | 20 + libgo/go/runtime/os_openbsd.go | 17 + libgo/go/runtime/os_plan9.go | 105 + libgo/go/runtime/os_solaris.go | 100 + libgo/go/runtime/os_windows.go | 58 + libgo/go/runtime/os_windows_386.go | 11 + libgo/go/runtime/os_windows_amd64.go | 11 + libgo/go/runtime/panic.go | 505 +++ libgo/go/runtime/pprof/mprof_test.go | 101 + libgo/go/runtime/pprof/pprof.go | 22 +- libgo/go/runtime/pprof/pprof_test.go | 147 +- libgo/go/runtime/print1.go | 323 ++ libgo/go/runtime/proc.go | 246 ++ libgo/go/runtime/proc_test.go | 66 +- libgo/go/runtime/race0.go | 37 + libgo/go/runtime/rdebug.go | 37 + libgo/go/runtime/rune.go | 219 ++ libgo/go/runtime/runtime.go | 60 + libgo/go/runtime/runtime_test.go | 131 +- libgo/go/runtime/runtime_unix_test.go | 56 + libgo/go/runtime/select.go | 651 ++++ libgo/go/runtime/sema.go | 275 ++ libgo/go/runtime/signal_unix.go | 13 + libgo/go/runtime/sigpanic_unix.go | 40 + libgo/go/runtime/sigqueue.go | 182 + libgo/go/runtime/slice.go | 139 + libgo/go/runtime/stack.go | 13 + libgo/go/runtime/string.go | 298 ++ libgo/go/runtime/stubs.go | 316 ++ libgo/go/runtime/syscall_windows.go | 174 + libgo/go/runtime/time.go | 289 ++ libgo/go/runtime/type.go | 55 - libgo/go/runtime/typekind.go | 44 + libgo/go/runtime/vlrt.go | 258 ++ libgo/go/sort/sort.go | 6 +- libgo/go/strconv/atob_test.go | 34 + libgo/go/strconv/atof.go | 11 - libgo/go/strconv/atoi.go | 10 +- libgo/go/strconv/isprint.go | 202 +- libgo/go/strconv/makeisprint.go | 69 +- libgo/go/strconv/quote.go | 19 +- libgo/go/strconv/quote_example_test.go | 35 + libgo/go/strconv/quote_test.go | 5 + libgo/go/strings/example_test.go | 32 +- libgo/go/strings/reader.go | 52 +- libgo/go/strings/reader_test.go | 56 +- libgo/go/strings/replace.go | 149 +- libgo/go/strings/replace_test.go | 60 +- libgo/go/strings/strings.go | 81 +- libgo/go/strings/strings_test.go | 60 +- libgo/go/sync/atomic/64bit_arm.go | 12 + libgo/go/sync/atomic/atomic_test.go | 23 +- libgo/go/sync/atomic/doc.go | 2 - libgo/go/sync/atomic/race.go | 276 -- libgo/go/sync/atomic/value.go | 85 + libgo/go/sync/atomic/value_test.go | 195 + libgo/go/sync/mutex_test.go | 72 +- libgo/go/sync/once.go | 7 +- libgo/go/sync/once_test.go | 51 +- libgo/go/sync/pool.go | 225 ++ libgo/go/sync/pool_test.go | 164 + libgo/go/sync/runtime.go | 8 +- libgo/go/sync/runtime_sema_test.go | 85 +- libgo/go/sync/rwmutex.go | 10 +- libgo/go/sync/rwmutex_test.go | 121 +- libgo/go/sync/waitgroup.go | 21 +- libgo/go/sync/waitgroup_test.go | 125 +- libgo/go/syscall/consistency_unix_test.go | 34 - libgo/go/syscall/dir_plan9.go | 9 +- libgo/go/syscall/env_plan9.go | 86 +- libgo/go/syscall/env_unix.go | 62 +- libgo/go/syscall/env_windows.go | 8 + libgo/go/syscall/exec_linux.go | 130 +- libgo/go/syscall/exec_unix.go | 5 +- libgo/go/syscall/exec_windows.go | 15 +- libgo/go/syscall/export_test.go | 7 + libgo/go/syscall/libcall_linux_s390.go | 7 + libgo/go/syscall/libcall_linux_s390x.go | 7 + libgo/go/syscall/libcall_posix.go | 11 +- libgo/go/syscall/libcall_posix_largefile.go | 6 + libgo/go/syscall/libcall_posix_regfile.go | 6 + libgo/go/syscall/lsf_linux.go | 4 +- libgo/go/syscall/mksyscall.awk | 9 +- libgo/go/syscall/mmap_unix_test.go | 22 + libgo/go/syscall/netlink_linux.go | 3 +- libgo/go/syscall/passfd_test.go | 206 - libgo/go/syscall/rlimit_linux_test.go | 41 - libgo/go/syscall/route_bsd.go | 11 +- libgo/go/syscall/route_dragonfly.go | 2 +- libgo/go/syscall/route_freebsd.go | 12 +- libgo/go/syscall/route_freebsd_32bit.go | 24 + libgo/go/syscall/route_freebsd_64bit.go | 14 + libgo/go/syscall/route_netbsd.go | 2 +- libgo/go/syscall/route_openbsd.go | 8 +- libgo/go/syscall/sockcmsg_unix.go | 8 +- libgo/go/syscall/socket.go | 50 +- libgo/go/syscall/socket_posix.go | 4 +- libgo/go/syscall/socket_xnet.go | 4 +- libgo/go/syscall/str.go | 6 +- libgo/go/syscall/syscall.go | 12 + libgo/go/syscall/syscall_errno.go | 2 +- libgo/go/syscall/syscall_linux_386.go | 3 + libgo/go/syscall/syscall_linux_s390.go | 21 + libgo/go/syscall/syscall_linux_s390x.go | 21 + libgo/go/syscall/syscall_test.go | 17 + libgo/go/syscall/syscall_unix.go | 9 +- libgo/go/syscall/syscall_unix_test.go | 318 ++ libgo/go/testing/allocs_test.go | 29 + libgo/go/testing/benchmark.go | 118 +- libgo/go/testing/benchmark_test.go | 55 + libgo/go/testing/cover.go | 28 +- libgo/go/testing/example.go | 6 +- libgo/go/testing/quick/quick.go | 6 +- libgo/go/testing/quick/quick_test.go | 11 +- libgo/go/testing/testing.go | 121 +- libgo/go/testing/testing_test.go | 18 + libgo/go/text/scanner/scanner.go | 37 +- libgo/go/text/scanner/scanner_test.go | 63 +- libgo/go/text/tabwriter/tabwriter.go | 12 +- libgo/go/text/tabwriter/tabwriter_test.go | 39 +- libgo/go/text/template/doc.go | 11 +- libgo/go/text/template/exec.go | 21 +- libgo/go/text/template/exec_test.go | 121 +- libgo/go/text/template/funcs.go | 86 +- libgo/go/text/template/multi_test.go | 12 + libgo/go/text/template/parse/node.go | 248 +- libgo/go/text/template/parse/parse.go | 62 +- libgo/go/text/template/parse/parse_test.go | 5 +- libgo/go/text/template/template.go | 2 +- libgo/go/time/example_test.go | 4 +- libgo/go/time/format.go | 18 +- libgo/go/time/format_test.go | 520 +++ libgo/go/time/genzabbrs.go | 20 +- libgo/go/time/internal_test.go | 43 +- libgo/go/time/sleep.go | 28 +- libgo/go/time/sleep_test.go | 78 +- libgo/go/time/sys_unix.go | 2 +- libgo/go/time/tick.go | 3 +- libgo/go/time/tick_test.go | 18 + libgo/go/time/time.go | 45 +- libgo/go/time/time_test.go | 557 +-- libgo/go/time/zoneinfo.go | 87 +- libgo/go/time/zoneinfo_abbrs_windows.go | 3 +- libgo/go/time/zoneinfo_plan9.go | 2 +- libgo/go/time/zoneinfo_read.go | 8 +- libgo/go/time/zoneinfo_test.go | 66 + libgo/go/time/zoneinfo_unix.go | 2 +- libgo/go/time/zoneinfo_windows.go | 10 +- libgo/go/unicode/letter.go | 7 +- libgo/go/unicode/letter_test.go | 16 +- libgo/go/unicode/script_test.go | 29 +- libgo/go/unicode/tables.go | 1297 +++++-- libgo/go/unicode/utf16/utf16.go | 2 +- libgo/go/unicode/utf16/utf16_test.go | 48 + libgo/go/unicode/utf8/example_test.go | 4 + libgo/go/unicode/utf8/utf8.go | 60 +- libgo/merge.sh | 85 +- libgo/mksysinfo.sh | 99 +- libgo/mvifdiff.sh | 15 + libgo/runtime/chan.c | 1508 -------- libgo/runtime/chan.goc | 1136 ++++++ libgo/runtime/chan.h | 75 + libgo/runtime/cpuprof.c | 447 --- libgo/runtime/cpuprof.goc | 442 +++ libgo/runtime/env_posix.c | 10 +- libgo/runtime/go-append.c | 5 +- libgo/runtime/go-assert-interface.c | 2 +- libgo/runtime/go-caller.c | 40 +- libgo/runtime/go-callers.c | 54 +- libgo/runtime/go-can-convert-interface.c | 2 +- libgo/runtime/go-cdiv.c | 31 +- libgo/runtime/go-cgo.c | 16 - libgo/runtime/go-check-interface.c | 4 +- libgo/runtime/go-convert-interface.c | 2 +- libgo/runtime/go-defer.c | 12 +- libgo/runtime/go-defer.h | 10 +- libgo/runtime/go-eface-compare.c | 4 - libgo/runtime/go-eface-val-compare.c | 2 - libgo/runtime/go-ffi.c | 346 ++ libgo/runtime/go-ffi.h | 16 + libgo/runtime/go-getgoroot.c | 26 - libgo/runtime/go-iface.goc | 130 + libgo/runtime/go-interface-eface-compare.c | 2 - libgo/runtime/go-make-slice.c | 2 +- libgo/runtime/go-map-delete.c | 9 +- libgo/runtime/go-map-index.c | 4 +- libgo/runtime/go-new.c | 12 +- libgo/runtime/go-now.c | 10 - libgo/runtime/go-panic.c | 6 +- libgo/runtime/go-panic.h | 9 + libgo/runtime/go-recover.c | 228 +- libgo/runtime/go-reflect-call.c | 332 +- libgo/runtime/go-reflect-map.c | 184 +- libgo/runtime/go-setenv.c | 20 +- libgo/runtime/go-signal.c | 25 +- libgo/runtime/go-string-to-byte-array.c | 9 +- libgo/runtime/go-string-to-int-array.c | 13 +- libgo/runtime/go-traceback.c | 2 +- libgo/runtime/go-type-complex.c | 110 +- libgo/runtime/go-type-eface.c | 3 - libgo/runtime/go-type-float.c | 88 +- libgo/runtime/go-type.h | 26 +- libgo/runtime/go-typestring.c | 17 - libgo/runtime/go-unsafe-pointer.c | 25 +- libgo/runtime/go-unsetenv.c | 54 + libgo/runtime/go-unwind.c | 12 +- libgo/runtime/go-varargs.c | 6 + libgo/runtime/goc2c.c | 17 +- libgo/runtime/heapdump.c | 776 ++++ libgo/runtime/iface.goc | 138 - libgo/runtime/lfstack.c | 79 - libgo/runtime/lfstack.goc | 79 + libgo/runtime/lock_futex.c | 16 +- libgo/runtime/lock_sema.c | 11 +- libgo/runtime/malloc.goc | 626 +-- libgo/runtime/malloc.h | 224 +- libgo/runtime/mcache.c | 124 +- libgo/runtime/mcentral.c | 205 +- libgo/runtime/mem.c | 55 +- libgo/runtime/mfinal.c | 218 -- libgo/runtime/mgc0.c | 1762 +++++---- libgo/runtime/mgc0.h | 41 + libgo/runtime/mheap.c | 482 ++- libgo/runtime/mprof.goc | 280 +- libgo/runtime/msize.c | 27 +- libgo/runtime/netpoll.goc | 205 +- libgo/runtime/netpoll_epoll.c | 13 +- libgo/runtime/netpoll_kqueue.c | 12 +- libgo/runtime/netpoll_select.c | 4 +- libgo/runtime/netpoll_stub.c | 3 +- libgo/runtime/panic.c | 113 +- libgo/runtime/parfor.c | 47 +- libgo/runtime/print.c | 77 +- libgo/runtime/proc.c | 707 ++-- libgo/runtime/race.h | 33 - libgo/runtime/rdebug.goc | 26 + libgo/runtime/reflect.goc | 2 - libgo/runtime/runtime.c | 138 +- libgo/runtime/runtime.h | 158 +- libgo/runtime/runtime1.goc | 75 + libgo/runtime/sema.goc | 6 +- libgo/runtime/signal_unix.c | 11 +- libgo/runtime/string.goc | 14 +- libgo/runtime/time.goc | 55 +- libgo/runtime/yield.c | 6 +- libgo/testsuite/Makefile.in | 1 + libgo/testsuite/gotest | 77 +- libgo/testsuite/lib/libgo.exp | 2 + 1116 files changed, 81967 insertions(+), 25993 deletions(-) create mode 100644 libgo/VERSION create mode 100644 libgo/go/archive/tar/testdata/sparse-formats.tar create mode 100644 libgo/go/archive/tar/testdata/writer-big-long.tar create mode 100644 libgo/go/archive/tar/testdata/xattrs.tar create mode 100644 libgo/go/archive/zip/testdata/zip64-2.zip create mode 100644 libgo/go/cmd/cgo/ast.go create mode 100644 libgo/go/cmd/cgo/doc.go create mode 100644 libgo/go/cmd/cgo/gcc.go create mode 100644 libgo/go/cmd/cgo/godefs.go create mode 100644 libgo/go/cmd/cgo/main.go create mode 100644 libgo/go/cmd/cgo/out.go create mode 100644 libgo/go/cmd/cgo/util.go create mode 100644 libgo/go/cmd/go/bootstrap.go create mode 100644 libgo/go/cmd/go/build.go create mode 100644 libgo/go/cmd/go/clean.go create mode 100644 libgo/go/cmd/go/context.go create mode 100644 libgo/go/cmd/go/discovery.go create mode 100644 libgo/go/cmd/go/doc.go create mode 100644 libgo/go/cmd/go/env.go create mode 100644 libgo/go/cmd/go/fix.go create mode 100644 libgo/go/cmd/go/fmt.go create mode 100644 libgo/go/cmd/go/generate.go create mode 100644 libgo/go/cmd/go/generate_test.go create mode 100644 libgo/go/cmd/go/get.go create mode 100644 libgo/go/cmd/go/go11.go create mode 100644 libgo/go/cmd/go/go_windows_test.go create mode 100644 libgo/go/cmd/go/help.go create mode 100644 libgo/go/cmd/go/http.go create mode 100644 libgo/go/cmd/go/list.go create mode 100644 libgo/go/cmd/go/main.go create mode 100644 libgo/go/cmd/go/match_test.go create mode 100644 libgo/go/cmd/go/mkdoc.sh create mode 100644 libgo/go/cmd/go/pkg.go create mode 100644 libgo/go/cmd/go/pkg_test.go create mode 100644 libgo/go/cmd/go/run.go create mode 100644 libgo/go/cmd/go/script create mode 100644 libgo/go/cmd/go/script.txt create mode 100644 libgo/go/cmd/go/signal.go create mode 100644 libgo/go/cmd/go/signal_notunix.go create mode 100644 libgo/go/cmd/go/signal_unix.go create mode 100644 libgo/go/cmd/go/tag_test.go create mode 100644 libgo/go/cmd/go/test.bash create mode 100644 libgo/go/cmd/go/test.go create mode 100644 libgo/go/cmd/go/testdata/cgocover/p.go create mode 100644 libgo/go/cmd/go/testdata/cgocover/p_test.go create mode 100644 libgo/go/cmd/go/testdata/dep_test.go create mode 100644 libgo/go/cmd/go/testdata/example1_test.go create mode 100644 libgo/go/cmd/go/testdata/example2_test.go create mode 100644 libgo/go/cmd/go/testdata/generate/test1.go create mode 100644 libgo/go/cmd/go/testdata/generate/test2.go create mode 100644 libgo/go/cmd/go/testdata/generate/test3.go create mode 100644 libgo/go/cmd/go/testdata/importcom/bad.go create mode 100644 libgo/go/cmd/go/testdata/importcom/conflict.go create mode 100644 libgo/go/cmd/go/testdata/importcom/src/bad/bad.go create mode 100644 libgo/go/cmd/go/testdata/importcom/src/conflict/a.go create mode 100644 libgo/go/cmd/go/testdata/importcom/src/conflict/b.go create mode 100644 libgo/go/cmd/go/testdata/importcom/src/works/x/x.go create mode 100644 libgo/go/cmd/go/testdata/importcom/src/works/x/x1.go create mode 100644 libgo/go/cmd/go/testdata/importcom/src/wrongplace/x.go create mode 100644 libgo/go/cmd/go/testdata/importcom/works.go create mode 100644 libgo/go/cmd/go/testdata/importcom/wrongplace.go create mode 100644 libgo/go/cmd/go/testdata/local/easy.go create mode 100644 libgo/go/cmd/go/testdata/local/easysub/easysub.go create mode 100644 libgo/go/cmd/go/testdata/local/easysub/main.go create mode 100644 libgo/go/cmd/go/testdata/local/hard.go create mode 100644 libgo/go/cmd/go/testdata/local/sub/sub.go create mode 100644 libgo/go/cmd/go/testdata/local/sub/sub/subsub.go create mode 100644 libgo/go/cmd/go/testdata/norunexample/example_test.go create mode 100644 libgo/go/cmd/go/testdata/norunexample/test_test.go create mode 100644 libgo/go/cmd/go/testdata/shadow/root1/src/foo/foo.go create mode 100644 libgo/go/cmd/go/testdata/shadow/root1/src/math/math.go create mode 100644 libgo/go/cmd/go/testdata/shadow/root2/src/foo/foo.go create mode 100644 libgo/go/cmd/go/testdata/src/badc/x.go create mode 100644 libgo/go/cmd/go/testdata/src/badpkg/x.go create mode 100644 libgo/go/cmd/go/testdata/src/badtest/badexec/x_test.go create mode 100644 libgo/go/cmd/go/testdata/src/badtest/badsyntax/x.go create mode 100644 libgo/go/cmd/go/testdata/src/badtest/badsyntax/x_test.go create mode 100644 libgo/go/cmd/go/testdata/src/badtest/badvar/x.go create mode 100644 libgo/go/cmd/go/testdata/src/badtest/badvar/x_test.go create mode 100644 libgo/go/cmd/go/testdata/src/cgotest/m.go create mode 100644 libgo/go/cmd/go/testdata/src/go-cmd-test/helloworld.go create mode 100644 libgo/go/cmd/go/testdata/src/main_test/m.go create mode 100644 libgo/go/cmd/go/testdata/src/main_test/m_test.go create mode 100644 libgo/go/cmd/go/testdata/src/notest/hello.go create mode 100644 libgo/go/cmd/go/testdata/src/syntaxerror/x.go create mode 100644 libgo/go/cmd/go/testdata/src/syntaxerror/x_test.go create mode 100644 libgo/go/cmd/go/testdata/src/testcycle/p1/p1.go create mode 100644 libgo/go/cmd/go/testdata/src/testcycle/p1/p1_test.go create mode 100644 libgo/go/cmd/go/testdata/src/testcycle/p2/p2.go create mode 100644 libgo/go/cmd/go/testdata/src/testcycle/p3/p3.go create mode 100644 libgo/go/cmd/go/testdata/src/testcycle/p3/p3_test.go create mode 100644 libgo/go/cmd/go/testdata/src/vetpkg/a_test.go create mode 100644 libgo/go/cmd/go/testdata/src/vetpkg/b.go create mode 100644 libgo/go/cmd/go/testdata/src/xtestonly/f.go create mode 100644 libgo/go/cmd/go/testdata/src/xtestonly/f_test.go create mode 100644 libgo/go/cmd/go/testdata/standalone_test.go create mode 100644 libgo/go/cmd/go/testdata/testimport/p.go create mode 100644 libgo/go/cmd/go/testdata/testimport/p1/p1.go create mode 100644 libgo/go/cmd/go/testdata/testimport/p2/p2.go create mode 100644 libgo/go/cmd/go/testdata/testimport/p_test.go create mode 100644 libgo/go/cmd/go/testdata/testimport/x_test.go create mode 100644 libgo/go/cmd/go/testdata/testinternal/p.go create mode 100644 libgo/go/cmd/go/testdata/testinternal2/p.go create mode 100644 libgo/go/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go create mode 100644 libgo/go/cmd/go/testdata/testonly/p_test.go create mode 100644 libgo/go/cmd/go/testflag.go create mode 100644 libgo/go/cmd/go/testgo.go create mode 100644 libgo/go/cmd/go/tool.go create mode 100644 libgo/go/cmd/go/vcs.go create mode 100644 libgo/go/cmd/go/vcs_test.go create mode 100644 libgo/go/cmd/go/version.go create mode 100644 libgo/go/cmd/go/vet.go create mode 100644 libgo/go/cmd/gofmt/doc.go create mode 100644 libgo/go/cmd/gofmt/gofmt.go create mode 100644 libgo/go/cmd/gofmt/gofmt_test.go create mode 100644 libgo/go/cmd/gofmt/long_test.go create mode 100644 libgo/go/cmd/gofmt/rewrite.go create mode 100644 libgo/go/cmd/gofmt/simplify.go create mode 100644 libgo/go/cmd/gofmt/testdata/comments.golden create mode 100644 libgo/go/cmd/gofmt/testdata/comments.input create mode 100644 libgo/go/cmd/gofmt/testdata/composites.golden create mode 100644 libgo/go/cmd/gofmt/testdata/composites.input create mode 100644 libgo/go/cmd/gofmt/testdata/crlf.golden create mode 100644 libgo/go/cmd/gofmt/testdata/crlf.input create mode 100644 libgo/go/cmd/gofmt/testdata/import.golden create mode 100644 libgo/go/cmd/gofmt/testdata/import.input create mode 100644 libgo/go/cmd/gofmt/testdata/old.golden create mode 100644 libgo/go/cmd/gofmt/testdata/old.input create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite1.golden create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite1.input create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite2.golden create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite2.input create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite3.golden create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite3.input create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite4.golden create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite4.input create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite5.golden create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite5.input create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite6.golden create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite6.input create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite7.golden create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite7.input create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite8.golden create mode 100644 libgo/go/cmd/gofmt/testdata/rewrite8.input create mode 100644 libgo/go/cmd/gofmt/testdata/slices1.golden create mode 100644 libgo/go/cmd/gofmt/testdata/slices1.input create mode 100644 libgo/go/cmd/gofmt/testdata/slices2.golden create mode 100644 libgo/go/cmd/gofmt/testdata/slices2.input create mode 100644 libgo/go/cmd/gofmt/testdata/stdin1.golden create mode 100644 libgo/go/cmd/gofmt/testdata/stdin1.input create mode 100644 libgo/go/cmd/gofmt/testdata/stdin2.golden create mode 100644 libgo/go/cmd/gofmt/testdata/stdin2.input create mode 100644 libgo/go/cmd/gofmt/testdata/stdin3.golden create mode 100644 libgo/go/cmd/gofmt/testdata/stdin3.input create mode 100644 libgo/go/cmd/gofmt/testdata/stdin4.golden create mode 100644 libgo/go/cmd/gofmt/testdata/stdin4.input create mode 100644 libgo/go/cmd/gofmt/testdata/typeswitch.golden create mode 100644 libgo/go/cmd/gofmt/testdata/typeswitch.input create mode 100644 libgo/go/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 create mode 100644 libgo/go/compress/bzip2/testdata/e.txt.bz2 create mode 100644 libgo/go/compress/flate/inflate_test.go create mode 100644 libgo/go/crypto/cipher/benchmark_test.go create mode 100644 libgo/go/crypto/cipher/xor.go create mode 100644 libgo/go/crypto/cipher/xor_test.go create mode 100644 libgo/go/crypto/md5/md5block_generic.go create mode 100644 libgo/go/crypto/rand/rand_linux.go create mode 100644 libgo/go/crypto/rand/util_test.go create mode 100644 libgo/go/crypto/sha1/sha1block_generic.go create mode 100644 libgo/go/crypto/sha256/sha256block_decl.go create mode 100644 libgo/go/crypto/sha512/sha512block_decl.go create mode 100644 libgo/go/crypto/tls/handshake_test.go create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4 create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4 create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES create mode 100644 libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4 create mode 100644 libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES create mode 100644 libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES create mode 100644 libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4 create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-3DES create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4 create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv11-FallbackSCSV create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv11-RSA-RC4 create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicket create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-3DES create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4 create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-Resume create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-ResumeDisabled create mode 100644 libgo/go/crypto/tls/testdata/Server-TLSv12-SNI create mode 100644 libgo/go/crypto/x509/root_cgo_darwin.go create mode 100644 libgo/go/crypto/x509/root_nocgo_darwin.go delete mode 100644 libgo/go/crypto/x509/root_stub.go create mode 100644 libgo/go/crypto/x509/x509_test_import.go create mode 100644 libgo/go/debug/dwarf/testdata/typedef.elf4 create mode 100644 libgo/go/debug/dwarf/typeunit.go create mode 100644 libgo/go/debug/elf/symbols_test.go create mode 100644 libgo/go/debug/elf/testdata/go-relocation-test-clang-x86.obj create mode 100644 libgo/go/debug/elf/testdata/go-relocation-test-gcc482-aarch64.obj create mode 100644 libgo/go/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj create mode 100644 libgo/go/debug/elf/testdata/go-relocation-test-gcc5-ppc.obj create mode 100644 libgo/go/debug/elf/testdata/hello.c create mode 100644 libgo/go/debug/macho/fat.go create mode 100644 libgo/go/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec create mode 100644 libgo/go/debug/pe/testdata/gcc-amd64-mingw-exec create mode 100644 libgo/go/debug/pe/testdata/gcc-amd64-mingw-obj create mode 100644 libgo/go/debug/plan9obj/file.go create mode 100644 libgo/go/debug/plan9obj/file_test.go create mode 100644 libgo/go/debug/plan9obj/plan9obj.go create mode 100644 libgo/go/debug/plan9obj/testdata/386-plan9-exec create mode 100644 libgo/go/debug/plan9obj/testdata/amd64-plan9-exec create mode 100644 libgo/go/debug/plan9obj/testdata/hello.c create mode 100644 libgo/go/encoding/gob/dec_helpers.go create mode 100644 libgo/go/encoding/gob/decgen.go create mode 100644 libgo/go/encoding/gob/enc_helpers.go create mode 100644 libgo/go/encoding/gob/encgen.go create mode 100644 libgo/go/encoding/json/fold.go create mode 100644 libgo/go/encoding/json/fold_test.go create mode 100644 libgo/go/go/build/testdata/multi/file.go create mode 100644 libgo/go/go/build/testdata/multi/file_appengine.go create mode 100644 libgo/go/go/doc/testdata/blank.0.golden create mode 100644 libgo/go/go/doc/testdata/blank.1.golden create mode 100644 libgo/go/go/doc/testdata/blank.2.golden create mode 100644 libgo/go/go/doc/testdata/blank.go delete mode 100644 libgo/go/go/types/testdata/builtins.src delete mode 100644 libgo/go/go/types/testdata/const0.src delete mode 100644 libgo/go/go/types/testdata/conversions.src delete mode 100644 libgo/go/go/types/testdata/decls0.src delete mode 100644 libgo/go/go/types/testdata/decls1.src delete mode 100644 libgo/go/go/types/testdata/decls2a.src delete mode 100644 libgo/go/go/types/testdata/decls2b.src delete mode 100644 libgo/go/go/types/testdata/decls3.src delete mode 100644 libgo/go/go/types/testdata/expr0.src delete mode 100644 libgo/go/go/types/testdata/expr1.src delete mode 100644 libgo/go/go/types/testdata/expr2.src delete mode 100644 libgo/go/go/types/testdata/expr3.src delete mode 100644 libgo/go/go/types/testdata/stmt0.src delete mode 100644 libgo/go/hash/crc32/crc32_amd64.go create mode 100644 libgo/go/hash/crc32/crc32_amd64x.go create mode 100644 libgo/go/image/color/palette/generate.go create mode 100644 libgo/go/image/png/testdata/benchGray.png create mode 100644 libgo/go/image/png/testdata/benchNRGBA-gradient.png create mode 100644 libgo/go/image/png/testdata/benchNRGBA-opaque.png create mode 100644 libgo/go/image/png/testdata/benchPaletted.png create mode 100644 libgo/go/image/png/testdata/benchRGB.png create mode 100644 libgo/go/image/testdata/video-001.separate.dc.progression.jpeg create mode 100644 libgo/go/image/testdata/video-001.separate.dc.progression.progressive.jpeg create mode 100644 libgo/go/image/testdata/video-005.gray.gif create mode 100644 libgo/go/internal/syscall/dummy.go create mode 100644 libgo/go/internal/syscall/getrandom_linux.go delete mode 100644 libgo/go/io/ioutil/blackhole.go create mode 100644 libgo/go/math/rand/regress_test.go create mode 100644 libgo/go/net/cgo_android.go create mode 100644 libgo/go/net/cgo_unix_test.go create mode 100644 libgo/go/net/dnsclient_test.go create mode 100644 libgo/go/net/dnsconfig_unix_test.go create mode 100644 libgo/go/net/fd_poll_nacl.go create mode 100644 libgo/go/net/file_stub.go delete mode 100644 libgo/go/net/http/chunked.go delete mode 100644 libgo/go/net/http/chunked_test.go delete mode 100644 libgo/go/net/http/httputil/chunked.go delete mode 100644 libgo/go/net/http/httputil/chunked_test.go create mode 100644 libgo/go/net/http/httputil/httputil.go create mode 100644 libgo/go/net/http/internal/chunked.go create mode 100644 libgo/go/net/http/internal/chunked_test.go create mode 100644 libgo/go/net/http/main_test.go create mode 100644 libgo/go/net/http/race.go delete mode 100644 libgo/go/net/http/z_last_test.go create mode 100644 libgo/go/net/lookup_stub.go create mode 100644 libgo/go/net/rpc/client_test.go delete mode 100644 libgo/go/net/sock_solaris.go create mode 100644 libgo/go/net/sock_stub.go create mode 100644 libgo/go/net/sockopt_plan9.go create mode 100644 libgo/go/net/sockopt_solaris.go create mode 100644 libgo/go/net/sockopt_stub.go create mode 100644 libgo/go/net/sockoptip_stub.go create mode 100644 libgo/go/net/tcpsockopt_dragonfly.go create mode 100644 libgo/go/net/tcpsockopt_plan9.go create mode 100644 libgo/go/net/tcpsockopt_solaris.go create mode 100644 libgo/go/net/tcpsockopt_stub.go create mode 100644 libgo/go/net/testdata/domain-resolv.conf create mode 100644 libgo/go/net/testdata/empty-resolv.conf create mode 100644 libgo/go/net/testdata/resolv.conf create mode 100644 libgo/go/net/testdata/search-resolv.conf create mode 100644 libgo/go/net/z_last_test.go create mode 100644 libgo/go/os/stat_nacl.go create mode 100644 libgo/go/os/sys_darwin.go create mode 100644 libgo/go/os/sys_freebsd.go create mode 100644 libgo/go/os/sys_nacl.go create mode 100644 libgo/go/os/sys_unix.go create mode 100644 libgo/go/path/filepath/export_test.go create mode 100644 libgo/go/path/filepath/symlink_unix.go delete mode 100644 libgo/go/reflect/makefunc_386.S delete mode 100644 libgo/go/reflect/makefunc_amd64.S delete mode 100644 libgo/go/reflect/makefunc_dummy.c create mode 100644 libgo/go/reflect/makefunc_ffi.go create mode 100644 libgo/go/reflect/makefunc_ffi_c.c delete mode 100644 libgo/go/reflect/makefuncgo_386.go delete mode 100644 libgo/go/reflect/makefuncgo_amd64.go create mode 100644 libgo/go/regexp/onepass.go create mode 100644 libgo/go/regexp/onepass_test.go create mode 100644 libgo/go/runtime/arch_386.go create mode 100644 libgo/go/runtime/arch_amd64.go create mode 100644 libgo/go/runtime/arch_amd64p32.go create mode 100644 libgo/go/runtime/arch_arm.go create mode 100644 libgo/go/runtime/atomic.go create mode 100644 libgo/go/runtime/cgocall.go create mode 100644 libgo/go/runtime/cgocallback.go create mode 100644 libgo/go/runtime/chan.go create mode 100644 libgo/go/runtime/complex.go create mode 100644 libgo/go/runtime/cpuprof.go create mode 100644 libgo/go/runtime/debug/heapdump_test.go create mode 100644 libgo/go/runtime/env_posix.go create mode 100644 libgo/go/runtime/gcinfo_test.go create mode 100644 libgo/go/runtime/hashmap.go create mode 100644 libgo/go/runtime/hashmap_fast.go create mode 100644 libgo/go/runtime/lock_futex.go create mode 100644 libgo/go/runtime/lock_sema.go create mode 100644 libgo/go/runtime/malloc.go delete mode 100644 libgo/go/runtime/malloc1.go delete mode 100644 libgo/go/runtime/mallocrand.go delete mode 100644 libgo/go/runtime/mallocrep.go delete mode 100644 libgo/go/runtime/mallocrep1.go create mode 100644 libgo/go/runtime/mprof.go create mode 100644 libgo/go/runtime/netpoll.go create mode 100644 libgo/go/runtime/netpoll_epoll.go create mode 100644 libgo/go/runtime/netpoll_kqueue.go create mode 100644 libgo/go/runtime/netpoll_nacl.go create mode 100644 libgo/go/runtime/noasm_arm.go create mode 100644 libgo/go/runtime/os_darwin.go create mode 100644 libgo/go/runtime/os_dragonfly.go create mode 100644 libgo/go/runtime/os_freebsd.go create mode 100644 libgo/go/runtime/os_linux.go create mode 100644 libgo/go/runtime/os_nacl.go create mode 100644 libgo/go/runtime/os_netbsd.go create mode 100644 libgo/go/runtime/os_openbsd.go create mode 100644 libgo/go/runtime/os_plan9.go create mode 100644 libgo/go/runtime/os_solaris.go create mode 100644 libgo/go/runtime/os_windows.go create mode 100644 libgo/go/runtime/os_windows_386.go create mode 100644 libgo/go/runtime/os_windows_amd64.go create mode 100644 libgo/go/runtime/panic.go create mode 100644 libgo/go/runtime/pprof/mprof_test.go create mode 100644 libgo/go/runtime/print1.go create mode 100644 libgo/go/runtime/proc.go create mode 100644 libgo/go/runtime/race0.go create mode 100644 libgo/go/runtime/rdebug.go create mode 100644 libgo/go/runtime/rune.go create mode 100644 libgo/go/runtime/runtime.go create mode 100644 libgo/go/runtime/runtime_unix_test.go create mode 100644 libgo/go/runtime/select.go create mode 100644 libgo/go/runtime/sema.go create mode 100644 libgo/go/runtime/signal_unix.go create mode 100644 libgo/go/runtime/sigpanic_unix.go create mode 100644 libgo/go/runtime/sigqueue.go create mode 100644 libgo/go/runtime/slice.go create mode 100644 libgo/go/runtime/stack.go create mode 100644 libgo/go/runtime/string.go create mode 100644 libgo/go/runtime/stubs.go create mode 100644 libgo/go/runtime/syscall_windows.go create mode 100644 libgo/go/runtime/time.go delete mode 100644 libgo/go/runtime/type.go create mode 100644 libgo/go/runtime/typekind.go create mode 100644 libgo/go/runtime/vlrt.go create mode 100644 libgo/go/strconv/quote_example_test.go delete mode 100644 libgo/go/sync/atomic/race.go create mode 100644 libgo/go/sync/atomic/value.go create mode 100644 libgo/go/sync/atomic/value_test.go create mode 100644 libgo/go/sync/pool.go create mode 100644 libgo/go/sync/pool_test.go delete mode 100644 libgo/go/syscall/consistency_unix_test.go create mode 100644 libgo/go/syscall/export_test.go create mode 100644 libgo/go/syscall/libcall_linux_s390.go create mode 100644 libgo/go/syscall/libcall_linux_s390x.go create mode 100644 libgo/go/syscall/mmap_unix_test.go delete mode 100644 libgo/go/syscall/passfd_test.go delete mode 100644 libgo/go/syscall/rlimit_linux_test.go create mode 100644 libgo/go/syscall/route_freebsd_32bit.go create mode 100644 libgo/go/syscall/route_freebsd_64bit.go create mode 100644 libgo/go/syscall/syscall_linux_s390.go create mode 100644 libgo/go/syscall/syscall_linux_s390x.go create mode 100644 libgo/go/syscall/syscall_unix_test.go create mode 100644 libgo/go/testing/allocs_test.go create mode 100644 libgo/go/testing/testing_test.go create mode 100644 libgo/go/time/format_test.go create mode 100644 libgo/go/time/zoneinfo_test.go create mode 100644 libgo/mvifdiff.sh delete mode 100644 libgo/runtime/chan.c create mode 100644 libgo/runtime/chan.goc create mode 100644 libgo/runtime/chan.h delete mode 100644 libgo/runtime/cpuprof.c create mode 100644 libgo/runtime/cpuprof.goc create mode 100644 libgo/runtime/go-ffi.c create mode 100644 libgo/runtime/go-ffi.h delete mode 100644 libgo/runtime/go-getgoroot.c create mode 100644 libgo/runtime/go-iface.goc delete mode 100644 libgo/runtime/go-typestring.c create mode 100644 libgo/runtime/go-unsetenv.c create mode 100644 libgo/runtime/heapdump.c delete mode 100644 libgo/runtime/iface.goc delete mode 100644 libgo/runtime/lfstack.c create mode 100644 libgo/runtime/lfstack.goc delete mode 100644 libgo/runtime/mfinal.c delete mode 100644 libgo/runtime/race.h create mode 100644 libgo/runtime/rdebug.goc (limited to 'libgo') diff --git a/libgo/MERGE b/libgo/MERGE index cc27a79977..260f8cf8e5 100644 --- a/libgo/MERGE +++ b/libgo/MERGE @@ -1,4 +1,4 @@ -0ddbdc3c7ce2 +883bc6ed0ea815293fe6309d66f967ea60630e87 -The first line of this file holds the Mercurial revision number of the +The first line of this file holds the git revision number of the last merge done from the master library sources. diff --git a/libgo/Makefile.am b/libgo/Makefile.am index 4f09bc30bf..00fbaabae3 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -15,7 +15,7 @@ endif SUBDIRS = ${subdirs} -gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) +gcc_version := $(shell $(GOC) -dumpversion) MAINT_CHARSET = latin1 @@ -26,10 +26,13 @@ STAMP = echo timestamp > toolexecdir = $(glibgo_toolexecdir) toolexeclibdir = $(glibgo_toolexeclibdir) toolexeclibgodir = $(nover_glibgo_toolexeclibdir)/go/$(gcc_version)/$(target_alias) +libexecsubdir = $(libexecdir)/gcc/$(target_alias)/$(gcc_version) LIBFFI = @LIBFFI@ LIBFFIINCS = @LIBFFIINCS@ +LIBATOMIC = @LIBATOMIC@ + WARN_CFLAGS = $(WARN_FLAGS) $(WERROR) # -I/-D flags to pass when compiling. @@ -97,8 +100,13 @@ AM_MAKEFLAGS = \ # Subdir rules rely on $(FLAGS_TO_PASS) FLAGS_TO_PASS = $(AM_MAKEFLAGS) +if GOC_IS_LLGO +toolexeclib_LTLIBRARIES = libgo-llgo.la +toolexeclib_LIBRARIES = libgobegin-llgo.a +else toolexeclib_LTLIBRARIES = libgo.la -toolexeclib_LIBRARIES = libgobegin.a +toolexeclib_LIBRARIES = libgobegin.a libnetgo.a +endif toolexeclibgo_DATA = \ bufio.gox \ @@ -196,7 +204,8 @@ toolexeclibgodebug_DATA = \ debug/elf.gox \ debug/gosym.gox \ debug/macho.gox \ - debug/pe.gox + debug/pe.gox \ + debug/plan9obj.gox toolexeclibgoencodingdir = $(toolexeclibgodir)/encoding @@ -441,8 +450,8 @@ runtime_files = \ runtime/go-deferred-recover.c \ runtime/go-eface-compare.c \ runtime/go-eface-val-compare.c \ + runtime/go-ffi.c \ runtime/go-fieldtrack.c \ - runtime/go-getgoroot.c \ runtime/go-int-array-to-string.c \ runtime/go-int-to-string.c \ runtime/go-interface-compare.c \ @@ -483,21 +492,18 @@ runtime_files = \ runtime/go-type-interface.c \ runtime/go-type-string.c \ runtime/go-typedesc-equal.c \ - runtime/go-typestring.c \ runtime/go-unsafe-new.c \ runtime/go-unsafe-newarray.c \ runtime/go-unsafe-pointer.c \ + runtime/go-unsetenv.c \ runtime/go-unwind.c \ runtime/go-varargs.c \ - runtime/chan.c \ - runtime/cpuprof.c \ runtime/env_posix.c \ - runtime/lfstack.c \ + runtime/heapdump.c \ $(runtime_lock_files) \ runtime/mcache.c \ runtime/mcentral.c \ $(runtime_mem_file) \ - runtime/mfinal.c \ runtime/mfixalloc.c \ runtime/mgc0.c \ runtime/mheap.c \ @@ -512,11 +518,15 @@ runtime_files = \ runtime/thread.c \ runtime/yield.c \ $(rtems_task_variable_add_file) \ - iface.c \ + chan.c \ + cpuprof.c \ + go-iface.c \ + lfstack.c \ malloc.c \ map.c \ mprof.c \ netpoll.c \ + rdebug.c \ reflect.c \ runtime1.c \ sema.c \ @@ -686,9 +696,9 @@ go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go else if LIBGO_IS_SOLARIS go_net_cgo_file = go/net/cgo_linux.go -go_net_sock_file = go/net/sock_solaris.go -go_net_sockopt_file = go/net/sockopt_bsd.go -go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go +go_net_sock_file = go/net/sock_stub.go +go_net_sockopt_file = go/net/sockopt_solaris.go +go_net_sockoptip_file = go/net/sockoptip_stub.go else if LIBGO_IS_FREEBSD go_net_cgo_file = go/net/cgo_bsd.go @@ -753,16 +763,18 @@ if LIBGO_IS_DARWIN go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go else if LIBGO_IS_SOLARIS -go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go +go_net_tcpsockopt_file = go/net/tcpsockopt_solaris.go +else +if LIBGO_IS_DRAGONFLY +go_net_tcpsockopt_file = go/net/tcpsockopt_dragonfly.go else -go_net_tcpsockopt_file = go/net/tcpsockopt_unix.go +go_net_tcpsockopt_file = go/net/tcpsockopt_unix.go +endif endif endif endif -go_net_files = \ - go/net/cgo_unix.go \ - $(go_net_cgo_file) \ +go_net_common_files = \ $(go_net_cloexec_file) \ go/net/dial.go \ go/net/dnsclient.go \ @@ -806,6 +818,15 @@ go_net_files = \ go/net/unixsock.go \ go/net/unixsock_posix.go +go_net_files = \ + go/net/cgo_unix.go \ + $(go_net_cgo_file) \ + $(go_net_common_files) + +go_netgo_files = \ + go/net/cgo_stub.go \ + $(go_net_common_files) + if LIBGO_IS_SOLARIS if LIBGO_IS_386 go_os_dir_file = go/os/dir_largefile.go @@ -848,6 +869,16 @@ endif endif endif +if LIBGO_IS_FREEBSD +go_os_cloexec_file = go/os/sys_freebsd.go +else +if LIBGO_IS_DARWIN +go_os_cloexec_file = go/os/sys_darwin.go +else +go_os_cloexec_file = go/os/sys_unix.go +endif +endif + if LIBGO_IS_SOLARIS go_os_stat_file = go/os/stat_solaris.go else @@ -906,6 +937,7 @@ go_os_files = \ $(go_os_stat_file) \ go/os/str.go \ $(go_os_sys_file) \ + $(go_os_cloexec_file) \ go/os/types.go \ go/os/types_notwin.go @@ -913,33 +945,18 @@ go_path_files = \ go/path/match.go \ go/path/path.go -if LIBGO_IS_X86_64 -go_reflect_makefunc_file = \ - go/reflect/makefuncgo_amd64.go -go_reflect_makefunc_s_file = \ - go/reflect/makefunc_amd64.S -else -if LIBGO_IS_386 -go_reflect_makefunc_file = \ - go/reflect/makefuncgo_386.go -go_reflect_makefunc_s_file = \ - go/reflect/makefunc_386.S -else -go_reflect_makefunc_file = -go_reflect_makefunc_s_file = \ - go/reflect/makefunc_dummy.c -endif -endif - go_reflect_files = \ go/reflect/deepequal.go \ go/reflect/makefunc.go \ - $(go_reflect_makefunc_file) \ + go/reflect/makefunc_ffi.go \ go/reflect/type.go \ go/reflect/value.go +go_reflect_makefunc_c_file = \ + go/reflect/makefunc_ffi_c.c go_regexp_files = \ go/regexp/exec.go \ + go/regexp/onepass.go \ go/regexp/regexp.go go_net_rpc_files = \ @@ -954,7 +971,6 @@ go_runtime_files = \ go/runtime/extern.go \ go/runtime/mem.go \ go/runtime/softfloat64.go \ - go/runtime/type.go \ version.go version.go: s-version; @true @@ -962,10 +978,25 @@ s-version: Makefile rm -f version.go.tmp echo "package runtime" > version.go.tmp echo 'const defaultGoroot = "$(prefix)"' >> version.go.tmp - echo 'const theVersion = "'`$(CC) --version | sed 1q`'"' >> version.go.tmp + echo 'const theVersion = "'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'"' >> version.go.tmp echo 'const theGoarch = "'$(GOARCH)'"' >> version.go.tmp echo 'const theGoos = "'$(GOOS)'"' >> version.go.tmp - $(SHELL) $(srcdir)/../move-if-change version.go.tmp version.go + echo 'const theGccgoToolDir = "$(libexecsubdir)"' >> version.go.tmp + $(SHELL) $(srcdir)/mvifdiff.sh version.go.tmp version.go + $(STAMP) $@ + +noinst_DATA = zstdpkglist.go + +# Generate the list of go std packages that were included in libgo +zstdpkglist.go: s-zstdpkglist; @true +s-zstdpkglist: Makefile + rm -f zstdpkglist.go.tmp + echo 'package main' > 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/\.lo /\": true,\n/g' | sed 's/\.lo/\": true,/' | sed 's/-go//' | grep -v _c | sed 's/^/\t\"/' | sort | uniq >> zstdpkglist.go.tmp + echo '}' >> zstdpkglist.go.tmp + $(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go $(STAMP) $@ go_sort_files = \ @@ -996,6 +1027,7 @@ go_sync_files = \ go/sync/cond.go \ go/sync/mutex.go \ go/sync/once.go \ + go/sync/pool.go \ go/sync/race0.go \ go/sync/runtime.go \ go/sync/rwmutex.go \ @@ -1122,7 +1154,8 @@ go_crypto_cipher_files = \ go/crypto/cipher/ctr.go \ go/crypto/cipher/gcm.go \ go/crypto/cipher/io.go \ - go/crypto/cipher/ofb.go + go/crypto/cipher/ofb.go \ + go/crypto/cipher/xor.go go_crypto_des_files = \ go/crypto/des/block.go \ go/crypto/des/cipher.go \ @@ -1139,11 +1172,21 @@ go_crypto_hmac_files = \ go/crypto/hmac/hmac.go go_crypto_md5_files = \ go/crypto/md5/md5.go \ - go/crypto/md5/md5block.go + go/crypto/md5/md5block.go \ + go/crypto/md5/md5block_generic.go + +if LIBGO_IS_LINUX +crypto_rand_file = go/crypto/rand/rand_linux.go +else +crypto_rand_file = +endif + go_crypto_rand_files = \ go/crypto/rand/rand.go \ go/crypto/rand/rand_unix.go \ + $(crypto_rand_file) \ go/crypto/rand/util.go + go_crypto_rc4_files = \ go/crypto/rc4/rc4.go \ go/crypto/rc4/rc4_ref.go @@ -1153,7 +1196,8 @@ go_crypto_rsa_files = \ go/crypto/rsa/rsa.go go_crypto_sha1_files = \ go/crypto/sha1/sha1.go \ - go/crypto/sha1/sha1block.go + go/crypto/sha1/sha1block.go \ + go/crypto/sha1/sha1block_generic.go go_crypto_sha256_files = \ go/crypto/sha256/sha256.go \ go/crypto/sha256/sha256block.go @@ -1203,6 +1247,7 @@ go_debug_dwarf_files = \ go/debug/dwarf/line.go \ go/debug/dwarf/open.go \ go/debug/dwarf/type.go \ + go/debug/dwarf/typeunit.go \ go/debug/dwarf/unit.go go_debug_elf_files = \ go/debug/elf/elf.go \ @@ -1211,11 +1256,15 @@ go_debug_gosym_files = \ go/debug/gosym/pclntab.go \ go/debug/gosym/symtab.go go_debug_macho_files = \ + go/debug/macho/fat.go \ go/debug/macho/file.go \ go/debug/macho/macho.go go_debug_pe_files = \ go/debug/pe/file.go \ go/debug/pe/pe.go +go_debug_plan9obj_files = \ + go/debug/plan9obj/file.go \ + go/debug/plan9obj/plan9obj.go go_encoding_ascii85_files = \ go/encoding/ascii85/ascii85.go @@ -1236,9 +1285,11 @@ go_encoding_csv_files = \ go_encoding_gob_files = \ go/encoding/gob/decode.go \ go/encoding/gob/decoder.go \ + go/encoding/gob/dec_helpers.go \ go/encoding/gob/doc.go \ go/encoding/gob/encode.go \ go/encoding/gob/encoder.go \ + go/encoding/gob/enc_helpers.go \ go/encoding/gob/error.go \ go/encoding/gob/type.go go_encoding_hex_files = \ @@ -1246,6 +1297,7 @@ go_encoding_hex_files = \ go_encoding_json_files = \ go/encoding/json/decode.go \ go/encoding/json/encode.go \ + go/encoding/json/fold.go \ go/encoding/json/indent.go \ go/encoding/json/scanner.go \ go/encoding/json/stream.go \ @@ -1361,7 +1413,6 @@ go_index_suffixarray_files = \ go/index/suffixarray/suffixarray.go go_io_ioutil_files = \ - go/io/ioutil/blackhole.go \ go/io/ioutil/ioutil.go \ go/io/ioutil/tempfile.go @@ -1399,7 +1450,6 @@ go_mime_multipart_files = \ go/mime/multipart/writer.go go_net_http_files = \ - go/net/http/chunked.go \ go/net/http/client.go \ go/net/http/cookie.go \ go/net/http/filetransport.go \ @@ -1443,11 +1493,12 @@ go_net_http_httptest_files = \ go_net_http_pprof_files = \ go/net/http/pprof/pprof.go go_net_http_httputil_files = \ - go/net/http/httputil/chunked.go \ go/net/http/httputil/dump.go \ + go/net/http/httputil/httputil.go \ go/net/http/httputil/persist.go \ go/net/http/httputil/reverseproxy.go - +go_net_http_internal_files = \ + go/net/http/internal/chunked.go go_old_regexp_files = \ go/old/regexp/regexp.go @@ -1481,7 +1532,8 @@ go_path_filepath_files = \ go/path/filepath/match.go \ go/path/filepath/path.go \ go/path/filepath/path_unix.go \ - go/path/filepath/symlink.go + go/path/filepath/symlink.go \ + go/path/filepath/symlink_unix.go go_regexp_syntax_files = \ go/regexp/syntax/compile.go \ @@ -1516,7 +1568,8 @@ go_text_template_parse_files = \ go/text/template/parse/parse.go go_sync_atomic_files = \ - go/sync/atomic/doc.go + go/sync/atomic/doc.go \ + go/sync/atomic/value.go go_sync_atomic_c_files = \ go/sync/atomic/atomic.c @@ -1730,21 +1783,34 @@ go_syscall_c_files = \ go_syscall_test_files = \ $(syscall_creds_test_file) \ - go/syscall/passfd_test.go + go/syscall/export_test.go \ + go/syscall/mmap_unix_test.go \ + go/syscall/syscall_test.go \ + go/syscall/syscall_unix_test.go + +if LIBGO_IS_LINUX +internal_syscall_getrandom_file = go/internal/syscall/getrandom_linux.go +else +internal_syscall_getrandom_file = +endif + +go_internal_syscall_files = \ + go/internal/syscall/dummy.go \ + $(internal_syscall_getrandom_file) libcalls.go: s-libcalls; @true s-libcalls: libcalls-list go/syscall/mksyscall.awk $(go_base_syscall_files) rm -f libcalls.go.tmp files=`echo $^ | sed -e 's/libcalls-list//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \ $(AWK) -f $(srcdir)/go/syscall/mksyscall.awk $${files} > libcalls.go.tmp - $(SHELL) $(srcdir)/../move-if-change libcalls.go.tmp libcalls.go + $(SHELL) $(srcdir)/mvifdiff.sh libcalls.go.tmp libcalls.go $(STAMP) $@ libcalls-list: s-libcalls-list; @true s-libcalls-list: Makefile rm -f libcalls-list.tmp echo $(go_base_syscall_files) > libcalls-list.tmp - $(SHELL) $(srcdir)/../move-if-change libcalls-list.tmp libcalls-list + $(SHELL) $(srcdir)/mvifdiff.sh libcalls-list.tmp libcalls-list $(STAMP) $@ syscall_arch.go: s-syscall_arch; @true @@ -1753,13 +1819,13 @@ s-syscall_arch: Makefile echo "package syscall" > syscall_arch.go.tmp echo 'const ARCH = "'$(GOARCH)'"' >> syscall_arch.go.tmp echo 'const OS = "'$(GOOS)'"' >> syscall_arch.go.tmp - $(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go + $(SHELL) $(srcdir)/mvifdiff.sh syscall_arch.go.tmp syscall_arch.go $(STAMP) $@ sysinfo.go: s-sysinfo; @true s-sysinfo: $(srcdir)/mksysinfo.sh config.h - CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh - $(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go + CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS) -O" $(SHELL) $(srcdir)/mksysinfo.sh + $(SHELL) $(srcdir)/mvifdiff.sh tmp-sysinfo.go sysinfo.go $(STAMP) $@ # The epoll struct has an embedded union and is packed on x86_64, @@ -1787,7 +1853,7 @@ s-epoll: Makefile exit 1; ;; \ esac echo '}' >> epoll.go.tmp - $(SHELL) $(srcdir)/../move-if-change epoll.go.tmp epoll.go + $(SHELL) $(srcdir)/mvifdiff.sh epoll.go.tmp epoll.go $(STAMP) $@ if LIBGO_IS_LINUX @@ -1818,7 +1884,7 @@ libgo_go_objs = \ os.lo \ path.lo \ reflect-go.lo \ - reflect/makefunc.lo \ + reflect/makefunc_ffi_c.lo \ regexp.lo \ runtime-go.lo \ sort.lo \ @@ -1868,6 +1934,7 @@ libgo_go_objs = \ debug/gosym.lo \ debug/macho.lo \ debug/pe.lo \ + debug/plan9obj.lo \ encoding/ascii85.lo \ encoding/asn1.lo \ encoding/base32.lo \ @@ -1899,6 +1966,7 @@ libgo_go_objs = \ net/http/fcgi.lo \ net/http/httptest.lo \ net/http/httputil.lo \ + net/http/internal.lo \ net/http/pprof.lo \ image/color.lo \ image/color/palette.lo \ @@ -1907,6 +1975,7 @@ libgo_go_objs = \ image/jpeg.lo \ image/png.lo \ index/suffixarray.lo \ + internal/syscall.lo \ io/ioutil.lo \ log/syslog.lo \ log/syslog/syslog_c.lo \ @@ -1942,19 +2011,30 @@ libgo_go_objs = \ unicode/utf16.lo \ unicode/utf8.lo -libgo_la_SOURCES = $(runtime_files) - -libgo_la_LDFLAGS = \ +libgo_ldflags = \ -version-info $(libtool_VERSION) $(PTHREAD_CFLAGS) $(AM_LDFLAGS) -libgo_la_LIBADD = \ +libgo_libadd = \ $(libgo_go_objs) ../libbacktrace/libbacktrace.la \ - ../libatomic/libatomic_convenience.la \ - $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS) + $(LIBATOMIC) $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS) + +libgo_la_SOURCES = $(runtime_files) +libgo_la_LDFLAGS = $(libgo_ldflags) +libgo_la_LIBADD = $(libgo_libadd) + +libgo_llgo_la_SOURCES = $(runtime_files) +libgo_llgo_la_LDFLAGS = $(libgo_ldflags) +libgo_llgo_la_LIBADD = $(libgo_libadd) libgobegin_a_SOURCES = \ runtime/go-main.c +libgobegin_llgo_a_SOURCES = \ + runtime/go-main.c + +libnetgo_a_SOURCES = $(go_netgo_files) +libnetgo_a_LIBADD = netgo.o + LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) GOCFLAGS = $(CFLAGS) @@ -1979,7 +2059,14 @@ BUILDPACKAGE = \ files=`echo $^ | sed -e 's/[^ ]*\.gox//g'`; \ $(LTGOCOMPILE) -I . -c -fgo-pkgpath=`echo $@ | sed -e 's/.lo$$//' -e 's/-go$$//'` -o $@ $$files +# Build netgo.o. +BUILDNETGO = \ + $(MKDIR_P) $(@D); \ + files=`echo $^ | sed -e 's/[^ ]*\.gox//g'`; \ + $(GOCOMPILE) -I . -c -fgo-pkgpath=net -o $@ $$files + GOTESTFLAGS = +GOBENCH = # Check a package. CHECK = \ @@ -1999,6 +2086,8 @@ CHECK = \ rm -f $@-testsum $@-testlog; \ if test "$(USE_DEJAGNU)" = "yes"; then \ $(SHELL) $(srcdir)/testsuite/gotest --dejagnu=yes --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --testname="$(@D)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \ + elif test "$(GOBENCH)" != ""; then \ + $(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" --bench="$(GOBENCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \ else \ if $(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files) >>$@-testlog 2>&1; then \ echo "PASS: $(@D)" >> $@-testlog; \ @@ -2013,7 +2102,7 @@ CHECK = \ fi # Build all packages before checking any. -CHECK_DEPS = libgo.la libgobegin.a \ +CHECK_DEPS = \ $(toolexeclibgo_DATA) \ $(toolexeclibgoarchive_DATA) \ $(toolexeclibgocompress_DATA) \ @@ -2042,6 +2131,12 @@ CHECK_DEPS = libgo.la libgobegin.a \ $(toolexeclibgotexttemplate_DATA) \ $(toolexeclibgounicode_DATA) +if GOC_IS_LLGO +CHECK_DEPS += libgo-llgo.la libgobegin-llgo.a +else +CHECK_DEPS += libgo.la libgobegin.a +endif + @go_include@ bufio.lo.dep bufio.lo.dep: $(go_bufio_files) $(BUILDDEPS) @@ -2191,6 +2286,12 @@ net/check: $(CHECK_DEPS) @$(CHECK) .PHONY: net/check +@go_include@ netgo.o.dep +netgo.o.dep: $(go_netgo_files) + $(BUILDDEPS) +netgo.o: $(go_netgo_files) + $(BUILDNETGO) + @go_include@ os.lo.dep os.lo.dep: $(go_os_files) $(BUILDDEPS) @@ -2216,7 +2317,7 @@ reflect-go.lo: $(go_reflect_files) $(BUILDPACKAGE) reflect/check: $(CHECK_DEPS) @$(CHECK) -reflect/makefunc.lo: $(go_reflect_makefunc_s_file) +reflect/makefunc_ffi_c.lo: $(go_reflect_makefunc_c_file) @$(MKDIR_P) reflect $(LTCOMPILE) -c -o $@ $< .PHONY: reflect/check @@ -2620,6 +2721,15 @@ debug/pe/check: $(CHECK_DEPS) @$(CHECK) .PHONY: debug/pe/check +@go_include@ debug/plan9obj.lo.dep +debug/plan9obj.lo.dep: $(go_debug_plan9obj_files) + $(BUILDDEPS) +debug/plan9obj.lo: $(go_debug_plan9obj_files) + $(BUILDPACKAGE) +debug/plan9obj/check: $(CHECK_DEPS) + @$(CHECK) +.PHONY: debug/plan9obj/check + @go_include@ encoding/asn1.lo.dep encoding/asn1.lo.dep: $(go_encoding_asn1_files) $(BUILDDEPS) @@ -3073,6 +3183,15 @@ net/http/httputil/check: $(check_deps) @$(CHECK) .PHONY: net/http/httputil/check +@go_include@ net/http/internal.lo.dep +net/http/internal.lo.dep: $(go_net_http_internal_files) + $(BUILDDEPS) +net/http/internal.lo: $(go_net_http_internal_files) + $(BUILDPACKAGE) +net/http/internal/check: $(CHECK_DEPS) + @$(CHECK) +.PHONY: net/http/internal/check + @go_include@ net/http/pprof.lo.dep net/http/pprof.lo.dep: $(go_net_http_pprof_files) $(BUILDDEPS) @@ -3173,7 +3292,8 @@ runtime/pprof/check: $(CHECK_DEPS) .PHONY: runtime/pprof/check # At least for now, we need -static-libgo for this test, because # otherwise we can't get the line numbers. -runtime_pprof_check_GOCFLAGS = -static-libgo +# Also use -fno-inline to get better results from the memory profiler. +runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline @go_include@ sync/atomic.lo.dep sync/atomic.lo.dep: $(go_sync_atomic_files) @@ -3276,6 +3396,15 @@ syscall/check: $(CHECK_DEPS) @$(CHECK) .PHONY: syscall/check +@go_include@ internal/syscall.lo.dep +internal/syscall.lo.dep: $(go_internal_syscall_files) + $(BUILDDEPS) +internal/syscall.lo: $(go_internal_syscall_files) + $(BUILDPACKAGE) +internal/syscall/check: $(CHECK_DEPS) + @$(CHECK) +.PHONY: internal/syscall/check + # How to build a .gox file from a .lo file. BUILDGOX = \ f=`echo $< | sed -e 's/.lo$$/.o/'`; \ @@ -3417,6 +3546,8 @@ debug/macho.gox: debug/macho.lo $(BUILDGOX) debug/pe.gox: debug/pe.lo $(BUILDGOX) +debug/plan9obj.gox: debug/plan9obj.lo + $(BUILDGOX) encoding/ascii85.gox: encoding/ascii85.lo $(BUILDGOX) @@ -3534,6 +3665,9 @@ net/http/httputil.gox: net/http/httputil.lo net/http/pprof.gox: net/http/pprof.lo $(BUILDGOX) +net/http/internal.gox: net/http/internal.lo + $(BUILDGOX) + net/rpc/jsonrpc.gox: net/rpc/jsonrpc.lo $(BUILDGOX) @@ -3563,6 +3697,9 @@ runtime/pprof.gox: runtime/pprof.lo sync/atomic.gox: sync/atomic.lo $(BUILDGOX) +internal/syscall.gox: internal/syscall.lo + $(BUILDGOX) + text/scanner.gox: text/scanner.lo $(BUILDGOX) text/tabwriter.gox: text/tabwriter.lo @@ -3641,6 +3778,7 @@ TEST_PACKAGES = \ debug/elf/check \ debug/macho/check \ debug/pe/check \ + debug/plan9obj/check \ encoding/ascii85/check \ encoding/asn1/check \ encoding/base32/check \ @@ -3684,6 +3822,7 @@ TEST_PACKAGES = \ net/http/fcgi/check \ net/http/httptest/check \ net/http/httputil/check \ + net/http/internal/check \ net/mail/check \ net/rpc/check \ net/smtp/check \ @@ -3806,6 +3945,9 @@ check-am: check-multi: $(MULTIDO) $(AM_MAKEFLAGS) DO=check-am multi-do # $(MAKE) +bench: + -@$(MAKE) -k $(TEST_PACKAGES) GOBENCH=. + MOSTLYCLEAN_FILES = libgo.head libgo.sum.sep libgo.log.sep mostlyclean-local: diff --git a/libgo/Makefile.in b/libgo/Makefile.in index cf93938379..8ecc339012 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -45,6 +45,8 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ +@GOC_IS_LLGO_TRUE@am__append_1 = libgo-llgo.la libgobegin-llgo.a +@GOC_IS_LLGO_FALSE@am__append_2 = libgo.la libgobegin.a subdir = . DIST_COMMON = README $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) \ @@ -126,78 +128,93 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \ "$(DESTDIR)$(toolexeclibgounicodedir)" LIBRARIES = $(toolexeclib_LIBRARIES) ARFLAGS = cru +libgobegin_llgo_a_AR = $(AR) $(ARFLAGS) +libgobegin_llgo_a_LIBADD = +am_libgobegin_llgo_a_OBJECTS = go-main.$(OBJEXT) +libgobegin_llgo_a_OBJECTS = $(am_libgobegin_llgo_a_OBJECTS) libgobegin_a_AR = $(AR) $(ARFLAGS) libgobegin_a_LIBADD = am_libgobegin_a_OBJECTS = go-main.$(OBJEXT) libgobegin_a_OBJECTS = $(am_libgobegin_a_OBJECTS) +libnetgo_a_AR = $(AR) $(ARFLAGS) +libnetgo_a_DEPENDENCIES = netgo.o +am__objects_1 = +am__objects_2 = $(am__objects_1) $(am__objects_1) $(am__objects_1) \ + $(am__objects_1) $(am__objects_1) $(am__objects_1) \ + $(am__objects_1) +am__objects_3 = $(am__objects_2) +am_libnetgo_a_OBJECTS = $(am__objects_3) +libnetgo_a_OBJECTS = $(am_libnetgo_a_OBJECTS) LTLIBRARIES = $(toolexeclib_LTLIBRARIES) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \ encoding.lo errors.lo expvar.lo flag.lo fmt.lo hash.lo html.lo \ image.lo io.lo log.lo math.lo mime.lo net.lo os.lo path.lo \ - reflect-go.lo reflect/makefunc.lo regexp.lo runtime-go.lo \ - sort.lo strconv.lo strings.lo strings/index.lo sync.lo \ - syscall.lo syscall/errno.lo syscall/signame.lo syscall/wait.lo \ - testing.lo time-go.lo unicode.lo archive/tar.lo archive/zip.lo \ - compress/bzip2.lo compress/flate.lo compress/gzip.lo \ - compress/lzw.lo compress/zlib.lo container/heap.lo \ - container/list.lo container/ring.lo crypto/aes.lo \ - crypto/cipher.lo crypto/des.lo crypto/dsa.lo crypto/ecdsa.lo \ - crypto/elliptic.lo crypto/hmac.lo crypto/md5.lo crypto/rand.lo \ - crypto/rc4.lo crypto/rsa.lo crypto/sha1.lo crypto/sha256.lo \ - crypto/sha512.lo crypto/subtle.lo crypto/tls.lo crypto/x509.lo \ + reflect-go.lo reflect/makefunc_ffi_c.lo regexp.lo \ + runtime-go.lo sort.lo strconv.lo strings.lo strings/index.lo \ + sync.lo syscall.lo syscall/errno.lo syscall/signame.lo \ + syscall/wait.lo testing.lo time-go.lo unicode.lo \ + archive/tar.lo archive/zip.lo compress/bzip2.lo \ + compress/flate.lo compress/gzip.lo compress/lzw.lo \ + compress/zlib.lo container/heap.lo container/list.lo \ + container/ring.lo crypto/aes.lo crypto/cipher.lo crypto/des.lo \ + crypto/dsa.lo crypto/ecdsa.lo crypto/elliptic.lo \ + crypto/hmac.lo crypto/md5.lo crypto/rand.lo crypto/rc4.lo \ + crypto/rsa.lo crypto/sha1.lo crypto/sha256.lo crypto/sha512.lo \ + crypto/subtle.lo crypto/tls.lo crypto/x509.lo \ crypto/x509/pkix.lo database/sql.lo database/sql/driver.lo \ debug/dwarf.lo debug/elf.lo debug/gosym.lo debug/macho.lo \ - debug/pe.lo encoding/ascii85.lo encoding/asn1.lo \ - encoding/base32.lo encoding/base64.lo encoding/binary.lo \ - encoding/csv.lo encoding/gob.lo encoding/hex.lo \ - encoding/json.lo encoding/pem.lo encoding/xml.lo exp/proxy.lo \ - exp/terminal.lo html/template.lo go/ast.lo go/build.lo \ - go/doc.lo go/format.lo go/parser.lo go/printer.lo \ - go/scanner.lo go/token.lo hash/adler32.lo hash/crc32.lo \ - hash/crc64.lo hash/fnv.lo net/http/cgi.lo \ + debug/pe.lo debug/plan9obj.lo encoding/ascii85.lo \ + encoding/asn1.lo encoding/base32.lo encoding/base64.lo \ + encoding/binary.lo encoding/csv.lo encoding/gob.lo \ + encoding/hex.lo encoding/json.lo encoding/pem.lo \ + encoding/xml.lo exp/proxy.lo exp/terminal.lo html/template.lo \ + go/ast.lo go/build.lo go/doc.lo go/format.lo go/parser.lo \ + go/printer.lo go/scanner.lo go/token.lo hash/adler32.lo \ + hash/crc32.lo hash/crc64.lo hash/fnv.lo net/http/cgi.lo \ net/http/cookiejar.lo net/http/fcgi.lo net/http/httptest.lo \ - net/http/httputil.lo net/http/pprof.lo image/color.lo \ - image/color/palette.lo image/draw.lo image/gif.lo \ - image/jpeg.lo image/png.lo index/suffixarray.lo io/ioutil.lo \ - log/syslog.lo log/syslog/syslog_c.lo math/big.lo math/cmplx.lo \ - math/rand.lo mime/multipart.lo net/http.lo net/mail.lo \ - net/rpc.lo net/smtp.lo net/textproto.lo net/url.lo \ - old/regexp.lo old/template.lo os/exec.lo $(am__DEPENDENCIES_1) \ - os/signal.lo os/user.lo path/filepath.lo regexp/syntax.lo \ + net/http/httputil.lo net/http/internal.lo net/http/pprof.lo \ + image/color.lo image/color/palette.lo image/draw.lo \ + image/gif.lo image/jpeg.lo image/png.lo index/suffixarray.lo \ + internal/syscall.lo io/ioutil.lo log/syslog.lo \ + log/syslog/syslog_c.lo math/big.lo math/cmplx.lo math/rand.lo \ + mime/multipart.lo net/http.lo net/mail.lo net/rpc.lo \ + net/smtp.lo net/textproto.lo net/url.lo old/regexp.lo \ + old/template.lo os/exec.lo $(am__DEPENDENCIES_1) os/signal.lo \ + os/user.lo path/filepath.lo regexp/syntax.lo \ net/rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \ sync/atomic.lo sync/atomic_c.lo text/scanner.lo \ text/tabwriter.lo text/template.lo text/template/parse.lo \ testing/iotest.lo testing/quick.lo unicode/utf16.lo \ unicode/utf8.lo -libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \ - ../libbacktrace/libbacktrace.la \ - ../libatomic/libatomic_convenience.la $(am__DEPENDENCIES_1) \ +am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2) \ + ../libbacktrace/libbacktrace.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) -@LIBGO_IS_LINUX_FALSE@am__objects_1 = lock_sema.lo thread-sema.lo -@LIBGO_IS_LINUX_TRUE@am__objects_1 = lock_futex.lo thread-linux.lo -@HAVE_SYS_MMAN_H_FALSE@am__objects_2 = mem_posix_memalign.lo -@HAVE_SYS_MMAN_H_TRUE@am__objects_2 = mem.lo -@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_3 = netpoll_kqueue.lo -@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_3 = netpoll_select.lo -@LIBGO_IS_LINUX_TRUE@am__objects_3 = netpoll_epoll.lo -@LIBGO_IS_RTEMS_TRUE@am__objects_4 = rtems-task-variable-add.lo -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_5 = getncpu-none.lo -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@am__objects_5 = getncpu-bsd.lo -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_5 = getncpu-bsd.lo -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_5 = getncpu-solaris.lo -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_5 = getncpu-irix.lo -@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_5 = \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +libgo_llgo_la_DEPENDENCIES = $(am__DEPENDENCIES_3) +@LIBGO_IS_LINUX_FALSE@am__objects_4 = lock_sema.lo thread-sema.lo +@LIBGO_IS_LINUX_TRUE@am__objects_4 = lock_futex.lo thread-linux.lo +@HAVE_SYS_MMAN_H_FALSE@am__objects_5 = mem_posix_memalign.lo +@HAVE_SYS_MMAN_H_TRUE@am__objects_5 = mem.lo +@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_6 = netpoll_kqueue.lo +@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_6 = netpoll_select.lo +@LIBGO_IS_LINUX_TRUE@am__objects_6 = netpoll_epoll.lo +@LIBGO_IS_RTEMS_TRUE@am__objects_7 = rtems-task-variable-add.lo +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_8 = getncpu-none.lo +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@am__objects_8 = getncpu-bsd.lo +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@am__objects_8 = getncpu-bsd.lo +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@am__objects_8 = getncpu-solaris.lo +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_8 = getncpu-irix.lo +@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@am__objects_8 = \ @LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_LINUX_FALSE@ getncpu-bsd.lo -@LIBGO_IS_LINUX_TRUE@am__objects_5 = getncpu-linux.lo -am__objects_6 = go-append.lo go-assert.lo go-assert-interface.lo \ +@LIBGO_IS_LINUX_TRUE@am__objects_8 = getncpu-linux.lo +am__objects_9 = go-append.lo go-assert.lo go-assert-interface.lo \ go-byte-array-to-string.lo go-breakpoint.lo go-caller.lo \ go-callers.lo go-can-convert-interface.lo go-cdiv.lo go-cgo.lo \ go-check-interface.lo go-construct-map.lo \ go-convert-interface.lo go-copy.lo go-defer.lo \ go-deferred-recover.lo go-eface-compare.lo \ - go-eface-val-compare.lo go-fieldtrack.lo go-getgoroot.lo \ + go-eface-val-compare.lo go-ffi.lo go-fieldtrack.lo \ go-int-array-to-string.lo go-int-to-string.lo \ go-interface-compare.lo go-interface-eface-compare.lo \ go-interface-val-compare.lo go-make-slice.lo go-map-delete.lo \ @@ -210,21 +227,29 @@ am__objects_6 = go-append.lo go-assert.lo go-assert-interface.lo \ go-strplus.lo go-strslice.lo go-traceback.lo \ go-type-complex.lo go-type-eface.lo go-type-error.lo \ go-type-float.lo go-type-identity.lo go-type-interface.lo \ - go-type-string.lo go-typedesc-equal.lo go-typestring.lo \ - go-unsafe-new.lo go-unsafe-newarray.lo go-unsafe-pointer.lo \ - go-unwind.lo go-varargs.lo chan.lo cpuprof.lo env_posix.lo \ - lfstack.lo $(am__objects_1) mcache.lo mcentral.lo \ - $(am__objects_2) mfinal.lo mfixalloc.lo mgc0.lo mheap.lo \ - msize.lo $(am__objects_3) panic.lo parfor.lo print.lo proc.lo \ - runtime.lo signal_unix.lo thread.lo yield.lo $(am__objects_4) \ - iface.lo malloc.lo map.lo mprof.lo netpoll.lo reflect.lo \ - runtime1.lo sema.lo sigqueue.lo string.lo time.lo \ - $(am__objects_5) -am_libgo_la_OBJECTS = $(am__objects_6) + go-type-string.lo go-typedesc-equal.lo go-unsafe-new.lo \ + go-unsafe-newarray.lo go-unsafe-pointer.lo go-unsetenv.lo \ + go-unwind.lo go-varargs.lo env_posix.lo heapdump.lo \ + $(am__objects_4) mcache.lo mcentral.lo $(am__objects_5) \ + mfixalloc.lo mgc0.lo mheap.lo msize.lo $(am__objects_6) \ + panic.lo parfor.lo print.lo proc.lo runtime.lo signal_unix.lo \ + thread.lo yield.lo $(am__objects_7) chan.lo cpuprof.lo \ + go-iface.lo lfstack.lo malloc.lo map.lo mprof.lo netpoll.lo \ + rdebug.lo reflect.lo runtime1.lo sema.lo sigqueue.lo string.lo \ + time.lo $(am__objects_8) +am_libgo_llgo_la_OBJECTS = $(am__objects_9) +libgo_llgo_la_OBJECTS = $(am_libgo_llgo_la_OBJECTS) +libgo_llgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libgo_llgo_la_LDFLAGS) $(LDFLAGS) -o $@ +@GOC_IS_LLGO_TRUE@am_libgo_llgo_la_rpath = -rpath $(toolexeclibdir) +libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_3) +am_libgo_la_OBJECTS = $(am__objects_9) libgo_la_OBJECTS = $(am_libgo_la_OBJECTS) libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(libgo_la_LDFLAGS) \ $(LDFLAGS) -o $@ +@GOC_IS_LLGO_FALSE@am_libgo_la_rpath = -rpath $(toolexeclibdir) DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/../depcomp am__depfiles_maybe = depfiles @@ -238,7 +263,9 @@ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -SOURCES = $(libgobegin_a_SOURCES) $(libgo_la_SOURCES) +SOURCES = $(libgobegin_llgo_a_SOURCES) $(libgobegin_a_SOURCES) \ + $(libnetgo_a_SOURCES) $(libgo_llgo_la_SOURCES) \ + $(libgo_la_SOURCES) MULTISRCTOP = MULTIBUILDTOP = MULTIDIRS = @@ -252,23 +279,24 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive -DATA = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \ - $(toolexeclibgocompress_DATA) $(toolexeclibgocontainer_DATA) \ - $(toolexeclibgocrypto_DATA) $(toolexeclibgocryptox509_DATA) \ - $(toolexeclibgodatabase_DATA) $(toolexeclibgodatabasesql_DATA) \ - $(toolexeclibgodebug_DATA) $(toolexeclibgoencoding_DATA) \ - $(toolexeclibgoexp_DATA) $(toolexeclibgogo_DATA) \ - $(toolexeclibgohash_DATA) $(toolexeclibgohtml_DATA) \ - $(toolexeclibgoimage_DATA) $(toolexeclibgoimagecolor_DATA) \ - $(toolexeclibgoindex_DATA) $(toolexeclibgoio_DATA) \ - $(toolexeclibgolog_DATA) $(toolexeclibgomath_DATA) \ - $(toolexeclibgomime_DATA) $(toolexeclibgonet_DATA) \ - $(toolexeclibgonethttp_DATA) $(toolexeclibgonetrpc_DATA) \ - $(toolexeclibgoold_DATA) $(toolexeclibgoos_DATA) \ - $(toolexeclibgopath_DATA) $(toolexeclibgoregexp_DATA) \ - $(toolexeclibgoruntime_DATA) $(toolexeclibgosync_DATA) \ - $(toolexeclibgotesting_DATA) $(toolexeclibgotext_DATA) \ - $(toolexeclibgotexttemplate_DATA) $(toolexeclibgounicode_DATA) +DATA = $(noinst_DATA) $(toolexeclibgo_DATA) \ + $(toolexeclibgoarchive_DATA) $(toolexeclibgocompress_DATA) \ + $(toolexeclibgocontainer_DATA) $(toolexeclibgocrypto_DATA) \ + $(toolexeclibgocryptox509_DATA) $(toolexeclibgodatabase_DATA) \ + $(toolexeclibgodatabasesql_DATA) $(toolexeclibgodebug_DATA) \ + $(toolexeclibgoencoding_DATA) $(toolexeclibgoexp_DATA) \ + $(toolexeclibgogo_DATA) $(toolexeclibgohash_DATA) \ + $(toolexeclibgohtml_DATA) $(toolexeclibgoimage_DATA) \ + $(toolexeclibgoimagecolor_DATA) $(toolexeclibgoindex_DATA) \ + $(toolexeclibgoio_DATA) $(toolexeclibgolog_DATA) \ + $(toolexeclibgomath_DATA) $(toolexeclibgomime_DATA) \ + $(toolexeclibgonet_DATA) $(toolexeclibgonethttp_DATA) \ + $(toolexeclibgonetrpc_DATA) $(toolexeclibgoold_DATA) \ + $(toolexeclibgoos_DATA) $(toolexeclibgopath_DATA) \ + $(toolexeclibgoregexp_DATA) $(toolexeclibgoruntime_DATA) \ + $(toolexeclibgosync_DATA) $(toolexeclibgotesting_DATA) \ + $(toolexeclibgotext_DATA) $(toolexeclibgotexttemplate_DATA) \ + $(toolexeclibgounicode_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ @@ -316,6 +344,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBATOMIC = @LIBATOMIC@ LIBFFI = @LIBFFI@ LIBFFIINCS = @LIBFFIINCS@ LIBOBJS = @LIBOBJS@ @@ -429,7 +458,7 @@ top_srcdir = @top_srcdir@ SUFFIXES = .c .go .gox .o .obj .lo .a @LIBGO_IS_RTEMS_TRUE@subdirs = testsuite SUBDIRS = ${subdirs} -gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) +gcc_version := $(shell $(GOC) -dumpversion) MAINT_CHARSET = latin1 mkinstalldirs = $(SHELL) $(toplevel_srcdir)/mkinstalldirs PWD_COMMAND = $${PWDCMD-pwd} @@ -437,6 +466,7 @@ STAMP = echo timestamp > toolexecdir = $(glibgo_toolexecdir) toolexeclibdir = $(glibgo_toolexeclibdir) toolexeclibgodir = $(nover_glibgo_toolexeclibdir)/go/$(gcc_version)/$(target_alias) +libexecsubdir = $(libexecdir)/gcc/$(target_alias)/$(gcc_version) WARN_CFLAGS = $(WARN_FLAGS) $(WERROR) # -I/-D flags to pass when compiling. @@ -500,8 +530,10 @@ AM_MAKEFLAGS = \ # Subdir rules rely on $(FLAGS_TO_PASS) FLAGS_TO_PASS = $(AM_MAKEFLAGS) -toolexeclib_LTLIBRARIES = libgo.la -toolexeclib_LIBRARIES = libgobegin.a +@GOC_IS_LLGO_FALSE@toolexeclib_LTLIBRARIES = libgo.la +@GOC_IS_LLGO_TRUE@toolexeclib_LTLIBRARIES = libgo-llgo.la +@GOC_IS_LLGO_FALSE@toolexeclib_LIBRARIES = libgobegin.a libnetgo.a +@GOC_IS_LLGO_TRUE@toolexeclib_LIBRARIES = libgobegin-llgo.a toolexeclibgo_DATA = \ bufio.gox \ bytes.gox \ @@ -590,7 +622,8 @@ toolexeclibgodebug_DATA = \ debug/elf.gox \ debug/gosym.gox \ debug/macho.gox \ - debug/pe.gox + debug/pe.gox \ + debug/plan9obj.gox toolexeclibgoencodingdir = $(toolexeclibgodir)/encoding toolexeclibgoencoding_DATA = \ @@ -772,8 +805,8 @@ runtime_files = \ runtime/go-deferred-recover.c \ runtime/go-eface-compare.c \ runtime/go-eface-val-compare.c \ + runtime/go-ffi.c \ runtime/go-fieldtrack.c \ - runtime/go-getgoroot.c \ runtime/go-int-array-to-string.c \ runtime/go-int-to-string.c \ runtime/go-interface-compare.c \ @@ -814,21 +847,18 @@ runtime_files = \ runtime/go-type-interface.c \ runtime/go-type-string.c \ runtime/go-typedesc-equal.c \ - runtime/go-typestring.c \ runtime/go-unsafe-new.c \ runtime/go-unsafe-newarray.c \ runtime/go-unsafe-pointer.c \ + runtime/go-unsetenv.c \ runtime/go-unwind.c \ runtime/go-varargs.c \ - runtime/chan.c \ - runtime/cpuprof.c \ runtime/env_posix.c \ - runtime/lfstack.c \ + runtime/heapdump.c \ $(runtime_lock_files) \ runtime/mcache.c \ runtime/mcentral.c \ $(runtime_mem_file) \ - runtime/mfinal.c \ runtime/mfixalloc.c \ runtime/mgc0.c \ runtime/mheap.c \ @@ -843,11 +873,15 @@ runtime_files = \ runtime/thread.c \ runtime/yield.c \ $(rtems_task_variable_add_file) \ - iface.c \ + chan.c \ + cpuprof.c \ + go-iface.c \ + lfstack.c \ malloc.c \ map.c \ mprof.c \ netpoll.c \ + rdebug.c \ reflect.c \ runtime1.c \ sema.c \ @@ -971,19 +1005,19 @@ go_mime_files = \ @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go @LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sock_file = go/net/sock_bsd.go -@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sock_file = go/net/sock_solaris.go +@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sock_file = go/net/sock_stub.go @LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sock_file = go/net/sock_linux.go @LIBGO_IS_LINUX_TRUE@go_net_sock_file = go/net/sock_linux.go @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go @LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockopt_file = go/net/sockopt_bsd.go -@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockopt_file = go/net/sockopt_bsd.go +@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockopt_file = go/net/sockopt_solaris.go @LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockopt_file = go/net/sockopt_linux.go @LIBGO_IS_LINUX_TRUE@go_net_sockopt_file = go/net/sockopt_linux.go @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go @LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go @LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go -@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockoptip_file = go/net/sockoptip_bsd.go go/net/sockoptip_posix.go +@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_sockoptip_file = go/net/sockoptip_stub.go @LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go @LIBGO_IS_LINUX_TRUE@go_net_sockoptip_file = go/net/sockoptip_linux.go go/net/sockoptip_posix.go @LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_sendfile_file = go/net/sendfile_stub.go @@ -996,13 +1030,12 @@ go_mime_files = \ @LIBGO_IS_LINUX_TRUE@go_net_interface_file = go/net/interface_linux.go @LIBGO_IS_LINUX_FALSE@go_net_cloexec_file = go/net/sys_cloexec.go @LIBGO_IS_LINUX_TRUE@go_net_cloexec_file = go/net/sock_cloexec.go -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_unix.go -@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_unix.go +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_dragonfly.go +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_solaris.go @LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_OPENBSD_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_darwin.go @LIBGO_IS_OPENBSD_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_openbsd.go -go_net_files = \ - go/net/cgo_unix.go \ - $(go_net_cgo_file) \ +go_net_common_files = \ $(go_net_cloexec_file) \ go/net/dial.go \ go/net/dnsclient.go \ @@ -1046,6 +1079,15 @@ go_net_files = \ go/net/unixsock.go \ go/net/unixsock_posix.go +go_net_files = \ + go/net/cgo_unix.go \ + $(go_net_cgo_file) \ + $(go_net_common_files) + +go_netgo_files = \ + go/net/cgo_stub.go \ + $(go_net_common_files) + @LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@go_os_dir_file = go/os/dir_regfile.go @LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@go_os_dir_file = go/os/dir_largefile.go @LIBGO_IS_386_TRUE@@LIBGO_IS_SOLARIS_TRUE@go_os_dir_file = go/os/dir_largefile.go @@ -1058,6 +1100,9 @@ go_net_files = \ @LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_sys_file = go/os/sys_uname.go @LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_os_sys_file = go/os/sys_uname.go @LIBGO_IS_LINUX_TRUE@go_os_sys_file = go/os/sys_linux.go +@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@go_os_cloexec_file = go/os/sys_unix.go +@LIBGO_IS_DARWIN_TRUE@@LIBGO_IS_FREEBSD_FALSE@go_os_cloexec_file = go/os/sys_darwin.go +@LIBGO_IS_FREEBSD_TRUE@go_os_cloexec_file = go/os/sys_freebsd.go @LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat.go @LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_dragonfly.go @LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_os_stat_file = go/os/stat_atimespec.go @@ -1090,6 +1135,7 @@ go_os_files = \ $(go_os_stat_file) \ go/os/str.go \ $(go_os_sys_file) \ + $(go_os_cloexec_file) \ go/os/types.go \ go/os/types_notwin.go @@ -1097,31 +1143,19 @@ go_path_files = \ go/path/match.go \ go/path/path.go -@LIBGO_IS_386_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file = -@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_file = \ -@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@ go/reflect/makefuncgo_386.go - -@LIBGO_IS_X86_64_TRUE@go_reflect_makefunc_file = \ -@LIBGO_IS_X86_64_TRUE@ go/reflect/makefuncgo_amd64.go - -@LIBGO_IS_386_FALSE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \ -@LIBGO_IS_386_FALSE@@LIBGO_IS_X86_64_FALSE@ go/reflect/makefunc_dummy.c - -@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@go_reflect_makefunc_s_file = \ -@LIBGO_IS_386_TRUE@@LIBGO_IS_X86_64_FALSE@ go/reflect/makefunc_386.S - -@LIBGO_IS_X86_64_TRUE@go_reflect_makefunc_s_file = \ -@LIBGO_IS_X86_64_TRUE@ go/reflect/makefunc_amd64.S - go_reflect_files = \ go/reflect/deepequal.go \ go/reflect/makefunc.go \ - $(go_reflect_makefunc_file) \ + go/reflect/makefunc_ffi.go \ go/reflect/type.go \ go/reflect/value.go +go_reflect_makefunc_c_file = \ + go/reflect/makefunc_ffi_c.c + go_regexp_files = \ go/regexp/exec.go \ + go/regexp/onepass.go \ go/regexp/regexp.go go_net_rpc_files = \ @@ -1136,9 +1170,9 @@ go_runtime_files = \ go/runtime/extern.go \ go/runtime/mem.go \ go/runtime/softfloat64.go \ - go/runtime/type.go \ version.go +noinst_DATA = zstdpkglist.go go_sort_files = \ go/sort/search.go \ go/sort/sort.go @@ -1168,6 +1202,7 @@ go_sync_files = \ go/sync/cond.go \ go/sync/mutex.go \ go/sync/once.go \ + go/sync/pool.go \ go/sync/race0.go \ go/sync/runtime.go \ go/sync/rwmutex.go \ @@ -1276,7 +1311,8 @@ go_crypto_cipher_files = \ go/crypto/cipher/ctr.go \ go/crypto/cipher/gcm.go \ go/crypto/cipher/io.go \ - go/crypto/cipher/ofb.go + go/crypto/cipher/ofb.go \ + go/crypto/cipher/xor.go go_crypto_des_files = \ go/crypto/des/block.go \ @@ -1299,11 +1335,15 @@ go_crypto_hmac_files = \ go_crypto_md5_files = \ go/crypto/md5/md5.go \ - go/crypto/md5/md5block.go + go/crypto/md5/md5block.go \ + go/crypto/md5/md5block_generic.go +@LIBGO_IS_LINUX_FALSE@crypto_rand_file = +@LIBGO_IS_LINUX_TRUE@crypto_rand_file = go/crypto/rand/rand_linux.go go_crypto_rand_files = \ go/crypto/rand/rand.go \ go/crypto/rand/rand_unix.go \ + $(crypto_rand_file) \ go/crypto/rand/util.go go_crypto_rc4_files = \ @@ -1317,7 +1357,8 @@ go_crypto_rsa_files = \ go_crypto_sha1_files = \ go/crypto/sha1/sha1.go \ - go/crypto/sha1/sha1block.go + go/crypto/sha1/sha1block.go \ + go/crypto/sha1/sha1block_generic.go go_crypto_sha256_files = \ go/crypto/sha256/sha256.go \ @@ -1372,6 +1413,7 @@ go_debug_dwarf_files = \ go/debug/dwarf/line.go \ go/debug/dwarf/open.go \ go/debug/dwarf/type.go \ + go/debug/dwarf/typeunit.go \ go/debug/dwarf/unit.go go_debug_elf_files = \ @@ -1383,6 +1425,7 @@ go_debug_gosym_files = \ go/debug/gosym/symtab.go go_debug_macho_files = \ + go/debug/macho/fat.go \ go/debug/macho/file.go \ go/debug/macho/macho.go @@ -1390,6 +1433,10 @@ go_debug_pe_files = \ go/debug/pe/file.go \ go/debug/pe/pe.go +go_debug_plan9obj_files = \ + go/debug/plan9obj/file.go \ + go/debug/plan9obj/plan9obj.go + go_encoding_ascii85_files = \ go/encoding/ascii85/ascii85.go @@ -1415,9 +1462,11 @@ go_encoding_csv_files = \ go_encoding_gob_files = \ go/encoding/gob/decode.go \ go/encoding/gob/decoder.go \ + go/encoding/gob/dec_helpers.go \ go/encoding/gob/doc.go \ go/encoding/gob/encode.go \ go/encoding/gob/encoder.go \ + go/encoding/gob/enc_helpers.go \ go/encoding/gob/error.go \ go/encoding/gob/type.go @@ -1427,6 +1476,7 @@ go_encoding_hex_files = \ go_encoding_json_files = \ go/encoding/json/decode.go \ go/encoding/json/encode.go \ + go/encoding/json/fold.go \ go/encoding/json/indent.go \ go/encoding/json/scanner.go \ go/encoding/json/stream.go \ @@ -1555,7 +1605,6 @@ go_index_suffixarray_files = \ go/index/suffixarray/suffixarray.go go_io_ioutil_files = \ - go/io/ioutil/blackhole.go \ go/io/ioutil/ioutil.go \ go/io/ioutil/tempfile.go @@ -1595,7 +1644,6 @@ go_mime_multipart_files = \ go/mime/multipart/writer.go go_net_http_files = \ - go/net/http/chunked.go \ go/net/http/client.go \ go/net/http/cookie.go \ go/net/http/filetransport.go \ @@ -1648,11 +1696,14 @@ go_net_http_pprof_files = \ go/net/http/pprof/pprof.go go_net_http_httputil_files = \ - go/net/http/httputil/chunked.go \ go/net/http/httputil/dump.go \ + go/net/http/httputil/httputil.go \ go/net/http/httputil/persist.go \ go/net/http/httputil/reverseproxy.go +go_net_http_internal_files = \ + go/net/http/internal/chunked.go + go_old_regexp_files = \ go/old/regexp/regexp.go @@ -1682,7 +1733,8 @@ go_path_filepath_files = \ go/path/filepath/match.go \ go/path/filepath/path.go \ go/path/filepath/path_unix.go \ - go/path/filepath/symlink.go + go/path/filepath/symlink.go \ + go/path/filepath/symlink_unix.go go_regexp_syntax_files = \ go/regexp/syntax/compile.go \ @@ -1720,7 +1772,8 @@ go_text_template_parse_files = \ go/text/template/parse/parse.go go_sync_atomic_files = \ - go/sync/atomic/doc.go + go/sync/atomic/doc.go \ + go/sync/atomic/value.go go_sync_atomic_c_files = \ go/sync/atomic/atomic.c @@ -1863,7 +1916,16 @@ go_syscall_c_files = \ go_syscall_test_files = \ $(syscall_creds_test_file) \ - go/syscall/passfd_test.go + go/syscall/export_test.go \ + go/syscall/mmap_unix_test.go \ + go/syscall/syscall_test.go \ + go/syscall/syscall_unix_test.go + +@LIBGO_IS_LINUX_FALSE@internal_syscall_getrandom_file = +@LIBGO_IS_LINUX_TRUE@internal_syscall_getrandom_file = go/internal/syscall/getrandom_linux.go +go_internal_syscall_files = \ + go/internal/syscall/dummy.go \ + $(internal_syscall_getrandom_file) @LIBGO_IS_LINUX_FALSE@os_lib_inotify_lo = @@ -1890,7 +1952,7 @@ libgo_go_objs = \ os.lo \ path.lo \ reflect-go.lo \ - reflect/makefunc.lo \ + reflect/makefunc_ffi_c.lo \ regexp.lo \ runtime-go.lo \ sort.lo \ @@ -1940,6 +2002,7 @@ libgo_go_objs = \ debug/gosym.lo \ debug/macho.lo \ debug/pe.lo \ + debug/plan9obj.lo \ encoding/ascii85.lo \ encoding/asn1.lo \ encoding/base32.lo \ @@ -1971,6 +2034,7 @@ libgo_go_objs = \ net/http/fcgi.lo \ net/http/httptest.lo \ net/http/httputil.lo \ + net/http/internal.lo \ net/http/pprof.lo \ image/color.lo \ image/color/palette.lo \ @@ -1979,6 +2043,7 @@ libgo_go_objs = \ image/jpeg.lo \ image/png.lo \ index/suffixarray.lo \ + internal/syscall.lo \ io/ioutil.lo \ log/syslog.lo \ log/syslog/syslog_c.lo \ @@ -2014,18 +2079,27 @@ libgo_go_objs = \ unicode/utf16.lo \ unicode/utf8.lo -libgo_la_SOURCES = $(runtime_files) -libgo_la_LDFLAGS = \ +libgo_ldflags = \ -version-info $(libtool_VERSION) $(PTHREAD_CFLAGS) $(AM_LDFLAGS) -libgo_la_LIBADD = \ +libgo_libadd = \ $(libgo_go_objs) ../libbacktrace/libbacktrace.la \ - ../libatomic/libatomic_convenience.la \ - $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS) + $(LIBATOMIC) $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS) +libgo_la_SOURCES = $(runtime_files) +libgo_la_LDFLAGS = $(libgo_ldflags) +libgo_la_LIBADD = $(libgo_libadd) +libgo_llgo_la_SOURCES = $(runtime_files) +libgo_llgo_la_LDFLAGS = $(libgo_ldflags) +libgo_llgo_la_LIBADD = $(libgo_libadd) libgobegin_a_SOURCES = \ runtime/go-main.c +libgobegin_llgo_a_SOURCES = \ + runtime/go-main.c + +libnetgo_a_SOURCES = $(go_netgo_files) +libnetgo_a_LIBADD = netgo.o LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) AM_GOCFLAGS = $(STRINGOPS_FLAG) GOCOMPILE = $(GOC) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_GOCFLAGS) $(GOCFLAGS) @@ -2049,7 +2123,15 @@ BUILDPACKAGE = \ files=`echo $^ | sed -e 's/[^ ]*\.gox//g'`; \ $(LTGOCOMPILE) -I . -c -fgo-pkgpath=`echo $@ | sed -e 's/.lo$$//' -e 's/-go$$//'` -o $@ $$files + +# Build netgo.o. +BUILDNETGO = \ + $(MKDIR_P) $(@D); \ + files=`echo $^ | sed -e 's/[^ ]*\.gox//g'`; \ + $(GOCOMPILE) -I . -c -fgo-pkgpath=net -o $@ $$files + GOTESTFLAGS = +GOBENCH = # Check a package. CHECK = \ @@ -2069,6 +2151,8 @@ CHECK = \ rm -f $@-testsum $@-testlog; \ if test "$(USE_DEJAGNU)" = "yes"; then \ $(SHELL) $(srcdir)/testsuite/gotest --dejagnu=yes --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --testname="$(@D)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \ + elif test "$(GOBENCH)" != ""; then \ + $(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" --bench="$(GOBENCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files); \ else \ if $(SHELL) $(srcdir)/testsuite/gotest --basedir=$(srcdir) --srcdir=$(srcdir)/go/$(@D) --pkgpath="$(@D)" --pkgfiles="$(go_$(subst /,_,$(@D))_files)" --goarch="$(GOARCH)" $(GOTESTFLAGS) $(go_$(subst /,_,$(@D))_test_files) >>$@-testlog 2>&1; then \ echo "PASS: $(@D)" >> $@-testlog; \ @@ -2084,38 +2168,24 @@ CHECK = \ # Build all packages before checking any. -CHECK_DEPS = libgo.la libgobegin.a \ - $(toolexeclibgo_DATA) \ - $(toolexeclibgoarchive_DATA) \ - $(toolexeclibgocompress_DATA) \ - $(toolexeclibgocontainer_DATA) \ - $(toolexeclibgocrypto_DATA) \ - $(toolexeclibgodebug_DATA) \ - $(toolexeclibgoencoding_DATA) \ - $(toolexeclibgoexp_DATA) \ - $(toolexeclibgogo_DATA) \ - $(toolexeclibgohash_DATA) \ - $(toolexeclibgoimage_DATA) \ - $(toolexeclibgoindex_DATA) \ - $(toolexeclibgoio_DATA) \ - $(toolexeclibgolog_DATA) \ - $(toolexeclibgomath_DATA) \ - $(toolexeclibgomime_DATA) \ - $(toolexeclibgonet_DATA) \ - $(toolexeclibgonethttp_DATA) \ - $(toolexeclibgoos_DATA) \ - $(toolexeclibgopath_DATA) \ - $(toolexeclibgorpc_DATA) \ - $(toolexeclibgoruntime_DATA) \ - $(toolexeclibgosync_DATA) \ - $(toolexeclibgotesting_DATA) \ - $(toolexeclibgotext_DATA) \ - $(toolexeclibgotexttemplate_DATA) \ - $(toolexeclibgounicode_DATA) - +CHECK_DEPS = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \ + $(toolexeclibgocompress_DATA) $(toolexeclibgocontainer_DATA) \ + $(toolexeclibgocrypto_DATA) $(toolexeclibgodebug_DATA) \ + $(toolexeclibgoencoding_DATA) $(toolexeclibgoexp_DATA) \ + $(toolexeclibgogo_DATA) $(toolexeclibgohash_DATA) \ + $(toolexeclibgoimage_DATA) $(toolexeclibgoindex_DATA) \ + $(toolexeclibgoio_DATA) $(toolexeclibgolog_DATA) \ + $(toolexeclibgomath_DATA) $(toolexeclibgomime_DATA) \ + $(toolexeclibgonet_DATA) $(toolexeclibgonethttp_DATA) \ + $(toolexeclibgoos_DATA) $(toolexeclibgopath_DATA) \ + $(toolexeclibgorpc_DATA) $(toolexeclibgoruntime_DATA) \ + $(toolexeclibgosync_DATA) $(toolexeclibgotesting_DATA) \ + $(toolexeclibgotext_DATA) $(toolexeclibgotexttemplate_DATA) \ + $(toolexeclibgounicode_DATA) $(am__append_1) $(am__append_2) # At least for now, we need -static-libgo for this test, because # otherwise we can't get the line numbers. -runtime_pprof_check_GOCFLAGS = -static-libgo +# Also use -fno-inline to get better results from the memory profiler. +runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline # How to build a .gox file from a .lo file. BUILDGOX = \ @@ -2181,6 +2251,7 @@ TEST_PACKAGES = \ debug/elf/check \ debug/macho/check \ debug/pe/check \ + debug/plan9obj/check \ encoding/ascii85/check \ encoding/asn1/check \ encoding/base32/check \ @@ -2224,6 +2295,7 @@ TEST_PACKAGES = \ net/http/fcgi/check \ net/http/httptest/check \ net/http/httputil/check \ + net/http/internal/check \ net/mail/check \ net/rpc/check \ net/smtp/check \ @@ -2337,10 +2409,18 @@ uninstall-toolexeclibLIBRARIES: clean-toolexeclibLIBRARIES: -test -z "$(toolexeclib_LIBRARIES)" || rm -f $(toolexeclib_LIBRARIES) +libgobegin-llgo.a: $(libgobegin_llgo_a_OBJECTS) $(libgobegin_llgo_a_DEPENDENCIES) + -rm -f libgobegin-llgo.a + $(libgobegin_llgo_a_AR) libgobegin-llgo.a $(libgobegin_llgo_a_OBJECTS) $(libgobegin_llgo_a_LIBADD) + $(RANLIB) libgobegin-llgo.a libgobegin.a: $(libgobegin_a_OBJECTS) $(libgobegin_a_DEPENDENCIES) -rm -f libgobegin.a $(libgobegin_a_AR) libgobegin.a $(libgobegin_a_OBJECTS) $(libgobegin_a_LIBADD) $(RANLIB) libgobegin.a +libnetgo.a: $(libnetgo_a_OBJECTS) $(libnetgo_a_DEPENDENCIES) + -rm -f libnetgo.a + $(libnetgo_a_AR) libnetgo.a $(libnetgo_a_OBJECTS) $(libnetgo_a_LIBADD) + $(RANLIB) libnetgo.a install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)" @@ -2372,8 +2452,10 @@ clean-toolexeclibLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done +libgo-llgo.la: $(libgo_llgo_la_OBJECTS) $(libgo_llgo_la_DEPENDENCIES) + $(libgo_llgo_la_LINK) $(am_libgo_llgo_la_rpath) $(libgo_llgo_la_OBJECTS) $(libgo_llgo_la_LIBADD) $(LIBS) libgo.la: $(libgo_la_OBJECTS) $(libgo_la_DEPENDENCIES) - $(libgo_la_LINK) -rpath $(toolexeclibdir) $(libgo_la_OBJECTS) $(libgo_la_LIBADD) $(LIBS) + $(libgo_la_LINK) $(am_libgo_la_rpath) $(libgo_la_OBJECTS) $(libgo_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -2407,8 +2489,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-deferred-recover.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-eface-compare.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-eface-val-compare.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-ffi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-fieldtrack.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-getgoroot.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-iface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-int-array-to-string.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-int-to-string.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-interface-compare.Plo@am__quote@ @@ -2450,13 +2533,13 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-interface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-type-string.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-typedesc-equal.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-typestring.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-new.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-newarray.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-pointer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsetenv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unwind.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-varargs.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iface.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heapdump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lfstack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock_futex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock_sema.Plo@am__quote@ @@ -2466,7 +2549,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mcentral.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem_posix_memalign.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mfinal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mfixalloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mgc0.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mheap.Plo@am__quote@ @@ -2480,6 +2562,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parfor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rdebug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reflect.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rtems-task-variable-add.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/runtime.Plo@am__quote@ @@ -2655,6 +2738,13 @@ go-eface-val-compare.lo: runtime/go-eface-val-compare.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-eface-val-compare.lo `test -f 'runtime/go-eface-val-compare.c' || echo '$(srcdir)/'`runtime/go-eface-val-compare.c +go-ffi.lo: runtime/go-ffi.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-ffi.lo -MD -MP -MF $(DEPDIR)/go-ffi.Tpo -c -o go-ffi.lo `test -f 'runtime/go-ffi.c' || echo '$(srcdir)/'`runtime/go-ffi.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-ffi.Tpo $(DEPDIR)/go-ffi.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-ffi.c' object='go-ffi.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-ffi.lo `test -f 'runtime/go-ffi.c' || echo '$(srcdir)/'`runtime/go-ffi.c + go-fieldtrack.lo: runtime/go-fieldtrack.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-fieldtrack.lo -MD -MP -MF $(DEPDIR)/go-fieldtrack.Tpo -c -o go-fieldtrack.lo `test -f 'runtime/go-fieldtrack.c' || echo '$(srcdir)/'`runtime/go-fieldtrack.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-fieldtrack.Tpo $(DEPDIR)/go-fieldtrack.Plo @@ -2662,13 +2752,6 @@ go-fieldtrack.lo: runtime/go-fieldtrack.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-fieldtrack.lo `test -f 'runtime/go-fieldtrack.c' || echo '$(srcdir)/'`runtime/go-fieldtrack.c -go-getgoroot.lo: runtime/go-getgoroot.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-getgoroot.lo -MD -MP -MF $(DEPDIR)/go-getgoroot.Tpo -c -o go-getgoroot.lo `test -f 'runtime/go-getgoroot.c' || echo '$(srcdir)/'`runtime/go-getgoroot.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-getgoroot.Tpo $(DEPDIR)/go-getgoroot.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-getgoroot.c' object='go-getgoroot.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-getgoroot.lo `test -f 'runtime/go-getgoroot.c' || echo '$(srcdir)/'`runtime/go-getgoroot.c - go-int-array-to-string.lo: runtime/go-int-array-to-string.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-int-array-to-string.lo -MD -MP -MF $(DEPDIR)/go-int-array-to-string.Tpo -c -o go-int-array-to-string.lo `test -f 'runtime/go-int-array-to-string.c' || echo '$(srcdir)/'`runtime/go-int-array-to-string.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-int-array-to-string.Tpo $(DEPDIR)/go-int-array-to-string.Plo @@ -2949,13 +3032,6 @@ go-typedesc-equal.lo: runtime/go-typedesc-equal.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-typedesc-equal.lo `test -f 'runtime/go-typedesc-equal.c' || echo '$(srcdir)/'`runtime/go-typedesc-equal.c -go-typestring.lo: runtime/go-typestring.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-typestring.lo -MD -MP -MF $(DEPDIR)/go-typestring.Tpo -c -o go-typestring.lo `test -f 'runtime/go-typestring.c' || echo '$(srcdir)/'`runtime/go-typestring.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-typestring.Tpo $(DEPDIR)/go-typestring.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-typestring.c' object='go-typestring.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-typestring.lo `test -f 'runtime/go-typestring.c' || echo '$(srcdir)/'`runtime/go-typestring.c - go-unsafe-new.lo: runtime/go-unsafe-new.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-unsafe-new.lo -MD -MP -MF $(DEPDIR)/go-unsafe-new.Tpo -c -o go-unsafe-new.lo `test -f 'runtime/go-unsafe-new.c' || echo '$(srcdir)/'`runtime/go-unsafe-new.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-unsafe-new.Tpo $(DEPDIR)/go-unsafe-new.Plo @@ -2977,6 +3053,13 @@ go-unsafe-pointer.lo: runtime/go-unsafe-pointer.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-unsafe-pointer.lo `test -f 'runtime/go-unsafe-pointer.c' || echo '$(srcdir)/'`runtime/go-unsafe-pointer.c +go-unsetenv.lo: runtime/go-unsetenv.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-unsetenv.lo -MD -MP -MF $(DEPDIR)/go-unsetenv.Tpo -c -o go-unsetenv.lo `test -f 'runtime/go-unsetenv.c' || echo '$(srcdir)/'`runtime/go-unsetenv.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-unsetenv.Tpo $(DEPDIR)/go-unsetenv.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-unsetenv.c' object='go-unsetenv.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-unsetenv.lo `test -f 'runtime/go-unsetenv.c' || echo '$(srcdir)/'`runtime/go-unsetenv.c + go-unwind.lo: runtime/go-unwind.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-unwind.lo -MD -MP -MF $(DEPDIR)/go-unwind.Tpo -c -o go-unwind.lo `test -f 'runtime/go-unwind.c' || echo '$(srcdir)/'`runtime/go-unwind.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-unwind.Tpo $(DEPDIR)/go-unwind.Plo @@ -2991,20 +3074,6 @@ go-varargs.lo: runtime/go-varargs.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-varargs.lo `test -f 'runtime/go-varargs.c' || echo '$(srcdir)/'`runtime/go-varargs.c -chan.lo: runtime/chan.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT chan.lo -MD -MP -MF $(DEPDIR)/chan.Tpo -c -o chan.lo `test -f 'runtime/chan.c' || echo '$(srcdir)/'`runtime/chan.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/chan.Tpo $(DEPDIR)/chan.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/chan.c' object='chan.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o chan.lo `test -f 'runtime/chan.c' || echo '$(srcdir)/'`runtime/chan.c - -cpuprof.lo: runtime/cpuprof.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpuprof.lo -MD -MP -MF $(DEPDIR)/cpuprof.Tpo -c -o cpuprof.lo `test -f 'runtime/cpuprof.c' || echo '$(srcdir)/'`runtime/cpuprof.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cpuprof.Tpo $(DEPDIR)/cpuprof.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/cpuprof.c' object='cpuprof.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cpuprof.lo `test -f 'runtime/cpuprof.c' || echo '$(srcdir)/'`runtime/cpuprof.c - env_posix.lo: runtime/env_posix.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT env_posix.lo -MD -MP -MF $(DEPDIR)/env_posix.Tpo -c -o env_posix.lo `test -f 'runtime/env_posix.c' || echo '$(srcdir)/'`runtime/env_posix.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/env_posix.Tpo $(DEPDIR)/env_posix.Plo @@ -3012,12 +3081,12 @@ env_posix.lo: runtime/env_posix.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o env_posix.lo `test -f 'runtime/env_posix.c' || echo '$(srcdir)/'`runtime/env_posix.c -lfstack.lo: runtime/lfstack.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lfstack.lo -MD -MP -MF $(DEPDIR)/lfstack.Tpo -c -o lfstack.lo `test -f 'runtime/lfstack.c' || echo '$(srcdir)/'`runtime/lfstack.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lfstack.Tpo $(DEPDIR)/lfstack.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/lfstack.c' object='lfstack.lo' libtool=yes @AMDEPBACKSLASH@ +heapdump.lo: runtime/heapdump.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT heapdump.lo -MD -MP -MF $(DEPDIR)/heapdump.Tpo -c -o heapdump.lo `test -f 'runtime/heapdump.c' || echo '$(srcdir)/'`runtime/heapdump.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/heapdump.Tpo $(DEPDIR)/heapdump.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/heapdump.c' object='heapdump.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lfstack.lo `test -f 'runtime/lfstack.c' || echo '$(srcdir)/'`runtime/lfstack.c +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o heapdump.lo `test -f 'runtime/heapdump.c' || echo '$(srcdir)/'`runtime/heapdump.c lock_sema.lo: runtime/lock_sema.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lock_sema.lo -MD -MP -MF $(DEPDIR)/lock_sema.Tpo -c -o lock_sema.lo `test -f 'runtime/lock_sema.c' || echo '$(srcdir)/'`runtime/lock_sema.c @@ -3075,13 +3144,6 @@ mem.lo: runtime/mem.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mem.lo `test -f 'runtime/mem.c' || echo '$(srcdir)/'`runtime/mem.c -mfinal.lo: runtime/mfinal.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mfinal.lo -MD -MP -MF $(DEPDIR)/mfinal.Tpo -c -o mfinal.lo `test -f 'runtime/mfinal.c' || echo '$(srcdir)/'`runtime/mfinal.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mfinal.Tpo $(DEPDIR)/mfinal.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/mfinal.c' object='mfinal.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mfinal.lo `test -f 'runtime/mfinal.c' || echo '$(srcdir)/'`runtime/mfinal.c - mfixalloc.lo: runtime/mfixalloc.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mfixalloc.lo -MD -MP -MF $(DEPDIR)/mfixalloc.Tpo -c -o mfixalloc.lo `test -f 'runtime/mfixalloc.c' || echo '$(srcdir)/'`runtime/mfixalloc.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mfixalloc.Tpo $(DEPDIR)/mfixalloc.Plo @@ -4357,10 +4419,23 @@ s-version: Makefile rm -f version.go.tmp echo "package runtime" > version.go.tmp echo 'const defaultGoroot = "$(prefix)"' >> version.go.tmp - echo 'const theVersion = "'`$(CC) --version | sed 1q`'"' >> version.go.tmp + echo 'const theVersion = "'`cat $(srcdir)/VERSION | sed 1q`' '`$(GOC) --version | sed 1q`'"' >> version.go.tmp echo 'const theGoarch = "'$(GOARCH)'"' >> version.go.tmp echo 'const theGoos = "'$(GOOS)'"' >> version.go.tmp - $(SHELL) $(srcdir)/../move-if-change version.go.tmp version.go + echo 'const theGccgoToolDir = "$(libexecsubdir)"' >> version.go.tmp + $(SHELL) $(srcdir)/mvifdiff.sh version.go.tmp version.go + $(STAMP) $@ + +# Generate the list of go std packages that were included in libgo +zstdpkglist.go: s-zstdpkglist; @true +s-zstdpkglist: Makefile + rm -f zstdpkglist.go.tmp + echo 'package main' > 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/\.lo /\": true,\n/g' | sed 's/\.lo/\": true,/' | sed 's/-go//' | grep -v _c | sed 's/^/\t\"/' | sort | uniq >> zstdpkglist.go.tmp + echo '}' >> zstdpkglist.go.tmp + $(SHELL) $(srcdir)/mvifdiff.sh zstdpkglist.go.tmp zstdpkglist.go $(STAMP) $@ libcalls.go: s-libcalls; @true @@ -4368,14 +4443,14 @@ s-libcalls: libcalls-list go/syscall/mksyscall.awk $(go_base_syscall_files) rm -f libcalls.go.tmp files=`echo $^ | sed -e 's/libcalls-list//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \ $(AWK) -f $(srcdir)/go/syscall/mksyscall.awk $${files} > libcalls.go.tmp - $(SHELL) $(srcdir)/../move-if-change libcalls.go.tmp libcalls.go + $(SHELL) $(srcdir)/mvifdiff.sh libcalls.go.tmp libcalls.go $(STAMP) $@ libcalls-list: s-libcalls-list; @true s-libcalls-list: Makefile rm -f libcalls-list.tmp echo $(go_base_syscall_files) > libcalls-list.tmp - $(SHELL) $(srcdir)/../move-if-change libcalls-list.tmp libcalls-list + $(SHELL) $(srcdir)/mvifdiff.sh libcalls-list.tmp libcalls-list $(STAMP) $@ syscall_arch.go: s-syscall_arch; @true @@ -4384,13 +4459,13 @@ s-syscall_arch: Makefile echo "package syscall" > syscall_arch.go.tmp echo 'const ARCH = "'$(GOARCH)'"' >> syscall_arch.go.tmp echo 'const OS = "'$(GOOS)'"' >> syscall_arch.go.tmp - $(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go + $(SHELL) $(srcdir)/mvifdiff.sh syscall_arch.go.tmp syscall_arch.go $(STAMP) $@ sysinfo.go: s-sysinfo; @true s-sysinfo: $(srcdir)/mksysinfo.sh config.h - CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh - $(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go + CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS) -O" $(SHELL) $(srcdir)/mksysinfo.sh + $(SHELL) $(srcdir)/mvifdiff.sh tmp-sysinfo.go sysinfo.go $(STAMP) $@ # The epoll struct has an embedded union and is packed on x86_64, @@ -4418,7 +4493,7 @@ s-epoll: Makefile exit 1; ;; \ esac echo '}' >> epoll.go.tmp - $(SHELL) $(srcdir)/../move-if-change epoll.go.tmp epoll.go + $(SHELL) $(srcdir)/mvifdiff.sh epoll.go.tmp epoll.go $(STAMP) $@ @go_include@ bufio.lo.dep @@ -4570,6 +4645,12 @@ net/check: $(CHECK_DEPS) @$(CHECK) .PHONY: net/check +@go_include@ netgo.o.dep +netgo.o.dep: $(go_netgo_files) + $(BUILDDEPS) +netgo.o: $(go_netgo_files) + $(BUILDNETGO) + @go_include@ os.lo.dep os.lo.dep: $(go_os_files) $(BUILDDEPS) @@ -4595,7 +4676,7 @@ reflect-go.lo: $(go_reflect_files) $(BUILDPACKAGE) reflect/check: $(CHECK_DEPS) @$(CHECK) -reflect/makefunc.lo: $(go_reflect_makefunc_s_file) +reflect/makefunc_ffi_c.lo: $(go_reflect_makefunc_c_file) @$(MKDIR_P) reflect $(LTCOMPILE) -c -o $@ $< .PHONY: reflect/check @@ -4999,6 +5080,15 @@ debug/pe/check: $(CHECK_DEPS) @$(CHECK) .PHONY: debug/pe/check +@go_include@ debug/plan9obj.lo.dep +debug/plan9obj.lo.dep: $(go_debug_plan9obj_files) + $(BUILDDEPS) +debug/plan9obj.lo: $(go_debug_plan9obj_files) + $(BUILDPACKAGE) +debug/plan9obj/check: $(CHECK_DEPS) + @$(CHECK) +.PHONY: debug/plan9obj/check + @go_include@ encoding/asn1.lo.dep encoding/asn1.lo.dep: $(go_encoding_asn1_files) $(BUILDDEPS) @@ -5452,6 +5542,15 @@ net/http/httputil/check: $(check_deps) @$(CHECK) .PHONY: net/http/httputil/check +@go_include@ net/http/internal.lo.dep +net/http/internal.lo.dep: $(go_net_http_internal_files) + $(BUILDDEPS) +net/http/internal.lo: $(go_net_http_internal_files) + $(BUILDPACKAGE) +net/http/internal/check: $(CHECK_DEPS) + @$(CHECK) +.PHONY: net/http/internal/check + @go_include@ net/http/pprof.lo.dep net/http/pprof.lo.dep: $(go_net_http_pprof_files) $(BUILDDEPS) @@ -5652,6 +5751,15 @@ syscall/check: $(CHECK_DEPS) @$(CHECK) .PHONY: syscall/check +@go_include@ internal/syscall.lo.dep +internal/syscall.lo.dep: $(go_internal_syscall_files) + $(BUILDDEPS) +internal/syscall.lo: $(go_internal_syscall_files) + $(BUILDPACKAGE) +internal/syscall/check: $(CHECK_DEPS) + @$(CHECK) +.PHONY: internal/syscall/check + bufio.gox: bufio.lo $(BUILDGOX) bytes.gox: bytes.lo @@ -5788,6 +5896,8 @@ debug/macho.gox: debug/macho.lo $(BUILDGOX) debug/pe.gox: debug/pe.lo $(BUILDGOX) +debug/plan9obj.gox: debug/plan9obj.lo + $(BUILDGOX) encoding/ascii85.gox: encoding/ascii85.lo $(BUILDGOX) @@ -5905,6 +6015,9 @@ net/http/httputil.gox: net/http/httputil.lo net/http/pprof.gox: net/http/pprof.lo $(BUILDGOX) +net/http/internal.gox: net/http/internal.lo + $(BUILDGOX) + net/rpc/jsonrpc.gox: net/rpc/jsonrpc.lo $(BUILDGOX) @@ -5934,6 +6047,9 @@ runtime/pprof.gox: runtime/pprof.lo sync/atomic.gox: sync/atomic.lo $(BUILDGOX) +internal/syscall.gox: internal/syscall.lo + $(BUILDGOX) + text/scanner.gox: text/scanner.lo $(BUILDGOX) text/tabwriter.gox: text/tabwriter.lo @@ -6052,6 +6168,9 @@ check-am: check-multi: $(MULTIDO) $(AM_MAKEFLAGS) DO=check-am multi-do # $(MAKE) +bench: + -@$(MAKE) -k $(TEST_PACKAGES) GOBENCH=. + mostlyclean-local: find . -name '*.lo' -print | xargs $(LIBTOOL) --mode=clean rm -f find . -name '*.$(OBJEXT)' -print | xargs rm -f diff --git a/libgo/README b/libgo/README index 732c3526c4..d5af7e2fd1 100644 --- a/libgo/README +++ b/libgo/README @@ -3,25 +3,24 @@ See ../README. This is the runtime support library for the Go programming language. This library is intended for use with the Go frontend. -The library has only been tested on GNU/Linux using glibc. It should -not be difficult to port to other operating systems. +This library should not be stripped when it is installed. Go code +relies on being able to look up file/line information, which comes +from the debugging info using the libbacktrace library. -The library has only been tested on x86/x86_64 systems. It should not -be difficult to port to other architectures. +The library has only been tested on GNU/Linux using glibc, and on +Solaris. It should not be difficult to port to other operating +systems. Directories: go - A copy of the Go library from http://golang.org/, with a few - changes for gccgo. Notably, the reflection interface is different. + A copy of the Go library from http://golang.org/, with several + changes for gccgo. runtime Runtime functions, written in C, which are called directly by the compiler or by the library. -syscalls - System call support. - Contributing ============ diff --git a/libgo/VERSION b/libgo/VERSION new file mode 100644 index 0000000000..bcab27e8d3 --- /dev/null +++ b/libgo/VERSION @@ -0,0 +1 @@ +go1.4.2 \ No newline at end of file diff --git a/libgo/config.h.in b/libgo/config.h.in index 2ee0cfc243..629c603e38 100644 --- a/libgo/config.h.in +++ b/libgo/config.h.in @@ -319,6 +319,9 @@ /* Define to 1 if you have the `unlinkat' function. */ #undef HAVE_UNLINKAT +/* Define to 1 if you have the `unsetenv' function. */ +#undef HAVE_UNSETENV + /* Define to 1 if you have the `unshare' function. */ #undef HAVE_UNSHARE @@ -344,9 +347,6 @@ */ #undef LT_OBJDIR -/* Define if makecontext expects top of stack in uc_stack. */ -#undef MAKECONTEXT_STACK_TOP - /* Name of package */ #undef PACKAGE diff --git a/libgo/config/libtool.m4 b/libgo/config/libtool.m4 index f1ffebf99c..f700594745 100644 --- a/libgo/config/libtool.m4 +++ b/libgo/config/libtool.m4 @@ -1011,7 +1011,7 @@ _LT_EOF case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[[012]]*) + 10.[[012]][[,.]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; @@ -1237,7 +1237,14 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) - LD="${LD-ld} -m elf_i386" + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" @@ -1293,27 +1300,14 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) CFLAGS="$SAVE_CFLAGS" fi ;; -*-*solaris*) +sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in - yes*) - case $host in - i?86-*-solaris* | x86_64-*-solaris2.1[[0-9]]*) - LD="${LD-ld} -m elf_x86_64" - ;; - sparc*-*-solaris*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - # GNU ld 2.21 introduced _sol2 emulations. Use them if available. - if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD="${LD-ld}_sol2" - fi - ;; + yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" @@ -2297,7 +2291,7 @@ freebsd* | dragonfly*) objformat=`/usr/bin/objformat` else case $host_os in - freebsd[[123]]*) objformat=aout ;; + freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi @@ -2315,7 +2309,7 @@ freebsd* | dragonfly*) esac shlibpath_var=LD_LIBRARY_PATH case $host_os in - freebsd2*) + freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) @@ -3597,6 +3591,7 @@ m4_if([$1], [CXX], [ # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) @@ -3908,6 +3903,7 @@ m4_if([$1], [CXX], [ # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) @@ -4828,7 +4824,7 @@ _LT_EOF ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) + freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes @@ -5775,7 +5771,7 @@ if test "$_lt_caught_CXX_error" != yes; then esac ;; - freebsd[[12]]*) + freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no diff --git a/libgo/config/ltmain.sh b/libgo/config/ltmain.sh index 17f19d888b..ce66b44906 100644 --- a/libgo/config/ltmain.sh +++ b/libgo/config/ltmain.sh @@ -5928,7 +5928,7 @@ func_mode_link () test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then - add_dir="-L$dir" + add_dir="-L$absdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in diff --git a/libgo/configure b/libgo/configure index 1223204a25..377179d2c3 100755 --- a/libgo/configure +++ b/libgo/configure @@ -616,6 +616,8 @@ PTHREAD_LIBS PTHREAD_CFLAGS NET_LIBS MATH_LIBS +GOC_IS_LLGO_FALSE +GOC_IS_LLGO_TRUE USING_SPLIT_STACK_FALSE USING_SPLIT_STACK_TRUE SPLIT_STACK @@ -631,6 +633,12 @@ LIBGO_IS_SPARC64_FALSE LIBGO_IS_SPARC64_TRUE LIBGO_IS_SPARC_FALSE LIBGO_IS_SPARC_TRUE +LIBGO_IS_S390X_FALSE +LIBGO_IS_S390X_TRUE +LIBGO_IS_S390_FALSE +LIBGO_IS_S390_TRUE +LIBGO_IS_PPC64LE_FALSE +LIBGO_IS_PPC64LE_TRUE LIBGO_IS_PPC64_FALSE LIBGO_IS_PPC64_TRUE LIBGO_IS_PPC_FALSE @@ -676,6 +684,7 @@ LIBGO_IS_FREEBSD_TRUE LIBGO_IS_DARWIN_FALSE LIBGO_IS_DARWIN_TRUE go_include +LIBATOMIC LIBFFIINCS LIBFFI nover_glibgo_toolexeclibdir @@ -817,6 +826,7 @@ enable_libtool_lock enable_werror enable_version_specific_runtime_libs with_libffi +with_libatomic with_system_libunwind enable_sjlj_exceptions ' @@ -1469,6 +1479,7 @@ Optional Packages: --with-pic try to use only PIC/non-PIC objects [default=use both] --without-libffi don't use libffi + --without-libatomic don't use libatomic --with-system-libunwind use installed libunwind Some influential environment variables: @@ -2500,7 +2511,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" -libtool_VERSION=5:0:0 +libtool_VERSION=7:0:0 # Default to --enable-multilib @@ -6521,7 +6532,14 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) - LD="${LD-ld} -m elf_i386" + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" @@ -6611,7 +6629,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } CFLAGS="$SAVE_CFLAGS" fi ;; -*-*solaris*) +sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 @@ -6622,20 +6640,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in - yes*) - case $host in - i?86-*-solaris* | x86_64-*-solaris2.1[0-9]*) - LD="${LD-ld} -m elf_x86_64" - ;; - sparc*-*-solaris*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - # GNU ld 2.21 introduced _sol2 emulations. Use them if available. - if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then - LD="${LD-ld}_sol2" - fi - ;; + yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" @@ -7243,7 +7248,7 @@ $as_echo "$lt_cv_ld_force_load" >&6; } case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[012]*) + 10.[012][,.]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; @@ -8169,6 +8174,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi + lt_prog_compiler_pic='-fPIC' ;; amigaos*) @@ -9350,7 +9356,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) + freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes @@ -10263,7 +10269,7 @@ freebsd* | dragonfly*) objformat=`/usr/bin/objformat` else case $host_os in - freebsd[123]*) objformat=aout ;; + freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi @@ -10281,7 +10287,7 @@ freebsd* | dragonfly*) esac shlibpath_var=LD_LIBRARY_PATH case $host_os in - freebsd2*) + freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) @@ -11115,7 +11121,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11118 "configure" +#line 11124 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11221,7 +11227,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11224 "configure" +#line 11230 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11600,6 +11606,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # AIX 5 now supports IA64 processor lt_prog_compiler_static_GO='-Bstatic' fi + lt_prog_compiler_pic_GO='-fPIC' ;; amigaos*) @@ -12766,7 +12773,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) + freebsd2.*) archive_cmds_GO='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GO=yes hardcode_minus_L_GO=yes @@ -13444,7 +13451,7 @@ else nover_glibgo_toolexecdir='${libdir}/gcc/${host_alias}' nover_glibgo_toolexeclibdir='${libdir}' fi -multi_os_directory=`$CC -print-multi-os-directory` +multi_os_directory=`$GOC -print-multi-os-directory` case $multi_os_directory in .) ;; # Avoid trailing /. *) nover_glibgo_toolexeclibdir=${nover_glibgo_toolexeclibdir}/${multi_os_directory} ;; @@ -13483,6 +13490,24 @@ fi +# See if the user wants to configure without libatomic. This is useful if we are +# on an architecture for which libgo does not need an atomic support library and +# libatomic does not support our C compiler. + +# Check whether --with-libatomic was given. +if test "${with_libatomic+set}" = set; then : + withval=$with_libatomic; : +else + with_libatomic=${with_libatomic_default-yes} +fi + + +LIBATOMIC= +if test "$with_libatomic" != no; then + LIBATOMIC=../libatomic/libatomic_convenience.la +fi + + # Used to tell GNU make to include a file without telling automake to # include it. go_include="-include" @@ -13599,6 +13624,9 @@ is_m68k=no mips_abi=unknown is_ppc=no is_ppc64=no +is_ppc64le=no +is_s390=no +is_s390x=no is_sparc=no is_sparc64=no is_x86_64=no @@ -13708,14 +13736,48 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext _ACEOF if ac_fn_c_try_compile "$LINENO"; then : is_ppc=yes +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if defined(_BIG_ENDIAN) || defined(__BIG_ENDIAN__) +#error 64be +#endif +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + is_ppc64le=yes else is_ppc64=yes fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test "$is_ppc" = "yes"; then GOARCH=ppc - else + elif test "$is_ppc64" = "yes"; then GOARCH=ppc64 + else + GOARCH=ppc64le + fi + ;; + s390*-*-*) + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if defined(__s390x__) +#error 64-bit +#endif +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + is_s390=yes +else + is_s390x=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test "$is_s390" = "yes"; then + GOARCH=s390 + else + GOARCH=s390x fi ;; sparc*-*-*) @@ -13835,6 +13897,30 @@ else LIBGO_IS_PPC64_FALSE= fi + if test $is_ppc64le = yes; then + LIBGO_IS_PPC64LE_TRUE= + LIBGO_IS_PPC64LE_FALSE='#' +else + LIBGO_IS_PPC64LE_TRUE='#' + LIBGO_IS_PPC64LE_FALSE= +fi + + if test $is_s390 = yes; then + LIBGO_IS_S390_TRUE= + LIBGO_IS_S390_FALSE='#' +else + LIBGO_IS_S390_TRUE='#' + LIBGO_IS_S390_FALSE= +fi + + if test $is_s390x = yes; then + LIBGO_IS_S390X_TRUE= + LIBGO_IS_S390X_FALSE='#' +else + LIBGO_IS_S390X_TRUE='#' + LIBGO_IS_S390X_FALSE= +fi + if test $is_sparc = yes; then LIBGO_IS_SPARC_TRUE= LIBGO_IS_SPARC_FALSE='#' @@ -13865,17 +13951,17 @@ GO_LIBCALL_OS_FILE= GO_LIBCALL_OS_ARCH_FILE= GO_SYSCALL_OS_FILE= GO_SYSCALL_OS_ARCH_FILE= -if test -f ${srcdir}/go/syscall/libcall_${GOOS}.go; then - GO_LIBCALL_OS_FILE=go/syscall/libcall_${GOOS}.go +if test -f "${srcdir}/go/syscall/libcall_${GOOS}.go"; then + GO_LIBCALL_OS_FILE="go/syscall/libcall_${GOOS}.go" fi -if test -f ${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go; then - GO_LIBCALL_OS_ARCH_FILE=go/syscall/libcall_${GOOS}_${GOARCH}.go +if test -f "${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go"; then + GO_LIBCALL_OS_ARCH_FILE="go/syscall/libcall_${GOOS}_${GOARCH}.go" fi -if test -f ${srcdir}/go/syscall/syscall_${GOOS}.go; then - GO_SYSCALL_OS_FILE=go/syscall/syscall_${GOOS}.go +if test -f "${srcdir}/go/syscall/syscall_${GOOS}.go"; then + GO_SYSCALL_OS_FILE="go/syscall/syscall_${GOOS}.go" fi -if test -f ${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go; then - GO_SYSCALL_OS_ARCH_FILE=go/syscall/syscall_${GOOS}_${GOARCH}.go +if test -f "${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go"; then + GO_SYSCALL_OS_ARCH_FILE="go/syscall/syscall_${GOOS}_${GOARCH}.go" fi @@ -13889,11 +13975,6 @@ case "$target" in # msghdr in . OSCFLAGS="$OSCFLAGS -D_XOPEN_SOURCE=500" ;; - *-*-solaris2.[89]) - # Solaris 8/9 need this so struct msghdr gets the msg_control - # etc. fields in (_XPG4_2). - OSCFLAGS="$OSCFLAGS -D_XOPEN_SOURCE=500 -D_XOPEN_SOURCE_EXTENDED -D__EXTENSIONS__" - ;; *-*-solaris2.1[01]) # Solaris 10+ needs this so struct msghdr gets the msg_control # etc. fields in (_XPG4_2). _XOPEN_SOURCE=600 as @@ -13960,6 +14041,27 @@ $as_echo "#define LINKER_SUPPORTS_SPLIT_STACK 1" >>confdefs.h fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler is llgo" >&5 +$as_echo_n "checking whether compiler is llgo... " >&6; } +if test "${libgo_cv_c_goc_is_llgo+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + libgo_cv_c_goc_is_llgo=no +if $GOC -dumpversion 2>/dev/null | grep llgo >/dev/null 2>&1; then + libgo_cv_c_goc_is_llgo=yes +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_goc_is_llgo" >&5 +$as_echo "$libgo_cv_c_goc_is_llgo" >&6; } + if test "$libgo_cv_c_goc_is_llgo" = yes; then + GOC_IS_LLGO_TRUE= + GOC_IS_LLGO_FALSE='#' +else + GOC_IS_LLGO_TRUE='#' + GOC_IS_LLGO_FALSE= +fi + + MATH_LIBS= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sqrt in -lm" >&5 $as_echo_n "checking for sqrt in -lm... " >&6; } @@ -14703,7 +14805,7 @@ else fi -for ac_func in strerror_r strsignal wait4 mincore setenv dl_iterate_phdr +for ac_func in strerror_r strsignal wait4 mincore setenv unsetenv dl_iterate_phdr do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -15053,20 +15155,6 @@ $as_echo "#define HAVE_STRUCT_EXCEPTION 1" >>confdefs.h fi -case "$target" in - sparc*-*-solaris2.[89]*) - libgo_cv_lib_makecontext_stack_top=yes - ;; - *) - libgo_cv_lib_makecontext_stack_top=no - ;; -esac -if test "$libgo_cv_lib_makecontext_stack_top" = "yes"; then - -$as_echo "#define MAKECONTEXT_STACK_TOP 1" >>confdefs.h - -fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether setcontext clobbers TLS variables" >&5 $as_echo_n "checking whether setcontext clobbers TLS variables... " >&6; } if test "${libgo_cv_lib_setcontext_clobbers_tls+set}" = set; then : @@ -15239,6 +15327,28 @@ $as_echo "#define EH_FRAME_FLAGS \"aw\"" >>confdefs.h fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports -Qunused-arguments" >&5 +$as_echo_n "checking if compiler supports -Qunused-arguments... " >&6; } +if test "${libgo_cv_c_unused_arguments+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + CFLAGS_hold=$CFLAGS +CFLAGS="$CFLAGS -Qunused-arguments" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int i; +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libgo_cv_c_unused_arguments=yes +else + libgo_cv_c_unused_arguments=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +CFLAGS=$CFLAGS_hold +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_unused_arguments" >&5 +$as_echo "$libgo_cv_c_unused_arguments" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if assembler supports GNU comdat group syntax" >&5 $as_echo_n "checking if assembler supports GNU comdat group syntax... " >&6; } if test "${libgo_cv_as_comdat_gnu+set}" = set; then : @@ -15246,11 +15356,16 @@ if test "${libgo_cv_as_comdat_gnu+set}" = set; then : else echo '.section .text,"axG",@progbits,.foo,comdat' > conftest.s +CFLAGS_hold=$CFLAGS +if test "$libgo_cv_c_unused_arguments" = yes; then + CFLAGS="$CFLAGS -Qunused-arguments" +fi if $CC $CFLAGS -c conftest.s > /dev/null 2>&1; then libgo_cv_as_comdat_gnu=yes else libgo_cv_as_comdat_gnu=no fi +CFLAGS=$CFLAGS_hold fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_as_comdat_gnu" >&5 @@ -15269,9 +15384,14 @@ else libgo_cv_as_x86_pcrel=yes echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s +CFLAGS_hold=$CFLAGS +if test "$libgo_cv_c_unused_arguments" = yes; then + CFLAGS="$CFLAGS -Qunused-arguments" +fi if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then libgo_cv_as_x86_pcrel=no fi +CFLAGS=$CFLAGS_hold fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_as_x86_pcrel" >&5 @@ -15290,9 +15410,14 @@ else libgo_cv_as_x86_64_unwind_section_type=yes echo '.section .eh_frame,"a",@unwind' > conftest.s +CFLAGS_hold=$CFLAGS +if test "$libgo_cv_c_unused_arguments" = yes; then + CFLAGS="$CFLAGS -Qunused-arguments" +fi if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then libgo_cv_as_x86_64_unwind_section_type=no fi +CFLAGS=$CFLAGS_hold fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_as_x86_64_unwind_section_type" >&5 @@ -15591,6 +15716,18 @@ if test -z "${LIBGO_IS_PPC64_TRUE}" && test -z "${LIBGO_IS_PPC64_FALSE}"; then as_fn_error "conditional \"LIBGO_IS_PPC64\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${LIBGO_IS_PPC64LE_TRUE}" && test -z "${LIBGO_IS_PPC64LE_FALSE}"; then + as_fn_error "conditional \"LIBGO_IS_PPC64LE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${LIBGO_IS_S390_TRUE}" && test -z "${LIBGO_IS_S390_FALSE}"; then + as_fn_error "conditional \"LIBGO_IS_S390\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${LIBGO_IS_S390X_TRUE}" && test -z "${LIBGO_IS_S390X_FALSE}"; then + as_fn_error "conditional \"LIBGO_IS_S390X\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${LIBGO_IS_SPARC_TRUE}" && test -z "${LIBGO_IS_SPARC_FALSE}"; then as_fn_error "conditional \"LIBGO_IS_SPARC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -15607,6 +15744,10 @@ if test -z "${USING_SPLIT_STACK_TRUE}" && test -z "${USING_SPLIT_STACK_FALSE}"; as_fn_error "conditional \"USING_SPLIT_STACK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${GOC_IS_LLGO_TRUE}" && test -z "${GOC_IS_LLGO_FALSE}"; then + as_fn_error "conditional \"GOC_IS_LLGO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${HAVE_SYS_MMAN_H_TRUE}" && test -z "${HAVE_SYS_MMAN_H_FALSE}"; then as_fn_error "conditional \"HAVE_SYS_MMAN_H\" was never defined. diff --git a/libgo/configure.ac b/libgo/configure.ac index 754e1906c6..0baff412de 100644 --- a/libgo/configure.ac +++ b/libgo/configure.ac @@ -11,7 +11,7 @@ AC_INIT(package-unused, version-unused,, libgo) AC_CONFIG_SRCDIR(Makefile.am) AC_CONFIG_HEADER(config.h) -libtool_VERSION=5:0:0 +libtool_VERSION=7:0:0 AC_SUBST(libtool_VERSION) AM_ENABLE_MULTILIB(, ..) @@ -88,7 +88,7 @@ else nover_glibgo_toolexecdir='${libdir}/gcc/${host_alias}' nover_glibgo_toolexeclibdir='${libdir}' fi -multi_os_directory=`$CC -print-multi-os-directory` +multi_os_directory=`$GOC -print-multi-os-directory` case $multi_os_directory in .) ;; # Avoid trailing /. *) nover_glibgo_toolexeclibdir=${nover_glibgo_toolexeclibdir}/${multi_os_directory} ;; @@ -122,6 +122,21 @@ fi AC_SUBST(LIBFFI) AC_SUBST(LIBFFIINCS) +# See if the user wants to configure without libatomic. This is useful if we are +# on an architecture for which libgo does not need an atomic support library and +# libatomic does not support our C compiler. +AC_ARG_WITH(libatomic, + AS_HELP_STRING([--without-libatomic], + [don't use libatomic]), + [:], + [with_libatomic=${with_libatomic_default-yes}]) + +LIBATOMIC= +if test "$with_libatomic" != no; then + LIBATOMIC=../libatomic/libatomic_convenience.la +fi +AC_SUBST(LIBATOMIC) + # Used to tell GNU make to include a file without telling automake to # include it. go_include="-include" @@ -179,6 +194,9 @@ is_m68k=no mips_abi=unknown is_ppc=no is_ppc64=no +is_ppc64le=no +is_s390=no +is_s390x=no is_sparc=no is_sparc64=no is_x86_64=no @@ -249,11 +267,30 @@ changequote([,])dnl #ifdef _ARCH_PPC64 #error 64-bit #endif], -[is_ppc=yes], [is_ppc64=yes]) +[is_ppc=yes], + [AC_COMPILE_IFELSE([ +#if defined(_BIG_ENDIAN) || defined(__BIG_ENDIAN__) +#error 64be +#endif], +[is_ppc64le=yes],[is_ppc64=yes])]) if test "$is_ppc" = "yes"; then GOARCH=ppc - else + elif test "$is_ppc64" = "yes"; then GOARCH=ppc64 + else + GOARCH=ppc64le + fi + ;; + s390*-*-*) + AC_COMPILE_IFELSE([ +#if defined(__s390x__) +#error 64-bit +#endif], +[is_s390=yes], [is_s390x=yes]) + if test "$is_s390" = "yes"; then + GOARCH=s390 + else + GOARCH=s390x fi ;; sparc*-*-*) @@ -281,6 +318,9 @@ AM_CONDITIONAL(LIBGO_IS_MIPSN64, test $mips_abi = n64) AM_CONDITIONAL(LIBGO_IS_MIPSO64, test $mips_abi = o64) AM_CONDITIONAL(LIBGO_IS_PPC, test $is_ppc = yes) AM_CONDITIONAL(LIBGO_IS_PPC64, test $is_ppc64 = yes) +AM_CONDITIONAL(LIBGO_IS_PPC64LE, test $is_ppc64le = yes) +AM_CONDITIONAL(LIBGO_IS_S390, test $is_s390 = yes) +AM_CONDITIONAL(LIBGO_IS_S390X, test $is_s390x = yes) AM_CONDITIONAL(LIBGO_IS_SPARC, test $is_sparc = yes) AM_CONDITIONAL(LIBGO_IS_SPARC64, test $is_sparc64 = yes) AM_CONDITIONAL(LIBGO_IS_X86_64, test $is_x86_64 = yes) @@ -291,17 +331,17 @@ GO_LIBCALL_OS_FILE= GO_LIBCALL_OS_ARCH_FILE= GO_SYSCALL_OS_FILE= GO_SYSCALL_OS_ARCH_FILE= -if test -f ${srcdir}/go/syscall/libcall_${GOOS}.go; then - GO_LIBCALL_OS_FILE=go/syscall/libcall_${GOOS}.go +if test -f "${srcdir}/go/syscall/libcall_${GOOS}.go"; then + GO_LIBCALL_OS_FILE="go/syscall/libcall_${GOOS}.go" fi -if test -f ${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go; then - GO_LIBCALL_OS_ARCH_FILE=go/syscall/libcall_${GOOS}_${GOARCH}.go +if test -f "${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go"; then + GO_LIBCALL_OS_ARCH_FILE="go/syscall/libcall_${GOOS}_${GOARCH}.go" fi -if test -f ${srcdir}/go/syscall/syscall_${GOOS}.go; then - GO_SYSCALL_OS_FILE=go/syscall/syscall_${GOOS}.go +if test -f "${srcdir}/go/syscall/syscall_${GOOS}.go"; then + GO_SYSCALL_OS_FILE="go/syscall/syscall_${GOOS}.go" fi -if test -f ${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go; then - GO_SYSCALL_OS_ARCH_FILE=go/syscall/syscall_${GOOS}_${GOARCH}.go +if test -f "${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go"; then + GO_SYSCALL_OS_ARCH_FILE="go/syscall/syscall_${GOOS}_${GOARCH}.go" fi AC_SUBST(GO_LIBCALL_OS_FILE) AC_SUBST(GO_LIBCALL_OS_ARCH_FILE) @@ -316,11 +356,6 @@ case "$target" in # msghdr in . OSCFLAGS="$OSCFLAGS -D_XOPEN_SOURCE=500" ;; - *-*-solaris2.[[89]]) - # Solaris 8/9 need this so struct msghdr gets the msg_control - # etc. fields in (_XPG4_2). - OSCFLAGS="$OSCFLAGS -D_XOPEN_SOURCE=500 -D_XOPEN_SOURCE_EXTENDED -D__EXTENSIONS__" - ;; *-*-solaris2.1[[01]]) # Solaris 10+ needs this so struct msghdr gets the msg_control # etc. fields in (_XPG4_2). _XOPEN_SOURCE=600 as @@ -366,6 +401,14 @@ if test "$libgo_cv_c_linker_supports_split_stack" = yes; then [Define if the linker support split stack adjustments]) fi +AC_CACHE_CHECK([whether compiler is llgo], +[libgo_cv_c_goc_is_llgo], +[libgo_cv_c_goc_is_llgo=no +if $GOC -dumpversion 2>/dev/null | grep llgo >/dev/null 2>&1; then + libgo_cv_c_goc_is_llgo=yes +fi]) +AM_CONDITIONAL(GOC_IS_LLGO, test "$libgo_cv_c_goc_is_llgo" = yes) + dnl Test for the -lm library. MATH_LIBS= AC_CHECK_LIB([m], [sqrt], MATH_LIBS=-lm) @@ -508,7 +551,7 @@ fi AM_CONDITIONAL(HAVE_SYS_MMAN_H, test "$ac_cv_header_sys_mman_h" = yes) -AC_CHECK_FUNCS(strerror_r strsignal wait4 mincore setenv dl_iterate_phdr) +AC_CHECK_FUNCS(strerror_r strsignal wait4 mincore setenv unsetenv dl_iterate_phdr) AM_CONDITIONAL(HAVE_STRERROR_R, test "$ac_cv_func_strerror_r" = yes) AM_CONDITIONAL(HAVE_WAIT4, test "$ac_cv_func_wait4" = yes) @@ -662,21 +705,6 @@ if test "$libgo_has_struct_exception" = "yes"; then [Define to 1 if defines struct exception]) fi -dnl Check if makecontext expects the uc_stack member of ucontext to point -dnl to the top of the stack. -case "$target" in - sparc*-*-solaris2.[[89]]*) - libgo_cv_lib_makecontext_stack_top=yes - ;; - *) - libgo_cv_lib_makecontext_stack_top=no - ;; -esac -if test "$libgo_cv_lib_makecontext_stack_top" = "yes"; then - AC_DEFINE(MAKECONTEXT_STACK_TOP, 1, - [Define if makecontext expects top of stack in uc_stack.]) -fi - dnl See whether setcontext changes the value of TLS variables. AC_CACHE_CHECK([whether setcontext clobbers TLS variables], [libgo_cv_lib_setcontext_clobbers_tls], @@ -790,14 +818,28 @@ else [Define to the flags needed for the .section .eh_frame directive.]) fi +AC_CACHE_CHECK([if compiler supports -Qunused-arguments], +[libgo_cv_c_unused_arguments], +[CFLAGS_hold=$CFLAGS +CFLAGS="$CFLAGS -Qunused-arguments" +AC_COMPILE_IFELSE([[int i;]], +[libgo_cv_c_unused_arguments=yes], +[libgo_cv_c_unused_arguments=no]) +CFLAGS=$CFLAGS_hold]) + AC_CACHE_CHECK([if assembler supports GNU comdat group syntax], libgo_cv_as_comdat_gnu, [ echo '.section .text,"axG",@progbits,.foo,comdat' > conftest.s +CFLAGS_hold=$CFLAGS +if test "$libgo_cv_c_unused_arguments" = yes; then + CFLAGS="$CFLAGS -Qunused-arguments" +fi if $CC $CFLAGS -c conftest.s > /dev/null 2>&1; then libgo_cv_as_comdat_gnu=yes else libgo_cv_as_comdat_gnu=no fi +CFLAGS=$CFLAGS_hold ]) if test "x$libgo_cv_as_comdat_gnu" = xyes; then AC_DEFINE(HAVE_AS_COMDAT_GAS, 1, @@ -808,9 +850,14 @@ AC_CACHE_CHECK([assembler supports pc related relocs], libgo_cv_as_x86_pcrel, [ libgo_cv_as_x86_pcrel=yes echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s +CFLAGS_hold=$CFLAGS +if test "$libgo_cv_c_unused_arguments" = yes; then + CFLAGS="$CFLAGS -Qunused-arguments" +fi if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then libgo_cv_as_x86_pcrel=no fi +CFLAGS=$CFLAGS_hold ]) if test "x$libgo_cv_as_x86_pcrel" = xyes; then AC_DEFINE(HAVE_AS_X86_PCREL, 1, @@ -821,9 +868,14 @@ AC_CACHE_CHECK([assembler supports unwind section type], libgo_cv_as_x86_64_unwind_section_type, [ libgo_cv_as_x86_64_unwind_section_type=yes echo '.section .eh_frame,"a",@unwind' > conftest.s +CFLAGS_hold=$CFLAGS +if test "$libgo_cv_c_unused_arguments" = yes; then + CFLAGS="$CFLAGS -Qunused-arguments" +fi if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then libgo_cv_as_x86_64_unwind_section_type=no fi +CFLAGS=$CFLAGS_hold ]) if test "x$libgo_cv_as_x86_64_unwind_section_type" = xyes; then AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1, diff --git a/libgo/go/archive/tar/common.go b/libgo/go/archive/tar/common.go index 1b961e3ec6..e363aa793e 100644 --- a/libgo/go/archive/tar/common.go +++ b/libgo/go/archive/tar/common.go @@ -38,6 +38,7 @@ const ( TypeXGlobalHeader = 'g' // global extended header TypeGNULongName = 'L' // Next file has a long name TypeGNULongLink = 'K' // Next file symlinks to a file w/ a long name + TypeGNUSparse = 'S' // sparse file ) // A Header represents a single header in a tar archive. @@ -57,6 +58,7 @@ type Header struct { Devminor int64 // minor number of character or block device AccessTime time.Time // access time ChangeTime time.Time // status change time + Xattrs map[string]string } // File name constants from the tar spec. @@ -189,6 +191,7 @@ const ( paxSize = "size" paxUid = "uid" paxUname = "uname" + paxXattr = "SCHILY.xattr." paxNone = "" ) diff --git a/libgo/go/archive/tar/reader.go b/libgo/go/archive/tar/reader.go index b2d62f3c51..a27559d0f0 100644 --- a/libgo/go/archive/tar/reader.go +++ b/libgo/go/archive/tar/reader.go @@ -29,12 +29,58 @@ const maxNanoSecondIntSize = 9 // The Next method advances to the next file in the archive (including the first), // and then it can be treated as an io.Reader to access the file's data. type Reader struct { - r io.Reader - err error - nb int64 // number of unread bytes for current file entry - pad int64 // amount of padding (ignored) after current file entry + r io.Reader + err error + pad int64 // amount of padding (ignored) after current file entry + curr numBytesReader // reader for current file entry + hdrBuff [blockSize]byte // buffer to use in readHeader } +// A numBytesReader is an io.Reader with a numBytes method, returning the number +// of bytes remaining in the underlying encoded data. +type numBytesReader interface { + io.Reader + numBytes() int64 +} + +// A regFileReader is a numBytesReader for reading file data from a tar archive. +type regFileReader struct { + r io.Reader // underlying reader + nb int64 // number of unread bytes for current file entry +} + +// A sparseFileReader is a numBytesReader for reading sparse file data from a tar archive. +type sparseFileReader struct { + rfr *regFileReader // reads the sparse-encoded file data + sp []sparseEntry // the sparse map for the file + pos int64 // keeps track of file position + tot int64 // total size of the file +} + +// Keywords for GNU sparse files in a PAX extended header +const ( + paxGNUSparseNumBlocks = "GNU.sparse.numblocks" + paxGNUSparseOffset = "GNU.sparse.offset" + paxGNUSparseNumBytes = "GNU.sparse.numbytes" + paxGNUSparseMap = "GNU.sparse.map" + paxGNUSparseName = "GNU.sparse.name" + paxGNUSparseMajor = "GNU.sparse.major" + paxGNUSparseMinor = "GNU.sparse.minor" + paxGNUSparseSize = "GNU.sparse.size" + paxGNUSparseRealSize = "GNU.sparse.realsize" +) + +// Keywords for old GNU sparse headers +const ( + oldGNUSparseMainHeaderOffset = 386 + oldGNUSparseMainHeaderIsExtendedOffset = 482 + oldGNUSparseMainHeaderNumEntries = 4 + oldGNUSparseExtendedHeaderIsExtendedOffset = 504 + oldGNUSparseExtendedHeaderNumEntries = 21 + oldGNUSparseOffsetSize = 12 + oldGNUSparseNumBytesSize = 12 +) + // NewReader creates a new Reader reading from r. func NewReader(r io.Reader) *Reader { return &Reader{r: r} } @@ -64,6 +110,18 @@ func (tr *Reader) Next() (*Header, error) { tr.skipUnread() hdr = tr.readHeader() mergePAX(hdr, headers) + + // Check for a PAX format sparse file + sp, err := tr.checkForGNUSparsePAXHeaders(hdr, headers) + if err != nil { + tr.err = err + return nil, err + } + if sp != nil { + // Current file is a PAX format GNU sparse file. + // Set the current file reader to a sparse file reader. + tr.curr = &sparseFileReader{rfr: tr.curr.(*regFileReader), sp: sp, tot: hdr.Size} + } return hdr, nil case TypeGNULongName: // We have a GNU long name header. Its contents are the real file name. @@ -87,6 +145,67 @@ func (tr *Reader) Next() (*Header, error) { return hdr, tr.err } +// checkForGNUSparsePAXHeaders checks the PAX headers for GNU sparse headers. If they are found, then +// this function reads the sparse map and returns it. Unknown sparse formats are ignored, causing the file to +// be treated as a regular file. +func (tr *Reader) checkForGNUSparsePAXHeaders(hdr *Header, headers map[string]string) ([]sparseEntry, error) { + var sparseFormat string + + // Check for sparse format indicators + major, majorOk := headers[paxGNUSparseMajor] + minor, minorOk := headers[paxGNUSparseMinor] + sparseName, sparseNameOk := headers[paxGNUSparseName] + _, sparseMapOk := headers[paxGNUSparseMap] + sparseSize, sparseSizeOk := headers[paxGNUSparseSize] + sparseRealSize, sparseRealSizeOk := headers[paxGNUSparseRealSize] + + // Identify which, if any, sparse format applies from which PAX headers are set + if majorOk && minorOk { + sparseFormat = major + "." + minor + } else if sparseNameOk && sparseMapOk { + sparseFormat = "0.1" + } else if sparseSizeOk { + sparseFormat = "0.0" + } else { + // Not a PAX format GNU sparse file. + return nil, nil + } + + // Check for unknown sparse format + if sparseFormat != "0.0" && sparseFormat != "0.1" && sparseFormat != "1.0" { + return nil, nil + } + + // Update hdr from GNU sparse PAX headers + if sparseNameOk { + hdr.Name = sparseName + } + if sparseSizeOk { + realSize, err := strconv.ParseInt(sparseSize, 10, 0) + if err != nil { + return nil, ErrHeader + } + hdr.Size = realSize + } else if sparseRealSizeOk { + realSize, err := strconv.ParseInt(sparseRealSize, 10, 0) + if err != nil { + return nil, ErrHeader + } + hdr.Size = realSize + } + + // Set up the sparse map, according to the particular sparse format in use + var sp []sparseEntry + var err error + switch sparseFormat { + case "0.0", "0.1": + sp, err = readGNUSparseMap0x1(headers) + case "1.0": + sp, err = readGNUSparseMap1x0(tr.curr) + } + return sp, err +} + // mergePAX merges well known headers according to PAX standard. // In general headers with the same name as those found // in the header struct overwrite those found in the header @@ -139,8 +258,14 @@ func mergePAX(hdr *Header, headers map[string]string) error { return err } hdr.Size = int64(size) + default: + if strings.HasPrefix(k, paxXattr) { + if hdr.Xattrs == nil { + hdr.Xattrs = make(map[string]string) + } + hdr.Xattrs[k[len(paxXattr):]] = v + } } - } return nil } @@ -188,6 +313,11 @@ func parsePAX(r io.Reader) (map[string]string, error) { if err != nil { return nil, err } + + // For GNU PAX sparse format 0.0 support. + // This function transforms the sparse format 0.0 headers into sparse format 0.1 headers. + var sparseMap bytes.Buffer + headers := make(map[string]string) // Each record is constructed as // "%d %s=%s\n", length, keyword, value @@ -205,7 +335,7 @@ func parsePAX(r io.Reader) (map[string]string, error) { return nil, ErrHeader } // Extract everything between the decimal and the n -1 on the - // beginning to to eat the ' ', -1 on the end to skip the newline. + // beginning to eat the ' ', -1 on the end to skip the newline. var record []byte record, buf = buf[sp+1:n-1], buf[n:] // The first equals is guaranteed to mark the end of the key. @@ -215,7 +345,21 @@ func parsePAX(r io.Reader) (map[string]string, error) { return nil, ErrHeader } key, value := record[:eq], record[eq+1:] - headers[string(key)] = string(value) + + keyStr := string(key) + if keyStr == paxGNUSparseOffset || keyStr == paxGNUSparseNumBytes { + // GNU sparse format 0.0 special key. Write to sparseMap instead of using the headers map. + sparseMap.Write(value) + sparseMap.Write([]byte{','}) + } else { + // Normal key. Set the value in the headers map. + headers[keyStr] = string(value) + } + } + if sparseMap.Len() != 0 { + // Add sparse info to headers, chopping off the extra comma + sparseMap.Truncate(sparseMap.Len() - 1) + headers[paxGNUSparseMap] = sparseMap.String() } return headers, nil } @@ -262,8 +406,8 @@ func (tr *Reader) octal(b []byte) int64 { // skipUnread skips any unread bytes in the existing file entry, as well as any alignment padding. func (tr *Reader) skipUnread() { - nr := tr.nb + tr.pad // number of bytes to skip - tr.nb, tr.pad = 0, 0 + nr := tr.numBytes() + tr.pad // number of bytes to skip + tr.curr, tr.pad = nil, 0 if sr, ok := tr.r.(io.Seeker); ok { if _, err := sr.Seek(nr, os.SEEK_CUR); err == nil { return @@ -283,7 +427,9 @@ func (tr *Reader) verifyChecksum(header []byte) bool { } func (tr *Reader) readHeader() *Header { - header := make([]byte, blockSize) + header := tr.hdrBuff[:] + copy(header, zeroBlock) + if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil { return nil } @@ -325,14 +471,14 @@ func (tr *Reader) readHeader() *Header { // so its magic bytes, like the rest of the block, are NULs. magic := string(s.next(8)) // contains version field as well. var format string - switch magic { - case "ustar\x0000": // POSIX tar (1003.1-1988) + switch { + case magic[:6] == "ustar\x00": // POSIX tar (1003.1-1988) if string(header[508:512]) == "tar\x00" { format = "star" } else { format = "posix" } - case "ustar \x00": // old GNU tar + case magic == "ustar \x00": // old GNU tar format = "gnu" } @@ -367,30 +513,308 @@ func (tr *Reader) readHeader() *Header { // Maximum value of hdr.Size is 64 GB (12 octal digits), // so there's no risk of int64 overflowing. - tr.nb = int64(hdr.Size) - tr.pad = -tr.nb & (blockSize - 1) // blockSize is a power of two + nb := int64(hdr.Size) + tr.pad = -nb & (blockSize - 1) // blockSize is a power of two + + // Set the current file reader. + tr.curr = ®FileReader{r: tr.r, nb: nb} + + // Check for old GNU sparse format entry. + if hdr.Typeflag == TypeGNUSparse { + // Get the real size of the file. + hdr.Size = tr.octal(header[483:495]) + + // Read the sparse map. + sp := tr.readOldGNUSparseMap(header) + if tr.err != nil { + return nil + } + // Current file is a GNU sparse file. Update the current file reader. + tr.curr = &sparseFileReader{rfr: tr.curr.(*regFileReader), sp: sp, tot: hdr.Size} + } return hdr } +// A sparseEntry holds a single entry in a sparse file's sparse map. +// A sparse entry indicates the offset and size in a sparse file of a +// block of data. +type sparseEntry struct { + offset int64 + numBytes int64 +} + +// readOldGNUSparseMap reads the sparse map as stored in the old GNU sparse format. +// The sparse map is stored in the tar header if it's small enough. If it's larger than four entries, +// then one or more extension headers are used to store the rest of the sparse map. +func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry { + isExtended := header[oldGNUSparseMainHeaderIsExtendedOffset] != 0 + spCap := oldGNUSparseMainHeaderNumEntries + if isExtended { + spCap += oldGNUSparseExtendedHeaderNumEntries + } + sp := make([]sparseEntry, 0, spCap) + s := slicer(header[oldGNUSparseMainHeaderOffset:]) + + // Read the four entries from the main tar header + for i := 0; i < oldGNUSparseMainHeaderNumEntries; i++ { + offset := tr.octal(s.next(oldGNUSparseOffsetSize)) + numBytes := tr.octal(s.next(oldGNUSparseNumBytesSize)) + if tr.err != nil { + tr.err = ErrHeader + return nil + } + if offset == 0 && numBytes == 0 { + break + } + sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) + } + + for isExtended { + // There are more entries. Read an extension header and parse its entries. + sparseHeader := make([]byte, blockSize) + if _, tr.err = io.ReadFull(tr.r, sparseHeader); tr.err != nil { + return nil + } + isExtended = sparseHeader[oldGNUSparseExtendedHeaderIsExtendedOffset] != 0 + s = slicer(sparseHeader) + for i := 0; i < oldGNUSparseExtendedHeaderNumEntries; i++ { + offset := tr.octal(s.next(oldGNUSparseOffsetSize)) + numBytes := tr.octal(s.next(oldGNUSparseNumBytesSize)) + if tr.err != nil { + tr.err = ErrHeader + return nil + } + if offset == 0 && numBytes == 0 { + break + } + sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) + } + } + return sp +} + +// readGNUSparseMap1x0 reads the sparse map as stored in GNU's PAX sparse format version 1.0. +// The sparse map is stored just before the file data and padded out to the nearest block boundary. +func readGNUSparseMap1x0(r io.Reader) ([]sparseEntry, error) { + buf := make([]byte, 2*blockSize) + sparseHeader := buf[:blockSize] + + // readDecimal is a helper function to read a decimal integer from the sparse map + // while making sure to read from the file in blocks of size blockSize + readDecimal := func() (int64, error) { + // Look for newline + nl := bytes.IndexByte(sparseHeader, '\n') + if nl == -1 { + if len(sparseHeader) >= blockSize { + // This is an error + return 0, ErrHeader + } + oldLen := len(sparseHeader) + newLen := oldLen + blockSize + if cap(sparseHeader) < newLen { + // There's more header, but we need to make room for the next block + copy(buf, sparseHeader) + sparseHeader = buf[:newLen] + } else { + // There's more header, and we can just reslice + sparseHeader = sparseHeader[:newLen] + } + + // Now that sparseHeader is large enough, read next block + if _, err := io.ReadFull(r, sparseHeader[oldLen:newLen]); err != nil { + return 0, err + } + + // Look for a newline in the new data + nl = bytes.IndexByte(sparseHeader[oldLen:newLen], '\n') + if nl == -1 { + // This is an error + return 0, ErrHeader + } + nl += oldLen // We want the position from the beginning + } + // Now that we've found a newline, read a number + n, err := strconv.ParseInt(string(sparseHeader[:nl]), 10, 0) + if err != nil { + return 0, ErrHeader + } + + // Update sparseHeader to consume this number + sparseHeader = sparseHeader[nl+1:] + return n, nil + } + + // Read the first block + if _, err := io.ReadFull(r, sparseHeader); err != nil { + return nil, err + } + + // The first line contains the number of entries + numEntries, err := readDecimal() + if err != nil { + return nil, err + } + + // Read all the entries + sp := make([]sparseEntry, 0, numEntries) + for i := int64(0); i < numEntries; i++ { + // Read the offset + offset, err := readDecimal() + if err != nil { + return nil, err + } + // Read numBytes + numBytes, err := readDecimal() + if err != nil { + return nil, err + } + + sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) + } + + return sp, nil +} + +// readGNUSparseMap0x1 reads the sparse map as stored in GNU's PAX sparse format version 0.1. +// The sparse map is stored in the PAX headers. +func readGNUSparseMap0x1(headers map[string]string) ([]sparseEntry, error) { + // Get number of entries + numEntriesStr, ok := headers[paxGNUSparseNumBlocks] + if !ok { + return nil, ErrHeader + } + numEntries, err := strconv.ParseInt(numEntriesStr, 10, 0) + if err != nil { + return nil, ErrHeader + } + + sparseMap := strings.Split(headers[paxGNUSparseMap], ",") + + // There should be two numbers in sparseMap for each entry + if int64(len(sparseMap)) != 2*numEntries { + return nil, ErrHeader + } + + // Loop through the entries in the sparse map + sp := make([]sparseEntry, 0, numEntries) + for i := int64(0); i < numEntries; i++ { + offset, err := strconv.ParseInt(sparseMap[2*i], 10, 0) + if err != nil { + return nil, ErrHeader + } + numBytes, err := strconv.ParseInt(sparseMap[2*i+1], 10, 0) + if err != nil { + return nil, ErrHeader + } + sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes}) + } + + return sp, nil +} + +// numBytes returns the number of bytes left to read in the current file's entry +// in the tar archive, or 0 if there is no current file. +func (tr *Reader) numBytes() int64 { + if tr.curr == nil { + // No current file, so no bytes + return 0 + } + return tr.curr.numBytes() +} + // Read reads from the current entry in the tar archive. // It returns 0, io.EOF when it reaches the end of that entry, // until Next is called to advance to the next entry. func (tr *Reader) Read(b []byte) (n int, err error) { - if tr.nb == 0 { - // file consumed + if tr.curr == nil { return 0, io.EOF } + n, err = tr.curr.Read(b) + if err != nil && err != io.EOF { + tr.err = err + } + return +} - if int64(len(b)) > tr.nb { - b = b[0:tr.nb] +func (rfr *regFileReader) Read(b []byte) (n int, err error) { + if rfr.nb == 0 { + // file consumed + return 0, io.EOF } - n, err = tr.r.Read(b) - tr.nb -= int64(n) + if int64(len(b)) > rfr.nb { + b = b[0:rfr.nb] + } + n, err = rfr.r.Read(b) + rfr.nb -= int64(n) - if err == io.EOF && tr.nb > 0 { + if err == io.EOF && rfr.nb > 0 { err = io.ErrUnexpectedEOF } - tr.err = err return } + +// numBytes returns the number of bytes left to read in the file's data in the tar archive. +func (rfr *regFileReader) numBytes() int64 { + return rfr.nb +} + +// readHole reads a sparse file hole ending at offset toOffset +func (sfr *sparseFileReader) readHole(b []byte, toOffset int64) int { + n64 := toOffset - sfr.pos + if n64 > int64(len(b)) { + n64 = int64(len(b)) + } + n := int(n64) + for i := 0; i < n; i++ { + b[i] = 0 + } + sfr.pos += n64 + return n +} + +// Read reads the sparse file data in expanded form. +func (sfr *sparseFileReader) Read(b []byte) (n int, err error) { + if len(sfr.sp) == 0 { + // No more data fragments to read from. + if sfr.pos < sfr.tot { + // We're in the last hole + n = sfr.readHole(b, sfr.tot) + return + } + // Otherwise, we're at the end of the file + return 0, io.EOF + } + if sfr.pos < sfr.sp[0].offset { + // We're in a hole + n = sfr.readHole(b, sfr.sp[0].offset) + return + } + + // We're not in a hole, so we'll read from the next data fragment + posInFragment := sfr.pos - sfr.sp[0].offset + bytesLeft := sfr.sp[0].numBytes - posInFragment + if int64(len(b)) > bytesLeft { + b = b[0:bytesLeft] + } + + n, err = sfr.rfr.Read(b) + sfr.pos += int64(n) + + if int64(n) == bytesLeft { + // We're done with this fragment + sfr.sp = sfr.sp[1:] + } + + if err == io.EOF && sfr.pos < sfr.tot { + // We reached the end of the last fragment's data, but there's a final hole + err = nil + } + return +} + +// numBytes returns the number of bytes left to read in the sparse file's +// sparse-encoded data in the tar archive. +func (sfr *sparseFileReader) numBytes() int64 { + return sfr.rfr.nb +} diff --git a/libgo/go/archive/tar/reader_test.go b/libgo/go/archive/tar/reader_test.go index 1285616565..9601ffe459 100644 --- a/libgo/go/archive/tar/reader_test.go +++ b/libgo/go/archive/tar/reader_test.go @@ -9,6 +9,7 @@ import ( "crypto/md5" "fmt" "io" + "io/ioutil" "os" "reflect" "strings" @@ -54,8 +55,92 @@ var gnuTarTest = &untarTest{ }, } +var sparseTarTest = &untarTest{ + file: "testdata/sparse-formats.tar", + headers: []*Header{ + { + Name: "sparse-gnu", + Mode: 420, + Uid: 1000, + Gid: 1000, + Size: 200, + ModTime: time.Unix(1392395740, 0), + Typeflag: 0x53, + Linkname: "", + Uname: "david", + Gname: "david", + Devmajor: 0, + Devminor: 0, + }, + { + Name: "sparse-posix-0.0", + Mode: 420, + Uid: 1000, + Gid: 1000, + Size: 200, + ModTime: time.Unix(1392342187, 0), + Typeflag: 0x30, + Linkname: "", + Uname: "david", + Gname: "david", + Devmajor: 0, + Devminor: 0, + }, + { + Name: "sparse-posix-0.1", + Mode: 420, + Uid: 1000, + Gid: 1000, + Size: 200, + ModTime: time.Unix(1392340456, 0), + Typeflag: 0x30, + Linkname: "", + Uname: "david", + Gname: "david", + Devmajor: 0, + Devminor: 0, + }, + { + Name: "sparse-posix-1.0", + Mode: 420, + Uid: 1000, + Gid: 1000, + Size: 200, + ModTime: time.Unix(1392337404, 0), + Typeflag: 0x30, + Linkname: "", + Uname: "david", + Gname: "david", + Devmajor: 0, + Devminor: 0, + }, + { + Name: "end", + Mode: 420, + Uid: 1000, + Gid: 1000, + Size: 4, + ModTime: time.Unix(1392398319, 0), + Typeflag: 0x30, + Linkname: "", + Uname: "david", + Gname: "david", + Devmajor: 0, + Devminor: 0, + }, + }, + cksums: []string{ + "6f53234398c2449fe67c1812d993012f", + "6f53234398c2449fe67c1812d993012f", + "6f53234398c2449fe67c1812d993012f", + "6f53234398c2449fe67c1812d993012f", + "b0061974914468de549a2af8ced10316", + }, +} + var untarTests = []*untarTest{ gnuTarTest, + sparseTarTest, { file: "testdata/star.tar", headers: []*Header{ @@ -161,6 +246,46 @@ var untarTests = []*untarTest{ }, }, }, + { + file: "testdata/xattrs.tar", + headers: []*Header{ + { + Name: "small.txt", + Mode: 0644, + Uid: 1000, + Gid: 10, + Size: 5, + ModTime: time.Unix(1386065770, 448252320), + Typeflag: '0', + Uname: "alex", + Gname: "wheel", + AccessTime: time.Unix(1389782991, 419875220), + ChangeTime: time.Unix(1389782956, 794414986), + Xattrs: map[string]string{ + "user.key": "value", + "user.key2": "value2", + // Interestingly, selinux encodes the terminating null inside the xattr + "security.selinux": "unconfined_u:object_r:default_t:s0\x00", + }, + }, + { + Name: "small2.txt", + Mode: 0644, + Uid: 1000, + Gid: 10, + Size: 11, + ModTime: time.Unix(1386065770, 449252304), + Typeflag: '0', + Uname: "alex", + Gname: "wheel", + AccessTime: time.Unix(1389782991, 419875220), + ChangeTime: time.Unix(1386065770, 449252304), + Xattrs: map[string]string{ + "security.selinux": "unconfined_u:object_r:default_t:s0\x00", + }, + }, + }, + }, } func TestReader(t *testing.T) { @@ -180,7 +305,7 @@ testLoop: f.Close() continue testLoop } - if *hdr != *header { + if !reflect.DeepEqual(*hdr, *header) { t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v", i, j, *hdr, *header) } @@ -253,7 +378,7 @@ func TestIncrementalRead(t *testing.T) { } // check the header - if *hdr != *headers[nread] { + if !reflect.DeepEqual(*hdr, *headers[nread]) { t.Errorf("Incorrect header:\nhave %+v\nwant %+v", *hdr, headers[nread]) } @@ -321,7 +446,7 @@ func TestParsePAXHeader(t *testing.T) { {"mtime", "mtime=1350244992.023960108", "30 mtime=1350244992.023960108\n"}} for _, test := range paxTests { key, expected, raw := test[0], test[1], test[2] - reader := bytes.NewBuffer([]byte(raw)) + reader := bytes.NewReader([]byte(raw)) headers, err := parsePAX(reader) if err != nil { t.Errorf("Couldn't parse correctly formatted headers: %v", err) @@ -337,7 +462,7 @@ func TestParsePAXHeader(t *testing.T) { t.Error("Buffer wasn't consumed") } } - badHeader := bytes.NewBuffer([]byte("3 somelongkey=")) + badHeader := bytes.NewReader([]byte("3 somelongkey=")) if _, err := parsePAX(badHeader); err != ErrHeader { t.Fatal("Unexpected success when parsing bad header") } @@ -346,7 +471,7 @@ func TestParsePAXHeader(t *testing.T) { func TestParsePAXTime(t *testing.T) { // Some valid PAX time values timestamps := map[string]time.Time{ - "1350244992.023960108": time.Unix(1350244992, 23960108), // The commoon case + "1350244992.023960108": time.Unix(1350244992, 23960108), // The common case "1350244992.02396010": time.Unix(1350244992, 23960100), // Lower precision value "1350244992.0239601089": time.Unix(1350244992, 23960108), // Higher precision value "1350244992": time.Unix(1350244992, 0), // Low precision value @@ -383,3 +508,236 @@ func TestMergePAX(t *testing.T) { t.Errorf("incorrect merge: got %+v, want %+v", hdr, want) } } + +func TestSparseEndToEnd(t *testing.T) { + test := sparseTarTest + f, err := os.Open(test.file) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + defer f.Close() + + tr := NewReader(f) + + headers := test.headers + cksums := test.cksums + nread := 0 + + // loop over all files + for ; ; nread++ { + hdr, err := tr.Next() + if hdr == nil || err == io.EOF { + break + } + + // check the header + if !reflect.DeepEqual(*hdr, *headers[nread]) { + t.Errorf("Incorrect header:\nhave %+v\nwant %+v", + *hdr, headers[nread]) + } + + // read and checksum the file data + h := md5.New() + _, err = io.Copy(h, tr) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + + // verify checksum + have := fmt.Sprintf("%x", h.Sum(nil)) + want := cksums[nread] + if want != have { + t.Errorf("Bad checksum on file %s:\nhave %+v\nwant %+v", hdr.Name, have, want) + } + } + if nread != len(headers) { + t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(headers), nread) + } +} + +type sparseFileReadTest struct { + sparseData []byte + sparseMap []sparseEntry + realSize int64 + expected []byte +} + +var sparseFileReadTests = []sparseFileReadTest{ + { + sparseData: []byte("abcde"), + sparseMap: []sparseEntry{ + {offset: 0, numBytes: 2}, + {offset: 5, numBytes: 3}, + }, + realSize: 8, + expected: []byte("ab\x00\x00\x00cde"), + }, + { + sparseData: []byte("abcde"), + sparseMap: []sparseEntry{ + {offset: 0, numBytes: 2}, + {offset: 5, numBytes: 3}, + }, + realSize: 10, + expected: []byte("ab\x00\x00\x00cde\x00\x00"), + }, + { + sparseData: []byte("abcde"), + sparseMap: []sparseEntry{ + {offset: 1, numBytes: 3}, + {offset: 6, numBytes: 2}, + }, + realSize: 8, + expected: []byte("\x00abc\x00\x00de"), + }, + { + sparseData: []byte("abcde"), + sparseMap: []sparseEntry{ + {offset: 1, numBytes: 3}, + {offset: 6, numBytes: 2}, + }, + realSize: 10, + expected: []byte("\x00abc\x00\x00de\x00\x00"), + }, + { + sparseData: []byte(""), + sparseMap: nil, + realSize: 2, + expected: []byte("\x00\x00"), + }, +} + +func TestSparseFileReader(t *testing.T) { + for i, test := range sparseFileReadTests { + r := bytes.NewReader(test.sparseData) + nb := int64(r.Len()) + sfr := &sparseFileReader{ + rfr: ®FileReader{r: r, nb: nb}, + sp: test.sparseMap, + pos: 0, + tot: test.realSize, + } + if sfr.numBytes() != nb { + t.Errorf("test %d: Before reading, sfr.numBytes() = %d, want %d", i, sfr.numBytes(), nb) + } + buf, err := ioutil.ReadAll(sfr) + if err != nil { + t.Errorf("test %d: Unexpected error: %v", i, err) + } + if e := test.expected; !bytes.Equal(buf, e) { + t.Errorf("test %d: Contents = %v, want %v", i, buf, e) + } + if sfr.numBytes() != 0 { + t.Errorf("test %d: After draining the reader, numBytes() was nonzero", i) + } + } +} + +func TestSparseIncrementalRead(t *testing.T) { + sparseMap := []sparseEntry{{10, 2}} + sparseData := []byte("Go") + expected := "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Go\x00\x00\x00\x00\x00\x00\x00\x00" + + r := bytes.NewReader(sparseData) + nb := int64(r.Len()) + sfr := &sparseFileReader{ + rfr: ®FileReader{r: r, nb: nb}, + sp: sparseMap, + pos: 0, + tot: int64(len(expected)), + } + + // We'll read the data 6 bytes at a time, with a hole of size 10 at + // the beginning and one of size 8 at the end. + var outputBuf bytes.Buffer + buf := make([]byte, 6) + for { + n, err := sfr.Read(buf) + if err == io.EOF { + break + } + if err != nil { + t.Errorf("Read: unexpected error %v\n", err) + } + if n > 0 { + _, err := outputBuf.Write(buf[:n]) + if err != nil { + t.Errorf("Write: unexpected error %v\n", err) + } + } + } + got := outputBuf.String() + if got != expected { + t.Errorf("Contents = %v, want %v", got, expected) + } +} + +func TestReadGNUSparseMap0x1(t *testing.T) { + headers := map[string]string{ + paxGNUSparseNumBlocks: "4", + paxGNUSparseMap: "0,5,10,5,20,5,30,5", + } + expected := []sparseEntry{ + {offset: 0, numBytes: 5}, + {offset: 10, numBytes: 5}, + {offset: 20, numBytes: 5}, + {offset: 30, numBytes: 5}, + } + + sp, err := readGNUSparseMap0x1(headers) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if !reflect.DeepEqual(sp, expected) { + t.Errorf("Incorrect sparse map: got %v, wanted %v", sp, expected) + } +} + +func TestReadGNUSparseMap1x0(t *testing.T) { + // This test uses lots of holes so the sparse header takes up more than two blocks + numEntries := 100 + expected := make([]sparseEntry, 0, numEntries) + sparseMap := new(bytes.Buffer) + + fmt.Fprintf(sparseMap, "%d\n", numEntries) + for i := 0; i < numEntries; i++ { + offset := int64(2048 * i) + numBytes := int64(1024) + expected = append(expected, sparseEntry{offset: offset, numBytes: numBytes}) + fmt.Fprintf(sparseMap, "%d\n%d\n", offset, numBytes) + } + + // Make the header the smallest multiple of blockSize that fits the sparseMap + headerBlocks := (sparseMap.Len() + blockSize - 1) / blockSize + bufLen := blockSize * headerBlocks + buf := make([]byte, bufLen) + copy(buf, sparseMap.Bytes()) + + // Get an reader to read the sparse map + r := bytes.NewReader(buf) + + // Read the sparse map + sp, err := readGNUSparseMap1x0(r) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if !reflect.DeepEqual(sp, expected) { + t.Errorf("Incorrect sparse map: got %v, wanted %v", sp, expected) + } +} + +func TestUninitializedRead(t *testing.T) { + test := gnuTarTest + f, err := os.Open(test.file) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + defer f.Close() + + tr := NewReader(f) + _, err = tr.Read([]byte{}) + if err == nil || err != io.EOF { + t.Errorf("Unexpected error: %v, wanted %v", err, io.EOF) + } + +} diff --git a/libgo/go/archive/tar/stat_atim.go b/libgo/go/archive/tar/stat_atim.go index 6029b08712..cf9cc79c59 100644 --- a/libgo/go/archive/tar/stat_atim.go +++ b/libgo/go/archive/tar/stat_atim.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux openbsd +// +build linux dragonfly openbsd solaris package tar diff --git a/libgo/go/archive/tar/stat_unix.go b/libgo/go/archive/tar/stat_unix.go index 92bc924242..cb843db4cf 100644 --- a/libgo/go/archive/tar/stat_unix.go +++ b/libgo/go/archive/tar/stat_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build linux darwin freebsd openbsd netbsd +// +build linux darwin dragonfly freebsd openbsd netbsd solaris package tar diff --git a/libgo/go/archive/tar/tar_test.go b/libgo/go/archive/tar/tar_test.go index 616a9cc57e..ed333f3ea4 100644 --- a/libgo/go/archive/tar/tar_test.go +++ b/libgo/go/archive/tar/tar_test.go @@ -36,6 +36,10 @@ func TestFileInfoHeader(t *testing.T) { if g, e := h.ModTime, fi.ModTime(); !g.Equal(e) { t.Errorf("ModTime = %v; want %v", g, e) } + // FileInfoHeader should error when passing nil FileInfo + if _, err := FileInfoHeader(nil, ""); err == nil { + t.Fatalf("Expected error when passing nil to FileInfoHeader") + } } func TestFileInfoHeaderDir(t *testing.T) { diff --git a/libgo/go/archive/tar/testdata/sparse-formats.tar b/libgo/go/archive/tar/testdata/sparse-formats.tar new file mode 100644 index 0000000000..8bd4e74d50 Binary files /dev/null and b/libgo/go/archive/tar/testdata/sparse-formats.tar differ diff --git a/libgo/go/archive/tar/testdata/writer-big-long.tar b/libgo/go/archive/tar/testdata/writer-big-long.tar new file mode 100644 index 0000000000..5960ee8247 Binary files /dev/null and b/libgo/go/archive/tar/testdata/writer-big-long.tar differ diff --git a/libgo/go/archive/tar/testdata/xattrs.tar b/libgo/go/archive/tar/testdata/xattrs.tar new file mode 100644 index 0000000000..9701950edd Binary files /dev/null and b/libgo/go/archive/tar/testdata/xattrs.tar differ diff --git a/libgo/go/archive/tar/writer.go b/libgo/go/archive/tar/writer.go index 549f1464c3..dafb2cabf3 100644 --- a/libgo/go/archive/tar/writer.go +++ b/libgo/go/archive/tar/writer.go @@ -37,8 +37,10 @@ type Writer struct { nb int64 // number of unwritten bytes for current file entry pad int64 // amount of padding to write after current file entry closed bool - usedBinary bool // whether the binary numeric field extension was used - preferPax bool // use pax header instead of binary numeric header + usedBinary bool // whether the binary numeric field extension was used + preferPax bool // use pax header instead of binary numeric header + hdrBuff [blockSize]byte // buffer to use in writeHeader when writing a regular header + paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header } // NewWriter creates a new Writer writing to w. @@ -160,7 +162,18 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error { // subsecond time resolution, but for now let's just capture // too long fields or non ascii characters - header := make([]byte, blockSize) + var header []byte + + // We need to select which scratch buffer to use carefully, + // since this method is called recursively to write PAX headers. + // If allowPax is true, this is the non-recursive call, and we will use hdrBuff. + // If allowPax is false, we are being called by writePAXHeader, and hdrBuff is + // already being used by the non-recursive call, so we must use paxHdrBuff. + header = tw.hdrBuff[:] + if !allowPax { + header = tw.paxHdrBuff[:] + } + copy(header, zeroBlock) s := slicer(header) // keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax @@ -218,8 +231,8 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error { tw.cString(prefixHeaderBytes, prefix, false, paxNone, nil) // Use the ustar magic if we used ustar long names. - if len(prefix) > 0 { - copy(header[257:265], []byte("ustar\000")) + if len(prefix) > 0 && !tw.usedBinary { + copy(header[257:265], []byte("ustar\x00")) } } } @@ -236,6 +249,12 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error { return tw.err } + if allowPax { + for k, v := range hdr.Xattrs { + paxHeaders[paxXattr+k] = v + } + } + if len(paxHeaders) > 0 { if !allowPax { return errInvalidHeader diff --git a/libgo/go/archive/tar/writer_test.go b/libgo/go/archive/tar/writer_test.go index 30ebf977ac..5e42e322f9 100644 --- a/libgo/go/archive/tar/writer_test.go +++ b/libgo/go/archive/tar/writer_test.go @@ -10,6 +10,7 @@ import ( "io" "io/ioutil" "os" + "reflect" "strings" "testing" "testing/iotest" @@ -102,6 +103,29 @@ var writerTests = []*writerTest{ }, }, }, + // The truncated test file was produced using these commands: + // dd if=/dev/zero bs=1048576 count=16384 > (longname/)*15 /16gig.txt + // tar -b 1 -c -f- (longname/)*15 /16gig.txt | dd bs=512 count=8 > writer-big-long.tar + { + file: "testdata/writer-big-long.tar", + entries: []*writerTestEntry{ + { + header: &Header{ + Name: strings.Repeat("longname/", 15) + "16gig.txt", + Mode: 0644, + Uid: 1000, + Gid: 1000, + Size: 16 << 30, + ModTime: time.Unix(1399583047, 0), + Typeflag: '0', + Uname: "guillaume", + Gname: "guillaume", + }, + // fake contents + contents: strings.Repeat("\x00", 4<<10), + }, + }, + }, // This file was produced using gnu tar 1.17 // gnutar -b 4 --format=ustar (longname/)*15 + file.txt { @@ -338,6 +362,45 @@ func TestPaxNonAscii(t *testing.T) { } } +func TestPaxXattrs(t *testing.T) { + xattrs := map[string]string{ + "user.key": "value", + } + + // Create an archive with an xattr + fileinfo, err := os.Stat("testdata/small.txt") + if err != nil { + t.Fatal(err) + } + hdr, err := FileInfoHeader(fileinfo, "") + if err != nil { + t.Fatalf("os.Stat: %v", err) + } + contents := "Kilts" + hdr.Xattrs = xattrs + var buf bytes.Buffer + writer := NewWriter(&buf) + if err := writer.WriteHeader(hdr); err != nil { + t.Fatal(err) + } + if _, err = writer.Write([]byte(contents)); err != nil { + t.Fatal(err) + } + if err := writer.Close(); err != nil { + t.Fatal(err) + } + // Test that we can get the xattrs back out of the archive. + reader := NewReader(&buf) + hdr, err = reader.Next() + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(hdr.Xattrs, xattrs) { + t.Fatalf("xattrs did not survive round trip: got %+v, want %+v", + hdr.Xattrs, xattrs) + } +} + func TestPAXHeader(t *testing.T) { medName := strings.Repeat("CD", 50) longName := strings.Repeat("AB", 100) @@ -391,3 +454,38 @@ func TestUSTARLongName(t *testing.T) { t.Fatal("Couldn't recover long name") } } + +func TestValidTypeflagWithPAXHeader(t *testing.T) { + var buffer bytes.Buffer + tw := NewWriter(&buffer) + + fileName := strings.Repeat("ab", 100) + + hdr := &Header{ + Name: fileName, + Size: 4, + Typeflag: 0, + } + if err := tw.WriteHeader(hdr); err != nil { + t.Fatalf("Failed to write header: %s", err) + } + if _, err := tw.Write([]byte("fooo")); err != nil { + t.Fatalf("Failed to write the file's data: %s", err) + } + tw.Close() + + tr := NewReader(&buffer) + + for { + header, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + t.Fatalf("Failed to read header: %s", err) + } + if header.Typeflag != 0 { + t.Fatalf("Typeflag should've been 0, found %d", header.Typeflag) + } + } +} diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go index 116737337f..8136b840d4 100644 --- a/libgo/go/archive/zip/reader.go +++ b/libgo/go/archive/zip/reader.go @@ -253,7 +253,7 @@ func readDirectoryHeader(f *File, r io.Reader) error { } if tag == zip64ExtraId { // update directory values from the zip64 extra block - eb := readBuf(b) + eb := readBuf(b[:size]) if len(eb) >= 8 { f.UncompressedSize64 = eb.uint64() } @@ -267,8 +267,13 @@ func readDirectoryHeader(f *File, r io.Reader) error { b = b[size:] } // Should have consumed the whole header. - if len(b) != 0 { - return ErrFormat + // But popular zip & JAR creation tools are broken and + // may pad extra zeros at the end, so accept those + // too. See golang.org/issue/8186. + for _, v := range b { + if v != 0 { + return ErrFormat + } } } return nil diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go index 78875ecbf0..29d0652dcc 100644 --- a/libgo/go/archive/zip/reader_test.go +++ b/libgo/go/archive/zip/reader_test.go @@ -13,6 +13,7 @@ import ( "os" "path/filepath" "regexp" + "strings" "testing" "time" ) @@ -235,6 +236,18 @@ var tests = []ZipTest{ }, }, }, + // Another zip64 file with different Extras fields. (golang.org/issue/7069) + { + Name: "zip64-2.zip", + File: []ZipTestFile{ + { + Name: "README", + Content: []byte("This small file is in ZIP64 format.\n"), + Mtime: "08-10-12 14:33:32", + Mode: 0644, + }, + }, + }, } var crossPlatform = []ZipTestFile{ @@ -343,19 +356,13 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) { testFileMode(t, zt.Name, f, ft.Mode) - size0 := f.UncompressedSize - var b bytes.Buffer r, err := f.Open() if err != nil { - t.Error(err) + t.Errorf("%s: %v", zt.Name, err) return } - if size1 := f.UncompressedSize; size0 != size1 { - t.Errorf("file %q changed f.UncompressedSize from %d to %d", f.Name, size0, size1) - } - _, err = io.Copy(&b, r) if err != ft.ContentErr { t.Errorf("%s: copying contents: %v (want %v)", zt.Name, err, ft.ContentErr) @@ -365,6 +372,14 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) { } r.Close() + size := uint64(f.UncompressedSize) + if size == uint32max { + size = f.UncompressedSize64 + } + if g := uint64(b.Len()); g != size { + t.Errorf("%v: read %v bytes but f.UncompressedSize == %v", f.Name, g, size) + } + var c []byte if ft.Content != nil { c = ft.Content @@ -494,3 +509,25 @@ func returnRecursiveZip() (r io.ReaderAt, size int64) { b := rZipBytes() return bytes.NewReader(b), int64(len(b)) } + +func TestIssue8186(t *testing.T) { + // Directory headers & data found in the TOC of a JAR file. + dirEnts := []string{ + "PK\x01\x02\n\x00\n\x00\x00\b\x00\x004\x9d3?\xaa\x1b\x06\xf0\x81\x02\x00\x00\x81\x02\x00\x00-\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00res/drawable-xhdpi-v4/ic_actionbar_accept.png\xfe\xca\x00\x00\x00", + "PK\x01\x02\n\x00\n\x00\x00\b\x00\x004\x9d3?\x90K\x89\xc7t\n\x00\x00t\n\x00\x00\x0e\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x02\x00\x00resources.arsc\x00\x00\x00", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\xff$\x18\xed3\x03\x00\x00\xb4\b\x00\x00\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00t\r\x00\x00AndroidManifest.xml", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\x14\xc5K\xab\x192\x02\x00\xc8\xcd\x04\x00\v\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x10\x00\x00classes.dex", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?E\x96\nD\xac\x01\x00\x00P\x03\x00\x00&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:C\x02\x00res/layout/actionbar_set_wallpaper.xml", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?Ļ\x14\xe3\xd8\x01\x00\x00\xd8\x03\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:E\x02\x00res/layout/wallpaper_cropper.xml", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?}\xc1\x15\x9eZ\x01\x00\x00!\x02\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00`G\x02\x00META-INF/MANIFEST.MF", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\xe6\x98Ьo\x01\x00\x00\x84\x02\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfcH\x02\x00META-INF/CERT.SF", + "PK\x01\x02\x14\x00\x14\x00\b\b\b\x004\x9d3?\xbfP\x96b\x86\x04\x00\x00\xb2\x06\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa9J\x02\x00META-INF/CERT.RSA", + } + for i, s := range dirEnts { + var f File + err := readDirectoryHeader(&f, strings.NewReader(s)) + if err != nil { + t.Errorf("error reading #%d: %v", i, err) + } + } +} diff --git a/libgo/go/archive/zip/register.go b/libgo/go/archive/zip/register.go index c046f081b7..4211ec7af7 100644 --- a/libgo/go/archive/zip/register.go +++ b/libgo/go/archive/zip/register.go @@ -6,6 +6,7 @@ package zip import ( "compress/flate" + "errors" "io" "io/ioutil" "sync" @@ -21,12 +22,50 @@ type Compressor func(io.Writer) (io.WriteCloser, error) // when they're finished reading. type Decompressor func(io.Reader) io.ReadCloser +var flateWriterPool sync.Pool + +func newFlateWriter(w io.Writer) io.WriteCloser { + fw, ok := flateWriterPool.Get().(*flate.Writer) + if ok { + fw.Reset(w) + } else { + fw, _ = flate.NewWriter(w, 5) + } + return &pooledFlateWriter{fw: fw} +} + +type pooledFlateWriter struct { + mu sync.Mutex // guards Close and Write + fw *flate.Writer +} + +func (w *pooledFlateWriter) Write(p []byte) (n int, err error) { + w.mu.Lock() + defer w.mu.Unlock() + if w.fw == nil { + return 0, errors.New("Write after Close") + } + return w.fw.Write(p) +} + +func (w *pooledFlateWriter) Close() error { + w.mu.Lock() + defer w.mu.Unlock() + var err error + if w.fw != nil { + err = w.fw.Close() + flateWriterPool.Put(w.fw) + w.fw = nil + } + return err +} + var ( mu sync.RWMutex // guards compressor and decompressor maps compressors = map[uint16]Compressor{ Store: func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }, - Deflate: func(w io.Writer) (io.WriteCloser, error) { return flate.NewWriter(w, 5) }, + Deflate: func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }, } decompressors = map[uint16]Decompressor{ diff --git a/libgo/go/archive/zip/struct.go b/libgo/go/archive/zip/struct.go index 65e5238c3b..cb28e83242 100644 --- a/libgo/go/archive/zip/struct.go +++ b/libgo/go/archive/zip/struct.go @@ -174,13 +174,13 @@ func timeToMsDosTime(t time.Time) (fDate uint16, fTime uint16) { return } -// ModTime returns the modification time. +// ModTime returns the modification time in UTC. // The resolution is 2s. func (h *FileHeader) ModTime() time.Time { return msDosTimeToTime(h.ModifiedDate, h.ModifiedTime) } -// SetModTime sets the ModifiedTime and ModifiedDate fields to the given time. +// SetModTime sets the ModifiedTime and ModifiedDate fields to the given time in UTC. // The resolution is 2s. func (h *FileHeader) SetModTime(t time.Time) { h.ModifiedDate, h.ModifiedTime = timeToMsDosTime(t) diff --git a/libgo/go/archive/zip/testdata/zip64-2.zip b/libgo/go/archive/zip/testdata/zip64-2.zip new file mode 100644 index 0000000000..f844e35373 Binary files /dev/null and b/libgo/go/archive/zip/testdata/zip64-2.zip differ diff --git a/libgo/go/archive/zip/writer.go b/libgo/go/archive/zip/writer.go index 6c9800a78f..170beec0ee 100644 --- a/libgo/go/archive/zip/writer.go +++ b/libgo/go/archive/zip/writer.go @@ -34,6 +34,12 @@ func NewWriter(w io.Writer) *Writer { return &Writer{cw: &countWriter{w: bufio.NewWriter(w)}} } +// Flush flushes any buffered data to the underlying writer. +// Calling Flush is not normally necessary; calling Close is sufficient. +func (w *Writer) Flush() error { + return w.cw.w.(*bufio.Writer).Flush() +} + // Close finishes writing the zip file by writing the central directory. // It does not (and can not) close the underlying writer. func (w *Writer) Close() error { diff --git a/libgo/go/archive/zip/writer_test.go b/libgo/go/archive/zip/writer_test.go index 8b1c4dfd26..184a7d96a7 100644 --- a/libgo/go/archive/zip/writer_test.go +++ b/libgo/go/archive/zip/writer_test.go @@ -6,6 +6,7 @@ package zip import ( "bytes" + "io" "io/ioutil" "math/rand" "os" @@ -86,6 +87,24 @@ func TestWriter(t *testing.T) { } } +func TestWriterFlush(t *testing.T) { + var buf bytes.Buffer + w := NewWriter(struct{ io.Writer }{&buf}) + _, err := w.Create("foo") + if err != nil { + t.Fatal(err) + } + if buf.Len() > 0 { + t.Fatalf("Unexpected %d bytes already in buffer", buf.Len()) + } + if err := w.Flush(); err != nil { + t.Fatal(err) + } + if buf.Len() == 0 { + t.Fatal("No bytes written after Flush") + } +} + func testCreate(t *testing.T, w *Writer, wt *WriteTest) { header := &FileHeader{ Name: wt.Name, @@ -125,3 +144,21 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) { t.Errorf("File contents %q, want %q", b, wt.Data) } } + +func BenchmarkCompressedZipGarbage(b *testing.B) { + b.ReportAllocs() + var buf bytes.Buffer + bigBuf := bytes.Repeat([]byte("a"), 1<<20) + for i := 0; i < b.N; i++ { + buf.Reset() + zw := NewWriter(&buf) + for j := 0; j < 3; j++ { + w, _ := zw.CreateHeader(&FileHeader{ + Name: "foo", + Method: Deflate, + }) + w.Write(bigBuf) + } + zw.Close() + } +} diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go index d1ff3c9edc..d3c68fe6fe 100644 --- a/libgo/go/bufio/bufio.go +++ b/libgo/go/bufio/bufio.go @@ -30,14 +30,15 @@ var ( // Reader implements buffering for an io.Reader object. type Reader struct { buf []byte - rd io.Reader - r, w int + rd io.Reader // reader provided by the client + r, w int // buf read and write positions err error lastByte int lastRuneSize int } const minReadBufferSize = 16 +const maxConsecutiveEmptyReads = 100 // NewReaderSize returns a new Reader whose buffer has at least the specified // size. If the argument io.Reader is already a Reader with large enough @@ -87,15 +88,26 @@ func (b *Reader) fill() { b.r = 0 } - // Read new data. - n, err := b.rd.Read(b.buf[b.w:]) - if n < 0 { - panic(errNegativeRead) + if b.w >= len(b.buf) { + panic("bufio: tried to fill full buffer") } - b.w += n - if err != nil { - b.err = err + + // Read new data: try a limited number of times. + for i := maxConsecutiveEmptyReads; i > 0; i-- { + n, err := b.rd.Read(b.buf[b.w:]) + if n < 0 { + panic(errNegativeRead) + } + b.w += n + if err != nil { + b.err = err + return + } + if n > 0 { + return + } } + b.err = io.ErrNoProgress } func (b *Reader) readErr() error { @@ -115,21 +127,21 @@ func (b *Reader) Peek(n int) ([]byte, error) { if n > len(b.buf) { return nil, ErrBufferFull } + // 0 <= n <= len(b.buf) for b.w-b.r < n && b.err == nil { - b.fill() - } - m := b.w - b.r - if m > n { - m = n + b.fill() // b.w-b.r < len(b.buf) => buffer is not full } + var err error - if m < n { + if avail := b.w - b.r; avail < n { + // not enough data in buffer + n = avail err = b.readErr() if err == nil { err = ErrBufferFull } } - return b.buf[b.r : b.r+m], err + return b.buf[b.r : b.r+n], err } // Read reads data into p. @@ -142,7 +154,7 @@ func (b *Reader) Read(p []byte) (n int, err error) { if n == 0 { return 0, b.readErr() } - if b.w == b.r { + if b.r == b.w { if b.err != nil { return 0, b.readErr() } @@ -150,22 +162,23 @@ func (b *Reader) Read(p []byte) (n int, err error) { // Large read, empty buffer. // Read directly into p to avoid copy. n, b.err = b.rd.Read(p) + if n < 0 { + panic(errNegativeRead) + } if n > 0 { b.lastByte = int(p[n-1]) b.lastRuneSize = -1 } return n, b.readErr() } - b.fill() - if b.w == b.r { + b.fill() // buffer is empty + if b.r == b.w { return 0, b.readErr() } } - if n > b.w-b.r { - n = b.w - b.r - } - copy(p[0:n], b.buf[b.r:]) + // copy as much as we can + n = copy(p, b.buf[b.r:b.w]) b.r += n b.lastByte = int(b.buf[b.r-1]) b.lastRuneSize = -1 @@ -176,11 +189,11 @@ func (b *Reader) Read(p []byte) (n int, err error) { // If no byte is available, returns an error. func (b *Reader) ReadByte() (c byte, err error) { b.lastRuneSize = -1 - for b.w == b.r { + for b.r == b.w { if b.err != nil { return 0, b.readErr() } - b.fill() + b.fill() // buffer is empty } c = b.buf[b.r] b.r++ @@ -190,19 +203,19 @@ func (b *Reader) ReadByte() (c byte, err error) { // UnreadByte unreads the last byte. Only the most recently read byte can be unread. func (b *Reader) UnreadByte() error { - b.lastRuneSize = -1 - if b.r == b.w && b.lastByte >= 0 { - b.w = 1 - b.r = 0 - b.buf[0] = byte(b.lastByte) - b.lastByte = -1 - return nil - } - if b.r <= 0 { + if b.lastByte < 0 || b.r == 0 && b.w > 0 { return ErrInvalidUnreadByte } - b.r-- + // b.r > 0 || b.w == 0 + if b.r > 0 { + b.r-- + } else { + // b.r == 0 && b.w == 0 + b.w = 1 + } + b.buf[b.r] = byte(b.lastByte) b.lastByte = -1 + b.lastRuneSize = -1 return nil } @@ -210,8 +223,8 @@ func (b *Reader) UnreadByte() error { // rune and its size in bytes. If the encoded rune is invalid, it consumes one byte // and returns unicode.ReplacementChar (U+FFFD) with a size of 1. func (b *Reader) ReadRune() (r rune, size int, err error) { - for b.r+utf8.UTFMax > b.w && !utf8.FullRune(b.buf[b.r:b.w]) && b.err == nil { - b.fill() + for b.r+utf8.UTFMax > b.w && !utf8.FullRune(b.buf[b.r:b.w]) && b.err == nil && b.w-b.r < len(b.buf) { + b.fill() // b.w-b.r < len(buf) => buffer is not full } b.lastRuneSize = -1 if b.r == b.w { @@ -232,7 +245,7 @@ func (b *Reader) ReadRune() (r rune, size int, err error) { // regard it is stricter than UnreadByte, which will unread the last byte // from any read operation.) func (b *Reader) UnreadRune() error { - if b.lastRuneSize < 0 || b.r == 0 { + if b.lastRuneSize < 0 || b.r < b.lastRuneSize { return ErrInvalidUnreadRune } b.r -= b.lastRuneSize @@ -255,37 +268,40 @@ func (b *Reader) Buffered() int { return b.w - b.r } // ReadBytes or ReadString instead. // ReadSlice returns err != nil if and only if line does not end in delim. func (b *Reader) ReadSlice(delim byte) (line []byte, err error) { - // Look in buffer. - if i := bytes.IndexByte(b.buf[b.r:b.w], delim); i >= 0 { - line1 := b.buf[b.r : b.r+i+1] - b.r += i + 1 - return line1, nil - } - - // Read more into buffer, until buffer fills or we find delim. for { - if b.err != nil { - line := b.buf[b.r:b.w] - b.r = b.w - return line, b.readErr() + // Search buffer. + if i := bytes.IndexByte(b.buf[b.r:b.w], delim); i >= 0 { + line = b.buf[b.r : b.r+i+1] + b.r += i + 1 + break } - n := b.Buffered() - b.fill() - - // Search new part of buffer - if i := bytes.IndexByte(b.buf[n:b.w], delim); i >= 0 { - line := b.buf[0 : n+i+1] - b.r = n + i + 1 - return line, nil + // Pending error? + if b.err != nil { + line = b.buf[b.r:b.w] + b.r = b.w + err = b.readErr() + break } - // Buffer is full? + // Buffer full? if b.Buffered() >= len(b.buf) { b.r = b.w - return b.buf, ErrBufferFull + line = b.buf + err = ErrBufferFull + break } + + b.fill() // buffer is not full + } + + // Handle last byte, if any. + if i := len(line) - 1; i >= 0 { + b.lastByte = int(line[i]) + b.lastRuneSize = -1 } + + return } // ReadLine is a low-level line-reading primitive. Most callers should use @@ -301,6 +317,9 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err error) { // // The text returned from ReadLine does not include the line end ("\r\n" or "\n"). // No indication or error is given if the input ends without a final line end. +// Calling UnreadByte after ReadLine will always unread the last byte read +// (possibly a character belonging to the line end) even if that byte is not +// part of the line returned by ReadLine. func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) { line, err = b.ReadSlice('\n') if err == ErrBufferFull { @@ -410,12 +429,24 @@ func (b *Reader) WriteTo(w io.Writer) (n int64, err error) { return n, err } - for b.fill(); b.r < b.w; b.fill() { + if w, ok := w.(io.ReaderFrom); ok { + m, err := w.ReadFrom(b.rd) + n += m + return n, err + } + + if b.w-b.r < len(b.buf) { + b.fill() // buffer not full + } + + for b.r < b.w { + // b.r < b.w => buffer is not empty m, err := b.writeBuf(w) n += m if err != nil { return n, err } + b.fill() // buffer is empty } if b.err == io.EOF { @@ -425,9 +456,14 @@ func (b *Reader) WriteTo(w io.Writer) (n int64, err error) { return n, b.readErr() } +var errNegativeWrite = errors.New("bufio: writer returned negative count from Write") + // writeBuf writes the Reader's buffer to the writer. func (b *Reader) writeBuf(w io.Writer) (int64, error) { n, err := w.Write(b.buf[b.r:b.w]) + if n < 0 { + panic(errNegativeWrite) + } b.r += n return int64(n), err } @@ -619,9 +655,16 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) { return n, err1 } } - m, err = r.Read(b.buf[b.n:]) - if m == 0 { - break + nr := 0 + for nr < maxConsecutiveEmptyReads { + m, err = r.Read(b.buf[b.n:]) + if m != 0 || err != nil { + break + } + nr++ + } + if nr == maxConsecutiveEmptyReads { + return n, io.ErrNoProgress } b.n += m n += int64(m) diff --git a/libgo/go/bufio/bufio_test.go b/libgo/go/bufio/bufio_test.go index 41bd3d4563..550dac9173 100644 --- a/libgo/go/bufio/bufio_test.go +++ b/libgo/go/bufio/bufio_test.go @@ -14,6 +14,7 @@ import ( "strings" "testing" "testing/iotest" + "time" "unicode/utf8" ) @@ -30,9 +31,6 @@ func newRot13Reader(r io.Reader) *rot13Reader { func (r13 *rot13Reader) Read(p []byte) (int, error) { n, err := r13.r.Read(p) - if err != nil { - return n, err - } for i := 0; i < n; i++ { c := p[i] | 0x20 // lowercase byte if 'a' <= c && c <= 'm' { @@ -41,7 +39,7 @@ func (r13 *rot13Reader) Read(p []byte) (int, error) { p[i] -= 13 } } - return n, nil + return n, err } // Call ReadByte to accumulate the text of a file @@ -65,12 +63,12 @@ func readBytes(buf *Reader) string { func TestReaderSimple(t *testing.T) { data := "hello world" - b := NewReader(bytes.NewBufferString(data)) + b := NewReader(strings.NewReader(data)) if s := readBytes(b); s != "hello world" { t.Errorf("simple hello world test failed: got %q", s) } - b = NewReader(newRot13Reader(bytes.NewBufferString(data))) + b = NewReader(newRot13Reader(strings.NewReader(data))) if s := readBytes(b); s != "uryyb jbeyq" { t.Errorf("rot13 hello world test failed: got %q", s) } @@ -139,7 +137,7 @@ var bufreaders = []bufReader{ const minReadBufferSize = 16 var bufsizes = []int{ - minReadBufferSize, 23, 32, 46, 64, 93, 128, 1024, 4096, + 0, minReadBufferSize, 23, 32, 46, 64, 93, 128, 1024, 4096, } func TestReader(t *testing.T) { @@ -161,7 +159,7 @@ func TestReader(t *testing.T) { readmaker := readMakers[i] bufreader := bufreaders[j] bufsize := bufsizes[k] - read := readmaker.fn(bytes.NewBufferString(text)) + read := readmaker.fn(strings.NewReader(text)) buf := NewReaderSize(read, bufsize) s := bufreader.fn(buf) if s != text { @@ -174,6 +172,34 @@ func TestReader(t *testing.T) { } } +type zeroReader struct{} + +func (zeroReader) Read(p []byte) (int, error) { + return 0, nil +} + +func TestZeroReader(t *testing.T) { + var z zeroReader + r := NewReader(z) + + c := make(chan error) + go func() { + _, err := r.ReadByte() + c <- err + }() + + select { + case err := <-c: + if err == nil { + t.Error("error expected") + } else if err != io.ErrNoProgress { + t.Error("unexpected error:", err) + } + case <-time.After(time.Second): + t.Error("test timed out (endless loop in ReadByte?)") + } +} + // A StringReader delivers its data one string segment at a time via Read. type StringReader struct { data []string @@ -228,34 +254,150 @@ func TestReadRune(t *testing.T) { } func TestUnreadRune(t *testing.T) { - got := "" segments := []string{"Hello, world:", "日本語"} - data := strings.Join(segments, "") r := NewReader(&StringReader{data: segments}) + got := "" + want := strings.Join(segments, "") // Normal execution. for { r1, _, err := r.ReadRune() if err != nil { if err != io.EOF { - t.Error("unexpected EOF") + t.Error("unexpected error on ReadRune:", err) } break } got += string(r1) - // Put it back and read it again + // Put it back and read it again. if err = r.UnreadRune(); err != nil { - t.Error("unexpected error on UnreadRune:", err) + t.Fatal("unexpected error on UnreadRune:", err) } r2, _, err := r.ReadRune() if err != nil { - t.Error("unexpected error reading after unreading:", err) + t.Fatal("unexpected error reading after unreading:", err) } if r1 != r2 { - t.Errorf("incorrect rune after unread: got %c wanted %c", r1, r2) + t.Fatalf("incorrect rune after unread: got %c, want %c", r1, r2) } } - if got != data { - t.Errorf("want=%q got=%q", data, got) + if got != want { + t.Errorf("got %q, want %q", got, want) + } +} + +func TestUnreadByte(t *testing.T) { + segments := []string{"Hello, ", "world"} + r := NewReader(&StringReader{data: segments}) + got := "" + want := strings.Join(segments, "") + // Normal execution. + for { + b1, err := r.ReadByte() + if err != nil { + if err != io.EOF { + t.Error("unexpected error on ReadByte:", err) + } + break + } + got += string(b1) + // Put it back and read it again. + if err = r.UnreadByte(); err != nil { + t.Fatal("unexpected error on UnreadByte:", err) + } + b2, err := r.ReadByte() + if err != nil { + t.Fatal("unexpected error reading after unreading:", err) + } + if b1 != b2 { + t.Fatalf("incorrect byte after unread: got %q, want %q", b1, b2) + } + } + if got != want { + t.Errorf("got %q, want %q", got, want) + } +} + +func TestUnreadByteMultiple(t *testing.T) { + segments := []string{"Hello, ", "world"} + data := strings.Join(segments, "") + for n := 0; n <= len(data); n++ { + r := NewReader(&StringReader{data: segments}) + // Read n bytes. + for i := 0; i < n; i++ { + b, err := r.ReadByte() + if err != nil { + t.Fatalf("n = %d: unexpected error on ReadByte: %v", n, err) + } + if b != data[i] { + t.Fatalf("n = %d: incorrect byte returned from ReadByte: got %q, want %q", n, b, data[i]) + } + } + // Unread one byte if there is one. + if n > 0 { + if err := r.UnreadByte(); err != nil { + t.Errorf("n = %d: unexpected error on UnreadByte: %v", n, err) + } + } + // Test that we cannot unread any further. + if err := r.UnreadByte(); err == nil { + t.Errorf("n = %d: expected error on UnreadByte", n) + } + } +} + +func TestUnreadByteOthers(t *testing.T) { + // A list of readers to use in conjunction with UnreadByte. + var readers = []func(*Reader, byte) ([]byte, error){ + (*Reader).ReadBytes, + (*Reader).ReadSlice, + func(r *Reader, delim byte) ([]byte, error) { + data, err := r.ReadString(delim) + return []byte(data), err + }, + // ReadLine doesn't fit the data/pattern easily + // so we leave it out. It should be covered via + // the ReadSlice test since ReadLine simply calls + // ReadSlice, and it's that function that handles + // the last byte. + } + + // Try all readers with UnreadByte. + for rno, read := range readers { + // Some input data that is longer than the minimum reader buffer size. + const n = 10 + var buf bytes.Buffer + for i := 0; i < n; i++ { + buf.WriteString("abcdefg") + } + + r := NewReaderSize(&buf, minReadBufferSize) + readTo := func(delim byte, want string) { + data, err := read(r, delim) + if err != nil { + t.Fatalf("#%d: unexpected error reading to %c: %v", rno, delim, err) + } + if got := string(data); got != want { + t.Fatalf("#%d: got %q, want %q", rno, got, want) + } + } + + // Read the data with occasional UnreadByte calls. + for i := 0; i < n; i++ { + readTo('d', "abcd") + for j := 0; j < 3; j++ { + if err := r.UnreadByte(); err != nil { + t.Fatalf("#%d: unexpected error on UnreadByte: %v", rno, err) + } + readTo('d', "d") + } + readTo('g', "efg") + } + + // All data should have been read. + _, err := r.ReadByte() + if err != io.EOF { + t.Errorf("#%d: got error %v; want EOF", rno, err) + } } } @@ -293,7 +435,7 @@ func TestUnreadRuneError(t *testing.T) { if err != nil { t.Error("unexpected error on ReadRune (2):", err) } - for _ = range buf { + for range buf { _, err = r.ReadByte() if err != nil { t.Error("unexpected error on ReadByte (2):", err) @@ -318,6 +460,18 @@ func TestUnreadRuneError(t *testing.T) { if r.UnreadRune() == nil { t.Error("expected error after UnreadByte (3)") } + // Test error after ReadSlice. + _, _, err = r.ReadRune() // reset state + if err != nil { + t.Error("unexpected error on ReadRune (4):", err) + } + _, err = r.ReadSlice(0) + if err != io.EOF { + t.Error("unexpected error on ReadSlice (4):", err) + } + if r.UnreadRune() == nil { + t.Error("expected error after ReadSlice (4)") + } } func TestUnreadRuneAtEOF(t *testing.T) { @@ -447,7 +601,7 @@ func TestWriteErrors(t *testing.T) { func TestNewReaderSizeIdempotent(t *testing.T) { const BufSize = 1000 - b := NewReaderSize(bytes.NewBufferString("hello world"), BufSize) + b := NewReaderSize(strings.NewReader("hello world"), BufSize) // Does it recognize itself? b1 := NewReaderSize(b, BufSize) if b1 != b { @@ -516,6 +670,9 @@ func TestPeek(t *testing.T) { if s, err := buf.Peek(4); string(s) != "abcd" || err != nil { t.Fatalf("want %q got %q, err=%v", "abcd", string(s), err) } + if _, err := buf.Peek(-1); err != ErrNegativeCount { + t.Fatalf("want ErrNegativeCount got %v", err) + } if _, err := buf.Peek(32); err != ErrBufferFull { t.Fatalf("want ErrBufFull got %v", err) } @@ -642,7 +799,7 @@ func TestLineTooLong(t *testing.T) { for i := 0; i < minReadBufferSize*5/2; i++ { data = append(data, '0'+byte(i%10)) } - buf := bytes.NewBuffer(data) + buf := bytes.NewReader(data) l := NewReaderSize(buf, minReadBufferSize) line, isPrefix, err := l.ReadLine() if !isPrefix || !bytes.Equal(line, data[:minReadBufferSize]) || err != nil { @@ -667,7 +824,7 @@ func TestLineTooLong(t *testing.T) { func TestReadAfterLines(t *testing.T) { line1 := "this is line1" restData := "this is line2\nthis is line 3\n" - inbuf := bytes.NewBuffer([]byte(line1 + "\n" + restData)) + inbuf := bytes.NewReader([]byte(line1 + "\n" + restData)) outbuf := new(bytes.Buffer) maxLineLength := len(line1) + len(restData)/2 l := NewReaderSize(inbuf, maxLineLength) @@ -693,7 +850,7 @@ func TestReadEmptyBuffer(t *testing.T) { } func TestLinesAfterRead(t *testing.T) { - l := NewReaderSize(bytes.NewBuffer([]byte("foo")), minReadBufferSize) + l := NewReaderSize(bytes.NewReader([]byte("foo")), minReadBufferSize) _, err := ioutil.ReadAll(l) if err != nil { t.Error(err) @@ -783,7 +940,7 @@ func createTestInput(n int) []byte { func TestReaderWriteTo(t *testing.T) { input := createTestInput(8192) - r := NewReader(onlyReader{bytes.NewBuffer(input)}) + r := NewReader(onlyReader{bytes.NewReader(input)}) w := new(bytes.Buffer) if n, err := r.WriteTo(w); err != nil || n != int64(len(input)) { t.Fatalf("r.WriteTo(w) = %d, %v, want %d, nil", n, err, len(input)) @@ -842,7 +999,7 @@ func TestWriterReadFrom(t *testing.T) { input := createTestInput(8192) b := new(bytes.Buffer) w := NewWriter(wfunc(b)) - r := rfunc(bytes.NewBuffer(input)) + r := rfunc(bytes.NewReader(input)) if n, err := w.ReadFrom(r); err != nil || n != int64(len(input)) { t.Errorf("ws[%d],rs[%d]: w.ReadFrom(r) = %d, %v, want %d, nil", wi, ri, n, err, len(input)) continue @@ -1021,7 +1178,61 @@ func TestWriterReadFromWhileFull(t *testing.T) { // Use ReadFrom to read in some data. n2, err := w.ReadFrom(strings.NewReader("abcdef")) if n2 != 6 || err != nil { - t.Fatalf("ReadFrom returned (%v, %v), want (6, nil)", n, err) + t.Fatalf("ReadFrom returned (%v, %v), want (6, nil)", n2, err) + } +} + +type emptyThenNonEmptyReader struct { + r io.Reader + n int +} + +func (r *emptyThenNonEmptyReader) Read(p []byte) (int, error) { + if r.n <= 0 { + return r.r.Read(p) + } + r.n-- + return 0, nil +} + +// Test for golang.org/issue/7611 +func TestWriterReadFromUntilEOF(t *testing.T) { + buf := new(bytes.Buffer) + w := NewWriterSize(buf, 5) + + // Partially fill buffer + n, err := w.Write([]byte("0123")) + if n != 4 || err != nil { + t.Fatalf("Write returned (%v, %v), want (4, nil)", n, err) + } + + // Use ReadFrom to read in some data. + r := &emptyThenNonEmptyReader{r: strings.NewReader("abcd"), n: 3} + n2, err := w.ReadFrom(r) + if n2 != 4 || err != nil { + t.Fatalf("ReadFrom returned (%v, %v), want (4, nil)", n2, err) + } + w.Flush() + if got, want := string(buf.Bytes()), "0123abcd"; got != want { + t.Fatalf("buf.Bytes() returned %q, want %q", got, want) + } +} + +func TestWriterReadFromErrNoProgress(t *testing.T) { + buf := new(bytes.Buffer) + w := NewWriterSize(buf, 5) + + // Partially fill buffer + n, err := w.Write([]byte("0123")) + if n != 4 || err != nil { + t.Fatalf("Write returned (%v, %v), want (4, nil)", n, err) + } + + // Use ReadFrom to read in some data. + r := &emptyThenNonEmptyReader{r: strings.NewReader("abcd"), n: 100} + n2, err := w.ReadFrom(r) + if n2 != 0 || err != io.ErrNoProgress { + t.Fatalf("buf.Bytes() returned (%v, %v), want (0, io.ErrNoProgress)", n2, err) } } @@ -1059,81 +1270,114 @@ func TestWriterReset(t *testing.T) { // An onlyReader only implements io.Reader, no matter what other methods the underlying implementation may have. type onlyReader struct { - r io.Reader -} - -func (r onlyReader) Read(b []byte) (int, error) { - return r.r.Read(b) + io.Reader } // An onlyWriter only implements io.Writer, no matter what other methods the underlying implementation may have. type onlyWriter struct { - w io.Writer -} - -func (w onlyWriter) Write(b []byte) (int, error) { - return w.w.Write(b) + io.Writer } func BenchmarkReaderCopyOptimal(b *testing.B) { // Optimal case is where the underlying reader implements io.WriterTo + srcBuf := bytes.NewBuffer(make([]byte, 8192)) + src := NewReader(srcBuf) + dstBuf := new(bytes.Buffer) + dst := onlyWriter{dstBuf} for i := 0; i < b.N; i++ { - b.StopTimer() - src := NewReader(bytes.NewBuffer(make([]byte, 8192))) - dst := onlyWriter{new(bytes.Buffer)} - b.StartTimer() + srcBuf.Reset() + src.Reset(srcBuf) + dstBuf.Reset() io.Copy(dst, src) } } func BenchmarkReaderCopyUnoptimal(b *testing.B) { // Unoptimal case is where the underlying reader doesn't implement io.WriterTo + srcBuf := bytes.NewBuffer(make([]byte, 8192)) + src := NewReader(onlyReader{srcBuf}) + dstBuf := new(bytes.Buffer) + dst := onlyWriter{dstBuf} for i := 0; i < b.N; i++ { - b.StopTimer() - src := NewReader(onlyReader{bytes.NewBuffer(make([]byte, 8192))}) - dst := onlyWriter{new(bytes.Buffer)} - b.StartTimer() + srcBuf.Reset() + src.Reset(onlyReader{srcBuf}) + dstBuf.Reset() io.Copy(dst, src) } } func BenchmarkReaderCopyNoWriteTo(b *testing.B) { + srcBuf := bytes.NewBuffer(make([]byte, 8192)) + srcReader := NewReader(srcBuf) + src := onlyReader{srcReader} + dstBuf := new(bytes.Buffer) + dst := onlyWriter{dstBuf} for i := 0; i < b.N; i++ { - b.StopTimer() - src := onlyReader{NewReader(bytes.NewBuffer(make([]byte, 8192)))} - dst := onlyWriter{new(bytes.Buffer)} - b.StartTimer() + srcBuf.Reset() + srcReader.Reset(srcBuf) + dstBuf.Reset() io.Copy(dst, src) } } +func BenchmarkReaderWriteToOptimal(b *testing.B) { + const bufSize = 16 << 10 + buf := make([]byte, bufSize) + r := bytes.NewReader(buf) + srcReader := NewReaderSize(onlyReader{r}, 1<<10) + if _, ok := ioutil.Discard.(io.ReaderFrom); !ok { + b.Fatal("ioutil.Discard doesn't support ReaderFrom") + } + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + srcReader.Reset(onlyReader{r}) + n, err := srcReader.WriteTo(ioutil.Discard) + if err != nil { + b.Fatal(err) + } + if n != bufSize { + b.Fatalf("n = %d; want %d", n, bufSize) + } + } +} + func BenchmarkWriterCopyOptimal(b *testing.B) { // Optimal case is where the underlying writer implements io.ReaderFrom + srcBuf := bytes.NewBuffer(make([]byte, 8192)) + src := onlyReader{srcBuf} + dstBuf := new(bytes.Buffer) + dst := NewWriter(dstBuf) for i := 0; i < b.N; i++ { - b.StopTimer() - src := onlyReader{bytes.NewBuffer(make([]byte, 8192))} - dst := NewWriter(new(bytes.Buffer)) - b.StartTimer() + srcBuf.Reset() + dstBuf.Reset() + dst.Reset(dstBuf) io.Copy(dst, src) } } func BenchmarkWriterCopyUnoptimal(b *testing.B) { + srcBuf := bytes.NewBuffer(make([]byte, 8192)) + src := onlyReader{srcBuf} + dstBuf := new(bytes.Buffer) + dst := NewWriter(onlyWriter{dstBuf}) for i := 0; i < b.N; i++ { - b.StopTimer() - src := onlyReader{bytes.NewBuffer(make([]byte, 8192))} - dst := NewWriter(onlyWriter{new(bytes.Buffer)}) - b.StartTimer() + srcBuf.Reset() + dstBuf.Reset() + dst.Reset(onlyWriter{dstBuf}) io.Copy(dst, src) } } func BenchmarkWriterCopyNoReadFrom(b *testing.B) { + srcBuf := bytes.NewBuffer(make([]byte, 8192)) + src := onlyReader{srcBuf} + dstBuf := new(bytes.Buffer) + dstWriter := NewWriter(dstBuf) + dst := onlyWriter{dstWriter} for i := 0; i < b.N; i++ { - b.StopTimer() - src := onlyReader{bytes.NewBuffer(make([]byte, 8192))} - dst := onlyWriter{NewWriter(new(bytes.Buffer))} - b.StartTimer() + srcBuf.Reset() + dstBuf.Reset() + dstWriter.Reset(dstBuf) io.Copy(dst, src) } } diff --git a/libgo/go/bufio/scan.go b/libgo/go/bufio/scan.go index 423505fbcb..364d159613 100644 --- a/libgo/go/bufio/scan.go +++ b/libgo/go/bufio/scan.go @@ -36,6 +36,7 @@ type Scanner struct { start int // First non-processed byte in buf. end int // End of data in buf. err error // Sticky error. + empties int // Count of successive empty tokens. } // SplitFunc is the signature of the split function used to tokenize the @@ -64,8 +65,9 @@ var ( ) const ( - // Maximum size used to buffer a token. The actual maximum token size - // may be smaller as the buffer may need to include, for instance, a newline. + // MaxScanTokenSize is the maximum size used to buffer a token. + // The actual maximum token size may be smaller as the buffer + // may need to include, for instance, a newline. MaxScanTokenSize = 64 * 1024 ) @@ -107,11 +109,15 @@ func (s *Scanner) Text() string { // After Scan returns false, the Err method will return any error that // occurred during scanning, except that if it was io.EOF, Err // will return nil. +// Split panics if the split function returns 100 empty tokens without +// advancing the input. This is a common error mode for scanners. func (s *Scanner) Scan() bool { // Loop until we have a token. for { // See if we can get a token with what we already have. - if s.end > s.start { + // If we've run out of data but have an error, give the split function + // a chance to recover any remaining, possibly empty token. + if s.end > s.start || s.err != nil { advance, token, err := s.split(s.buf[s.start:s.end], s.err != nil) if err != nil { s.setErr(err) @@ -122,6 +128,15 @@ func (s *Scanner) Scan() bool { } s.token = token if token != nil { + if s.err == nil || advance > 0 { + s.empties = 0 + } else { + // Returning tokens not advancing input at EOF. + s.empties++ + if s.empties > 100 { + panic("bufio.Scan: 100 empty tokens without progressing") + } + } return true } } @@ -135,7 +150,7 @@ func (s *Scanner) Scan() bool { } // Must read more data. // First, shift data to beginning of buffer if there's lots of empty space - // or space is neded. + // or space is needed. if s.start > 0 && (s.end == len(s.buf) || s.start > len(s.buf)/2) { copy(s.buf, s.buf[s.start:s.end]) s.end -= s.start @@ -169,10 +184,11 @@ func (s *Scanner) Scan() bool { break } if n > 0 { + s.empties = 0 break } loop++ - if loop > 100 { + if loop > maxConsecutiveEmptyReads { s.setErr(io.ErrNoProgress) break } @@ -306,7 +322,7 @@ func isSpace(r rune) bool { return true } switch r { - case '\u1680', '\u180e', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000': + case '\u1680', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000': return true } return false @@ -326,9 +342,6 @@ func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) { break } } - if atEOF && len(data) == 0 { - return 0, nil, nil - } // Scan until space, marking end of word. for width, i := 0, start; i < len(data); i += width { var r rune @@ -342,5 +355,5 @@ func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) { return len(data), data[start:], nil } // Request more data. - return 0, nil, nil + return start, nil, nil } diff --git a/libgo/go/bufio/scan_test.go b/libgo/go/bufio/scan_test.go index c1483b2685..eea87cbf7b 100644 --- a/libgo/go/bufio/scan_test.go +++ b/libgo/go/bufio/scan_test.go @@ -15,6 +15,8 @@ import ( "unicode/utf8" ) +const smallMaxTokenSize = 256 // Much smaller for more efficient testing. + // Test white space table matches the Unicode definition. func TestSpace(t *testing.T) { for r := rune(0); r <= utf8.MaxRune; r++ { @@ -38,7 +40,7 @@ var scanTests = []string{ func TestScanByte(t *testing.T) { for n, test := range scanTests { - buf := bytes.NewBufferString(test) + buf := strings.NewReader(test) s := NewScanner(buf) s.Split(ScanBytes) var i int @@ -60,7 +62,7 @@ func TestScanByte(t *testing.T) { // Test that the rune splitter returns same sequence of runes (not bytes) as for range string. func TestScanRune(t *testing.T) { for n, test := range scanTests { - buf := bytes.NewBufferString(test) + buf := strings.NewReader(test) s := NewScanner(buf) s.Split(ScanRunes) var i, runeCount int @@ -104,7 +106,7 @@ var wordScanTests = []string{ // Test that the word splitter returns the same data as strings.Fields. func TestScanWords(t *testing.T) { for n, test := range wordScanTests { - buf := bytes.NewBufferString(test) + buf := strings.NewReader(test) s := NewScanner(buf) s.Split(ScanWords) words := strings.Fields(test) @@ -135,7 +137,7 @@ func TestScanWords(t *testing.T) { // reads in Scanner.Scan. type slowReader struct { max int - buf *bytes.Buffer + buf io.Reader } func (sr *slowReader) Read(p []byte) (n int, err error) { @@ -172,7 +174,6 @@ func genLine(buf *bytes.Buffer, lineNum, n int, addNewline bool) { // Test the line splitter, including some carriage returns but no long lines. func TestScanLongLines(t *testing.T) { - const smallMaxTokenSize = 256 // Much smaller for more efficient testing. // Build a buffer of lots of line lengths up to but not exceeding smallMaxTokenSize. tmp := new(bytes.Buffer) buf := new(bytes.Buffer) @@ -248,7 +249,7 @@ func TestScanLineTooLong(t *testing.T) { // Test that the line splitter handles a final line without a newline. func testNoNewline(text string, lines []string, t *testing.T) { - buf := bytes.NewBufferString(text) + buf := strings.NewReader(text) s := NewScanner(&slowReader{7, buf}) s.Split(ScanLines) for lineNum := 0; s.Scan(); lineNum++ { @@ -277,7 +278,7 @@ func TestScanLineNoNewline(t *testing.T) { testNoNewline(text, lines, t) } -// Test that the line splitter handles a final line with a carriage return but nonewline. +// Test that the line splitter handles a final line with a carriage return but no newline. func TestScanLineReturnButNoNewline(t *testing.T) { const text = "abcdefghijklmn\nopqrstuvwxyz\r" lines := []string{ @@ -328,7 +329,7 @@ func TestSplitError(t *testing.T) { } // Read the data. const text = "abcdefghijklmnopqrstuvwxyz" - buf := bytes.NewBufferString(text) + buf := strings.NewReader(text) s := NewScanner(&slowReader{1, buf}) s.Split(errorSplit) var i int @@ -404,3 +405,120 @@ func TestBadReader(t *testing.T) { t.Errorf("unexpected error: %v", err) } } + +func TestScanWordsExcessiveWhiteSpace(t *testing.T) { + const word = "ipsum" + s := strings.Repeat(" ", 4*smallMaxTokenSize) + word + scanner := NewScanner(strings.NewReader(s)) + scanner.MaxTokenSize(smallMaxTokenSize) + scanner.Split(ScanWords) + if !scanner.Scan() { + t.Fatalf("scan failed: %v", scanner.Err()) + } + if token := scanner.Text(); token != word { + t.Fatalf("unexpected token: %v", token) + } +} + +// Test that empty tokens, including at end of line or end of file, are found by the scanner. +// Issue 8672: Could miss final empty token. + +func commaSplit(data []byte, atEOF bool) (advance int, token []byte, err error) { + for i := 0; i < len(data); i++ { + if data[i] == ',' { + return i + 1, data[:i], nil + } + } + if !atEOF { + return 0, nil, nil + } + return 0, data, nil +} + +func TestEmptyTokens(t *testing.T) { + s := NewScanner(strings.NewReader("1,2,3,")) + values := []string{"1", "2", "3", ""} + s.Split(commaSplit) + var i int + for i = 0; i < len(values); i++ { + if !s.Scan() { + break + } + if s.Text() != values[i] { + t.Errorf("%d: expected %q got %q", i, values[i], s.Text()) + } + } + if i != len(values) { + t.Errorf("got %d fields, expected %d", i, len(values)) + } + if err := s.Err(); err != nil { + t.Fatal(err) + } +} + +func loopAtEOFSplit(data []byte, atEOF bool) (advance int, token []byte, err error) { + if len(data) > 0 { + return 1, data[:1], nil + } + return 0, data, nil +} + +func TestDontLoopForever(t *testing.T) { + s := NewScanner(strings.NewReader("abc")) + s.Split(loopAtEOFSplit) + // Expect a panic + defer func() { + err := recover() + if err == nil { + t.Fatal("should have panicked") + } + if msg, ok := err.(string); !ok || !strings.Contains(msg, "empty tokens") { + panic(err) + } + }() + for count := 0; s.Scan(); count++ { + if count > 1000 { + t.Fatal("looping") + } + } + if s.Err() != nil { + t.Fatal("after scan:", s.Err()) + } +} + +func TestBlankLines(t *testing.T) { + s := NewScanner(strings.NewReader(strings.Repeat("\n", 1000))) + for count := 0; s.Scan(); count++ { + if count > 2000 { + t.Fatal("looping") + } + } + if s.Err() != nil { + t.Fatal("after scan:", s.Err()) + } +} + +type countdown int + +func (c *countdown) split(data []byte, atEOF bool) (advance int, token []byte, err error) { + if *c > 0 { + *c-- + return 1, data[:1], nil + } + return 0, nil, nil +} + +// Check that the looping-at-EOF check doesn't trigger for merely empty tokens. +func TestEmptyLinesOK(t *testing.T) { + c := countdown(10000) + s := NewScanner(strings.NewReader(strings.Repeat("\n", 10000))) + s.Split(c.split) + for s.Scan() { + } + if s.Err() != nil { + t.Fatal("after scan:", s.Err()) + } + if c != 0 { + t.Fatalf("stopped with %d left to process", c) + } +} diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go index 01a5d9ae4e..7634707b3c 100644 --- a/libgo/go/bytes/bytes.go +++ b/libgo/go/bytes/bytes.go @@ -265,8 +265,10 @@ func Fields(s []byte) [][]byte { // FieldsFunc interprets s as a sequence of UTF-8-encoded Unicode code points. // It splits the slice s at each run of code points c satisfying f(c) and -// returns a slice of subslices of s. If no code points in s satisfy f(c), an -// empty slice is returned. +// returns a slice of subslices of s. If all code points in s satisfy f(c), or +// len(s) == 0, an empty slice is returned. +// FieldsFunc makes no guarantees about the order in which it calls f(c). +// If f does not return consistent results for a given c, FieldsFunc may crash. func FieldsFunc(s []byte, f func(rune) bool) [][]byte { n := 0 inField := false @@ -356,7 +358,11 @@ func Map(mapping func(r rune) rune, s []byte) []byte { } r = mapping(r) if r >= 0 { - if nbytes+utf8.RuneLen(r) > maxbytes { + rl := utf8.RuneLen(r) + if rl < 0 { + rl = len(string(utf8.RuneError)) + } + if nbytes+rl > maxbytes { // Grow the buffer. maxbytes = maxbytes*2 + utf8.UTFMax nb := make([]byte, maxbytes) @@ -373,9 +379,10 @@ func Map(mapping func(r rune) rune, s []byte) []byte { // Repeat returns a new byte slice consisting of count copies of b. func Repeat(b []byte, count int) []byte { nb := make([]byte, len(b)*count) - bp := 0 - for i := 0; i < count; i++ { - bp += copy(nb[bp:], b) + bp := copy(nb, b) + for bp < len(nb) { + copy(nb[bp:], nb[:bp]) + bp *= 2 } return nb } @@ -600,6 +607,9 @@ func Runes(s []byte) []rune { // Replace returns a copy of the slice s with the first n // non-overlapping instances of old replaced by new. +// If old is empty, it matches at the beginning of the slice +// and after each UTF-8 sequence, yielding up to k+1 replacements +// for a k-rune slice. // If n < 0, there is no limit on the number of replacements. func Replace(s, old, new []byte, n int) []byte { m := 0 diff --git a/libgo/go/bytes/bytes_test.go b/libgo/go/bytes/bytes_test.go index ab5da4fbf0..980c41d754 100644 --- a/libgo/go/bytes/bytes_test.go +++ b/libgo/go/bytes/bytes_test.go @@ -785,6 +785,16 @@ func TestMap(t *testing.T) { if string(m) != expect { t.Errorf("drop: expected %q got %q", expect, m) } + + // 6. Invalid rune + invalidRune := func(r rune) rune { + return utf8.MaxRune + 1 + } + m = Map(invalidRune, []byte("x")) + expect = "\uFFFD" + if string(m) != expect { + t.Errorf("invalidRune: expected %q got %q", expect, m) + } } func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTests) } @@ -1073,6 +1083,8 @@ var TitleTests = []TitleTest{ {"123a456", "123a456"}, {"double-blind", "Double-Blind"}, {"ÿøû", "Ÿøû"}, + {"with_underscore", "With_underscore"}, + {"unicode \xe2\x80\xa8 line separator", "Unicode \xe2\x80\xa8 Line Separator"}, } func TestTitle(t *testing.T) { @@ -1132,7 +1144,7 @@ func TestEqualFold(t *testing.T) { func TestBufferGrowNegative(t *testing.T) { defer func() { if err := recover(); err == nil { - t.Fatal("Grow(-1) should have paniced") + t.Fatal("Grow(-1) should have panicked") } }() var b Buffer @@ -1142,7 +1154,7 @@ func TestBufferGrowNegative(t *testing.T) { func TestBufferTruncateNegative(t *testing.T) { defer func() { if err := recover(); err == nil { - t.Fatal("Truncate(-1) should have paniced") + t.Fatal("Truncate(-1) should have panicked") } }() var b Buffer @@ -1152,7 +1164,7 @@ func TestBufferTruncateNegative(t *testing.T) { func TestBufferTruncateOutOfRange(t *testing.T) { defer func() { if err := recover(); err == nil { - t.Fatal("Truncate(20) should have paniced") + t.Fatal("Truncate(20) should have panicked") } }() var b Buffer @@ -1160,6 +1172,24 @@ func TestBufferTruncateOutOfRange(t *testing.T) { b.Truncate(20) } +var containsTests = []struct { + b, subslice []byte + want bool +}{ + {[]byte("hello"), []byte("hel"), true}, + {[]byte("日本語"), []byte("日本"), true}, + {[]byte("hello"), []byte("Hello, world"), false}, + {[]byte("東京"), []byte("京東"), false}, +} + +func TestContains(t *testing.T) { + for _, tt := range containsTests { + if got := Contains(tt.b, tt.subslice); got != tt.want { + t.Errorf("Contains(%q, %q) = %v, want %v", tt.b, tt.subslice, got, tt.want) + } + } +} + var makeFieldsInput = func() []byte { x := make([]byte, 1<<20) // Input is ~10% space, ~10% 2-byte UTF-8, rest ASCII non-space. @@ -1202,3 +1232,9 @@ func BenchmarkTrimSpace(b *testing.B) { TrimSpace(s) } } + +func BenchmarkRepeat(b *testing.B) { + for i := 0; i < b.N; i++ { + Repeat([]byte("-"), 80) + } +} diff --git a/libgo/go/bytes/compare_test.go b/libgo/go/bytes/compare_test.go index 0a36f5ad39..63522374ee 100644 --- a/libgo/go/bytes/compare_test.go +++ b/libgo/go/bytes/compare_test.go @@ -1,3 +1,7 @@ +// 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 bytes_test import ( diff --git a/libgo/go/bytes/reader.go b/libgo/go/bytes/reader.go index 77511b9455..d2d40fa7ca 100644 --- a/libgo/go/bytes/reader.go +++ b/libgo/go/bytes/reader.go @@ -16,40 +16,41 @@ import ( // Unlike a Buffer, a Reader is read-only and supports seeking. type Reader struct { s []byte - i int // current reading index - prevRune int // index of previous rune; or < 0 + i int64 // current reading index + prevRune int // index of previous rune; or < 0 } // Len returns the number of bytes of the unread portion of the // slice. func (r *Reader) Len() int { - if r.i >= len(r.s) { + if r.i >= int64(len(r.s)) { return 0 } - return len(r.s) - r.i + return int(int64(len(r.s)) - r.i) } func (r *Reader) Read(b []byte) (n int, err error) { if len(b) == 0 { return 0, nil } - if r.i >= len(r.s) { + if r.i >= int64(len(r.s)) { return 0, io.EOF } - n = copy(b, r.s[r.i:]) - r.i += n r.prevRune = -1 + n = copy(b, r.s[r.i:]) + r.i += int64(n) return } func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) { + // cannot modify state - see io.ReaderAt if off < 0 { - return 0, errors.New("bytes: invalid offset") + return 0, errors.New("bytes.Reader.ReadAt: negative offset") } if off >= int64(len(r.s)) { return 0, io.EOF } - n = copy(b, r.s[int(off):]) + n = copy(b, r.s[off:]) if n < len(b) { err = io.EOF } @@ -57,49 +58,51 @@ func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) { } func (r *Reader) ReadByte() (b byte, err error) { - if r.i >= len(r.s) { + r.prevRune = -1 + if r.i >= int64(len(r.s)) { return 0, io.EOF } b = r.s[r.i] r.i++ - r.prevRune = -1 return } func (r *Reader) UnreadByte() error { + r.prevRune = -1 if r.i <= 0 { - return errors.New("bytes.Reader: at beginning of slice") + return errors.New("bytes.Reader.UnreadByte: at beginning of slice") } r.i-- - r.prevRune = -1 return nil } func (r *Reader) ReadRune() (ch rune, size int, err error) { - if r.i >= len(r.s) { + if r.i >= int64(len(r.s)) { + r.prevRune = -1 return 0, 0, io.EOF } - r.prevRune = r.i + r.prevRune = int(r.i) if c := r.s[r.i]; c < utf8.RuneSelf { r.i++ return rune(c), 1, nil } ch, size = utf8.DecodeRune(r.s[r.i:]) - r.i += size + r.i += int64(size) return } func (r *Reader) UnreadRune() error { if r.prevRune < 0 { - return errors.New("bytes.Reader: previous operation was not ReadRune") + return errors.New("bytes.Reader.UnreadRune: previous operation was not ReadRune") } - r.i = r.prevRune + r.i = int64(r.prevRune) r.prevRune = -1 return nil } // Seek implements the io.Seeker interface. func (r *Reader) Seek(offset int64, whence int) (int64, error) { + r.prevRune = -1 var abs int64 switch whence { case 0: @@ -109,22 +112,19 @@ func (r *Reader) Seek(offset int64, whence int) (int64, error) { case 2: abs = int64(len(r.s)) + offset default: - return 0, errors.New("bytes: invalid whence") + return 0, errors.New("bytes.Reader.Seek: invalid whence") } if abs < 0 { - return 0, errors.New("bytes: negative position") - } - if abs >= 1<<31 { - return 0, errors.New("bytes: position out of range") + return 0, errors.New("bytes.Reader.Seek: negative position") } - r.i = int(abs) + r.i = abs return abs, nil } // WriteTo implements the io.WriterTo interface. func (r *Reader) WriteTo(w io.Writer) (n int64, err error) { r.prevRune = -1 - if r.i >= len(r.s) { + if r.i >= int64(len(r.s)) { return 0, nil } b := r.s[r.i:] @@ -132,7 +132,7 @@ func (r *Reader) WriteTo(w io.Writer) (n int64, err error) { if m > len(b) { panic("bytes.Reader.WriteTo: invalid Write count") } - r.i += m + r.i += int64(m) n = int64(m) if m != len(b) && err == nil { err = io.ErrShortWrite diff --git a/libgo/go/bytes/reader_test.go b/libgo/go/bytes/reader_test.go index 19f014da03..d3dce53499 100644 --- a/libgo/go/bytes/reader_test.go +++ b/libgo/go/bytes/reader_test.go @@ -10,6 +10,7 @@ import ( "io" "io/ioutil" "os" + "sync" "testing" ) @@ -26,9 +27,9 @@ func TestReader(t *testing.T) { {seek: os.SEEK_SET, off: 0, n: 20, want: "0123456789"}, {seek: os.SEEK_SET, off: 1, n: 1, want: "1"}, {seek: os.SEEK_CUR, off: 1, wantpos: 3, n: 2, want: "34"}, - {seek: os.SEEK_SET, off: -1, seekerr: "bytes: negative position"}, - {seek: os.SEEK_SET, off: 1<<31 - 1}, - {seek: os.SEEK_CUR, off: 1, seekerr: "bytes: position out of range"}, + {seek: os.SEEK_SET, off: -1, seekerr: "bytes.Reader.Seek: negative position"}, + {seek: os.SEEK_SET, off: 1 << 33, wantpos: 1 << 33}, + {seek: os.SEEK_CUR, off: 1, wantpos: 1<<33 + 1}, {seek: os.SEEK_SET, n: 5, want: "01234"}, {seek: os.SEEK_CUR, n: 5, want: "56789"}, {seek: os.SEEK_END, off: -1, n: 1, wantpos: 9, want: "9"}, @@ -60,6 +61,16 @@ func TestReader(t *testing.T) { } } +func TestReadAfterBigSeek(t *testing.T) { + r := NewReader([]byte("0123456789")) + if _, err := r.Seek(1<<31+5, os.SEEK_SET); err != nil { + t.Fatal(err) + } + if n, err := r.Read(make([]byte, 10)); n != 0 || err != io.EOF { + t.Errorf("Read = %d, %v; want 0, EOF", n, err) + } +} + func TestReaderAt(t *testing.T) { r := NewReader([]byte("0123456789")) tests := []struct { @@ -73,7 +84,7 @@ func TestReaderAt(t *testing.T) { {1, 9, "123456789", nil}, {11, 10, "", io.EOF}, {0, 0, "", nil}, - {-1, 0, "", "bytes: invalid offset"}, + {-1, 0, "", "bytes.Reader.ReadAt: negative offset"}, } for i, tt := range tests { b := make([]byte, tt.n) @@ -88,6 +99,43 @@ func TestReaderAt(t *testing.T) { } } +func TestReaderAtConcurrent(t *testing.T) { + // Test for the race detector, to verify ReadAt doesn't mutate + // any state. + r := NewReader([]byte("0123456789")) + var wg sync.WaitGroup + for i := 0; i < 5; i++ { + wg.Add(1) + go func(i int) { + defer wg.Done() + var buf [1]byte + r.ReadAt(buf[:], int64(i)) + }(i) + } + wg.Wait() +} + +func TestEmptyReaderConcurrent(t *testing.T) { + // Test for the race detector, to verify a Read that doesn't yield any bytes + // is okay to use from multiple goroutines. This was our historic behavior. + // See golang.org/issue/7856 + r := NewReader([]byte{}) + var wg sync.WaitGroup + for i := 0; i < 5; i++ { + wg.Add(2) + go func() { + defer wg.Done() + var buf [1]byte + r.Read(buf[:]) + }() + go func() { + defer wg.Done() + r.Read(nil) + }() + } + wg.Wait() +} + func TestReaderWriteTo(t *testing.T) { for i := 0; i < 30; i += 3 { var l int @@ -133,6 +181,32 @@ func TestReaderLen(t *testing.T) { } } +var UnreadRuneErrorTests = []struct { + name string + f func(*Reader) +}{ + {"Read", func(r *Reader) { r.Read([]byte{0}) }}, + {"ReadByte", func(r *Reader) { r.ReadByte() }}, + {"UnreadRune", func(r *Reader) { r.UnreadRune() }}, + {"Seek", func(r *Reader) { r.Seek(0, 1) }}, + {"WriteTo", func(r *Reader) { r.WriteTo(&Buffer{}) }}, +} + +func TestUnreadRuneError(t *testing.T) { + for _, tt := range UnreadRuneErrorTests { + reader := NewReader([]byte("0123456789")) + if _, _, err := reader.ReadRune(); err != nil { + // should not happen + t.Fatal(err) + } + tt.f(reader) + err := reader.UnreadRune() + if err == nil { + t.Errorf("Unreading after %s: expected error", tt.name) + } + } +} + func TestReaderDoubleUnreadRune(t *testing.T) { buf := NewBuffer([]byte("groucho")) if _, _, err := buf.ReadRune(); err != nil { diff --git a/libgo/go/cmd/cgo/ast.go b/libgo/go/cmd/cgo/ast.go new file mode 100644 index 0000000000..10e2278a1d --- /dev/null +++ b/libgo/go/cmd/cgo/ast.go @@ -0,0 +1,463 @@ +// 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. + +// Parse input AST and prepare Prog structure. + +package main + +import ( + "fmt" + "go/ast" + "go/parser" + "go/scanner" + "go/token" + "os" + "path/filepath" + "strings" +) + +func parse(name string, flags parser.Mode) *ast.File { + ast1, err := parser.ParseFile(fset, name, nil, flags) + if err != nil { + if list, ok := err.(scanner.ErrorList); ok { + // If err is a scanner.ErrorList, its String will print just + // the first error and then (+n more errors). + // Instead, turn it into a new Error that will return + // details for all the errors. + for _, e := range list { + fmt.Fprintln(os.Stderr, e) + } + os.Exit(2) + } + fatalf("parsing %s: %s", name, err) + } + return ast1 +} + +func sourceLine(n ast.Node) int { + return fset.Position(n.Pos()).Line +} + +// ReadGo populates f with information learned from reading the +// Go source file with the given file name. It gathers the C preamble +// attached to the import "C" comment, a list of references to C.xxx, +// a list of exported functions, and the actual AST, to be rewritten and +// printed. +func (f *File) ReadGo(name string) { + // Create absolute path for file, so that it will be used in error + // messages and recorded in debug line number information. + // This matches the rest of the toolchain. See golang.org/issue/5122. + if aname, err := filepath.Abs(name); err == nil { + name = aname + } + + // Two different parses: once with comments, once without. + // The printer is not good enough at printing comments in the + // right place when we start editing the AST behind its back, + // so we use ast1 to look for the doc comments on import "C" + // and on exported functions, and we use ast2 for translating + // and reprinting. + ast1 := parse(name, parser.ParseComments) + ast2 := parse(name, 0) + + f.Package = ast1.Name.Name + f.Name = make(map[string]*Name) + + // In ast1, find the import "C" line and get any extra C preamble. + sawC := false + for _, decl := range ast1.Decls { + d, ok := decl.(*ast.GenDecl) + if !ok { + continue + } + for _, spec := range d.Specs { + s, ok := spec.(*ast.ImportSpec) + if !ok || string(s.Path.Value) != `"C"` { + continue + } + sawC = true + if s.Name != nil { + error_(s.Path.Pos(), `cannot rename import "C"`) + } + cg := s.Doc + if cg == nil && len(d.Specs) == 1 { + cg = d.Doc + } + if cg != nil { + f.Preamble += fmt.Sprintf("#line %d %q\n", sourceLine(cg), name) + f.Preamble += commentText(cg) + "\n" + } + } + } + if !sawC { + error_(token.NoPos, `cannot find import "C"`) + } + + // In ast2, strip the import "C" line. + w := 0 + for _, decl := range ast2.Decls { + d, ok := decl.(*ast.GenDecl) + if !ok { + ast2.Decls[w] = decl + w++ + continue + } + ws := 0 + for _, spec := range d.Specs { + s, ok := spec.(*ast.ImportSpec) + if !ok || string(s.Path.Value) != `"C"` { + d.Specs[ws] = spec + ws++ + } + } + if ws == 0 { + continue + } + d.Specs = d.Specs[0:ws] + ast2.Decls[w] = d + w++ + } + ast2.Decls = ast2.Decls[0:w] + + // Accumulate pointers to uses of C.x. + if f.Ref == nil { + f.Ref = make([]*Ref, 0, 8) + } + f.walk(ast2, "prog", (*File).saveRef) + + // Accumulate exported functions. + // The comments are only on ast1 but we need to + // save the function bodies from ast2. + // The first walk fills in ExpFunc, and the + // second walk changes the entries to + // refer to ast2 instead. + f.walk(ast1, "prog", (*File).saveExport) + f.walk(ast2, "prog", (*File).saveExport2) + + f.Comments = ast1.Comments + f.AST = ast2 +} + +// Like ast.CommentGroup's Text method but preserves +// leading blank lines, so that line numbers line up. +func commentText(g *ast.CommentGroup) string { + if g == nil { + return "" + } + var pieces []string + for _, com := range g.List { + c := string(com.Text) + // Remove comment markers. + // The parser has given us exactly the comment text. + switch c[1] { + case '/': + //-style comment (no newline at the end) + c = c[2:] + "\n" + case '*': + /*-style comment */ + c = c[2 : len(c)-2] + } + pieces = append(pieces, c) + } + return strings.Join(pieces, "") +} + +// Save references to C.xxx for later processing. +func (f *File) saveRef(x interface{}, context string) { + n, ok := x.(*ast.Expr) + if !ok { + return + } + if sel, ok := (*n).(*ast.SelectorExpr); ok { + // For now, assume that the only instance of capital C is + // when used as the imported package identifier. + // The parser should take care of scoping in the future, + // so that we will be able to distinguish a "top-level C" + // from a local C. + if l, ok := sel.X.(*ast.Ident); ok && l.Name == "C" { + if context == "as2" { + context = "expr" + } + if context == "embed-type" { + error_(sel.Pos(), "cannot embed C type") + } + goname := sel.Sel.Name + if goname == "errno" { + error_(sel.Pos(), "cannot refer to errno directly; see documentation") + return + } + if goname == "_CMalloc" { + error_(sel.Pos(), "cannot refer to C._CMalloc; use C.malloc") + return + } + if goname == "malloc" { + goname = "_CMalloc" + } + name := f.Name[goname] + if name == nil { + name = &Name{ + Go: goname, + } + f.Name[goname] = name + } + f.Ref = append(f.Ref, &Ref{ + Name: name, + Expr: n, + Context: context, + }) + return + } + } +} + +// If a function should be exported add it to ExpFunc. +func (f *File) saveExport(x interface{}, context string) { + n, ok := x.(*ast.FuncDecl) + if !ok { + return + } + + if n.Doc == nil { + return + } + for _, c := range n.Doc.List { + if !strings.HasPrefix(string(c.Text), "//export ") { + continue + } + + name := strings.TrimSpace(string(c.Text[9:])) + if name == "" { + error_(c.Pos(), "export missing name") + } + + if name != n.Name.Name { + error_(c.Pos(), "export comment has wrong name %q, want %q", name, n.Name.Name) + } + + f.ExpFunc = append(f.ExpFunc, &ExpFunc{ + Func: n, + ExpName: name, + }) + break + } +} + +// Make f.ExpFunc[i] point at the Func from this AST instead of the other one. +func (f *File) saveExport2(x interface{}, context string) { + n, ok := x.(*ast.FuncDecl) + if !ok { + return + } + + for _, exp := range f.ExpFunc { + if exp.Func.Name.Name == n.Name.Name { + exp.Func = n + break + } + } +} + +// walk walks the AST x, calling visit(f, x, context) for each node. +func (f *File) walk(x interface{}, context string, visit func(*File, interface{}, string)) { + visit(f, x, context) + switch n := x.(type) { + case *ast.Expr: + f.walk(*n, context, visit) + + // everything else just recurs + default: + error_(token.NoPos, "unexpected type %T in walk", x, visit) + panic("unexpected type") + + case nil: + + // These are ordered and grouped to match ../../go/ast/ast.go + case *ast.Field: + if len(n.Names) == 0 && context == "field" { + f.walk(&n.Type, "embed-type", visit) + } else { + f.walk(&n.Type, "type", visit) + } + case *ast.FieldList: + for _, field := range n.List { + f.walk(field, context, visit) + } + case *ast.BadExpr: + case *ast.Ident: + case *ast.Ellipsis: + case *ast.BasicLit: + case *ast.FuncLit: + f.walk(n.Type, "type", visit) + f.walk(n.Body, "stmt", visit) + case *ast.CompositeLit: + f.walk(&n.Type, "type", visit) + f.walk(n.Elts, "expr", visit) + case *ast.ParenExpr: + f.walk(&n.X, context, visit) + case *ast.SelectorExpr: + f.walk(&n.X, "selector", visit) + case *ast.IndexExpr: + f.walk(&n.X, "expr", visit) + f.walk(&n.Index, "expr", visit) + case *ast.SliceExpr: + f.walk(&n.X, "expr", visit) + if n.Low != nil { + f.walk(&n.Low, "expr", visit) + } + if n.High != nil { + f.walk(&n.High, "expr", visit) + } + if n.Max != nil { + f.walk(&n.Max, "expr", visit) + } + case *ast.TypeAssertExpr: + f.walk(&n.X, "expr", visit) + f.walk(&n.Type, "type", visit) + case *ast.CallExpr: + if context == "as2" { + f.walk(&n.Fun, "call2", visit) + } else { + f.walk(&n.Fun, "call", visit) + } + f.walk(n.Args, "expr", visit) + case *ast.StarExpr: + f.walk(&n.X, context, visit) + case *ast.UnaryExpr: + f.walk(&n.X, "expr", visit) + case *ast.BinaryExpr: + f.walk(&n.X, "expr", visit) + f.walk(&n.Y, "expr", visit) + case *ast.KeyValueExpr: + f.walk(&n.Key, "expr", visit) + f.walk(&n.Value, "expr", visit) + + case *ast.ArrayType: + f.walk(&n.Len, "expr", visit) + f.walk(&n.Elt, "type", visit) + case *ast.StructType: + f.walk(n.Fields, "field", visit) + case *ast.FuncType: + f.walk(n.Params, "param", visit) + if n.Results != nil { + f.walk(n.Results, "param", visit) + } + case *ast.InterfaceType: + f.walk(n.Methods, "field", visit) + case *ast.MapType: + f.walk(&n.Key, "type", visit) + f.walk(&n.Value, "type", visit) + case *ast.ChanType: + f.walk(&n.Value, "type", visit) + + case *ast.BadStmt: + case *ast.DeclStmt: + f.walk(n.Decl, "decl", visit) + case *ast.EmptyStmt: + case *ast.LabeledStmt: + f.walk(n.Stmt, "stmt", visit) + case *ast.ExprStmt: + f.walk(&n.X, "expr", visit) + case *ast.SendStmt: + f.walk(&n.Chan, "expr", visit) + f.walk(&n.Value, "expr", visit) + case *ast.IncDecStmt: + f.walk(&n.X, "expr", visit) + case *ast.AssignStmt: + f.walk(n.Lhs, "expr", visit) + if len(n.Lhs) == 2 && len(n.Rhs) == 1 { + f.walk(n.Rhs, "as2", visit) + } else { + f.walk(n.Rhs, "expr", visit) + } + case *ast.GoStmt: + f.walk(n.Call, "expr", visit) + case *ast.DeferStmt: + f.walk(n.Call, "expr", visit) + case *ast.ReturnStmt: + f.walk(n.Results, "expr", visit) + case *ast.BranchStmt: + case *ast.BlockStmt: + f.walk(n.List, context, visit) + case *ast.IfStmt: + f.walk(n.Init, "stmt", visit) + f.walk(&n.Cond, "expr", visit) + f.walk(n.Body, "stmt", visit) + f.walk(n.Else, "stmt", visit) + case *ast.CaseClause: + if context == "typeswitch" { + context = "type" + } else { + context = "expr" + } + f.walk(n.List, context, visit) + f.walk(n.Body, "stmt", visit) + case *ast.SwitchStmt: + f.walk(n.Init, "stmt", visit) + f.walk(&n.Tag, "expr", visit) + f.walk(n.Body, "switch", visit) + case *ast.TypeSwitchStmt: + f.walk(n.Init, "stmt", visit) + f.walk(n.Assign, "stmt", visit) + f.walk(n.Body, "typeswitch", visit) + case *ast.CommClause: + f.walk(n.Comm, "stmt", visit) + f.walk(n.Body, "stmt", visit) + case *ast.SelectStmt: + f.walk(n.Body, "stmt", visit) + case *ast.ForStmt: + f.walk(n.Init, "stmt", visit) + f.walk(&n.Cond, "expr", visit) + f.walk(n.Post, "stmt", visit) + f.walk(n.Body, "stmt", visit) + case *ast.RangeStmt: + f.walk(&n.Key, "expr", visit) + f.walk(&n.Value, "expr", visit) + f.walk(&n.X, "expr", visit) + f.walk(n.Body, "stmt", visit) + + case *ast.ImportSpec: + case *ast.ValueSpec: + f.walk(&n.Type, "type", visit) + f.walk(n.Values, "expr", visit) + case *ast.TypeSpec: + f.walk(&n.Type, "type", visit) + + case *ast.BadDecl: + case *ast.GenDecl: + f.walk(n.Specs, "spec", visit) + case *ast.FuncDecl: + if n.Recv != nil { + f.walk(n.Recv, "param", visit) + } + f.walk(n.Type, "type", visit) + if n.Body != nil { + f.walk(n.Body, "stmt", visit) + } + + case *ast.File: + f.walk(n.Decls, "decl", visit) + + case *ast.Package: + for _, file := range n.Files { + f.walk(file, "file", visit) + } + + case []ast.Decl: + for _, d := range n { + f.walk(d, context, visit) + } + case []ast.Expr: + for i := range n { + f.walk(&n[i], context, visit) + } + case []ast.Stmt: + for _, s := range n { + f.walk(s, context, visit) + } + case []ast.Spec: + for _, s := range n { + f.walk(s, context, visit) + } + } +} diff --git a/libgo/go/cmd/cgo/doc.go b/libgo/go/cmd/cgo/doc.go new file mode 100644 index 0000000000..6179c7afd1 --- /dev/null +++ b/libgo/go/cmd/cgo/doc.go @@ -0,0 +1,748 @@ +// 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. + +/* + +Cgo enables the creation of Go packages that call C code. + +Using cgo with the go command + +To use cgo write normal Go code that imports a pseudo-package "C". +The Go code can then refer to types such as C.size_t, variables such +as C.stdout, or functions such as C.putchar. + +If the import of "C" is immediately preceded by a comment, that +comment, called the preamble, is used as a header when compiling +the C parts of the package. For example: + + // #include + // #include + import "C" + +See $GOROOT/misc/cgo/stdio and $GOROOT/misc/cgo/gmp for examples. See +"C? Go? Cgo!" for an introduction to using cgo: +http://golang.org/doc/articles/c_go_cgo.html. + +CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS may be defined with pseudo #cgo +directives within these comments to tweak the behavior of the C or C++ +compiler. Values defined in multiple directives are concatenated +together. The directive can include a list of build constraints limiting its +effect to systems satisfying one of the constraints +(see http://golang.org/pkg/go/build/#hdr-Build_Constraints for details about the constraint syntax). +For example: + + // #cgo CFLAGS: -DPNG_DEBUG=1 + // #cgo amd64 386 CFLAGS: -DX86=1 + // #cgo LDFLAGS: -lpng + // #include + import "C" + +Alternatively, CPPFLAGS and LDFLAGS may be obtained via the pkg-config +tool using a '#cgo pkg-config:' directive followed by the package names. +For example: + + // #cgo pkg-config: png cairo + // #include + import "C" + +When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS and +CGO_LDFLAGS environment variables are added to the flags derived from +these directives. Package-specific flags should be set using the +directives, not the environment variables, so that builds work in +unmodified environments. + +All the cgo CPPFLAGS and CFLAGS directives in a package are concatenated and +used to compile C files in that package. All the CPPFLAGS and CXXFLAGS +directives in a package are concatenated and used to compile C++ files in that +package. All the LDFLAGS directives in any package in the program are +concatenated and used at link time. All the pkg-config directives are +concatenated and sent to pkg-config simultaneously to add to each appropriate +set of command-line flags. + +When the Go tool sees that one or more Go files use the special import +"C", it will look for other non-Go files in the directory and compile +them as part of the Go package. Any .c, .s, or .S files will be +compiled with the C compiler. Any .cc, .cpp, or .cxx files will be +compiled with the C++ compiler. Any .h, .hh, .hpp, or .hxx files will +not be compiled separately, but, if these header files are changed, +the C and C++ files will be recompiled. The default C and C++ +compilers may be changed by the CC and CXX environment variables, +respectively; those environment variables may include command line +options. + +To enable cgo during cross compiling builds, set the CGO_ENABLED +environment variable to 1 when building the Go tools with make.bash. +Also, set CC_FOR_TARGET to the C cross compiler for the target. CC will +be used for compiling for the host. + +After the Go tools are built, when running the go command, CC_FOR_TARGET is +ignored. The value of CC_FOR_TARGET when running make.bash is the default +compiler. However, you can set the environment variable CC, not CC_FOR_TARGET, +to control the compiler when running the go tool. + +CXX_FOR_TARGET works in a similar way for C++ code. + +Go references to C + +Within the Go file, C's struct field names that are keywords in Go +can be accessed by prefixing them with an underscore: if x points at a C +struct with a field named "type", x._type accesses the field. +C struct fields that cannot be expressed in Go, such as bit fields +or misaligned data, are omitted in the Go struct, replaced by +appropriate padding to reach the next field or the end of the struct. + +The standard C numeric types are available under the names +C.char, C.schar (signed char), C.uchar (unsigned char), +C.short, C.ushort (unsigned short), C.int, C.uint (unsigned int), +C.long, C.ulong (unsigned long), C.longlong (long long), +C.ulonglong (unsigned long long), C.float, C.double. +The C type void* is represented by Go's unsafe.Pointer. + +To access a struct, union, or enum type directly, prefix it with +struct_, union_, or enum_, as in C.struct_stat. + +As Go doesn't have support for C's union type in the general case, +C's union types are represented as a Go byte array with the same length. + +Go structs cannot embed fields with C types. + +Cgo translates C types into equivalent unexported Go types. +Because the translations are unexported, a Go package should not +expose C types in its exported API: a C type used in one Go package +is different from the same C type used in another. + +Any C function (even void functions) may be called in a multiple +assignment context to retrieve both the return value (if any) and the +C errno variable as an error (use _ to skip the result value if the +function returns void). For example: + + n, err := C.sqrt(-1) + _, err := C.voidFunc() + +Calling C function pointers is currently not supported, however you can +declare Go variables which hold C function pointers and pass them +back and forth between Go and C. C code may call function pointers +received from Go. For example: + + package main + + // typedef int (*intFunc) (); + // + // int + // bridge_int_func(intFunc f) + // { + // return f(); + // } + // + // int fortytwo() + // { + // return 42; + // } + import "C" + import "fmt" + + func main() { + f := C.intFunc(C.fortytwo) + fmt.Println(int(C.bridge_int_func(f))) + // Output: 42 + } + +In C, a function argument written as a fixed size array +actually requires a pointer to the first element of the array. +C compilers are aware of this calling convention and adjust +the call accordingly, but Go cannot. In Go, you must pass +the pointer to the first element explicitly: C.f(&C.x[0]). + +A few special functions convert between Go and C types +by making copies of the data. In pseudo-Go definitions: + + // Go string to C string + // The C string is allocated in the C heap using malloc. + // It is the caller's responsibility to arrange for it to be + // freed, such as by calling C.free (be sure to include stdlib.h + // if C.free is needed). + func C.CString(string) *C.char + + // C string to Go string + func C.GoString(*C.char) string + + // C string, length to Go string + func C.GoStringN(*C.char, C.int) string + + // C pointer, length to Go []byte + func C.GoBytes(unsafe.Pointer, C.int) []byte + +C references to Go + +Go functions can be exported for use by C code in the following way: + + //export MyFunction + func MyFunction(arg1, arg2 int, arg3 string) int64 {...} + + //export MyFunction2 + func MyFunction2(arg1, arg2 int, arg3 string) (int64, *C.char) {...} + +They will be available in the C code as: + + extern int64 MyFunction(int arg1, int arg2, GoString arg3); + extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3); + +found in the _cgo_export.h generated header, after any preambles +copied from the cgo input files. Functions with multiple +return values are mapped to functions returning a struct. +Not all Go types can be mapped to C types in a useful way. + +Using //export in a file places a restriction on the preamble: +since it is copied into two different C output files, it must not +contain any definitions, only declarations. Definitions must be +placed in preambles in other files, or in C source files. + +Using cgo directly + +Usage: + go tool cgo [cgo options] [-- compiler options] file.go + +Cgo transforms the input file.go into four output files: two Go source +files, a C file for 6c (or 8c or 5c), and a C file for gcc. + +The compiler options are passed through uninterpreted when +invoking the C compiler to compile the C parts of the package. + +The following options are available when running cgo directly: + + -dynimport file + Write list of symbols imported by file. Write to + -dynout argument or to standard output. Used by go + build when building a cgo package. + -dynout file + Write -dynimport output to file. + -dynlinker + Write dynamic linker as part of -dynimport output. + -godefs + Write out input file in Go syntax replacing C package + names with real values. Used to generate files in the + syscall package when bootstrapping a new target. + -cdefs + Like -godefs, but write file in C syntax. + Used to generate files in the runtime package when + bootstrapping a new target. + -objdir directory + Put all generated files in directory. + -gccgo + Generate output for the gccgo compiler rather than the + gc compiler. + -gccgoprefix prefix + The -fgo-prefix option to be used with gccgo. + -gccgopkgpath path + The -fgo-pkgpath option to be used with gccgo. + -import_runtime_cgo + If set (which it is by default) import runtime/cgo in + generated output. + -import_syscall + If set (which it is by default) import syscall in + generated output. + -debug-define + Debugging option. Print #defines. + -debug-gcc + Debugging option. Trace C compiler execution and output. +*/ +package main + +/* +Implementation details. + +Cgo provides a way for Go programs to call C code linked into the same +address space. This comment explains the operation of cgo. + +Cgo reads a set of Go source files and looks for statements saying +import "C". If the import has a doc comment, that comment is +taken as literal C code to be used as a preamble to any C code +generated by cgo. A typical preamble #includes necessary definitions: + + // #include + import "C" + +For more details about the usage of cgo, see the documentation +comment at the top of this file. + +Understanding C + +Cgo scans the Go source files that import "C" for uses of that +package, such as C.puts. It collects all such identifiers. The next +step is to determine each kind of name. In C.xxx the xxx might refer +to a type, a function, a constant, or a global variable. Cgo must +decide which. + +The obvious thing for cgo to do is to process the preamble, expanding +#includes and processing the corresponding C code. That would require +a full C parser and type checker that was also aware of any extensions +known to the system compiler (for example, all the GNU C extensions) as +well as the system-specific header locations and system-specific +pre-#defined macros. This is certainly possible to do, but it is an +enormous amount of work. + +Cgo takes a different approach. It determines the meaning of C +identifiers not by parsing C code but by feeding carefully constructed +programs into the system C compiler and interpreting the generated +error messages, debug information, and object files. In practice, +parsing these is significantly less work and more robust than parsing +C source. + +Cgo first invokes gcc -E -dM on the preamble, in order to find out +about simple #defines for constants and the like. These are recorded +for later use. + +Next, cgo needs to identify the kinds for each identifier. For the +identifiers C.foo and C.bar, cgo generates this C program: + + + #line 1 "not-declared" + void __cgo_f_xxx_1(void) { __typeof__(foo) *__cgo_undefined__; } + #line 1 "not-type" + void __cgo_f_xxx_2(void) { foo *__cgo_undefined__; } + #line 1 "not-const" + void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (foo)*1 }; } + #line 2 "not-declared" + void __cgo_f_xxx_1(void) { __typeof__(bar) *__cgo_undefined__; } + #line 2 "not-type" + void __cgo_f_xxx_2(void) { bar *__cgo_undefined__; } + #line 2 "not-const" + void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (bar)*1 }; } + +This program will not compile, but cgo can use the presence or absence +of an error message on a given line to deduce the information it +needs. The program is syntactically valid regardless of whether each +name is a type or an ordinary identifier, so there will be no syntax +errors that might stop parsing early. + +An error on not-declared:1 indicates that foo is undeclared. +An error on not-type:1 indicates that foo is not a type (if declared at all, it is an identifier). +An error on not-const:1 indicates that foo is not an integer constant. + +The line number specifies the name involved. In the example, 1 is foo and 2 is bar. + +Next, cgo must learn the details of each type, variable, function, or +constant. It can do this by reading object files. If cgo has decided +that t1 is a type, v2 and v3 are variables or functions, and c4, c5, +and c6 are constants, it generates: + + + __typeof__(t1) *__cgo__1; + __typeof__(v2) *__cgo__2; + __typeof__(v3) *__cgo__3; + __typeof__(c4) *__cgo__4; + enum { __cgo_enum__4 = c4 }; + __typeof__(c5) *__cgo__5; + enum { __cgo_enum__5 = c5 }; + __typeof__(c6) *__cgo__6; + enum { __cgo_enum__6 = c6 }; + + long long __cgo_debug_data[] = { + 0, // t1 + 0, // v2 + 0, // v3 + c4, + c5, + c6, + 1 + }; + +and again invokes the system C compiler, to produce an object file +containing debug information. Cgo parses the DWARF debug information +for __cgo__N to learn the type of each identifier. (The types also +distinguish functions from global variables.) If using a standard gcc, +cgo can parse the DWARF debug information for the __cgo_enum__N to +learn the identifier's value. The LLVM-based gcc on OS X emits +incomplete DWARF information for enums; in that case cgo reads the +constant values from the __cgo_debug_data from the object file's data +segment. + +At this point cgo knows the meaning of each C.xxx well enough to start +the translation process. + +Translating Go + +[The rest of this comment refers to 6g and 6c, the Go and C compilers +that are part of the amd64 port of the gc Go toolchain. Everything here +applies to another architecture's compilers as well.] + +Given the input Go files x.go and y.go, cgo generates these source +files: + + x.cgo1.go # for 6g + y.cgo1.go # for 6g + _cgo_gotypes.go # for 6g + _cgo_defun.c # for 6c + x.cgo2.c # for gcc + y.cgo2.c # for gcc + _cgo_export.c # for gcc + _cgo_main.c # for gcc + +The file x.cgo1.go is a copy of x.go with the import "C" removed and +references to C.xxx replaced with names like _Cfunc_xxx or _Ctype_xxx. +The definitions of those identifiers, written as Go functions, types, +or variables, are provided in _cgo_gotypes.go. + +Here is a _cgo_gotypes.go containing definitions for C.flush (provided +in the preamble) and C.puts (from stdio): + + type _Ctype_char int8 + type _Ctype_int int32 + type _Ctype_void [0]byte + + func _Cfunc_CString(string) *_Ctype_char + func _Cfunc_flush() _Ctype_void + func _Cfunc_puts(*_Ctype_char) _Ctype_int + +For functions, cgo only writes an external declaration in the Go +output. The implementation is in a combination of C for 6c (meaning +any gc-toolchain compiler) and C for gcc. + +The 6c file contains the definitions of the functions. They all have +similar bodies that invoke runtime·cgocall to make a switch from the +Go runtime world to the system C (GCC-based) world. + +For example, here is the definition of _Cfunc_puts: + + void _cgo_be59f0f25121_Cfunc_puts(void*); + + void + ·_Cfunc_puts(struct{uint8 x[1];}p) + { + runtime·cgocall(_cgo_be59f0f25121_Cfunc_puts, &p); + } + +The hexadecimal number is a hash of cgo's input, chosen to be +deterministic yet unlikely to collide with other uses. The actual +function _cgo_be59f0f25121_Cfunc_puts is implemented in a C source +file compiled by gcc, the file x.cgo2.c: + + void + _cgo_be59f0f25121_Cfunc_puts(void *v) + { + struct { + char* p0; + int r; + char __pad12[4]; + } __attribute__((__packed__, __gcc_struct__)) *a = v; + a->r = puts((void*)a->p0); + } + +It extracts the arguments from the pointer to _Cfunc_puts's argument +frame, invokes the system C function (in this case, puts), stores the +result in the frame, and returns. + +Linking + +Once the _cgo_export.c and *.cgo2.c files have been compiled with gcc, +they need to be linked into the final binary, along with the libraries +they might depend on (in the case of puts, stdio). 6l has been +extended to understand basic ELF files, but it does not understand ELF +in the full complexity that modern C libraries embrace, so it cannot +in general generate direct references to the system libraries. + +Instead, the build process generates an object file using dynamic +linkage to the desired libraries. The main function is provided by +_cgo_main.c: + + int main() { return 0; } + void crosscall2(void(*fn)(void*, int), void *a, int c) { } + void _cgo_allocate(void *a, int c) { } + void _cgo_panic(void *a, int c) { } + +The extra functions here are stubs to satisfy the references in the C +code generated for gcc. The build process links this stub, along with +_cgo_export.c and *.cgo2.c, into a dynamic executable and then lets +cgo examine the executable. Cgo records the list of shared library +references and resolved names and writes them into a new file +_cgo_import.c, which looks like: + + #pragma cgo_dynamic_linker "/lib64/ld-linux-x86-64.so.2" + #pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6" + #pragma cgo_import_dynamic __libc_start_main __libc_start_main#GLIBC_2.2.5 "libc.so.6" + #pragma cgo_import_dynamic stdout stdout#GLIBC_2.2.5 "libc.so.6" + #pragma cgo_import_dynamic fflush fflush#GLIBC_2.2.5 "libc.so.6" + #pragma cgo_import_dynamic _ _ "libpthread.so.0" + #pragma cgo_import_dynamic _ _ "libc.so.6" + +In the end, the compiled Go package, which will eventually be +presented to 6l as part of a larger program, contains: + + _go_.6 # 6g-compiled object for _cgo_gotypes.go *.cgo1.go + _cgo_defun.6 # 6c-compiled object for _cgo_defun.c + _all.o # gcc-compiled object for _cgo_export.c, *.cgo2.c + _cgo_import.6 # 6c-compiled object for _cgo_import.c + +The final program will be a dynamic executable, so that 6l can avoid +needing to process arbitrary .o files. It only needs to process the .o +files generated from C files that cgo writes, and those are much more +limited in the ELF or other features that they use. + +In essence, the _cgo_import.6 file includes the extra linking +directives that 6l is not sophisticated enough to derive from _all.o +on its own. Similarly, the _all.o uses dynamic references to real +system object code because 6l is not sophisticated enough to process +the real code. + +The main benefits of this system are that 6l remains relatively simple +(it does not need to implement a complete ELF and Mach-O linker) and +that gcc is not needed after the package is compiled. For example, +package net uses cgo for access to name resolution functions provided +by libc. Although gcc is needed to compile package net, gcc is not +needed to link programs that import package net. + +Runtime + +When using cgo, Go must not assume that it owns all details of the +process. In particular it needs to coordinate with C in the use of +threads and thread-local storage. The runtime package, in its own +(6c-compiled) C code, declares a few uninitialized (default bss) +variables: + + bool runtime·iscgo; + void (*libcgo_thread_start)(void*); + void (*initcgo)(G*); + +Any package using cgo imports "runtime/cgo", which provides +initializations for these variables. It sets iscgo to 1, initcgo to a +gcc-compiled function that can be called early during program startup, +and libcgo_thread_start to a gcc-compiled function that can be used to +create a new thread, in place of the runtime's usual direct system +calls. + +Internal and External Linking + +The text above describes "internal" linking, in which 6l parses and +links host object files (ELF, Mach-O, PE, and so on) into the final +executable itself. Keeping 6l simple means we cannot possibly +implement the full semantics of the host linker, so the kinds of +objects that can be linked directly into the binary is limited (other +code can only be used as a dynamic library). On the other hand, when +using internal linking, 6l can generate Go binaries by itself. + +In order to allow linking arbitrary object files without requiring +dynamic libraries, cgo will soon support an "external" linking mode +too. In external linking mode, 6l does not process any host object +files. Instead, it collects all the Go code and writes a single go.o +object file containing it. Then it invokes the host linker (usually +gcc) to combine the go.o object file and any supporting non-Go code +into a final executable. External linking avoids the dynamic library +requirement but introduces a requirement that the host linker be +present to create such a binary. + +Most builds both compile source code and invoke the linker to create a +binary. When cgo is involved, the compile step already requires gcc, so +it is not problematic for the link step to require gcc too. + +An important exception is builds using a pre-compiled copy of the +standard library. In particular, package net uses cgo on most systems, +and we want to preserve the ability to compile pure Go code that +imports net without requiring gcc to be present at link time. (In this +case, the dynamic library requirement is less significant, because the +only library involved is libc.so, which can usually be assumed +present.) + +This conflict between functionality and the gcc requirement means we +must support both internal and external linking, depending on the +circumstances: if net is the only cgo-using package, then internal +linking is probably fine, but if other packages are involved, so that there +are dependencies on libraries beyond libc, external linking is likely +to work better. The compilation of a package records the relevant +information to support both linking modes, leaving the decision +to be made when linking the final binary. + +Linking Directives + +In either linking mode, package-specific directives must be passed +through to 6l. These are communicated by writing #pragma directives +in a C source file compiled by 6c. The directives are copied into the .6 object file +and then processed by the linker. + +The directives are: + +#pragma cgo_import_dynamic [ [""]] + + In internal linking mode, allow an unresolved reference to + , assuming it will be resolved by a dynamic library + symbol. The optional specifies the symbol's name and + possibly version in the dynamic library, and the optional "" + names the specific library where the symbol should be found. + + In the , # or @ can be used to introduce a symbol version. + + Examples: + #pragma cgo_import_dynamic puts + #pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 + #pragma cgo_import_dynamic puts puts#GLIBC_2.2.5 "libc.so.6" + + A side effect of the cgo_import_dynamic directive with a + library is to make the final binary depend on that dynamic + library. To get the dependency without importing any specific + symbols, use _ for local and remote. + + Example: + #pragma cgo_import_dynamic _ _ "libc.so.6" + + For compatibility with current versions of SWIG, + #pragma dynimport is an alias for #pragma cgo_import_dynamic. + +#pragma cgo_dynamic_linker "" + + In internal linking mode, use "" as the dynamic linker + in the final binary. This directive is only needed from one + package when constructing a binary; by convention it is + supplied by runtime/cgo. + + Example: + #pragma cgo_dynamic_linker "/lib/ld-linux.so.2" + +#pragma cgo_export_dynamic + + In internal linking mode, put the Go symbol + named into the program's exported symbol table as + , so that C code can refer to it by that name. This + mechanism makes it possible for C code to call back into Go or + to share Go's data. + + For compatibility with current versions of SWIG, + #pragma dynexport is an alias for #pragma cgo_export_dynamic. + +#pragma cgo_import_static + + In external linking mode, allow unresolved references to + in the go.o object file prepared for the host linker, + under the assumption that will be supplied by the + other object files that will be linked with go.o. + + Example: + #pragma cgo_import_static puts_wrapper + +#pragma cgo_export_static + + In external linking mode, put the Go symbol + named into the program's exported symbol table as + , so that C code can refer to it by that name. This + mechanism makes it possible for C code to call back into Go or + to share Go's data. + +#pragma cgo_ldflag "" + + In external linking mode, invoke the host linker (usually gcc) + with "" as a command-line argument following the .o files. + Note that the arguments are for "gcc", not "ld". + + Example: + #pragma cgo_ldflag "-lpthread" + #pragma cgo_ldflag "-L/usr/local/sqlite3/lib" + +A package compiled with cgo will include directives for both +internal and external linking; the linker will select the appropriate +subset for the chosen linking mode. + +Example + +As a simple example, consider a package that uses cgo to call C.sin. +The following code will be generated by cgo: + + // compiled by 6g + + type _Ctype_double float64 + func _Cfunc_sin(_Ctype_double) _Ctype_double + + // compiled by 6c + + #pragma cgo_import_dynamic sin sin#GLIBC_2.2.5 "libm.so.6" + + #pragma cgo_import_static _cgo_gcc_Cfunc_sin + #pragma cgo_ldflag "-lm" + + void _cgo_gcc_Cfunc_sin(void*); + + void + ·_Cfunc_sin(struct{uint8 x[16];}p) + { + runtime·cgocall(_cgo_gcc_Cfunc_sin, &p); + } + + // compiled by gcc, into foo.cgo2.o + + void + _cgo_gcc_Cfunc_sin(void *v) + { + struct { + double p0; + double r; + } __attribute__((__packed__)) *a = v; + a->r = sin(a->p0); + } + +What happens at link time depends on whether the final binary is linked +using the internal or external mode. If other packages are compiled in +"external only" mode, then the final link will be an external one. +Otherwise the link will be an internal one. + +The directives in the 6c-compiled file are used according to the kind +of final link used. + +In internal mode, 6l itself processes all the host object files, in +particular foo.cgo2.o. To do so, it uses the cgo_import_dynamic and +cgo_dynamic_linker directives to learn that the otherwise undefined +reference to sin in foo.cgo2.o should be rewritten to refer to the +symbol sin with version GLIBC_2.2.5 from the dynamic library +"libm.so.6", and the binary should request "/lib/ld-linux.so.2" as its +runtime dynamic linker. + +In external mode, 6l does not process any host object files, in +particular foo.cgo2.o. It links together the 6g- and 6c-generated +object files, along with any other Go code, into a go.o file. While +doing that, 6l will discover that there is no definition for +_cgo_gcc_Cfunc_sin, referred to by the 6c-compiled source file. This +is okay, because 6l also processes the cgo_import_static directive and +knows that _cgo_gcc_Cfunc_sin is expected to be supplied by a host +object file, so 6l does not treat the missing symbol as an error when +creating go.o. Indeed, the definition for _cgo_gcc_Cfunc_sin will be +provided to the host linker by foo2.cgo.o, which in turn will need the +symbol 'sin'. 6l also processes the cgo_ldflag directives, so that it +knows that the eventual host link command must include the -lm +argument, so that the host linker will be able to find 'sin' in the +math library. + +6l Command Line Interface + +The go command and any other Go-aware build systems invoke 6l +to link a collection of packages into a single binary. By default, 6l will +present the same interface it does today: + + 6l main.a + +produces a file named 6.out, even if 6l does so by invoking the host +linker in external linking mode. + +By default, 6l will decide the linking mode as follows: if the only +packages using cgo are those on a whitelist of standard library +packages (net, os/user, runtime/cgo), 6l will use internal linking +mode. Otherwise, there are non-standard cgo packages involved, and 6l +will use external linking mode. The first rule means that a build of +the godoc binary, which uses net but no other cgo, can run without +needing gcc available. The second rule means that a build of a +cgo-wrapped library like sqlite3 can generate a standalone executable +instead of needing to refer to a dynamic library. The specific choice +can be overridden using a command line flag: 6l -linkmode=internal or +6l -linkmode=external. + +In an external link, 6l will create a temporary directory, write any +host object files found in package archives to that directory (renamed +to avoid conflicts), write the go.o file to that directory, and invoke +the host linker. The default value for the host linker is $CC, split +into fields, or else "gcc". The specific host linker command line can +be overridden using command line flags: 6l -extld=clang +-extldflags='-ggdb -O3'. If any package in a build includes a .cc or +other file compiled by the C++ compiler, the go tool will use the +-extld option to set the host linker to the C++ compiler. + +These defaults mean that Go-aware build systems can ignore the linking +changes and keep running plain '6l' and get reasonable results, but +they can also control the linking details if desired. + +*/ diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go new file mode 100644 index 0000000000..abdd369d71 --- /dev/null +++ b/libgo/go/cmd/cgo/gcc.go @@ -0,0 +1,1753 @@ +// 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. + +// Annotate Ref in Prog with C types by parsing gcc debug output. +// Conversion of debug output to Go types. + +package main + +import ( + "bytes" + "debug/dwarf" + "debug/elf" + "debug/macho" + "debug/pe" + "encoding/binary" + "errors" + "flag" + "fmt" + "go/ast" + "go/parser" + "go/token" + "os" + "strconv" + "strings" + "unicode" + "unicode/utf8" +) + +var debugDefine = flag.Bool("debug-define", false, "print relevant #defines") +var debugGcc = flag.Bool("debug-gcc", false, "print gcc invocations") + +var nameToC = map[string]string{ + "schar": "signed char", + "uchar": "unsigned char", + "ushort": "unsigned short", + "uint": "unsigned int", + "ulong": "unsigned long", + "longlong": "long long", + "ulonglong": "unsigned long long", + "complexfloat": "float complex", + "complexdouble": "double complex", +} + +// cname returns the C name to use for C.s. +// The expansions are listed in nameToC and also +// struct_foo becomes "struct foo", and similarly for +// union and enum. +func cname(s string) string { + if t, ok := nameToC[s]; ok { + return t + } + + if strings.HasPrefix(s, "struct_") { + return "struct " + s[len("struct_"):] + } + if strings.HasPrefix(s, "union_") { + return "union " + s[len("union_"):] + } + if strings.HasPrefix(s, "enum_") { + return "enum " + s[len("enum_"):] + } + if strings.HasPrefix(s, "sizeof_") { + return "sizeof(" + cname(s[len("sizeof_"):]) + ")" + } + return s +} + +// DiscardCgoDirectives processes the import C preamble, and discards +// all #cgo CFLAGS and LDFLAGS directives, so they don't make their +// way into _cgo_export.h. +func (f *File) DiscardCgoDirectives() { + linesIn := strings.Split(f.Preamble, "\n") + linesOut := make([]string, 0, len(linesIn)) + for _, line := range linesIn { + l := strings.TrimSpace(line) + if len(l) < 5 || l[:4] != "#cgo" || !unicode.IsSpace(rune(l[4])) { + linesOut = append(linesOut, line) + } else { + linesOut = append(linesOut, "") + } + } + f.Preamble = strings.Join(linesOut, "\n") +} + +// addToFlag appends args to flag. All flags are later written out onto the +// _cgo_flags file for the build system to use. +func (p *Package) addToFlag(flag string, args []string) { + p.CgoFlags[flag] = append(p.CgoFlags[flag], args...) + if flag == "CFLAGS" { + // We'll also need these when preprocessing for dwarf information. + p.GccOptions = append(p.GccOptions, args...) + } +} + +// splitQuoted splits the string s around each instance of one or more consecutive +// white space characters while taking into account quotes and escaping, and +// returns an array of substrings of s or an empty list if s contains only white space. +// Single quotes and double quotes are recognized to prevent splitting within the +// quoted region, and are removed from the resulting substrings. If a quote in s +// isn't closed err will be set and r will have the unclosed argument as the +// last element. The backslash is used for escaping. +// +// For example, the following string: +// +// `a b:"c d" 'e''f' "g\""` +// +// Would be parsed as: +// +// []string{"a", "b:c d", "ef", `g"`} +// +func splitQuoted(s string) (r []string, err error) { + var args []string + arg := make([]rune, len(s)) + escaped := false + quoted := false + quote := '\x00' + i := 0 + for _, r := range s { + switch { + case escaped: + escaped = false + case r == '\\': + escaped = true + continue + case quote != 0: + if r == quote { + quote = 0 + continue + } + case r == '"' || r == '\'': + quoted = true + quote = r + continue + case unicode.IsSpace(r): + if quoted || i > 0 { + quoted = false + args = append(args, string(arg[:i])) + i = 0 + } + continue + } + arg[i] = r + i++ + } + if quoted || i > 0 { + args = append(args, string(arg[:i])) + } + if quote != 0 { + err = errors.New("unclosed quote") + } else if escaped { + err = errors.New("unfinished escaping") + } + return args, err +} + +var safeBytes = []byte(`+-.,/0123456789:=ABCDEFGHIJKLMNOPQRSTUVWXYZ\_abcdefghijklmnopqrstuvwxyz`) + +func safeName(s string) bool { + if s == "" { + return false + } + for i := 0; i < len(s); i++ { + if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 { + return false + } + } + return true +} + +// Translate rewrites f.AST, the original Go input, to remove +// references to the imported package C, replacing them with +// references to the equivalent Go types, functions, and variables. +func (p *Package) Translate(f *File) { + for _, cref := range f.Ref { + // Convert C.ulong to C.unsigned long, etc. + cref.Name.C = cname(cref.Name.Go) + } + p.loadDefines(f) + needType := p.guessKinds(f) + if len(needType) > 0 { + p.loadDWARF(f, needType) + } + p.rewriteRef(f) +} + +// loadDefines coerces gcc into spitting out the #defines in use +// in the file f and saves relevant renamings in f.Name[name].Define. +func (p *Package) loadDefines(f *File) { + var b bytes.Buffer + b.WriteString(f.Preamble) + b.WriteString(builtinProlog) + stdout := p.gccDefines(b.Bytes()) + + for _, line := range strings.Split(stdout, "\n") { + if len(line) < 9 || line[0:7] != "#define" { + continue + } + + line = strings.TrimSpace(line[8:]) + + var key, val string + spaceIndex := strings.Index(line, " ") + tabIndex := strings.Index(line, "\t") + + if spaceIndex == -1 && tabIndex == -1 { + continue + } else if tabIndex == -1 || (spaceIndex != -1 && spaceIndex < tabIndex) { + key = line[0:spaceIndex] + val = strings.TrimSpace(line[spaceIndex:]) + } else { + key = line[0:tabIndex] + val = strings.TrimSpace(line[tabIndex:]) + } + + if n := f.Name[key]; n != nil { + if *debugDefine { + fmt.Fprintf(os.Stderr, "#define %s %s\n", key, val) + } + n.Define = val + } + } +} + +// guessKinds tricks gcc into revealing the kind of each +// name xxx for the references C.xxx in the Go input. +// The kind is either a constant, type, or variable. +func (p *Package) guessKinds(f *File) []*Name { + // Determine kinds for names we already know about, + // like #defines or 'struct foo', before bothering with gcc. + var names, needType []*Name + for _, key := range nameKeys(f.Name) { + n := f.Name[key] + // If we've already found this name as a #define + // and we can translate it as a constant value, do so. + if n.Define != "" { + isConst := false + if _, err := strconv.Atoi(n.Define); err == nil { + isConst = true + } else if n.Define[0] == '"' || n.Define[0] == '\'' { + if _, err := parser.ParseExpr(n.Define); err == nil { + isConst = true + } + } + if isConst { + n.Kind = "const" + // Turn decimal into hex, just for consistency + // with enum-derived constants. Otherwise + // in the cgo -godefs output half the constants + // are in hex and half are in whatever the #define used. + i, err := strconv.ParseInt(n.Define, 0, 64) + if err == nil { + n.Const = fmt.Sprintf("%#x", i) + } else { + n.Const = n.Define + } + continue + } + + if isName(n.Define) { + n.C = n.Define + } + } + + needType = append(needType, n) + + // If this is a struct, union, or enum type name, no need to guess the kind. + if strings.HasPrefix(n.C, "struct ") || strings.HasPrefix(n.C, "union ") || strings.HasPrefix(n.C, "enum ") { + n.Kind = "type" + continue + } + + // Otherwise, we'll need to find out from gcc. + names = append(names, n) + } + + // Bypass gcc if there's nothing left to find out. + if len(names) == 0 { + return needType + } + + // Coerce gcc into telling us whether each name is a type, a value, or undeclared. + // For names, find out whether they are integer constants. + // We used to look at specific warning or error messages here, but that tied the + // behavior too closely to specific versions of the compilers. + // Instead, arrange that we can infer what we need from only the presence or absence + // of an error on a specific line. + // + // For each name, we generate these lines, where xxx is the index in toSniff plus one. + // + // #line xxx "not-declared" + // void __cgo_f_xxx_1(void) { __typeof__(name) *__cgo_undefined__; } + // #line xxx "not-type" + // void __cgo_f_xxx_2(void) { name *__cgo_undefined__; } + // #line xxx "not-const" + // void __cgo_f_xxx_3(void) { enum { __cgo_undefined__ = (name)*1 }; } + // + // If we see an error at not-declared:xxx, the corresponding name is not declared. + // If we see an error at not-type:xxx, the corresponding name is a type. + // If we see an error at not-const:xxx, the corresponding name is not an integer constant. + // If we see no errors, we assume the name is an expression but not a constant + // (so a variable or a function). + // + // The specific input forms are chosen so that they are valid C syntax regardless of + // whether name denotes a type or an expression. + + var b bytes.Buffer + b.WriteString(f.Preamble) + b.WriteString(builtinProlog) + + for i, n := range names { + fmt.Fprintf(&b, "#line %d \"not-declared\"\n"+ + "void __cgo_f_%d_1(void) { __typeof__(%s) *__cgo_undefined__; }\n"+ + "#line %d \"not-type\"\n"+ + "void __cgo_f_%d_2(void) { %s *__cgo_undefined__; }\n"+ + "#line %d \"not-const\"\n"+ + "void __cgo_f_%d_3(void) { enum { __cgo__undefined__ = (%s)*1 }; }\n", + i+1, i+1, n.C, + i+1, i+1, n.C, + i+1, i+1, n.C) + } + fmt.Fprintf(&b, "#line 1 \"completed\"\n"+ + "int __cgo__1 = __cgo__2;\n") + + stderr := p.gccErrors(b.Bytes()) + if stderr == "" { + fatalf("%s produced no output\non input:\n%s", p.gccBaseCmd()[0], b.Bytes()) + } + + completed := false + sniff := make([]int, len(names)) + const ( + notType = 1 << iota + notConst + notDeclared + ) + for _, line := range strings.Split(stderr, "\n") { + if !strings.Contains(line, ": error:") { + // we only care about errors. + // we tried to turn off warnings on the command line, but one never knows. + continue + } + + c1 := strings.Index(line, ":") + if c1 < 0 { + continue + } + c2 := strings.Index(line[c1+1:], ":") + if c2 < 0 { + continue + } + c2 += c1 + 1 + + filename := line[:c1] + i, _ := strconv.Atoi(line[c1+1 : c2]) + i-- + if i < 0 || i >= len(names) { + continue + } + + switch filename { + case "completed": + // Strictly speaking, there is no guarantee that seeing the error at completed:1 + // (at the end of the file) means we've seen all the errors from earlier in the file, + // but usually it does. Certainly if we don't see the completed:1 error, we did + // not get all the errors we expected. + completed = true + + case "not-declared": + sniff[i] |= notDeclared + case "not-type": + sniff[i] |= notType + case "not-const": + sniff[i] |= notConst + } + } + + if !completed { + fatalf("%s did not produce error at completed:1\non input:\n%s\nfull error output:\n%s", p.gccBaseCmd()[0], b.Bytes(), stderr) + } + + for i, n := range names { + switch sniff[i] { + default: + error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go)) + case notType: + n.Kind = "const" + case notConst: + n.Kind = "type" + case notConst | notType: + n.Kind = "not-type" + } + } + if nerrors > 0 { + // Check if compiling the preamble by itself causes any errors, + // because the messages we've printed out so far aren't helpful + // to users debugging preamble mistakes. See issue 8442. + preambleErrors := p.gccErrors([]byte(f.Preamble)) + if len(preambleErrors) > 0 { + error_(token.NoPos, "\n%s errors for preamble:\n%s", p.gccBaseCmd()[0], preambleErrors) + } + + fatalf("unresolved names") + } + + needType = append(needType, names...) + return needType +} + +// loadDWARF parses the DWARF debug information generated +// by gcc to learn the details of the constants, variables, and types +// being referred to as C.xxx. +func (p *Package) loadDWARF(f *File, names []*Name) { + // Extract the types from the DWARF section of an object + // from a well-formed C program. Gcc only generates DWARF info + // for symbols in the object file, so it is not enough to print the + // preamble and hope the symbols we care about will be there. + // Instead, emit + // __typeof__(names[i]) *__cgo__i; + // for each entry in names and then dereference the type we + // learn for __cgo__i. + var b bytes.Buffer + b.WriteString(f.Preamble) + b.WriteString(builtinProlog) + for i, n := range names { + fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i) + if n.Kind == "const" { + fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C) + } + } + + // Apple's LLVM-based gcc does not include the enumeration + // names and values in its DWARF debug output. In case we're + // using such a gcc, create a data block initialized with the values. + // We can read them out of the object file. + fmt.Fprintf(&b, "long long __cgodebug_data[] = {\n") + for _, n := range names { + if n.Kind == "const" { + fmt.Fprintf(&b, "\t%s,\n", n.C) + } else { + fmt.Fprintf(&b, "\t0,\n") + } + } + // for the last entry, we can not use 0, otherwise + // in case all __cgodebug_data is zero initialized, + // LLVM-based gcc will place the it in the __DATA.__common + // zero-filled section (our debug/macho doesn't support + // this) + fmt.Fprintf(&b, "\t1\n") + fmt.Fprintf(&b, "};\n") + + d, bo, debugData := p.gccDebug(b.Bytes()) + enumVal := make([]int64, len(debugData)/8) + for i := range enumVal { + enumVal[i] = int64(bo.Uint64(debugData[i*8:])) + } + + // Scan DWARF info for top-level TagVariable entries with AttrName __cgo__i. + types := make([]dwarf.Type, len(names)) + enums := make([]dwarf.Offset, len(names)) + nameToIndex := make(map[*Name]int) + for i, n := range names { + nameToIndex[n] = i + } + nameToRef := make(map[*Name]*Ref) + for _, ref := range f.Ref { + nameToRef[ref.Name] = ref + } + r := d.Reader() + for { + e, err := r.Next() + if err != nil { + fatalf("reading DWARF entry: %s", err) + } + if e == nil { + break + } + switch e.Tag { + case dwarf.TagEnumerationType: + offset := e.Offset + for { + e, err := r.Next() + if err != nil { + fatalf("reading DWARF entry: %s", err) + } + if e.Tag == 0 { + break + } + if e.Tag == dwarf.TagEnumerator { + entryName := e.Val(dwarf.AttrName).(string) + if strings.HasPrefix(entryName, "__cgo_enum__") { + n, _ := strconv.Atoi(entryName[len("__cgo_enum__"):]) + if 0 <= n && n < len(names) { + enums[n] = offset + } + } + } + } + case dwarf.TagVariable: + name, _ := e.Val(dwarf.AttrName).(string) + typOff, _ := e.Val(dwarf.AttrType).(dwarf.Offset) + if name == "" || typOff == 0 { + fatalf("malformed DWARF TagVariable entry") + } + if !strings.HasPrefix(name, "__cgo__") { + break + } + typ, err := d.Type(typOff) + if err != nil { + fatalf("loading DWARF type: %s", err) + } + t, ok := typ.(*dwarf.PtrType) + if !ok || t == nil { + fatalf("internal error: %s has non-pointer type", name) + } + i, err := strconv.Atoi(name[7:]) + if err != nil { + fatalf("malformed __cgo__ name: %s", name) + } + if enums[i] != 0 { + t, err := d.Type(enums[i]) + if err != nil { + fatalf("loading DWARF type: %s", err) + } + types[i] = t + } else { + types[i] = t.Type + } + } + if e.Tag != dwarf.TagCompileUnit { + r.SkipChildren() + } + } + + // Record types and typedef information. + var conv typeConv + conv.Init(p.PtrSize, p.IntSize) + for i, n := range names { + if types[i] == nil { + continue + } + pos := token.NoPos + if ref, ok := nameToRef[n]; ok { + pos = ref.Pos() + } + f, fok := types[i].(*dwarf.FuncType) + if n.Kind != "type" && fok { + n.Kind = "func" + n.FuncType = conv.FuncType(f, pos) + } else { + n.Type = conv.Type(types[i], pos) + if enums[i] != 0 && n.Type.EnumValues != nil { + k := fmt.Sprintf("__cgo_enum__%d", i) + n.Kind = "const" + n.Const = fmt.Sprintf("%#x", n.Type.EnumValues[k]) + // Remove injected enum to ensure the value will deep-compare + // equally in future loads of the same constant. + delete(n.Type.EnumValues, k) + } + // Prefer debug data over DWARF debug output, if we have it. + if n.Kind == "const" && i < len(enumVal) { + n.Const = fmt.Sprintf("%#x", enumVal[i]) + } + } + conv.FinishType(pos) + } +} + +// mangleName does name mangling to translate names +// from the original Go source files to the names +// used in the final Go files generated by cgo. +func (p *Package) mangleName(n *Name) { + // When using gccgo variables have to be + // exported so that they become global symbols + // that the C code can refer to. + prefix := "_C" + if *gccgo && n.IsVar() { + prefix = "C" + } + n.Mangle = prefix + n.Kind + "_" + n.Go +} + +// rewriteRef rewrites all the C.xxx references in f.AST to refer to the +// Go equivalents, now that we have figured out the meaning of all +// the xxx. In *godefs or *cdefs mode, rewriteRef replaces the names +// with full definitions instead of mangled names. +func (p *Package) rewriteRef(f *File) { + // Keep a list of all the functions, to remove the ones + // only used as expressions and avoid generating bridge + // code for them. + functions := make(map[string]bool) + + // Assign mangled names. + for _, n := range f.Name { + if n.Kind == "not-type" { + n.Kind = "var" + } + if n.Mangle == "" { + p.mangleName(n) + } + if n.Kind == "func" { + functions[n.Go] = false + } + } + + // Now that we have all the name types filled in, + // scan through the Refs to identify the ones that + // are trying to do a ,err call. Also check that + // functions are only used in calls. + for _, r := range f.Ref { + if r.Name.Kind == "const" && r.Name.Const == "" { + error_(r.Pos(), "unable to find value of constant C.%s", fixGo(r.Name.Go)) + } + var expr ast.Expr = ast.NewIdent(r.Name.Mangle) // default + switch r.Context { + case "call", "call2": + if r.Name.Kind != "func" { + if r.Name.Kind == "type" { + r.Context = "type" + expr = r.Name.Type.Go + break + } + error_(r.Pos(), "call of non-function C.%s", fixGo(r.Name.Go)) + break + } + functions[r.Name.Go] = true + if r.Context == "call2" { + if r.Name.Go == "_CMalloc" { + error_(r.Pos(), "no two-result form for C.malloc") + break + } + // Invent new Name for the two-result function. + n := f.Name["2"+r.Name.Go] + if n == nil { + n = new(Name) + *n = *r.Name + n.AddError = true + n.Mangle = "_C2func_" + n.Go + f.Name["2"+r.Name.Go] = n + } + expr = ast.NewIdent(n.Mangle) + r.Name = n + break + } + case "expr": + if r.Name.Kind == "func" { + // Function is being used in an expression, to e.g. pass around a C function pointer. + // Create a new Name for this Ref which causes the variable to be declared in Go land. + fpName := "fp_" + r.Name.Go + name := f.Name[fpName] + if name == nil { + name = &Name{ + Go: fpName, + C: r.Name.C, + Kind: "fpvar", + Type: &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*"), Go: ast.NewIdent("unsafe.Pointer")}, + } + p.mangleName(name) + f.Name[fpName] = name + } + r.Name = name + // Rewrite into call to _Cgo_ptr to prevent assignments. The _Cgo_ptr + // function is defined in out.go and simply returns its argument. See + // issue 7757. + expr = &ast.CallExpr{ + Fun: &ast.Ident{NamePos: (*r.Expr).Pos(), Name: "_Cgo_ptr"}, + Args: []ast.Expr{ast.NewIdent(name.Mangle)}, + } + } else if r.Name.Kind == "type" { + // Okay - might be new(T) + expr = r.Name.Type.Go + } else if r.Name.Kind == "var" { + expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr} + } + + case "type": + if r.Name.Kind != "type" { + error_(r.Pos(), "expression C.%s used as type", fixGo(r.Name.Go)) + } else if r.Name.Type == nil { + // Use of C.enum_x, C.struct_x or C.union_x without C definition. + // GCC won't raise an error when using pointers to such unknown types. + error_(r.Pos(), "type C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C) + } else { + expr = r.Name.Type.Go + } + default: + if r.Name.Kind == "func" { + error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go)) + } + } + if *godefs || *cdefs { + // Substitute definition for mangled type name. + if id, ok := expr.(*ast.Ident); ok { + if t := typedef[id.Name]; t != nil { + expr = t.Go + } + if id.Name == r.Name.Mangle && r.Name.Const != "" { + expr = ast.NewIdent(r.Name.Const) + } + } + } + + // Copy position information from old expr into new expr, + // in case expression being replaced is first on line. + // See golang.org/issue/6563. + pos := (*r.Expr).Pos() + switch x := expr.(type) { + case *ast.Ident: + expr = &ast.Ident{NamePos: pos, Name: x.Name} + } + + *r.Expr = expr + } + + // Remove functions only used as expressions, so their respective + // bridge functions are not generated. + for name, used := range functions { + if !used { + delete(f.Name, name) + } + } +} + +// gccBaseCmd returns the start of the compiler command line. +// It uses $CC if set, or else $GCC, or else the compiler recorded +// during the initial build as defaultCC. +// defaultCC is defined in zdefaultcc.go, written by cmd/dist. +func (p *Package) gccBaseCmd() []string { + // Use $CC if set, since that's what the build uses. + if ret := strings.Fields(os.Getenv("CC")); len(ret) > 0 { + return ret + } + // Try $GCC if set, since that's what we used to use. + if ret := strings.Fields(os.Getenv("GCC")); len(ret) > 0 { + return ret + } + return strings.Fields(defaultCC) +} + +// gccMachine returns the gcc -m flag to use, either "-m32", "-m64" or "-marm". +func (p *Package) gccMachine() []string { + switch goarch { + case "amd64": + return []string{"-m64"} + case "386": + return []string{"-m32"} + case "arm": + return []string{"-marm"} // not thumb + } + return nil +} + +func gccTmp() string { + return *objDir + "_cgo_.o" +} + +// gccCmd returns the gcc command line to use for compiling +// the input. +func (p *Package) gccCmd() []string { + c := append(p.gccBaseCmd(), + "-w", // no warnings + "-Wno-error", // warnings are not errors + "-o"+gccTmp(), // write object to tmp + "-gdwarf-2", // generate DWARF v2 debugging symbols + "-c", // do not link + "-xc", // input language is C + ) + if strings.Contains(c[0], "clang") { + c = append(c, + "-ferror-limit=0", + // Apple clang version 1.7 (tags/Apple/clang-77) (based on LLVM 2.9svn) + // doesn't have -Wno-unneeded-internal-declaration, so we need yet another + // flag to disable the warning. Yes, really good diagnostics, clang. + "-Wno-unknown-warning-option", + "-Wno-unneeded-internal-declaration", + "-Wno-unused-function", + "-Qunused-arguments", + // Clang embeds prototypes for some builtin functions, + // like malloc and calloc, but all size_t parameters are + // incorrectly typed unsigned long. We work around that + // by disabling the builtin functions (this is safe as + // it won't affect the actual compilation of the C code). + // See: http://golang.org/issue/6506. + "-fno-builtin", + ) + } + + c = append(c, p.GccOptions...) + c = append(c, p.gccMachine()...) + c = append(c, "-") //read input from standard input + return c +} + +// gccDebug runs gcc -gdwarf-2 over the C program stdin and +// returns the corresponding DWARF data and, if present, debug data block. +func (p *Package) gccDebug(stdin []byte) (*dwarf.Data, binary.ByteOrder, []byte) { + runGcc(stdin, p.gccCmd()) + + isDebugData := func(s string) bool { + // Some systems use leading _ to denote non-assembly symbols. + return s == "__cgodebug_data" || s == "___cgodebug_data" + } + + if f, err := macho.Open(gccTmp()); err == nil { + defer f.Close() + d, err := f.DWARF() + if err != nil { + fatalf("cannot load DWARF output from %s: %v", gccTmp(), err) + } + var data []byte + if f.Symtab != nil { + for i := range f.Symtab.Syms { + s := &f.Symtab.Syms[i] + if isDebugData(s.Name) { + // Found it. Now find data section. + if i := int(s.Sect) - 1; 0 <= i && i < len(f.Sections) { + sect := f.Sections[i] + if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size { + if sdat, err := sect.Data(); err == nil { + data = sdat[s.Value-sect.Addr:] + } + } + } + } + } + } + return d, f.ByteOrder, data + } + + if f, err := elf.Open(gccTmp()); err == nil { + defer f.Close() + d, err := f.DWARF() + if err != nil { + fatalf("cannot load DWARF output from %s: %v", gccTmp(), err) + } + var data []byte + symtab, err := f.Symbols() + if err == nil { + for i := range symtab { + s := &symtab[i] + if isDebugData(s.Name) { + // Found it. Now find data section. + if i := int(s.Section); 0 <= i && i < len(f.Sections) { + sect := f.Sections[i] + if sect.Addr <= s.Value && s.Value < sect.Addr+sect.Size { + if sdat, err := sect.Data(); err == nil { + data = sdat[s.Value-sect.Addr:] + } + } + } + } + } + } + return d, f.ByteOrder, data + } + + if f, err := pe.Open(gccTmp()); err == nil { + defer f.Close() + d, err := f.DWARF() + if err != nil { + fatalf("cannot load DWARF output from %s: %v", gccTmp(), err) + } + var data []byte + for _, s := range f.Symbols { + if isDebugData(s.Name) { + if i := int(s.SectionNumber) - 1; 0 <= i && i < len(f.Sections) { + sect := f.Sections[i] + if s.Value < sect.Size { + if sdat, err := sect.Data(); err == nil { + data = sdat[s.Value:] + } + } + } + } + } + return d, binary.LittleEndian, data + } + + fatalf("cannot parse gcc output %s as ELF, Mach-O, PE object", gccTmp()) + panic("not reached") +} + +// gccDefines runs gcc -E -dM -xc - over the C program stdin +// and returns the corresponding standard output, which is the +// #defines that gcc encountered while processing the input +// and its included files. +func (p *Package) gccDefines(stdin []byte) string { + base := append(p.gccBaseCmd(), "-E", "-dM", "-xc") + base = append(base, p.gccMachine()...) + stdout, _ := runGcc(stdin, append(append(base, p.GccOptions...), "-")) + return stdout +} + +// gccErrors runs gcc over the C program stdin and returns +// the errors that gcc prints. That is, this function expects +// gcc to fail. +func (p *Package) gccErrors(stdin []byte) string { + // TODO(rsc): require failure + args := p.gccCmd() + + if *debugGcc { + fmt.Fprintf(os.Stderr, "$ %s < 0 { + dtype := c.ptrKeys[0] + c.ptrKeys = c.ptrKeys[1:] + + // Note Type might invalidate c.ptrs[dtype]. + t := c.Type(dtype, pos) + for _, ptr := range c.ptrs[dtype] { + ptr.Go.(*ast.StarExpr).X = t.Go + ptr.C.Set("%s*", t.C) + } + c.ptrs[dtype] = nil // retain the map key + } +} + +// Type returns a *Type with the same memory layout as +// dtype when used as the type of a variable or a struct field. +func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { + if t, ok := c.m[dtype]; ok { + if t.Go == nil { + fatalf("%s: type conversion loop at %s", lineno(pos), dtype) + } + return t + } + + t := new(Type) + t.Size = dtype.Size() // note: wrong for array of pointers, corrected below + t.Align = -1 + t.C = &TypeRepr{Repr: dtype.Common().Name} + c.m[dtype] = t + + switch dt := dtype.(type) { + default: + fatalf("%s: unexpected type: %s", lineno(pos), dtype) + + case *dwarf.AddrType: + if t.Size != c.ptrSize { + fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype) + } + t.Go = c.uintptr + t.Align = t.Size + + case *dwarf.ArrayType: + if dt.StrideBitSize > 0 { + // Cannot represent bit-sized elements in Go. + t.Go = c.Opaque(t.Size) + break + } + count := dt.Count + if count == -1 { + // Indicates flexible array member, which Go doesn't support. + // Translate to zero-length array instead. + count = 0 + } + sub := c.Type(dt.Type, pos) + t.Align = sub.Align + t.Go = &ast.ArrayType{ + Len: c.intExpr(count), + Elt: sub.Go, + } + // Recalculate t.Size now that we know sub.Size. + t.Size = count * sub.Size + t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count) + + case *dwarf.BoolType: + t.Go = c.bool + t.Align = 1 + + case *dwarf.CharType: + if t.Size != 1 { + fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype) + } + t.Go = c.int8 + t.Align = 1 + + case *dwarf.EnumType: + if t.Align = t.Size; t.Align >= c.ptrSize { + t.Align = c.ptrSize + } + t.C.Set("enum " + dt.EnumName) + signed := 0 + t.EnumValues = make(map[string]int64) + for _, ev := range dt.Val { + t.EnumValues[ev.Name] = ev.Val + if ev.Val < 0 { + signed = signedDelta + } + } + switch t.Size + int64(signed) { + default: + fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype) + case 1: + t.Go = c.uint8 + case 2: + t.Go = c.uint16 + case 4: + t.Go = c.uint32 + case 8: + t.Go = c.uint64 + case 1 + signedDelta: + t.Go = c.int8 + case 2 + signedDelta: + t.Go = c.int16 + case 4 + signedDelta: + t.Go = c.int32 + case 8 + signedDelta: + t.Go = c.int64 + } + + case *dwarf.FloatType: + switch t.Size { + default: + fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype) + case 4: + t.Go = c.float32 + case 8: + t.Go = c.float64 + } + if t.Align = t.Size; t.Align >= c.ptrSize { + t.Align = c.ptrSize + } + + case *dwarf.ComplexType: + switch t.Size { + default: + fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype) + case 8: + t.Go = c.complex64 + case 16: + t.Go = c.complex128 + } + if t.Align = t.Size; t.Align >= c.ptrSize { + t.Align = c.ptrSize + } + + case *dwarf.FuncType: + // No attempt at translation: would enable calls + // directly between worlds, but we need to moderate those. + t.Go = c.uintptr + t.Align = c.ptrSize + + case *dwarf.IntType: + if dt.BitSize > 0 { + fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype) + } + switch t.Size { + default: + fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype) + case 1: + t.Go = c.int8 + case 2: + t.Go = c.int16 + case 4: + t.Go = c.int32 + case 8: + t.Go = c.int64 + } + if t.Align = t.Size; t.Align >= c.ptrSize { + t.Align = c.ptrSize + } + + case *dwarf.PtrType: + // Clang doesn't emit DW_AT_byte_size for pointer types. + if t.Size != c.ptrSize && t.Size != -1 { + fatalf("%s: unexpected: %d-byte pointer type - %s", lineno(pos), t.Size, dtype) + } + t.Size = c.ptrSize + t.Align = c.ptrSize + + if _, ok := base(dt.Type).(*dwarf.VoidType); ok { + t.Go = c.goVoidPtr + t.C.Set("void*") + break + } + + // Placeholder initialization; completed in FinishType. + t.Go = &ast.StarExpr{} + t.C.Set("*") + if _, ok := c.ptrs[dt.Type]; !ok { + c.ptrKeys = append(c.ptrKeys, dt.Type) + } + c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t) + + case *dwarf.QualType: + // Ignore qualifier. + t = c.Type(dt.Type, pos) + c.m[dtype] = t + return t + + case *dwarf.StructType: + // Convert to Go struct, being careful about alignment. + // Have to give it a name to simulate C "struct foo" references. + tag := dt.StructName + if dt.ByteSize < 0 && tag == "" { // opaque unnamed struct - should not be possible + break + } + if tag == "" { + tag = "__" + strconv.Itoa(tagGen) + tagGen++ + } else if t.C.Empty() { + t.C.Set(dt.Kind + " " + tag) + } + name := c.Ident("_Ctype_" + dt.Kind + "_" + tag) + t.Go = name // publish before recursive calls + goIdent[name.Name] = name + if dt.ByteSize < 0 { + // Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown), + // so execute the basic things that the struct case would do + // other than try to determine a Go representation. + tt := *t + tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}} + tt.Go = c.Ident("struct{}") + typedef[name.Name] = &tt + break + } + switch dt.Kind { + case "class", "union": + t.Go = c.Opaque(t.Size) + if t.C.Empty() { + t.C.Set("__typeof__(unsigned char[%d])", t.Size) + } + t.Align = 1 // TODO: should probably base this on field alignment. + typedef[name.Name] = t + case "struct": + g, csyntax, align := c.Struct(dt, pos) + if t.C.Empty() { + t.C.Set(csyntax) + } + t.Align = align + tt := *t + if tag != "" { + tt.C = &TypeRepr{"struct %s", []interface{}{tag}} + } + tt.Go = g + typedef[name.Name] = &tt + } + + case *dwarf.TypedefType: + // Record typedef for printing. + if dt.Name == "_GoString_" { + // Special C name for Go string type. + // Knows string layout used by compilers: pointer plus length, + // which rounds up to 2 pointers after alignment. + t.Go = c.string + t.Size = c.ptrSize * 2 + t.Align = c.ptrSize + break + } + if dt.Name == "_GoBytes_" { + // Special C name for Go []byte type. + // Knows slice layout used by compilers: pointer, length, cap. + t.Go = c.Ident("[]byte") + t.Size = c.ptrSize + 4 + 4 + t.Align = c.ptrSize + break + } + name := c.Ident("_Ctype_" + dt.Name) + goIdent[name.Name] = name + sub := c.Type(dt.Type, pos) + t.Go = name + t.Size = sub.Size + t.Align = sub.Align + oldType := typedef[name.Name] + if oldType == nil { + tt := *t + tt.Go = sub.Go + typedef[name.Name] = &tt + } + + // If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo", + // use that as the Go form for this typedef too, so that the typedef will be interchangeable + // with the base type. + // In -godefs and -cdefs mode, do this for all typedefs. + if isStructUnionClass(sub.Go) || *godefs || *cdefs { + t.Go = sub.Go + + if isStructUnionClass(sub.Go) { + // Use the typedef name for C code. + typedef[sub.Go.(*ast.Ident).Name].C = t.C + } + + // If we've seen this typedef before, and it + // was an anonymous struct/union/class before + // too, use the old definition. + // TODO: it would be safer to only do this if + // we verify that the types are the same. + if oldType != nil && isStructUnionClass(oldType.Go) { + t.Go = oldType.Go + } + } + + case *dwarf.UcharType: + if t.Size != 1 { + fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype) + } + t.Go = c.uint8 + t.Align = 1 + + case *dwarf.UintType: + if dt.BitSize > 0 { + fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype) + } + switch t.Size { + default: + fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype) + case 1: + t.Go = c.uint8 + case 2: + t.Go = c.uint16 + case 4: + t.Go = c.uint32 + case 8: + t.Go = c.uint64 + } + if t.Align = t.Size; t.Align >= c.ptrSize { + t.Align = c.ptrSize + } + + case *dwarf.VoidType: + t.Go = c.goVoid + t.C.Set("void") + t.Align = 1 + } + + switch dtype.(type) { + case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType: + s := dtype.Common().Name + if s != "" { + if ss, ok := dwarfToName[s]; ok { + s = ss + } + s = strings.Join(strings.Split(s, " "), "") // strip spaces + name := c.Ident("_Ctype_" + s) + tt := *t + typedef[name.Name] = &tt + if !*godefs && !*cdefs { + t.Go = name + } + } + } + + if t.Size < 0 { + // Unsized types are [0]byte, unless they're typedefs of other types + // or structs with tags. + // if so, use the name we've already defined. + t.Size = 0 + switch dt := dtype.(type) { + case *dwarf.TypedefType: + // ok + case *dwarf.StructType: + if dt.StructName != "" { + break + } + t.Go = c.Opaque(0) + default: + t.Go = c.Opaque(0) + } + if t.C.Empty() { + t.C.Set("void") + } + } + + if t.C.Empty() { + fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype) + } + + return t +} + +// isStructUnionClass reports whether the type described by the Go syntax x +// is a struct, union, or class with a tag. +func isStructUnionClass(x ast.Expr) bool { + id, ok := x.(*ast.Ident) + if !ok { + return false + } + name := id.Name + return strings.HasPrefix(name, "_Ctype_struct_") || + strings.HasPrefix(name, "_Ctype_union_") || + strings.HasPrefix(name, "_Ctype_class_") +} + +// FuncArg returns a Go type with the same memory layout as +// dtype when used as the type of a C function argument. +func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type { + t := c.Type(dtype, pos) + switch dt := dtype.(type) { + case *dwarf.ArrayType: + // Arrays are passed implicitly as pointers in C. + // In Go, we must be explicit. + tr := &TypeRepr{} + tr.Set("%s*", t.C) + return &Type{ + Size: c.ptrSize, + Align: c.ptrSize, + Go: &ast.StarExpr{X: t.Go}, + C: tr, + } + case *dwarf.TypedefType: + // C has much more relaxed rules than Go for + // implicit type conversions. When the parameter + // is type T defined as *X, simulate a little of the + // laxness of C by making the argument *X instead of T. + if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok { + // Unless the typedef happens to point to void* since + // Go has special rules around using unsafe.Pointer. + if _, void := base(ptr.Type).(*dwarf.VoidType); void { + break + } + + t = c.Type(ptr, pos) + if t == nil { + return nil + } + + // Remember the C spelling, in case the struct + // has __attribute__((unavailable)) on it. See issue 2888. + t.Typedef = dt.Name + } + } + return t +} + +// FuncType returns the Go type analogous to dtype. +// There is no guarantee about matching memory layout. +func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType { + p := make([]*Type, len(dtype.ParamType)) + gp := make([]*ast.Field, len(dtype.ParamType)) + for i, f := range dtype.ParamType { + // gcc's DWARF generator outputs a single DotDotDotType parameter for + // function pointers that specify no parameters (e.g. void + // (*__cgo_0)()). Treat this special case as void. This case is + // invalid according to ISO C anyway (i.e. void (*__cgo_1)(...) is not + // legal). + if _, ok := f.(*dwarf.DotDotDotType); ok && i == 0 { + p, gp = nil, nil + break + } + p[i] = c.FuncArg(f, pos) + gp[i] = &ast.Field{Type: p[i].Go} + } + var r *Type + var gr []*ast.Field + if _, ok := dtype.ReturnType.(*dwarf.VoidType); ok { + gr = []*ast.Field{{Type: c.goVoid}} + } else if dtype.ReturnType != nil { + r = c.Type(dtype.ReturnType, pos) + gr = []*ast.Field{{Type: r.Go}} + } + return &FuncType{ + Params: p, + Result: r, + Go: &ast.FuncType{ + Params: &ast.FieldList{List: gp}, + Results: &ast.FieldList{List: gr}, + }, + } +} + +// Identifier +func (c *typeConv) Ident(s string) *ast.Ident { + return ast.NewIdent(s) +} + +// Opaque type of n bytes. +func (c *typeConv) Opaque(n int64) ast.Expr { + return &ast.ArrayType{ + Len: c.intExpr(n), + Elt: c.byte, + } +} + +// Expr for integer n. +func (c *typeConv) intExpr(n int64) ast.Expr { + return &ast.BasicLit{ + Kind: token.INT, + Value: strconv.FormatInt(n, 10), + } +} + +// Add padding of given size to fld. +func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field { + n := len(fld) + fld = fld[0 : n+1] + fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident("_")}, Type: c.Opaque(size)} + return fld +} + +// Struct conversion: return Go and (6g) C syntax for type. +func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) { + // Minimum alignment for a struct is 1 byte. + align = 1 + + var buf bytes.Buffer + buf.WriteString("struct {") + fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field + off := int64(0) + + // Rename struct fields that happen to be named Go keywords into + // _{keyword}. Create a map from C ident -> Go ident. The Go ident will + // be mangled. Any existing identifier that already has the same name on + // the C-side will cause the Go-mangled version to be prefixed with _. + // (e.g. in a struct with fields '_type' and 'type', the latter would be + // rendered as '__type' in Go). + ident := make(map[string]string) + used := make(map[string]bool) + for _, f := range dt.Field { + ident[f.Name] = f.Name + used[f.Name] = true + } + + if !*godefs && !*cdefs { + for cid, goid := range ident { + if token.Lookup(goid).IsKeyword() { + // Avoid keyword + goid = "_" + goid + + // Also avoid existing fields + for _, exist := used[goid]; exist; _, exist = used[goid] { + goid = "_" + goid + } + + used[goid] = true + ident[cid] = goid + } + } + } + + anon := 0 + for _, f := range dt.Field { + if f.ByteOffset > off { + fld = c.pad(fld, f.ByteOffset-off) + off = f.ByteOffset + } + + name := f.Name + ft := f.Type + + // In godefs or cdefs mode, if this field is a C11 + // anonymous union then treat the first field in the + // union as the field in the struct. This handles + // cases like the glibc file; see + // issue 6677. + if *godefs || *cdefs { + if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] { + name = st.Field[0].Name + ident[name] = name + ft = st.Field[0].Type + } + } + + // TODO: Handle fields that are anonymous structs by + // promoting the fields of the inner struct. + + t := c.Type(ft, pos) + tgo := t.Go + size := t.Size + talign := t.Align + if f.BitSize > 0 { + if f.BitSize%8 != 0 { + continue + } + size = f.BitSize / 8 + name := tgo.(*ast.Ident).String() + if strings.HasPrefix(name, "int") { + name = "int" + } else { + name = "uint" + } + tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize)) + talign = size + } + + if talign > 0 && f.ByteOffset%talign != 0 && !*cdefs { + // Drop misaligned fields, the same way we drop integer bit fields. + // The goal is to make available what can be made available. + // Otherwise one bad and unneeded field in an otherwise okay struct + // makes the whole program not compile. Much of the time these + // structs are in system headers that cannot be corrected. + // Exception: In -cdefs mode, we use #pragma pack, so misaligned + // fields should still work. + continue + } + n := len(fld) + fld = fld[0 : n+1] + if name == "" { + name = fmt.Sprintf("anon%d", anon) + anon++ + ident[name] = name + } + fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[name])}, Type: tgo} + off += size + buf.WriteString(t.C.String()) + buf.WriteString(" ") + buf.WriteString(name) + buf.WriteString("; ") + if talign > align { + align = talign + } + } + if off < dt.ByteSize { + fld = c.pad(fld, dt.ByteSize-off) + off = dt.ByteSize + } + if off != dt.ByteSize { + fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize) + } + buf.WriteString("}") + csyntax = buf.String() + + if *godefs || *cdefs { + godefsFields(fld) + } + expr = &ast.StructType{Fields: &ast.FieldList{List: fld}} + return +} + +func upper(s string) string { + if s == "" { + return "" + } + r, size := utf8.DecodeRuneInString(s) + if r == '_' { + return "X" + s + } + return string(unicode.ToUpper(r)) + s[size:] +} + +// godefsFields rewrites field names for use in Go or C definitions. +// It strips leading common prefixes (like tv_ in tv_sec, tv_usec) +// converts names to upper case, and rewrites _ into Pad_godefs_n, +// so that all fields are exported. +func godefsFields(fld []*ast.Field) { + prefix := fieldPrefix(fld) + npad := 0 + for _, f := range fld { + for _, n := range f.Names { + if n.Name != prefix { + n.Name = strings.TrimPrefix(n.Name, prefix) + } + if n.Name == "_" { + // Use exported name instead. + n.Name = "Pad_cgo_" + strconv.Itoa(npad) + npad++ + } + if !*cdefs { + n.Name = upper(n.Name) + } + } + } +} + +// fieldPrefix returns the prefix that should be removed from all the +// field names when generating the C or Go code. For generated +// C, we leave the names as is (tv_sec, tv_usec), since that's what +// people are used to seeing in C. For generated Go code, such as +// package syscall's data structures, we drop a common prefix +// (so sec, usec, which will get turned into Sec, Usec for exporting). +func fieldPrefix(fld []*ast.Field) string { + if *cdefs { + return "" + } + prefix := "" + for _, f := range fld { + for _, n := range f.Names { + // Ignore field names that don't have the prefix we're + // looking for. It is common in C headers to have fields + // named, say, _pad in an otherwise prefixed header. + // If the struct has 3 fields tv_sec, tv_usec, _pad1, then we + // still want to remove the tv_ prefix. + // The check for "orig_" here handles orig_eax in the + // x86 ptrace register sets, which otherwise have all fields + // with reg_ prefixes. + if strings.HasPrefix(n.Name, "orig_") || strings.HasPrefix(n.Name, "_") { + continue + } + i := strings.Index(n.Name, "_") + if i < 0 { + continue + } + if prefix == "" { + prefix = n.Name[:i+1] + } else if prefix != n.Name[:i+1] { + return "" + } + } + } + return prefix +} diff --git a/libgo/go/cmd/cgo/godefs.go b/libgo/go/cmd/cgo/godefs.go new file mode 100644 index 0000000000..ce5ac2736c --- /dev/null +++ b/libgo/go/cmd/cgo/godefs.go @@ -0,0 +1,294 @@ +// 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 main + +import ( + "bytes" + "fmt" + "go/ast" + "go/printer" + "go/token" + "os" + "strings" +) + +// godefs returns the output for -godefs mode. +func (p *Package) godefs(f *File, srcfile string) string { + var buf bytes.Buffer + + fmt.Fprintf(&buf, "// Created by cgo -godefs - DO NOT EDIT\n") + fmt.Fprintf(&buf, "// %s\n", strings.Join(os.Args, " ")) + fmt.Fprintf(&buf, "\n") + + override := make(map[string]string) + + // Allow source file to specify override mappings. + // For example, the socket data structures refer + // to in_addr and in_addr6 structs but we want to be + // able to treat them as byte arrays, so the godefs + // inputs in package syscall say + // + // // +godefs map struct_in_addr [4]byte + // // +godefs map struct_in_addr6 [16]byte + // + for _, g := range f.Comments { + for _, c := range g.List { + i := strings.Index(c.Text, "+godefs map") + if i < 0 { + continue + } + s := strings.TrimSpace(c.Text[i+len("+godefs map"):]) + i = strings.Index(s, " ") + if i < 0 { + fmt.Fprintf(os.Stderr, "invalid +godefs map comment: %s\n", c.Text) + continue + } + override["_Ctype_"+strings.TrimSpace(s[:i])] = strings.TrimSpace(s[i:]) + } + } + for _, n := range f.Name { + if s := override[n.Go]; s != "" { + override[n.Mangle] = s + } + } + + // Otherwise, if the source file says type T C.whatever, + // use "T" as the mangling of C.whatever, + // except in the definition (handled at end of function). + refName := make(map[*ast.Expr]*Name) + for _, r := range f.Ref { + refName[r.Expr] = r.Name + } + for _, d := range f.AST.Decls { + d, ok := d.(*ast.GenDecl) + if !ok || d.Tok != token.TYPE { + continue + } + for _, s := range d.Specs { + s := s.(*ast.TypeSpec) + n := refName[&s.Type] + if n != nil && n.Mangle != "" { + override[n.Mangle] = s.Name.Name + } + } + } + + // Extend overrides using typedefs: + // If we know that C.xxx should format as T + // and xxx is a typedef for yyy, make C.yyy format as T. + for typ, def := range typedef { + if new := override[typ]; new != "" { + if id, ok := def.Go.(*ast.Ident); ok { + override[id.Name] = new + } + } + } + + // Apply overrides. + for old, new := range override { + if id := goIdent[old]; id != nil { + id.Name = new + } + } + + // Any names still using the _C syntax are not going to compile, + // although in general we don't know whether they all made it + // into the file, so we can't warn here. + // + // The most common case is union types, which begin with + // _Ctype_union and for which typedef[name] is a Go byte + // array of the appropriate size (such as [4]byte). + // Substitute those union types with byte arrays. + for name, id := range goIdent { + if id.Name == name && strings.Contains(name, "_Ctype_union") { + if def := typedef[name]; def != nil { + id.Name = gofmt(def) + } + } + } + + conf.Fprint(&buf, fset, f.AST) + + return buf.String() +} + +// cdefs returns the output for -cdefs mode. +// The easiest way to do this is to translate the godefs Go to C. +func (p *Package) cdefs(f *File, srcfile string) string { + godefsOutput := p.godefs(f, srcfile) + + lines := strings.Split(godefsOutput, "\n") + lines[0] = "// Created by cgo -cdefs - DO NOT EDIT" + + for i, line := range lines { + lines[i] = strings.TrimSpace(line) + } + + var out bytes.Buffer + printf := func(format string, args ...interface{}) { fmt.Fprintf(&out, format, args...) } + + didTypedef := false + for i := 0; i < len(lines); i++ { + line := lines[i] + + // Delete + // package x + if strings.HasPrefix(line, "package ") { + continue + } + + // Convert + // const ( + // A = 1 + // B = 2 + // ) + // + // to + // + // enum { + // A = 1, + // B = 2, + // }; + if line == "const (" { + printf("enum {\n") + for i++; i < len(lines) && lines[i] != ")"; i++ { + line = lines[i] + if line != "" { + printf("\t%s,", line) + } + printf("\n") + } + printf("};\n") + continue + } + + // Convert + // const A = 1 + // to + // enum { A = 1 }; + if strings.HasPrefix(line, "const ") { + printf("enum { %s };\n", line[len("const "):]) + continue + } + + // On first type definition, typedef all the structs + // in case there are dependencies between them. + if !didTypedef && strings.HasPrefix(line, "type ") { + didTypedef = true + for _, line := range lines { + line = strings.TrimSpace(line) + if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") { + s := strings.TrimSuffix(strings.TrimPrefix(line, "type "), " struct {") + printf("typedef struct %s %s;\n", s, s) + } + } + printf("\n") + printf("#pragma pack on\n") + printf("\n") + } + + // Convert + // type T struct { + // X int64 + // Y *int32 + // Z [4]byte + // } + // + // to + // + // struct T { + // int64 X; + // int32 *Y; + // byte Z[4]; + // } + if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") { + if len(lines) > i+1 && lines[i+1] == "}" { + // do not output empty struct + i++ + continue + } + s := line[len("type ") : len(line)-len(" struct {")] + printf("struct %s {\n", s) + for i++; i < len(lines) && lines[i] != "}"; i++ { + line := lines[i] + if line != "" { + f := strings.Fields(line) + if len(f) != 2 { + fmt.Fprintf(os.Stderr, "cgo: cannot parse struct field: %s\n", line) + nerrors++ + continue + } + printf("\t%s;", cdecl(f[0], f[1])) + } + printf("\n") + } + printf("};\n") + continue + } + + // Convert + // type T int + // to + // typedef int T; + if strings.HasPrefix(line, "type ") { + f := strings.Fields(line[len("type "):]) + if len(f) != 2 { + fmt.Fprintf(os.Stderr, "cgo: cannot parse type definition: %s\n", line) + nerrors++ + continue + } + printf("typedef\t%s;\n", cdecl(f[0], f[1])) + continue + } + + printf("%s\n", line) + } + + if didTypedef { + printf("\n") + printf("#pragma pack off\n") + } + + return out.String() +} + +// cdecl returns the C declaration for the given Go name and type. +// It only handles the specific cases necessary for converting godefs output. +func cdecl(name, typ string) string { + // X *[0]byte -> X *void + if strings.HasPrefix(typ, "*[0]") { + typ = "*void" + } + // X [4]byte -> X[4] byte + for strings.HasPrefix(typ, "[") { + i := strings.Index(typ, "]") + 1 + name = name + typ[:i] + typ = typ[i:] + } + // X *byte -> *X byte + for strings.HasPrefix(typ, "*") { + name = "*" + name + typ = typ[1:] + } + // X T -> T X + // Handle the special case: 'unsafe.Pointer' is 'void *' + if typ == "unsafe.Pointer" { + typ = "void" + name = "*" + name + } + return typ + "\t" + name +} + +var gofmtBuf bytes.Buffer + +// gofmt returns the gofmt-formatted string for an AST node. +func gofmt(n interface{}) string { + gofmtBuf.Reset() + err := printer.Fprint(&gofmtBuf, fset, n) + if err != nil { + return "<" + err.Error() + ">" + } + return gofmtBuf.String() +} diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go new file mode 100644 index 0000000000..48257fc6c4 --- /dev/null +++ b/libgo/go/cmd/cgo/main.go @@ -0,0 +1,382 @@ +// 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. + +// Cgo; see gmp.go for an overview. + +// TODO(rsc): +// Emit correct line number annotations. +// Make 6g understand the annotations. + +package main + +import ( + "crypto/md5" + "flag" + "fmt" + "go/ast" + "go/printer" + "go/token" + "io" + "os" + "path/filepath" + "reflect" + "runtime" + "sort" + "strings" +) + +// A Package collects information about the package we're going to write. +type Package struct { + PackageName string // name of package + PackagePath string + PtrSize int64 + IntSize int64 + GccOptions []string + CgoFlags map[string][]string // #cgo flags (CFLAGS, LDFLAGS) + Written map[string]bool + Name map[string]*Name // accumulated Name from Files + ExpFunc []*ExpFunc // accumulated ExpFunc from Files + Decl []ast.Decl + GoFiles []string // list of Go files + GccFiles []string // list of gcc output files + Preamble string // collected preamble for _cgo_export.h +} + +// A File collects information about a single Go input file. +type File struct { + AST *ast.File // parsed AST + Comments []*ast.CommentGroup // comments from file + Package string // Package name + Preamble string // C preamble (doc comment on import "C") + Ref []*Ref // all references to C.xxx in AST + ExpFunc []*ExpFunc // exported functions for this file + Name map[string]*Name // map from Go name to Name +} + +func nameKeys(m map[string]*Name) []string { + var ks []string + for k := range m { + ks = append(ks, k) + } + sort.Strings(ks) + return ks +} + +// A Ref refers to an expression of the form C.xxx in the AST. +type Ref struct { + Name *Name + Expr *ast.Expr + Context string // "type", "expr", "call", or "call2" +} + +func (r *Ref) Pos() token.Pos { + return (*r.Expr).Pos() +} + +// A Name collects information about C.xxx. +type Name struct { + Go string // name used in Go referring to package C + Mangle string // name used in generated Go + C string // name used in C + Define string // #define expansion + Kind string // "const", "type", "var", "fpvar", "func", "not-type" + Type *Type // the type of xxx + FuncType *FuncType + AddError bool + Const string // constant definition +} + +// IsVar returns true if Kind is either "var" or "fpvar" +func (n *Name) IsVar() bool { + return n.Kind == "var" || n.Kind == "fpvar" +} + +// A ExpFunc is an exported function, callable from C. +// Such functions are identified in the Go input file +// by doc comments containing the line //export ExpName +type ExpFunc struct { + Func *ast.FuncDecl + ExpName string // name to use from C +} + +// A TypeRepr contains the string representation of a type. +type TypeRepr struct { + Repr string + FormatArgs []interface{} +} + +// A Type collects information about a type in both the C and Go worlds. +type Type struct { + Size int64 + Align int64 + C *TypeRepr + Go ast.Expr + EnumValues map[string]int64 + Typedef string +} + +// A FuncType collects information about a function type in both the C and Go worlds. +type FuncType struct { + Params []*Type + Result *Type + Go *ast.FuncType +} + +func usage() { + fmt.Fprint(os.Stderr, "usage: cgo -- [compiler options] file.go ...\n") + flag.PrintDefaults() + os.Exit(2) +} + +var ptrSizeMap = map[string]int64{ + "386": 4, + "alpha": 8, + "amd64": 8, + "arm": 4, + "arm64": 8, + "m68k": 4, + "mipso32": 4, + "mipsn32": 4, + "mipso64": 8, + "mipsn64": 8, + "ppc": 4, + "ppc64": 8, + "ppc64le": 8, + "s390": 4, + "s390x": 8, + "sparc": 4, + "sparc64": 8, +} + +var intSizeMap = map[string]int64{ + "386": 4, + "alpha": 8, + "amd64": 8, + "arm": 4, + "arm64": 8, + "m68k": 4, + "mipso32": 4, + "mipsn32": 4, + "mipso64": 8, + "mipsn64": 8, + "ppc": 4, + "ppc64": 8, + "ppc64le": 8, + "s390": 4, + "s390x": 8, + "sparc": 4, + "sparc64": 8, +} + +var cPrefix string + +var fset = token.NewFileSet() + +var dynobj = flag.String("dynimport", "", "if non-empty, print dynamic import data for that file") +var dynout = flag.String("dynout", "", "write -dynobj output to this file") +var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in dynimport mode") + +// These flags are for bootstrapping a new Go implementation, +// to generate Go and C headers that match the data layout and +// constant values used in the host's C libraries and system calls. +var godefs = flag.Bool("godefs", false, "for bootstrap: write Go definitions for C file to standard output") +var cdefs = flag.Bool("cdefs", false, "for bootstrap: write C definitions for C file to standard output") +var objDir = flag.String("objdir", "", "object directory") + +var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo") +var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo") +var gccgopkgpath = flag.String("gccgopkgpath", "", "-fgo-pkgpath option used with gccgo") +var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo in generated code") +var importSyscall = flag.Bool("import_syscall", true, "import syscall in generated code") +var goarch, goos string + +func main() { + flag.Usage = usage + flag.Parse() + + if *dynobj != "" { + // cgo -dynimport is essentially a separate helper command + // built into the cgo binary. It scans a gcc-produced executable + // and dumps information about the imported symbols and the + // imported libraries. The 'go build' rules for cgo prepare an + // appropriate executable and then use its import information + // instead of needing to make the linkers duplicate all the + // specialized knowledge gcc has about where to look for imported + // symbols and which ones to use. + dynimport(*dynobj) + return + } + + if *godefs && *cdefs { + fmt.Fprintf(os.Stderr, "cgo: cannot use -cdefs and -godefs together\n") + os.Exit(2) + } + + if *godefs || *cdefs { + // Generating definitions pulled from header files, + // to be checked into Go repositories. + // Line numbers are just noise. + conf.Mode &^= printer.SourcePos + } + + args := flag.Args() + if len(args) < 1 { + usage() + } + + // Find first arg that looks like a go file and assume everything before + // that are options to pass to gcc. + var i int + for i = len(args); i > 0; i-- { + if !strings.HasSuffix(args[i-1], ".go") { + break + } + } + if i == len(args) { + usage() + } + + goFiles := args[i:] + + p := newPackage(args[:i]) + + // Record CGO_LDFLAGS from the environment for external linking. + if ldflags := os.Getenv("CGO_LDFLAGS"); ldflags != "" { + args, err := splitQuoted(ldflags) + if err != nil { + fatalf("bad CGO_LDFLAGS: %q (%s)", ldflags, err) + } + p.addToFlag("LDFLAGS", args) + } + + // Need a unique prefix for the global C symbols that + // we use to coordinate between gcc and ourselves. + // We already put _cgo_ at the beginning, so the main + // concern is other cgo wrappers for the same functions. + // Use the beginning of the md5 of the input to disambiguate. + h := md5.New() + for _, input := range goFiles { + f, err := os.Open(input) + if err != nil { + fatalf("%s", err) + } + io.Copy(h, f) + f.Close() + } + cPrefix = fmt.Sprintf("_%x", h.Sum(nil)[0:6]) + + fs := make([]*File, len(goFiles)) + for i, input := range goFiles { + f := new(File) + f.ReadGo(input) + f.DiscardCgoDirectives() + fs[i] = f + } + + if *objDir == "" { + // make sure that _obj directory exists, so that we can write + // all the output files there. + os.Mkdir("_obj", 0777) + *objDir = "_obj" + } + *objDir += string(filepath.Separator) + + for i, input := range goFiles { + f := fs[i] + p.Translate(f) + for _, cref := range f.Ref { + switch cref.Context { + case "call", "call2": + if cref.Name.Kind != "type" { + break + } + *cref.Expr = cref.Name.Type.Go + } + } + if nerrors > 0 { + os.Exit(2) + } + pkg := f.Package + if dir := os.Getenv("CGOPKGPATH"); dir != "" { + pkg = filepath.Join(dir, pkg) + } + p.PackagePath = pkg + p.Record(f) + if *godefs { + os.Stdout.WriteString(p.godefs(f, input)) + } else if *cdefs { + os.Stdout.WriteString(p.cdefs(f, input)) + } else { + p.writeOutput(f, input) + } + } + + if !*godefs && !*cdefs { + p.writeDefs() + } + if nerrors > 0 { + os.Exit(2) + } +} + +// newPackage returns a new Package that will invoke +// gcc with the additional arguments specified in args. +func newPackage(args []string) *Package { + goarch = runtime.GOARCH + if s := os.Getenv("GOARCH"); s != "" { + goarch = s + } + goos = runtime.GOOS + if s := os.Getenv("GOOS"); s != "" { + goos = s + } + ptrSize := ptrSizeMap[goarch] + if ptrSize == 0 { + fatalf("unknown ptrSize for $GOARCH %q", goarch) + } + intSize := intSizeMap[goarch] + if intSize == 0 { + fatalf("unknown intSize for $GOARCH %q", goarch) + } + + // Reset locale variables so gcc emits English errors [sic]. + os.Setenv("LANG", "en_US.UTF-8") + os.Setenv("LC_ALL", "C") + + p := &Package{ + PtrSize: ptrSize, + IntSize: intSize, + CgoFlags: make(map[string][]string), + Written: make(map[string]bool), + } + p.addToFlag("CFLAGS", args) + return p +} + +// Record what needs to be recorded about f. +func (p *Package) Record(f *File) { + if p.PackageName == "" { + p.PackageName = f.Package + } else if p.PackageName != f.Package { + error_(token.NoPos, "inconsistent package names: %s, %s", p.PackageName, f.Package) + } + + if p.Name == nil { + p.Name = f.Name + } else { + for k, v := range f.Name { + if p.Name[k] == nil { + p.Name[k] = v + } else if !reflect.DeepEqual(p.Name[k], v) { + error_(token.NoPos, "inconsistent definitions for C.%s", fixGo(k)) + } + } + } + + if f.ExpFunc != nil { + p.ExpFunc = append(p.ExpFunc, f.ExpFunc...) + p.Preamble += "\n" + f.Preamble + } + p.Decl = append(p.Decl, f.AST.Decls...) +} diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go new file mode 100644 index 0000000000..d92bed9bf0 --- /dev/null +++ b/libgo/go/cmd/cgo/out.go @@ -0,0 +1,1334 @@ +// 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 main + +import ( + "bytes" + "debug/elf" + "debug/macho" + "debug/pe" + "fmt" + "go/ast" + "go/printer" + "go/token" + "os" + "sort" + "strings" +) + +var conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8} + +// writeDefs creates output files to be compiled by 6g, 6c, and gcc. +// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.) +func (p *Package) writeDefs() { + fgo2 := creat(*objDir + "_cgo_gotypes.go") + fc := creat(*objDir + "_cgo_defun.c") + fm := creat(*objDir + "_cgo_main.c") + + var gccgoInit bytes.Buffer + + fflg := creat(*objDir + "_cgo_flags") + for k, v := range p.CgoFlags { + fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " ")) + if k == "LDFLAGS" && !*gccgo { + for _, arg := range v { + fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg) + } + } + } + fflg.Close() + + // Write C main file for using gcc to resolve imports. + fmt.Fprintf(fm, "int main() { return 0; }\n") + if *importRuntimeCgo { + fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n") + fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n") + } else { + // If we're not importing runtime/cgo, we *are* runtime/cgo, + // which provides crosscall2. We just need a prototype. + fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c);\n") + } + fmt.Fprintf(fm, "void _cgo_allocate(void *a, int c) { }\n") + fmt.Fprintf(fm, "void _cgo_panic(void *a, int c) { }\n") + + // Write second Go output: definitions of _C_xxx. + // In a separate file so that the import of "unsafe" does not + // pollute the original file. + fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n") + fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName) + fmt.Fprintf(fgo2, "import \"unsafe\"\n\n") + if !*gccgo && *importRuntimeCgo { + fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n") + } + if *importSyscall { + fmt.Fprintf(fgo2, "import \"syscall\"\n\n") + fmt.Fprintf(fgo2, "var _ syscall.Errno\n") + } + fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n") + + typedefNames := make([]string, 0, len(typedef)) + for name := range typedef { + typedefNames = append(typedefNames, name) + } + sort.Strings(typedefNames) + for _, name := range typedefNames { + def := typedef[name] + fmt.Fprintf(fgo2, "type %s ", name) + conf.Fprint(fgo2, fset, def.Go) + fmt.Fprintf(fgo2, "\n\n") + } + if *gccgo { + fmt.Fprintf(fgo2, "type _Ctype_void byte\n") + } else { + fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n") + } + + if *gccgo { + fmt.Fprint(fc, p.cPrologGccgo()) + } else { + fmt.Fprint(fc, cProlog) + fmt.Fprint(fgo2, goProlog) + } + + gccgoSymbolPrefix := p.gccgoSymbolPrefix() + + cVars := make(map[string]bool) + for _, key := range nameKeys(p.Name) { + n := p.Name[key] + if !n.IsVar() { + continue + } + + if !cVars[n.C] { + fmt.Fprintf(fm, "extern char %s[];\n", n.C) + fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C) + + if !*gccgo { + fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C) + } + + fmt.Fprintf(fc, "extern byte *%s;\n", n.C) + + cVars[n.C] = true + } + var amp string + var node ast.Node + if n.Kind == "var" { + amp = "&" + node = &ast.StarExpr{X: n.Type.Go} + } else if n.Kind == "fpvar" { + node = n.Type.Go + if *gccgo { + amp = "&" + } + } else { + panic(fmt.Errorf("invalid var kind %q", n.Kind)) + } + if *gccgo { + fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle) + fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C) + } else { + fmt.Fprintf(fc, "#pragma dataflag NOPTR /* C pointer, not heap pointer */ \n") + fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n.C) + } + fmt.Fprintf(fc, "\n") + + fmt.Fprintf(fgo2, "var %s ", n.Mangle) + conf.Fprint(fgo2, fset, node) + fmt.Fprintf(fgo2, "\n") + } + fmt.Fprintf(fc, "\n") + + for _, key := range nameKeys(p.Name) { + n := p.Name[key] + if n.Const != "" { + fmt.Fprintf(fgo2, "const _Cconst_%s = %s\n", n.Go, n.Const) + } + } + fmt.Fprintf(fgo2, "\n") + + for _, key := range nameKeys(p.Name) { + n := p.Name[key] + if n.FuncType != nil { + p.writeDefsFunc(fc, fgo2, n) + } + } + + if *gccgo { + p.writeGccgoExports(fgo2, fc, fm) + } else { + p.writeExports(fgo2, fc, fm) + } + + init := gccgoInit.String() + if init != "" { + fmt.Fprintln(fc, "static void init(void) __attribute__ ((constructor));") + fmt.Fprintln(fc, "static void init(void) {") + fmt.Fprint(fc, init) + fmt.Fprintln(fc, "}") + } + + fgo2.Close() + fc.Close() +} + +func dynimport(obj string) { + stdout := os.Stdout + if *dynout != "" { + f, err := os.Create(*dynout) + if err != nil { + fatalf("%s", err) + } + stdout = f + } + + if f, err := elf.Open(obj); err == nil { + if *dynlinker { + // Emit the cgo_dynamic_linker line. + if sec := f.Section(".interp"); sec != nil { + if data, err := sec.Data(); err == nil && len(data) > 1 { + // skip trailing \0 in data + fmt.Fprintf(stdout, "#pragma cgo_dynamic_linker %q\n", string(data[:len(data)-1])) + } + } + } + sym, err := f.ImportedSymbols() + if err != nil { + fatalf("cannot load imported symbols from ELF file %s: %v", obj, err) + } + for _, s := range sym { + targ := s.Name + if s.Version != "" { + targ += "#" + s.Version + } + fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library) + } + lib, err := f.ImportedLibraries() + if err != nil { + fatalf("cannot load imported libraries from ELF file %s: %v", obj, err) + } + for _, l := range lib { + fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l) + } + return + } + + if f, err := macho.Open(obj); err == nil { + sym, err := f.ImportedSymbols() + if err != nil { + fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err) + } + for _, s := range sym { + if len(s) > 0 && s[0] == '_' { + s = s[1:] + } + fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s, s, "") + } + lib, err := f.ImportedLibraries() + if err != nil { + fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err) + } + for _, l := range lib { + fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l) + } + return + } + + if f, err := pe.Open(obj); err == nil { + sym, err := f.ImportedSymbols() + if err != nil { + fatalf("cannot load imported symbols from PE file %s: %v", obj, err) + } + for _, s := range sym { + ss := strings.Split(s, ":") + name := strings.Split(ss[0], "@")[0] + fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1])) + } + return + } + + fatalf("cannot parse %s as ELF, Mach-O or PE", obj) +} + +// Construct a gcc struct matching the 6c argument frame. +// Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes. +// These assumptions are checked by the gccProlog. +// Also assumes that 6c convention is to word-align the +// input and output parameters. +func (p *Package) structType(n *Name) (string, int64) { + var buf bytes.Buffer + fmt.Fprint(&buf, "struct {\n") + off := int64(0) + for i, t := range n.FuncType.Params { + if off%t.Align != 0 { + pad := t.Align - off%t.Align + fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) + off += pad + } + c := t.Typedef + if c == "" { + c = t.C.String() + } + fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i) + off += t.Size + } + if off%p.PtrSize != 0 { + pad := p.PtrSize - off%p.PtrSize + fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) + off += pad + } + if t := n.FuncType.Result; t != nil { + if off%t.Align != 0 { + pad := t.Align - off%t.Align + fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) + off += pad + } + qual := "" + if c := t.C.String(); c[len(c)-1] == '*' { + qual = "const " + } + fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C) + off += t.Size + } + if off%p.PtrSize != 0 { + pad := p.PtrSize - off%p.PtrSize + fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) + off += pad + } + if off == 0 { + fmt.Fprintf(&buf, "\t\tchar unused;\n") // avoid empty struct + } + fmt.Fprintf(&buf, "\t}") + return buf.String(), off +} + +func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) { + name := n.Go + gtype := n.FuncType.Go + void := gtype.Results == nil || len(gtype.Results.List) == 0 + if n.AddError { + // Add "error" to return type list. + // Type list is known to be 0 or 1 element - it's a C function. + err := &ast.Field{Type: ast.NewIdent("error")} + l := gtype.Results.List + if len(l) == 0 { + l = []*ast.Field{err} + } else { + l = []*ast.Field{l[0], err} + } + t := new(ast.FuncType) + *t = *gtype + t.Results = &ast.FieldList{List: l} + gtype = t + } + + // Go func declaration. + d := &ast.FuncDecl{ + Name: ast.NewIdent(n.Mangle), + Type: gtype, + } + + // Builtins defined in the C prolog. + inProlog := builtinDefs[name] != "" + cname := fmt.Sprintf("_cgo%s%s", cPrefix, n.Mangle) + paramnames := []string(nil) + for i, param := range d.Type.Params.List { + paramName := fmt.Sprintf("p%d", i) + param.Names = []*ast.Ident{ast.NewIdent(paramName)} + paramnames = append(paramnames, paramName) + } + + if *gccgo { + // Gccgo style hooks. + fmt.Fprint(fgo2, "\n") + conf.Fprint(fgo2, fset, d) + fmt.Fprint(fgo2, " {\n") + if !inProlog { + fmt.Fprint(fgo2, "\tdefer syscall.CgocallDone()\n") + fmt.Fprint(fgo2, "\tsyscall.Cgocall()\n") + } + if n.AddError { + fmt.Fprint(fgo2, "\tsyscall.SetErrno(0)\n") + } + fmt.Fprint(fgo2, "\t") + if !void { + fmt.Fprint(fgo2, "r := ") + } + fmt.Fprintf(fgo2, "%s(%s)\n", cname, strings.Join(paramnames, ", ")) + + if n.AddError { + fmt.Fprint(fgo2, "\te := syscall.GetErrno()\n") + fmt.Fprint(fgo2, "\tif e != 0 {\n") + fmt.Fprint(fgo2, "\t\treturn ") + if !void { + fmt.Fprint(fgo2, "r, ") + } + fmt.Fprint(fgo2, "e\n") + fmt.Fprint(fgo2, "\t}\n") + fmt.Fprint(fgo2, "\treturn ") + if !void { + fmt.Fprint(fgo2, "r, ") + } + fmt.Fprint(fgo2, "nil\n") + } else if !void { + fmt.Fprint(fgo2, "\treturn r\n") + } + + fmt.Fprint(fgo2, "}\n") + + // declare the C function. + fmt.Fprintf(fgo2, "//extern %s\n", cname) + d.Name = ast.NewIdent(cname) + if n.AddError { + l := d.Type.Results.List + d.Type.Results.List = l[:len(l)-1] + } + conf.Fprint(fgo2, fset, d) + fmt.Fprint(fgo2, "\n") + + return + } + + if inProlog { + fmt.Fprint(fgo2, builtinDefs[name]) + return + } + + // C wrapper calls into gcc, passing a pointer to the argument frame. + fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", cname) + fmt.Fprintf(fc, "void %s(void*);\n", cname) + fmt.Fprintf(fc, "#pragma dataflag NOPTR\n") + fmt.Fprintf(fc, "void *·%s = %s;\n", cname, cname) + + nret := 0 + if !void { + d.Type.Results.List[0].Names = []*ast.Ident{ast.NewIdent("r1")} + nret = 1 + } + if n.AddError { + d.Type.Results.List[nret].Names = []*ast.Ident{ast.NewIdent("r2")} + } + + fmt.Fprint(fgo2, "\n") + fmt.Fprintf(fgo2, "var %s unsafe.Pointer\n", cname) + conf.Fprint(fgo2, fset, d) + fmt.Fprint(fgo2, " {\n") + + // NOTE: Using uintptr to hide from escape analysis. + arg := "0" + if len(paramnames) > 0 { + arg = "uintptr(unsafe.Pointer(&p0))" + } else if !void { + arg = "uintptr(unsafe.Pointer(&r1))" + } + + prefix := "" + if n.AddError { + prefix = "errno := " + } + fmt.Fprintf(fgo2, "\t%s_cgo_runtime_cgocall_errno(%s, %s)\n", prefix, cname, arg) + if n.AddError { + fmt.Fprintf(fgo2, "\tif errno != 0 { r2 = syscall.Errno(errno) }\n") + } + fmt.Fprintf(fgo2, "\treturn\n") + fmt.Fprintf(fgo2, "}\n") +} + +// writeOutput creates stubs for a specific source file to be compiled by 6g +// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.) +func (p *Package) writeOutput(f *File, srcfile string) { + base := srcfile + if strings.HasSuffix(base, ".go") { + base = base[0 : len(base)-3] + } + base = strings.Map(slashToUnderscore, base) + fgo1 := creat(*objDir + base + ".cgo1.go") + fgcc := creat(*objDir + base + ".cgo2.c") + + p.GoFiles = append(p.GoFiles, base+".cgo1.go") + p.GccFiles = append(p.GccFiles, base+".cgo2.c") + + // Write Go output: Go input with rewrites of C.xxx to _C_xxx. + fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n") + conf.Fprint(fgo1, fset, f.AST) + + // While we process the vars and funcs, also write 6c and gcc output. + // Gcc output starts with the preamble. + fmt.Fprintf(fgcc, "%s\n", f.Preamble) + fmt.Fprintf(fgcc, "%s\n", gccProlog) + + for _, key := range nameKeys(f.Name) { + n := f.Name[key] + if n.FuncType != nil { + p.writeOutputFunc(fgcc, n) + } + } + + fgo1.Close() + fgcc.Close() +} + +// fixGo converts the internal Name.Go field into the name we should show +// to users in error messages. There's only one for now: on input we rewrite +// C.malloc into C._CMalloc, so change it back here. +func fixGo(name string) string { + if name == "_CMalloc" { + return "malloc" + } + return name +} + +var isBuiltin = map[string]bool{ + "_Cfunc_CString": true, + "_Cfunc_GoString": true, + "_Cfunc_GoStringN": true, + "_Cfunc_GoBytes": true, + "_Cfunc__CMalloc": true, +} + +func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { + name := n.Mangle + if isBuiltin[name] || p.Written[name] { + // The builtins are already defined in the C prolog, and we don't + // want to duplicate function definitions we've already done. + return + } + p.Written[name] = true + + if *gccgo { + p.writeGccgoOutputFunc(fgcc, n) + return + } + + ctype, _ := p.structType(n) + + // Gcc wrapper unpacks the C argument struct + // and calls the actual C function. + if n.AddError { + fmt.Fprintf(fgcc, "int\n") + } else { + fmt.Fprintf(fgcc, "void\n") + } + fmt.Fprintf(fgcc, "_cgo%s%s(void *v)\n", cPrefix, n.Mangle) + fmt.Fprintf(fgcc, "{\n") + if n.AddError { + fmt.Fprintf(fgcc, "\terrno = 0;\n") + } + // We're trying to write a gcc struct that matches 6c/8c/5c's layout. + // Use packed attribute to force no padding in this struct in case + // gcc has different packing requirements. + fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute()) + if n.FuncType.Result != nil { + // Save the stack top for use below. + fmt.Fprintf(fgcc, "\tchar *stktop = _cgo_topofstack();\n") + } + fmt.Fprintf(fgcc, "\t") + if t := n.FuncType.Result; t != nil { + fmt.Fprintf(fgcc, "__typeof__(a->r) r = ") + if c := t.C.String(); c[len(c)-1] == '*' { + fmt.Fprint(fgcc, "(__typeof__(a->r)) ") + } + } + fmt.Fprintf(fgcc, "%s(", n.C) + for i, t := range n.FuncType.Params { + if i > 0 { + fmt.Fprintf(fgcc, ", ") + } + // We know the type params are correct, because + // the Go equivalents had good type params. + // However, our version of the type omits the magic + // words const and volatile, which can provoke + // C compiler warnings. Silence them by casting + // all pointers to void*. (Eventually that will produce + // other warnings.) + if c := t.C.String(); c[len(c)-1] == '*' { + fmt.Fprintf(fgcc, "(void*)") + } + fmt.Fprintf(fgcc, "a->p%d", i) + } + fmt.Fprintf(fgcc, ");\n") + if n.FuncType.Result != nil { + // The cgo call may have caused a stack copy (via a callback). + // Adjust the return value pointer appropriately. + fmt.Fprintf(fgcc, "\ta = (void*)((char*)a + (_cgo_topofstack() - stktop));\n") + // Save the return value. + fmt.Fprintf(fgcc, "\ta->r = r;\n") + } + if n.AddError { + fmt.Fprintf(fgcc, "\treturn errno;\n") + } + fmt.Fprintf(fgcc, "}\n") + fmt.Fprintf(fgcc, "\n") +} + +// Write out a wrapper for a function when using gccgo. This is a +// simple wrapper that just calls the real function. We only need a +// wrapper to support static functions in the prologue--without a +// wrapper, we can't refer to the function, since the reference is in +// a different file. +func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) { + if t := n.FuncType.Result; t != nil { + fmt.Fprintf(fgcc, "%s\n", t.C.String()) + } else { + fmt.Fprintf(fgcc, "void\n") + } + fmt.Fprintf(fgcc, "_cgo%s%s(", cPrefix, n.Mangle) + for i, t := range n.FuncType.Params { + if i > 0 { + fmt.Fprintf(fgcc, ", ") + } + c := t.Typedef + if c == "" { + c = t.C.String() + } + fmt.Fprintf(fgcc, "%s p%d", c, i) + } + fmt.Fprintf(fgcc, ")\n") + fmt.Fprintf(fgcc, "{\n") + fmt.Fprintf(fgcc, "\t") + if t := n.FuncType.Result; t != nil { + fmt.Fprintf(fgcc, "return ") + // Cast to void* to avoid warnings due to omitted qualifiers. + if c := t.C.String(); c[len(c)-1] == '*' { + fmt.Fprintf(fgcc, "(void*)") + } + } + fmt.Fprintf(fgcc, "%s(", n.C) + for i, t := range n.FuncType.Params { + if i > 0 { + fmt.Fprintf(fgcc, ", ") + } + // Cast to void* to avoid warnings due to omitted qualifiers. + if c := t.C.String(); c[len(c)-1] == '*' { + fmt.Fprintf(fgcc, "(void*)") + } + fmt.Fprintf(fgcc, "p%d", i) + } + fmt.Fprintf(fgcc, ");\n") + fmt.Fprintf(fgcc, "}\n") + fmt.Fprintf(fgcc, "\n") +} + +// packedAttribute returns host compiler struct attribute that will be +// used to match 6c/8c/5c's struct layout. For example, on 386 Windows, +// gcc wants to 8-align int64s, but 8c does not. +// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86, +// and http://golang.org/issue/5603. +func (p *Package) packedAttribute() string { + s := "__attribute__((__packed__" + if !strings.Contains(p.gccBaseCmd()[0], "clang") && (goarch == "amd64" || goarch == "386") { + s += ", __gcc_struct__" + } + return s + "))" +} + +// Write out the various stubs we need to support functions exported +// from Go so that they are callable from C. +func (p *Package) writeExports(fgo2, fc, fm *os.File) { + fgcc := creat(*objDir + "_cgo_export.c") + fgcch := creat(*objDir + "_cgo_export.h") + + fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n") + fmt.Fprintf(fgcch, "%s\n", p.Preamble) + fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog()) + + fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") + fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n") + + fmt.Fprintf(fgcc, "\nextern void crosscall2(void (*fn)(void *, int), void *, int);\n\n") + + for _, exp := range p.ExpFunc { + fn := exp.Func + + // Construct a gcc struct matching the 6c argument and + // result frame. The gcc struct will be compiled with + // __attribute__((packed)) so all padding must be accounted + // for explicitly. + ctype := "struct {\n" + off := int64(0) + npad := 0 + if fn.Recv != nil { + t := p.cgoType(fn.Recv.List[0].Type) + ctype += fmt.Sprintf("\t\t%s recv;\n", t.C) + off += t.Size + } + fntype := fn.Type + forFieldList(fntype.Params, + func(i int, atype ast.Expr) { + t := p.cgoType(atype) + if off%t.Align != 0 { + pad := t.Align - off%t.Align + ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) + off += pad + npad++ + } + ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i) + off += t.Size + }) + if off%p.PtrSize != 0 { + pad := p.PtrSize - off%p.PtrSize + ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) + off += pad + npad++ + } + forFieldList(fntype.Results, + func(i int, atype ast.Expr) { + t := p.cgoType(atype) + if off%t.Align != 0 { + pad := t.Align - off%t.Align + ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) + off += pad + npad++ + } + ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i) + off += t.Size + }) + if off%p.PtrSize != 0 { + pad := p.PtrSize - off%p.PtrSize + ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad) + off += pad + npad++ + } + if ctype == "struct {\n" { + ctype += "\t\tchar unused;\n" // avoid empty struct + } + ctype += "\t}" + + // Get the return type of the wrapper function + // compiled by gcc. + gccResult := "" + if fntype.Results == nil || len(fntype.Results.List) == 0 { + gccResult = "void" + } else if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 { + gccResult = p.cgoType(fntype.Results.List[0].Type).C.String() + } else { + fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName) + fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName) + forFieldList(fntype.Results, + func(i int, atype ast.Expr) { + fmt.Fprintf(fgcch, "\t%s r%d;\n", p.cgoType(atype).C, i) + }) + fmt.Fprintf(fgcch, "};\n") + gccResult = "struct " + exp.ExpName + "_return" + } + + // Build the wrapper function compiled by gcc. + s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName) + if fn.Recv != nil { + s += p.cgoType(fn.Recv.List[0].Type).C.String() + s += " recv" + } + forFieldList(fntype.Params, + func(i int, atype ast.Expr) { + if i > 0 || fn.Recv != nil { + s += ", " + } + s += fmt.Sprintf("%s p%d", p.cgoType(atype).C, i) + }) + s += ")" + fmt.Fprintf(fgcch, "\nextern %s;\n", s) + + fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int);\n", cPrefix, exp.ExpName) + fmt.Fprintf(fgcc, "\n%s\n", s) + fmt.Fprintf(fgcc, "{\n") + fmt.Fprintf(fgcc, "\t%s %v a;\n", ctype, p.packedAttribute()) + if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) { + fmt.Fprintf(fgcc, "\t%s r;\n", gccResult) + } + if fn.Recv != nil { + fmt.Fprintf(fgcc, "\ta.recv = recv;\n") + } + forFieldList(fntype.Params, + func(i int, atype ast.Expr) { + fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i) + }) + fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off) + if gccResult != "void" { + if len(fntype.Results.List) == 1 && len(fntype.Results.List[0].Names) <= 1 { + fmt.Fprintf(fgcc, "\treturn a.r0;\n") + } else { + forFieldList(fntype.Results, + func(i int, atype ast.Expr) { + fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i) + }) + fmt.Fprintf(fgcc, "\treturn r;\n") + } + } + fmt.Fprintf(fgcc, "}\n") + + // Build the wrapper function compiled by 6c/8c + goname := exp.Func.Name.Name + if fn.Recv != nil { + goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname + } + fmt.Fprintf(fc, "#pragma cgo_export_dynamic %s\n", goname) + fmt.Fprintf(fc, "extern void ·%s();\n\n", goname) + fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName) + fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g + fmt.Fprintf(fc, "void\n") + fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName) + fmt.Fprintf(fc, "{\n") + fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname) + fmt.Fprintf(fc, "}\n") + + fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName) + + // Calling a function with a receiver from C requires + // a Go wrapper function. + if fn.Recv != nil { + fmt.Fprintf(fgo2, "func %s(recv ", goname) + conf.Fprint(fgo2, fset, fn.Recv.List[0].Type) + forFieldList(fntype.Params, + func(i int, atype ast.Expr) { + fmt.Fprintf(fgo2, ", p%d ", i) + conf.Fprint(fgo2, fset, atype) + }) + fmt.Fprintf(fgo2, ")") + if gccResult != "void" { + fmt.Fprint(fgo2, " (") + forFieldList(fntype.Results, + func(i int, atype ast.Expr) { + if i > 0 { + fmt.Fprint(fgo2, ", ") + } + conf.Fprint(fgo2, fset, atype) + }) + fmt.Fprint(fgo2, ")") + } + fmt.Fprint(fgo2, " {\n") + fmt.Fprint(fgo2, "\t") + if gccResult != "void" { + fmt.Fprint(fgo2, "return ") + } + fmt.Fprintf(fgo2, "recv.%s(", exp.Func.Name) + forFieldList(fntype.Params, + func(i int, atype ast.Expr) { + if i > 0 { + fmt.Fprint(fgo2, ", ") + } + fmt.Fprintf(fgo2, "p%d", i) + }) + fmt.Fprint(fgo2, ")\n") + fmt.Fprint(fgo2, "}\n") + } + } +} + +// Write out the C header allowing C code to call exported gccgo functions. +func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) { + fgcc := creat(*objDir + "_cgo_export.c") + fgcch := creat(*objDir + "_cgo_export.h") + + gccgoSymbolPrefix := p.gccgoSymbolPrefix() + + fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n") + fmt.Fprintf(fgcch, "%s\n", p.Preamble) + fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog()) + + fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") + fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n") + + fmt.Fprintf(fm, "#include \"_cgo_export.h\"\n") + + for _, exp := range p.ExpFunc { + fn := exp.Func + fntype := fn.Type + + cdeclBuf := new(bytes.Buffer) + resultCount := 0 + forFieldList(fntype.Results, + func(i int, atype ast.Expr) { resultCount++ }) + switch resultCount { + case 0: + fmt.Fprintf(cdeclBuf, "void") + case 1: + forFieldList(fntype.Results, + func(i int, atype ast.Expr) { + t := p.cgoType(atype) + fmt.Fprintf(cdeclBuf, "%s", t.C) + }) + default: + // Declare a result struct. + fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName) + forFieldList(fntype.Results, + func(i int, atype ast.Expr) { + t := p.cgoType(atype) + fmt.Fprintf(fgcch, "\t%s r%d;\n", t.C, i) + }) + fmt.Fprintf(fgcch, "};\n") + fmt.Fprintf(cdeclBuf, "struct %s_result", exp.ExpName) + } + + cRet := cdeclBuf.String() + + cdeclBuf = new(bytes.Buffer) + fmt.Fprintf(cdeclBuf, "(") + if fn.Recv != nil { + fmt.Fprintf(cdeclBuf, "%s recv", p.cgoType(fn.Recv.List[0].Type).C.String()) + } + // Function parameters. + forFieldList(fntype.Params, + func(i int, atype ast.Expr) { + if i > 0 || fn.Recv != nil { + fmt.Fprintf(cdeclBuf, ", ") + } + t := p.cgoType(atype) + fmt.Fprintf(cdeclBuf, "%s p%d", t.C, i) + }) + fmt.Fprintf(cdeclBuf, ")") + cParams := cdeclBuf.String() + + // We need to use a name that will be exported by the + // Go code; otherwise gccgo will make it static and we + // will not be able to link against it from the C + // code. + goName := "Cgoexp_" + exp.ExpName + fmt.Fprintf(fgcch, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName) + fmt.Fprint(fgcch, "\n") + + // Use a #define so that the C code that includes + // cgo_export.h will be able to refer to the Go + // function using the expected name. + fmt.Fprintf(fgcch, "#define %s %s\n", exp.ExpName, goName) + + // Use a #undef in _cgo_export.c so that we ignore the + // #define from cgo_export.h, since here we are + // defining the real function. + fmt.Fprintf(fgcc, "#undef %s\n", exp.ExpName) + + fmt.Fprint(fgcc, "\n") + fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams) + fmt.Fprint(fgcc, "\t") + if resultCount > 0 { + fmt.Fprint(fgcc, "return ") + } + fmt.Fprintf(fgcc, "%s(", goName) + if fn.Recv != nil { + fmt.Fprint(fgcc, "recv") + } + forFieldList(fntype.Params, + func(i int, atype ast.Expr) { + if i > 0 || fn.Recv != nil { + fmt.Fprintf(fgcc, ", ") + } + fmt.Fprintf(fgcc, "p%d", i) + }) + fmt.Fprint(fgcc, ");\n") + fmt.Fprint(fgcc, "}\n") + + // Dummy declaration for _cgo_main.c + fmt.Fprintf(fm, "%s %s %s {}\n", cRet, goName, cParams) + + // For gccgo we use a wrapper function in Go, in order + // to call CgocallBack and CgocallBackDone. + + // This code uses printer.Fprint, not conf.Fprint, + // because we don't want //line comments in the middle + // of the function types. + fmt.Fprint(fgo2, "\n") + fmt.Fprintf(fgo2, "func %s(", goName) + if fn.Recv != nil { + fmt.Fprint(fgo2, "recv ") + printer.Fprint(fgo2, fset, fn.Recv.List[0].Type) + } + forFieldList(fntype.Params, + func(i int, atype ast.Expr) { + if i > 0 || fn.Recv != nil { + fmt.Fprintf(fgo2, ", ") + } + fmt.Fprintf(fgo2, "p%d ", i) + printer.Fprint(fgo2, fset, atype) + }) + fmt.Fprintf(fgo2, ")") + if resultCount > 0 { + fmt.Fprintf(fgo2, " (") + forFieldList(fntype.Results, + func(i int, atype ast.Expr) { + if i > 0 { + fmt.Fprint(fgo2, ", ") + } + printer.Fprint(fgo2, fset, atype) + }) + fmt.Fprint(fgo2, ")") + } + fmt.Fprint(fgo2, " {\n") + fmt.Fprint(fgo2, "\tsyscall.CgocallBack()\n") + fmt.Fprint(fgo2, "\tdefer syscall.CgocallBackDone()\n") + fmt.Fprint(fgo2, "\t") + if resultCount > 0 { + fmt.Fprint(fgo2, "return ") + } + if fn.Recv != nil { + fmt.Fprint(fgo2, "recv.") + } + fmt.Fprintf(fgo2, "%s(", exp.Func.Name) + forFieldList(fntype.Params, + func(i int, atype ast.Expr) { + if i > 0 { + fmt.Fprint(fgo2, ", ") + } + fmt.Fprintf(fgo2, "p%d", i) + }) + fmt.Fprint(fgo2, ")\n") + fmt.Fprint(fgo2, "}\n") + } +} + +// Return the package prefix when using gccgo. +func (p *Package) gccgoSymbolPrefix() string { + if !*gccgo { + return "" + } + + clean := func(r rune) rune { + switch { + case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z', + '0' <= r && r <= '9': + return r + } + return '_' + } + + if *gccgopkgpath != "" { + return strings.Map(clean, *gccgopkgpath) + } + if *gccgoprefix == "" && p.PackageName == "main" { + return "main" + } + prefix := strings.Map(clean, *gccgoprefix) + if prefix == "" { + prefix = "go" + } + return prefix + "." + p.PackageName +} + +// Call a function for each entry in an ast.FieldList, passing the +// index into the list and the type. +func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) { + if fl == nil { + return + } + i := 0 + for _, r := range fl.List { + if r.Names == nil { + fn(i, r.Type) + i++ + } else { + for range r.Names { + fn(i, r.Type) + i++ + } + } + } +} + +func c(repr string, args ...interface{}) *TypeRepr { + return &TypeRepr{repr, args} +} + +// Map predeclared Go types to Type. +var goTypes = map[string]*Type{ + "bool": {Size: 1, Align: 1, C: c("GoUint8")}, + "byte": {Size: 1, Align: 1, C: c("GoUint8")}, + "int": {Size: 0, Align: 0, C: c("GoInt")}, + "uint": {Size: 0, Align: 0, C: c("GoUint")}, + "rune": {Size: 4, Align: 4, C: c("GoInt32")}, + "int8": {Size: 1, Align: 1, C: c("GoInt8")}, + "uint8": {Size: 1, Align: 1, C: c("GoUint8")}, + "int16": {Size: 2, Align: 2, C: c("GoInt16")}, + "uint16": {Size: 2, Align: 2, C: c("GoUint16")}, + "int32": {Size: 4, Align: 4, C: c("GoInt32")}, + "uint32": {Size: 4, Align: 4, C: c("GoUint32")}, + "int64": {Size: 8, Align: 8, C: c("GoInt64")}, + "uint64": {Size: 8, Align: 8, C: c("GoUint64")}, + "float32": {Size: 4, Align: 4, C: c("GoFloat32")}, + "float64": {Size: 8, Align: 8, C: c("GoFloat64")}, + "complex64": {Size: 8, Align: 8, C: c("GoComplex64")}, + "complex128": {Size: 16, Align: 16, C: c("GoComplex128")}, +} + +// Map an ast type to a Type. +func (p *Package) cgoType(e ast.Expr) *Type { + switch t := e.(type) { + case *ast.StarExpr: + x := p.cgoType(t.X) + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)} + case *ast.ArrayType: + if t.Len == nil { + // Slice: pointer, len, cap. + return &Type{Size: p.PtrSize * 3, Align: p.PtrSize, C: c("GoSlice")} + } + case *ast.StructType: + // TODO + case *ast.FuncType: + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")} + case *ast.InterfaceType: + return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")} + case *ast.MapType: + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoMap")} + case *ast.ChanType: + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")} + case *ast.Ident: + // Look up the type in the top level declarations. + // TODO: Handle types defined within a function. + for _, d := range p.Decl { + gd, ok := d.(*ast.GenDecl) + if !ok || gd.Tok != token.TYPE { + continue + } + for _, spec := range gd.Specs { + ts, ok := spec.(*ast.TypeSpec) + if !ok { + continue + } + if ts.Name.Name == t.Name { + return p.cgoType(ts.Type) + } + } + } + if def := typedef[t.Name]; def != nil { + return def + } + if t.Name == "uintptr" { + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoUintptr")} + } + if t.Name == "string" { + // The string data is 1 pointer + 1 (pointer-sized) int. + return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoString")} + } + if t.Name == "error" { + return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")} + } + if r, ok := goTypes[t.Name]; ok { + if r.Size == 0 { // int or uint + rr := new(Type) + *rr = *r + rr.Size = p.IntSize + rr.Align = p.IntSize + r = rr + } + if r.Align > p.PtrSize { + r.Align = p.PtrSize + } + return r + } + error_(e.Pos(), "unrecognized Go type %s", t.Name) + return &Type{Size: 4, Align: 4, C: c("int")} + case *ast.SelectorExpr: + id, ok := t.X.(*ast.Ident) + if ok && id.Name == "unsafe" && t.Sel.Name == "Pointer" { + return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")} + } + } + error_(e.Pos(), "Go type not supported in export: %s", gofmt(e)) + return &Type{Size: 4, Align: 4, C: c("int")} +} + +const gccProlog = ` +// Usual nonsense: if x and y are not equal, the type will be invalid +// (have a negative array count) and an inscrutable error will come +// out of the compiler and hopefully mention "name". +#define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1]; + +// Check at compile time that the sizes we use match our expectations. +#define __cgo_size_assert(t, n) __cgo_compile_assert_eq(sizeof(t), n, _cgo_sizeof_##t##_is_not_##n) + +__cgo_size_assert(char, 1) +__cgo_size_assert(short, 2) +__cgo_size_assert(int, 4) +typedef long long __cgo_long_long; +__cgo_size_assert(__cgo_long_long, 8) +__cgo_size_assert(float, 4) +__cgo_size_assert(double, 8) + +extern char* _cgo_topofstack(void); + +#include +#include +` + +const builtinProlog = ` +#include /* for ptrdiff_t and size_t below */ + +/* Define intgo when compiling with GCC. */ +typedef ptrdiff_t intgo; + +typedef struct { char *p; intgo n; } _GoString_; +typedef struct { char *p; intgo n; intgo c; } _GoBytes_; +_GoString_ GoString(char *p); +_GoString_ GoStringN(char *p, int l); +_GoBytes_ GoBytes(void *p, int n); +char *CString(_GoString_); +void *_CMalloc(size_t); +` + +const cProlog = ` +#include "runtime.h" +#include "cgocall.h" +#include "textflag.h" + +#pragma dataflag NOPTR +static void *cgocall_errno = runtime·cgocall_errno; +#pragma dataflag NOPTR +void *·_cgo_runtime_cgocall_errno = &cgocall_errno; + +#pragma dataflag NOPTR +static void *runtime_gostring = runtime·gostring; +#pragma dataflag NOPTR +void *·_cgo_runtime_gostring = &runtime_gostring; + +#pragma dataflag NOPTR +static void *runtime_gostringn = runtime·gostringn; +#pragma dataflag NOPTR +void *·_cgo_runtime_gostringn = &runtime_gostringn; + +#pragma dataflag NOPTR +static void *runtime_gobytes = runtime·gobytes; +#pragma dataflag NOPTR +void *·_cgo_runtime_gobytes = &runtime_gobytes; + +#pragma dataflag NOPTR +static void *runtime_cmalloc = runtime·cmalloc; +#pragma dataflag NOPTR +void *·_cgo_runtime_cmalloc = &runtime_cmalloc; + +void ·_Cerrno(void*, int32); +` + +const goProlog = ` +var _cgo_runtime_cgocall_errno func(unsafe.Pointer, uintptr) int32 +var _cgo_runtime_cmalloc func(uintptr) unsafe.Pointer +` + +const goStringDef = ` +var _cgo_runtime_gostring func(*_Ctype_char) string +func _Cfunc_GoString(p *_Ctype_char) string { + return _cgo_runtime_gostring(p) +} +` + +const goStringNDef = ` +var _cgo_runtime_gostringn func(*_Ctype_char, int) string +func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string { + return _cgo_runtime_gostringn(p, int(l)) +} +` + +const goBytesDef = ` +var _cgo_runtime_gobytes func(unsafe.Pointer, int) []byte +func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte { + return _cgo_runtime_gobytes(p, int(l)) +} +` + +const cStringDef = ` +func _Cfunc_CString(s string) *_Ctype_char { + p := _cgo_runtime_cmalloc(uintptr(len(s)+1)) + pp := (*[1<<30]byte)(p) + copy(pp[:], s) + pp[len(s)] = 0 + return (*_Ctype_char)(p) +} +` + +const cMallocDef = ` +func _Cfunc__CMalloc(n _Ctype_size_t) unsafe.Pointer { + return _cgo_runtime_cmalloc(uintptr(n)) +} +` + +var builtinDefs = map[string]string{ + "GoString": goStringDef, + "GoStringN": goStringNDef, + "GoBytes": goBytesDef, + "CString": cStringDef, + "_CMalloc": cMallocDef, +} + +func (p *Package) cPrologGccgo() string { + return strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1) +} + +const cPrologGccgo = ` +#include +#include +#include + +typedef unsigned char byte; +typedef intptr_t intgo; + +struct __go_string { + const unsigned char *__data; + intgo __length; +}; + +typedef struct __go_open_array { + void* __values; + intgo __count; + intgo __capacity; +} Slice; + +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); + +const char *_cgoPREFIX_Cfunc_CString(struct __go_string s) { + char *p = malloc(s.__length+1); + memmove(p, s.__data, s.__length); + p[s.__length] = 0; + return p; +} + +struct __go_string _cgoPREFIX_Cfunc_GoString(char *p) { + intgo len = (p != NULL) ? strlen(p) : 0; + return __go_byte_array_to_string(p, len); +} + +struct __go_string _cgoPREFIX_Cfunc_GoStringN(char *p, int32_t n) { + return __go_byte_array_to_string(p, n); +} + +Slice _cgoPREFIX_Cfunc_GoBytes(char *p, int32_t n) { + struct __go_string s = { (const unsigned char *)p, 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; +} +` + +func (p *Package) gccExportHeaderProlog() string { + return strings.Replace(gccExportHeaderProlog, "GOINTBITS", fmt.Sprint(8*p.IntSize), -1) +} + +const gccExportHeaderProlog = ` +typedef signed char GoInt8; +typedef unsigned char GoUint8; +typedef short GoInt16; +typedef unsigned short GoUint16; +typedef int GoInt32; +typedef unsigned int GoUint32; +typedef long long GoInt64; +typedef unsigned long long GoUint64; +typedef GoIntGOINTBITS GoInt; +typedef GoUintGOINTBITS GoUint; +typedef __SIZE_TYPE__ GoUintptr; +typedef float GoFloat32; +typedef double GoFloat64; +typedef __complex float GoComplex64; +typedef __complex double GoComplex128; + +typedef struct { char *p; GoInt n; } GoString; +typedef void *GoMap; +typedef void *GoChan; +typedef struct { void *t; void *v; } GoInterface; +typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; +` diff --git a/libgo/go/cmd/cgo/util.go b/libgo/go/cmd/cgo/util.go new file mode 100644 index 0000000000..4e7800d127 --- /dev/null +++ b/libgo/go/cmd/cgo/util.go @@ -0,0 +1,84 @@ +// 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 main + +import ( + "bytes" + "fmt" + "go/token" + "os" + "os/exec" +) + +// run runs the command argv, feeding in stdin on standard input. +// It returns the output to standard output and standard error. +// ok indicates whether the command exited successfully. +func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) { + p := exec.Command(argv[0], argv[1:]...) + p.Stdin = bytes.NewReader(stdin) + var bout, berr bytes.Buffer + p.Stdout = &bout + p.Stderr = &berr + err := p.Run() + if _, ok := err.(*exec.ExitError); err != nil && !ok { + fatalf("%s", err) + } + ok = p.ProcessState.Success() + stdout, stderr = bout.Bytes(), berr.Bytes() + return +} + +func lineno(pos token.Pos) string { + return fset.Position(pos).String() +} + +// Die with an error message. +func fatalf(msg string, args ...interface{}) { + // If we've already printed other errors, they might have + // caused the fatal condition. Assume they're enough. + if nerrors == 0 { + fmt.Fprintf(os.Stderr, msg+"\n", args...) + } + os.Exit(2) +} + +var nerrors int + +func error_(pos token.Pos, msg string, args ...interface{}) { + nerrors++ + if pos.IsValid() { + fmt.Fprintf(os.Stderr, "%s: ", fset.Position(pos).String()) + } + fmt.Fprintf(os.Stderr, msg, args...) + fmt.Fprintf(os.Stderr, "\n") +} + +// isName returns true if s is a valid C identifier +func isName(s string) bool { + for i, v := range s { + if v != '_' && (v < 'A' || v > 'Z') && (v < 'a' || v > 'z') && (v < '0' || v > '9') { + return false + } + if i == 0 && '0' <= v && v <= '9' { + return false + } + } + return s != "" +} + +func creat(name string) *os.File { + f, err := os.Create(name) + if err != nil { + fatalf("%s", err) + } + return f +} + +func slashToUnderscore(c rune) rune { + if c == '/' || c == '\\' || c == ':' { + c = '_' + } + return c +} diff --git a/libgo/go/cmd/go/bootstrap.go b/libgo/go/cmd/go/bootstrap.go new file mode 100644 index 0000000000..dc7ed5f4c0 --- /dev/null +++ b/libgo/go/cmd/go/bootstrap.go @@ -0,0 +1,30 @@ +// 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. + +// +build cmd_go_bootstrap + +// This code is compiled only into the bootstrap 'go' binary. +// These stubs avoid importing packages with large dependency +// trees, like the use of "net/http" in vcs.go. + +package main + +import ( + "errors" + "io" +) + +var errHTTP = errors.New("no http in bootstrap go command") + +func httpGET(url string) ([]byte, error) { + return nil, errHTTP +} + +func httpsOrHTTP(importPath string) (string, io.ReadCloser, error) { + return "", nil, errHTTP +} + +func parseMetaGoImports(r io.Reader) ([]metaImport, error) { + panic("unreachable") +} diff --git a/libgo/go/cmd/go/build.go b/libgo/go/cmd/go/build.go new file mode 100644 index 0000000000..781a43b5d9 --- /dev/null +++ b/libgo/go/cmd/go/build.go @@ -0,0 +1,2691 @@ +// 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 main + +import ( + "bufio" + "bytes" + "container/heap" + "errors" + "flag" + "fmt" + "go/build" + "io" + "io/ioutil" + "log" + "os" + "os/exec" + "path" + "path/filepath" + "regexp" + "runtime" + "strconv" + "strings" + "sync" + "time" +) + +var cmdBuild = &Command{ + UsageLine: "build [-o output] [-i] [build flags] [packages]", + Short: "compile packages and dependencies", + Long: ` +Build compiles the packages named by the import paths, +along with their dependencies, but it does not install the results. + +If the arguments are a list of .go files, build treats them as a list +of source files specifying a single package. + +When the command line specifies a single main package, +build writes the resulting executable to output. +Otherwise build compiles the packages but discards the results, +serving only as a check that the packages can be built. + +The -o flag specifies the output file name. If not specified, the +output file name depends on the arguments and derives from the name +of the package, such as p.a for package p, unless p is 'main'. If +the package is main and file names are provided, the file name +derives from the first file name mentioned, such as f1 for 'go build +f1.go f2.go'; with no files provided ('go build'), the output file +name is the base name of the containing directory. + +The -i flag installs the packages that are dependencies of the target. + +The build flags are shared by the build, clean, get, install, list, run, +and test commands: + + -a + force rebuilding of packages that are already up-to-date. + In Go releases, does not apply to the standard library. + -n + print the commands but do not run them. + -p n + the number of builds that can be run in parallel. + The default is the number of CPUs available. + -race + enable data race detection. + Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. + -v + print the names of packages as they are compiled. + -work + print the name of the temporary work directory and + do not delete it when exiting. + -x + print the commands. + + -ccflags 'arg list' + arguments to pass on each 5c, 6c, or 8c compiler invocation. + -compiler name + name of compiler to use, as in runtime.Compiler (gccgo or gc). + -gccgoflags 'arg list' + arguments to pass on each gccgo compiler/linker invocation. + -gcflags 'arg list' + arguments to pass on each 5g, 6g, or 8g compiler invocation. + -installsuffix suffix + a suffix to use in the name of the package installation directory, + in order to keep output separate from default builds. + If using the -race flag, the install suffix is automatically set to race + or, if set explicitly, has _race appended to it. + -ldflags 'flag list' + arguments to pass on each 5l, 6l, or 8l linker invocation. + -tags 'tag list' + a list of build tags to consider satisfied during the build. + For more information about build tags, see the description of + build constraints in the documentation for the go/build package. + +The list flags accept a space-separated list of strings. To embed spaces +in an element in the list, surround it with either single or double quotes. + +For more about specifying packages, see 'go help packages'. +For more about where packages and binaries are installed, +run 'go help gopath'. For more about calling between Go and C/C++, +run 'go help c'. + +See also: go install, go get, go clean. + `, +} + +func init() { + // break init cycle + cmdBuild.Run = runBuild + cmdInstall.Run = runInstall + + cmdBuild.Flag.BoolVar(&buildI, "i", false, "") + + addBuildFlags(cmdBuild) + addBuildFlags(cmdInstall) +} + +// Flags set by multiple commands. +var buildA bool // -a flag +var buildN bool // -n flag +var buildP = runtime.NumCPU() // -p flag +var buildV bool // -v flag +var buildX bool // -x flag +var buildI bool // -i flag +var buildO = cmdBuild.Flag.String("o", "", "output file") +var buildWork bool // -work flag +var buildGcflags []string // -gcflags flag +var buildCcflags []string // -ccflags flag +var buildLdflags []string // -ldflags flag +var buildGccgoflags []string // -gccgoflags flag +var buildRace bool // -race flag + +// Require the source for go std packages +var reqStdPkgSrc bool +var buildContext = build.Default +var buildToolchain toolchain = noToolchain{} + +// buildCompiler implements flag.Var. +// It implements Set by updating both +// buildToolchain and buildContext.Compiler. +type buildCompiler struct{} + +func (c buildCompiler) Set(value string) error { + switch value { + case "gc": + buildToolchain = gcToolchain{} + case "gccgo": + buildToolchain = gccgoToolchain{} + default: + return fmt.Errorf("unknown compiler %q", value) + } + buildContext.Compiler = value + return nil +} + +func (c buildCompiler) String() string { + return buildContext.Compiler +} + +func init() { + switch build.Default.Compiler { + case "gc": + buildToolchain = gcToolchain{} + case "gccgo": + buildToolchain = gccgoToolchain{} + } +} + +// addBuildFlags adds the flags common to the build, clean, get, +// install, list, run, and test commands. +func addBuildFlags(cmd *Command) { + // NOTE: If you add flags here, also add them to testflag.go. + cmd.Flag.BoolVar(&buildA, "a", false, "") + cmd.Flag.BoolVar(&buildN, "n", false, "") + cmd.Flag.IntVar(&buildP, "p", buildP, "") + cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "") + cmd.Flag.BoolVar(&buildV, "v", false, "") + cmd.Flag.BoolVar(&buildX, "x", false, "") + cmd.Flag.BoolVar(&buildWork, "work", false, "") + cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "") + cmd.Flag.Var((*stringsFlag)(&buildCcflags), "ccflags", "") + cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "") + cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "") + cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "") + cmd.Flag.Var(buildCompiler{}, "compiler", "") + cmd.Flag.BoolVar(&buildRace, "race", false, "") + switch build.Default.Compiler { + case "gc": + reqStdPkgSrc = true + case "gccgo": + reqStdPkgSrc = false + } +} + +func addBuildFlagsNX(cmd *Command) { + cmd.Flag.BoolVar(&buildN, "n", false, "") + cmd.Flag.BoolVar(&buildX, "x", false, "") +} + +func isSpaceByte(c byte) bool { + return c == ' ' || c == '\t' || c == '\n' || c == '\r' +} + +// fileExtSplit expects a filename and returns the name +// and ext (without the dot). If the file has no +// extension, ext will be empty. +func fileExtSplit(file string) (name, ext string) { + dotExt := filepath.Ext(file) + name = file[:len(file)-len(dotExt)] + if dotExt != "" { + ext = dotExt[1:] + } + return +} + +type stringsFlag []string + +func (v *stringsFlag) Set(s string) error { + var err error + *v, err = splitQuotedFields(s) + if *v == nil { + *v = []string{} + } + return err +} + +func splitQuotedFields(s string) ([]string, error) { + // Split fields allowing '' or "" around elements. + // Quotes further inside the string do not count. + var f []string + for len(s) > 0 { + for len(s) > 0 && isSpaceByte(s[0]) { + s = s[1:] + } + if len(s) == 0 { + break + } + // Accepted quoted string. No unescaping inside. + if s[0] == '"' || s[0] == '\'' { + quote := s[0] + s = s[1:] + i := 0 + for i < len(s) && s[i] != quote { + i++ + } + if i >= len(s) { + return nil, fmt.Errorf("unterminated %c string", quote) + } + f = append(f, s[:i]) + s = s[i+1:] + continue + } + i := 0 + for i < len(s) && !isSpaceByte(s[i]) { + i++ + } + f = append(f, s[:i]) + s = s[i:] + } + return f, nil +} + +func (v *stringsFlag) String() string { + return "" +} + +func runBuild(cmd *Command, args []string) { + raceInit() + var b builder + b.init() + + pkgs := packagesForBuild(args) + + if len(pkgs) == 1 && pkgs[0].Name == "main" && *buildO == "" { + _, *buildO = path.Split(pkgs[0].ImportPath) + *buildO += exeSuffix + } + + // sanity check some often mis-used options + switch buildContext.Compiler { + case "gccgo": + if len(buildGcflags) != 0 { + fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags") + } + if len(buildLdflags) != 0 { + fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags") + } + case "gc": + if len(buildGccgoflags) != 0 { + fmt.Println("go build: when using gc toolchain, please pass compile flags using -gcflags, and linker flags using -ldflags") + } + } + + depMode := modeBuild + if buildI { + depMode = modeInstall + } + + if *buildO != "" { + if len(pkgs) > 1 { + fatalf("go build: cannot use -o with multiple packages") + } else if len(pkgs) == 0 { + fatalf("no packages to build") + } + p := pkgs[0] + p.target = "" // must build - not up to date + a := b.action(modeInstall, depMode, p) + a.target = *buildO + b.do(a) + return + } + + a := &action{} + for _, p := range packages(args) { + a.deps = append(a.deps, b.action(modeBuild, depMode, p)) + } + b.do(a) +} + +var cmdInstall = &Command{ + UsageLine: "install [build flags] [packages]", + Short: "compile and install packages and dependencies", + Long: ` +Install compiles and installs the packages named by the import paths, +along with their dependencies. + +For more about the build flags, see 'go help build'. +For more about specifying packages, see 'go help packages'. + +See also: go build, go get, go clean. + `, +} + +func runInstall(cmd *Command, args []string) { + raceInit() + pkgs := packagesForBuild(args) + + for _, p := range pkgs { + if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") { + if p.cmdline { + errorf("go install: no install location for .go files listed on command line (GOBIN not set)") + } else if p.ConflictDir != "" { + errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir) + } else { + errorf("go install: no install location for directory %s outside GOPATH", p.Dir) + } + } + } + exitIfErrors() + + var b builder + b.init() + a := &action{} + for _, p := range pkgs { + a.deps = append(a.deps, b.action(modeInstall, modeInstall, p)) + } + b.do(a) +} + +// Global build parameters (used during package load) +var ( + goarch string + goos string + archChar string + exeSuffix string +) + +func init() { + goarch = buildContext.GOARCH + goos = buildContext.GOOS + if goos == "windows" { + exeSuffix = ".exe" + } + var err error + archChar, err = build.ArchChar(goarch) + if err != nil { + if _, isgc := buildToolchain.(gcToolchain); isgc { + fatalf("%s", err) + } + // archChar is only required for gcToolchain, if we're using + // another toolchain leave it blank. + archChar = "" + } +} + +// A builder holds global state about a build. +// It does not hold per-package state, because we +// build packages in parallel, and the builder is shared. +type builder struct { + work string // the temporary work directory (ends in filepath.Separator) + actionCache map[cacheKey]*action // a cache of already-constructed actions + mkdirCache map[string]bool // a cache of created directories + print func(args ...interface{}) (int, error) + + output sync.Mutex + scriptDir string // current directory in printed script + + exec sync.Mutex + readySema chan bool + ready actionQueue +} + +// An action represents a single action in the action graph. +type action struct { + p *Package // the package this action works on + deps []*action // actions that must happen before this one + triggers []*action // inverse of deps + cgo *action // action for cgo binary if needed + args []string // additional args for runProgram + testOutput *bytes.Buffer // test output buffer + + f func(*builder, *action) error // the action itself (nil = no-op) + ignoreFail bool // whether to run f even if dependencies fail + + // Generated files, directories. + link bool // target is executable, not just package + pkgdir string // the -I or -L argument to use when importing this package + objdir string // directory for intermediate objects + objpkg string // the intermediate package .a file created during the action + target string // goal of the action: the created package or executable + + // Execution state. + pending int // number of deps yet to complete + priority int // relative execution priority + failed bool // whether the action failed +} + +// cacheKey is the key for the action cache. +type cacheKey struct { + mode buildMode + p *Package +} + +// buildMode specifies the build mode: +// are we just building things or also installing the results? +type buildMode int + +const ( + modeBuild buildMode = iota + modeInstall +) + +var ( + goroot = filepath.Clean(runtime.GOROOT()) + gobin = os.Getenv("GOBIN") + gorootBin = filepath.Join(goroot, "bin") + gorootPkg = filepath.Join(goroot, "pkg") + gorootSrc = filepath.Join(goroot, "src") +) + +func (b *builder) init() { + var err error + b.print = func(a ...interface{}) (int, error) { + return fmt.Fprint(os.Stderr, a...) + } + b.actionCache = make(map[cacheKey]*action) + b.mkdirCache = make(map[string]bool) + + if buildN { + b.work = "$WORK" + } else { + b.work, err = ioutil.TempDir("", "go-build") + if err != nil { + fatalf("%s", err) + } + if buildX || buildWork { + fmt.Fprintf(os.Stderr, "WORK=%s\n", b.work) + } + if !buildWork { + workdir := b.work + atexit(func() { os.RemoveAll(workdir) }) + } + } +} + +// 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(gofiles []string) *Package { + // TODO: Remove this restriction. + for _, f := range gofiles { + if !strings.HasSuffix(f, ".go") { + fatalf("named files must be .go files") + } + } + + var stk importStack + ctxt := buildContext + ctxt.UseAllFiles = true + + // Synthesize fake "directory" that only shows the named files, + // to make it look like this is a standard package or + // command directory. So that local imports resolve + // consistently, the files must all be in the same directory. + var dirent []os.FileInfo + var dir string + for _, file := range gofiles { + fi, err := os.Stat(file) + if err != nil { + fatalf("%s", err) + } + if fi.IsDir() { + fatalf("%s is a directory, should be a Go file", file) + } + dir1, _ := filepath.Split(file) + if dir == "" { + dir = dir1 + } else if dir != dir1 { + fatalf("named files must all be in one directory; have %s and %s", dir, dir1) + } + dirent = append(dirent, fi) + } + ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil } + + var err error + if dir == "" { + dir = cwd + } + dir, err = filepath.Abs(dir) + if err != nil { + fatalf("%s", err) + } + + bp, err := ctxt.ImportDir(dir, 0) + pkg := new(Package) + pkg.local = true + pkg.cmdline = true + pkg.load(&stk, bp, err) + pkg.localPrefix = dirToImportPath(dir) + pkg.ImportPath = "command-line-arguments" + pkg.target = "" + + if pkg.Name == "main" { + _, elem := filepath.Split(gofiles[0]) + exe := elem[:len(elem)-len(".go")] + exeSuffix + if *buildO == "" { + *buildO = exe + } + if gobin != "" { + pkg.target = filepath.Join(gobin, exe) + } + } else { + if *buildO == "" { + *buildO = pkg.Name + ".a" + } + } + pkg.Target = pkg.target + pkg.Stale = true + + computeStale(pkg) + return pkg +} + +// action returns the action for applying the given operation (mode) to the package. +// depMode is the action to use when building dependencies. +func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action { + key := cacheKey{mode, p} + a := b.actionCache[key] + if a != nil { + return a + } + + a = &action{p: p, pkgdir: p.build.PkgRoot} + if p.pkgdir != "" { // overrides p.t + a.pkgdir = p.pkgdir + } + + b.actionCache[key] = a + + for _, p1 := range p.imports { + a.deps = append(a.deps, b.action(depMode, depMode, p1)) + } + + // If we are not doing a cross-build, then record the binary we'll + // generate for cgo as a dependency of the build of any package + // using cgo, to make sure we do not overwrite the binary while + // a package is using it. If this is a cross-build, then the cgo we + // are writing is not the cgo we need to use. + + if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace { + if reqStdPkgSrc { + if len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo" { + var stk importStack + p1 := loadPackage("cmd/cgo", &stk) + if p1.Error != nil { + fatalf("load cmd/cgo: %v", p1.Error) + } + a.cgo = b.action(depMode, depMode, p1) + a.deps = append(a.deps, a.cgo) + } + } + } + + if p.Standard { + switch p.ImportPath { + case "builtin", "unsafe": + // Fake packages - nothing to build. + return a + } + // gccgo standard library is "fake" too. + if _, ok := buildToolchain.(gccgoToolchain); ok { + // the target name is needed for cgo. + a.target = p.target + return a + } + } + + if !p.Stale && p.target != "" { + // p.Stale==false implies that p.target is up-to-date. + // Record target name for use by actions depending on this one. + a.target = p.target + return a + } + + if p.local && p.target == "" { + // Imported via local path. No permanent target. + mode = modeBuild + } + work := p.pkgdir + if work == "" { + work = b.work + } + a.objdir = filepath.Join(work, a.p.ImportPath, "_obj") + string(filepath.Separator) + a.objpkg = buildToolchain.pkgpath(work, a.p) + a.link = p.Name == "main" + + switch mode { + case modeInstall: + a.f = (*builder).install + a.deps = []*action{b.action(modeBuild, depMode, p)} + a.target = a.p.target + case modeBuild: + a.f = (*builder).build + a.target = a.objpkg + if a.link { + // An executable file. (This is the name of a temporary file.) + // Because we run the temporary file in 'go run' and 'go test', + // the name will show up in ps listings. If the caller has specified + // a name, use that instead of a.out. The binary is generated + // in an otherwise empty subdirectory named exe to avoid + // naming conflicts. The only possible conflict is if we were + // to create a top-level package named exe. + name := "a.out" + if p.exeName != "" { + name = p.exeName + } + a.target = a.objdir + filepath.Join("exe", name) + exeSuffix + } + } + + return a +} + +// actionList returns the list of actions in the dag rooted at root +// as visited in a depth-first post-order traversal. +func actionList(root *action) []*action { + seen := map[*action]bool{} + all := []*action{} + var walk func(*action) + walk = func(a *action) { + if seen[a] { + return + } + seen[a] = true + for _, a1 := range a.deps { + walk(a1) + } + all = append(all, a) + } + walk(root) + return all +} + +// do runs the action graph rooted at root. +func (b *builder) do(root *action) { + // Build list of all actions, assigning depth-first post-order priority. + // The original implementation here was a true queue + // (using a channel) but it had the effect of getting + // distracted by low-level leaf actions to the detriment + // of completing higher-level actions. The order of + // work does not matter much to overall execution time, + // but when running "go test std" it is nice to see each test + // results as soon as possible. The priorities assigned + // ensure that, all else being equal, the execution prefers + // to do what it would have done first in a simple depth-first + // dependency order traversal. + all := actionList(root) + for i, a := range all { + a.priority = i + } + + b.readySema = make(chan bool, len(all)) + + // Initialize per-action execution state. + for _, a := range all { + for _, a1 := range a.deps { + a1.triggers = append(a1.triggers, a) + } + a.pending = len(a.deps) + if a.pending == 0 { + b.ready.push(a) + b.readySema <- true + } + } + + // Handle runs a single action and takes care of triggering + // any actions that are runnable as a result. + handle := func(a *action) { + var err error + if a.f != nil && (!a.failed || a.ignoreFail) { + err = a.f(b, a) + } + + // The actions run in parallel but all the updates to the + // shared work state are serialized through b.exec. + b.exec.Lock() + defer b.exec.Unlock() + + if err != nil { + if err == errPrintedOutput { + setExitStatus(2) + } else { + errorf("%s", err) + } + a.failed = true + } + + for _, a0 := range a.triggers { + if a.failed { + a0.failed = true + } + if a0.pending--; a0.pending == 0 { + b.ready.push(a0) + b.readySema <- true + } + } + + if a == root { + close(b.readySema) + } + } + + var wg sync.WaitGroup + + // Kick off goroutines according to parallelism. + // If we are using the -n flag (just printing commands) + // drop the parallelism to 1, both to make the output + // deterministic and because there is no real work anyway. + par := buildP + if buildN { + par = 1 + } + for i := 0; i < par; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for { + select { + case _, ok := <-b.readySema: + if !ok { + return + } + // Receiving a value from b.readySema entitles + // us to take from the ready queue. + b.exec.Lock() + a := b.ready.pop() + b.exec.Unlock() + handle(a) + case <-interrupted: + setExitStatus(1) + return + } + } + }() + } + + wg.Wait() +} + +// hasString reports whether s appears in the list of strings. +func hasString(strings []string, s string) bool { + for _, t := range strings { + if s == t { + return true + } + } + return false +} + +// build is the action for building a single package or command. +func (b *builder) build(a *action) (err error) { + // Return an error if the package has CXX files but it's not using + // cgo nor SWIG, since the CXX files can only be processed by cgo + // and SWIG (it's possible to have packages with C files without + // using cgo, they will get compiled with the plan9 C compiler and + // linked with the rest of the package). + if len(a.p.CXXFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() { + return fmt.Errorf("can't build package %s because it contains C++ files (%s) but it's not using cgo nor SWIG", + a.p.ImportPath, strings.Join(a.p.CXXFiles, ",")) + } + // Same as above for Objective-C files + if len(a.p.MFiles) > 0 && !a.p.usesCgo() && !a.p.usesSwig() { + return fmt.Errorf("can't build package %s because it contains Objective-C files (%s) but it's not using cgo nor SWIG", + a.p.ImportPath, strings.Join(a.p.MFiles, ",")) + } + defer func() { + if err != nil && err != errPrintedOutput { + err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err) + } + }() + if buildN { + // In -n mode, print a banner between packages. + // The banner is five lines so that when changes to + // different sections of the bootstrap script have to + // be merged, the banners give patch something + // to use to find its context. + fmt.Printf("\n#\n# %s\n#\n\n", a.p.ImportPath) + } + + if buildV { + fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath) + } + + if a.p.Standard && a.p.ImportPath == "runtime" && buildContext.Compiler == "gc" && + !hasString(a.p.HFiles, "zasm_"+buildContext.GOOS+"_"+buildContext.GOARCH+".h") { + return fmt.Errorf("%s/%s must be bootstrapped using make%v", buildContext.GOOS, buildContext.GOARCH, defaultSuffix()) + } + + // Make build directory. + obj := a.objdir + if err := b.mkdir(obj); err != nil { + return err + } + + // make target directory + dir, _ := filepath.Split(a.target) + if dir != "" { + if err := b.mkdir(dir); err != nil { + return err + } + } + + var gofiles, cfiles, sfiles, objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string + + gofiles = append(gofiles, a.p.GoFiles...) + cfiles = append(cfiles, a.p.CFiles...) + sfiles = append(sfiles, a.p.SFiles...) + + if a.p.usesCgo() || a.p.usesSwig() { + if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(a.p); err != nil { + return + } + } + // Run cgo. + if a.p.usesCgo() { + // In a package using cgo, cgo compiles the C, C++ and assembly files with gcc. + // There is one exception: runtime/cgo's job is to bridge the + // cgo and non-cgo worlds, so it necessarily has files in both. + // In that case gcc only gets the gcc_* files. + var gccfiles []string + if a.p.Standard && a.p.ImportPath == "runtime/cgo" { + filter := func(files, nongcc, gcc []string) ([]string, []string) { + for _, f := range files { + if strings.HasPrefix(f, "gcc_") { + gcc = append(gcc, f) + } else { + nongcc = append(nongcc, f) + } + } + return nongcc, gcc + } + cfiles, gccfiles = filter(cfiles, cfiles[:0], gccfiles) + sfiles, gccfiles = filter(sfiles, sfiles[:0], gccfiles) + } else { + gccfiles = append(cfiles, sfiles...) + cfiles = nil + sfiles = nil + } + + cgoExe := tool("cgo") + if a.cgo != nil && a.cgo.target != "" { + cgoExe = a.cgo.target + } + outGo, outObj, err := b.cgo(a.p, cgoExe, obj, pcCFLAGS, pcLDFLAGS, gccfiles, a.p.CXXFiles, a.p.MFiles) + if err != nil { + return err + } + cgoObjects = append(cgoObjects, outObj...) + gofiles = append(gofiles, outGo...) + } + + // Run SWIG. + if a.p.usesSwig() { + // In a package using SWIG, any .c or .s files are + // compiled with gcc. + gccfiles := append(cfiles, sfiles...) + cxxfiles, mfiles := a.p.CXXFiles, a.p.MFiles + cfiles = nil + sfiles = nil + + // Don't build c/c++ files twice if cgo is enabled (mainly for pkg-config). + if a.p.usesCgo() { + cxxfiles = nil + gccfiles = nil + mfiles = nil + } + + outGo, outObj, err := b.swig(a.p, obj, pcCFLAGS, gccfiles, cxxfiles, mfiles) + if err != nil { + return err + } + cgoObjects = append(cgoObjects, outObj...) + gofiles = append(gofiles, outGo...) + } + + if len(gofiles) == 0 { + return &build.NoGoError{Dir: a.p.Dir} + } + + // If we're doing coverage, preprocess the .go files and put them in the work directory + if a.p.coverMode != "" { + for i, file := range gofiles { + var sourceFile string + var coverFile string + var key string + if strings.HasSuffix(file, ".cgo1.go") { + // cgo files have absolute paths + base := filepath.Base(file) + sourceFile = file + coverFile = filepath.Join(obj, base) + key = strings.TrimSuffix(base, ".cgo1.go") + ".go" + } else { + sourceFile = filepath.Join(a.p.Dir, file) + coverFile = filepath.Join(obj, file) + key = file + } + cover := a.p.coverVars[key] + if cover == nil || isTestFile(file) { + // Not covering this file. + continue + } + if err := b.cover(a, coverFile, sourceFile, 0666, cover.Var); err != nil { + return err + } + gofiles[i] = coverFile + } + } + + // Prepare Go import path list. + inc := b.includeArgs("-I", a.deps) + + // Compile Go. + ofile, out, err := buildToolchain.gc(b, a.p, a.objpkg, obj, inc, gofiles) + if len(out) > 0 { + b.showOutput(a.p.Dir, a.p.ImportPath, b.processOutput(out)) + if err != nil { + return errPrintedOutput + } + } + if err != nil { + return err + } + if ofile != a.objpkg { + objects = append(objects, ofile) + } + + // Copy .h files named for goos or goarch or goos_goarch + // to names using GOOS and GOARCH. + // For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h. + _goos_goarch := "_" + goos + "_" + goarch + _goos := "_" + goos + _goarch := "_" + goarch + for _, file := range a.p.HFiles { + name, ext := fileExtSplit(file) + switch { + case strings.HasSuffix(name, _goos_goarch): + targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext + if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644); err != nil { + return err + } + case strings.HasSuffix(name, _goarch): + targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext + if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644); err != nil { + return err + } + case strings.HasSuffix(name, _goos): + targ := file[:len(name)-len(_goos)] + "_GOOS." + ext + if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644); err != nil { + return err + } + } + } + + objExt := archChar + if _, ok := buildToolchain.(gccgoToolchain); ok { + objExt = "o" + } + + for _, file := range cfiles { + out := file[:len(file)-len(".c")] + "." + objExt + if err := buildToolchain.cc(b, a.p, obj, obj+out, file); err != nil { + return err + } + objects = append(objects, out) + } + + // Assemble .s files. + for _, file := range sfiles { + out := file[:len(file)-len(".s")] + "." + objExt + if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err != nil { + return err + } + objects = append(objects, out) + } + + // NOTE(rsc): On Windows, it is critically important that the + // gcc-compiled objects (cgoObjects) be listed after the ordinary + // objects in the archive. I do not know why this is. + // http://golang.org/issue/2601 + objects = append(objects, cgoObjects...) + + // Add system object files. + for _, syso := range a.p.SysoFiles { + objects = append(objects, filepath.Join(a.p.Dir, syso)) + } + + // Pack into archive in obj directory. + // If the Go compiler wrote an archive, we only need to add the + // object files for non-Go sources to the archive. + // If the Go compiler wrote an archive and the package is entirely + // Go sources, there is no pack to execute at all. + if len(objects) > 0 { + if err := buildToolchain.pack(b, a.p, obj, a.objpkg, objects); err != nil { + return err + } + } + + // Link if needed. + if a.link { + // The compiler only cares about direct imports, but the + // linker needs the whole dependency tree. + all := actionList(a) + all = all[:len(all)-1] // drop a + if err := buildToolchain.ld(b, a.p, a.target, all, a.objpkg, objects); err != nil { + return err + } + } + + return nil +} + +// Calls pkg-config if needed and returns the cflags/ldflags needed to build the package. +func (b *builder) getPkgConfigFlags(p *Package) (cflags, ldflags []string, err error) { + if pkgs := p.CgoPkgConfig; len(pkgs) > 0 { + var out []byte + out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--cflags", pkgs) + if err != nil { + b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(pkgs, " "), string(out)) + b.print(err.Error() + "\n") + err = errPrintedOutput + return + } + if len(out) > 0 { + cflags = strings.Fields(string(out)) + } + out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs) + if err != nil { + b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pkgs, " "), string(out)) + b.print(err.Error() + "\n") + err = errPrintedOutput + return + } + if len(out) > 0 { + ldflags = strings.Fields(string(out)) + } + } + return +} + +// install is the action for installing a single package or executable. +func (b *builder) install(a *action) (err error) { + defer func() { + if err != nil && err != errPrintedOutput { + err = fmt.Errorf("go install %s: %v", a.p.ImportPath, err) + } + }() + a1 := a.deps[0] + perm := os.FileMode(0644) + if a1.link { + perm = 0755 + } + + // make target directory + dir, _ := filepath.Split(a.target) + if dir != "" { + if err := b.mkdir(dir); err != nil { + return err + } + } + + // remove object dir to keep the amount of + // garbage down in a large build. On an operating system + // with aggressive buffering, cleaning incrementally like + // this keeps the intermediate objects from hitting the disk. + if !buildWork { + defer os.RemoveAll(a1.objdir) + defer os.Remove(a1.target) + } + + return b.moveOrCopyFile(a, a.target, a1.target, perm) +} + +// includeArgs returns the -I or -L directory list for access +// to the results of the list of actions. +func (b *builder) includeArgs(flag string, all []*action) []string { + inc := []string{} + incMap := map[string]bool{ + b.work: true, // handled later + gorootPkg: true, + "": true, // ignore empty strings + } + + // Look in the temporary space for results of test-specific actions. + // This is the $WORK/my/package/_test directory for the + // package being built, so there are few of these. + for _, a1 := range all { + if dir := a1.pkgdir; dir != a1.p.build.PkgRoot && !incMap[dir] { + incMap[dir] = true + inc = append(inc, flag, dir) + } + } + + // Also look in $WORK for any non-test packages that have + // been built but not installed. + inc = append(inc, flag, b.work) + + // Finally, look in the installed package directories for each action. + for _, a1 := range all { + if dir := a1.pkgdir; dir == a1.p.build.PkgRoot && !incMap[dir] { + incMap[dir] = true + if _, ok := buildToolchain.(gccgoToolchain); ok { + dir = filepath.Join(dir, "gccgo_"+goos+"_"+goarch) + } else { + dir = filepath.Join(dir, goos+"_"+goarch) + if buildContext.InstallSuffix != "" { + dir += "_" + buildContext.InstallSuffix + } + } + inc = append(inc, flag, dir) + } + } + + return inc +} + +// moveOrCopyFile is like 'mv src dst' or 'cp src dst'. +func (b *builder) moveOrCopyFile(a *action, dst, src string, perm os.FileMode) error { + if buildN { + b.showcmd("", "mv %s %s", src, dst) + return nil + } + + // If we can update the mode and rename to the dst, do it. + // Otherwise fall back to standard copy. + if err := os.Chmod(src, perm); err == nil { + if err := os.Rename(src, dst); err == nil { + if buildX { + b.showcmd("", "mv %s %s", src, dst) + } + return nil + } + } + + return b.copyFile(a, dst, src, perm) +} + +// copyFile is like 'cp src dst'. +func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode) error { + if buildN || buildX { + b.showcmd("", "cp %s %s", src, dst) + if buildN { + return nil + } + } + + sf, err := os.Open(src) + if err != nil { + return err + } + defer sf.Close() + + // Be careful about removing/overwriting dst. + // Do not remove/overwrite if dst exists and is a directory + // or a non-object file. + if fi, err := os.Stat(dst); err == nil { + if fi.IsDir() { + return fmt.Errorf("build output %q already exists and is a directory", dst) + } + if !isObject(dst) { + return fmt.Errorf("build output %q already exists and is not an object file", dst) + } + } + + // On Windows, remove lingering ~ file from last attempt. + if toolIsWindows { + if _, err := os.Stat(dst + "~"); err == nil { + os.Remove(dst + "~") + } + } + + os.Remove(dst) + df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) + if err != nil && toolIsWindows { + // Windows does not allow deletion of a binary file + // while it is executing. Try to move it out of the way. + // If the move fails, which is likely, we'll try again the + // next time we do an install of this binary. + if err := os.Rename(dst, dst+"~"); err == nil { + os.Remove(dst + "~") + } + df, err = os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) + } + if err != nil { + return err + } + + _, err = io.Copy(df, sf) + df.Close() + if err != nil { + os.Remove(dst) + return fmt.Errorf("copying %s to %s: %v", src, dst, err) + } + return nil +} + +// cover runs, in effect, +// go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go +func (b *builder) cover(a *action, dst, src string, perm os.FileMode, varName string) error { + return b.run(a.objdir, "cover "+a.p.ImportPath, nil, + tool("cover"), + "-mode", a.p.coverMode, + "-var", varName, + "-o", dst, + src) +} + +var objectMagic = [][]byte{ + {'!', '<', 'a', 'r', 'c', 'h', '>', '\n'}, // Package archive + {'\x7F', 'E', 'L', 'F'}, // ELF + {0xFE, 0xED, 0xFA, 0xCE}, // Mach-O big-endian 32-bit + {0xFE, 0xED, 0xFA, 0xCF}, // Mach-O big-endian 64-bit + {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, 0x04, 0x00}, // PE (Windows) as generated by 6l/8l + {0x00, 0x00, 0x01, 0xEB}, // Plan 9 i386 + {0x00, 0x00, 0x8a, 0x97}, // Plan 9 amd64 +} + +func isObject(s string) bool { + f, err := os.Open(s) + if err != nil { + return false + } + defer f.Close() + buf := make([]byte, 64) + io.ReadFull(f, buf) + for _, magic := range objectMagic { + if bytes.HasPrefix(buf, magic) { + return true + } + } + return false +} + +// fmtcmd formats a command in the manner of fmt.Sprintf but also: +// +// If dir is non-empty and the script is not in dir right now, +// fmtcmd inserts "cd dir\n" before the command. +// +// fmtcmd replaces the value of b.work with $WORK. +// fmtcmd replaces the value of goroot with $GOROOT. +// fmtcmd replaces the value of b.gobin with $GOBIN. +// +// fmtcmd replaces the name of the current directory with dot (.) +// but only when it is at the beginning of a space-separated token. +// +func (b *builder) fmtcmd(dir string, format string, args ...interface{}) string { + cmd := fmt.Sprintf(format, args...) + if dir != "" && dir != "/" { + cmd = strings.Replace(" "+cmd, " "+dir, " .", -1)[1:] + if b.scriptDir != dir { + b.scriptDir = dir + cmd = "cd " + dir + "\n" + cmd + } + } + if b.work != "" { + cmd = strings.Replace(cmd, b.work, "$WORK", -1) + } + return cmd +} + +// showcmd prints the given command to standard output +// for the implementation of -n or -x. +func (b *builder) showcmd(dir string, format string, args ...interface{}) { + b.output.Lock() + defer b.output.Unlock() + b.print(b.fmtcmd(dir, format, args...) + "\n") +} + +// showOutput prints "# desc" followed by the given output. +// The output is expected to contain references to 'dir', usually +// the source directory for the package that has failed to build. +// showOutput rewrites mentions of dir with a relative path to dir +// when the relative path is shorter. This is usually more pleasant. +// For example, if fmt doesn't compile and we are in src/html, +// the output is +// +// $ go build +// # fmt +// ../fmt/print.go:1090: undefined: asdf +// $ +// +// instead of +// +// $ go build +// # fmt +// /usr/gopher/go/src/fmt/print.go:1090: undefined: asdf +// $ +// +// showOutput also replaces references to the work directory with $WORK. +// +func (b *builder) showOutput(dir, desc, out string) { + prefix := "# " + desc + suffix := "\n" + out + if reldir := shortPath(dir); reldir != dir { + suffix = strings.Replace(suffix, " "+dir, " "+reldir, -1) + suffix = strings.Replace(suffix, "\n"+dir, "\n"+reldir, -1) + } + suffix = strings.Replace(suffix, " "+b.work, " $WORK", -1) + + b.output.Lock() + defer b.output.Unlock() + b.print(prefix, suffix) +} + +// 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) { + return rel + } + return path +} + +// relPaths returns a copy of paths with absolute paths +// made relative to the current directory if they would be shorter. +func relPaths(paths []string) []string { + var out []string + pwd, _ := os.Getwd() + for _, p := range paths { + rel, err := filepath.Rel(pwd, p) + if err == nil && len(rel) < len(p) { + p = rel + } + out = append(out, p) + } + return out +} + +// errPrintedOutput is a special error indicating that a command failed +// but that it generated output as well, and that output has already +// been printed, so there's no point showing 'exit status 1' or whatever +// the wait status was. The main executor, builder.do, knows not to +// print this error. +var errPrintedOutput = errors.New("already printed output - no need to show error") + +var cgoLine = regexp.MustCompile(`\[[^\[\]]+\.cgo1\.go:[0-9]+\]`) +var cgoTypeSigRe = regexp.MustCompile(`\b_Ctype_\B`) + +// run runs the command given by cmdline in the directory dir. +// If the command fails, run prints information about the failure +// and returns a non-nil error. +func (b *builder) run(dir string, desc string, env []string, cmdargs ...interface{}) error { + out, err := b.runOut(dir, desc, env, cmdargs...) + if len(out) > 0 { + if desc == "" { + desc = b.fmtcmd(dir, "%s", strings.Join(stringList(cmdargs...), " ")) + } + b.showOutput(dir, desc, b.processOutput(out)) + if err != nil { + err = errPrintedOutput + } + } + return err +} + +// processOutput prepares the output of runOut to be output to the console. +func (b *builder) processOutput(out []byte) string { + if out[len(out)-1] != '\n' { + out = append(out, '\n') + } + messages := string(out) + // Fix up output referring to cgo-generated code to be more readable. + // Replace x.go:19[/tmp/.../x.cgo1.go:18] with x.go:19. + // Replace *[100]_Ctype_foo with *[100]C.foo. + // If we're using -x, assume we're debugging and want the full dump, so disable the rewrite. + if !buildX && cgoLine.MatchString(messages) { + messages = cgoLine.ReplaceAllString(messages, "") + messages = cgoTypeSigRe.ReplaceAllString(messages, "C.") + } + return messages +} + +// runOut runs the command given by cmdline in the directory dir. +// It returns the command output and any errors that occurred. +func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) { + cmdline := stringList(cmdargs...) + if buildN || buildX { + var envcmdline string + for i := range env { + envcmdline += env[i] + envcmdline += " " + } + envcmdline += joinUnambiguously(cmdline) + b.showcmd(dir, "%s", envcmdline) + if buildN { + return nil, nil + } + } + + nbusy := 0 + for { + var buf bytes.Buffer + cmd := exec.Command(cmdline[0], cmdline[1:]...) + cmd.Stdout = &buf + cmd.Stderr = &buf + cmd.Dir = dir + cmd.Env = mergeEnvLists(env, envForDir(cmd.Dir)) + err := cmd.Run() + + // cmd.Run will fail on Unix if some other process has the binary + // we want to run open for writing. This can happen here because + // we build and install the cgo command and then run it. + // If another command was kicked off while we were writing the + // cgo binary, the child process for that command may be holding + // a reference to the fd, keeping us from running exec. + // + // But, you might reasonably wonder, how can this happen? + // The cgo fd, like all our fds, is close-on-exec, so that we need + // not worry about other processes inheriting the fd accidentally. + // The answer is that running a command is fork and exec. + // A child forked while the cgo fd is open inherits that fd. + // Until the child has called exec, it holds the fd open and the + // kernel will not let us run cgo. Even if the child were to close + // the fd explicitly, it would still be open from the time of the fork + // until the time of the explicit close, and the race would remain. + // + // On Unix systems, this results in ETXTBSY, which formats + // as "text file busy". Rather than hard-code specific error cases, + // we just look for that string. If this happens, sleep a little + // and try again. We let this happen three times, with increasing + // sleep lengths: 100+200+400 ms = 0.7 seconds. + // + // An alternate solution might be to split the cmd.Run into + // separate cmd.Start and cmd.Wait, and then use an RWLock + // to make sure that copyFile only executes when no cmd.Start + // call is in progress. However, cmd.Start (really syscall.forkExec) + // only guarantees that when it returns, the exec is committed to + // happen and succeed. It uses a close-on-exec file descriptor + // itself to determine this, so we know that when cmd.Start returns, + // at least one close-on-exec file descriptor has been closed. + // However, we cannot be sure that all of them have been closed, + // so the program might still encounter ETXTBSY even with such + // an RWLock. The race window would be smaller, perhaps, but not + // guaranteed to be gone. + // + // Sleeping when we observe the race seems to be the most reliable + // option we have. + // + // http://golang.org/issue/3001 + // + if err != nil && nbusy < 3 && strings.Contains(err.Error(), "text file busy") { + time.Sleep(100 * time.Millisecond << uint(nbusy)) + nbusy++ + continue + } + + // err can be something like 'exit status 1'. + // Add information about what program was running. + // Note that if buf.Bytes() is non-empty, the caller usually + // shows buf.Bytes() and does not print err at all, so the + // prefix here does not make most output any more verbose. + if err != nil { + err = errors.New(cmdline[0] + ": " + err.Error()) + } + return buf.Bytes(), err + } +} + +// joinUnambiguously prints the slice, quoting where necessary to make the +// output unambiguous. +// TODO: See issue 5279. The printing of commands needs a complete redo. +func joinUnambiguously(a []string) string { + var buf bytes.Buffer + for i, s := range a { + if i > 0 { + buf.WriteByte(' ') + } + q := strconv.Quote(s) + if s == "" || strings.Contains(s, " ") || len(q) > len(s)+2 { + buf.WriteString(q) + } else { + buf.WriteString(s) + } + } + return buf.String() +} + +// mkdir makes the named directory. +func (b *builder) mkdir(dir string) error { + b.exec.Lock() + defer b.exec.Unlock() + // We can be a little aggressive about being + // sure directories exist. Skip repeated calls. + if b.mkdirCache[dir] { + return nil + } + b.mkdirCache[dir] = true + + if buildN || buildX { + b.showcmd("", "mkdir -p %s", dir) + if buildN { + return nil + } + } + + if err := os.MkdirAll(dir, 0777); err != nil { + return err + } + return nil +} + +// mkAbs returns an absolute path corresponding to +// evaluating f in the directory dir. +// We always pass absolute paths of source files so that +// the error messages will include the full path to a file +// in need of attention. +func mkAbs(dir, f string) string { + // Leave absolute paths alone. + // Also, during -n mode we use the pseudo-directory $WORK + // instead of creating an actual work directory that won't be used. + // Leave paths beginning with $WORK alone too. + if filepath.IsAbs(f) || strings.HasPrefix(f, "$WORK") { + return f + } + return filepath.Join(dir, f) +} + +type toolchain interface { + // gc runs the compiler in a specific directory on a set of files + // and returns the name of the generated output file. + // The compiler runs in the directory dir. + gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error) + // cc runs the toolchain's C compiler in a directory on a C file + // to produce an output file. + cc(b *builder, p *Package, objdir, ofile, cfile string) error + // asm runs the assembler in a specific directory on a specific file + // to generate the named output file. + asm(b *builder, p *Package, obj, ofile, sfile string) error + // pkgpath builds an appropriate path for a temporary package file. + pkgpath(basedir string, p *Package) string + // pack runs the archive packer in a specific directory to create + // an archive from a set of object files. + // typically it is run in the object directory. + pack(b *builder, p *Package, objDir, afile string, ofiles []string) error + // ld runs the linker to create a package starting at mainpkg. + ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error + + compiler() string + linker() string +} + +type noToolchain struct{} + +func noCompiler() error { + log.Fatalf("unknown compiler %q", buildContext.Compiler) + return nil +} + +func (noToolchain) compiler() string { + noCompiler() + return "" +} + +func (noToolchain) linker() string { + noCompiler() + return "" +} + +func (noToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error) { + return "", nil, noCompiler() +} + +func (noToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { + return noCompiler() +} + +func (noToolchain) pkgpath(basedir string, p *Package) string { + noCompiler() + return "" +} + +func (noToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error { + return noCompiler() +} + +func (noToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error { + return noCompiler() +} + +func (noToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { + return noCompiler() +} + +// The Go toolchain. +type gcToolchain struct{} + +func (gcToolchain) compiler() string { + return tool(archChar + "g") +} + +func (gcToolchain) linker() string { + return tool(archChar + "l") +} + +func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) { + if archive != "" { + ofile = archive + } else { + out := "_go_." + archChar + ofile = obj + out + } + + gcargs := []string{"-p", p.ImportPath} + if p.Standard && p.ImportPath == "runtime" { + // runtime compiles with a special 6g flag to emit + // additional reflect type data. + gcargs = append(gcargs, "-+") + } + + // If we're giving the compiler the entire package (no C etc files), tell it that, + // so that it can give good error messages about forward declarations. + // Exceptions: a few standard packages have forward declarations for + // pieces supplied behind-the-scenes by package runtime. + extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.MFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles) + if p.Standard { + switch p.ImportPath { + case "bytes", "net", "os", "runtime/pprof", "sync", "time": + extFiles++ + } + } + if extFiles == 0 { + gcargs = append(gcargs, "-complete") + } + if buildContext.InstallSuffix != "" { + gcargs = append(gcargs, "-installsuffix", buildContext.InstallSuffix) + } + + args := stringList(tool(archChar+"g"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs) + if ofile == archive { + args = append(args, "-pack") + } + for _, f := range gofiles { + args = append(args, mkAbs(p.Dir, f)) + } + + output, err = b.runOut(p.Dir, p.ImportPath, nil, args) + return ofile, output, err +} + +func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { + // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files. + inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) + sfile = mkAbs(p.Dir, sfile) + return b.run(p.Dir, p.ImportPath, nil, tool(archChar+"a"), "-trimpath", b.work, "-I", obj, "-I", inc, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile) +} + +func (gcToolchain) pkgpath(basedir string, p *Package) string { + end := filepath.FromSlash(p.ImportPath + ".a") + return filepath.Join(basedir, end) +} + +func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error { + var absOfiles []string + for _, f := range ofiles { + absOfiles = append(absOfiles, mkAbs(objDir, f)) + } + cmd := "c" + absAfile := mkAbs(objDir, afile) + appending := false + if _, err := os.Stat(absAfile); err == nil { + appending = true + cmd = "r" + } + + cmdline := stringList("pack", cmd, absAfile, absOfiles) + + if appending { + if buildN || buildX { + b.showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline)) + } + if buildN { + return nil + } + if err := packInternal(b, absAfile, absOfiles); err != nil { + b.showOutput(p.Dir, p.ImportPath, err.Error()+"\n") + return errPrintedOutput + } + return nil + } + + // Need actual pack. + cmdline[0] = tool("pack") + return b.run(p.Dir, p.ImportPath, nil, cmdline) +} + +func packInternal(b *builder, afile string, ofiles []string) error { + dst, err := os.OpenFile(afile, os.O_WRONLY|os.O_APPEND, 0) + if err != nil { + return err + } + defer dst.Close() // only for error returns or panics + w := bufio.NewWriter(dst) + + for _, ofile := range ofiles { + src, err := os.Open(ofile) + if err != nil { + return err + } + fi, err := src.Stat() + if err != nil { + src.Close() + return err + } + // Note: Not using %-16.16s format because we care + // about bytes, not runes. + name := fi.Name() + if len(name) > 16 { + name = name[:16] + } else { + name += strings.Repeat(" ", 16-len(name)) + } + size := fi.Size() + fmt.Fprintf(w, "%s%-12d%-6d%-6d%-8o%-10d`\n", + name, 0, 0, 0, 0644, size) + n, err := io.Copy(w, src) + src.Close() + if err == nil && n < size { + err = io.ErrUnexpectedEOF + } else if err == nil && n > size { + err = fmt.Errorf("file larger than size reported by stat") + } + if err != nil { + return fmt.Errorf("copying %s to %s: %v", ofile, afile, err) + } + if size&1 != 0 { + w.WriteByte(0) + } + } + + if err := w.Flush(); err != nil { + return err + } + return dst.Close() +} + +func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error { + importArgs := b.includeArgs("-L", allactions) + cxx := len(p.CXXFiles) > 0 + for _, a := range allactions { + if a.p != nil && len(a.p.CXXFiles) > 0 { + cxx = true + } + } + ldflags := buildLdflags + // Limit slice capacity so that concurrent appends do not race on the shared array. + ldflags = ldflags[:len(ldflags):len(ldflags)] + if buildContext.InstallSuffix != "" { + ldflags = append(ldflags, "-installsuffix", buildContext.InstallSuffix) + } + if p.omitDWARF { + ldflags = append(ldflags, "-w") + } + + // If the user has not specified the -extld option, then specify the + // appropriate linker. In case of C++ code, use the compiler named + // by the CXX environment variable or defaultCXX if CXX is not set. + // Else, use the CC environment variable and defaultCC as fallback. + extld := false + for _, f := range ldflags { + if f == "-extld" || strings.HasPrefix(f, "-extld=") { + extld = true + break + } + } + if !extld { + var compiler []string + if cxx { + compiler = envList("CXX", defaultCXX) + } else { + compiler = envList("CC", defaultCC) + } + ldflags = append(ldflags, "-extld="+compiler[0]) + if len(compiler) > 1 { + extldflags := false + add := strings.Join(compiler[1:], " ") + for i, f := range ldflags { + if f == "-extldflags" && i+1 < len(ldflags) { + ldflags[i+1] = add + " " + ldflags[i+1] + extldflags = true + break + } else if strings.HasPrefix(f, "-extldflags=") { + ldflags[i] = "-extldflags=" + add + " " + ldflags[i][len("-extldflags="):] + extldflags = true + break + } + } + if !extldflags { + ldflags = append(ldflags, "-extldflags="+add) + } + } + } + return b.run(".", p.ImportPath, nil, tool(archChar+"l"), "-o", out, importArgs, ldflags, mainpkg) +} + +func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { + inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) + cfile = mkAbs(p.Dir, cfile) + warn := []string{"-w"} + if p.usesSwig() { + // When using SWIG, this compiler is only used to + // compile the C files generated by SWIG. + // We don't want warnings. + // See issue 9065 for details. + warn = nil + } + args := stringList(tool(archChar+"c"), "-F", "-V", warn, "-trimpath", b.work, "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile) + return b.run(p.Dir, p.ImportPath, nil, args) +} + +// The Gccgo toolchain. +type gccgoToolchain struct{} + +var gccgoName, gccgoBin string + +func init() { + gccgoName = os.Getenv("GCCGO") + if gccgoName == "" { + gccgoName = defaultGCCGO + } + gccgoBin, _ = exec.LookPath(gccgoName) +} + +func (gccgoToolchain) compiler() string { + return gccgoBin +} + +func (gccgoToolchain) linker() string { + return gccgoBin +} + +func (tools gccgoToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) { + out := "_go_.o" + ofile = obj + out + gcargs := []string{"-g"} + gcargs = append(gcargs, b.gccArchArgs()...) + if pkgpath := gccgoPkgpath(p); pkgpath != "" { + gcargs = append(gcargs, "-fgo-pkgpath="+pkgpath) + } + if p.localPrefix != "" { + gcargs = append(gcargs, "-fgo-relative-import-path="+p.localPrefix) + } + args := stringList(tools.compiler(), importArgs, "-c", gcargs, "-o", ofile, buildGccgoflags) + for _, f := range gofiles { + args = append(args, mkAbs(p.Dir, f)) + } + + output, err = b.runOut(p.Dir, p.ImportPath, nil, args) + return ofile, output, err +} + +func (tools gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { + sfile = mkAbs(p.Dir, sfile) + defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch} + if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { + defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) + } + defs = append(defs, b.gccArchArgs()...) + + return b.run(p.Dir, p.ImportPath, nil, tools.compiler(), "-c", "-I", obj, "-o", ofile, defs, sfile) +} + +func (gccgoToolchain) pkgpath(basedir string, p *Package) string { + end := filepath.FromSlash(p.ImportPath + ".a") + afile := filepath.Join(basedir, end) + // add "lib" to the final element + return filepath.Join(filepath.Dir(afile), "lib"+filepath.Base(afile)) +} + +func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []string) error { + var absOfiles []string + for _, f := range ofiles { + absOfiles = append(absOfiles, mkAbs(objDir, f)) + } + return b.run(p.Dir, p.ImportPath, nil, "ar", "cru", mkAbs(objDir, afile), absOfiles) +} + +func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []*action, mainpkg string, ofiles []string) error { + // gccgo needs explicit linking with all package dependencies, + // and all LDFLAGS from cgo dependencies. + apackagesSeen := make(map[*Package]bool) + afiles := []string{} + xfiles := []string{} + ldflags := b.gccArchArgs() + cgoldflags := []string{} + usesCgo := false + cxx := len(p.CXXFiles) > 0 + objc := len(p.MFiles) > 0 + + // Prefer the output of an install action to the output of a build action, + // because the install action will delete the output of the build action. + // Iterate over the list backward (reverse dependency order) so that we + // always see the install before the build. + for i := len(allactions) - 1; i >= 0; i-- { + a := allactions[i] + if !a.p.Standard { + if a.p != nil && !apackagesSeen[a.p] { + apackagesSeen[a.p] = true + if a.p.fake && a.p.external { + // external _tests, if present must come before + // internal _tests. Store these on a seperate list + // and place them at the head after this loop. + xfiles = append(xfiles, a.target) + } else if a.p.fake { + // move _test files to the top of the link order + afiles = append([]string{a.target}, afiles...) + } else { + afiles = append(afiles, a.target) + } + } + } + } + afiles = append(xfiles, afiles...) + + for _, a := range allactions { + if a.p != nil { + cgoldflags = append(cgoldflags, a.p.CgoLDFLAGS...) + if len(a.p.CgoFiles) > 0 { + usesCgo = true + } + if a.p.usesSwig() { + usesCgo = true + } + if len(a.p.CXXFiles) > 0 { + cxx = true + } + if len(a.p.MFiles) > 0 { + objc = true + } + } + } + ldflags = append(ldflags, afiles...) + ldflags = append(ldflags, cgoldflags...) + ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...) + ldflags = append(ldflags, p.CgoLDFLAGS...) + if usesCgo && goos == "linux" { + ldflags = append(ldflags, "-Wl,-E") + } + if cxx { + ldflags = append(ldflags, "-lstdc++") + } + if objc { + ldflags = append(ldflags, "-lobjc") + } + return b.run(".", p.ImportPath, nil, tools.linker(), "-o", out, ofiles, "-Wl,-(", ldflags, "-Wl,-)", buildGccgoflags) +} + +func (gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { + inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) + cfile = mkAbs(p.Dir, cfile) + defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch} + defs = append(defs, b.gccArchArgs()...) + if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" { + defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`) + } + return b.run(p.Dir, p.ImportPath, nil, envList("CC", defaultCC), "-Wall", "-g", + "-I", objdir, "-I", inc, "-o", ofile, defs, "-c", cfile) +} + +func gccgoPkgpath(p *Package) string { + if p.build.IsCommand() && !p.forceLibrary { + return "" + } + return p.ImportPath +} + +func gccgoCleanPkgpath(p *Package) string { + clean := func(r rune) rune { + switch { + case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z', + '0' <= r && r <= '9': + return r + } + return '_' + } + return strings.Map(clean, gccgoPkgpath(p)) +} + +// libgcc returns the filename for libgcc, as determined by invoking gcc with +// the -print-libgcc-file-name option. +func (b *builder) libgcc(p *Package) (string, error) { + var buf bytes.Buffer + + gccCmd := b.gccCmd(p.Dir) + + prev := b.print + if buildN { + // In -n mode we temporarily swap out the builder's + // print function to capture the command-line. This + // let's us assign it to $LIBGCC and produce a valid + // buildscript for cgo packages. + b.print = func(a ...interface{}) (int, error) { + return fmt.Fprint(&buf, a...) + } + } + f, err := b.runOut(p.Dir, p.ImportPath, nil, gccCmd, "-print-libgcc-file-name") + if err != nil { + return "", fmt.Errorf("gcc -print-libgcc-file-name: %v (%s)", err, f) + } + if buildN { + s := fmt.Sprintf("LIBGCC=$(%s)\n", buf.Next(buf.Len()-1)) + b.print = prev + b.print(s) + return "$LIBGCC", nil + } + + // The compiler might not be able to find libgcc, and in that case, + // it will simply return "libgcc.a", which is of no use to us. + if !filepath.IsAbs(string(f)) { + return "", nil + } + + return strings.Trim(string(f), "\r\n"), nil +} + +// gcc runs the gcc C compiler to create an object from a single C file. +func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error { + return b.ccompile(p, out, flags, cfile, b.gccCmd(p.Dir)) +} + +// gxx runs the g++ C++ compiler to create an object from a single C++ file. +func (b *builder) gxx(p *Package, out string, flags []string, cxxfile string) error { + return b.ccompile(p, out, flags, cxxfile, b.gxxCmd(p.Dir)) +} + +// ccompile runs the given C or C++ compiler and creates an object from a single source file. +func (b *builder) ccompile(p *Package, out string, flags []string, file string, compiler []string) error { + file = mkAbs(p.Dir, file) + return b.run(p.Dir, p.ImportPath, nil, compiler, flags, "-o", out, "-c", file) +} + +// gccld runs the gcc linker to create an executable from a set of object files. +func (b *builder) gccld(p *Package, out string, flags []string, obj []string) error { + var cmd []string + if len(p.CXXFiles) > 0 { + cmd = b.gxxCmd(p.Dir) + } else { + cmd = b.gccCmd(p.Dir) + } + return b.run(p.Dir, p.ImportPath, nil, cmd, "-o", out, obj, flags) +} + +// gccCmd returns a gcc command line prefix +// defaultCC is defined in zdefaultcc.go, written by cmd/dist. +func (b *builder) gccCmd(objdir string) []string { + return b.ccompilerCmd("CC", defaultCC, objdir) +} + +// gxxCmd returns a g++ command line prefix +// defaultCXX is defined in zdefaultcc.go, written by cmd/dist. +func (b *builder) gxxCmd(objdir string) []string { + return b.ccompilerCmd("CXX", defaultCXX, objdir) +} + +// ccompilerCmd returns a command line prefix for the given environment +// variable and using the default command when the variable is empty. +func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string { + // NOTE: env.go's mkEnv knows that the first three + // strings returned are "gcc", "-I", objdir (and cuts them off). + + compiler := envList(envvar, defcmd) + a := []string{compiler[0], "-I", objdir} + a = append(a, compiler[1:]...) + + // Definitely want -fPIC but on Windows gcc complains + // "-fPIC ignored for target (all code is position independent)" + if goos != "windows" { + a = append(a, "-fPIC") + } + a = append(a, b.gccArchArgs()...) + // gcc-4.5 and beyond require explicit "-pthread" flag + // for multithreading with pthread library. + if buildContext.CgoEnabled { + switch goos { + case "windows": + a = append(a, "-mthreads") + default: + a = append(a, "-pthread") + } + } + + if strings.Contains(a[0], "clang") { + // disable ASCII art in clang errors, if possible + a = append(a, "-fno-caret-diagnostics") + // clang is too smart about command-line arguments + a = append(a, "-Qunused-arguments") + } + + // disable word wrapping in error messages + a = append(a, "-fmessage-length=0") + + // On OS X, some of the compilers behave as if -fno-common + // is always set, and the Mach-O linker in 6l/8l assumes this. + // See http://golang.org/issue/3253. + if goos == "darwin" { + a = append(a, "-fno-common") + } + + return a +} + +// gccArchArgs returns arguments to pass to gcc based on the architecture. +func (b *builder) gccArchArgs() []string { + switch archChar { + case "8": + return []string{"-m32"} + case "6": + return []string{"-m64"} + case "5": + return []string{"-marm"} // not thumb + } + return nil +} + +// envList returns the value of the given environment variable broken +// into fields, using the default value when the variable is empty. +func envList(key, def string) []string { + v := os.Getenv(key) + if v == "" { + v = def + } + return strings.Fields(v) +} + +// Return the flags to use when invoking the C or C++ compilers, or cgo. +func (b *builder) cflags(p *Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) { + var defaults string + if def { + defaults = "-g -O2" + } + + cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS) + cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS) + cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS) + ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS) + return +} + +var cgoRe = regexp.MustCompile(`[/\\:]`) + +var ( + cgoLibGccFile string + cgoLibGccErr error + cgoLibGccFileOnce sync.Once +) + +func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) { + cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoLDFLAGS := b.cflags(p, true) + _, cgoexeCFLAGS, _, _ := b.cflags(p, false) + cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...) + cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...) + // If we are compiling Objective-C code, then we need to link against libobjc + if len(mfiles) > 0 { + cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc") + } + + // Allows including _cgo_export.h from .[ch] files in the package. + cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj) + + // cgo + // TODO: CGOPKGPATH, CGO_FLAGS? + gofiles := []string{obj + "_cgo_gotypes.go"} + cfiles := []string{"_cgo_main.c", "_cgo_export.c"} + for _, fn := range p.CgoFiles { + f := cgoRe.ReplaceAllString(fn[:len(fn)-2], "_") + gofiles = append(gofiles, obj+f+"cgo1.go") + cfiles = append(cfiles, f+"cgo2.c") + } + defunC := obj + "_cgo_defun.c" + + cgoflags := []string{} + // TODO: make cgo not depend on $GOARCH? + + objExt := archChar + + if p.Standard && p.ImportPath == "runtime/cgo" { + cgoflags = append(cgoflags, "-import_runtime_cgo=false") + } + if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/cgo") { + cgoflags = append(cgoflags, "-import_syscall=false") + } + + // Update $CGO_LDFLAGS with p.CgoLDFLAGS. + var cgoenv []string + if len(cgoLDFLAGS) > 0 { + flags := make([]string, len(cgoLDFLAGS)) + for i, f := range cgoLDFLAGS { + flags[i] = strconv.Quote(f) + } + cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")} + } + + if _, ok := buildToolchain.(gccgoToolchain); ok { + cgoflags = append(cgoflags, "-gccgo") + if pkgpath := gccgoPkgpath(p); pkgpath != "" { + cgoflags = append(cgoflags, "-gccgopkgpath="+pkgpath) + } + objExt = "o" + } + if err := b.run(p.Dir, p.ImportPath, cgoenv, cgoExe, "-objdir", obj, cgoflags, "--", cgoCPPFLAGS, cgoexeCFLAGS, p.CgoFiles); err != nil { + return nil, nil, err + } + outGo = append(outGo, gofiles...) + + // cc _cgo_defun.c + defunObj := obj + "_cgo_defun." + objExt + if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil { + return nil, nil, err + } + outObj = append(outObj, defunObj) + + // gcc + var linkobj []string + + var bareLDFLAGS []string + // filter out -lsomelib, -l somelib, *.{so,dll,dylib}, and (on Darwin) -framework X + for i := 0; i < len(cgoLDFLAGS); i++ { + f := cgoLDFLAGS[i] + switch { + // skip "-lc" or "-l somelib" + case strings.HasPrefix(f, "-l"): + if f == "-l" { + i++ + } + // skip "-framework X" on Darwin + case goos == "darwin" && f == "-framework": + i++ + // skip "*.{dylib,so,dll}" + case strings.HasSuffix(f, ".dylib"), + strings.HasSuffix(f, ".so"), + strings.HasSuffix(f, ".dll"): + continue + // Remove any -fsanitize=foo flags. + // Otherwise the compiler driver thinks that we are doing final link + // and links sanitizer runtime into the object file. But we are not doing + // the final link, we will link the resulting object file again. And + // so the program ends up with two copies of sanitizer runtime. + // See issue 8788 for details. + case strings.HasPrefix(f, "-fsanitize="): + continue + default: + bareLDFLAGS = append(bareLDFLAGS, f) + } + } + + cgoLibGccFileOnce.Do(func() { + cgoLibGccFile, cgoLibGccErr = b.libgcc(p) + }) + if cgoLibGccFile == "" && cgoLibGccErr != nil { + return nil, nil, err + } + + var staticLibs []string + if goos == "windows" { + // libmingw32 and libmingwex might also use libgcc, so libgcc must come last, + // and they also have some inter-dependencies, so must use linker groups. + staticLibs = []string{"-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group"} + } + if cgoLibGccFile != "" { + staticLibs = append(staticLibs, cgoLibGccFile) + } + + cflags := stringList(cgoCPPFLAGS, cgoCFLAGS) + for _, cfile := range cfiles { + ofile := obj + cfile[:len(cfile)-1] + "o" + if err := b.gcc(p, ofile, cflags, obj+cfile); err != nil { + return nil, nil, err + } + linkobj = append(linkobj, ofile) + if !strings.HasSuffix(ofile, "_cgo_main.o") { + outObj = append(outObj, ofile) + } + } + + for _, file := range gccfiles { + ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o" + if err := b.gcc(p, ofile, cflags, file); err != nil { + return nil, nil, err + } + linkobj = append(linkobj, ofile) + outObj = append(outObj, ofile) + } + + cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS) + for _, file := range gxxfiles { + // Append .o to the file, just in case the pkg has file.c and file.cpp + ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" + if err := b.gxx(p, ofile, cxxflags, file); err != nil { + return nil, nil, err + } + linkobj = append(linkobj, ofile) + outObj = append(outObj, ofile) + } + + for _, file := range mfiles { + // Append .o to the file, just in case the pkg has file.c and file.m + ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" + if err := b.gcc(p, ofile, cflags, file); err != nil { + return nil, nil, err + } + linkobj = append(linkobj, ofile) + outObj = append(outObj, ofile) + } + + linkobj = append(linkobj, p.SysoFiles...) + dynobj := obj + "_cgo_.o" + pie := goarch == "arm" && (goos == "linux" || goos == "android") + if pie { // we need to use -pie for Linux/ARM to get accurate imported sym + cgoLDFLAGS = append(cgoLDFLAGS, "-pie") + } + if err := b.gccld(p, dynobj, cgoLDFLAGS, linkobj); err != nil { + return nil, nil, err + } + if pie { // but we don't need -pie for normal cgo programs + cgoLDFLAGS = cgoLDFLAGS[0 : len(cgoLDFLAGS)-1] + } + + if _, ok := buildToolchain.(gccgoToolchain); ok { + // we don't use dynimport when using gccgo. + return outGo, outObj, nil + } + + // cgo -dynimport + importC := obj + "_cgo_import.c" + cgoflags = []string{} + if p.Standard && p.ImportPath == "runtime/cgo" { + cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker + } + if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC, cgoflags); err != nil { + return nil, nil, err + } + + // cc _cgo_import.ARCH + importObj := obj + "_cgo_import." + objExt + if err := buildToolchain.cc(b, p, obj, importObj, importC); err != nil { + return nil, nil, err + } + + ofile := obj + "_all.o" + var gccObjs, nonGccObjs []string + for _, f := range outObj { + if strings.HasSuffix(f, ".o") { + gccObjs = append(gccObjs, f) + } else { + nonGccObjs = append(nonGccObjs, f) + } + } + ldflags := stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs) + + // Some systems, such as Ubuntu, always add --build-id to + // every link, but we don't want a build ID since we are + // producing an object file. On some of those system a plain + // -r (not -Wl,-r) will turn off --build-id, but clang 3.0 + // doesn't support a plain -r. I don't know how to turn off + // --build-id when using clang other than passing a trailing + // --build-id=none. So that is what we do, but only on + // systems likely to support it, which is to say, systems that + // normally use gold or the GNU linker. + switch goos { + case "android", "dragonfly", "linux", "netbsd": + ldflags = append(ldflags, "-Wl,--build-id=none") + } + + if err := b.gccld(p, ofile, ldflags, gccObjs); err != nil { + return nil, nil, err + } + + // NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows + // must be processed before the gcc-generated objects. + // Put it first. http://golang.org/issue/2601 + outObj = stringList(importObj, nonGccObjs, ofile) + + return outGo, outObj, nil +} + +// Run SWIG on all SWIG input files. +// TODO: Don't build a shared library, once SWIG emits the necessary +// pragmas for external linking. +func (b *builder) swig(p *Package, obj string, pcCFLAGS, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) { + cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true) + cflags := stringList(cgoCPPFLAGS, cgoCFLAGS) + cxxflags := stringList(cgoCPPFLAGS, cgoCXXFLAGS) + + for _, file := range gccfiles { + ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o" + if err := b.gcc(p, ofile, cflags, file); err != nil { + return nil, nil, err + } + outObj = append(outObj, ofile) + } + + for _, file := range gxxfiles { + // Append .o to the file, just in case the pkg has file.c and file.cpp + ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" + if err := b.gxx(p, ofile, cxxflags, file); err != nil { + return nil, nil, err + } + outObj = append(outObj, ofile) + } + + for _, file := range mfiles { + // Append .o to the file, just in case the pkg has file.c and file.cpp + ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o" + if err := b.gcc(p, ofile, cflags, file); err != nil { + return nil, nil, err + } + outObj = append(outObj, ofile) + } + + if err := b.swigVersionCheck(); err != nil { + return nil, nil, err + } + + intgosize, err := b.swigIntSize(obj) + if err != nil { + return nil, nil, err + } + + for _, f := range p.SwigFiles { + goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, pcCFLAGS, false, intgosize) + if err != nil { + return nil, nil, err + } + if goFile != "" { + outGo = append(outGo, goFile) + } + if objFile != "" { + outObj = append(outObj, objFile) + } + if gccObjFile != "" { + outObj = append(outObj, gccObjFile) + } + } + for _, f := range p.SwigCXXFiles { + goFile, objFile, gccObjFile, err := b.swigOne(p, f, obj, pcCFLAGS, true, intgosize) + if err != nil { + return nil, nil, err + } + if goFile != "" { + outGo = append(outGo, goFile) + } + if objFile != "" { + outObj = append(outObj, objFile) + } + if gccObjFile != "" { + outObj = append(outObj, gccObjFile) + } + } + return outGo, outObj, nil +} + +// Make sure SWIG is new enough. +var ( + swigCheckOnce sync.Once + swigCheck error +) + +func (b *builder) swigDoVersionCheck() error { + out, err := b.runOut("", "", nil, "swig", "-version") + if err != nil { + return err + } + re := regexp.MustCompile(`[vV]ersion +([\d])`) + matches := re.FindSubmatch(out) + if matches == nil { + // Can't find version number; hope for the best. + return nil + } + major, err := strconv.Atoi(string(matches[1])) + if err != nil { + // Can't find version number; hope for the best. + return nil + } + if major < 3 { + return errors.New("must have SWIG version >= 3.0") + } + return nil +} + +func (b *builder) swigVersionCheck() error { + swigCheckOnce.Do(func() { + swigCheck = b.swigDoVersionCheck() + }) + return swigCheck +} + +// This code fails to build if sizeof(int) <= 32 +const swigIntSizeCode = ` +package main +const i int = 1 << 32 +` + +// Determine the size of int on the target system for the -intgosize option +// of swig >= 2.0.9 +func (b *builder) swigIntSize(obj string) (intsize string, err error) { + if buildN { + return "$INTBITS", nil + } + src := filepath.Join(b.work, "swig_intsize.go") + if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0644); err != nil { + return + } + srcs := []string{src} + + p := goFilesPackage(srcs) + + if _, _, e := buildToolchain.gc(b, p, "", obj, nil, srcs); e != nil { + return "32", nil + } + return "64", nil +} + +// Run SWIG on one SWIG input file. +func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outObj, objGccObj string, err error) { + cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _ := b.cflags(p, true) + var cflags []string + if cxx { + cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS) + } else { + cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCFLAGS) + } + + n := 5 // length of ".swig" + if cxx { + n = 8 // length of ".swigcxx" + } + base := file[:len(file)-n] + goFile := base + ".go" + cBase := base + "_gc." + gccBase := base + "_wrap." + gccExt := "c" + if cxx { + gccExt = "cxx" + } + + _, gccgo := buildToolchain.(gccgoToolchain) + + // swig + args := []string{ + "-go", + "-intgosize", intgosize, + "-module", base, + "-o", obj + gccBase + gccExt, + "-outdir", obj, + } + + for _, f := range cflags { + if len(f) > 3 && f[:2] == "-I" { + args = append(args, f) + } + } + + if gccgo { + args = append(args, "-gccgo") + if pkgpath := gccgoPkgpath(p); pkgpath != "" { + args = append(args, "-go-pkgpath", pkgpath) + } + } + if cxx { + args = append(args, "-c++") + } + + if out, err := b.runOut(p.Dir, p.ImportPath, nil, "swig", args, file); err != nil { + if len(out) > 0 { + if bytes.Contains(out, []byte("Unrecognized option -intgosize")) { + return "", "", "", errors.New("must have SWIG version >= 3.0") + } + b.showOutput(p.Dir, p.ImportPath, b.processOutput(out)) + return "", "", "", errPrintedOutput + } + return "", "", "", err + } + + var cObj string + if !gccgo { + // cc + cObj = obj + cBase + archChar + if err := buildToolchain.cc(b, p, obj, cObj, obj+cBase+"c"); err != nil { + return "", "", "", err + } + } + + // gcc + gccObj := obj + gccBase + "o" + if !cxx { + if err := b.gcc(p, gccObj, cflags, obj+gccBase+gccExt); err != nil { + return "", "", "", err + } + } else { + if err := b.gxx(p, gccObj, cflags, obj+gccBase+gccExt); err != nil { + return "", "", "", err + } + } + + return obj + goFile, cObj, gccObj, nil +} + +// An actionQueue is a priority queue of actions. +type actionQueue []*action + +// Implement heap.Interface +func (q *actionQueue) Len() int { return len(*q) } +func (q *actionQueue) Swap(i, j int) { (*q)[i], (*q)[j] = (*q)[j], (*q)[i] } +func (q *actionQueue) Less(i, j int) bool { return (*q)[i].priority < (*q)[j].priority } +func (q *actionQueue) Push(x interface{}) { *q = append(*q, x.(*action)) } +func (q *actionQueue) Pop() interface{} { + n := len(*q) - 1 + x := (*q)[n] + *q = (*q)[:n] + return x +} + +func (q *actionQueue) push(a *action) { + heap.Push(q, a) +} + +func (q *actionQueue) pop() *action { + return heap.Pop(q).(*action) +} + +func raceInit() { + if !buildRace { + return + } + if goarch != "amd64" || goos != "linux" && goos != "freebsd" && goos != "darwin" && goos != "windows" { + fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0]) + os.Exit(2) + } + buildGcflags = append(buildGcflags, "-race") + buildLdflags = append(buildLdflags, "-race") + buildCcflags = append(buildCcflags, "-D", "RACE") + if buildContext.InstallSuffix != "" { + buildContext.InstallSuffix += "_" + } + buildContext.InstallSuffix += "race" + buildContext.BuildTags = append(buildContext.BuildTags, "race") +} + +// defaultSuffix returns file extension used for command files in +// current os environment. +func defaultSuffix() string { + switch runtime.GOOS { + case "windows": + return ".bat" + case "plan9": + return ".rc" + default: + return ".bash" + } +} diff --git a/libgo/go/cmd/go/clean.go b/libgo/go/cmd/go/clean.go new file mode 100644 index 0000000000..16054a5b5b --- /dev/null +++ b/libgo/go/cmd/go/clean.go @@ -0,0 +1,248 @@ +// 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 ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" +) + +var cmdClean = &Command{ + UsageLine: "clean [-i] [-r] [-n] [-x] [build flags] [packages]", + Short: "remove object files", + Long: ` +Clean removes object files from package source directories. +The go command builds most objects in a temporary directory, +so go clean is mainly concerned with object files left by other +tools or by manual invocations of go build. + +Specifically, clean removes the following files from each of the +source directories corresponding to the import paths: + + _obj/ old object directory, left from Makefiles + _test/ old test directory, left from Makefiles + _testmain.go old gotest file, left from Makefiles + test.out old test log, left from Makefiles + build.out old test log, left from Makefiles + *.[568ao] object files, left from Makefiles + + DIR(.exe) from go build + DIR.test(.exe) from go test -c + MAINFILE(.exe) from go build MAINFILE.go + *.so from SWIG + +In the list, DIR represents the final path element of the +directory, and MAINFILE is the base name of any Go source +file in the directory that is not included when building +the package. + +The -i flag causes clean to remove the corresponding installed +archive or binary (what 'go install' would create). + +The -n flag causes clean to print the remove commands it would execute, +but not run them. + +The -r flag causes clean to be applied recursively to all the +dependencies of the packages named by the import paths. + +The -x flag causes clean to print remove commands as it executes them. + +For more about build flags, see 'go help build'. + +For more about specifying packages, see 'go help packages'. + `, +} + +var cleanI bool // clean -i flag +var cleanR bool // clean -r flag + +func init() { + // break init cycle + cmdClean.Run = runClean + + cmdClean.Flag.BoolVar(&cleanI, "i", false, "") + cmdClean.Flag.BoolVar(&cleanR, "r", false, "") + // -n and -x are important enough to be + // mentioned explicitly in the docs but they + // are part of the build flags. + + addBuildFlags(cmdClean) +} + +func runClean(cmd *Command, args []string) { + for _, pkg := range packagesAndErrors(args) { + clean(pkg) + } +} + +var cleaned = map[*Package]bool{} + +// TODO: These are dregs left by Makefile-based builds. +// Eventually, can stop deleting these. +var cleanDir = map[string]bool{ + "_test": true, + "_obj": true, +} + +var cleanFile = map[string]bool{ + "_testmain.go": true, + "test.out": true, + "build.out": true, + "a.out": true, +} + +var cleanExt = map[string]bool{ + ".5": true, + ".6": true, + ".8": true, + ".a": true, + ".o": true, + ".so": true, +} + +func clean(p *Package) { + if cleaned[p] { + return + } + cleaned[p] = true + + if p.Dir == "" { + errorf("can't load package: %v", p.Error) + return + } + dirs, err := ioutil.ReadDir(p.Dir) + if err != nil { + errorf("go clean %s: %v", p.Dir, err) + return + } + + var b builder + b.print = fmt.Print + + packageFile := map[string]bool{} + if p.Name != "main" { + // Record which files are not in package main. + // The others are. + keep := func(list []string) { + for _, f := range list { + packageFile[f] = true + } + } + keep(p.GoFiles) + keep(p.CgoFiles) + keep(p.TestGoFiles) + keep(p.XTestGoFiles) + } + + _, elem := filepath.Split(p.Dir) + var allRemove []string + + // Remove dir-named executable only if this is package main. + if p.Name == "main" { + allRemove = append(allRemove, + elem, + elem+".exe", + ) + } + + // Remove package test executables. + allRemove = append(allRemove, + elem+".test", + elem+".test.exe", + ) + + // Remove a potential executable for each .go file in the directory that + // is not part of the directory's package. + for _, dir := range dirs { + name := dir.Name() + if packageFile[name] { + continue + } + if !dir.IsDir() && strings.HasSuffix(name, ".go") { + // TODO(adg,rsc): check that this .go file is actually + // in "package main", and therefore capable of building + // to an executable file. + base := name[:len(name)-len(".go")] + allRemove = append(allRemove, base, base+".exe") + } + } + + if buildN || buildX { + b.showcmd(p.Dir, "rm -f %s", strings.Join(allRemove, " ")) + } + + toRemove := map[string]bool{} + for _, name := range allRemove { + toRemove[name] = true + } + for _, dir := range dirs { + name := dir.Name() + if dir.IsDir() { + // TODO: Remove once Makefiles are forgotten. + if cleanDir[name] { + if buildN || buildX { + b.showcmd(p.Dir, "rm -r %s", name) + if buildN { + continue + } + } + if err := os.RemoveAll(filepath.Join(p.Dir, name)); err != nil { + errorf("go clean: %v", err) + } + } + continue + } + + if buildN { + continue + } + + if cleanFile[name] || cleanExt[filepath.Ext(name)] || toRemove[name] { + removeFile(filepath.Join(p.Dir, name)) + } + } + + if cleanI && p.target != "" { + if buildN || buildX { + b.showcmd("", "rm -f %s", p.target) + } + if !buildN { + removeFile(p.target) + } + } + + if cleanR { + for _, p1 := range p.imports { + clean(p1) + } + } +} + +// removeFile tries to remove file f, if error other than file doesn't exist +// occurs, it will report the error. +func removeFile(f string) { + err := os.Remove(f) + if err == nil || os.IsNotExist(err) { + return + } + // Windows does not allow deletion of a binary file while it is executing. + if toolIsWindows { + // Remove lingering ~ file from last attempt. + if _, err2 := os.Stat(f + "~"); err2 == nil { + os.Remove(f + "~") + } + // Try to move it out of the way. If the move fails, + // which is likely, we'll try again the + // next time we do an install of this binary. + if err2 := os.Rename(f, f+"~"); err2 == nil { + os.Remove(f + "~") + return + } + } + errorf("go clean: %v", err) +} diff --git a/libgo/go/cmd/go/context.go b/libgo/go/cmd/go/context.go new file mode 100644 index 0000000000..68e518259f --- /dev/null +++ b/libgo/go/cmd/go/context.go @@ -0,0 +1,36 @@ +// 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 main + +import ( + "go/build" +) + +type Context struct { + GOARCH string `json:",omitempty"` // target architecture + GOOS string `json:",omitempty"` // target operating system + GOROOT string `json:",omitempty"` // Go root + GOPATH string `json:",omitempty"` // Go path + CgoEnabled bool `json:",omitempty"` // whether cgo can be used + 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 + 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 +} + +func newContext(c *build.Context) *Context { + return &Context{ + GOARCH: c.GOARCH, + GOOS: c.GOOS, + GOROOT: c.GOROOT, + CgoEnabled: c.CgoEnabled, + UseAllFiles: c.UseAllFiles, + Compiler: c.Compiler, + BuildTags: c.BuildTags, + ReleaseTags: c.ReleaseTags, + InstallSuffix: c.InstallSuffix, + } +} diff --git a/libgo/go/cmd/go/discovery.go b/libgo/go/cmd/go/discovery.go new file mode 100644 index 0000000000..b9f4279954 --- /dev/null +++ b/libgo/go/cmd/go/discovery.go @@ -0,0 +1,83 @@ +// 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. + +// +build !cmd_go_bootstrap + +// This code is compiled into the real 'go' binary, but it is not +// compiled into the binary that is built during all.bash, so as +// to avoid needing to build net (and thus use cgo) during the +// bootstrap process. + +package main + +import ( + "encoding/xml" + "fmt" + "io" + "strings" +) + +// charsetReader returns a reader for the given charset. Currently +// it only supports UTF-8 and ASCII. Otherwise, it returns a meaningful +// error which is printed by go get, so the user can find why the package +// wasn't downloaded if the encoding is not supported. Note that, in +// order to reduce potential errors, ASCII is treated as UTF-8 (i.e. characters +// greater than 0x7f are not rejected). +func charsetReader(charset string, input io.Reader) (io.Reader, error) { + switch strings.ToLower(charset) { + case "ascii": + return input, nil + default: + return nil, fmt.Errorf("can't decode XML document using charset %q", charset) + } +} + +// parseMetaGoImports returns meta imports from the HTML in r. +// Parsing ends at the end of the section or the beginning of the . +func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) { + d := xml.NewDecoder(r) + d.CharsetReader = charsetReader + d.Strict = false + var t xml.Token + for { + t, err = d.Token() + if err != nil { + if err == io.EOF { + err = nil + } + return + } + if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") { + return + } + if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") { + return + } + e, ok := t.(xml.StartElement) + if !ok || !strings.EqualFold(e.Name.Local, "meta") { + continue + } + if attrValue(e.Attr, "name") != "go-import" { + continue + } + if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 { + imports = append(imports, metaImport{ + Prefix: f[0], + VCS: f[1], + RepoRoot: f[2], + }) + } + } +} + +// attrValue returns the attribute value for the case-insensitive key +// `name', or the empty string if nothing is found. +func attrValue(attrs []xml.Attr, name string) string { + for _, a := range attrs { + if strings.EqualFold(a.Name.Local, name) { + return a.Value + } + } + return "" +} diff --git a/libgo/go/cmd/go/doc.go b/libgo/go/cmd/go/doc.go new file mode 100644 index 0000000000..7191ee0f3a --- /dev/null +++ b/libgo/go/cmd/go/doc.go @@ -0,0 +1,1131 @@ +// 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. + +// DO NOT EDIT THIS FILE. GENERATED BY mkdoc.sh. +// Edit the documentation in other files and rerun mkdoc.sh to generate this one. + +/* +Go is a tool for managing Go source code. + +Usage: + + go command [arguments] + +The commands are: + + build compile packages and dependencies + clean remove object files + env print Go environment information + fix run go tool fix on packages + fmt run gofmt on package sources + generate generate Go files by processing source + get download and install packages and dependencies + install compile and install packages and dependencies + list list packages + run compile and run Go program + test test packages + tool run specified go tool + version print Go version + vet run go tool vet on packages + +Use "go help [command]" for more information about a command. + +Additional help topics: + + c calling between Go and C + filetype file types + gopath GOPATH environment variable + importpath import path syntax + packages description of package lists + testflag description of testing flags + testfunc description of testing functions + +Use "go help [topic]" for more information about that topic. + + +Compile packages and dependencies + +Usage: + + go build [-o output] [-i] [build flags] [packages] + +Build compiles the packages named by the import paths, +along with their dependencies, but it does not install the results. + +If the arguments are a list of .go files, build treats them as a list +of source files specifying a single package. + +When the command line specifies a single main package, +build writes the resulting executable to output. +Otherwise build compiles the packages but discards the results, +serving only as a check that the packages can be built. + +The -o flag specifies the output file name. If not specified, the +output file name depends on the arguments and derives from the name +of the package, such as p.a for package p, unless p is 'main'. If +the package is main and file names are provided, the file name +derives from the first file name mentioned, such as f1 for 'go build +f1.go f2.go'; with no files provided ('go build'), the output file +name is the base name of the containing directory. + +The -i flag installs the packages that are dependencies of the target. + +The build flags are shared by the build, clean, get, install, list, run, +and test commands: + + -a + force rebuilding of packages that are already up-to-date. + In Go releases, does not apply to the standard library. + -n + print the commands but do not run them. + -p n + the number of builds that can be run in parallel. + The default is the number of CPUs available. + -race + enable data race detection. + Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. + -v + print the names of packages as they are compiled. + -work + print the name of the temporary work directory and + do not delete it when exiting. + -x + print the commands. + + -ccflags 'arg list' + arguments to pass on each 5c, 6c, or 8c compiler invocation. + -compiler name + name of compiler to use, as in runtime.Compiler (gccgo or gc). + -gccgoflags 'arg list' + arguments to pass on each gccgo compiler/linker invocation. + -gcflags 'arg list' + arguments to pass on each 5g, 6g, or 8g compiler invocation. + -installsuffix suffix + a suffix to use in the name of the package installation directory, + in order to keep output separate from default builds. + If using the -race flag, the install suffix is automatically set to race + or, if set explicitly, has _race appended to it. + -ldflags 'flag list' + arguments to pass on each 5l, 6l, or 8l linker invocation. + -tags 'tag list' + a list of build tags to consider satisfied during the build. + For more information about build tags, see the description of + build constraints in the documentation for the go/build package. + +The list flags accept a space-separated list of strings. To embed spaces +in an element in the list, surround it with either single or double quotes. + +For more about specifying packages, see 'go help packages'. +For more about where packages and binaries are installed, +run 'go help gopath'. For more about calling between Go and C/C++, +run 'go help c'. + +See also: go install, go get, go clean. + + +Remove object files + +Usage: + + go clean [-i] [-r] [-n] [-x] [build flags] [packages] + +Clean removes object files from package source directories. +The go command builds most objects in a temporary directory, +so go clean is mainly concerned with object files left by other +tools or by manual invocations of go build. + +Specifically, clean removes the following files from each of the +source directories corresponding to the import paths: + + _obj/ old object directory, left from Makefiles + _test/ old test directory, left from Makefiles + _testmain.go old gotest file, left from Makefiles + test.out old test log, left from Makefiles + build.out old test log, left from Makefiles + *.[568ao] object files, left from Makefiles + + DIR(.exe) from go build + DIR.test(.exe) from go test -c + MAINFILE(.exe) from go build MAINFILE.go + *.so from SWIG + +In the list, DIR represents the final path element of the +directory, and MAINFILE is the base name of any Go source +file in the directory that is not included when building +the package. + +The -i flag causes clean to remove the corresponding installed +archive or binary (what 'go install' would create). + +The -n flag causes clean to print the remove commands it would execute, +but not run them. + +The -r flag causes clean to be applied recursively to all the +dependencies of the packages named by the import paths. + +The -x flag causes clean to print remove commands as it executes them. + +For more about build flags, see 'go help build'. + +For more about specifying packages, see 'go help packages'. + + +Print Go environment information + +Usage: + + go env [var ...] + +Env prints Go environment information. + +By default env prints information as a shell script +(on Windows, a batch file). If one or more variable +names is given as arguments, env prints the value of +each named variable on its own line. + + +Run go tool fix on packages + +Usage: + + go fix [packages] + +Fix runs the Go fix command on the packages named by the import paths. + +For more about fix, see 'godoc fix'. +For more about specifying packages, see 'go help packages'. + +To run fix with specific options, run 'go tool fix'. + +See also: go fmt, go vet. + + +Run gofmt on package sources + +Usage: + + go fmt [-n] [-x] [packages] + +Fmt runs the command 'gofmt -l -w' on the packages named +by the import paths. It prints the names of the files that are modified. + +For more about gofmt, see 'godoc gofmt'. +For more about specifying packages, see 'go help packages'. + +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + +To run gofmt with specific options, run gofmt itself. + +See also: go fix, go vet. + + +Generate Go files by processing source + +Usage: + + go generate [-run regexp] [file.go... | packages] + +Generate runs commands described by directives within existing +files. Those commands can run any process but the intent is to +create or update Go source files, for instance by running yacc. + +Go generate is never run automatically by go build, go get, go test, +and so on. It must be run explicitly. + +Go generate scans the file for directives, which are lines of +the form, + + //go:generate command argument... + +(note: no leading spaces and no space in "//go") where command +is the generator to be run, corresponding to an executable file +that can be run locally. It must either be in the shell path +(gofmt), a fully qualified path (/usr/you/bin/mytool), or a +command alias, described below. + +Note that go generate does not parse the file, so lines that look +like directives in comments or multiline strings will be treated +as directives. + +The arguments to the directive are space-separated tokens or +double-quoted strings passed to the generator as individual +arguments when it is run. + +Quoted strings use Go syntax and are evaluated before execution; a +quoted string appears as a single argument to the generator. + +Go generate sets several variables when it runs the generator: + + $GOARCH + The execution architecture (arm, amd64, etc.) + $GOOS + The execution operating system (linux, windows, etc.) + $GOFILE + The base name of the file. + $GOPACKAGE + The name of the package of the file containing the directive. + +Other than variable substitution and quoted-string evaluation, no +special processing such as "globbing" is performed on the command +line. + +As a last step before running the command, any invocations of any +environment variables with alphanumeric names, such as $GOFILE or +$HOME, are expanded throughout the command line. The syntax for +variable expansion is $NAME on all operating systems. Due to the +order of evaluation, variables are expanded even inside quoted +strings. If the variable NAME is not set, $NAME expands to the +empty string. + +A directive of the form, + + //go:generate -command xxx args... + +specifies, for the remainder of this source file only, that the +string xxx represents the command identified by the arguments. This +can be used to create aliases or to handle multiword generators. +For example, + + //go:generate -command yacc go tool yacc + +specifies that the command "yacc" represents the generator +"go tool yacc". + +Generate processes packages in the order given on the command line, +one at a time. If the command line lists .go files, they are treated +as a single package. Within a package, generate processes the +source files in a package in file name order, one at a time. Within +a source file, generate runs generators in the order they appear +in the file, one at a time. + +If any generator returns an error exit status, "go generate" skips +all further processing for that package. + +The generator is run in the package's source directory. + +Go generate accepts one specific flag: + + -run="" + TODO: This flag is unimplemented. + if non-empty, specifies a regular expression to + select directives whose command matches the expression. + +It also accepts the standard build flags -v, -n, and -x. +The -v flag prints the names of packages and files as they are +processed. +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + +For more about specifying packages, see 'go help packages'. + + +Download and install packages and dependencies + +Usage: + + go get [-d] [-f] [-fix] [-t] [-u] [build flags] [packages] + +Get downloads and installs the packages named by the import paths, +along with their dependencies. + +The -d flag instructs get to stop after downloading the packages; that is, +it instructs get not to install the packages. + +The -f flag, valid only when -u is set, forces get -u not to verify that +each package has been checked out from the source control repository +implied by its import path. This can be useful if the source is a local fork +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 -t flag instructs get to also download the packages required to build +the tests for the specified packages. + +The -u flag instructs get to use the network to update the named packages +and their dependencies. By default, get uses the network to check out +missing packages but does not use it to look for updates to existing packages. + +Get also accepts build flags to control the installation. See 'go help build'. + +When checking out or updating a package, get looks for a branch or tag +that matches the locally installed version of Go. The most important +rule is that if the local installation is running version "go1", get +searches for a branch or tag named "go1". If no such version exists it +retrieves the most recent version of the package. + +For more about specifying packages, see 'go help packages'. + +For more about how 'go get' finds source code to +download, see 'go help importpath'. + +See also: go build, go install, go clean. + + +Compile and install packages and dependencies + +Usage: + + go install [build flags] [packages] + +Install compiles and installs the packages named by the import paths, +along with their dependencies. + +For more about the build flags, see 'go help build'. +For more about specifying packages, see 'go help packages'. + +See also: go build, go get, go clean. + + +List packages + +Usage: + + go list [-e] [-f format] [-json] [build flags] [packages] + +List lists the packages named by the import paths, one per line. + +The default output shows the package import path: + + code.google.com/p/google-api-go-client/books/v1 + code.google.com/p/goauth2/oauth + code.google.com/p/sqlite + +The -f flag specifies an alternate format for the list, using the +syntax of package template. The default output is equivalent to -f +'{{.ImportPath}}'. The struct being passed to the template is: + + type Package struct { + Dir string // directory containing package sources + ImportPath string // import path of package in dir + ImportComment string // path in import comment on package statement + Name string // package name + Doc string // package documentation string + Target string // install path + Goroot bool // is this package in the Go root? + Standard bool // is this package part of the standard Go library? + Stale bool // would 'go install' do anything for this package? + Root string // Go root or Go path dir containing this package + + // Source files + GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) + CgoFiles []string // .go sources files that import "C" + IgnoredGoFiles []string // .go sources ignored due to build constraints + CFiles []string // .c source files + CXXFiles []string // .cc, .cxx and .cpp source files + MFiles []string // .m source files + HFiles []string // .h, .hh, .hpp and .hxx source files + SFiles []string // .s source files + SwigFiles []string // .swig files + SwigCXXFiles []string // .swigcxx files + SysoFiles []string // .syso object files to add to archive + + // Cgo directives + CgoCFLAGS []string // cgo: flags for C compiler + CgoCPPFLAGS []string // cgo: flags for C preprocessor + CgoCXXFLAGS []string // cgo: flags for C++ compiler + CgoLDFLAGS []string // cgo: flags for linker + CgoPkgConfig []string // cgo: pkg-config names + + // Dependency information + Imports []string // import paths used by this package + Deps []string // all (recursively) imported dependencies + + // Error information + Incomplete bool // this package or a dependency has an error + Error *PackageError // error loading package + DepsErrors []*PackageError // errors loading dependencies + + TestGoFiles []string // _test.go files in package + TestImports []string // imports from TestGoFiles + XTestGoFiles []string // _test.go files outside package + XTestImports []string // imports from XTestGoFiles + } + +The template function "join" calls strings.Join. + +The template function "context" returns the build context, defined as: + + type Context struct { + GOARCH string // target architecture + GOOS string // target operating system + GOROOT string // Go root + GOPATH string // Go path + CgoEnabled bool // whether cgo can be used + UseAllFiles bool // use files regardless of +build lines, file names + Compiler string // compiler to assume when computing target paths + BuildTags []string // build constraints to match in +build lines + ReleaseTags []string // releases the current release is compatible with + InstallSuffix string // suffix to use in the name of the install dir + } + +For more information about the meaning of these fields see the documentation +for the go/build package's Context type. + +The -json flag causes the package data to be printed in JSON format +instead of using the template format. + +The -e flag changes the handling of erroneous packages, those that +cannot be found or are malformed. By default, the list command +prints an error to standard error for each erroneous package and +omits the packages from consideration during the usual printing. +With the -e flag, the list command never prints errors to standard +error and instead processes the erroneous packages with the usual +printing. Erroneous packages will have a non-empty ImportPath and +a non-nil Error field; other information may or may not be missing +(zeroed). + +For more about build flags, see 'go help build'. + +For more about specifying packages, see 'go help packages'. + + +Compile and run Go program + +Usage: + + go run [build flags] [-exec xprog] gofiles... [arguments...] + +Run compiles and runs the main package comprising the named Go source files. +A Go source file is defined to be a file ending in a literal ".go" suffix. + +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...'. +If the -exec flag is not given, GOOS or GOARCH is different from the system +default, and a program named go_$GOOS_$GOARCH_exec can be found +on the current search path, 'go run' invokes the binary using that program, +for example 'go_nacl_386_exec a.out arguments...'. This allows execution of +cross-compiled programs when a simulator or other execution method is +available. + +For more about build flags, see 'go help build'. + +See also: go build. + + +Test packages + +Usage: + + go test [-c] [-i] [build and test flags] [packages] [flags for test binary] + +'Go test' automates testing the packages named by the import paths. +It prints a summary of the test results in the format: + + ok archive/tar 0.011s + FAIL archive/zip 0.022s + ok compress/gzip 0.033s + ... + +followed by detailed output for each failed package. + +'Go test' recompiles each package along with any files with names matching +the file pattern "*_test.go". +Files whose names begin with "_" (including "_test.go") or "." are ignored. +These additional files can contain test functions, benchmark functions, and +example functions. See 'go help testfunc' for more. +Each listed package causes the execution of a separate test binary. + +Test files that declare a package with the suffix "_test" will be compiled as a +separate package, and then linked and run with the main test binary. + +By default, go test needs no arguments. It compiles and tests the package +with source in the current directory, including tests, and runs the tests. + +The package is built in a temporary directory so it does not interfere with the +non-test installation. + +In addition to the build flags, the flags handled by 'go test' itself are: + + -c + Compile the test binary to pkg.test but do not run it + (where pkg is the last element of the package's import path). + The file name can be changed with the -o flag. + + -exec xprog + Run the test binary using xprog. The behavior is the same as + in 'go run'. See 'go help run' for details. + + -i + Install packages that are dependencies of the test. + Do not run the test. + + -o file + Compile the test binary to the named file. + The test still runs (unless -c or -i is specified). + + +The test binary also accepts flags that control execution of the test; these +flags are also accessible by 'go test'. See 'go help testflag' for details. + +If the test binary needs any other flags, they should be presented after the +package names. The go tool treats as a flag the first argument that begins with +a minus sign that it does not recognize itself; that argument and all subsequent +arguments are passed as arguments to the test binary. + +For more about build flags, see 'go help build'. +For more about specifying packages, see 'go help packages'. + +See also: go build, go vet. + + +Run specified go tool + +Usage: + + go tool [-n] command [args...] + +Tool runs the go tool command identified by the arguments. +With no arguments it prints the list of known tools. + +The -n flag causes tool to print the command that would be +executed but not execute it. + +For more about each tool command, see 'go tool command -h'. + + +Print Go version + +Usage: + + go version + +Version prints the Go version, as reported by runtime.Version. + + +Run go tool vet on packages + +Usage: + + go vet [-n] [-x] [packages] + +Vet runs the Go vet command on the packages named by the import paths. + +For more about vet, see 'godoc golang.org/x/tools/cmd/vet'. +For more about specifying packages, see 'go help packages'. + +To run the vet tool with specific options, run 'go tool vet'. + +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + +See also: go fmt, go fix. + + +Calling between Go and C + +There are two different ways to call between Go and C/C++ code. + +The first is the cgo tool, which is part of the Go distribution. For +information on how to use it see the cgo documentation (godoc cmd/cgo). + +The second is the SWIG program, which is a general tool for +interfacing between languages. For information on SWIG see +http://swig.org/. When running go build, any file with a .swig +extension will be passed to SWIG. Any file with a .swigcxx extension +will be passed to SWIG with the -c++ option. + +When either cgo or SWIG is used, go build will pass any .c, .m, .s, +or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++ +compiler. The CC or CXX environment variables may be set to determine +the C or C++ compiler, respectively, to use. + + +File types + +The go command examines the contents of a restricted set of files +in each directory. It identifies which files to examine based on +the extension of the file name. These extensions are: + + .go + Go source files. + .c, .h + C source files. + If the package uses cgo, these will be compiled with the + OS-native compiler (typically gcc); otherwise they will be + compiled with the Go-specific support compiler, + 5c, 6c, or 8c, etc. as appropriate. + .cc, .cpp, .cxx, .hh, .hpp, .hxx + C++ source files. Only useful with cgo or SWIG, and always + compiled with the OS-native compiler. + .m + Objective-C source files. Only useful with cgo, and always + compiled with the OS-native compiler. + .s, .S + Assembler source files. + If the package uses cgo, these will be assembled with the + OS-native assembler (typically gcc (sic)); otherwise they + will be assembled with the Go-specific support assembler, + 5a, 6a, or 8a, etc., as appropriate. + .swig, .swigcxx + SWIG definition files. + .syso + System object files. + +Files of each of these types except .syso may contain build +constraints, but the go command stops scanning for build constraints +at the first item in the file that is not a blank line or //-style +line comment. + + +GOPATH environment variable + +The Go path is used to resolve import statements. +It is implemented by and documented in the go/build package. + +The GOPATH environment variable lists places to look for Go code. +On Unix, the value is a colon-separated string. +On Windows, the value is a semicolon-separated string. +On Plan 9, the value is a list. + +GOPATH must be set to get, build and install packages outside the +standard Go tree. + +Each directory listed in GOPATH must have a prescribed structure: + +The src/ directory holds source code. The path below 'src' +determines the import path or executable name. + +The pkg/ directory holds installed package objects. +As in the Go tree, each target operating system and +architecture pair has its own subdirectory of pkg +(pkg/GOOS_GOARCH). + +If DIR is a directory listed in the GOPATH, a package with +source in DIR/src/foo/bar can be imported as "foo/bar" and +has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a". + +The bin/ directory holds compiled commands. +Each command is named for its source directory, but only +the final element, not the entire path. That is, the +command with source in DIR/src/foo/quux is installed into +DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped +so that you can add DIR/bin to your PATH to get at the +installed commands. If the GOBIN environment variable is +set, commands are installed to the directory it names instead +of DIR/bin. + +Here's an example directory layout: + + GOPATH=/home/user/gocode + + /home/user/gocode/ + src/ + foo/ + bar/ (go code in package bar) + x.go + quux/ (go code in package main) + y.go + bin/ + quux (installed command) + pkg/ + linux_amd64/ + foo/ + bar.a (installed package object) + +Go searches each directory listed in GOPATH to find source code, +but new packages are always downloaded into the first directory +in the list. + + +Import path syntax + +An import path (see 'go help packages') denotes a package +stored in the local file system. In general, an import path denotes +either a standard package (such as "unicode/utf8") or a package +found in one of the work spaces (see 'go help gopath'). + +Relative import paths + +An import path beginning with ./ or ../ is called a relative path. +The toolchain supports relative import paths as a shortcut in two ways. + +First, a relative path can be used as a shorthand on the command line. +If you are working in the directory containing the code imported as +"unicode" and want to run the tests for "unicode/utf8", you can type +"go test ./utf8" instead of needing to specify the full path. +Similarly, in the reverse situation, "go test .." will test "unicode" from +the "unicode/utf8" directory. Relative patterns are also allowed, like +"go test ./..." to test all subdirectories. See 'go help packages' for details +on the pattern syntax. + +Second, if you are compiling a Go program not in a work space, +you can use a relative path in an import statement in that program +to refer to nearby code also not in a work space. +This makes it easy to experiment with small multipackage programs +outside of the usual work spaces, but such programs cannot be +installed with "go install" (there is no work space in which to install them), +so they are rebuilt from scratch each time they are built. +To avoid ambiguity, Go programs cannot use relative import paths +within a work space. + +Remote import paths + +Certain import paths also +describe how to obtain the source code for the package using +a revision control system. + +A few common code hosting sites have special syntax: + + Bitbucket (Git, Mercurial) + + import "bitbucket.org/user/project" + import "bitbucket.org/user/project/sub/directory" + + GitHub (Git) + + import "github.com/user/project" + import "github.com/user/project/sub/directory" + + Google Code Project Hosting (Git, Mercurial, Subversion) + + import "code.google.com/p/project" + import "code.google.com/p/project/sub/directory" + + import "code.google.com/p/project.subrepository" + import "code.google.com/p/project.subrepository/sub/directory" + + Launchpad (Bazaar) + + import "launchpad.net/project" + import "launchpad.net/project/series" + import "launchpad.net/project/series/sub/directory" + + import "launchpad.net/~user/project/branch" + import "launchpad.net/~user/project/branch/sub/directory" + + IBM DevOps Services (Git) + + import "hub.jazz.net/git/user/project" + import "hub.jazz.net/git/user/project/sub/directory" + +For code hosted on other servers, import paths may either be qualified +with the version control type, or the go tool can dynamically fetch +the import path over https/http and discover where the code resides +from a tag in the HTML. + +To declare the code location, an import path of the form + + repository.vcs/path + +specifies the given repository, with or without the .vcs suffix, +using the named version control system, and then the path inside +that repository. The supported version control systems are: + + Bazaar .bzr + Git .git + Mercurial .hg + Subversion .svn + +For example, + + import "example.org/user/foo.hg" + +denotes the root directory of the Mercurial repository at +example.org/user/foo or foo.hg, and + + import "example.org/repo.git/foo/bar" + +denotes the foo/bar directory of the Git repository at +example.org/repo or repo.git. + +When a version control system supports multiple protocols, +each is tried in turn when downloading. For example, a Git +download tries git://, then https://, then http://. + +If the import path is not a known code hosting site and also lacks a +version control qualifier, the go tool attempts to fetch the import +over https/http and looks for a tag in the document's HTML +. + +The meta tag has the form: + + + +The import-prefix is the import path corresponding to the repository +root. It must be a prefix or an exact match of the package being +fetched with "go get". If it's not an exact match, another http +request is made at the prefix to verify the tags match. + +The vcs is one of "git", "hg", "svn", etc, + +The repo-root is the root of the version control system +containing a scheme and not containing a .vcs qualifier. + +For example, + + import "example.org/pkg/foo" + +will result in the following request(s): + + https://example.org/pkg/foo?go-get=1 (preferred) + http://example.org/pkg/foo?go-get=1 (fallback) + +If that page contains the meta tag + + + +the go tool will verify that https://example.org/?go-get=1 contains the +same meta tag and then git clone https://code.org/r/p/exproj into +GOPATH/src/example.org. + +New downloaded packages are written to the first directory +listed in the GOPATH environment variable (see 'go help gopath'). + +The go command attempts to download the version of the +package appropriate for the Go release being used. +Run 'go help get' for more. + +Import path checking + +When the custom import path feature described above redirects to a +known code hosting site, each of the resulting packages has two possible +import paths, using the custom domain or the known hosting site. + +A package statement is said to have an "import comment" if it is immediately +followed (before the next newline) by a comment of one of these two forms: + + package math // import "path" + package math /* import "path" * / + +The go command will refuse to install a package with an import comment +unless it is being referred to by that import path. In this way, import comments +let package authors make sure the custom import path is used and not a +direct path to the underlying code hosting site. + +See https://golang.org/s/go14customimport for details. + + +Description of package lists + +Many commands apply to a set of packages: + + go action [packages] + +Usually, [packages] is a list of import paths. + +An import path that is a rooted path or that begins with +a . or .. element is interpreted as a file system path and +denotes the package in that directory. + +Otherwise, the import path P denotes the package found in +the directory DIR/src/P for some DIR listed in the GOPATH +environment variable (see 'go help gopath'). + +If no import paths are given, the action applies to the +package in the current directory. + +There are three reserved names for paths that should not be used +for packages to be built with the go tool: + +- "main" denotes the top-level package in a stand-alone executable. + +- "all" expands to all package directories found in all the GOPATH +trees. For example, 'go list all' lists all the packages on the local +system. + +- "std" is like all but expands to just the packages in the standard +Go library. + +An import path is a pattern if it includes one or more "..." wildcards, +each of which can match any string, including the empty string and +strings containing slashes. Such a pattern expands to all package +directories found in the GOPATH trees with names matching the +patterns. As a special case, x/... matches x as well as x's subdirectories. +For example, net/... expands to net and packages in its subdirectories. + +An import path can also name a package to be downloaded from +a remote repository. Run 'go help importpath' for details. + +Every package in a program must have a unique import path. +By convention, this is arranged by starting each path with a +unique prefix that belongs to you. For example, paths used +internally at Google all begin with 'google', and paths +denoting remote repositories begin with the path to the code, +such as 'code.google.com/p/project'. + +As a special case, if the package list is a list of .go files from a +single directory, the command is applied to a single synthesized +package made up of exactly those files, ignoring any build constraints +in those files and ignoring any other files in the directory. + +Directory and file names that begin with "." or "_" are ignored +by the go tool, as are directories named "testdata". + + +Description of testing flags + +The 'go test' command takes both flags that apply to 'go test' itself +and flags that apply to the resulting test binary. + +Several of the flags control profiling and write an execution profile +suitable for "go tool pprof"; run "go tool pprof help" for more +information. The --alloc_space, --alloc_objects, and --show_bytes +options of pprof control how the information is presented. + +The following flags are recognized by the 'go test' command and +control the execution of any test: + + -bench regexp + Run benchmarks matching the regular expression. + By default, no benchmarks run. To run all benchmarks, + use '-bench .' or '-bench=.'. + + -benchmem + Print memory allocation statistics for benchmarks. + + -benchtime t + Run enough iterations of each benchmark to take t, specified + as a time.Duration (for example, -benchtime 1h30s). + The default is 1 second (1s). + + -blockprofile block.out + Write a goroutine blocking profile to the specified file + when all tests are complete. + Writes test binary as -c would. + + -blockprofilerate n + Control the detail provided in goroutine blocking profiles by + calling runtime.SetBlockProfileRate with n. + See 'godoc runtime SetBlockProfileRate'. + The profiler aims to sample, on average, one blocking event every + n nanoseconds the program spends blocked. By default, + if -test.blockprofile is set without this flag, all blocking events + are recorded, equivalent to -test.blockprofilerate=1. + + -cover + Enable coverage analysis. + + -covermode set,count,atomic + Set the mode for coverage analysis for the package[s] + being tested. The default is "set" unless -race is enabled, + in which case it is "atomic". + The values: + set: bool: does this statement run? + count: int: how many times does this statement run? + atomic: int: count, but correct in multithreaded tests; + significantly more expensive. + Sets -cover. + + -coverpkg pkg1,pkg2,pkg3 + Apply coverage analysis in each test to the given list of packages. + The default is for each test to analyze only the package being tested. + Packages are specified as import paths. + Sets -cover. + + -coverprofile cover.out + Write a coverage profile to the file after all tests have passed. + Sets -cover. + + -cpu 1,2,4 + Specify a list of GOMAXPROCS values for which the tests or + benchmarks should be executed. The default is the current value + of GOMAXPROCS. + + -cpuprofile cpu.out + Write a CPU profile to the specified file before exiting. + Writes test binary as -c would. + + -memprofile mem.out + Write a memory profile to the file after all tests have passed. + Writes test binary as -c would. + + -memprofilerate n + Enable more precise (and expensive) memory profiles by setting + runtime.MemProfileRate. See 'godoc runtime MemProfileRate'. + To profile all memory allocations, use -test.memprofilerate=1 + and pass --alloc_space flag to the pprof tool. + + -outputdir directory + Place output files from profiling in the specified directory, + by default the directory in which "go test" is running. + + -parallel n + Allow parallel execution of test functions that call t.Parallel. + The value of this flag is the maximum number of tests to run + simultaneously; by default, it is set to the value of GOMAXPROCS. + + -run regexp + Run only those tests and examples matching the regular + expression. + + -short + Tell long-running tests to shorten their run time. + It is off by default but set during all.bash so that installing + the Go tree can run a sanity check but not spend time running + exhaustive tests. + + -timeout t + If a test runs longer than t, panic. + + -v + Verbose output: log all tests as they are run. Also print all + text from Log and Logf calls even if the test succeeds. + +The test binary, called pkg.test where pkg is the name of the +directory containing the package sources, can be invoked directly +after building it with 'go test -c'. When invoking the test binary +directly, each of the standard flag names must be prefixed with 'test.', +as in -test.run=TestMyFunc or -test.v. + +When running 'go test', flags not listed above are passed through +unaltered. For instance, the command + + go test -x -v -cpuprofile=prof.out -dir=testdata -update + +will compile the test binary and then run it as + + pkg.test -test.v -test.cpuprofile=prof.out -dir=testdata -update + +The test flags that generate profiles (other than for coverage) also +leave the test binary in pkg.test for use when analyzing the profiles. + +Flags not recognized by 'go test' must be placed after any specified packages. + + +Description of testing functions + +The 'go test' command expects to find test, benchmark, and example functions +in the "*_test.go" files corresponding to the package under test. + +A test function is one named TestXXX (where XXX is any alphanumeric string +not starting with a lower case letter) and should have the signature, + + func TestXXX(t *testing.T) { ... } + +A benchmark function is one named BenchmarkXXX and should have the signature, + + func BenchmarkXXX(b *testing.B) { ... } + +An example function is similar to a test function but, instead of using +*testing.T to report success or failure, prints output to os.Stdout. +That output is compared against the function's "Output:" comment, which +must be the last comment in the function body (see example below). An +example with no such comment, or with no text after "Output:" is compiled +but not executed. + +Godoc displays the body of ExampleXXX to demonstrate the use +of the function, constant, or variable XXX. An example of a method M with +receiver type T or *T is named ExampleT_M. There may be multiple examples +for a given function, constant, or variable, distinguished by a trailing _xxx, +where xxx is a suffix not beginning with an upper case letter. + +Here is an example of an example: + + func ExamplePrintln() { + Println("The output of\nthis example.") + // Output: The output of + // this example. + } + +The entire test file is presented as the example when it contains a single +example function, at least one other function, type, variable, or constant +declaration, and no test or benchmark functions. + +See the documentation of the testing package for more information. + + +*/ +package main diff --git a/libgo/go/cmd/go/env.go b/libgo/go/cmd/go/env.go new file mode 100644 index 0000000000..26d37df4f9 --- /dev/null +++ b/libgo/go/cmd/go/env.go @@ -0,0 +1,112 @@ +// 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 ( + "fmt" + "os" + "runtime" + "strings" +) + +var cmdEnv = &Command{ + Run: runEnv, + UsageLine: "env [var ...]", + Short: "print Go environment information", + Long: ` +Env prints Go environment information. + +By default env prints information as a shell script +(on Windows, a batch file). If one or more variable +names is given as arguments, env prints the value of +each named variable on its own line. + `, +} + +type envVar struct { + name, value string +} + +func mkEnv() []envVar { + var b builder + b.init() + + env := []envVar{ + {"GOARCH", goarch}, + {"GOBIN", gobin}, + {"GOCHAR", archChar}, + {"GOEXE", exeSuffix}, + {"GOHOSTARCH", runtime.GOARCH}, + {"GOHOSTOS", runtime.GOOS}, + {"GOOS", goos}, + {"GOPATH", os.Getenv("GOPATH")}, + {"GORACE", os.Getenv("GORACE")}, + {"GOROOT", goroot}, + {"GOTOOLDIR", toolDir}, + + // disable escape codes in clang errors + {"TERM", "dumb"}, + } + + if goos != "plan9" { + cmd := b.gccCmd(".") + env = append(env, envVar{"CC", cmd[0]}) + env = append(env, envVar{"GOGCCFLAGS", strings.Join(cmd[3:], " ")}) + cmd = b.gxxCmd(".") + env = append(env, envVar{"CXX", cmd[0]}) + } + + if buildContext.CgoEnabled { + env = append(env, envVar{"CGO_ENABLED", "1"}) + } else { + env = append(env, envVar{"CGO_ENABLED", "0"}) + } + + return env +} + +func findEnv(env []envVar, name string) string { + for _, e := range env { + if e.name == name { + return e.value + } + } + return "" +} + +func runEnv(cmd *Command, args []string) { + env := mkEnv() + if len(args) > 0 { + for _, name := range args { + fmt.Printf("%s\n", findEnv(env, name)) + } + return + } + + for _, e := range env { + if e.name != "TERM" { + switch runtime.GOOS { + default: + fmt.Printf("%s=\"%s\"\n", e.name, e.value) + case "plan9": + if strings.IndexByte(e.value, '\x00') < 0 { + fmt.Printf("%s='%s'\n", e.name, strings.Replace(e.value, "'", "''", -1)) + } else { + v := strings.Split(e.value, "\x00") + fmt.Printf("%s=(", e.name) + for x, s := range v { + if x > 0 { + fmt.Printf(" ") + } + fmt.Printf("%s", s) + } + fmt.Printf(")\n") + } + case "windows": + fmt.Printf("set %s=%s\n", e.name, e.value) + } + } + } +} diff --git a/libgo/go/cmd/go/fix.go b/libgo/go/cmd/go/fix.go new file mode 100644 index 0000000000..8736cce3e2 --- /dev/null +++ b/libgo/go/cmd/go/fix.go @@ -0,0 +1,30 @@ +// 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 main + +var cmdFix = &Command{ + Run: runFix, + UsageLine: "fix [packages]", + Short: "run go tool fix on packages", + Long: ` +Fix runs the Go fix command on the packages named by the import paths. + +For more about fix, see 'godoc fix'. +For more about specifying packages, see 'go help packages'. + +To run fix with specific options, run 'go tool fix'. + +See also: go fmt, go vet. + `, +} + +func runFix(cmd *Command, args []string) { + for _, pkg := range packages(args) { + // Use pkg.gofiles instead of pkg.Dir so that + // the command only applies to this package, + // not to packages in subdirectories. + run(stringList(tool("fix"), relPaths(pkg.allgofiles))) + } +} diff --git a/libgo/go/cmd/go/fmt.go b/libgo/go/cmd/go/fmt.go new file mode 100644 index 0000000000..65dc3ca599 --- /dev/null +++ b/libgo/go/cmd/go/fmt.go @@ -0,0 +1,38 @@ +// 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 main + +func init() { + addBuildFlagsNX(cmdFmt) +} + +var cmdFmt = &Command{ + Run: runFmt, + UsageLine: "fmt [-n] [-x] [packages]", + Short: "run gofmt on package sources", + Long: ` +Fmt runs the command 'gofmt -l -w' on the packages named +by the import paths. It prints the names of the files that are modified. + +For more about gofmt, see 'godoc gofmt'. +For more about specifying packages, see 'go help packages'. + +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + +To run gofmt with specific options, run gofmt itself. + +See also: go fix, go vet. + `, +} + +func runFmt(cmd *Command, args []string) { + for _, pkg := range packages(args) { + // Use pkg.gofiles instead of pkg.Dir so that + // the command only applies to this package, + // not to packages in subdirectories. + run(stringList("gofmt", "-l", "-w", relPaths(pkg.allgofiles))) + } +} diff --git a/libgo/go/cmd/go/generate.go b/libgo/go/cmd/go/generate.go new file mode 100644 index 0000000000..3c0af8760b --- /dev/null +++ b/libgo/go/cmd/go/generate.go @@ -0,0 +1,403 @@ +// 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 main + +import ( + "bufio" + "bytes" + "fmt" + "io" + "log" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + "unicode" + "unicode/utf8" +) + +var cmdGenerate = &Command{ + Run: runGenerate, + UsageLine: "generate [-run regexp] [file.go... | packages]", + Short: "generate Go files by processing source", + Long: ` +Generate runs commands described by directives within existing +files. Those commands can run any process but the intent is to +create or update Go source files, for instance by running yacc. + +Go generate is never run automatically by go build, go get, go test, +and so on. It must be run explicitly. + +Go generate scans the file for directives, which are lines of +the form, + + //go:generate command argument... + +(note: no leading spaces and no space in "//go") where command +is the generator to be run, corresponding to an executable file +that can be run locally. It must either be in the shell path +(gofmt), a fully qualified path (/usr/you/bin/mytool), or a +command alias, described below. + +Note that go generate does not parse the file, so lines that look +like directives in comments or multiline strings will be treated +as directives. + +The arguments to the directive are space-separated tokens or +double-quoted strings passed to the generator as individual +arguments when it is run. + +Quoted strings use Go syntax and are evaluated before execution; a +quoted string appears as a single argument to the generator. + +Go generate sets several variables when it runs the generator: + + $GOARCH + The execution architecture (arm, amd64, etc.) + $GOOS + The execution operating system (linux, windows, etc.) + $GOFILE + The base name of the file. + $GOPACKAGE + The name of the package of the file containing the directive. + +Other than variable substitution and quoted-string evaluation, no +special processing such as "globbing" is performed on the command +line. + +As a last step before running the command, any invocations of any +environment variables with alphanumeric names, such as $GOFILE or +$HOME, are expanded throughout the command line. The syntax for +variable expansion is $NAME on all operating systems. Due to the +order of evaluation, variables are expanded even inside quoted +strings. If the variable NAME is not set, $NAME expands to the +empty string. + +A directive of the form, + + //go:generate -command xxx args... + +specifies, for the remainder of this source file only, that the +string xxx represents the command identified by the arguments. This +can be used to create aliases or to handle multiword generators. +For example, + + //go:generate -command yacc go tool yacc + +specifies that the command "yacc" represents the generator +"go tool yacc". + +Generate processes packages in the order given on the command line, +one at a time. If the command line lists .go files, they are treated +as a single package. Within a package, generate processes the +source files in a package in file name order, one at a time. Within +a source file, generate runs generators in the order they appear +in the file, one at a time. + +If any generator returns an error exit status, "go generate" skips +all further processing for that package. + +The generator is run in the package's source directory. + +Go generate accepts one specific flag: + + -run="" + TODO: This flag is unimplemented. + if non-empty, specifies a regular expression to + select directives whose command matches the expression. + +It also accepts the standard build flags -v, -n, and -x. +The -v flag prints the names of packages and files as they are +processed. +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + +For more about specifying packages, see 'go help packages'. + `, +} + +var generateRunFlag string // generate -run flag + +func init() { + addBuildFlags(cmdGenerate) + cmdGenerate.Flag.StringVar(&generateRunFlag, "run", "", "") +} + +func runGenerate(cmd *Command, args []string) { + // Even if the arguments are .go files, this loop suffices. + for _, pkg := range packages(args) { + for _, file := range pkg.gofiles { + if !generate(pkg.Name, file) { + break + } + } + } +} + +// generate runs the generation directives for a single file. +func generate(pkg, absFile string) bool { + fd, err := os.Open(absFile) + if err != nil { + log.Fatalf("generate: %s", err) + } + defer fd.Close() + g := &Generator{ + r: fd, + path: absFile, + pkg: pkg, + commands: make(map[string][]string), + } + return g.run() +} + +// A Generator represents the state of a single Go source file +// being scanned for generator commands. +type Generator struct { + r io.Reader + path string // full rooted path name. + dir string // full rooted directory of file. + file string // base name of file. + pkg string + commands map[string][]string + lineNum int +} + +// run runs the generators in the current file. +func (g *Generator) run() (ok bool) { + // Processing below here calls g.errorf on failure, which does panic(stop). + // If we encounter an error, we abort the package. + defer func() { + e := recover() + if e != nil { + ok = false + if e != stop { + panic(e) + } + setExitStatus(1) + } + }() + g.dir, g.file = filepath.Split(g.path) + g.dir = filepath.Clean(g.dir) // No final separator please. + if buildV { + fmt.Fprintf(os.Stderr, "%s\n", shortPath(g.path)) + } + + // Scan for lines that start "//go:generate". + // Can't use bufio.Scanner because it can't handle long lines, + // which are likely to appear when using generate. + input := bufio.NewReader(g.r) + var err error + // One line per loop. + for { + g.lineNum++ // 1-indexed. + var buf []byte + buf, err = input.ReadSlice('\n') + if err == bufio.ErrBufferFull { + // Line too long - consume and ignore. + if isGoGenerate(buf) { + g.errorf("directive too long") + } + for err == bufio.ErrBufferFull { + _, err = input.ReadSlice('\n') + } + if err != nil { + break + } + continue + } + + if err != nil { + // Check for marker at EOF without final \n. + if err == io.EOF && isGoGenerate(buf) { + err = io.ErrUnexpectedEOF + } + break + } + + if !isGoGenerate(buf) { + continue + } + + words := g.split(string(buf)) + if len(words) == 0 { + g.errorf("no arguments to directive") + } + if words[0] == "-command" { + g.setShorthand(words) + continue + } + // Run the command line. + if buildN || buildX { + fmt.Fprintf(os.Stderr, "%s\n", strings.Join(words, " ")) + } + if buildN { + continue + } + g.exec(words) + } + if err != nil && err != io.EOF { + g.errorf("error reading %s: %s", shortPath(g.path), err) + } + return true +} + +func isGoGenerate(buf []byte) bool { + return bytes.HasPrefix(buf, []byte("//go:generate ")) || bytes.HasPrefix(buf, []byte("//go:generate\t")) +} + +// split breaks the line into words, evaluating quoted +// strings and evaluating environment variables. +// The initial //go:generate element is present in line. +func (g *Generator) split(line string) []string { + // Parse line, obeying quoted strings. + var words []string + line = line[len("//go:generate ") : len(line)-1] // Drop preamble and final newline. + // There may still be a carriage return. + if len(line) > 0 && line[len(line)-1] == '\r' { + line = line[:len(line)-1] + } + // One (possibly quoted) word per iteration. +Words: + for { + line = strings.TrimLeft(line, " \t") + if len(line) == 0 { + break + } + if line[0] == '"' { + for i := 1; i < len(line); i++ { + c := line[i] // Only looking for ASCII so this is OK. + switch c { + case '\\': + if i+1 == len(line) { + g.errorf("bad backslash") + } + i++ // Absorb next byte (If it's a multibyte we'll get an error in Unquote). + case '"': + word, err := strconv.Unquote(line[0 : i+1]) + if err != nil { + g.errorf("bad quoted string") + } + words = append(words, word) + line = line[i+1:] + // Check the next character is space or end of line. + if len(line) > 0 && line[0] != ' ' && line[0] != '\t' { + g.errorf("expect space after quoted argument") + } + continue Words + } + } + g.errorf("mismatched quoted string") + } + i := strings.IndexAny(line, " \t") + if i < 0 { + i = len(line) + } + words = append(words, line[0:i]) + line = line[i:] + } + // Substitute command if required. + if len(words) > 0 && g.commands[words[0]] != nil { + // Replace 0th word by command substitution. + words = append(g.commands[words[0]], words[1:]...) + } + // Substitute environment variables. + for i, word := range words { + words[i] = g.expandEnv(word) + } + return words +} + +var stop = fmt.Errorf("error in generation") + +// errorf logs an error message prefixed with the file and line number. +// It then exits the program (with exit status 1) because generation stops +// at the first error. +func (g *Generator) errorf(format string, args ...interface{}) { + fmt.Fprintf(os.Stderr, "%s:%d: %s\n", shortPath(g.path), g.lineNum, + fmt.Sprintf(format, args...)) + panic(stop) +} + +// expandEnv expands any $XXX invocations in word. +func (g *Generator) expandEnv(word string) string { + if !strings.ContainsRune(word, '$') { + return word + } + var buf bytes.Buffer + var w int + var r rune + for i := 0; i < len(word); i += w { + r, w = utf8.DecodeRuneInString(word[i:]) + if r != '$' { + buf.WriteRune(r) + continue + } + w += g.identLength(word[i+w:]) + envVar := word[i+1 : i+w] + var sub string + switch envVar { + case "GOARCH": + sub = runtime.GOARCH + case "GOOS": + sub = runtime.GOOS + case "GOFILE": + sub = g.file + case "GOPACKAGE": + sub = g.pkg + default: + sub = os.Getenv(envVar) + } + buf.WriteString(sub) + } + return buf.String() +} + +// identLength returns the length of the identifier beginning the string. +func (g *Generator) identLength(word string) int { + for i, r := range word { + if r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) { + continue + } + return i + } + return len(word) +} + +// setShorthand installs a new shorthand as defined by a -command directive. +func (g *Generator) setShorthand(words []string) { + // Create command shorthand. + if len(words) == 1 { + g.errorf("no command specified for -command") + } + command := words[1] + if g.commands[command] != nil { + g.errorf("command %q defined multiply defined", command) + } + g.commands[command] = words[2:len(words):len(words)] // force later append to make copy +} + +// exec runs the command specified by the argument. The first word is +// the command name itself. +func (g *Generator) exec(words []string) { + cmd := exec.Command(words[0], words[1:]...) + // Standard in and out of generator should be the usual. + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + // Run the command in the package directory. + cmd.Dir = g.dir + env := []string{ + "GOARCH=" + runtime.GOARCH, + "GOOS=" + runtime.GOOS, + "GOFILE=" + g.file, + "GOPACKAGE=" + g.pkg, + } + cmd.Env = mergeEnvLists(env, os.Environ()) + err := cmd.Run() + if err != nil { + g.errorf("running %q: %s", words[0], err) + } +} diff --git a/libgo/go/cmd/go/generate_test.go b/libgo/go/cmd/go/generate_test.go new file mode 100644 index 0000000000..2ec548630a --- /dev/null +++ b/libgo/go/cmd/go/generate_test.go @@ -0,0 +1,54 @@ +// 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 main + +import ( + "reflect" + "runtime" + "testing" +) + +type splitTest struct { + in string + out []string +} + +var splitTests = []splitTest{ + {"", nil}, + {"x", []string{"x"}}, + {" a b\tc ", []string{"a", "b", "c"}}, + {` " a " `, []string{" a "}}, + {"$GOARCH", []string{runtime.GOARCH}}, + {"$GOOS", []string{runtime.GOOS}}, + {"$GOFILE", []string{"proc.go"}}, + {"$GOPACKAGE", []string{"sys"}}, + {"a $XXNOTDEFINEDXX b", []string{"a", "", "b"}}, + {"/$XXNOTDEFINED/", []string{"//"}}, + {"yacc -o $GOARCH/yacc_$GOFILE", []string{"go", "tool", "yacc", "-o", runtime.GOARCH + "/yacc_proc.go"}}, +} + +func TestGenerateCommandParse(t *testing.T) { + g := &Generator{ + r: nil, // Unused here. + path: "/usr/ken/sys/proc.go", + dir: "/usr/ken/sys", + file: "proc.go", + pkg: "sys", + commands: make(map[string][]string), + } + g.setShorthand([]string{"-command", "yacc", "go", "tool", "yacc"}) + for _, test := range splitTests { + // First with newlines. + got := g.split("//go:generate " + test.in + "\n") + if !reflect.DeepEqual(got, test.out) { + t.Errorf("split(%q): got %q expected %q", test.in, got, test.out) + } + // Then with CRLFs, thank you Windows. + got = g.split("//go:generate " + test.in + "\r\n") + if !reflect.DeepEqual(got, test.out) { + t.Errorf("split(%q): got %q expected %q", test.in, got, test.out) + } + } +} diff --git a/libgo/go/cmd/go/get.go b/libgo/go/cmd/go/get.go new file mode 100644 index 0000000000..50e0ca93bf --- /dev/null +++ b/libgo/go/cmd/go/get.go @@ -0,0 +1,460 @@ +// 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 main + +import ( + "fmt" + "go/build" + "os" + "path/filepath" + "regexp" + "runtime" + "strconv" + "strings" +) + +var cmdGet = &Command{ + UsageLine: "get [-d] [-f] [-fix] [-t] [-u] [build flags] [packages]", + Short: "download and install packages and dependencies", + Long: ` +Get downloads and installs the packages named by the import paths, +along with their dependencies. + +The -d flag instructs get to stop after downloading the packages; that is, +it instructs get not to install the packages. + +The -f flag, valid only when -u is set, forces get -u not to verify that +each package has been checked out from the source control repository +implied by its import path. This can be useful if the source is a local fork +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 -t flag instructs get to also download the packages required to build +the tests for the specified packages. + +The -u flag instructs get to use the network to update the named packages +and their dependencies. By default, get uses the network to check out +missing packages but does not use it to look for updates to existing packages. + +Get also accepts build flags to control the installation. See 'go help build'. + +When checking out or updating a package, get looks for a branch or tag +that matches the locally installed version of Go. The most important +rule is that if the local installation is running version "go1", get +searches for a branch or tag named "go1". If no such version exists it +retrieves the most recent version of the package. + +For more about specifying packages, see 'go help packages'. + +For more about how 'go get' finds source code to +download, see 'go help importpath'. + +See also: go build, go install, go clean. + `, +} + +var getD = cmdGet.Flag.Bool("d", false, "") +var getF = cmdGet.Flag.Bool("f", false, "") +var getT = cmdGet.Flag.Bool("t", false, "") +var getU = cmdGet.Flag.Bool("u", false, "") +var getFix = cmdGet.Flag.Bool("fix", false, "") + +func init() { + addBuildFlags(cmdGet) + cmdGet.Run = runGet // break init loop +} + +func runGet(cmd *Command, args []string) { + if *getF && !*getU { + fatalf("go get: cannot use -f flag without -u") + } + + // Phase 1. Download/update. + var stk importStack + for _, arg := range downloadPaths(args) { + download(arg, &stk, *getT) + } + exitIfErrors() + + // Phase 2. Rescan packages and re-evaluate args list. + + // Code we downloaded and all code that depends on it + // needs to be evicted from the package cache so that + // the information will be recomputed. Instead of keeping + // track of the reverse dependency information, evict + // everything. + for name := range packageCache { + delete(packageCache, name) + } + + args = importPaths(args) + + // Phase 3. Install. + if *getD { + // Download only. + // Check delayed until now so that importPaths + // has a chance to print errors. + return + } + + runInstall(cmd, args) +} + +// downloadPaths prepares the list of paths to pass to download. +// It expands ... patterns that can be expanded. If there is no match +// for a particular pattern, downloadPaths leaves it in the result list, +// in the hope that we can figure out the repository from the +// initial ...-free prefix. +func downloadPaths(args []string) []string { + args = importPathsNoDotExpansion(args) + var out []string + for _, a := range args { + if strings.Contains(a, "...") { + var expand []string + // Use matchPackagesInFS to avoid printing + // warnings. They will be printed by the + // eventual call to importPaths instead. + if build.IsLocalImport(a) { + expand = matchPackagesInFS(a) + } else { + expand = matchPackages(a) + } + if len(expand) > 0 { + out = append(out, expand...) + continue + } + } + out = append(out, a) + } + return out +} + +// downloadCache records the import paths we have already +// considered during the download, to avoid duplicate work when +// there is more than one dependency sequence leading to +// a particular package. +var downloadCache = map[string]bool{} + +// downloadRootCache records the version control repository +// root directories we have already considered during the download. +// For example, all the packages in the code.google.com/p/codesearch repo +// share the same root (the directory for that path), and we only need +// to run the hg commands to consider each repository once. +var downloadRootCache = map[string]bool{} + +// download runs the download half of the get command +// for the package named by the argument. +func download(arg string, stk *importStack, getTestDeps bool) { + p := loadPackage(arg, stk) + if p.Error != nil && p.Error.hard { + errorf("%s", p.Error) + return + } + + // There's nothing to do if this is a package in the standard library. + if p.Standard { + return + } + + // Only process each package once. + // (Unless we're fetching test dependencies for this package, + // in which case we want to process it again.) + if downloadCache[arg] && !getTestDeps { + return + } + downloadCache[arg] = true + + pkgs := []*Package{p} + wildcardOkay := len(*stk) == 0 + isWildcard := false + + // Download if the package is missing, or update if we're using -u. + if p.Dir == "" || *getU { + // The actual download. + stk.push(p.ImportPath) + err := downloadPackage(p) + if err != nil { + errorf("%s", &PackageError{ImportStack: stk.copy(), Err: err.Error()}) + stk.pop() + return + } + + args := []string{arg} + // If the argument has a wildcard in it, re-evaluate the wildcard. + // We delay this until after reloadPackage so that the old entry + // for p has been replaced in the package cache. + if wildcardOkay && strings.Contains(arg, "...") { + if build.IsLocalImport(arg) { + args = matchPackagesInFS(arg) + } else { + args = matchPackages(arg) + } + isWildcard = true + } + + // Clear all relevant package cache entries before + // doing any new loads. + for _, arg := range args { + p := packageCache[arg] + if p != nil { + delete(packageCache, p.Dir) + delete(packageCache, p.ImportPath) + } + } + + pkgs = pkgs[:0] + for _, arg := range args { + stk.push(arg) + p := loadPackage(arg, stk) + stk.pop() + if p.Error != nil { + errorf("%s", p.Error) + continue + } + pkgs = append(pkgs, p) + } + } + + // Process package, which might now be multiple packages + // due to wildcard expansion. + for _, p := range pkgs { + if *getFix { + run(stringList(tool("fix"), relPaths(p.allgofiles))) + + // The imports might have changed, so reload again. + p = reloadPackage(arg, stk) + if p.Error != nil { + errorf("%s", p.Error) + return + } + } + + if isWildcard { + // Report both the real package and the + // wildcard in any error message. + stk.push(p.ImportPath) + } + + // Process dependencies, now that we know what they are. + for _, dep := range p.deps { + // Don't get test dependencies recursively. + download(dep.ImportPath, stk, false) + } + if getTestDeps { + // Process test dependencies when -t is specified. + // (Don't get test dependencies for test dependencies.) + for _, path := range p.TestImports { + download(path, stk, false) + } + for _, path := range p.XTestImports { + download(path, stk, false) + } + } + + if isWildcard { + stk.pop() + } + } +} + +// downloadPackage runs the create or download command +// to make the first copy of or update a copy of the given package. +func downloadPackage(p *Package) error { + var ( + vcs *vcsCmd + repo, rootPath string + err error + ) + if p.build.SrcRoot != "" { + // Directory exists. Look for checkout along path to src. + vcs, rootPath, err = vcsForDir(p) + if err != nil { + return err + } + repo = "" // should be unused; make distinctive + + // Double-check where it came from. + if *getU && vcs.remoteRepo != nil && !*getF { + dir := filepath.Join(p.build.SrcRoot, rootPath) + if remote, err := vcs.remoteRepo(vcs, dir); err == nil { + if rr, err := repoRootForImportPath(p.ImportPath); err == nil { + repo := rr.repo + if rr.vcs.resolveRepo != nil { + resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo) + if err == nil { + repo = resolved + } + } + if remote != repo { + return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.root, repo, dir, remote) + } + } + } + } + } else { + // Analyze the import path to determine the version control system, + // repository, and the import path for the root of the repository. + rr, err := repoRootForImportPath(p.ImportPath) + if err != nil { + return err + } + vcs, repo, rootPath = rr.vcs, rr.repo, rr.root + } + + if p.build.SrcRoot == "" { + // Package not found. Put in first directory of $GOPATH. + list := filepath.SplitList(buildContext.GOPATH) + if len(list) == 0 { + return fmt.Errorf("cannot download, $GOPATH not set. For more details see: go help gopath") + } + // Guard against people setting GOPATH=$GOROOT. + if list[0] == goroot { + return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: go help gopath") + } + p.build.SrcRoot = filepath.Join(list[0], "src") + p.build.PkgRoot = filepath.Join(list[0], "pkg") + } + root := filepath.Join(p.build.SrcRoot, rootPath) + // If we've considered this repository already, don't do it again. + if downloadRootCache[root] { + return nil + } + downloadRootCache[root] = true + + if buildV { + fmt.Fprintf(os.Stderr, "%s (download)\n", rootPath) + } + + // Check that this is an appropriate place for the repo to be checked out. + // The target directory must either not exist or have a repo checked out already. + meta := filepath.Join(root, "."+vcs.cmd) + st, err := os.Stat(meta) + if err == nil && !st.IsDir() { + return fmt.Errorf("%s exists but is not a directory", meta) + } + if err != nil { + // Metadata directory does not exist. Prepare to checkout new copy. + // Some version control tools require the target directory not to exist. + // We require that too, just to avoid stepping on existing work. + if _, err := os.Stat(root); err == nil { + return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta) + } + // Some version control tools require the parent of the target to exist. + parent, _ := filepath.Split(root) + if err = os.MkdirAll(parent, 0777); err != nil { + return err + } + if err = vcs.create(root, repo); err != nil { + return err + } + } else { + // Metadata directory does exist; download incremental updates. + if err = vcs.download(root); err != nil { + return err + } + } + + if buildN { + // Do not show tag sync in -n; it's noise more than anything, + // and since we're not running commands, no tag will be found. + // But avoid printing nothing. + fmt.Fprintf(os.Stderr, "# cd %s; %s sync/update\n", root, vcs.cmd) + return nil + } + + // Select and sync to appropriate version of the repository. + tags, err := vcs.tags(root) + if err != nil { + return err + } + vers := runtime.Version() + if i := strings.Index(vers, " "); i >= 0 { + vers = vers[:i] + } + if err := vcs.tagSync(root, selectTag(vers, tags)); err != nil { + return err + } + + return nil +} + +// goTag matches go release tags such as go1 and go1.2.3. +// The numbers involved must be small (at most 4 digits), +// have no unnecessary leading zeros, and the version cannot +// end in .0 - it is go1, not go1.0 or go1.0.0. +var goTag = regexp.MustCompile( + `^go((0|[1-9][0-9]{0,3})\.)*([1-9][0-9]{0,3})$`, +) + +// selectTag returns the closest matching tag for a given version. +// Closest means the latest one that is not after the current release. +// Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form. +// Version "release.rN" matches tags of the form "go.rN" (N being a floating-point number). +// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD". +// +// NOTE(rsc): Eventually we will need to decide on some logic here. +// For now, there is only "go1". This matches the docs in go help get. +func selectTag(goVersion string, tags []string) (match string) { + for _, t := range tags { + if t == "go1" { + return "go1" + } + } + return "" + + /* + if goTag.MatchString(goVersion) { + v := goVersion + for _, t := range tags { + if !goTag.MatchString(t) { + continue + } + if cmpGoVersion(match, t) < 0 && cmpGoVersion(t, v) <= 0 { + match = t + } + } + } + + return match + */ +} + +// cmpGoVersion returns -1, 0, +1 reporting whether +// x < y, x == y, or x > y. +func cmpGoVersion(x, y string) int { + // Malformed strings compare less than well-formed strings. + if !goTag.MatchString(x) { + return -1 + } + if !goTag.MatchString(y) { + return +1 + } + + // Compare numbers in sequence. + xx := strings.Split(x[len("go"):], ".") + yy := strings.Split(y[len("go"):], ".") + + for i := 0; i < len(xx) && i < len(yy); i++ { + // The Atoi are guaranteed to succeed + // because the versions match goTag. + xi, _ := strconv.Atoi(xx[i]) + yi, _ := strconv.Atoi(yy[i]) + if xi < yi { + return -1 + } else if xi > yi { + return +1 + } + } + + if len(xx) < len(yy) { + return -1 + } + if len(xx) > len(yy) { + return +1 + } + return 0 +} diff --git a/libgo/go/cmd/go/go11.go b/libgo/go/cmd/go/go11.go new file mode 100644 index 0000000000..8a434dfed1 --- /dev/null +++ b/libgo/go/cmd/go/go11.go @@ -0,0 +1,10 @@ +// 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. + +// +build go1.1 + +package main + +// Test that go1.1 tag above is included in builds. main.go refers to this definition. +const go11tag = true diff --git a/libgo/go/cmd/go/go_windows_test.go b/libgo/go/cmd/go/go_windows_test.go new file mode 100644 index 0000000000..53d695cccc --- /dev/null +++ b/libgo/go/cmd/go/go_windows_test.go @@ -0,0 +1,55 @@ +// 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 main + +import ( + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +func TestAbsolutePath(t *testing.T) { + tmp, err := ioutil.TempDir("", "TestAbsolutePath") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmp) + + file := filepath.Join(tmp, "a.go") + err = ioutil.WriteFile(file, []byte{}, 0644) + if err != nil { + t.Fatal(err) + } + dir := filepath.Join(tmp, "dir") + err = os.Mkdir(dir, 0777) + if err != nil { + t.Fatal(err) + } + + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + defer os.Chdir(wd) + + // Chdir so current directory and a.go reside on the same drive. + err = os.Chdir(dir) + if err != nil { + t.Fatal(err) + } + + noVolume := file[len(filepath.VolumeName(file)):] + wrongPath := filepath.Join(dir, noVolume) + output, err := exec.Command("go", "build", noVolume).CombinedOutput() + if err == nil { + t.Fatal("build should fail") + } + if strings.Contains(string(output), wrongPath) { + t.Fatalf("wrong output found: %v %v", err, string(output)) + } +} diff --git a/libgo/go/cmd/go/help.go b/libgo/go/cmd/go/help.go new file mode 100644 index 0000000000..c590fdb37f --- /dev/null +++ b/libgo/go/cmd/go/help.go @@ -0,0 +1,362 @@ +// 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 main + +var helpC = &Command{ + UsageLine: "c", + Short: "calling between Go and C", + Long: ` +There are two different ways to call between Go and C/C++ code. + +The first is the cgo tool, which is part of the Go distribution. For +information on how to use it see the cgo documentation (godoc cmd/cgo). + +The second is the SWIG program, which is a general tool for +interfacing between languages. For information on SWIG see +http://swig.org/. When running go build, any file with a .swig +extension will be passed to SWIG. Any file with a .swigcxx extension +will be passed to SWIG with the -c++ option. + +When either cgo or SWIG is used, go build will pass any .c, .m, .s, +or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++ +compiler. The CC or CXX environment variables may be set to determine +the C or C++ compiler, respectively, to use. + `, +} + +var helpPackages = &Command{ + UsageLine: "packages", + Short: "description of package lists", + Long: ` +Many commands apply to a set of packages: + + go action [packages] + +Usually, [packages] is a list of import paths. + +An import path that is a rooted path or that begins with +a . or .. element is interpreted as a file system path and +denotes the package in that directory. + +Otherwise, the import path P denotes the package found in +the directory DIR/src/P for some DIR listed in the GOPATH +environment variable (see 'go help gopath'). + +If no import paths are given, the action applies to the +package in the current directory. + +There are three reserved names for paths that should not be used +for packages to be built with the go tool: + +- "main" denotes the top-level package in a stand-alone executable. + +- "all" expands to all package directories found in all the GOPATH +trees. For example, 'go list all' lists all the packages on the local +system. + +- "std" is like all but expands to just the packages in the standard +Go library. + +An import path is a pattern if it includes one or more "..." wildcards, +each of which can match any string, including the empty string and +strings containing slashes. Such a pattern expands to all package +directories found in the GOPATH trees with names matching the +patterns. As a special case, x/... matches x as well as x's subdirectories. +For example, net/... expands to net and packages in its subdirectories. + +An import path can also name a package to be downloaded from +a remote repository. Run 'go help importpath' for details. + +Every package in a program must have a unique import path. +By convention, this is arranged by starting each path with a +unique prefix that belongs to you. For example, paths used +internally at Google all begin with 'google', and paths +denoting remote repositories begin with the path to the code, +such as 'code.google.com/p/project'. + +As a special case, if the package list is a list of .go files from a +single directory, the command is applied to a single synthesized +package made up of exactly those files, ignoring any build constraints +in those files and ignoring any other files in the directory. + +Directory and file names that begin with "." or "_" are ignored +by the go tool, as are directories named "testdata". + `, +} + +var helpImportPath = &Command{ + UsageLine: "importpath", + Short: "import path syntax", + Long: ` + +An import path (see 'go help packages') denotes a package +stored in the local file system. In general, an import path denotes +either a standard package (such as "unicode/utf8") or a package +found in one of the work spaces (see 'go help gopath'). + +Relative import paths + +An import path beginning with ./ or ../ is called a relative path. +The toolchain supports relative import paths as a shortcut in two ways. + +First, a relative path can be used as a shorthand on the command line. +If you are working in the directory containing the code imported as +"unicode" and want to run the tests for "unicode/utf8", you can type +"go test ./utf8" instead of needing to specify the full path. +Similarly, in the reverse situation, "go test .." will test "unicode" from +the "unicode/utf8" directory. Relative patterns are also allowed, like +"go test ./..." to test all subdirectories. See 'go help packages' for details +on the pattern syntax. + +Second, if you are compiling a Go program not in a work space, +you can use a relative path in an import statement in that program +to refer to nearby code also not in a work space. +This makes it easy to experiment with small multipackage programs +outside of the usual work spaces, but such programs cannot be +installed with "go install" (there is no work space in which to install them), +so they are rebuilt from scratch each time they are built. +To avoid ambiguity, Go programs cannot use relative import paths +within a work space. + +Remote import paths + +Certain import paths also +describe how to obtain the source code for the package using +a revision control system. + +A few common code hosting sites have special syntax: + + Bitbucket (Git, Mercurial) + + import "bitbucket.org/user/project" + import "bitbucket.org/user/project/sub/directory" + + GitHub (Git) + + import "github.com/user/project" + import "github.com/user/project/sub/directory" + + Google Code Project Hosting (Git, Mercurial, Subversion) + + import "code.google.com/p/project" + import "code.google.com/p/project/sub/directory" + + import "code.google.com/p/project.subrepository" + import "code.google.com/p/project.subrepository/sub/directory" + + Launchpad (Bazaar) + + import "launchpad.net/project" + import "launchpad.net/project/series" + import "launchpad.net/project/series/sub/directory" + + import "launchpad.net/~user/project/branch" + import "launchpad.net/~user/project/branch/sub/directory" + + IBM DevOps Services (Git) + + import "hub.jazz.net/git/user/project" + import "hub.jazz.net/git/user/project/sub/directory" + +For code hosted on other servers, import paths may either be qualified +with the version control type, or the go tool can dynamically fetch +the import path over https/http and discover where the code resides +from a tag in the HTML. + +To declare the code location, an import path of the form + + repository.vcs/path + +specifies the given repository, with or without the .vcs suffix, +using the named version control system, and then the path inside +that repository. The supported version control systems are: + + Bazaar .bzr + Git .git + Mercurial .hg + Subversion .svn + +For example, + + import "example.org/user/foo.hg" + +denotes the root directory of the Mercurial repository at +example.org/user/foo or foo.hg, and + + import "example.org/repo.git/foo/bar" + +denotes the foo/bar directory of the Git repository at +example.org/repo or repo.git. + +When a version control system supports multiple protocols, +each is tried in turn when downloading. For example, a Git +download tries git://, then https://, then http://. + +If the import path is not a known code hosting site and also lacks a +version control qualifier, the go tool attempts to fetch the import +over https/http and looks for a tag in the document's HTML +. + +The meta tag has the form: + + + +The import-prefix is the import path corresponding to the repository +root. It must be a prefix or an exact match of the package being +fetched with "go get". If it's not an exact match, another http +request is made at the prefix to verify the tags match. + +The vcs is one of "git", "hg", "svn", etc, + +The repo-root is the root of the version control system +containing a scheme and not containing a .vcs qualifier. + +For example, + + import "example.org/pkg/foo" + +will result in the following request(s): + + https://example.org/pkg/foo?go-get=1 (preferred) + http://example.org/pkg/foo?go-get=1 (fallback) + +If that page contains the meta tag + + + +the go tool will verify that https://example.org/?go-get=1 contains the +same meta tag and then git clone https://code.org/r/p/exproj into +GOPATH/src/example.org. + +New downloaded packages are written to the first directory +listed in the GOPATH environment variable (see 'go help gopath'). + +The go command attempts to download the version of the +package appropriate for the Go release being used. +Run 'go help get' for more. + +Import path checking + +When the custom import path feature described above redirects to a +known code hosting site, each of the resulting packages has two possible +import paths, using the custom domain or the known hosting site. + +A package statement is said to have an "import comment" if it is immediately +followed (before the next newline) by a comment of one of these two forms: + + package math // import "path" + package math /* import "path" */ + +The go command will refuse to install a package with an import comment +unless it is being referred to by that import path. In this way, import comments +let package authors make sure the custom import path is used and not a +direct path to the underlying code hosting site. + +See https://golang.org/s/go14customimport for details. + `, +} + +var helpGopath = &Command{ + UsageLine: "gopath", + Short: "GOPATH environment variable", + Long: ` +The Go path is used to resolve import statements. +It is implemented by and documented in the go/build package. + +The GOPATH environment variable lists places to look for Go code. +On Unix, the value is a colon-separated string. +On Windows, the value is a semicolon-separated string. +On Plan 9, the value is a list. + +GOPATH must be set to get, build and install packages outside the +standard Go tree. + +Each directory listed in GOPATH must have a prescribed structure: + +The src/ directory holds source code. The path below 'src' +determines the import path or executable name. + +The pkg/ directory holds installed package objects. +As in the Go tree, each target operating system and +architecture pair has its own subdirectory of pkg +(pkg/GOOS_GOARCH). + +If DIR is a directory listed in the GOPATH, a package with +source in DIR/src/foo/bar can be imported as "foo/bar" and +has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a". + +The bin/ directory holds compiled commands. +Each command is named for its source directory, but only +the final element, not the entire path. That is, the +command with source in DIR/src/foo/quux is installed into +DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped +so that you can add DIR/bin to your PATH to get at the +installed commands. If the GOBIN environment variable is +set, commands are installed to the directory it names instead +of DIR/bin. + +Here's an example directory layout: + + GOPATH=/home/user/gocode + + /home/user/gocode/ + src/ + foo/ + bar/ (go code in package bar) + x.go + quux/ (go code in package main) + y.go + bin/ + quux (installed command) + pkg/ + linux_amd64/ + foo/ + bar.a (installed package object) + +Go searches each directory listed in GOPATH to find source code, +but new packages are always downloaded into the first directory +in the list. + `, +} + +var helpFileType = &Command{ + UsageLine: "filetype", + Short: "file types", + Long: ` +The go command examines the contents of a restricted set of files +in each directory. It identifies which files to examine based on +the extension of the file name. These extensions are: + + .go + Go source files. + .c, .h + C source files. + If the package uses cgo, these will be compiled with the + OS-native compiler (typically gcc); otherwise they will be + compiled with the Go-specific support compiler, + 5c, 6c, or 8c, etc. as appropriate. + .cc, .cpp, .cxx, .hh, .hpp, .hxx + C++ source files. Only useful with cgo or SWIG, and always + compiled with the OS-native compiler. + .m + Objective-C source files. Only useful with cgo, and always + compiled with the OS-native compiler. + .s, .S + Assembler source files. + If the package uses cgo, these will be assembled with the + OS-native assembler (typically gcc (sic)); otherwise they + will be assembled with the Go-specific support assembler, + 5a, 6a, or 8a, etc., as appropriate. + .swig, .swigcxx + SWIG definition files. + .syso + System object files. + +Files of each of these types except .syso may contain build +constraints, but the go command stops scanning for build constraints +at the first item in the file that is not a blank line or //-style +line comment. + `, +} diff --git a/libgo/go/cmd/go/http.go b/libgo/go/cmd/go/http.go new file mode 100644 index 0000000000..107b820f28 --- /dev/null +++ b/libgo/go/cmd/go/http.go @@ -0,0 +1,87 @@ +// 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. + +// +build !cmd_go_bootstrap + +// This code is compiled into the real 'go' binary, but it is not +// compiled into the binary that is built during all.bash, so as +// to avoid needing to build net (and thus use cgo) during the +// bootstrap process. + +package main + +import ( + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "net/url" +) + +// httpClient is the default HTTP client, but a variable so it can be +// changed by tests, without modifying http.DefaultClient. +var httpClient = http.DefaultClient + +// httpGET returns the data from an HTTP GET request for the given URL. +func httpGET(url string) ([]byte, error) { + resp, err := httpClient.Get(url) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + return nil, fmt.Errorf("%s: %s", url, resp.Status) + } + b, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("%s: %v", url, err) + } + return b, nil +} + +// httpsOrHTTP returns the body of either the importPath's +// https resource or, if unavailable, the http resource. +func httpsOrHTTP(importPath string) (urlStr string, body io.ReadCloser, err error) { + fetch := func(scheme string) (urlStr string, res *http.Response, err error) { + u, err := url.Parse(scheme + "://" + importPath) + if err != nil { + return "", nil, err + } + u.RawQuery = "go-get=1" + urlStr = u.String() + if buildV { + log.Printf("Fetching %s", urlStr) + } + res, err = httpClient.Get(urlStr) + return + } + closeBody := func(res *http.Response) { + if res != nil { + res.Body.Close() + } + } + urlStr, res, err := fetch("https") + if err != nil || res.StatusCode != 200 { + if buildV { + if err != nil { + log.Printf("https fetch failed.") + } else { + log.Printf("ignoring https fetch with status code %d", res.StatusCode) + } + } + closeBody(res) + urlStr, res, err = fetch("http") + } + if err != nil { + closeBody(res) + return "", nil, err + } + // Note: accepting a non-200 OK here, so people can serve a + // meta import in their http 404 page. + if buildV { + log.Printf("Parsing meta tags from %s (status code %d)", urlStr, res.StatusCode) + } + return urlStr, res.Body, nil +} diff --git a/libgo/go/cmd/go/list.go b/libgo/go/cmd/go/list.go new file mode 100644 index 0000000000..fbf96167fe --- /dev/null +++ b/libgo/go/cmd/go/list.go @@ -0,0 +1,209 @@ +// 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 main + +import ( + "bufio" + "encoding/json" + "io" + "os" + "strings" + "text/template" +) + +var cmdList = &Command{ + UsageLine: "list [-e] [-f format] [-json] [build flags] [packages]", + Short: "list packages", + Long: ` +List lists the packages named by the import paths, one per line. + +The default output shows the package import path: + + code.google.com/p/google-api-go-client/books/v1 + code.google.com/p/goauth2/oauth + code.google.com/p/sqlite + +The -f flag specifies an alternate format for the list, using the +syntax of package template. The default output is equivalent to -f +'{{.ImportPath}}'. The struct being passed to the template is: + + type Package struct { + Dir string // directory containing package sources + ImportPath string // import path of package in dir + ImportComment string // path in import comment on package statement + Name string // package name + Doc string // package documentation string + Target string // install path + Goroot bool // is this package in the Go root? + Standard bool // is this package part of the standard Go library? + Stale bool // would 'go install' do anything for this package? + Root string // Go root or Go path dir containing this package + + // Source files + GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) + CgoFiles []string // .go sources files that import "C" + IgnoredGoFiles []string // .go sources ignored due to build constraints + CFiles []string // .c source files + CXXFiles []string // .cc, .cxx and .cpp source files + MFiles []string // .m source files + HFiles []string // .h, .hh, .hpp and .hxx source files + SFiles []string // .s source files + SwigFiles []string // .swig files + SwigCXXFiles []string // .swigcxx files + SysoFiles []string // .syso object files to add to archive + + // Cgo directives + CgoCFLAGS []string // cgo: flags for C compiler + CgoCPPFLAGS []string // cgo: flags for C preprocessor + CgoCXXFLAGS []string // cgo: flags for C++ compiler + CgoLDFLAGS []string // cgo: flags for linker + CgoPkgConfig []string // cgo: pkg-config names + + // Dependency information + Imports []string // import paths used by this package + Deps []string // all (recursively) imported dependencies + + // Error information + Incomplete bool // this package or a dependency has an error + Error *PackageError // error loading package + DepsErrors []*PackageError // errors loading dependencies + + TestGoFiles []string // _test.go files in package + TestImports []string // imports from TestGoFiles + XTestGoFiles []string // _test.go files outside package + XTestImports []string // imports from XTestGoFiles + } + +The template function "join" calls strings.Join. + +The template function "context" returns the build context, defined as: + + type Context struct { + GOARCH string // target architecture + GOOS string // target operating system + GOROOT string // Go root + GOPATH string // Go path + CgoEnabled bool // whether cgo can be used + UseAllFiles bool // use files regardless of +build lines, file names + Compiler string // compiler to assume when computing target paths + BuildTags []string // build constraints to match in +build lines + ReleaseTags []string // releases the current release is compatible with + InstallSuffix string // suffix to use in the name of the install dir + } + +For more information about the meaning of these fields see the documentation +for the go/build package's Context type. + +The -json flag causes the package data to be printed in JSON format +instead of using the template format. + +The -e flag changes the handling of erroneous packages, those that +cannot be found or are malformed. By default, the list command +prints an error to standard error for each erroneous package and +omits the packages from consideration during the usual printing. +With the -e flag, the list command never prints errors to standard +error and instead processes the erroneous packages with the usual +printing. Erroneous packages will have a non-empty ImportPath and +a non-nil Error field; other information may or may not be missing +(zeroed). + +For more about build flags, see 'go help build'. + +For more about specifying packages, see 'go help packages'. + `, +} + +func init() { + cmdList.Run = runList // break init cycle + addBuildFlags(cmdList) +} + +var listE = cmdList.Flag.Bool("e", false, "") +var listFmt = cmdList.Flag.String("f", "{{.ImportPath}}", "") +var listJson = cmdList.Flag.Bool("json", false, "") +var nl = []byte{'\n'} + +func runList(cmd *Command, args []string) { + out := newTrackingWriter(os.Stdout) + defer out.w.Flush() + + var do func(*Package) + if *listJson { + do = func(p *Package) { + b, err := json.MarshalIndent(p, "", "\t") + if err != nil { + out.Flush() + fatalf("%s", err) + } + out.Write(b) + out.Write(nl) + } + } else { + var cachedCtxt *Context + context := func() *Context { + if cachedCtxt == nil { + cachedCtxt = newContext(&buildContext) + } + return cachedCtxt + } + fm := template.FuncMap{ + "join": strings.Join, + "context": context, + } + tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt) + if err != nil { + fatalf("%s", err) + } + do = func(p *Package) { + if err := tmpl.Execute(out, p); err != nil { + out.Flush() + fatalf("%s", err) + } + if out.NeedNL() { + out.Write(nl) + } + } + } + + load := packages + if *listE { + load = packagesAndErrors + } + + for _, pkg := range load(args) { + do(pkg) + } +} + +// TrackingWriter tracks the last byte written on every write so +// we can avoid printing a newline if one was already written or +// if there is no output at all. +type TrackingWriter struct { + w *bufio.Writer + last byte +} + +func newTrackingWriter(w io.Writer) *TrackingWriter { + return &TrackingWriter{ + w: bufio.NewWriter(w), + last: '\n', + } +} + +func (t *TrackingWriter) Write(p []byte) (n int, err error) { + n, err = t.w.Write(p) + if n > 0 { + t.last = p[n-1] + } + return +} + +func (t *TrackingWriter) Flush() { + t.w.Flush() +} + +func (t *TrackingWriter) NeedNL() bool { + return t.last != '\n' +} diff --git a/libgo/go/cmd/go/main.go b/libgo/go/cmd/go/main.go new file mode 100644 index 0000000000..9691f39c76 --- /dev/null +++ b/libgo/go/cmd/go/main.go @@ -0,0 +1,723 @@ +// 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 main + +import ( + "bytes" + "flag" + "fmt" + "go/build" + "io" + "log" + "os" + "os/exec" + "path" + "path/filepath" + "regexp" + "runtime" + "strings" + "sync" + "text/template" + "unicode" + "unicode/utf8" +) + +// A Command is an implementation of a go command +// like go build or go fix. +type Command struct { + // Run runs the command. + // The args are the arguments after the command name. + Run func(cmd *Command, args []string) + + // UsageLine is the one-line usage message. + // The first word in the line is taken to be the command name. + UsageLine string + + // Short is the short description shown in the 'go help' output. + Short string + + // Long is the long message shown in the 'go help ' output. + Long string + + // Flag is a set of flags specific to this command. + Flag flag.FlagSet + + // CustomFlags indicates that the command will do its own + // flag parsing. + CustomFlags bool +} + +// Name returns the command's name: the first word in the usage line. +func (c *Command) Name() string { + name := c.UsageLine + i := strings.Index(name, " ") + if i >= 0 { + name = name[:i] + } + return name +} + +func (c *Command) Usage() { + fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine) + fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long)) + os.Exit(2) +} + +// Runnable reports whether the command can be run; otherwise +// it is a documentation pseudo-command such as importpath. +func (c *Command) Runnable() bool { + return c.Run != nil +} + +// Commands lists the available commands and help topics. +// The order here is the order in which they are printed by 'go help'. +var commands = []*Command{ + cmdBuild, + cmdClean, + cmdEnv, + cmdFix, + cmdFmt, + cmdGenerate, + cmdGet, + cmdInstall, + cmdList, + cmdRun, + cmdTest, + cmdTool, + cmdVersion, + cmdVet, + + helpC, + helpFileType, + helpGopath, + helpImportPath, + helpPackages, + helpTestflag, + helpTestfunc, +} + +var exitStatus = 0 +var exitMu sync.Mutex + +func setExitStatus(n int) { + exitMu.Lock() + if exitStatus < n { + exitStatus = n + } + exitMu.Unlock() +} + +func main() { + _ = go11tag + flag.Usage = usage + flag.Parse() + log.SetFlags(0) + + args := flag.Args() + if len(args) < 1 { + usage() + } + + if args[0] == "help" { + help(args[1:]) + return + } + + // Diagnose common mistake: GOPATH==GOROOT. + // This setting is equivalent to not setting GOPATH at all, + // which is not what most people want when they do it. + if gopath := os.Getenv("GOPATH"); gopath == runtime.GOROOT() { + fmt.Fprintf(os.Stderr, "warning: GOPATH set to GOROOT (%s) has no effect\n", gopath) + } else { + for _, p := range filepath.SplitList(gopath) { + // Note: using HasPrefix instead of Contains because a ~ can appear + // in the middle of directory elements, such as /tmp/git-1.8.2~rc3 + // or C:\PROGRA~1. Only ~ as a path prefix has meaning to the shell. + if strings.HasPrefix(p, "~") { + fmt.Fprintf(os.Stderr, "go: GOPATH entry cannot start with shell metacharacter '~': %q\n", p) + os.Exit(2) + } + if build.IsLocalImport(p) { + fmt.Fprintf(os.Stderr, "go: GOPATH entry is relative; must be absolute path: %q.\nRun 'go help gopath' for usage.\n", p) + os.Exit(2) + } + } + } + + if fi, err := os.Stat(goroot); err != nil || !fi.IsDir() { + fmt.Fprintf(os.Stderr, "go: cannot find GOROOT directory: %v\n", goroot) + os.Exit(2) + } + + for _, cmd := range commands { + if cmd.Name() == args[0] && cmd.Run != nil { + cmd.Flag.Usage = func() { cmd.Usage() } + if cmd.CustomFlags { + args = args[1:] + } else { + cmd.Flag.Parse(args[1:]) + args = cmd.Flag.Args() + } + cmd.Run(cmd, args) + exit() + return + } + } + + fmt.Fprintf(os.Stderr, "go: unknown subcommand %q\nRun 'go help' for usage.\n", args[0]) + setExitStatus(2) + exit() +} + +var usageTemplate = `Go is a tool for managing Go source code. + +Usage: + + go command [arguments] + +The commands are: +{{range .}}{{if .Runnable}} + {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}} + +Use "go help [command]" for more information about a command. + +Additional help topics: +{{range .}}{{if not .Runnable}} + {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}} + +Use "go help [topic]" for more information about that topic. + +` + +var helpTemplate = `{{if .Runnable}}usage: go {{.UsageLine}} + +{{end}}{{.Long | trim}} +` + +var documentationTemplate = `// 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. + +// DO NOT EDIT THIS FILE. GENERATED BY mkdoc.sh. +// Edit the documentation in other files and rerun mkdoc.sh to generate this one. + +/* +{{range .}}{{if .Short}}{{.Short | capitalize}} + +{{end}}{{if .Runnable}}Usage: + + go {{.UsageLine}} + +{{end}}{{.Long | trim}} + + +{{end}}*/ +package main +` + +// tmpl executes the given template text on data, writing the result to w. +func tmpl(w io.Writer, text string, data interface{}) { + t := template.New("top") + t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize}) + template.Must(t.Parse(text)) + if err := t.Execute(w, data); err != nil { + panic(err) + } +} + +func capitalize(s string) string { + if s == "" { + return s + } + r, n := utf8.DecodeRuneInString(s) + return string(unicode.ToTitle(r)) + s[n:] +} + +func printUsage(w io.Writer) { + tmpl(w, usageTemplate, commands) +} + +func usage() { + // special case "go test -h" + if len(os.Args) > 1 && os.Args[1] == "test" { + help([]string{"testflag"}) + os.Exit(2) + } + printUsage(os.Stderr) + os.Exit(2) +} + +// help implements the 'help' command. +func help(args []string) { + if len(args) == 0 { + printUsage(os.Stdout) + // not exit 2: succeeded at 'go help'. + return + } + if len(args) != 1 { + fmt.Fprintf(os.Stderr, "usage: go help command\n\nToo many arguments given.\n") + os.Exit(2) // failed at 'go help' + } + + arg := args[0] + + // 'go help documentation' generates doc.go. + if arg == "documentation" { + buf := new(bytes.Buffer) + printUsage(buf) + usage := &Command{Long: buf.String()} + tmpl(os.Stdout, documentationTemplate, append([]*Command{usage}, commands...)) + return + } + + for _, cmd := range commands { + if cmd.Name() == arg { + tmpl(os.Stdout, helpTemplate, cmd) + // not exit 2: succeeded at 'go help cmd'. + return + } + } + + fmt.Fprintf(os.Stderr, "Unknown help topic %#q. Run 'go help'.\n", arg) + os.Exit(2) // failed at 'go help cmd' +} + +// importPathsNoDotExpansion returns the import paths to use for the given +// command line, but it does no ... expansion. +func importPathsNoDotExpansion(args []string) []string { + if len(args) == 0 { + return []string{"."} + } + var out []string + for _, a := range args { + // Arguments are supposed to be import paths, but + // as a courtesy to Windows developers, rewrite \ to / + // in command-line arguments. Handles .\... and so on. + if filepath.Separator == '\\' { + a = strings.Replace(a, `\`, `/`, -1) + } + + // Put argument in canonical form, but preserve leading ./. + if strings.HasPrefix(a, "./") { + a = "./" + path.Clean(a) + if a == "./." { + a = "." + } + } else { + a = path.Clean(a) + } + if a == "all" || a == "std" { + out = append(out, allPackages(a)...) + continue + } + out = append(out, a) + } + return out +} + +// importPaths returns the import paths to use for the given command line. +func importPaths(args []string) []string { + args = importPathsNoDotExpansion(args) + var out []string + for _, a := range args { + if strings.Contains(a, "...") { + if build.IsLocalImport(a) { + out = append(out, allPackagesInFS(a)...) + } else { + out = append(out, allPackages(a)...) + } + continue + } + out = append(out, a) + } + return out +} + +var atexitFuncs []func() + +func atexit(f func()) { + atexitFuncs = append(atexitFuncs, f) +} + +func exit() { + for _, f := range atexitFuncs { + f() + } + os.Exit(exitStatus) +} + +func fatalf(format string, args ...interface{}) { + errorf(format, args...) + exit() +} + +func errorf(format string, args ...interface{}) { + log.Printf(format, args...) + setExitStatus(1) +} + +var logf = log.Printf + +func exitIfErrors() { + if exitStatus != 0 { + exit() + } +} + +func run(cmdargs ...interface{}) { + cmdline := stringList(cmdargs...) + if buildN || buildX { + fmt.Printf("%s\n", strings.Join(cmdline, " ")) + if buildN { + return + } + } + + cmd := exec.Command(cmdline[0], cmdline[1:]...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + errorf("%v", err) + } +} + +func runOut(dir string, cmdargs ...interface{}) []byte { + cmdline := stringList(cmdargs...) + cmd := exec.Command(cmdline[0], cmdline[1:]...) + cmd.Dir = dir + out, err := cmd.CombinedOutput() + if err != nil { + os.Stderr.Write(out) + errorf("%v", err) + out = nil + } + return out +} + +// envForDir returns a copy of the environment +// suitable for running in the given directory. +// The environment is the current process's environment +// but with an updated $PWD, so that an os.Getwd in the +// child will be faster. +func envForDir(dir string) []string { + env := os.Environ() + // Internally we only use rooted paths, so dir is rooted. + // Even if dir is not rooted, no harm done. + return mergeEnvLists([]string{"PWD=" + dir}, env) +} + +// mergeEnvLists merges the two environment lists such that +// variables with the same name in "in" replace those in "out". +func mergeEnvLists(in, out []string) []string { +NextVar: + for _, inkv := range in { + k := strings.SplitAfterN(inkv, "=", 2)[0] + for i, outkv := range out { + if strings.HasPrefix(outkv, k) { + out[i] = inkv + continue NextVar + } + } + out = append(out, inkv) + } + return out +} + +// matchPattern(pattern)(name) reports whether +// name matches pattern. Pattern is a limited glob +// pattern in which '...' means 'any string' and there +// is no other special syntax. +func matchPattern(pattern string) func(name string) bool { + re := regexp.QuoteMeta(pattern) + re = strings.Replace(re, `\.\.\.`, `.*`, -1) + // Special case: foo/... matches foo too. + if strings.HasSuffix(re, `/.*`) { + re = re[:len(re)-len(`/.*`)] + `(/.*)?` + } + reg := regexp.MustCompile(`^` + re + `$`) + return func(name string) bool { + return reg.MatchString(name) + } +} + +// hasPathPrefix reports whether the path s begins with the +// elements in prefix. +func hasPathPrefix(s, prefix string) bool { + switch { + default: + return false + case len(s) == len(prefix): + return s == prefix + case len(s) > len(prefix): + if prefix != "" && prefix[len(prefix)-1] == '/' { + return strings.HasPrefix(s, prefix) + } + return s[len(prefix)] == '/' && s[:len(prefix)] == prefix + } +} + +// treeCanMatchPattern(pattern)(name) reports whether +// name or children of name can possibly match pattern. +// Pattern is the same limited glob accepted by matchPattern. +func treeCanMatchPattern(pattern string) func(name string) bool { + wildCard := false + if i := strings.Index(pattern, "..."); i >= 0 { + wildCard = true + pattern = pattern[:i] + } + return func(name string) bool { + return len(name) <= len(pattern) && hasPathPrefix(pattern, name) || + wildCard && strings.HasPrefix(name, pattern) + } +} + +// allPackages returns all the packages that can be found +// under the $GOPATH directories and $GOROOT matching pattern. +// The pattern is either "all" (all packages), "std" (standard packages) +// or a path including "...". +func allPackages(pattern string) []string { + pkgs := matchPackages(pattern) + if len(pkgs) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return pkgs +} + +func matchPackages(pattern string) []string { + match := func(string) bool { return true } + treeCanMatch := func(string) bool { return true } + if pattern != "all" && pattern != "std" { + match = matchPattern(pattern) + treeCanMatch = treeCanMatchPattern(pattern) + } + + have := map[string]bool{ + "builtin": true, // ignore pseudo-package that exists only for documentation + } + if !buildContext.CgoEnabled { + have["runtime/cgo"] = true // ignore during walk + } + var pkgs []string + + // Commands + cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator) + filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() || path == cmd { + return nil + } + name := path[len(cmd):] + if !treeCanMatch(name) { + return filepath.SkipDir + } + // Commands are all in cmd/, not in subdirectories. + if strings.Contains(name, string(filepath.Separator)) { + return filepath.SkipDir + } + + // We use, e.g., cmd/gofmt as the pseudo import path for gofmt. + name = "cmd/" + name + if have[name] { + return nil + } + have[name] = true + if !match(name) { + return nil + } + _, err = buildContext.ImportDir(path, 0) + if err != nil { + if _, noGo := err.(*build.NoGoError); !noGo { + log.Print(err) + } + return nil + } + pkgs = append(pkgs, name) + return nil + }) + + for _, src := range buildContext.SrcDirs() { + if pattern == "std" && src != gorootSrc { + continue + } + src = filepath.Clean(src) + string(filepath.Separator) + filepath.Walk(src, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() || path == src { + return nil + } + + // Avoid .foo, _foo, and testdata directory trees. + _, elem := filepath.Split(path) + if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { + return filepath.SkipDir + } + + name := filepath.ToSlash(path[len(src):]) + if pattern == "std" && strings.Contains(name, ".") { + return filepath.SkipDir + } + if !treeCanMatch(name) { + return filepath.SkipDir + } + if have[name] { + return nil + } + have[name] = true + if !match(name) { + return nil + } + _, err = buildContext.ImportDir(path, 0) + if err != nil { + if _, noGo := err.(*build.NoGoError); noGo { + return nil + } + } + pkgs = append(pkgs, name) + return nil + }) + } + return pkgs +} + +// allPackagesInFS is like allPackages but is passed a pattern +// beginning ./ or ../, meaning it should scan the tree rooted +// at the given directory. There are ... in the pattern too. +func allPackagesInFS(pattern string) []string { + pkgs := matchPackagesInFS(pattern) + if len(pkgs) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return pkgs +} + +func matchPackagesInFS(pattern string) []string { + // Find directory to begin the scan. + // Could be smarter but this one optimization + // is enough for now, since ... is usually at the + // end of a path. + i := strings.Index(pattern, "...") + dir, _ := path.Split(pattern[:i]) + + // pattern begins with ./ or ../. + // path.Clean will discard the ./ but not the ../. + // We need to preserve the ./ for pattern matching + // and in the returned import paths. + prefix := "" + if strings.HasPrefix(pattern, "./") { + prefix = "./" + } + match := matchPattern(pattern) + + var pkgs []string + filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() { + return nil + } + if path == dir { + // filepath.Walk starts at dir and recurses. For the recursive case, + // the path is the result of filepath.Join, which calls filepath.Clean. + // The initial case is not Cleaned, though, so we do this explicitly. + // + // This converts a path like "./io/" to "io". Without this step, running + // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io + // package, because prepending the prefix "./" to the unclean path would + // result in "././io", and match("././io") returns false. + path = filepath.Clean(path) + } + + // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..". + _, elem := filepath.Split(path) + dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".." + if dot || strings.HasPrefix(elem, "_") || elem == "testdata" { + return filepath.SkipDir + } + + name := prefix + filepath.ToSlash(path) + if !match(name) { + return nil + } + if _, err = build.ImportDir(path, 0); err != nil { + if _, noGo := err.(*build.NoGoError); !noGo { + log.Print(err) + } + return nil + } + pkgs = append(pkgs, name) + return nil + }) + return pkgs +} + +// stringList's arguments should be a sequence of string or []string values. +// stringList flattens them into a single []string. +func stringList(args ...interface{}) []string { + var x []string + for _, arg := range args { + switch arg := arg.(type) { + case []string: + x = append(x, arg...) + case string: + x = append(x, arg) + default: + panic("stringList: invalid argument") + } + } + return x +} + +// toFold returns a string with the property that +// strings.EqualFold(s, t) iff toFold(s) == toFold(t) +// This lets us test a large set of strings for fold-equivalent +// duplicates without making a quadratic number of calls +// to EqualFold. Note that strings.ToUpper and strings.ToLower +// have the desired property in some corner cases. +func toFold(s string) string { + // Fast path: all ASCII, no upper case. + // Most paths look like this already. + for i := 0; i < len(s); i++ { + c := s[i] + if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' { + goto Slow + } + } + return s + +Slow: + var buf bytes.Buffer + for _, r := range s { + // SimpleFold(x) cycles to the next equivalent rune > x + // or wraps around to smaller values. Iterate until it wraps, + // and we've found the minimum value. + for { + r0 := r + r = unicode.SimpleFold(r0) + if r <= r0 { + break + } + } + // Exception to allow fast path above: A-Z => a-z + if 'A' <= r && r <= 'Z' { + r += 'a' - 'A' + } + buf.WriteRune(r) + } + return buf.String() +} + +// foldDup reports a pair of strings from the list that are +// equal according to strings.EqualFold. +// It returns "", "" if there are no such strings. +func foldDup(list []string) (string, string) { + clash := map[string]string{} + for _, s := range list { + fold := toFold(s) + if t := clash[fold]; t != "" { + if s > t { + s, t = t, s + } + return s, t + } + clash[fold] = s + } + return "", "" +} diff --git a/libgo/go/cmd/go/match_test.go b/libgo/go/cmd/go/match_test.go new file mode 100644 index 0000000000..38b9b115e7 --- /dev/null +++ b/libgo/go/cmd/go/match_test.go @@ -0,0 +1,88 @@ +// 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 "testing" + +var matchPatternTests = []stringPairTest{ + {"...", "foo", true}, + {"net", "net", true}, + {"net", "net/http", false}, + {"net/http", "net", false}, + {"net/http", "net/http", true}, + {"net...", "netchan", true}, + {"net...", "net", true}, + {"net...", "net/http", true}, + {"net...", "not/http", false}, + {"net/...", "netchan", false}, + {"net/...", "net", true}, + {"net/...", "net/http", true}, + {"net/...", "not/http", false}, +} + +func TestMatchPattern(t *testing.T) { + testStringPairs(t, "matchPattern", matchPatternTests, func(pattern, name string) bool { + return matchPattern(pattern)(name) + }) +} + +var treeCanMatchPatternTests = []stringPairTest{ + {"...", "foo", true}, + {"net", "net", true}, + {"net", "net/http", false}, + {"net/http", "net", true}, + {"net/http", "net/http", true}, + {"net...", "netchan", true}, + {"net...", "net", true}, + {"net...", "net/http", true}, + {"net...", "not/http", false}, + {"net/...", "netchan", false}, + {"net/...", "net", true}, + {"net/...", "net/http", true}, + {"net/...", "not/http", false}, + {"abc.../def", "abcxyz", true}, + {"abc.../def", "xyxabc", false}, + {"x/y/z/...", "x", true}, + {"x/y/z/...", "x/y", true}, + {"x/y/z/...", "x/y/z", true}, + {"x/y/z/...", "x/y/z/w", true}, + {"x/y/z", "x", true}, + {"x/y/z", "x/y", true}, + {"x/y/z", "x/y/z", true}, + {"x/y/z", "x/y/z/w", false}, + {"x/.../y/z", "x/a/b/c", true}, + {"x/.../y/z", "y/x/a/b/c", false}, +} + +func TestChildrenCanMatchPattern(t *testing.T) { + testStringPairs(t, "treeCanMatchPattern", treeCanMatchPatternTests, func(pattern, name string) bool { + return treeCanMatchPattern(pattern)(name) + }) +} + +var hasPathPrefixTests = []stringPairTest{ + {"abc", "a", false}, + {"a/bc", "a", true}, + {"a", "a", true}, + {"a/bc", "a/", true}, +} + +func TestHasPathPrefix(t *testing.T) { + testStringPairs(t, "hasPathPrefix", hasPathPrefixTests, hasPathPrefix) +} + +type stringPairTest struct { + in1 string + in2 string + out bool +} + +func testStringPairs(t *testing.T, name string, tests []stringPairTest, f func(string, string) bool) { + for _, tt := range tests { + if out := f(tt.in1, tt.in2); out != tt.out { + t.Errorf("%s(%q, %q) = %v, want %v", name, tt.in1, tt.in2, out, tt.out) + } + } +} diff --git a/libgo/go/cmd/go/mkdoc.sh b/libgo/go/cmd/go/mkdoc.sh new file mode 100644 index 0000000000..12fd7ba3e7 --- /dev/null +++ b/libgo/go/cmd/go/mkdoc.sh @@ -0,0 +1,9 @@ +#!/bin/sh +# 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. + +go install # So the next line will produce updated documentation. +go help documentation > doc.go +gofmt -w doc.go + diff --git a/libgo/go/cmd/go/pkg.go b/libgo/go/cmd/go/pkg.go new file mode 100644 index 0000000000..ef440dd3b7 --- /dev/null +++ b/libgo/go/cmd/go/pkg.go @@ -0,0 +1,969 @@ +// 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 main + +import ( + "bytes" + "errors" + "fmt" + "go/build" + "go/scanner" + "go/token" + "os" + pathpkg "path" + "path/filepath" + "runtime" + "sort" + "strings" + "time" + "unicode" +) + +// A Package describes a single package found in a directory. +type Package struct { + // Note: These fields are part of the go command's public API. + // See list.go. It is okay to add fields, but not to change or + // remove existing ones. Keep in sync with list.go + Dir string `json:",omitempty"` // directory containing package sources + ImportPath string `json:",omitempty"` // import path of package in dir + ImportComment string `json:",omitempty"` // path in import comment on package statement + Name string `json:",omitempty"` // package name + Doc string `json:",omitempty"` // package documentation string + Target string `json:",omitempty"` // install path + Goroot bool `json:",omitempty"` // is this package found in the Go root? + Standard bool `json:",omitempty"` // is this package part of the standard Go library? + Stale bool `json:",omitempty"` // would 'go install' do anything for this package? + Root string `json:",omitempty"` // Go root or Go path dir containing this package + ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory + + // Source files + GoFiles []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) + CgoFiles []string `json:",omitempty"` // .go sources files that import "C" + IgnoredGoFiles []string `json:",omitempty"` // .go sources ignored due to build constraints + CFiles []string `json:",omitempty"` // .c source files + CXXFiles []string `json:",omitempty"` // .cc, .cpp and .cxx source files + MFiles []string `json:",omitempty"` // .m source files + HFiles []string `json:",omitempty"` // .h, .hh, .hpp and .hxx source files + SFiles []string `json:",omitempty"` // .s source files + SwigFiles []string `json:",omitempty"` // .swig files + SwigCXXFiles []string `json:",omitempty"` // .swigcxx files + SysoFiles []string `json:",omitempty"` // .syso system object files added to package + + // Cgo directives + CgoCFLAGS []string `json:",omitempty"` // cgo: flags for C compiler + CgoCPPFLAGS []string `json:",omitempty"` // cgo: flags for C preprocessor + CgoCXXFLAGS []string `json:",omitempty"` // cgo: flags for C++ compiler + CgoLDFLAGS []string `json:",omitempty"` // cgo: flags for linker + CgoPkgConfig []string `json:",omitempty"` // cgo: pkg-config names + + // Dependency information + Imports []string `json:",omitempty"` // import paths used by this package + Deps []string `json:",omitempty"` // all (recursively) imported dependencies + + // Error information + Incomplete bool `json:",omitempty"` // was there an error loading this package or dependencies? + Error *PackageError `json:",omitempty"` // error loading this package (not dependencies) + DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies + + // Test information + TestGoFiles []string `json:",omitempty"` // _test.go files in package + TestImports []string `json:",omitempty"` // imports from TestGoFiles + XTestGoFiles []string `json:",omitempty"` // _test.go files outside package + XTestImports []string `json:",omitempty"` // imports from XTestGoFiles + + // Unexported fields are not part of the public API. + build *build.Package + pkgdir string // overrides build.PkgDir + imports []*Package + deps []*Package + gofiles []string // GoFiles+CgoFiles+TestGoFiles+XTestGoFiles files, absolute paths + sfiles []string + allgofiles []string // gofiles + IgnoredGoFiles, absolute paths + target string // installed file for this package (may be executable) + fake bool // synthesized package + external bool // synthesized external test package + forceBuild bool // this package must be rebuilt + forceLibrary bool // this package is a library (even if named "main") + cmdline bool // defined by files listed on command line + local bool // imported via local path (./ or ../) + localPrefix string // interpret ./ and ../ imports relative to this prefix + exeName string // desired name for temporary executable + coverMode string // preprocess Go source files with the coverage tool in this mode + coverVars map[string]*CoverVar // variables created by coverage analysis + omitDWARF bool // tell linker not to write DWARF information +} + +// CoverVar holds the name of the generated coverage variables targeting the named file. +type CoverVar struct { + File string // local file name + Var string // name of count struct +} + +func (p *Package) copyBuild(pp *build.Package) { + p.build = pp + + p.Dir = pp.Dir + p.ImportPath = pp.ImportPath + p.ImportComment = pp.ImportComment + p.Name = pp.Name + p.Doc = pp.Doc + p.Root = pp.Root + p.ConflictDir = pp.ConflictDir + // TODO? Target + p.Goroot = pp.Goroot + if buildContext.Compiler == "gccgo" { + p.Standard = stdpkg[p.ImportPath] + } else { + p.Standard = p.Goroot && p.ImportPath != "" && !strings.Contains(p.ImportPath, ".") + } + p.GoFiles = pp.GoFiles + p.CgoFiles = pp.CgoFiles + p.IgnoredGoFiles = pp.IgnoredGoFiles + p.CFiles = pp.CFiles + p.CXXFiles = pp.CXXFiles + p.MFiles = pp.MFiles + p.HFiles = pp.HFiles + p.SFiles = pp.SFiles + p.SwigFiles = pp.SwigFiles + p.SwigCXXFiles = pp.SwigCXXFiles + p.SysoFiles = pp.SysoFiles + p.CgoCFLAGS = pp.CgoCFLAGS + p.CgoCPPFLAGS = pp.CgoCPPFLAGS + p.CgoCXXFLAGS = pp.CgoCXXFLAGS + p.CgoLDFLAGS = pp.CgoLDFLAGS + p.CgoPkgConfig = pp.CgoPkgConfig + p.Imports = pp.Imports + p.TestGoFiles = pp.TestGoFiles + p.TestImports = pp.TestImports + p.XTestGoFiles = pp.XTestGoFiles + p.XTestImports = pp.XTestImports +} + +// A PackageError describes an error loading information about a package. +type PackageError struct { + ImportStack []string // shortest path from package named on command line to this one + Pos string // position of error + Err string // the error itself + isImportCycle bool // the error is an import cycle + hard bool // whether the error is soft or hard; soft errors are ignored in some places +} + +func (p *PackageError) Error() string { + // Import cycles deserve special treatment. + if p.isImportCycle { + return fmt.Sprintf("%s\npackage %s\n", p.Err, strings.Join(p.ImportStack, "\n\timports ")) + } + if p.Pos != "" { + // Omit import stack. The full path to the file where the error + // is the most important thing. + return p.Pos + ": " + p.Err + } + if len(p.ImportStack) == 0 { + return p.Err + } + return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Err +} + +// An importStack is a stack of import paths. +type importStack []string + +func (s *importStack) push(p string) { + *s = append(*s, p) +} + +func (s *importStack) pop() { + *s = (*s)[0 : len(*s)-1] +} + +func (s *importStack) copy() []string { + return append([]string{}, *s...) +} + +// shorterThan returns true if sp is shorter than t. +// We use this to record the shortest import sequence +// that leads to a particular package. +func (sp *importStack) shorterThan(t []string) bool { + s := *sp + if len(s) != len(t) { + return len(s) < len(t) + } + // If they are the same length, settle ties using string ordering. + for i := range s { + if s[i] != t[i] { + return s[i] < t[i] + } + } + return false // they are equal +} + +// packageCache is a lookup cache for loadPackage, +// so that if we look up a package multiple times +// we return the same pointer each time. +var packageCache = map[string]*Package{} + +// reloadPackage is like loadPackage but makes sure +// not to use the package cache. +func reloadPackage(arg string, stk *importStack) *Package { + p := packageCache[arg] + if p != nil { + delete(packageCache, p.Dir) + delete(packageCache, p.ImportPath) + } + return loadPackage(arg, stk) +} + +// dirToImportPath returns the pseudo-import path we use for a package +// outside the Go path. It begins with _/ and then contains the full path +// to the directory. If the package lives in c:\home\gopher\my\pkg then +// the pseudo-import path is _/c_/home/gopher/my/pkg. +// Using a pseudo-import path like this makes the ./ imports no longer +// a special case, so that all the code to deal with ordinary imports works +// automatically. +func dirToImportPath(dir string) string { + return pathpkg.Join("_", strings.Map(makeImportValid, filepath.ToSlash(dir))) +} + +func makeImportValid(r rune) rune { + // Should match Go spec, compilers, and ../../go/parser/parser.go:/isValidImport. + const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD" + if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) { + return '_' + } + return r +} + +// loadImport scans the directory named by path, which must be an import path, +// but possibly a local import path (an absolute file system path or one beginning +// with ./ or ../). A local relative path is interpreted relative to srcDir. +// It returns a *Package describing the package found in that directory. +func loadImport(path string, srcDir string, stk *importStack, importPos []token.Position) *Package { + stk.push(path) + defer stk.pop() + + // Determine canonical identifier for this package. + // For a local import the identifier is the pseudo-import path + // we create from the full directory to the package. + // Otherwise it is the usual import path. + importPath := path + isLocal := build.IsLocalImport(path) + if isLocal { + importPath = dirToImportPath(filepath.Join(srcDir, path)) + } + if p := packageCache[importPath]; p != nil { + if perr := disallowInternal(srcDir, p, stk); perr != p { + return perr + } + return reusePackage(p, stk) + } + + p := new(Package) + p.local = isLocal + p.ImportPath = importPath + packageCache[importPath] = p + + // Load package. + // Import always returns bp != nil, even if an error occurs, + // in order to return partial information. + // + // TODO: After Go 1, decide when to pass build.AllowBinary here. + // See issue 3268 for mistakes to avoid. + bp, err := buildContext.Import(path, srcDir, build.ImportComment) + bp.ImportPath = importPath + if gobin != "" { + bp.BinDir = gobin + } + if err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path { + err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment) + } + p.load(stk, bp, err) + if p.Error != nil && len(importPos) > 0 { + pos := importPos[0] + pos.Filename = shortPath(pos.Filename) + p.Error.Pos = pos.String() + } + + if perr := disallowInternal(srcDir, p, stk); perr != p { + return perr + } + + return p +} + +// reusePackage reuses package p to satisfy the import at the top +// of the import stack stk. If this use causes an import loop, +// reusePackage updates p's error information to record the loop. +func reusePackage(p *Package, stk *importStack) *Package { + // We use p.imports==nil to detect a package that + // is in the midst of its own loadPackage call + // (all the recursion below happens before p.imports gets set). + if p.imports == nil { + if p.Error == nil { + p.Error = &PackageError{ + ImportStack: stk.copy(), + Err: "import cycle not allowed", + isImportCycle: true, + } + } + p.Incomplete = true + } + // Don't rewrite the import stack in the error if we have an import cycle. + // If we do, we'll lose the path that describes the cycle. + if p.Error != nil && !p.Error.isImportCycle && stk.shorterThan(p.Error.ImportStack) { + p.Error.ImportStack = stk.copy() + } + return p +} + +// disallowInternal checks that srcDir is allowed to import p. +// If the import is allowed, disallowInternal returns the original package p. +// If not, it returns a new package containing just an appropriate error. +func disallowInternal(srcDir string, p *Package, stk *importStack) *Package { + // golang.org/s/go14internal: + // An import of a path containing the element “internal” + // is disallowed if the importing code is outside the tree + // rooted at the parent of the “internal” directory. + // + // ... For Go 1.4, we will implement the rule first for $GOROOT, but not $GOPATH. + + // Only applies to $GOROOT. + if !p.Standard { + return p + } + + // The stack includes p.ImportPath. + // If that's the only thing on the stack, we started + // with a name given on the command line, not an + // import. Anything listed on the command line is fine. + if len(*stk) == 1 { + return p + } + + // Check for "internal" element: four cases depending on begin of string and/or end of string. + i, ok := findInternal(p.ImportPath) + if !ok { + return p + } + + // Internal is present. + // Map import path back to directory corresponding to parent of internal. + if i > 0 { + i-- // rewind over slash in ".../internal" + } + parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)] + if hasPathPrefix(filepath.ToSlash(srcDir), filepath.ToSlash(parent)) { + return p + } + + // Internal is present, and srcDir is outside parent's tree. Not allowed. + perr := *p + perr.Error = &PackageError{ + ImportStack: stk.copy(), + Err: "use of internal package not allowed", + } + perr.Incomplete = true + return &perr +} + +// findInternal looks for the final "internal" path element in the given import path. +// If there isn't one, findInternal returns ok=false. +// Otherwise, findInternal returns ok=true and the index of the "internal". +func findInternal(path string) (index int, ok bool) { + // Four cases, depending on internal at start/end of string or not. + // The order matters: we must return the index of the final element, + // because the final one produces the most restrictive requirement + // on the importer. + switch { + case strings.HasSuffix(path, "/internal"): + return len(path) - len("internal"), true + case strings.Contains(path, "/internal/"): + return strings.LastIndex(path, "/internal/") + 1, true + case path == "internal", strings.HasPrefix(path, "internal/"): + return 0, true + } + return 0, false +} + +type targetDir int + +const ( + toRoot targetDir = iota // to bin dir inside package root (default) + toTool // GOROOT/pkg/tool + toBin // GOROOT/bin + stalePath // the old import path; fail to build +) + +// goTools is a map of Go program import path to install target directory. +var goTools = map[string]targetDir{ + "cmd/addr2line": toTool, + "cmd/api": toTool, + "cmd/cgo": toTool, + "cmd/fix": toTool, + "cmd/link": toTool, + "cmd/nm": toTool, + "cmd/objdump": toTool, + "cmd/pack": toTool, + "cmd/pprof": toTool, + "cmd/yacc": toTool, + "golang.org/x/tools/cmd/cover": toTool, + "golang.org/x/tools/cmd/godoc": toBin, + "golang.org/x/tools/cmd/vet": toTool, + "code.google.com/p/go.tools/cmd/cover": stalePath, + "code.google.com/p/go.tools/cmd/godoc": stalePath, + "code.google.com/p/go.tools/cmd/vet": stalePath, +} + +// expandScanner expands a scanner.List error into all the errors in the list. +// The default Error method only shows the first error. +func expandScanner(err error) error { + // Look for parser errors. + if err, ok := err.(scanner.ErrorList); ok { + // Prepare error with \n before each message. + // When printed in something like context: %v + // this will put the leading file positions each on + // its own line. It will also show all the errors + // instead of just the first, as err.Error does. + var buf bytes.Buffer + for _, e := range err { + e.Pos.Filename = shortPath(e.Pos.Filename) + buf.WriteString("\n") + buf.WriteString(e.Error()) + } + return errors.New(buf.String()) + } + return err +} + +var raceExclude = map[string]bool{ + "runtime/race": true, + "runtime/cgo": true, + "cmd/cgo": true, + "syscall": true, + "errors": true, +} + +var cgoExclude = map[string]bool{ + "runtime/cgo": true, +} + +var cgoSyscallExclude = map[string]bool{ + "runtime/cgo": true, + "runtime/race": true, +} + +// load populates p using information from bp, err, which should +// be the result of calling build.Context.Import. +func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package { + p.copyBuild(bp) + + // The localPrefix is the path we interpret ./ imports relative to. + // Synthesized main packages sometimes override this. + p.localPrefix = dirToImportPath(p.Dir) + + if err != nil { + p.Incomplete = true + err = expandScanner(err) + p.Error = &PackageError{ + ImportStack: stk.copy(), + Err: err.Error(), + } + return p + } + + if p.Name == "main" { + // Report an error when the old code.google.com/p/go.tools paths are used. + if goTools[p.ImportPath] == stalePath { + newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1) + e := fmt.Sprintf("the %v command has moved; use %v instead.", p.ImportPath, newPath) + p.Error = &PackageError{Err: e} + return p + } + _, elem := filepath.Split(p.Dir) + full := buildContext.GOOS + "_" + buildContext.GOARCH + "/" + elem + if buildContext.GOOS != toolGOOS || buildContext.GOARCH != toolGOARCH { + // Install cross-compiled binaries to subdirectories of bin. + elem = full + } + if p.build.BinDir != gobin && goTools[p.ImportPath] == toBin { + // Override BinDir. + // This is from a subrepo but installs to $GOROOT/bin + // by default anyway (like godoc). + p.target = filepath.Join(gorootBin, elem) + } else if p.build.BinDir != "" { + // Install to GOBIN or bin of GOPATH entry. + p.target = filepath.Join(p.build.BinDir, elem) + } + if goTools[p.ImportPath] == toTool { + // This is for 'go tool'. + // Override all the usual logic and force it into the tool directory. + p.target = filepath.Join(gorootPkg, "tool", full) + } + if p.target != "" && buildContext.GOOS == "windows" { + p.target += ".exe" + } + } else if p.local { + // Local import turned into absolute path. + // No permanent install target. + p.target = "" + } else { + p.target = p.build.PkgObj + } + + importPaths := p.Imports + // Packages that use cgo import runtime/cgo implicitly. + // Packages that use cgo also import syscall implicitly, + // to wrap errno. + // Exclude certain packages to avoid circular dependencies. + if len(p.CgoFiles) > 0 && (!p.Standard || !cgoExclude[p.ImportPath]) { + importPaths = append(importPaths, "runtime/cgo") + } + if len(p.CgoFiles) > 0 && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) { + importPaths = append(importPaths, "syscall") + } + // Everything depends on runtime, except runtime and unsafe. + if !p.Standard || (p.ImportPath != "runtime" && p.ImportPath != "unsafe") { + importPaths = append(importPaths, "runtime") + // When race detection enabled everything depends on runtime/race. + // Exclude certain packages to avoid circular dependencies. + if buildRace && (!p.Standard || !raceExclude[p.ImportPath]) { + importPaths = append(importPaths, "runtime/race") + } + } + + // Build list of full paths to all Go files in the package, + // for use by commands like go fmt. + p.gofiles = stringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles) + for i := range p.gofiles { + p.gofiles[i] = filepath.Join(p.Dir, p.gofiles[i]) + } + sort.Strings(p.gofiles) + + p.sfiles = stringList(p.SFiles) + for i := range p.sfiles { + p.sfiles[i] = filepath.Join(p.Dir, p.sfiles[i]) + } + sort.Strings(p.sfiles) + + p.allgofiles = stringList(p.IgnoredGoFiles) + for i := range p.allgofiles { + p.allgofiles[i] = filepath.Join(p.Dir, p.allgofiles[i]) + } + p.allgofiles = append(p.allgofiles, p.gofiles...) + sort.Strings(p.allgofiles) + + // Check for case-insensitive collision of input files. + // To avoid problems on case-insensitive files, we reject any package + // where two different input files have equal names under a case-insensitive + // comparison. + f1, f2 := foldDup(stringList( + p.GoFiles, + p.CgoFiles, + p.IgnoredGoFiles, + p.CFiles, + p.CXXFiles, + p.MFiles, + p.HFiles, + p.SFiles, + p.SysoFiles, + p.SwigFiles, + p.SwigCXXFiles, + p.TestGoFiles, + p.XTestGoFiles, + )) + if f1 != "" { + p.Error = &PackageError{ + ImportStack: stk.copy(), + Err: fmt.Sprintf("case-insensitive file name collision: %q and %q", f1, f2), + } + return p + } + + // Build list of imported packages and full dependency list. + imports := make([]*Package, 0, len(p.Imports)) + deps := make(map[string]*Package) + for i, path := range importPaths { + if path == "C" { + continue + } + p1 := loadImport(path, p.Dir, stk, p.build.ImportPos[path]) + if !reqStdPkgSrc && p1.Standard { + continue + } + if p1.local { + if !p.local && p.Error == nil { + p.Error = &PackageError{ + ImportStack: stk.copy(), + Err: fmt.Sprintf("local import %q in non-local package", path), + } + pos := p.build.ImportPos[path] + if len(pos) > 0 { + p.Error.Pos = pos[0].String() + } + } + path = p1.ImportPath + importPaths[i] = path + } + deps[path] = p1 + imports = append(imports, p1) + for _, dep := range p1.deps { + deps[dep.ImportPath] = dep + } + if p1.Incomplete { + p.Incomplete = true + } + } + p.imports = imports + + p.Deps = make([]string, 0, len(deps)) + for dep := range deps { + p.Deps = append(p.Deps, dep) + } + sort.Strings(p.Deps) + for _, dep := range p.Deps { + p1 := deps[dep] + if p1 == nil { + panic("impossible: missing entry in package cache for " + dep + " imported by " + p.ImportPath) + } + p.deps = append(p.deps, p1) + if p1.Error != nil { + p.DepsErrors = append(p.DepsErrors, p1.Error) + } + } + + // unsafe is a fake package. + if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") { + p.target = "" + } + p.Target = p.target + + // Check for C code compiled with Plan 9 C compiler. + // No longer allowed except in runtime and runtime/cgo, for now. + if len(p.CFiles) > 0 && !p.usesCgo() && (!p.Standard || p.ImportPath != "runtime") { + p.Error = &PackageError{ + ImportStack: stk.copy(), + Err: fmt.Sprintf("C source files not allowed when not using cgo: %s", strings.Join(p.CFiles, " ")), + } + return p + } + + // In the absence of errors lower in the dependency tree, + // check for case-insensitive collisions of import paths. + if len(p.DepsErrors) == 0 { + dep1, dep2 := foldDup(p.Deps) + if dep1 != "" { + p.Error = &PackageError{ + ImportStack: stk.copy(), + Err: fmt.Sprintf("case-insensitive import collision: %q and %q", dep1, dep2), + } + return p + } + } + + return p +} + +// usesSwig reports whether the package needs to run SWIG. +func (p *Package) usesSwig() bool { + return len(p.SwigFiles) > 0 || len(p.SwigCXXFiles) > 0 +} + +// usesCgo reports whether the package needs to run cgo +func (p *Package) usesCgo() bool { + return len(p.CgoFiles) > 0 +} + +// packageList returns the list of packages in the dag rooted at roots +// as visited in a depth-first post-order traversal. +func packageList(roots []*Package) []*Package { + seen := map[*Package]bool{} + all := []*Package{} + var walk func(*Package) + walk = func(p *Package) { + if seen[p] { + return + } + seen[p] = true + for _, p1 := range p.imports { + walk(p1) + } + all = append(all, p) + } + for _, root := range roots { + walk(root) + } + return all +} + +// computeStale computes the Stale flag in the package dag that starts +// at the named pkgs (command-line arguments). +func computeStale(pkgs ...*Package) { + topRoot := map[string]bool{} + for _, p := range pkgs { + topRoot[p.Root] = true + } + + for _, p := range packageList(pkgs) { + p.Stale = isStale(p, topRoot) + } +} + +// The runtime version string takes one of two forms: +// "go1.X[.Y]" for Go releases, and "devel +hash" at tip. +// Determine whether we are in a released copy by +// inspecting the version. +var isGoRelease = strings.HasPrefix(runtime.Version(), "go1") + +// isStale reports whether package p needs to be rebuilt. +func isStale(p *Package, topRoot map[string]bool) bool { + if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") { + // fake, builtin package + return false + } + if p.Error != nil { + return true + } + + // A package without Go sources means we only found + // the installed .a file. Since we don't know how to rebuild + // it, it can't be stale, even if -a is set. This enables binary-only + // distributions of Go packages, although such binaries are + // only useful with the specific version of the toolchain that + // created them. + if len(p.gofiles) == 0 && !p.usesSwig() { + return false + } + + // If we are running a release copy of Go, do not rebuild the standard packages. + // They may not be writable anyway, but they are certainly not changing. + // This makes 'go build -a' skip the standard packages when using an official release. + // See issue 4106 and issue 8290. + pkgBuildA := buildA + if p.Standard && isGoRelease { + pkgBuildA = false + } + + if pkgBuildA || p.target == "" || p.Stale { + return true + } + + // Package is stale if completely unbuilt. + var built time.Time + if fi, err := os.Stat(p.target); err == nil { + built = fi.ModTime() + } + if built.IsZero() { + return true + } + + olderThan := func(file string) bool { + fi, err := os.Stat(file) + return err != nil || fi.ModTime().After(built) + } + + // Package is stale if a dependency is, or if a dependency is newer. + for _, p1 := range p.deps { + if p1.Stale || p1.target != "" && olderThan(p1.target) { + return true + } + } + + // As a courtesy to developers installing new versions of the compiler + // frequently, define that packages are stale if they are + // older than the compiler, and commands if they are older than + // the linker. This heuristic will not work if the binaries are + // back-dated, as some binary distributions may do, but it does handle + // a very common case. + // See issue 3036. + // Assume code in $GOROOT is up to date, since it may not be writeable. + // See issue 4106. + if p.Root != goroot { + if olderThan(buildToolchain.compiler()) { + return true + } + if p.build.IsCommand() && olderThan(buildToolchain.linker()) { + return true + } + } + + // Have installed copy, probably built using current compilers, + // and built after its imported packages. The only reason now + // that we'd have to rebuild it is if the sources were newer than + // the package. If a package p is not in the same tree as any + // package named on the command-line, assume it is up-to-date + // no matter what the modification times on the source files indicate. + // This avoids rebuilding $GOROOT packages when people are + // working outside the Go root, and it effectively makes each tree + // listed in $GOPATH a separate compilation world. + // See issue 3149. + if p.Root != "" && !topRoot[p.Root] { + return false + } + + srcs := stringList(p.GoFiles, p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.SFiles, p.CgoFiles, p.SysoFiles, p.SwigFiles, p.SwigCXXFiles) + for _, src := range srcs { + if olderThan(filepath.Join(p.Dir, src)) { + return true + } + } + + return false +} + +var cwd, _ = os.Getwd() + +var cmdCache = map[string]*Package{} + +// loadPackage is like loadImport but is used for command-line arguments, +// not for paths found in import statements. In addition to ordinary import paths, +// loadPackage accepts pseudo-paths beginning with cmd/ to denote commands +// in the Go command directory, as well as paths to those directories. +func loadPackage(arg string, stk *importStack) *Package { + if build.IsLocalImport(arg) { + dir := arg + if !filepath.IsAbs(dir) { + if abs, err := filepath.Abs(dir); err == nil { + // interpret relative to current directory + dir = abs + } + } + if sub, ok := hasSubdir(gorootSrc, dir); ok && strings.HasPrefix(sub, "cmd/") && !strings.Contains(sub[4:], "/") { + arg = sub + } + } + if strings.HasPrefix(arg, "cmd/") && !strings.Contains(arg[4:], "/") { + if p := cmdCache[arg]; p != nil { + return p + } + stk.push(arg) + defer stk.pop() + + bp, err := buildContext.ImportDir(filepath.Join(gorootSrc, arg), 0) + bp.ImportPath = arg + bp.Goroot = true + bp.BinDir = gorootBin + if gobin != "" { + bp.BinDir = gobin + } + bp.Root = goroot + bp.SrcRoot = gorootSrc + p := new(Package) + cmdCache[arg] = p + p.load(stk, bp, err) + if p.Error == nil && p.Name != "main" { + p.Error = &PackageError{ + ImportStack: stk.copy(), + Err: fmt.Sprintf("expected package main but found package %s in %s", p.Name, p.Dir), + } + } + return p + } + + // Wasn't a command; must be a package. + // If it is a local import path but names a standard package, + // we treat it as if the user specified the standard package. + // This lets you run go test ./ioutil in package io and be + // referring to io/ioutil rather than a hypothetical import of + // "./ioutil". + if build.IsLocalImport(arg) { + bp, _ := buildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly) + if bp.ImportPath != "" && bp.ImportPath != "." { + arg = bp.ImportPath + } + } + + return loadImport(arg, cwd, stk, nil) +} + +// packages returns the packages named by the +// command line arguments 'args'. If a named package +// cannot be loaded at all (for example, if the directory does not exist), +// then packages prints an error and does not include that +// package in the results. However, if errors occur trying +// to load dependencies of a named package, the named +// package is still returned, with p.Incomplete = true +// and details in p.DepsErrors. +func packages(args []string) []*Package { + var pkgs []*Package + for _, pkg := range packagesAndErrors(args) { + if pkg.Error != nil { + errorf("can't load package: %s", pkg.Error) + continue + } + pkgs = append(pkgs, pkg) + } + return pkgs +} + +// packagesAndErrors is like 'packages' but returns a +// *Package for every argument, even the ones that +// cannot be loaded at all. +// The packages that fail to load will have p.Error != nil. +func packagesAndErrors(args []string) []*Package { + if len(args) > 0 && strings.HasSuffix(args[0], ".go") { + return []*Package{goFilesPackage(args)} + } + + args = importPaths(args) + var pkgs []*Package + var stk importStack + var set = make(map[string]bool) + + for _, arg := range args { + if !set[arg] { + pkgs = append(pkgs, loadPackage(arg, &stk)) + set[arg] = true + } + } + computeStale(pkgs...) + + return pkgs +} + +// packagesForBuild is like 'packages' but fails if any of +// the packages or their dependencies have errors +// (cannot be built). +func packagesForBuild(args []string) []*Package { + pkgs := packagesAndErrors(args) + printed := map[*PackageError]bool{} + for _, pkg := range pkgs { + if pkg.Error != nil { + errorf("can't load package: %s", pkg.Error) + } + for _, err := range pkg.DepsErrors { + // Since these are errors in dependencies, + // the same error might show up multiple times, + // once in each package that depends on it. + // Only print each once. + if !printed[err] { + printed[err] = true + errorf("%s", err) + } + } + } + exitIfErrors() + return pkgs +} + +// hasSubdir reports whether dir is a subdirectory of +// (possibly multiple levels below) root. +// If so, it sets rel to the path fragment that must be +// appended to root to reach dir. +func hasSubdir(root, dir string) (rel string, ok bool) { + if p, err := filepath.EvalSymlinks(root); err == nil { + root = p + } + if p, err := filepath.EvalSymlinks(dir); err == nil { + dir = p + } + const sep = string(filepath.Separator) + root = filepath.Clean(root) + if !strings.HasSuffix(root, sep) { + root += sep + } + dir = filepath.Clean(dir) + if !strings.HasPrefix(dir, root) { + return "", false + } + return filepath.ToSlash(dir[len(root):]), true +} diff --git a/libgo/go/cmd/go/pkg_test.go b/libgo/go/cmd/go/pkg_test.go new file mode 100644 index 0000000000..06b9f0ac6e --- /dev/null +++ b/libgo/go/cmd/go/pkg_test.go @@ -0,0 +1,73 @@ +// 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 main + +import ( + "reflect" + "strings" + "testing" +) + +var foldDupTests = []struct { + list []string + f1, f2 string +}{ + {stringList("math/rand", "math/big"), "", ""}, + {stringList("math", "strings"), "", ""}, + {stringList("strings"), "", ""}, + {stringList("strings", "strings"), "strings", "strings"}, + {stringList("Rand", "rand", "math", "math/rand", "math/Rand"), "Rand", "rand"}, +} + +func TestFoldDup(t *testing.T) { + for _, tt := range foldDupTests { + f1, f2 := foldDup(tt.list) + if f1 != tt.f1 || f2 != tt.f2 { + t.Errorf("foldDup(%q) = %q, %q, want %q, %q", tt.list, f1, f2, tt.f1, tt.f2) + } + } +} + +var parseMetaGoImportsTests = []struct { + in string + out []metaImport +}{ + { + ``, + []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}}, + }, + { + ` + `, + []metaImport{ + {"foo/bar", "git", "https://github.com/rsc/foo/bar"}, + {"baz/quux", "git", "http://github.com/rsc/baz/quux"}, + }, + }, + { + ` + + `, + []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}}, + }, + { + ` + `, + []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}}, + }, +} + +func TestParseMetaGoImports(t *testing.T) { + for i, tt := range parseMetaGoImportsTests { + out, err := parseMetaGoImports(strings.NewReader(tt.in)) + if err != nil { + t.Errorf("test#%d: %v", i, err) + continue + } + if !reflect.DeepEqual(out, tt.out) { + t.Errorf("test#%d:\n\thave %q\n\twant %q", i, out, tt.out) + } + } +} diff --git a/libgo/go/cmd/go/run.go b/libgo/go/cmd/go/run.go new file mode 100644 index 0000000000..ef8aa95a35 --- /dev/null +++ b/libgo/go/cmd/go/run.go @@ -0,0 +1,143 @@ +// 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 main + +import ( + "fmt" + "os" + "os/exec" + "runtime" + "strings" +) + +var execCmd []string // -exec flag, for run and test + +func findExecCmd() []string { + if execCmd != nil { + return execCmd + } + execCmd = []string{} // avoid work the second time + if goos == runtime.GOOS && goarch == runtime.GOARCH { + return execCmd + } + path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", goos, goarch)) + if err == nil { + execCmd = []string{path} + } + return execCmd +} + +var cmdRun = &Command{ + UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]", + Short: "compile and run Go program", + Long: ` +Run compiles and runs the main package comprising the named Go source files. +A Go source file is defined to be a file ending in a literal ".go" suffix. + +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...'. +If the -exec flag is not given, GOOS or GOARCH is different from the system +default, and a program named go_$GOOS_$GOARCH_exec can be found +on the current search path, 'go run' invokes the binary using that program, +for example 'go_nacl_386_exec a.out arguments...'. This allows execution of +cross-compiled programs when a simulator or other execution method is +available. + +For more about build flags, see 'go help build'. + +See also: go build. + `, +} + +func init() { + cmdRun.Run = runRun // break init loop + + addBuildFlags(cmdRun) + cmdRun.Flag.Var((*stringsFlag)(&execCmd), "exec", "") +} + +func printStderr(args ...interface{}) (int, error) { + return fmt.Fprint(os.Stderr, args...) +} + +func runRun(cmd *Command, args []string) { + raceInit() + var b builder + b.init() + b.print = printStderr + i := 0 + for i < len(args) && strings.HasSuffix(args[i], ".go") { + i++ + } + files, cmdArgs := args[:i], args[i:] + if len(files) == 0 { + fatalf("go run: no go files listed") + } + for _, file := range files { + if strings.HasSuffix(file, "_test.go") { + // goFilesPackage is going to assign this to TestGoFiles. + // Reject since it won't be part of the build. + fatalf("go run: cannot run *_test.go files (%s)", file) + } + } + p := goFilesPackage(files) + if p.Error != nil { + fatalf("%s", p.Error) + } + p.omitDWARF = true + for _, err := range p.DepsErrors { + errorf("%s", err) + } + exitIfErrors() + if p.Name != "main" { + fatalf("go run: cannot run non-main package") + } + p.target = "" // must build - not up to date + var src string + if len(p.GoFiles) > 0 { + src = p.GoFiles[0] + } else if len(p.CgoFiles) > 0 { + src = p.CgoFiles[0] + } else { + // this case could only happen if the provided source uses cgo + // while cgo is disabled. + hint := "" + if !buildContext.CgoEnabled { + hint = " (cgo is disabled)" + } + fatalf("go run: no suitable source files%s", hint) + } + p.exeName = src[:len(src)-len(".go")] // name temporary executable for first go file + a1 := b.action(modeBuild, modeBuild, p) + a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}} + b.do(a) +} + +// runProgram is the action for running a binary that has already +// been compiled. We ignore exit status. +func (b *builder) runProgram(a *action) error { + cmdline := stringList(findExecCmd(), a.deps[0].target, a.args) + if buildN || buildX { + b.showcmd("", "%s", strings.Join(cmdline, " ")) + if buildN { + return nil + } + } + + runStdin(cmdline) + return nil +} + +// runStdin is like run, but connects Stdin. +func runStdin(cmdline []string) { + cmd := exec.Command(cmdline[0], cmdline[1:]...) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + startSigHandlers() + if err := cmd.Run(); err != nil { + errorf("%v", err) + } +} diff --git a/libgo/go/cmd/go/script b/libgo/go/cmd/go/script new file mode 100644 index 0000000000..340a7e824c --- /dev/null +++ b/libgo/go/cmd/go/script @@ -0,0 +1,23 @@ +#!/bin/sh + +x() { + echo '--- ' "$@" + "$@" + echo '---' + echo +} + +x go help +x go help build +x go help clean +x go help install +x go help fix +x go help fmt +x go help get +x go help list +x go help test +x go help version +x go help vet +x go help gopath +x go help importpath +x go help remote diff --git a/libgo/go/cmd/go/script.txt b/libgo/go/cmd/go/script.txt new file mode 100644 index 0000000000..a672146584 --- /dev/null +++ b/libgo/go/cmd/go/script.txt @@ -0,0 +1,352 @@ +--- go help +usage: go command [arguments] + +go manages Go source code. + +The commands are: + + build compile and install packages and dependencies + clean remove intermediate objects + fix run gofix on packages + fmt run gofmt -w on packages + get download and install packages and dependencies + install install packages and dependencies + list list packages + test test packages + version print Go version + vet run govet on packages + +Use "go help [command]" for more information about a command. + +Additional help topics: + + gopath GOPATH environment variable + importpath description of import paths + remote remote import path syntax + +Use "go help [topic]" for more information about that topic. + +--- + +--- go help build +usage: go build [-n] [-v] [importpath...] + +Build compiles the packages named by the import paths, +along with their dependencies, but it does not install the results. + +The -n flag prints the commands but does not run them. +The -v flag prints the commands. + +For more about import paths, see 'go help importpath'. + +See also: go install, go get, go clean. +--- + +--- go help clean +usage: go clean [-nuke] [importpath...] + +Clean removes intermediate object files generated during +the compilation of the packages named by the import paths, +but by default it does not remove the installed package binaries. + +The -nuke flag causes clean to remove the installed package binaries too. + +TODO: Clean does not clean dependencies of the packages. + +For more about import paths, see 'go help importpath'. +--- + +--- go help install +usage: go install [-n] [-v] [importpath...] + +Install compiles and installs the packages named by the import paths, +along with their dependencies. + +The -n flag prints the commands but does not run them. +The -v flag prints the commands. + +For more about import paths, see 'go help importpath'. + +See also: go build, go get, go clean. +--- + +--- go help fix +usage: go fix [importpath...] + +Fix runs the gofix command on the packages named by the import paths. + +For more about gofix, see 'godoc gofix'. +For more about import paths, see 'go help importpath'. + +To run gofix with specific options, run gofix itself. + +See also: go fmt, go vet. +--- + +--- go help fmt +usage: go fmt [importpath...] + +Fmt runs the command 'gofmt -w' on the packages named by the import paths. + +For more about gofmt, see 'godoc gofmt'. +For more about import paths, see 'go help importpath'. + +To run gofmt with specific options, run gofmt itself. + +See also: go fix, go vet. +--- + +--- go help get +usage: go get [importpath...] + +Get downloads and installs the packages named by the import paths, +along with their dependencies. + +After downloading the code, 'go get' looks for a tag beginning +with "go." that corresponds to the local Go version. +For Go "release.r58" it looks for a tag named "go.r58". +For "weekly.2011-06-03" it looks for "go.weekly.2011-06-03". +If the specific "go.X" tag is not found, it uses the latest earlier +version it can find. Otherwise, it uses the default version for +the version control system: HEAD for git, tip for Mercurial, +and so on. + +TODO: Explain versions better. + +For more about import paths, see 'go help importpath'. + +For more about how 'go get' finds source code to +download, see 'go help remote'. + +See also: go build, go install, go clean. +--- + +--- go help list +usage: go list [-f format] [-json] [importpath...] + +List lists the packages named by the import paths. + +The default output shows the package name and file system location: + + books /home/you/src/google-api-go-client.googlecode.com/hg/books/v1 + oauth /home/you/src/goauth2.googlecode.com/hg/oauth + sqlite /home/you/src/gosqlite.googlecode.com/hg/sqlite + +The -f flag specifies an alternate format for the list, +using the syntax of package template. The default output +is equivalent to -f '{{.Name}} {{.Dir}}' The struct +being passed to the template is: + + type Package struct { + Name string // package name + Doc string // package documentation string + GoFiles []string // names of Go source files in package + ImportPath string // import path denoting package + Imports []string // import paths used by this package + Deps []string // all (recursively) imported dependencies + Dir string // directory containing package sources + Version string // version of installed package + } + +The -json flag causes the package data to be printed in JSON format. + +For more about import paths, see 'go help importpath'. +--- + +--- go help test +usage: go test [importpath...] + +Test runs gotest to test the packages named by the import paths. +It prints a summary of the test results in the format: + + test archive/tar + FAIL archive/zip + test compress/gzip + ... + +followed by gotest output for each failed package. + +For more about import paths, see 'go help importpath'. + +See also: go build, go compile, go vet. +--- + +--- go help version +usage: go version + +Version prints the Go version, as reported by runtime.Version. +--- + +--- go help vet +usage: go vet [importpath...] + +Vet runs the govet command on the packages named by the import paths. + +For more about govet, see 'godoc govet'. +For more about import paths, see 'go help importpath'. + +To run govet with specific options, run govet itself. + +See also: go fmt, go fix. +--- + +--- go help gopath +The GOPATH environment variable lists places to look for Go code. +On Unix, the value is a colon-separated string. +On Windows, the value is a semicolon-separated string. +On Plan 9, the value is a list. + +GOPATH must be set to build and install packages outside the +standard Go tree. + +Each directory listed in GOPATH must have a prescribed structure: + +The src/ directory holds source code. The path below 'src' +determines the import path or executable name. + +The pkg/ directory holds installed package objects. +As in the Go tree, each target operating system and +architecture pair has its own subdirectory of pkg +(pkg/GOOS_GOARCH). + +If DIR is a directory listed in the GOPATH, a package with +source in DIR/src/foo/bar can be imported as "foo/bar" and +has its compiled form installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a". + +The bin/ directory holds compiled commands. +Each command is named for its source directory, but only +the final element, not the entire path. That is, the +command with source in DIR/src/foo/quux is installed into +DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped +so that you can add DIR/bin to your PATH to get at the +installed commands. + +Here's an example directory layout: + + GOPATH=/home/user/gocode + + /home/user/gocode/ + src/ + foo/ + bar/ (go code in package bar) + x.go + quux/ (go code in package main) + y.go + bin/ + quux (installed command) + pkg/ + linux_amd64/ + foo/ + bar.a (installed package object) + +Go searches each directory listed in GOPATH to find source code, +but new packages are always downloaded into the first directory +in the list. +--- + +--- go help importpath +Many commands apply to a set of packages named by import paths: + + go action [importpath...] + +An import path that is a rooted path or that begins with +a . or .. element is interpreted as a file system path and +denotes the package in that directory. + +Otherwise, the import path P denotes the package found in +the directory DIR/src/P for some DIR listed in the GOPATH +environment variable (see 'go help gopath'). + +If no import paths are given, the action applies to the +package in the current directory. + +The special import path "all" expands to all package directories +found in all the GOPATH trees. For example, 'go list all' +lists all the packages on the local system. + +An import path can also name a package to be downloaded from +a remote repository. Run 'go help remote' for details. + +Every package in a program must have a unique import path. +By convention, this is arranged by starting each path with a +unique prefix that belongs to you. For example, paths used +internally at Google all begin with 'google', and paths +denoting remote repositories begin with the path to the code, +such as 'project.googlecode.com/'. +--- + +--- go help remote +An import path (see 'go help importpath') denotes a package +stored in the local file system. Certain import paths also +describe how to obtain the source code for the package using +a revision control system. + +A few common code hosting sites have special syntax: + + BitBucket (Mercurial) + + import "bitbucket.org/user/project" + import "bitbucket.org/user/project/sub/directory" + + GitHub (Git) + + import "github.com/user/project" + import "github.com/user/project/sub/directory" + + Google Code Project Hosting (Git, Mercurial, Subversion) + + import "project.googlecode.com/git" + import "project.googlecode.com/git/sub/directory" + + import "project.googlecode.com/hg" + import "project.googlecode.com/hg/sub/directory" + + import "project.googlecode.com/svn/trunk" + import "project.googlecode.com/svn/trunk/sub/directory" + + Launchpad (Bazaar) + + import "launchpad.net/project" + import "launchpad.net/project/series" + import "launchpad.net/project/series/sub/directory" + + import "launchpad.net/~user/project/branch" + import "launchpad.net/~user/project/branch/sub/directory" + +For code hosted on other servers, an import path of the form + + repository.vcs/path + +specifies the given repository, with or without the .vcs suffix, +using the named version control system, and then the path inside +that repository. The supported version control systems are: + + Bazaar .bzr + Git .git + Mercurial .hg + Subversion .svn + +For example, + + import "example.org/user/foo.hg" + +denotes the root directory of the Mercurial repository at +example.org/user/foo or foo.hg, and + + import "example.org/repo.git/foo/bar" + +denotes the foo/bar directory of the Git repository at +example.com/repo or repo.git. + +When a version control system supports multiple protocols, +each is tried in turn when downloading. For example, a Git +download tries git://, then https://, then http://. + +New downloaded packages are written to the first directory +listed in the GOPATH environment variable (see 'go help gopath'). + +The go command attempts to download the version of the +package appropriate for the Go release being used. +Run 'go help install' for more. +--- + diff --git a/libgo/go/cmd/go/signal.go b/libgo/go/cmd/go/signal.go new file mode 100644 index 0000000000..e8ba0d3655 --- /dev/null +++ b/libgo/go/cmd/go/signal.go @@ -0,0 +1,31 @@ +// 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 ( + "os" + "os/signal" + "sync" +) + +// interrupted is closed, if go process is interrupted. +var interrupted = make(chan struct{}) + +// processSignals setups signal handler. +func processSignals() { + sig := make(chan os.Signal) + signal.Notify(sig, signalsToIgnore...) + go func() { + <-sig + close(interrupted) + }() +} + +var onceProcessSignals sync.Once + +// startSigHandlers start signal handlers. +func startSigHandlers() { + onceProcessSignals.Do(processSignals) +} diff --git a/libgo/go/cmd/go/signal_notunix.go b/libgo/go/cmd/go/signal_notunix.go new file mode 100644 index 0000000000..29aa9d8c20 --- /dev/null +++ b/libgo/go/cmd/go/signal_notunix.go @@ -0,0 +1,17 @@ +// 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. + +// +build plan9 windows + +package main + +import ( + "os" +) + +var signalsToIgnore = []os.Signal{os.Interrupt} + +// signalTrace is the signal to send to make a Go program +// crash with a stack trace. +var signalTrace os.Signal = nil diff --git a/libgo/go/cmd/go/signal_unix.go b/libgo/go/cmd/go/signal_unix.go new file mode 100644 index 0000000000..e86cd46523 --- /dev/null +++ b/libgo/go/cmd/go/signal_unix.go @@ -0,0 +1,18 @@ +// 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. + +// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris + +package main + +import ( + "os" + "syscall" +) + +var signalsToIgnore = []os.Signal{os.Interrupt, syscall.SIGQUIT} + +// signalTrace is the signal to send to make a Go program +// crash with a stack trace. +var signalTrace os.Signal = syscall.SIGQUIT diff --git a/libgo/go/cmd/go/tag_test.go b/libgo/go/cmd/go/tag_test.go new file mode 100644 index 0000000000..ffe218c7b6 --- /dev/null +++ b/libgo/go/cmd/go/tag_test.go @@ -0,0 +1,100 @@ +// 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 main + +import "testing" + +var selectTagTestTags = []string{ + "go.r58", + "go.r58.1", + "go.r59", + "go.r59.1", + "go.r61", + "go.r61.1", + "go.weekly.2010-01-02", + "go.weekly.2011-10-12", + "go.weekly.2011-10-12.1", + "go.weekly.2011-10-14", + "go.weekly.2011-11-01", + "go1", + "go1.0.1", + "go1.999", + "go1.9.2", + "go5", + + // these should be ignored: + "release.r59", + "release.r59.1", + "release", + "weekly.2011-10-12", + "weekly.2011-10-12.1", + "weekly", + "foo", + "bar", + "go.f00", + "go!r60", + "go.1999-01-01", + "go.2x", + "go.20000000000000", + "go.2.", + "go.2.0", + "go2x", + "go20000000000000", + "go2.", + "go2.0", +} + +var selectTagTests = []struct { + version string + selected string +}{ + /* + {"release.r57", ""}, + {"release.r58.2", "go.r58.1"}, + {"release.r59", "go.r59"}, + {"release.r59.1", "go.r59.1"}, + {"release.r60", "go.r59.1"}, + {"release.r60.1", "go.r59.1"}, + {"release.r61", "go.r61"}, + {"release.r66", "go.r61.1"}, + {"weekly.2010-01-01", ""}, + {"weekly.2010-01-02", "go.weekly.2010-01-02"}, + {"weekly.2010-01-02.1", "go.weekly.2010-01-02"}, + {"weekly.2010-01-03", "go.weekly.2010-01-02"}, + {"weekly.2011-10-12", "go.weekly.2011-10-12"}, + {"weekly.2011-10-12.1", "go.weekly.2011-10-12.1"}, + {"weekly.2011-10-13", "go.weekly.2011-10-12.1"}, + {"weekly.2011-10-14", "go.weekly.2011-10-14"}, + {"weekly.2011-10-14.1", "go.weekly.2011-10-14"}, + {"weekly.2011-11-01", "go.weekly.2011-11-01"}, + {"weekly.2014-01-01", "go.weekly.2011-11-01"}, + {"weekly.3000-01-01", "go.weekly.2011-11-01"}, + {"go1", "go1"}, + {"go1.1", "go1.0.1"}, + {"go1.998", "go1.9.2"}, + {"go1.1000", "go1.999"}, + {"go6", "go5"}, + + // faulty versions: + {"release.f00", ""}, + {"weekly.1999-01-01", ""}, + {"junk", ""}, + {"", ""}, + {"go2x", ""}, + {"go200000000000", ""}, + {"go2.", ""}, + {"go2.0", ""}, + */ + {"anything", "go1"}, +} + +func TestSelectTag(t *testing.T) { + for _, c := range selectTagTests { + selected := selectTag(c.version, selectTagTestTags) + if selected != c.selected { + t.Errorf("selectTag(%q) = %q, want %q", c.version, selected, c.selected) + } + } +} diff --git a/libgo/go/cmd/go/test.bash b/libgo/go/cmd/go/test.bash new file mode 100644 index 0000000000..0060ce2185 --- /dev/null +++ b/libgo/go/cmd/go/test.bash @@ -0,0 +1,820 @@ +#!/bin/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. + +set -e +go build -o testgo +go() { + echo TEST ERROR: ran go, not testgo: go "$@" >&2 + exit 2 +} + +started=false +TEST() { + if $started; then + stop + fi + echo TEST: "$@" + started=true + ok=true +} +stop() { + if ! $started; then + echo TEST ERROR: stop missing start >&2 + exit 2 + fi + started=false + if $ok; then + echo PASS + else + echo FAIL + allok=false + fi +} + +ok=true +allok=true + +unset GOBIN +unset GOPATH +unset GOROOT + +TEST 'file:line in error messages' +# Test that error messages have file:line information at beginning of +# the line. Also test issue 4917: that the error is on stderr. +d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX) +fn=$d/err.go +echo "package main" > $fn +echo 'import "bar"' >> $fn +./testgo run $fn 2>$d/err.out || true +if ! grep -q "^$fn:" $d/err.out; then + echo "missing file:line in error message" + cat $d/err.out + ok=false +fi +rm -r $d + +# Test local (./) imports. +testlocal() { + local="$1" + TEST local imports $2 '(easy)' + ./testgo build -o hello "testdata/$local/easy.go" + ./hello >hello.out + if ! grep -q '^easysub\.Hello' hello.out; then + echo "testdata/$local/easy.go did not generate expected output" + cat hello.out + ok=false + fi + + TEST local imports $2 '(easysub)' + ./testgo build -o hello "testdata/$local/easysub/main.go" + ./hello >hello.out + if ! grep -q '^easysub\.Hello' hello.out; then + echo "testdata/$local/easysub/main.go did not generate expected output" + cat hello.out + ok=false + fi + + TEST local imports $2 '(hard)' + ./testgo build -o hello "testdata/$local/hard.go" + ./hello >hello.out + if ! grep -q '^sub\.Hello' hello.out || ! grep -q '^subsub\.Hello' hello.out ; then + echo "testdata/$local/hard.go did not generate expected output" + cat hello.out + ok=false + fi + + rm -f hello.out hello + + # Test that go install x.go fails. + TEST local imports $2 '(go install should fail)' + if ./testgo install "testdata/$local/easy.go" >/dev/null 2>&1; then + echo "go install testdata/$local/easy.go succeeded" + ok=false + fi +} + +# Test local imports +testlocal local '' + +# Test local imports again, with bad characters in the directory name. +bad='#$%:, &()*;<=>?\^{}' +rm -rf "testdata/$bad" +cp -R testdata/local "testdata/$bad" +testlocal "$bad" 'with bad characters in path' +rm -rf "testdata/$bad" + +TEST error message for syntax error in test go file says FAIL +export GOPATH=$(pwd)/testdata +if ./testgo test syntaxerror 2>testdata/err; then + echo 'go test syntaxerror succeeded' + ok=false +elif ! grep FAIL testdata/err >/dev/null; then + echo 'go test did not say FAIL:' + cat testdata/err + ok=false +fi +rm -f ./testdata/err +unset GOPATH + +TEST wildcards do not look in useless directories +export GOPATH=$(pwd)/testdata +if ./testgo list ... >testdata/err 2>&1; then + echo "go list ... succeeded" + ok=false +elif ! grep badpkg testdata/err >/dev/null; then + echo "go list ... failure does not mention badpkg" + cat testdata/err + ok=false +elif ! ./testgo list m... >testdata/err 2>&1; then + echo "go list m... failed" + ok=false +fi +rm -rf ./testdata/err +unset GOPATH + +# Test tests with relative imports. +TEST relative imports '(go test)' +if ! ./testgo test ./testdata/testimport; then + echo "go test ./testdata/testimport failed" + ok=false +fi + +# Test installation with relative imports. +TEST relative imports '(go test -i)' +if ! ./testgo test -i ./testdata/testimport; then + echo "go test -i ./testdata/testimport failed" + ok=false +fi + +# Test tests with relative imports in packages synthesized +# from Go files named on the command line. +TEST relative imports in command-line package +if ! ./testgo test ./testdata/testimport/*.go; then + echo "go test ./testdata/testimport/*.go failed" + ok=false +fi + +TEST version control error message includes correct directory +export GOPATH=$(pwd)/testdata/shadow/root1 +if ./testgo get -u foo 2>testdata/err; then + echo "go get -u foo succeeded unexpectedly" + ok=false +elif ! grep testdata/shadow/root1/src/foo testdata/err >/dev/null; then + echo "go get -u error does not mention shadow/root1/src/foo:" + cat testdata/err + ok=false +fi +unset GOPATH + +TEST go install fails with no buildable files +export GOPATH=$(pwd)/testdata +export CGO_ENABLED=0 +if ./testgo install cgotest 2>testdata/err; then + echo "go install cgotest succeeded unexpectedly" +elif ! grep 'no buildable Go source files' testdata/err >/dev/null; then + echo "go install cgotest did not report 'no buildable Go source files'" + cat testdata/err + ok=false +fi +unset CGO_ENABLED +unset GOPATH + +# Test that without $GOBIN set, binaries get installed +# into the GOPATH bin directory. +TEST install into GOPATH +rm -rf testdata/bin +if ! GOPATH=$(pwd)/testdata ./testgo install go-cmd-test; then + echo "go install go-cmd-test failed" + ok=false +elif ! test -x testdata/bin/go-cmd-test; then + echo "go install go-cmd-test did not write to testdata/bin/go-cmd-test" + ok=false +fi + +TEST package main_test imports archive not binary +export GOBIN=$(pwd)/testdata/bin +mkdir -p $GOBIN +export GOPATH=$(pwd)/testdata +touch ./testdata/src/main_test/m.go +if ! ./testgo test main_test; then + echo "go test main_test failed without install" + ok=false +elif ! ./testgo install main_test; then + echo "go test main_test failed" + ok=false +elif [ "$(./testgo list -f '{{.Stale}}' main_test)" != false ]; then + echo "after go install, main listed as stale" + ok=false +elif ! ./testgo test main_test; then + echo "go test main_test failed after install" + ok=false +fi +rm -rf $GOBIN +unset GOBIN + +# And with $GOBIN set, binaries get installed to $GOBIN. +TEST install into GOBIN +if ! GOBIN=$(pwd)/testdata/bin1 GOPATH=$(pwd)/testdata ./testgo install go-cmd-test; then + echo "go install go-cmd-test failed" + ok=false +elif ! test -x testdata/bin1/go-cmd-test; then + echo "go install go-cmd-test did not write to testdata/bin1/go-cmd-test" + ok=false +fi + +# Without $GOBIN set, installing a program outside $GOPATH should fail +# (there is nowhere to install it). +TEST install without destination fails +if ./testgo install testdata/src/go-cmd-test/helloworld.go 2>testdata/err; then + echo "go install testdata/src/go-cmd-test/helloworld.go should have failed, did not" + ok=false +elif ! grep 'no install location for .go files listed on command line' testdata/err; then + echo "wrong error:" + cat testdata/err + ok=false +fi +rm -f testdata/err + +# With $GOBIN set, should install there. +TEST install to GOBIN '(command-line package)' +if ! GOBIN=$(pwd)/testdata/bin1 ./testgo install testdata/src/go-cmd-test/helloworld.go; then + echo "go install testdata/src/go-cmd-test/helloworld.go failed" + ok=false +elif ! test -x testdata/bin1/helloworld; then + echo "go install testdata/src/go-cmd-test/helloworld.go did not write testdata/bin1/helloworld" + ok=false +fi + +TEST godoc installs into GOBIN +d=$(mktemp -d -t testgoXXX) +export GOPATH=$d +mkdir $d/gobin +GOBIN=$d/gobin ./testgo get code.google.com/p/go.tools/cmd/godoc +if [ ! -x $d/gobin/godoc ]; then + echo did not install godoc to '$GOBIN' + GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' code.google.com/p/go.tools/cmd/godoc + ok=false +fi + +TEST godoc installs into GOROOT +GOROOT=$(./testgo env GOROOT) +rm -f $GOROOT/bin/godoc +./testgo install code.google.com/p/go.tools/cmd/godoc +if [ ! -x $GOROOT/bin/godoc ]; then + echo did not install godoc to '$GOROOT/bin' + ./testgo list -f 'Target: {{.Target}}' code.google.com/p/go.tools/cmd/godoc + ok=false +fi + +TEST cmd/fix installs into tool +GOOS=$(./testgo env GOOS) +GOARCH=$(./testgo env GOARCH) +rm -f $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix +./testgo install cmd/fix +if [ ! -x $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix ]; then + echo 'did not install cmd/fix to $GOROOT/pkg/tool' + GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix + ok=false +fi +rm -f $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix +GOBIN=$d/gobin ./testgo install cmd/fix +if [ ! -x $GOROOT/pkg/tool/${GOOS}_${GOARCH}/fix ]; then + echo 'did not install cmd/fix to $GOROOT/pkg/tool with $GOBIN set' + GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' cmd/fix + ok=false +fi + +TEST gopath program installs into GOBIN +mkdir $d/src/progname +echo 'package main; func main() {}' >$d/src/progname/p.go +GOBIN=$d/gobin ./testgo install progname +if [ ! -x $d/gobin/progname ]; then + echo 'did not install progname to $GOBIN/progname' + ./testgo list -f 'Target: {{.Target}}' cmd/api + ok=false +fi +rm -f $d/gobin/progname $d/bin/progname + +TEST gopath program installs into GOPATH/bin +./testgo install progname +if [ ! -x $d/bin/progname ]; then + echo 'did not install progname to $GOPATH/bin/progname' + ./testgo list -f 'Target: {{.Target}}' progname + ok=false +fi + +unset GOPATH +rm -rf $d + +# Reject relative paths in GOPATH. +TEST reject relative paths in GOPATH '(command-line package)' +if GOPATH=. ./testgo build testdata/src/go-cmd-test/helloworld.go; then + echo 'GOPATH="." go build should have failed, did not' + ok=false +fi + +TEST reject relative paths in GOPATH +if GOPATH=:$(pwd)/testdata:. ./testgo build go-cmd-test; then + echo 'GOPATH=":$(pwd)/testdata:." go build should have failed, did not' + ok=false +fi + +# issue 4104 +TEST go test with package listed multiple times +if [ $(./testgo test fmt fmt fmt fmt fmt | wc -l) -ne 1 ] ; then + echo 'go test fmt fmt fmt fmt fmt tested the same package multiple times' + ok=false +fi + +# ensure that output of 'go list' is consistent between runs +TEST go list is consistent +./testgo list std > test_std.list +if ! ./testgo list std | cmp -s test_std.list - ; then + echo "go list std ordering is inconsistent" + ok=false +fi +rm -f test_std.list + +# issue 4096. Validate the output of unsuccessful go install foo/quxx +TEST unsuccessful go install should mention missing package +if [ $(./testgo install 'foo/quxx' 2>&1 | grep -c 'cannot find package "foo/quxx" in any of') -ne 1 ] ; then + echo 'go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of' + ok=false +fi +# test GOROOT search failure is reported +TEST GOROOT search failure reporting +if [ $(./testgo install 'foo/quxx' 2>&1 | egrep -c 'foo/quxx \(from \$GOROOT\)$') -ne 1 ] ; then + echo 'go install foo/quxx expected error: .*foo/quxx (from $GOROOT)' + ok=false +fi +# test multiple GOPATH entries are reported separately +TEST multiple GOPATH entries reported separately +if [ $(GOPATH=$(pwd)/testdata/a:$(pwd)/testdata/b ./testgo install 'foo/quxx' 2>&1 | egrep -c 'testdata/./src/foo/quxx') -ne 2 ] ; then + echo 'go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)\n.*testdata/b/src/foo/quxx' + ok=false +fi +# test (from $GOPATH) annotation is reported for the first GOPATH entry +TEST mention GOPATH in first GOPATH entry +if [ $(GOPATH=$(pwd)/testdata/a:$(pwd)/testdata/b ./testgo install 'foo/quxx' 2>&1 | egrep -c 'testdata/a/src/foo/quxx \(from \$GOPATH\)$') -ne 1 ] ; then + echo 'go install foo/quxx expected error: .*testdata/a/src/foo/quxx (from $GOPATH)' + ok=false +fi +# but not on the second +TEST but not the second entry +if [ $(GOPATH=$(pwd)/testdata/a:$(pwd)/testdata/b ./testgo install 'foo/quxx' 2>&1 | egrep -c 'testdata/b/src/foo/quxx$') -ne 1 ] ; then + echo 'go install foo/quxx expected error: .*testdata/b/src/foo/quxx' + ok=false +fi +# test missing GOPATH is reported +TEST missing GOPATH is reported +if [ $(GOPATH= ./testgo install 'foo/quxx' 2>&1 | egrep -c '\(\$GOPATH not set\)$') -ne 1 ] ; then + echo 'go install foo/quxx expected error: ($GOPATH not set)' + ok=false +fi + +# issue 4186. go get cannot be used to download packages to $GOROOT +# Test that without GOPATH set, go get should fail +TEST without GOPATH, go get fails +d=$(mktemp -d -t testgoXXX) +mkdir -p $d/src/pkg +if GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then + echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with $GOPATH unset' + ok=false +fi +rm -rf $d + +# Test that with GOPATH=$GOROOT, go get should fail +TEST with GOPATH=GOROOT, go get fails +d=$(mktemp -d -t testgoXXX) +mkdir -p $d/src/pkg +if GOPATH=$d GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then + echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT' + ok=false +fi +rm -rf $d + +TEST ldflags arguments with spaces '(issue 3941)' +d=$(mktemp -d -t testgoXXX) +cat >$d/main.go<hello.out +if ! grep -q '^hello world' hello.out; then + echo "ldflags -X main.extern 'hello world' failed. Output:" + cat hello.out + ok=false +fi +rm -rf $d hello.out + +TEST go test -cpuprofile leaves binary behind +./testgo test -cpuprofile strings.prof strings || ok=false +if [ ! -x strings.test ]; then + echo "go test -cpuprofile did not create strings.test" + ok=false +fi +rm -f strings.prof strings.test + +TEST symlinks do not confuse go list '(issue 4568)' +old=$(pwd) +tmp=$(cd /tmp && pwd -P) +d=$(TMPDIR=$tmp mktemp -d -t testgoXXX) +mkdir -p $d/src +( + ln -s $d $d/src/dir1 + cd $d/src + echo package p >dir1/p.go + export GOPATH=$d + if [ "$($old/testgo list -f '{{.Root}}' dir1)" != "$d" ]; then + echo Confused by symlinks. + echo "Package in current directory $(pwd) should have Root $d" + env|grep WD + $old/testgo list -json . dir1 + touch $d/failed + fi +) +if [ -f $d/failed ]; then + ok=false +fi +rm -rf $d + +TEST 'install with tags (issue 4515)' +d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX) +mkdir -p $d/src/example/a $d/src/example/b $d/bin +cat >$d/src/example/a/main.go <$d/src/example/b/main.go <$d/src/example/a/a.go <$d/src/example/a/pkg/pkg.go <$d/src/example/a/Pkg/pkg.go <$d/out; then + echo go list example/a should have failed, did not. + ok=false +elif ! grep "case-insensitive import collision" $d/out >/dev/null; then + echo go list example/a did not report import collision. + ok=false +fi +cat >$d/src/example/b/file.go <$d/src/example/b/FILE.go <$d/out; then + echo go list example/b should have failed, did not. + ok=false +elif ! grep "case-insensitive file name collision" $d/out >/dev/null; then + echo go list example/b did not report file name collision. + ok=false +fi + +TEST go get cover +./testgo get code.google.com/p/go.tools/cmd/cover || ok=false + +unset GOPATH +rm -rf $d + +TEST shadowing logic +export GOPATH=$(pwd)/testdata/shadow/root1:$(pwd)/testdata/shadow/root2 + +# The math in root1 is not "math" because the standard math is. +cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root1/src/math) +if [ "$cdir" != "(_$(pwd)/testdata/shadow/root1/src/math) ($GOROOT/src/pkg/math)" ]; then + echo shadowed math is not shadowed: "$cdir" + ok=false +fi + +# The foo in root1 is "foo". +cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root1/src/foo) +if [ "$cdir" != "(foo) ()" ]; then + echo unshadowed foo is shadowed: "$cdir" + ok=false +fi + +# The foo in root2 is not "foo" because the foo in root1 got there first. +cdir=$(./testgo list -f '({{.ImportPath}}) ({{.ConflictDir}})' ./testdata/shadow/root2/src/foo) +if [ "$cdir" != "(_$(pwd)/testdata/shadow/root2/src/foo) ($(pwd)/testdata/shadow/root1/src/foo)" ]; then + echo shadowed foo is not shadowed: "$cdir" + ok=false +fi + +# The error for go install should mention the conflicting directory. +err=$(! ./testgo install ./testdata/shadow/root2/src/foo 2>&1) +if [ "$err" != "go install: no install location for $(pwd)/testdata/shadow/root2/src/foo: hidden by $(pwd)/testdata/shadow/root1/src/foo" ]; then + echo wrong shadowed install error: "$err" + ok=false +fi + +# Only succeeds if source order is preserved. +TEST source file name order preserved +./testgo test testdata/example[12]_test.go || ok=false + +# Check that coverage analysis works at all. +# Don't worry about the exact numbers but require not 0.0%. +checkcoverage() { + if grep '[^0-9]0\.0%' testdata/cover.txt >/dev/null; then + echo 'some coverage results are 0.0%' + ok=false + fi + cat testdata/cover.txt + rm -f testdata/cover.txt +} + +TEST coverage runs +./testgo test -short -coverpkg=strings strings regexp >testdata/cover.txt 2>&1 || ok=false +./testgo test -short -cover strings math regexp >>testdata/cover.txt 2>&1 || ok=false +checkcoverage + +# Check that coverage analysis uses set mode. +TEST coverage uses set mode +if ./testgo test -short -cover encoding/binary -coverprofile=testdata/cover.out >testdata/cover.txt 2>&1; then + if ! grep -q 'mode: set' testdata/cover.out; then + ok=false + fi + checkcoverage +else + ok=false +fi +rm -f testdata/cover.out testdata/cover.txt + +TEST coverage uses atomic mode for -race. +if ./testgo test -short -race -cover encoding/binary -coverprofile=testdata/cover.out >testdata/cover.txt 2>&1; then + if ! grep -q 'mode: atomic' testdata/cover.out; then + ok=false + fi + checkcoverage +else + ok=false +fi +rm -f testdata/cover.out + +TEST coverage uses actual setting to override even for -race. +if ./testgo test -short -race -cover encoding/binary -covermode=count -coverprofile=testdata/cover.out >testdata/cover.txt 2>&1; then + if ! grep -q 'mode: count' testdata/cover.out; then + ok=false + fi + checkcoverage +else + ok=false +fi +rm -f testdata/cover.out + +TEST coverage with cgo +d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX) +./testgo test -short -cover ./testdata/cgocover >testdata/cover.txt 2>&1 || ok=false +checkcoverage + +TEST cgo depends on syscall +rm -rf $GOROOT/pkg/*_race +d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX) +export GOPATH=$d +mkdir -p $d/src/foo +echo ' +package foo +//#include +import "C" +' >$d/src/foo/foo.go +./testgo build -race foo || ok=false +rm -rf $d +unset GOPATH + +TEST cgo shows full path names +d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX) +export GOPATH=$d +mkdir -p $d/src/x/y/dirname +echo ' +package foo +import "C" +func f() { +' >$d/src/x/y/dirname/foo.go +if ./testgo build x/y/dirname >$d/err 2>&1; then + echo build succeeded unexpectedly. + ok=false +elif ! grep x/y/dirname $d/err >/dev/null; then + echo error did not use full path. + cat $d/err + ok=false +fi +rm -rf $d +unset GOPATH + +TEST 'cgo handles -Wl,$ORIGIN' +d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX) +export GOPATH=$d +mkdir -p $d/src/origin +echo ' +package origin +// #cgo !darwin LDFLAGS: -Wl,-rpath -Wl,$ORIGIN +// void f(void) {} +import "C" + +func f() { C.f() } +' >$d/src/origin/origin.go +if ! ./testgo build origin; then + echo build failed + ok=false +fi +rm -rf $d +unset GOPATH + +TEST 'Issue 6480: "go test -c -test.bench=XXX fmt" should not hang' +if ! ./testgo test -c -test.bench=XXX fmt; then + echo build test failed + ok=false +fi +rm -f fmt.test + +TEST 'Issue 7573: cmd/cgo: undefined reference when linking a C-library using gccgo' +d=$(mktemp -d -t testgoXXX) +export GOPATH=$d +mkdir -p $d/src/cgoref +ldflags="-L alibpath -lalib" +echo " +package main +// #cgo LDFLAGS: $ldflags +// void f(void) {} +import \"C\" + +func main() { C.f() } +" >$d/src/cgoref/cgoref.go +go_cmds="$(./testgo build -n -compiler gccgo cgoref 2>&1 1>/dev/null)" +ldflags_count="$(echo "$go_cmds" | egrep -c "^gccgo.*$(echo $ldflags | sed -e 's/-/\\-/g')" || true)" +if [ "$ldflags_count" -lt 1 ]; then + echo "No Go-inline "#cgo LDFLAGS:" (\"$ldflags\") passed to gccgo linking stage." + ok=false +fi +rm -rf $d +unset ldflags_count +unset go_cmds +unset ldflags +unset GOPATH + +TEST list template can use context function +if ! ./testgo list -f "GOARCH: {{context.GOARCH}}"; then + echo unable to use context in list template + ok=false +fi + +TEST 'Issue 7108: cmd/go: "go test" should fail if package does not build' +export GOPATH=$(pwd)/testdata +if ./testgo test notest >/dev/null 2>&1; then + echo 'go test notest succeeded, but should fail' + ok=false +fi +unset GOPATH + +TEST 'Issue 6844: cmd/go: go test -a foo does not rebuild regexp' +if ! ./testgo test -x -a -c testdata/dep_test.go 2>deplist; then + echo "go test -x -a -c testdata/dep_test.go failed" + ok=false +elif ! grep -q regexp deplist; then + echo "go test -x -a -c testdata/dep_test.go did not rebuild regexp" + ok=false +fi +rm -f deplist +rm -f deps.test + +TEST list template can use context function +if ! ./testgo list -f "GOARCH: {{context.GOARCH}}"; then + echo unable to use context in list template + ok=false +fi + +TEST build -i installs dependencies +d=$(TMPDIR=/var/tmp mktemp -d -t testgoXXX) +export GOPATH=$d +mkdir -p $d/src/x/y/foo $d/src/x/y/bar +echo ' +package foo +func F() {} +' >$d/src/x/y/foo/foo.go +echo ' +package bar +import "x/y/foo" +func F() { foo.F() } +' >$d/src/x/y/bar/bar.go +if ! ./testgo build -v -i x/y/bar &> $d/err; then + echo build -i failed + cat $d/err + ok=false +elif ! grep x/y/foo $d/err >/dev/null; then + echo first build -i did not build x/y/foo + cat $d/err + ok=false +fi +if ! ./testgo build -v -i x/y/bar &> $d/err; then + echo second build -i failed + cat $d/err + ok=false +elif grep x/y/foo $d/err >/dev/null; then + echo second build -i built x/y/foo + cat $d/err + ok=false +fi +rm -rf $d +unset GOPATH + +TEST 'go build in test-only directory fails with a good error' +if ./testgo build ./testdata/testonly 2>testdata/err.out; then + echo "go build ./testdata/testonly succeeded, should have failed" + ok=false +elif ! grep 'no buildable Go' testdata/err.out >/dev/null; then + echo "go build ./testdata/testonly produced unexpected error:" + cat testdata/err.out + ok=false +fi +rm -f testdata/err.out + +TEST 'go test detects test-only import cycles' +export GOPATH=$(pwd)/testdata +if ./testgo test -c testcycle/p3 2>testdata/err.out; then + echo "go test testcycle/p3 succeeded, should have failed" + ok=false +elif ! grep 'import cycle not allowed in test' testdata/err.out >/dev/null; then + echo "go test testcycle/p3 produced unexpected error:" + cat testdata/err.out + ok=false +fi +rm -f testdata/err.out +unset GOPATH + +TEST 'go test foo_test.go works' +if ! ./testgo test testdata/standalone_test.go; then + echo "go test testdata/standalone_test.go failed" + ok=false +fi + +TEST 'go test xtestonly works' +export GOPATH=$(pwd)/testdata +./testgo clean -i xtestonly +if ! ./testgo test xtestonly >/dev/null; then + echo "go test xtestonly failed" + ok=false +fi +unset GOPATH + + +# clean up +if $started; then stop; fi +rm -rf testdata/bin testdata/bin1 +rm -f testgo + +if $allok; then + echo PASS +else + echo FAIL + exit 1 +fi diff --git a/libgo/go/cmd/go/test.go b/libgo/go/cmd/go/test.go new file mode 100644 index 0000000000..5cf7aaf071 --- /dev/null +++ b/libgo/go/cmd/go/test.go @@ -0,0 +1,1412 @@ +// 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 main + +import ( + "bytes" + "errors" + "fmt" + "go/ast" + "go/build" + "go/doc" + "go/parser" + "go/token" + "log" + "os" + "os/exec" + "path" + "path/filepath" + "regexp" + "runtime" + "sort" + "strings" + "text/template" + "time" + "unicode" + "unicode/utf8" +) + +// Break init loop. +func init() { + cmdTest.Run = runTest +} + +var cmdTest = &Command{ + CustomFlags: true, + UsageLine: "test [-c] [-i] [build and test flags] [packages] [flags for test binary]", + Short: "test packages", + Long: ` +'Go test' automates testing the packages named by the import paths. +It prints a summary of the test results in the format: + + ok archive/tar 0.011s + FAIL archive/zip 0.022s + ok compress/gzip 0.033s + ... + +followed by detailed output for each failed package. + +'Go test' recompiles each package along with any files with names matching +the file pattern "*_test.go". +Files whose names begin with "_" (including "_test.go") or "." are ignored. +These additional files can contain test functions, benchmark functions, and +example functions. See 'go help testfunc' for more. +Each listed package causes the execution of a separate test binary. + +Test files that declare a package with the suffix "_test" will be compiled as a +separate package, and then linked and run with the main test binary. + +By default, go test needs no arguments. It compiles and tests the package +with source in the current directory, including tests, and runs the tests. + +The package is built in a temporary directory so it does not interfere with the +non-test installation. + +In addition to the build flags, the flags handled by 'go test' itself are: + + -c + Compile the test binary to pkg.test but do not run it + (where pkg is the last element of the package's import path). + The file name can be changed with the -o flag. + + -exec xprog + Run the test binary using xprog. The behavior is the same as + in 'go run'. See 'go help run' for details. + + -i + Install packages that are dependencies of the test. + Do not run the test. + + -o file + Compile the test binary to the named file. + The test still runs (unless -c or -i is specified). + + +The test binary also accepts flags that control execution of the test; these +flags are also accessible by 'go test'. See 'go help testflag' for details. + +If the test binary needs any other flags, they should be presented after the +package names. The go tool treats as a flag the first argument that begins with +a minus sign that it does not recognize itself; that argument and all subsequent +arguments are passed as arguments to the test binary. + +For more about build flags, see 'go help build'. +For more about specifying packages, see 'go help packages'. + +See also: go build, go vet. +`, +} + +var helpTestflag = &Command{ + UsageLine: "testflag", + Short: "description of testing flags", + Long: ` +The 'go test' command takes both flags that apply to 'go test' itself +and flags that apply to the resulting test binary. + +Several of the flags control profiling and write an execution profile +suitable for "go tool pprof"; run "go tool pprof help" for more +information. The --alloc_space, --alloc_objects, and --show_bytes +options of pprof control how the information is presented. + +The following flags are recognized by the 'go test' command and +control the execution of any test: + + -bench regexp + Run benchmarks matching the regular expression. + By default, no benchmarks run. To run all benchmarks, + use '-bench .' or '-bench=.'. + + -benchmem + Print memory allocation statistics for benchmarks. + + -benchtime t + Run enough iterations of each benchmark to take t, specified + as a time.Duration (for example, -benchtime 1h30s). + The default is 1 second (1s). + + -blockprofile block.out + Write a goroutine blocking profile to the specified file + when all tests are complete. + Writes test binary as -c would. + + -blockprofilerate n + Control the detail provided in goroutine blocking profiles by + calling runtime.SetBlockProfileRate with n. + See 'godoc runtime SetBlockProfileRate'. + The profiler aims to sample, on average, one blocking event every + n nanoseconds the program spends blocked. By default, + if -test.blockprofile is set without this flag, all blocking events + are recorded, equivalent to -test.blockprofilerate=1. + + -cover + Enable coverage analysis. + + -covermode set,count,atomic + Set the mode for coverage analysis for the package[s] + being tested. The default is "set" unless -race is enabled, + in which case it is "atomic". + The values: + set: bool: does this statement run? + count: int: how many times does this statement run? + atomic: int: count, but correct in multithreaded tests; + significantly more expensive. + Sets -cover. + + -coverpkg pkg1,pkg2,pkg3 + Apply coverage analysis in each test to the given list of packages. + The default is for each test to analyze only the package being tested. + Packages are specified as import paths. + Sets -cover. + + -coverprofile cover.out + Write a coverage profile to the file after all tests have passed. + Sets -cover. + + -cpu 1,2,4 + Specify a list of GOMAXPROCS values for which the tests or + benchmarks should be executed. The default is the current value + of GOMAXPROCS. + + -cpuprofile cpu.out + Write a CPU profile to the specified file before exiting. + Writes test binary as -c would. + + -memprofile mem.out + Write a memory profile to the file after all tests have passed. + Writes test binary as -c would. + + -memprofilerate n + Enable more precise (and expensive) memory profiles by setting + runtime.MemProfileRate. See 'godoc runtime MemProfileRate'. + To profile all memory allocations, use -test.memprofilerate=1 + and pass --alloc_space flag to the pprof tool. + + -outputdir directory + Place output files from profiling in the specified directory, + by default the directory in which "go test" is running. + + -parallel n + Allow parallel execution of test functions that call t.Parallel. + The value of this flag is the maximum number of tests to run + simultaneously; by default, it is set to the value of GOMAXPROCS. + + -run regexp + Run only those tests and examples matching the regular + expression. + + -short + Tell long-running tests to shorten their run time. + It is off by default but set during all.bash so that installing + the Go tree can run a sanity check but not spend time running + exhaustive tests. + + -timeout t + If a test runs longer than t, panic. + + -v + Verbose output: log all tests as they are run. Also print all + text from Log and Logf calls even if the test succeeds. + +The test binary, called pkg.test where pkg is the name of the +directory containing the package sources, can be invoked directly +after building it with 'go test -c'. When invoking the test binary +directly, each of the standard flag names must be prefixed with 'test.', +as in -test.run=TestMyFunc or -test.v. + +When running 'go test', flags not listed above are passed through +unaltered. For instance, the command + + go test -x -v -cpuprofile=prof.out -dir=testdata -update + +will compile the test binary and then run it as + + pkg.test -test.v -test.cpuprofile=prof.out -dir=testdata -update + +The test flags that generate profiles (other than for coverage) also +leave the test binary in pkg.test for use when analyzing the profiles. + +Flags not recognized by 'go test' must be placed after any specified packages. +`, +} + +var helpTestfunc = &Command{ + UsageLine: "testfunc", + Short: "description of testing functions", + Long: ` +The 'go test' command expects to find test, benchmark, and example functions +in the "*_test.go" files corresponding to the package under test. + +A test function is one named TestXXX (where XXX is any alphanumeric string +not starting with a lower case letter) and should have the signature, + + func TestXXX(t *testing.T) { ... } + +A benchmark function is one named BenchmarkXXX and should have the signature, + + func BenchmarkXXX(b *testing.B) { ... } + +An example function is similar to a test function but, instead of using +*testing.T to report success or failure, prints output to os.Stdout. +That output is compared against the function's "Output:" comment, which +must be the last comment in the function body (see example below). An +example with no such comment, or with no text after "Output:" is compiled +but not executed. + +Godoc displays the body of ExampleXXX to demonstrate the use +of the function, constant, or variable XXX. An example of a method M with +receiver type T or *T is named ExampleT_M. There may be multiple examples +for a given function, constant, or variable, distinguished by a trailing _xxx, +where xxx is a suffix not beginning with an upper case letter. + +Here is an example of an example: + + func ExamplePrintln() { + Println("The output of\nthis example.") + // Output: The output of + // this example. + } + +The entire test file is presented as the example when it contains a single +example function, at least one other function, type, variable, or constant +declaration, and no test or benchmark functions. + +See the documentation of the testing package for more information. +`, +} + +var ( + testC bool // -c flag + testCover bool // -cover flag + testCoverMode string // -covermode flag + testCoverPaths []string // -coverpkg flag + testCoverPkgs []*Package // -coverpkg flag + testO string // -o flag + testProfile bool // some profiling flag + testNeedBinary bool // profile needs to keep binary around + testV bool // -v flag + testTimeout string // -timeout flag + testArgs []string + testBench bool + testStreamOutput bool // show output as it is generated + testShowPass bool // show passing output + + testKillTimeout = 10 * time.Minute +) + +var testMainDeps = map[string]bool{ + // Dependencies for testmain. + "testing": true, + "regexp": true, + "os": true, +} + +func runTest(cmd *Command, args []string) { + var pkgArgs []string + pkgArgs, testArgs = testFlags(args) + + findExecCmd() // initialize cached result + + raceInit() + pkgs := packagesForBuild(pkgArgs) + if len(pkgs) == 0 { + fatalf("no packages to test") + } + + if testC && len(pkgs) != 1 { + fatalf("cannot use -c flag with multiple packages") + } + if testO != "" && len(pkgs) != 1 { + fatalf("cannot use -o flag with multiple packages") + } + if testProfile && len(pkgs) != 1 { + fatalf("cannot use test profile flag with multiple packages") + } + + // If a test timeout was given and is parseable, set our kill timeout + // to that timeout plus one minute. This is a backup alarm in case + // the test wedges with a goroutine spinning and its background + // timer does not get a chance to fire. + if dt, err := time.ParseDuration(testTimeout); err == nil && dt > 0 { + testKillTimeout = dt + 1*time.Minute + } + + // show passing test output (after buffering) with -v flag. + // must buffer because tests are running in parallel, and + // otherwise the output will get mixed. + testShowPass = testV + + // stream test output (no buffering) when no package has + // been given on the command line (implicit current directory) + // or when benchmarking. + // Also stream if we're showing output anyway with a + // single package under test. In that case, streaming the + // output produces the same result as not streaming, + // just more immediately. + testStreamOutput = len(pkgArgs) == 0 || testBench || + (len(pkgs) <= 1 && testShowPass) + + var b builder + b.init() + + if buildI { + buildV = testV + + deps := make(map[string]bool) + for dep := range testMainDeps { + deps[dep] = true + } + + for _, p := range pkgs { + // Dependencies for each test. + for _, path := range p.Imports { + deps[path] = true + } + for _, path := range p.TestImports { + deps[path] = true + } + for _, path := range p.XTestImports { + deps[path] = true + } + } + + // translate C to runtime/cgo + if deps["C"] { + delete(deps, "C") + deps["runtime/cgo"] = true + if buildContext.GOOS == runtime.GOOS && buildContext.GOARCH == runtime.GOARCH { + deps["cmd/cgo"] = true + } + } + // Ignore pseudo-packages. + delete(deps, "unsafe") + + all := []string{} + for path := range deps { + if !build.IsLocalImport(path) { + all = append(all, path) + } + } + sort.Strings(all) + + a := &action{} + for _, p := range packagesForBuild(all) { + if !reqStdPkgSrc && p.Standard { + continue + } + a.deps = append(a.deps, b.action(modeInstall, modeInstall, p)) + } + b.do(a) + if !testC || a.failed { + return + } + b.init() + } + + var builds, runs, prints []*action + + if testCoverPaths != nil { + // Load packages that were asked about for coverage. + // packagesForBuild exits if the packages cannot be loaded. + testCoverPkgs = packagesForBuild(testCoverPaths) + + // Warn about -coverpkg arguments that are not actually used. + used := make(map[string]bool) + for _, p := range pkgs { + used[p.ImportPath] = true + for _, dep := range p.Deps { + used[dep] = true + } + } + for _, p := range testCoverPkgs { + if !used[p.ImportPath] { + log.Printf("warning: no packages being tested depend on %s", p.ImportPath) + } + } + + // Mark all the coverage packages for rebuilding with coverage. + for _, p := range testCoverPkgs { + p.Stale = true // rebuild + p.fake = true // do not warn about rebuild + p.coverMode = testCoverMode + var coverFiles []string + coverFiles = append(coverFiles, p.GoFiles...) + coverFiles = append(coverFiles, p.CgoFiles...) + coverFiles = append(coverFiles, p.TestGoFiles...) + p.coverVars = declareCoverVars(p.ImportPath, coverFiles...) + } + } + + // Prepare build + run + print actions for all packages being tested. + for _, p := range pkgs { + buildTest, runTest, printTest, err := b.test(p) + if err != nil { + str := err.Error() + if strings.HasPrefix(str, "\n") { + str = str[1:] + } + failed := fmt.Sprintf("FAIL\t%s [setup failed]\n", p.ImportPath) + + if p.ImportPath != "" { + errorf("# %s\n%s\n%s", p.ImportPath, str, failed) + } else { + errorf("%s\n%s", str, failed) + } + continue + } + builds = append(builds, buildTest) + runs = append(runs, runTest) + prints = append(prints, printTest) + } + + // Ultimately the goal is to print the output. + root := &action{deps: prints} + + // Force the printing of results to happen in order, + // one at a time. + for i, a := range prints { + if i > 0 { + a.deps = append(a.deps, prints[i-1]) + } + } + + // Force benchmarks to run in serial. + if !testC && testBench { + // The first run must wait for all builds. + // Later runs must wait for the previous run's print. + for i, run := range runs { + if i == 0 { + run.deps = append(run.deps, builds...) + } else { + run.deps = append(run.deps, prints[i-1]) + } + } + } + + // If we are building any out-of-date packages other + // than those under test, warn. + okBuild := map[*Package]bool{} + for _, p := range pkgs { + okBuild[p] = true + } + warned := false + for _, a := range actionList(root) { + if a.p == nil || okBuild[a.p] { + continue + } + okBuild[a.p] = true // warn at most once + + // Don't warn about packages being rebuilt because of + // things like coverage analysis. + for _, p1 := range a.p.imports { + if p1.fake { + a.p.fake = true + } + } + + if a.f != nil && !okBuild[a.p] && !a.p.fake && !a.p.local { + if !warned { + fmt.Fprintf(os.Stderr, "warning: building out-of-date packages:\n") + warned = true + } + fmt.Fprintf(os.Stderr, "\t%s\n", a.p.ImportPath) + } + } + if warned { + args := strings.Join(pkgArgs, " ") + if args != "" { + args = " " + args + } + extraOpts := "" + if buildRace { + extraOpts = "-race " + } + fmt.Fprintf(os.Stderr, "installing these packages with 'go test %s-i%s' will speed future tests.\n\n", extraOpts, args) + } + + b.do(root) +} + +func contains(x []string, s string) bool { + for _, t := range x { + if t == s { + return true + } + } + return false +} + +var windowsBadWords = []string{ + "install", + "patch", + "setup", + "update", +} + +func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, err error) { + if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 { + build := b.action(modeBuild, modeBuild, p) + run := &action{p: p, deps: []*action{build}} + print := &action{f: (*builder).notest, p: p, deps: []*action{run}} + return build, run, print, nil + } + + // Build Package structs describing: + // ptest - package + test files + // pxtest - package of external test files + // pmain - pkg.test binary + var ptest, pxtest, pmain *Package + + var imports, ximports []*Package + var stk importStack + stk.push(p.ImportPath + " (test)") + for _, path := range p.TestImports { + p1 := loadImport(path, p.Dir, &stk, p.build.TestImportPos[path]) + if !reqStdPkgSrc && p1.Standard { + continue + } + if p1.Error != nil { + return nil, nil, nil, p1.Error + } + if contains(p1.Deps, p.ImportPath) { + // Same error that loadPackage returns (via reusePackage) in pkg.go. + // Can't change that code, because that code is only for loading the + // non-test copy of a package. + err := &PackageError{ + ImportStack: testImportStack(stk[0], p1, p.ImportPath), + Err: "import cycle not allowed in test", + isImportCycle: true, + } + return nil, nil, nil, err + } + imports = append(imports, p1) + } + stk.pop() + stk.push(p.ImportPath + "_test") + pxtestNeedsPtest := false + for _, path := range p.XTestImports { + if path == p.ImportPath { + pxtestNeedsPtest = true + continue + } + p1 := loadImport(path, p.Dir, &stk, p.build.XTestImportPos[path]) + if !reqStdPkgSrc && p1.Standard { + continue + } + if p1.Error != nil { + return nil, nil, nil, p1.Error + } + ximports = append(ximports, p1) + } + stk.pop() + + // Use last element of import path, not package name. + // They differ when package name is "main". + // But if the import path is "command-line-arguments", + // like it is during 'go run', use the package name. + var elem string + if p.ImportPath == "command-line-arguments" { + elem = p.Name + } else { + _, elem = path.Split(p.ImportPath) + } + testBinary := elem + ".test" + + // The ptest package needs to be importable under the + // same import path that p has, but we cannot put it in + // the usual place in the temporary tree, because then + // other tests will see it as the real package. + // Instead we make a _test directory under the import path + // and then repeat the import path there. We tell the + // compiler and linker to look in that _test directory first. + // + // That is, if the package under test is unicode/utf8, + // then the normal place to write the package archive is + // $WORK/unicode/utf8.a, but we write the test package archive to + // $WORK/unicode/utf8/_test/unicode/utf8.a. + // We write the external test package archive to + // $WORK/unicode/utf8/_test/unicode/utf8_test.a. + testDir := filepath.Join(b.work, filepath.FromSlash(p.ImportPath+"/_test")) + ptestObj := buildToolchain.pkgpath(testDir, p) + + // Create the directory for the .a files. + ptestDir, _ := filepath.Split(ptestObj) + if err := b.mkdir(ptestDir); err != nil { + return nil, nil, nil, err + } + + // Should we apply coverage analysis locally, + // only for this package and only for this test? + // Yes, if -cover is on but -coverpkg has not specified + // a list of packages for global coverage. + localCover := testCover && testCoverPaths == nil + + // Test package. + if len(p.TestGoFiles) > 0 || localCover || p.Name == "main" { + ptest = new(Package) + *ptest = *p + ptest.GoFiles = nil + ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...) + ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...) + ptest.target = "" + ptest.Imports = stringList(p.Imports, p.TestImports) + ptest.imports = append(append([]*Package{}, p.imports...), imports...) + ptest.pkgdir = testDir + ptest.fake = true + ptest.forceLibrary = true + ptest.Stale = true + ptest.build = new(build.Package) + *ptest.build = *p.build + m := map[string][]token.Position{} + for k, v := range p.build.ImportPos { + m[k] = append(m[k], v...) + } + for k, v := range p.build.TestImportPos { + m[k] = append(m[k], v...) + } + ptest.build.ImportPos = m + + if localCover { + ptest.coverMode = testCoverMode + var coverFiles []string + coverFiles = append(coverFiles, ptest.GoFiles...) + coverFiles = append(coverFiles, ptest.CgoFiles...) + ptest.coverVars = declareCoverVars(ptest.ImportPath, coverFiles...) + } + } else { + ptest = p + } + + // External test package. + if len(p.XTestGoFiles) > 0 { + pxtest = &Package{ + Name: p.Name + "_test", + ImportPath: p.ImportPath + "_test", + localPrefix: p.localPrefix, + Root: p.Root, + Dir: p.Dir, + GoFiles: p.XTestGoFiles, + Imports: p.XTestImports, + build: &build.Package{ + ImportPos: p.build.XTestImportPos, + }, + imports: ximports, + pkgdir: testDir, + fake: true, + external: true, + Stale: true, + } + if pxtestNeedsPtest { + pxtest.imports = append(pxtest.imports, ptest) + } + } + + // Action for building pkg.test. + pmain = &Package{ + Name: "main", + Dir: testDir, + GoFiles: []string{"_testmain.go"}, + ImportPath: "testmain", + Root: p.Root, + build: &build.Package{Name: "main"}, + pkgdir: testDir, + fake: true, + Stale: true, + omitDWARF: !testC && !testNeedBinary, + } + + // The generated main also imports testing, regexp, and os. + stk.push("testmain") + for dep := range testMainDeps { + if dep == ptest.ImportPath { + pmain.imports = append(pmain.imports, ptest) + } else { + p1 := loadImport(dep, "", &stk, nil) + if !reqStdPkgSrc && p1.Standard { + continue + } + if p1.Error != nil { + return nil, nil, nil, p1.Error + } + pmain.imports = append(pmain.imports, p1) + } + } + + if testCoverPkgs != nil { + // Add imports, but avoid duplicates. + seen := map[*Package]bool{p: true, ptest: true} + for _, p1 := range pmain.imports { + seen[p1] = true + } + for _, p1 := range testCoverPkgs { + if !seen[p1] { + seen[p1] = true + pmain.imports = append(pmain.imports, p1) + } + } + } + + // Do initial scan for metadata needed for writing _testmain.go + // Use that metadata to update the list of imports for package main. + // The list of imports is used by recompileForTest and by the loop + // afterward that gathers t.Cover information. + t, err := loadTestFuncs(ptest) + if err != nil { + return nil, nil, nil, err + } + if len(ptest.GoFiles) > 0 { + pmain.imports = append(pmain.imports, ptest) + t.ImportTest = true + } + if pxtest != nil { + pmain.imports = append(pmain.imports, pxtest) + t.ImportXtest = true + } + + if ptest != p && localCover { + // We have made modifications to the package p being tested + // and are rebuilding p (as ptest), writing it to the testDir tree. + // Arrange to rebuild, writing to that same tree, all packages q + // such that the test depends on q, and q depends on p. + // This makes sure that q sees the modifications to p. + // Strictly speaking, the rebuild is only necessary if the + // modifications to p change its export metadata, but + // determining that is a bit tricky, so we rebuild always. + // + // This will cause extra compilation, so for now we only do it + // when testCover is set. The conditions are more general, though, + // and we may find that we need to do it always in the future. + recompileForTest(pmain, p, ptest, testDir) + } + + for _, cp := range pmain.imports { + if len(cp.coverVars) > 0 { + t.Cover = append(t.Cover, coverInfo{cp, cp.coverVars}) + } + } + + // writeTestmain writes _testmain.go. This must happen after recompileForTest, + // because recompileForTest modifies XXX. + if err := writeTestmain(filepath.Join(testDir, "_testmain.go"), t); err != nil { + return nil, nil, nil, err + } + + computeStale(pmain) + + if ptest != p { + a := b.action(modeBuild, modeBuild, ptest) + a.objdir = testDir + string(filepath.Separator) + "_obj_test" + string(filepath.Separator) + a.objpkg = ptestObj + a.target = ptestObj + a.link = false + } + + if pxtest != nil { + a := b.action(modeBuild, modeBuild, pxtest) + a.objdir = testDir + string(filepath.Separator) + "_obj_xtest" + string(filepath.Separator) + a.objpkg = buildToolchain.pkgpath(testDir, pxtest) + a.target = a.objpkg + } + + a := b.action(modeBuild, modeBuild, pmain) + a.objdir = testDir + string(filepath.Separator) + a.objpkg = filepath.Join(testDir, "main.a") + a.target = filepath.Join(testDir, testBinary) + exeSuffix + if goos == "windows" { + // There are many reserved words on Windows that, + // if used in the name of an executable, cause Windows + // to try to ask for extra permissions. + // The word list includes setup, install, update, and patch, + // but it does not appear to be defined anywhere. + // We have run into this trying to run the + // go.codereview/patch tests. + // For package names containing those words, use test.test.exe + // instead of pkgname.test.exe. + // Note that this file name is only used in the Go command's + // temporary directory. If the -c or other flags are + // given, the code below will still use pkgname.test.exe. + // There are two user-visible effects of this change. + // First, you can actually run 'go test' in directories that + // have names that Windows thinks are installer-like, + // without getting a dialog box asking for more permissions. + // Second, in the Windows process listing during go test, + // the test shows up as test.test.exe, not pkgname.test.exe. + // That second one is a drawback, but it seems a small + // price to pay for the test running at all. + // If maintaining the list of bad words is too onerous, + // we could just do this always on Windows. + for _, bad := range windowsBadWords { + if strings.Contains(testBinary, bad) { + a.target = filepath.Join(testDir, "test.test") + exeSuffix + break + } + } + } + buildAction = a + + if testC || testNeedBinary { + // -c or profiling flag: create action to copy binary to ./test.out. + target := filepath.Join(cwd, testBinary+exeSuffix) + if testO != "" { + target = testO + if !filepath.IsAbs(target) { + target = filepath.Join(cwd, target) + } + } + buildAction = &action{ + f: (*builder).install, + deps: []*action{buildAction}, + p: pmain, + target: target, + } + runAction = buildAction // make sure runAction != nil even if not running test + } + if testC { + printAction = &action{p: p, deps: []*action{runAction}} // nop + } else { + // run test + runAction = &action{ + f: (*builder).runTest, + deps: []*action{buildAction}, + p: p, + ignoreFail: true, + } + cleanAction := &action{ + f: (*builder).cleanTest, + deps: []*action{runAction}, + p: p, + } + printAction = &action{ + f: (*builder).printTest, + deps: []*action{cleanAction}, + p: p, + } + } + + return buildAction, runAction, printAction, nil +} + +func testImportStack(top string, p *Package, target string) []string { + stk := []string{top, p.ImportPath} +Search: + for p.ImportPath != target { + for _, p1 := range p.imports { + if p1.ImportPath == target || contains(p1.Deps, target) { + stk = append(stk, p1.ImportPath) + p = p1 + continue Search + } + } + // Can't happen, but in case it does... + stk = append(stk, "") + break + } + return stk +} + +func recompileForTest(pmain, preal, ptest *Package, testDir string) { + // The "test copy" of preal is ptest. + // For each package that depends on preal, make a "test copy" + // that depends on ptest. And so on, up the dependency tree. + testCopy := map[*Package]*Package{preal: ptest} + for _, p := range packageList([]*Package{pmain}) { + // Copy on write. + didSplit := false + split := func() { + if didSplit { + return + } + didSplit = true + if p.pkgdir != testDir { + p1 := new(Package) + testCopy[p] = p1 + *p1 = *p + p1.imports = make([]*Package, len(p.imports)) + copy(p1.imports, p.imports) + p = p1 + p.pkgdir = testDir + p.target = "" + p.fake = true + p.Stale = true + } + } + + // Update p.deps and p.imports to use at test copies. + for i, dep := range p.deps { + if p1 := testCopy[dep]; p1 != nil && p1 != dep { + split() + p.deps[i] = p1 + } + } + for i, imp := range p.imports { + if p1 := testCopy[imp]; p1 != nil && p1 != imp { + split() + p.imports[i] = p1 + } + } + } +} + +var coverIndex = 0 + +// isTestFile reports whether the source file is a set of tests and should therefore +// be excluded from coverage analysis. +func isTestFile(file string) bool { + // We don't cover tests, only the code they test. + return strings.HasSuffix(file, "_test.go") +} + +// declareCoverVars attaches the required cover variables names +// to the files, to be used when annotating the files. +func declareCoverVars(importPath string, files ...string) map[string]*CoverVar { + coverVars := make(map[string]*CoverVar) + for _, file := range files { + if isTestFile(file) { + continue + } + coverVars[file] = &CoverVar{ + File: filepath.Join(importPath, file), + Var: fmt.Sprintf("GoCover_%d", coverIndex), + } + coverIndex++ + } + return coverVars +} + +// runTest is the action for running a test binary. +func (b *builder) runTest(a *action) error { + args := stringList(findExecCmd(), a.deps[0].target, testArgs) + a.testOutput = new(bytes.Buffer) + + if buildN || buildX { + b.showcmd("", "%s", strings.Join(args, " ")) + if buildN { + return nil + } + } + + if a.failed { + // We were unable to build the binary. + a.failed = false + fmt.Fprintf(a.testOutput, "FAIL\t%s [build failed]\n", a.p.ImportPath) + setExitStatus(1) + return nil + } + + cmd := exec.Command(args[0], args[1:]...) + cmd.Dir = a.p.Dir + cmd.Env = envForDir(cmd.Dir) + var buf bytes.Buffer + if testStreamOutput { + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + } else { + cmd.Stdout = &buf + cmd.Stderr = &buf + } + + // If there are any local SWIG dependencies, we want to load + // the shared library from the build directory. + if a.p.usesSwig() { + env := cmd.Env + found := false + prefix := "LD_LIBRARY_PATH=" + for i, v := range env { + if strings.HasPrefix(v, prefix) { + env[i] = v + ":." + found = true + break + } + } + if !found { + env = append(env, "LD_LIBRARY_PATH=.") + } + cmd.Env = env + } + + t0 := time.Now() + err := cmd.Start() + + // This is a last-ditch deadline to detect and + // stop wedged test binaries, to keep the builders + // running. + if err == nil { + tick := time.NewTimer(testKillTimeout) + startSigHandlers() + done := make(chan error) + go func() { + done <- cmd.Wait() + }() + Outer: + select { + case err = <-done: + // ok + case <-tick.C: + if signalTrace != nil { + // Send a quit signal in the hope that the program will print + // a stack trace and exit. Give it five seconds before resorting + // to Kill. + cmd.Process.Signal(signalTrace) + select { + case err = <-done: + fmt.Fprintf(&buf, "*** Test killed with %v: ran too long (%v).\n", signalTrace, testKillTimeout) + break Outer + case <-time.After(5 * time.Second): + } + } + cmd.Process.Kill() + err = <-done + fmt.Fprintf(&buf, "*** Test killed: ran too long (%v).\n", testKillTimeout) + } + tick.Stop() + } + out := buf.Bytes() + t := fmt.Sprintf("%.3fs", time.Since(t0).Seconds()) + if err == nil { + if testShowPass { + a.testOutput.Write(out) + } + fmt.Fprintf(a.testOutput, "ok \t%s\t%s%s\n", a.p.ImportPath, t, coveragePercentage(out)) + return nil + } + + setExitStatus(1) + if len(out) > 0 { + a.testOutput.Write(out) + // assume printing the test binary's exit status is superfluous + } else { + fmt.Fprintf(a.testOutput, "%s\n", err) + } + fmt.Fprintf(a.testOutput, "FAIL\t%s\t%s\n", a.p.ImportPath, t) + + return nil +} + +// coveragePercentage returns the coverage results (if enabled) for the +// test. It uncovers the data by scanning the output from the test run. +func coveragePercentage(out []byte) string { + if !testCover { + return "" + } + // The string looks like + // test coverage for encoding/binary: 79.9% of statements + // Extract the piece from the percentage to the end of the line. + re := regexp.MustCompile(`coverage: (.*)\n`) + matches := re.FindSubmatch(out) + if matches == nil { + // Probably running "go test -cover" not "go test -cover fmt". + // The coverage output will appear in the output directly. + return "" + } + return fmt.Sprintf("\tcoverage: %s", matches[1]) +} + +// cleanTest is the action for cleaning up after a test. +func (b *builder) cleanTest(a *action) error { + if buildWork { + return nil + } + run := a.deps[0] + testDir := filepath.Join(b.work, filepath.FromSlash(run.p.ImportPath+"/_test")) + os.RemoveAll(testDir) + return nil +} + +// printTest is the action for printing a test result. +func (b *builder) printTest(a *action) error { + clean := a.deps[0] + run := clean.deps[0] + os.Stdout.Write(run.testOutput.Bytes()) + run.testOutput = nil + return nil +} + +// notest is the action for testing a package with no test files. +func (b *builder) notest(a *action) error { + fmt.Printf("? \t%s\t[no test files]\n", a.p.ImportPath) + return nil +} + +// isTestMain tells whether fn is a TestMain(m *testing.M) function. +func isTestMain(fn *ast.FuncDecl) bool { + if fn.Name.String() != "TestMain" || + fn.Type.Results != nil && len(fn.Type.Results.List) > 0 || + fn.Type.Params == nil || + len(fn.Type.Params.List) != 1 || + len(fn.Type.Params.List[0].Names) > 1 { + return false + } + ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr) + if !ok { + return false + } + // We can't easily check that the type is *testing.M + // because we don't know how testing has been imported, + // but at least check that it's *M or *something.M. + if name, ok := ptr.X.(*ast.Ident); ok && name.Name == "M" { + return true + } + if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == "M" { + return true + } + return false +} + +// isTest tells whether name looks like a test (or benchmark, according to prefix). +// It is a Test (say) if there is a character after Test that is not a lower-case letter. +// We don't want TesticularCancer. +func isTest(name, prefix string) bool { + if !strings.HasPrefix(name, prefix) { + return false + } + if len(name) == len(prefix) { // "Test" is ok + return true + } + rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) + return !unicode.IsLower(rune) +} + +type coverInfo struct { + Package *Package + Vars map[string]*CoverVar +} + +// loadTestFuncs returns the testFuncs describing the tests that will be run. +func loadTestFuncs(ptest *Package) (*testFuncs, error) { + t := &testFuncs{ + Package: ptest, + } + for _, file := range ptest.TestGoFiles { + if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); err != nil { + return nil, err + } + } + for _, file := range ptest.XTestGoFiles { + if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); err != nil { + return nil, err + } + } + return t, nil +} + +// writeTestmain writes the _testmain.go file for t to the file named out. +func writeTestmain(out string, t *testFuncs) error { + f, err := os.Create(out) + if err != nil { + return err + } + defer f.Close() + + if err := testmainTmpl.Execute(f, t); err != nil { + return err + } + + return nil +} + +type testFuncs struct { + Tests []testFunc + Benchmarks []testFunc + Examples []testFunc + TestMain *testFunc + Package *Package + ImportTest bool + NeedTest bool + ImportXtest bool + NeedXtest bool + Cover []coverInfo +} + +func (t *testFuncs) CoverMode() string { + return testCoverMode +} + +func (t *testFuncs) CoverEnabled() bool { + return testCover +} + +// Covered returns a string describing which packages are being tested for coverage. +// If the covered package is the same as the tested package, it returns the empty string. +// Otherwise it is a comma-separated human-readable list of packages beginning with +// " in", ready for use in the coverage message. +func (t *testFuncs) Covered() string { + if testCoverPaths == nil { + return "" + } + return " in " + strings.Join(testCoverPaths, ", ") +} + +// Tested returns the name of the package being tested. +func (t *testFuncs) Tested() string { + return t.Package.Name +} + +type testFunc struct { + Package string // imported package name (_test or _xtest) + Name string // function name + Output string // output, for examples +} + +var testFileSet = token.NewFileSet() + +func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error { + f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments) + if err != nil { + return expandScanner(err) + } + for _, d := range f.Decls { + n, ok := d.(*ast.FuncDecl) + if !ok { + continue + } + if n.Recv != nil { + continue + } + name := n.Name.String() + switch { + case isTestMain(n): + if t.TestMain != nil { + return errors.New("multiple definitions of TestMain") + } + t.TestMain = &testFunc{pkg, name, ""} + *doImport, *seen = true, true + case isTest(name, "Test"): + t.Tests = append(t.Tests, testFunc{pkg, name, ""}) + *doImport, *seen = true, true + case isTest(name, "Benchmark"): + t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, ""}) + *doImport, *seen = true, true + } + } + ex := doc.Examples(f) + sort.Sort(byOrder(ex)) + for _, e := range ex { + *doImport = true // import test file whether executed or not + if e.Output == "" && !e.EmptyOutput { + // Don't run examples with no output. + continue + } + t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output}) + *seen = true + } + return nil +} + +type byOrder []*doc.Example + +func (x byOrder) Len() int { return len(x) } +func (x byOrder) Swap(i, j int) { x[i], x[j] = x[j], x[i] } +func (x byOrder) Less(i, j int) bool { return x[i].Order < x[j].Order } + +var testmainTmpl = template.Must(template.New("main").Parse(` +package main + +import ( +{{if not .TestMain}} + "os" +{{end}} + "regexp" + "testing" + +{{if .ImportTest}} + {{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}} +{{end}} +{{if .ImportXtest}} + {{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}} +{{end}} +{{range $i, $p := .Cover}} + _cover{{$i}} {{$p.Package.ImportPath | printf "%q"}} +{{end}} +) + +var tests = []testing.InternalTest{ +{{range .Tests}} + {"{{.Name}}", {{.Package}}.{{.Name}}}, +{{end}} +} + +var benchmarks = []testing.InternalBenchmark{ +{{range .Benchmarks}} + {"{{.Name}}", {{.Package}}.{{.Name}}}, +{{end}} +} + +var examples = []testing.InternalExample{ +{{range .Examples}} + {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}}, +{{end}} +} + +var matchPat string +var matchRe *regexp.Regexp + +func matchString(pat, str string) (result bool, err error) { + if matchRe == nil || matchPat != pat { + matchPat = pat + matchRe, err = regexp.Compile(matchPat) + if err != nil { + return + } + } + return matchRe.MatchString(str), nil +} + +{{if .CoverEnabled}} + +// Only updated by init functions, so no need for atomicity. +var ( + coverCounters = make(map[string][]uint32) + coverBlocks = make(map[string][]testing.CoverBlock) +) + +func init() { + {{range $i, $p := .Cover}} + {{range $file, $cover := $p.Vars}} + coverRegisterFile({{printf "%q" $cover.File}}, _cover{{$i}}.{{$cover.Var}}.Count[:], _cover{{$i}}.{{$cover.Var}}.Pos[:], _cover{{$i}}.{{$cover.Var}}.NumStmt[:]) + {{end}} + {{end}} +} + +func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts []uint16) { + if 3*len(counter) != len(pos) || len(counter) != len(numStmts) { + panic("coverage: mismatched sizes") + } + if coverCounters[fileName] != nil { + // Already registered. + return + } + coverCounters[fileName] = counter + block := make([]testing.CoverBlock, len(counter)) + for i := range counter { + block[i] = testing.CoverBlock{ + Line0: pos[3*i+0], + Col0: uint16(pos[3*i+2]), + Line1: pos[3*i+1], + Col1: uint16(pos[3*i+2]>>16), + Stmts: numStmts[i], + } + } + coverBlocks[fileName] = block +} +{{end}} + +func main() { +{{if .CoverEnabled}} + testing.RegisterCover(testing.Cover{ + Mode: {{printf "%q" .CoverMode}}, + Counters: coverCounters, + Blocks: coverBlocks, + CoveredPackages: {{printf "%q" .Covered}}, + }) +{{end}} + m := testing.MainStart(matchString, tests, benchmarks, examples) +{{with .TestMain}} + {{.Package}}.{{.Name}}(m) +{{else}} + os.Exit(m.Run()) +{{end}} +} + +`)) diff --git a/libgo/go/cmd/go/testdata/cgocover/p.go b/libgo/go/cmd/go/testdata/cgocover/p.go new file mode 100644 index 0000000000..a6a3891cd4 --- /dev/null +++ b/libgo/go/cmd/go/testdata/cgocover/p.go @@ -0,0 +1,19 @@ +package p + +/* +void +f(void) +{ +} +*/ +import "C" + +var b bool + +func F() { + if b { + for { + } + } + C.f() +} diff --git a/libgo/go/cmd/go/testdata/cgocover/p_test.go b/libgo/go/cmd/go/testdata/cgocover/p_test.go new file mode 100644 index 0000000000..a8f057e358 --- /dev/null +++ b/libgo/go/cmd/go/testdata/cgocover/p_test.go @@ -0,0 +1,7 @@ +package p + +import "testing" + +func TestF(t *testing.T) { + F() +} diff --git a/libgo/go/cmd/go/testdata/dep_test.go b/libgo/go/cmd/go/testdata/dep_test.go new file mode 100644 index 0000000000..0c53ac4f96 --- /dev/null +++ b/libgo/go/cmd/go/testdata/dep_test.go @@ -0,0 +1,7 @@ +// 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 deps + +import _ "testing" diff --git a/libgo/go/cmd/go/testdata/example1_test.go b/libgo/go/cmd/go/testdata/example1_test.go new file mode 100644 index 0000000000..ec7092e972 --- /dev/null +++ b/libgo/go/cmd/go/testdata/example1_test.go @@ -0,0 +1,23 @@ +// 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/example2_test.go b/libgo/go/cmd/go/testdata/example2_test.go new file mode 100644 index 0000000000..1e0e80b80f --- /dev/null +++ b/libgo/go/cmd/go/testdata/example2_test.go @@ -0,0 +1,21 @@ +// 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/generate/test1.go b/libgo/go/cmd/go/testdata/generate/test1.go new file mode 100644 index 0000000000..1f05734f04 --- /dev/null +++ b/libgo/go/cmd/go/testdata/generate/test1.go @@ -0,0 +1,13 @@ +// 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 diff --git a/libgo/go/cmd/go/testdata/generate/test2.go b/libgo/go/cmd/go/testdata/generate/test2.go new file mode 100644 index 0000000000..ef1a3d9515 --- /dev/null +++ b/libgo/go/cmd/go/testdata/generate/test2.go @@ -0,0 +1,10 @@ +// 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 diff --git a/libgo/go/cmd/go/testdata/generate/test3.go b/libgo/go/cmd/go/testdata/generate/test3.go new file mode 100644 index 0000000000..41ffb7ea87 --- /dev/null +++ b/libgo/go/cmd/go/testdata/generate/test3.go @@ -0,0 +1,9 @@ +// 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 $GOPACKAGE xyz$GOPACKAGE/$GOFILE/123 + +package p diff --git a/libgo/go/cmd/go/testdata/importcom/bad.go b/libgo/go/cmd/go/testdata/importcom/bad.go new file mode 100644 index 0000000000..e104c2e992 --- /dev/null +++ b/libgo/go/cmd/go/testdata/importcom/bad.go @@ -0,0 +1,3 @@ +package p + +import "bad" diff --git a/libgo/go/cmd/go/testdata/importcom/conflict.go b/libgo/go/cmd/go/testdata/importcom/conflict.go new file mode 100644 index 0000000000..995556c511 --- /dev/null +++ b/libgo/go/cmd/go/testdata/importcom/conflict.go @@ -0,0 +1,3 @@ +package p + +import "conflict" diff --git a/libgo/go/cmd/go/testdata/importcom/src/bad/bad.go b/libgo/go/cmd/go/testdata/importcom/src/bad/bad.go new file mode 100644 index 0000000000..bc51fd3fde --- /dev/null +++ b/libgo/go/cmd/go/testdata/importcom/src/bad/bad.go @@ -0,0 +1 @@ +package bad // import diff --git a/libgo/go/cmd/go/testdata/importcom/src/conflict/a.go b/libgo/go/cmd/go/testdata/importcom/src/conflict/a.go new file mode 100644 index 0000000000..2d67703511 --- /dev/null +++ b/libgo/go/cmd/go/testdata/importcom/src/conflict/a.go @@ -0,0 +1 @@ +package conflict // import "a" diff --git a/libgo/go/cmd/go/testdata/importcom/src/conflict/b.go b/libgo/go/cmd/go/testdata/importcom/src/conflict/b.go new file mode 100644 index 0000000000..8fcfb3c8bd --- /dev/null +++ b/libgo/go/cmd/go/testdata/importcom/src/conflict/b.go @@ -0,0 +1 @@ +package conflict /* import "b" */ diff --git a/libgo/go/cmd/go/testdata/importcom/src/works/x/x.go b/libgo/go/cmd/go/testdata/importcom/src/works/x/x.go new file mode 100644 index 0000000000..044c6eca80 --- /dev/null +++ b/libgo/go/cmd/go/testdata/importcom/src/works/x/x.go @@ -0,0 +1 @@ +package x // import "works/x" diff --git a/libgo/go/cmd/go/testdata/importcom/src/works/x/x1.go b/libgo/go/cmd/go/testdata/importcom/src/works/x/x1.go new file mode 100644 index 0000000000..2449b29df5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/importcom/src/works/x/x1.go @@ -0,0 +1 @@ +package x // important! not an import comment diff --git a/libgo/go/cmd/go/testdata/importcom/src/wrongplace/x.go b/libgo/go/cmd/go/testdata/importcom/src/wrongplace/x.go new file mode 100644 index 0000000000..b89849da78 --- /dev/null +++ b/libgo/go/cmd/go/testdata/importcom/src/wrongplace/x.go @@ -0,0 +1 @@ +package x // import "my/x" diff --git a/libgo/go/cmd/go/testdata/importcom/works.go b/libgo/go/cmd/go/testdata/importcom/works.go new file mode 100644 index 0000000000..31b55d08a3 --- /dev/null +++ b/libgo/go/cmd/go/testdata/importcom/works.go @@ -0,0 +1,3 @@ +package p + +import _ "works/x" diff --git a/libgo/go/cmd/go/testdata/importcom/wrongplace.go b/libgo/go/cmd/go/testdata/importcom/wrongplace.go new file mode 100644 index 0000000000..e2535e01ae --- /dev/null +++ b/libgo/go/cmd/go/testdata/importcom/wrongplace.go @@ -0,0 +1,3 @@ +package p + +import "wrongplace" diff --git a/libgo/go/cmd/go/testdata/local/easy.go b/libgo/go/cmd/go/testdata/local/easy.go new file mode 100644 index 0000000000..4eeb517da1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/local/easy.go @@ -0,0 +1,7 @@ +package main + +import "./easysub" + +func main() { + easysub.Hello() +} diff --git a/libgo/go/cmd/go/testdata/local/easysub/easysub.go b/libgo/go/cmd/go/testdata/local/easysub/easysub.go new file mode 100644 index 0000000000..07040daee5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/local/easysub/easysub.go @@ -0,0 +1,7 @@ +package easysub + +import "fmt" + +func Hello() { + fmt.Println("easysub.Hello") +} diff --git a/libgo/go/cmd/go/testdata/local/easysub/main.go b/libgo/go/cmd/go/testdata/local/easysub/main.go new file mode 100644 index 0000000000..6c30b52362 --- /dev/null +++ b/libgo/go/cmd/go/testdata/local/easysub/main.go @@ -0,0 +1,9 @@ +// +build ignore + +package main + +import "." + +func main() { + easysub.Hello() +} diff --git a/libgo/go/cmd/go/testdata/local/hard.go b/libgo/go/cmd/go/testdata/local/hard.go new file mode 100644 index 0000000000..2ffac3fd73 --- /dev/null +++ b/libgo/go/cmd/go/testdata/local/hard.go @@ -0,0 +1,7 @@ +package main + +import "./sub" + +func main() { + sub.Hello() +} diff --git a/libgo/go/cmd/go/testdata/local/sub/sub.go b/libgo/go/cmd/go/testdata/local/sub/sub.go new file mode 100644 index 0000000000..d5dbf6d5fa --- /dev/null +++ b/libgo/go/cmd/go/testdata/local/sub/sub.go @@ -0,0 +1,12 @@ +package sub + +import ( + "fmt" + + subsub "./sub" +) + +func Hello() { + fmt.Println("sub.Hello") + subsub.Hello() +} diff --git a/libgo/go/cmd/go/testdata/local/sub/sub/subsub.go b/libgo/go/cmd/go/testdata/local/sub/sub/subsub.go new file mode 100644 index 0000000000..4cc72233e1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/local/sub/sub/subsub.go @@ -0,0 +1,7 @@ +package subsub + +import "fmt" + +func Hello() { + fmt.Println("subsub.Hello") +} diff --git a/libgo/go/cmd/go/testdata/norunexample/example_test.go b/libgo/go/cmd/go/testdata/norunexample/example_test.go new file mode 100644 index 0000000000..e158305a6c --- /dev/null +++ b/libgo/go/cmd/go/testdata/norunexample/example_test.go @@ -0,0 +1,11 @@ +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. +} diff --git a/libgo/go/cmd/go/testdata/norunexample/test_test.go b/libgo/go/cmd/go/testdata/norunexample/test_test.go new file mode 100644 index 0000000000..d2e919838f --- /dev/null +++ b/libgo/go/cmd/go/testdata/norunexample/test_test.go @@ -0,0 +1,10 @@ +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/shadow/root1/src/foo/foo.go b/libgo/go/cmd/go/testdata/shadow/root1/src/foo/foo.go new file mode 100644 index 0000000000..f52652b1ba --- /dev/null +++ b/libgo/go/cmd/go/testdata/shadow/root1/src/foo/foo.go @@ -0,0 +1 @@ +package foo diff --git a/libgo/go/cmd/go/testdata/shadow/root1/src/math/math.go b/libgo/go/cmd/go/testdata/shadow/root1/src/math/math.go new file mode 100644 index 0000000000..c91c24e967 --- /dev/null +++ b/libgo/go/cmd/go/testdata/shadow/root1/src/math/math.go @@ -0,0 +1 @@ +package math diff --git a/libgo/go/cmd/go/testdata/shadow/root2/src/foo/foo.go b/libgo/go/cmd/go/testdata/shadow/root2/src/foo/foo.go new file mode 100644 index 0000000000..f52652b1ba --- /dev/null +++ b/libgo/go/cmd/go/testdata/shadow/root2/src/foo/foo.go @@ -0,0 +1 @@ +package foo diff --git a/libgo/go/cmd/go/testdata/src/badc/x.go b/libgo/go/cmd/go/testdata/src/badc/x.go new file mode 100644 index 0000000000..bfa1de28bd --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/badc/x.go @@ -0,0 +1 @@ +package badc diff --git a/libgo/go/cmd/go/testdata/src/badpkg/x.go b/libgo/go/cmd/go/testdata/src/badpkg/x.go new file mode 100644 index 0000000000..dda35e8ed3 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/badpkg/x.go @@ -0,0 +1 @@ +pkg badpkg diff --git a/libgo/go/cmd/go/testdata/src/badtest/badexec/x_test.go b/libgo/go/cmd/go/testdata/src/badtest/badexec/x_test.go new file mode 100644 index 0000000000..12f5051712 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/badtest/badexec/x_test.go @@ -0,0 +1,5 @@ +package badexec + +func init() { + panic("badexec") +} diff --git a/libgo/go/cmd/go/testdata/src/badtest/badsyntax/x.go b/libgo/go/cmd/go/testdata/src/badtest/badsyntax/x.go new file mode 100644 index 0000000000..c8a5407a5a --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/badtest/badsyntax/x.go @@ -0,0 +1 @@ +package badsyntax diff --git a/libgo/go/cmd/go/testdata/src/badtest/badsyntax/x_test.go b/libgo/go/cmd/go/testdata/src/badtest/badsyntax/x_test.go new file mode 100644 index 0000000000..5be10745d9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/badtest/badsyntax/x_test.go @@ -0,0 +1,3 @@ +package badsyntax + +func func func func func! diff --git a/libgo/go/cmd/go/testdata/src/badtest/badvar/x.go b/libgo/go/cmd/go/testdata/src/badtest/badvar/x.go new file mode 100644 index 0000000000..fdd46c4c72 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/badtest/badvar/x.go @@ -0,0 +1 @@ +package badvar diff --git a/libgo/go/cmd/go/testdata/src/badtest/badvar/x_test.go b/libgo/go/cmd/go/testdata/src/badtest/badvar/x_test.go new file mode 100644 index 0000000000..c67df01c5c --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/badtest/badvar/x_test.go @@ -0,0 +1,5 @@ +package badvar_test + +func f() { + _ = notdefined +} diff --git a/libgo/go/cmd/go/testdata/src/cgotest/m.go b/libgo/go/cmd/go/testdata/src/cgotest/m.go new file mode 100644 index 0000000000..4d68307cf0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/cgotest/m.go @@ -0,0 +1,5 @@ +package cgotest + +import "C" + +var _ C.int diff --git a/libgo/go/cmd/go/testdata/src/go-cmd-test/helloworld.go b/libgo/go/cmd/go/testdata/src/go-cmd-test/helloworld.go new file mode 100644 index 0000000000..002a5c740c --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/go-cmd-test/helloworld.go @@ -0,0 +1,5 @@ +package main + +func main() { + println("hello world") +} diff --git a/libgo/go/cmd/go/testdata/src/main_test/m.go b/libgo/go/cmd/go/testdata/src/main_test/m.go new file mode 100644 index 0000000000..c682f030b4 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/main_test/m.go @@ -0,0 +1,4 @@ +package main + +func F() {} +func main() {} diff --git a/libgo/go/cmd/go/testdata/src/main_test/m_test.go b/libgo/go/cmd/go/testdata/src/main_test/m_test.go new file mode 100644 index 0000000000..f865b7734f --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/main_test/m_test.go @@ -0,0 +1,10 @@ +package main_test + +import ( + . "main_test" + "testing" +) + +func Test1(t *testing.T) { + F() +} diff --git a/libgo/go/cmd/go/testdata/src/notest/hello.go b/libgo/go/cmd/go/testdata/src/notest/hello.go new file mode 100644 index 0000000000..7c42c32fb0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/notest/hello.go @@ -0,0 +1,6 @@ +package notest + +func hello() { + println("hello world") +} +Hello world diff --git a/libgo/go/cmd/go/testdata/src/syntaxerror/x.go b/libgo/go/cmd/go/testdata/src/syntaxerror/x.go new file mode 100644 index 0000000000..c89cd18d0f --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/syntaxerror/x.go @@ -0,0 +1 @@ +package p diff --git a/libgo/go/cmd/go/testdata/src/syntaxerror/x_test.go b/libgo/go/cmd/go/testdata/src/syntaxerror/x_test.go new file mode 100644 index 0000000000..2460743e50 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/syntaxerror/x_test.go @@ -0,0 +1,4 @@ +package p + +func f() (x.y, z int) { +} diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p1/p1.go b/libgo/go/cmd/go/testdata/src/testcycle/p1/p1.go new file mode 100644 index 0000000000..65ab76d4e1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/testcycle/p1/p1.go @@ -0,0 +1,7 @@ +package p1 + +import _ "testcycle/p2" + +func init() { + println("p1 init") +} diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p1/p1_test.go b/libgo/go/cmd/go/testdata/src/testcycle/p1/p1_test.go new file mode 100644 index 0000000000..75abb13e6d --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/testcycle/p1/p1_test.go @@ -0,0 +1,6 @@ +package p1 + +import "testing" + +func Test(t *testing.T) { +} diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p2/p2.go b/libgo/go/cmd/go/testdata/src/testcycle/p2/p2.go new file mode 100644 index 0000000000..7e26cdf19c --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/testcycle/p2/p2.go @@ -0,0 +1,7 @@ +package p2 + +import _ "testcycle/p3" + +func init() { + println("p2 init") +} diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p3/p3.go b/libgo/go/cmd/go/testdata/src/testcycle/p3/p3.go new file mode 100644 index 0000000000..bb0a2f4f65 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/testcycle/p3/p3.go @@ -0,0 +1,5 @@ +package p3 + +func init() { + println("p3 init") +} diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p3/p3_test.go b/libgo/go/cmd/go/testdata/src/testcycle/p3/p3_test.go new file mode 100644 index 0000000000..9b4b0757f8 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/testcycle/p3/p3_test.go @@ -0,0 +1,10 @@ +package p3 + +import ( + "testing" + + _ "testcycle/p1" +) + +func Test(t *testing.T) { +} diff --git a/libgo/go/cmd/go/testdata/src/vetpkg/a_test.go b/libgo/go/cmd/go/testdata/src/vetpkg/a_test.go new file mode 100644 index 0000000000..9b64e8e1a2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/vetpkg/a_test.go @@ -0,0 +1 @@ +package p_test diff --git a/libgo/go/cmd/go/testdata/src/vetpkg/b.go b/libgo/go/cmd/go/testdata/src/vetpkg/b.go new file mode 100644 index 0000000000..99e18f63dc --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/vetpkg/b.go @@ -0,0 +1,7 @@ +package p + +import "fmt" + +func f() { + fmt.Printf("%d") +} diff --git a/libgo/go/cmd/go/testdata/src/xtestonly/f.go b/libgo/go/cmd/go/testdata/src/xtestonly/f.go new file mode 100644 index 0000000000..dac039e1ad --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/xtestonly/f.go @@ -0,0 +1,3 @@ +package xtestonly + +func F() int { return 42 } diff --git a/libgo/go/cmd/go/testdata/src/xtestonly/f_test.go b/libgo/go/cmd/go/testdata/src/xtestonly/f_test.go new file mode 100644 index 0000000000..01f6e83730 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/xtestonly/f_test.go @@ -0,0 +1,12 @@ +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/standalone_test.go b/libgo/go/cmd/go/testdata/standalone_test.go new file mode 100644 index 0000000000..59cf918b9b --- /dev/null +++ b/libgo/go/cmd/go/testdata/standalone_test.go @@ -0,0 +1,6 @@ +package standalone_test + +import "testing" + +func Test(t *testing.T) { +} diff --git a/libgo/go/cmd/go/testdata/testimport/p.go b/libgo/go/cmd/go/testdata/testimport/p.go new file mode 100644 index 0000000000..f94d2cd0e6 --- /dev/null +++ b/libgo/go/cmd/go/testdata/testimport/p.go @@ -0,0 +1,3 @@ +package p + +func F() int { return 1 } diff --git a/libgo/go/cmd/go/testdata/testimport/p1/p1.go b/libgo/go/cmd/go/testdata/testimport/p1/p1.go new file mode 100644 index 0000000000..fd315272ea --- /dev/null +++ b/libgo/go/cmd/go/testdata/testimport/p1/p1.go @@ -0,0 +1,3 @@ +package p1 + +func F() int { return 1 } diff --git a/libgo/go/cmd/go/testdata/testimport/p2/p2.go b/libgo/go/cmd/go/testdata/testimport/p2/p2.go new file mode 100644 index 0000000000..d4888865dd --- /dev/null +++ b/libgo/go/cmd/go/testdata/testimport/p2/p2.go @@ -0,0 +1,3 @@ +package p2 + +func F() int { return 1 } diff --git a/libgo/go/cmd/go/testdata/testimport/p_test.go b/libgo/go/cmd/go/testdata/testimport/p_test.go new file mode 100644 index 0000000000..a3fb4a9e27 --- /dev/null +++ b/libgo/go/cmd/go/testdata/testimport/p_test.go @@ -0,0 +1,13 @@ +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/testimport/x_test.go b/libgo/go/cmd/go/testdata/testimport/x_test.go new file mode 100644 index 0000000000..b253e3fd2d --- /dev/null +++ b/libgo/go/cmd/go/testdata/testimport/x_test.go @@ -0,0 +1,15 @@ +package p_test + +import ( + . "../testimport" + + "./p2" + + "testing" +) + +func TestF1(t *testing.T) { + if F() != p2.F() { + t.Fatal(F()) + } +} diff --git a/libgo/go/cmd/go/testdata/testinternal/p.go b/libgo/go/cmd/go/testdata/testinternal/p.go new file mode 100644 index 0000000000..e3558a53b2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/testinternal/p.go @@ -0,0 +1,3 @@ +package p + +import _ "net/http/internal" diff --git a/libgo/go/cmd/go/testdata/testinternal2/p.go b/libgo/go/cmd/go/testdata/testinternal2/p.go new file mode 100644 index 0000000000..c594f5c5e9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/testinternal2/p.go @@ -0,0 +1,3 @@ +package p + +import _ "./x/y/z/internal/w" diff --git a/libgo/go/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go b/libgo/go/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go new file mode 100644 index 0000000000..a796c0b5f4 --- /dev/null +++ b/libgo/go/cmd/go/testdata/testinternal2/x/y/z/internal/w/w.go @@ -0,0 +1 @@ +package w diff --git a/libgo/go/cmd/go/testdata/testonly/p_test.go b/libgo/go/cmd/go/testdata/testonly/p_test.go new file mode 100644 index 0000000000..c89cd18d0f --- /dev/null +++ b/libgo/go/cmd/go/testdata/testonly/p_test.go @@ -0,0 +1 @@ +package p diff --git a/libgo/go/cmd/go/testflag.go b/libgo/go/cmd/go/testflag.go new file mode 100644 index 0000000000..6da74b9967 --- /dev/null +++ b/libgo/go/cmd/go/testflag.go @@ -0,0 +1,319 @@ +// 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 main + +import ( + "fmt" + "os" + "strconv" + "strings" +) + +// The flag handling part of go test is large and distracting. +// We can't use the flag package because some of the flags from +// our command line are for us, and some are for 6.out, and +// some are for both. + +var usageMessage = `Usage of go test: + -c=false: compile but do not run the test binary + -file=file_test.go: specify file to use for tests; + use multiple times for multiple files + -p=n: build and test up to n packages in parallel + -x=false: print command lines as they are executed + + // These flags can be passed with or without a "test." prefix: -v or -test.v. + -bench="": passes -test.bench to test + -benchmem=false: print memory allocation statistics for benchmarks + -benchtime=1s: passes -test.benchtime to test + -cover=false: enable coverage analysis + -covermode="set": specifies mode for coverage analysis + -coverpkg="": comma-separated list of packages for coverage analysis + -coverprofile="": passes -test.coverprofile to test if -cover + -cpu="": passes -test.cpu to test + -cpuprofile="": passes -test.cpuprofile to test + -memprofile="": passes -test.memprofile to test + -memprofilerate=0: passes -test.memprofilerate to test + -blockprofile="": pases -test.blockprofile to test + -blockprofilerate=0: passes -test.blockprofilerate to test + -outputdir=$PWD: passes -test.outputdir to test + -parallel=0: passes -test.parallel to test + -run="": passes -test.run to test + -short=false: passes -test.short to test + -timeout=0: passes -test.timeout to test + -v=false: passes -test.v to test +` + +// usage prints a usage message and exits. +func testUsage() { + fmt.Fprint(os.Stderr, usageMessage) + setExitStatus(2) + exit() +} + +// testFlagSpec defines a flag we know about. +type testFlagSpec struct { + name string + boolVar *bool + passToTest bool // pass to Test + multiOK bool // OK to have multiple instances + present bool // flag has been seen +} + +// testFlagDefn is the set of flags we process. +var testFlagDefn = []*testFlagSpec{ + // local. + {name: "c", boolVar: &testC}, + {name: "cover", boolVar: &testCover}, + {name: "coverpkg"}, + {name: "o"}, + + // build flags. + {name: "a", boolVar: &buildA}, + {name: "n", boolVar: &buildN}, + {name: "p"}, + {name: "x", boolVar: &buildX}, + {name: "i", boolVar: &buildI}, + {name: "work", boolVar: &buildWork}, + {name: "ccflags"}, + {name: "gcflags"}, + {name: "exec"}, + {name: "ldflags"}, + {name: "gccgoflags"}, + {name: "tags"}, + {name: "compiler"}, + {name: "race", boolVar: &buildRace}, + {name: "installsuffix"}, + + // passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v. + {name: "bench", passToTest: true}, + {name: "benchmem", boolVar: new(bool), passToTest: true}, + {name: "benchtime", passToTest: true}, + {name: "covermode"}, + {name: "coverprofile", passToTest: true}, + {name: "cpu", passToTest: true}, + {name: "cpuprofile", passToTest: true}, + {name: "memprofile", passToTest: true}, + {name: "memprofilerate", passToTest: true}, + {name: "blockprofile", passToTest: true}, + {name: "blockprofilerate", passToTest: true}, + {name: "outputdir", passToTest: true}, + {name: "parallel", passToTest: true}, + {name: "run", passToTest: true}, + {name: "short", boolVar: new(bool), passToTest: true}, + {name: "timeout", passToTest: true}, + {name: "v", boolVar: &testV, passToTest: true}, +} + +// testFlags processes the command line, grabbing -x and -c, rewriting known flags +// to have "test" before them, and reading the command line for the 6.out. +// Unfortunately for us, we need to do our own flag processing because go test +// grabs some flags but otherwise its command line is just a holding place for +// pkg.test's arguments. +// We allow known flags both before and after the package name list, +// to allow both +// go test fmt -custom-flag-for-fmt-test +// go test -x math +func testFlags(args []string) (packageNames, passToTest []string) { + inPkg := false + outputDir := "" + for i := 0; i < len(args); i++ { + if !strings.HasPrefix(args[i], "-") { + if !inPkg && packageNames == nil { + // First package name we've seen. + inPkg = true + } + if inPkg { + packageNames = append(packageNames, args[i]) + continue + } + } + + if inPkg { + // Found an argument beginning with "-"; end of package list. + inPkg = false + } + + f, value, extraWord := testFlag(args, i) + if f == nil { + // This is a flag we do not know; we must assume + // that any args we see after this might be flag + // arguments, not package names. + inPkg = false + if packageNames == nil { + // make non-nil: we have seen the empty package list + packageNames = []string{} + } + passToTest = append(passToTest, args[i]) + continue + } + var err error + switch f.name { + // bool flags. + case "a", "c", "i", "n", "x", "v", "race", "cover", "work": + setBoolFlag(f.boolVar, value) + case "o": + testO = value + testNeedBinary = true + case "p": + setIntFlag(&buildP, value) + case "exec": + execCmd, err = splitQuotedFields(value) + if err != nil { + fatalf("invalid flag argument for -%s: %v", f.name, err) + } + case "ccflags": + buildCcflags, err = splitQuotedFields(value) + if err != nil { + fatalf("invalid flag argument for -%s: %v", f.name, err) + } + case "gcflags": + buildGcflags, err = splitQuotedFields(value) + if err != nil { + fatalf("invalid flag argument for -%s: %v", f.name, err) + } + case "ldflags": + buildLdflags, err = splitQuotedFields(value) + if err != nil { + fatalf("invalid flag argument for -%s: %v", f.name, err) + } + case "gccgoflags": + buildGccgoflags, err = splitQuotedFields(value) + if err != nil { + fatalf("invalid flag argument for -%s: %v", f.name, err) + } + case "tags": + buildContext.BuildTags = strings.Fields(value) + case "compiler": + buildCompiler{}.Set(value) + case "bench": + // record that we saw the flag; don't care about the value + testBench = true + case "timeout": + testTimeout = value + case "blockprofile", "cpuprofile", "memprofile": + testProfile = true + testNeedBinary = true + case "coverpkg": + testCover = true + if value == "" { + testCoverPaths = nil + } else { + testCoverPaths = strings.Split(value, ",") + } + case "coverprofile": + testCover = true + testProfile = true + case "covermode": + switch value { + case "set", "count", "atomic": + testCoverMode = value + default: + fatalf("invalid flag argument for -cover: %q", value) + } + testCover = true + case "outputdir": + outputDir = value + } + if extraWord { + i++ + } + if f.passToTest { + passToTest = append(passToTest, "-test."+f.name+"="+value) + } + } + + if testCoverMode == "" { + testCoverMode = "set" + if buildRace { + // Default coverage mode is atomic when -race is set. + testCoverMode = "atomic" + } + } + + // Tell the test what directory we're running in, so it can write the profiles there. + if testProfile && outputDir == "" { + dir, err := os.Getwd() + if err != nil { + fatalf("error from os.Getwd: %s", err) + } + passToTest = append(passToTest, "-test.outputdir", dir) + } + return +} + +// testFlag sees if argument i is a known flag and returns its definition, value, and whether it consumed an extra word. +func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool) { + arg := args[i] + if strings.HasPrefix(arg, "--") { // reduce two minuses to one + arg = arg[1:] + } + switch arg { + case "-?", "-h", "-help": + usage() + } + if arg == "" || arg[0] != '-' { + return + } + name := arg[1:] + // If there's already "test.", drop it for now. + name = strings.TrimPrefix(name, "test.") + equals := strings.Index(name, "=") + if equals >= 0 { + value = name[equals+1:] + name = name[:equals] + } + for _, f = range testFlagDefn { + if name == f.name { + // Booleans are special because they have modes -x, -x=true, -x=false. + if f.boolVar != nil { + if equals < 0 { // otherwise, it's been set and will be verified in setBoolFlag + value = "true" + } else { + // verify it parses + setBoolFlag(new(bool), value) + } + } else { // Non-booleans must have a value. + extra = equals < 0 + if extra { + if i+1 >= len(args) { + testSyntaxError("missing argument for flag " + f.name) + } + value = args[i+1] + } + } + if f.present && !f.multiOK { + testSyntaxError(f.name + " flag may be set only once") + } + f.present = true + return + } + } + f = nil + return +} + +// setBoolFlag sets the addressed boolean to the value. +func setBoolFlag(flag *bool, value string) { + x, err := strconv.ParseBool(value) + if err != nil { + testSyntaxError("illegal bool flag value " + value) + } + *flag = x +} + +// setIntFlag sets the addressed integer to the value. +func setIntFlag(flag *int, value string) { + x, err := strconv.Atoi(value) + if err != nil { + testSyntaxError("illegal int flag value " + value) + } + *flag = x +} + +func testSyntaxError(msg string) { + fmt.Fprintf(os.Stderr, "go test: %s\n", msg) + fmt.Fprintf(os.Stderr, `run "go help test" or "go help testflag" for more information`+"\n") + os.Exit(2) +} diff --git a/libgo/go/cmd/go/testgo.go b/libgo/go/cmd/go/testgo.go new file mode 100644 index 0000000000..01923f74bd --- /dev/null +++ b/libgo/go/cmd/go/testgo.go @@ -0,0 +1,21 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file contains extra hooks for testing the go command. +// It is compiled into the Go binary only when building the +// test copy; it does not get compiled into the standard go +// command, so these testing hooks are not present in the +// go command that everyone uses. + +// +build testgo + +package main + +import "os" + +func init() { + if v := os.Getenv("TESTGO_IS_GO_RELEASE"); v != "" { + isGoRelease = v == "1" + } +} diff --git a/libgo/go/cmd/go/tool.go b/libgo/go/cmd/go/tool.go new file mode 100644 index 0000000000..3f11c3e3d4 --- /dev/null +++ b/libgo/go/cmd/go/tool.go @@ -0,0 +1,146 @@ +// 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 main + +import ( + "fmt" + "go/build" + "os" + "os/exec" + "path/filepath" + "runtime" + "sort" + "strings" +) + +var cmdTool = &Command{ + Run: runTool, + UsageLine: "tool [-n] command [args...]", + Short: "run specified go tool", + Long: ` +Tool runs the go tool command identified by the arguments. +With no arguments it prints the list of known tools. + +The -n flag causes tool to print the command that would be +executed but not execute it. + +For more about each tool command, see 'go tool command -h'. +`, +} + +var ( + toolGOOS = runtime.GOOS + toolGOARCH = runtime.GOARCH + toolIsWindows = toolGOOS == "windows" + toolDir = build.ToolDir + + toolN bool +) + +func init() { + cmdTool.Flag.BoolVar(&toolN, "n", false, "") +} + +const toolWindowsExtension = ".exe" + +func tool(toolName string) string { + toolPath := filepath.Join(toolDir, toolName) + if toolIsWindows { + toolPath += toolWindowsExtension + } + // Give a nice message if there is no tool with that name. + if _, err := os.Stat(toolPath); err != nil { + if isInGoToolsRepo(toolName) { + fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get golang.org/x/tools/cmd/%s\n", toolName, toolName) + } else { + fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName) + } + setExitStatus(3) + exit() + } + return toolPath +} + +func isInGoToolsRepo(toolName string) bool { + switch toolName { + case "cover", "vet": + return true + } + return false +} + +func runTool(cmd *Command, args []string) { + if len(args) == 0 { + listTools() + return + } + toolName := args[0] + // The tool name must be lower-case letters, numbers or underscores. + for _, c := range toolName { + switch { + case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_': + default: + fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName) + setExitStatus(2) + return + } + } + toolPath := tool(toolName) + if toolPath == "" { + return + } + if toolN { + fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " ")) + return + } + toolCmd := &exec.Cmd{ + Path: toolPath, + Args: args, + Stdin: os.Stdin, + Stdout: os.Stdout, + Stderr: os.Stderr, + } + err := toolCmd.Run() + if err != nil { + // Only print about the exit status if the command + // didn't even run (not an ExitError) or it didn't exit cleanly + // or we're printing command lines too (-x mode). + // Assume if command exited cleanly (even with non-zero status) + // it printed any messages it wanted to print. + if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || buildX { + fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err) + } + setExitStatus(1) + return + } +} + +// listTools prints a list of the available tools in the tools directory. +func listTools() { + f, err := os.Open(toolDir) + if err != nil { + fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err) + setExitStatus(2) + return + } + defer f.Close() + names, err := f.Readdirnames(-1) + if err != nil { + fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err) + setExitStatus(2) + return + } + + sort.Strings(names) + for _, name := range names { + // Unify presentation by going to lower case. + name = strings.ToLower(name) + // If it's windows, don't show the .exe suffix. + if toolIsWindows && strings.HasSuffix(name, toolWindowsExtension) { + name = name[:len(name)-len(toolWindowsExtension)] + } + fmt.Println(name) + } +} diff --git a/libgo/go/cmd/go/vcs.go b/libgo/go/cmd/go/vcs.go new file mode 100644 index 0000000000..1cac613388 --- /dev/null +++ b/libgo/go/cmd/go/vcs.go @@ -0,0 +1,855 @@ +// 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 ( + "bytes" + "encoding/json" + "errors" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "regexp" + "strings" +) + +// A vcsCmd describes how to use a version control system +// like Mercurial, Git, or Subversion. +type vcsCmd struct { + name string + cmd string // name of binary to invoke command + + createCmd string // command to download a fresh copy of a repository + downloadCmd string // command to download updates into an existing repository + + tagCmd []tagCmd // commands to list tags + tagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd + tagSyncCmd string // command to sync to specific tag + tagSyncDefault string // command to sync to default tag + + scheme []string + pingCmd string + + remoteRepo func(v *vcsCmd, rootDir string) (remoteRepo string, err error) + resolveRepo func(v *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error) +} + +// A tagCmd describes a command to list available tags +// that can be passed to tagSyncCmd. +type tagCmd struct { + cmd string // command to list tags + pattern string // regexp to extract tags from list +} + +// vcsList lists the known version control systems +var vcsList = []*vcsCmd{ + vcsHg, + vcsGit, + vcsSvn, + vcsBzr, +} + +// vcsByCmd returns the version control system for the given +// command name (hg, git, svn, bzr). +func vcsByCmd(cmd string) *vcsCmd { + for _, vcs := range vcsList { + if vcs.cmd == cmd { + return vcs + } + } + return nil +} + +// vcsHg describes how to use Mercurial. +var vcsHg = &vcsCmd{ + name: "Mercurial", + cmd: "hg", + + createCmd: "clone -U {repo} {dir}", + downloadCmd: "pull", + + // We allow both tag and branch names as 'tags' + // for selecting a version. This lets people have + // a go.release.r60 branch and a go1 branch + // and make changes in both, without constantly + // editing .hgtags. + tagCmd: []tagCmd{ + {"tags", `^(\S+)`}, + {"branches", `^(\S+)`}, + }, + tagSyncCmd: "update -r {tag}", + tagSyncDefault: "update default", + + scheme: []string{"https", "http", "ssh"}, + pingCmd: "identify {scheme}://{repo}", + remoteRepo: hgRemoteRepo, +} + +func hgRemoteRepo(vcsHg *vcsCmd, rootDir string) (remoteRepo string, err error) { + out, err := vcsHg.runOutput(rootDir, "paths default") + if err != nil { + return "", err + } + return strings.TrimSpace(string(out)), nil +} + +// vcsGit describes how to use Git. +var vcsGit = &vcsCmd{ + name: "Git", + cmd: "git", + + createCmd: "clone {repo} {dir}", + downloadCmd: "pull --ff-only", + + tagCmd: []tagCmd{ + // tags/xxx matches a git tag named xxx + // origin/xxx matches a git branch named xxx on the default remote repository + {"show-ref", `(?:tags|origin)/(\S+)$`}, + }, + tagLookupCmd: []tagCmd{ + {"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`}, + }, + tagSyncCmd: "checkout {tag}", + tagSyncDefault: "checkout master", + + scheme: []string{"git", "https", "http", "git+ssh"}, + pingCmd: "ls-remote {scheme}://{repo}", + remoteRepo: gitRemoteRepo, +} + +func gitRemoteRepo(vcsGit *vcsCmd, rootDir string) (remoteRepo string, err error) { + outb, err := vcsGit.runOutput(rootDir, "remote -v") + if err != nil { + return "", err + } + out := string(outb) + + // Expect: + // origin https://github.com/rsc/pdf (fetch) + // origin https://github.com/rsc/pdf (push) + // use first line only. + + if !strings.HasPrefix(out, "origin\t") { + return "", fmt.Errorf("unable to parse output of git remote -v") + } + out = strings.TrimPrefix(out, "origin\t") + i := strings.Index(out, "\n") + if i < 0 { + return "", fmt.Errorf("unable to parse output of git remote -v") + } + out = out[:i] + i = strings.LastIndex(out, " ") + if i < 0 { + return "", fmt.Errorf("unable to parse output of git remote -v") + } + out = out[:i] + return strings.TrimSpace(string(out)), nil +} + +// vcsBzr describes how to use Bazaar. +var vcsBzr = &vcsCmd{ + name: "Bazaar", + cmd: "bzr", + + createCmd: "branch {repo} {dir}", + + // Without --overwrite bzr will not pull tags that changed. + // Replace by --overwrite-tags after http://pad.lv/681792 goes in. + downloadCmd: "pull --overwrite", + + tagCmd: []tagCmd{{"tags", `^(\S+)`}}, + tagSyncCmd: "update -r {tag}", + tagSyncDefault: "update -r revno:-1", + + scheme: []string{"https", "http", "bzr", "bzr+ssh"}, + pingCmd: "info {scheme}://{repo}", + remoteRepo: bzrRemoteRepo, + resolveRepo: bzrResolveRepo, +} + +func bzrRemoteRepo(vcsBzr *vcsCmd, rootDir string) (remoteRepo string, err error) { + outb, err := vcsBzr.runOutput(rootDir, "config parent_location") + if err != nil { + return "", err + } + return strings.TrimSpace(string(outb)), nil +} + +func bzrResolveRepo(vcsBzr *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error) { + outb, err := vcsBzr.runOutput(rootDir, "info "+remoteRepo) + if err != nil { + return "", err + } + out := string(outb) + + // Expect: + // ... + // (branch root|repository branch): + // ... + + found := false + for _, prefix := range []string{"\n branch root: ", "\n repository branch: "} { + i := strings.Index(out, prefix) + if i >= 0 { + out = out[i+len(prefix):] + found = true + break + } + } + if !found { + return "", fmt.Errorf("unable to parse output of bzr info") + } + + i := strings.Index(out, "\n") + if i < 0 { + return "", fmt.Errorf("unable to parse output of bzr info") + } + out = out[:i] + return strings.TrimSpace(string(out)), nil +} + +// vcsSvn describes how to use Subversion. +var vcsSvn = &vcsCmd{ + name: "Subversion", + cmd: "svn", + + createCmd: "checkout {repo} {dir}", + downloadCmd: "update", + + // There is no tag command in subversion. + // The branch information is all in the path names. + + scheme: []string{"https", "http", "svn", "svn+ssh"}, + pingCmd: "info {scheme}://{repo}", + remoteRepo: svnRemoteRepo, +} + +func svnRemoteRepo(vcsSvn *vcsCmd, rootDir string) (remoteRepo string, err error) { + outb, err := vcsSvn.runOutput(rootDir, "info") + if err != nil { + return "", err + } + out := string(outb) + + // Expect: + // ... + // Repository Root: + // ... + + i := strings.Index(out, "\nRepository Root: ") + if i < 0 { + return "", fmt.Errorf("unable to parse output of svn info") + } + out = out[i+len("\nRepository Root: "):] + i = strings.Index(out, "\n") + if i < 0 { + return "", fmt.Errorf("unable to parse output of svn info") + } + out = out[:i] + return strings.TrimSpace(string(out)), nil +} + +func (v *vcsCmd) String() string { + return v.name +} + +// run runs the command line cmd in the given directory. +// keyval is a list of key, value pairs. run expands +// instances of {key} in cmd into value, but only after +// splitting cmd into individual arguments. +// If an error occurs, run prints the command line and the +// command's combined stdout+stderr to standard error. +// Otherwise run discards the command's output. +func (v *vcsCmd) run(dir string, cmd string, keyval ...string) error { + _, err := v.run1(dir, cmd, keyval, true) + return err +} + +// runVerboseOnly is like run but only generates error output to standard error in verbose mode. +func (v *vcsCmd) runVerboseOnly(dir string, cmd string, keyval ...string) error { + _, err := v.run1(dir, cmd, keyval, false) + return err +} + +// runOutput is like run but returns the output of the command. +func (v *vcsCmd) runOutput(dir string, cmd string, keyval ...string) ([]byte, error) { + return v.run1(dir, cmd, keyval, true) +} + +// run1 is the generalized implementation of run and runOutput. +func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([]byte, error) { + m := make(map[string]string) + for i := 0; i < len(keyval); i += 2 { + m[keyval[i]] = keyval[i+1] + } + args := strings.Fields(cmdline) + for i, arg := range args { + args[i] = expand(m, arg) + } + + _, err := exec.LookPath(v.cmd) + if err != nil { + fmt.Fprintf(os.Stderr, + "go: missing %s command. See http://golang.org/s/gogetcmd\n", + v.name) + return nil, err + } + + cmd := exec.Command(v.cmd, args...) + cmd.Dir = dir + cmd.Env = envForDir(cmd.Dir) + if buildX { + fmt.Printf("cd %s\n", dir) + fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " ")) + } + var buf bytes.Buffer + cmd.Stdout = &buf + cmd.Stderr = &buf + err = cmd.Run() + out := buf.Bytes() + if err != nil { + if verbose || buildV { + fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " ")) + os.Stderr.Write(out) + } + return nil, err + } + return out, nil +} + +// ping pings to determine scheme to use. +func (v *vcsCmd) ping(scheme, repo string) error { + return v.runVerboseOnly(".", v.pingCmd, "scheme", scheme, "repo", repo) +} + +// create creates a new copy of repo in dir. +// The parent of dir must exist; dir must not. +func (v *vcsCmd) create(dir, repo string) error { + return v.run(".", v.createCmd, "dir", dir, "repo", repo) +} + +// download downloads any new changes for the repo in dir. +func (v *vcsCmd) download(dir string) error { + if err := v.fixDetachedHead(dir); err != nil { + return err + } + return v.run(dir, v.downloadCmd) +} + +// fixDetachedHead switches a Git repository in dir from a detached head to the master branch. +// Go versions before 1.2 downloaded Git repositories in an unfortunate way +// that resulted in the working tree state being on a detached head. +// That meant the repository was not usable for normal Git operations. +// Go 1.2 fixed that, but we can't pull into a detached head, so if this is +// a Git repository we check for being on a detached head and switch to the +// real branch, almost always called "master". +// TODO(dsymonds): Consider removing this for Go 1.3. +func (v *vcsCmd) fixDetachedHead(dir string) error { + if v != vcsGit { + return nil + } + + // "git symbolic-ref HEAD" succeeds iff we are not on a detached head. + if err := v.runVerboseOnly(dir, "symbolic-ref HEAD"); err == nil { + // not on a detached head + return nil + } + if buildV { + log.Printf("%s on detached head; repairing", dir) + } + return v.run(dir, "checkout master") +} + +// tags returns the list of available tags for the repo in dir. +func (v *vcsCmd) tags(dir string) ([]string, error) { + var tags []string + for _, tc := range v.tagCmd { + out, err := v.runOutput(dir, tc.cmd) + if err != nil { + return nil, err + } + re := regexp.MustCompile(`(?m-s)` + tc.pattern) + for _, m := range re.FindAllStringSubmatch(string(out), -1) { + tags = append(tags, m[1]) + } + } + return tags, nil +} + +// tagSync syncs the repo in dir to the named tag, +// which either is a tag returned by tags or is v.tagDefault. +func (v *vcsCmd) tagSync(dir, tag string) error { + if v.tagSyncCmd == "" { + return nil + } + if tag != "" { + for _, tc := range v.tagLookupCmd { + out, err := v.runOutput(dir, tc.cmd, "tag", tag) + if err != nil { + return err + } + re := regexp.MustCompile(`(?m-s)` + tc.pattern) + m := re.FindStringSubmatch(string(out)) + if len(m) > 1 { + tag = m[1] + break + } + } + } + if tag == "" && v.tagSyncDefault != "" { + return v.run(dir, v.tagSyncDefault) + } + return v.run(dir, v.tagSyncCmd, "tag", tag) +} + +// A vcsPath describes how to convert an import path into a +// version control system and repository name. +type vcsPath struct { + prefix string // prefix this description applies to + re string // pattern for import path + repo string // repository to use (expand with match of re) + vcs string // version control system to use (expand with match of re) + check func(match map[string]string) error // additional checks + ping bool // ping for scheme to use to download repo + + regexp *regexp.Regexp // cached compiled form of re +} + +// vcsForDir inspects dir and its parents to determine the +// version control system and code repository to use. +// On return, root is the import path +// corresponding to the root of the repository +// (thus root is a prefix of importPath). +func vcsForDir(p *Package) (vcs *vcsCmd, root string, err error) { + // Clean and double-check that dir is in (a subdirectory of) srcRoot. + dir := filepath.Clean(p.Dir) + srcRoot := filepath.Clean(p.build.SrcRoot) + if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator { + return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot) + } + + origDir := dir + for len(dir) > len(srcRoot) { + for _, vcs := range vcsList { + if fi, err := os.Stat(filepath.Join(dir, "."+vcs.cmd)); err == nil && fi.IsDir() { + return vcs, dir[len(srcRoot)+1:], nil + } + } + + // Move to parent. + ndir := filepath.Dir(dir) + if len(ndir) >= len(dir) { + // Shouldn't happen, but just in case, stop. + break + } + dir = ndir + } + + return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir) +} + +// repoRoot represents a version control system, a repo, and a root of +// where to put it on disk. +type repoRoot struct { + vcs *vcsCmd + + // repo is the repository URL, including scheme + repo string + + // root is the import path corresponding to the root of the + // repository + root string +} + +var httpPrefixRE = regexp.MustCompile(`^https?:`) + +// repoRootForImportPath analyzes importPath to determine the +// version control system, and code repository to use. +func repoRootForImportPath(importPath string) (*repoRoot, error) { + rr, err := repoRootForImportPathStatic(importPath, "") + if err == errUnknownSite { + // If there are wildcards, look up the thing before the wildcard, + // hoping it applies to the wildcarded parts too. + // This makes 'go get rsc.io/pdf/...' work in a fresh GOPATH. + lookup := strings.TrimSuffix(importPath, "/...") + if i := strings.Index(lookup, "/.../"); i >= 0 { + lookup = lookup[:i] + } + rr, err = repoRootForImportDynamic(lookup) + + // repoRootForImportDynamic returns error detail + // that is irrelevant if the user didn't intend to use a + // dynamic import in the first place. + // Squelch it. + if err != nil { + if buildV { + log.Printf("import %q: %v", importPath, err) + } + err = fmt.Errorf("unrecognized import path %q", importPath) + } + } + + if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.root, "...") { + // Do not allow wildcards in the repo root. + rr = nil + err = fmt.Errorf("cannot expand ... in %q", importPath) + } + return rr, err +} + +var errUnknownSite = errors.New("dynamic lookup required to find mapping") + +// repoRootForImportPathStatic attempts to map importPath to a +// repoRoot using the commonly-used VCS hosting sites in vcsPaths +// (github.com/user/dir), or from a fully-qualified importPath already +// containing its VCS type (foo.com/repo.git/dir) +// +// If scheme is non-empty, that scheme is forced. +func repoRootForImportPathStatic(importPath, scheme string) (*repoRoot, error) { + // A common error is to use https://packagepath because that's what + // hg and git require. Diagnose this helpfully. + if loc := httpPrefixRE.FindStringIndex(importPath); loc != nil { + // The importPath has been cleaned, so has only one slash. The pattern + // ignores the slashes; the error message puts them back on the RHS at least. + return nil, fmt.Errorf("%q not allowed in import path", importPath[loc[0]:loc[1]]+"//") + } + for _, srv := range vcsPaths { + if !strings.HasPrefix(importPath, srv.prefix) { + continue + } + m := srv.regexp.FindStringSubmatch(importPath) + if m == nil { + if srv.prefix != "" { + return nil, fmt.Errorf("invalid %s import path %q", srv.prefix, importPath) + } + continue + } + + // Build map of named subexpression matches for expand. + match := map[string]string{ + "prefix": srv.prefix, + "import": importPath, + } + for i, name := range srv.regexp.SubexpNames() { + if name != "" && match[name] == "" { + match[name] = m[i] + } + } + if srv.vcs != "" { + match["vcs"] = expand(match, srv.vcs) + } + if srv.repo != "" { + match["repo"] = expand(match, srv.repo) + } + if srv.check != nil { + if err := srv.check(match); err != nil { + return nil, err + } + } + vcs := vcsByCmd(match["vcs"]) + if vcs == nil { + return nil, fmt.Errorf("unknown version control system %q", match["vcs"]) + } + if srv.ping { + if scheme != "" { + match["repo"] = scheme + "://" + match["repo"] + } else { + for _, scheme := range vcs.scheme { + if vcs.ping(scheme, match["repo"]) == nil { + match["repo"] = scheme + "://" + match["repo"] + break + } + } + } + } + rr := &repoRoot{ + vcs: vcs, + repo: match["repo"], + root: match["root"], + } + return rr, nil + } + return nil, errUnknownSite +} + +// repoRootForImportDynamic finds a *repoRoot for a custom domain that's not +// statically known by repoRootForImportPathStatic. +// +// This handles "vanity import paths" like "name.tld/pkg/foo". +func repoRootForImportDynamic(importPath string) (*repoRoot, error) { + slash := strings.Index(importPath, "/") + if slash < 0 { + return nil, errors.New("import path does not contain a slash") + } + host := importPath[:slash] + if !strings.Contains(host, ".") { + return nil, errors.New("import path does not begin with hostname") + } + urlStr, body, err := httpsOrHTTP(importPath) + if err != nil { + return nil, fmt.Errorf("http/https fetch: %v", err) + } + defer body.Close() + imports, err := parseMetaGoImports(body) + if err != nil { + return nil, fmt.Errorf("parsing %s: %v", importPath, err) + } + metaImport, err := matchGoImport(imports, importPath) + if err != nil { + if err != errNoMatch { + return nil, fmt.Errorf("parse %s: %v", urlStr, err) + } + return nil, fmt.Errorf("parse %s: no go-import meta tags", urlStr) + } + if buildV { + log.Printf("get %q: found meta tag %#v at %s", importPath, metaImport, urlStr) + } + // If the import was "uni.edu/bob/project", which said the + // prefix was "uni.edu" and the RepoRoot was "evilroot.com", + // make sure we don't trust Bob and check out evilroot.com to + // "uni.edu" yet (possibly overwriting/preempting another + // non-evil student). Instead, first verify the root and see + // if it matches Bob's claim. + if metaImport.Prefix != importPath { + if buildV { + log.Printf("get %q: verifying non-authoritative meta tag", importPath) + } + urlStr0 := urlStr + urlStr, body, err = httpsOrHTTP(metaImport.Prefix) + if err != nil { + return nil, fmt.Errorf("fetch %s: %v", urlStr, err) + } + imports, err := parseMetaGoImports(body) + if err != nil { + return nil, fmt.Errorf("parsing %s: %v", importPath, err) + } + if len(imports) == 0 { + return nil, fmt.Errorf("fetch %s: no go-import meta tag", urlStr) + } + metaImport2, err := matchGoImport(imports, importPath) + if err != nil || metaImport != metaImport2 { + return nil, fmt.Errorf("%s and %s disagree about go-import for %s", urlStr0, urlStr, metaImport.Prefix) + } + } + + if !strings.Contains(metaImport.RepoRoot, "://") { + return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, metaImport.RepoRoot) + } + rr := &repoRoot{ + vcs: vcsByCmd(metaImport.VCS), + repo: metaImport.RepoRoot, + root: metaImport.Prefix, + } + if rr.vcs == nil { + return nil, fmt.Errorf("%s: unknown vcs %q", urlStr, metaImport.VCS) + } + return rr, nil +} + +// metaImport represents the parsed tags from HTML files. +type metaImport struct { + Prefix, VCS, RepoRoot string +} + +// errNoMatch is returned from matchGoImport when there's no applicable match. +var errNoMatch = errors.New("no import match") + +// matchGoImport returns the metaImport from imports matching importPath. +// An error is returned if there are multiple matches. +// errNoMatch is returned if none match. +func matchGoImport(imports []metaImport, importPath string) (_ metaImport, err error) { + match := -1 + for i, im := range imports { + if !strings.HasPrefix(importPath, im.Prefix) { + continue + } + if match != -1 { + err = fmt.Errorf("multiple meta tags match import path %q", importPath) + return + } + match = i + } + if match == -1 { + err = errNoMatch + return + } + return imports[match], nil +} + +// expand rewrites s to replace {k} with match[k] for each key k in match. +func expand(match map[string]string, s string) string { + for k, v := range match { + s = strings.Replace(s, "{"+k+"}", v, -1) + } + return s +} + +// vcsPaths lists the known vcs paths. +var vcsPaths = []*vcsPath{ + // Google Code - new syntax + { + prefix: "code.google.com/", + re: `^(?Pcode\.google\.com/p/(?P[a-z0-9\-]+)(\.(?P[a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`, + repo: "https://{root}", + check: googleCodeVCS, + }, + + // Google Code - old syntax + { + re: `^(?P[a-z0-9_\-.]+)\.googlecode\.com/(git|hg|svn)(?P/.*)?$`, + check: oldGoogleCode, + }, + + // Github + { + prefix: "github.com/", + re: `^(?Pgithub\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`, + vcs: "git", + repo: "https://{root}", + check: noVCSSuffix, + }, + + // Bitbucket + { + prefix: "bitbucket.org/", + re: `^(?Pbitbucket\.org/(?P[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`, + repo: "https://{root}", + check: bitbucketVCS, + }, + + // Launchpad + { + prefix: "launchpad.net/", + re: `^(?Plaunchpad\.net/((?P[A-Za-z0-9_.\-]+)(?P/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`, + vcs: "bzr", + repo: "https://{root}", + check: launchpadVCS, + }, + + // IBM DevOps Services (JazzHub) + { + prefix: "hub.jazz.net/git", + re: `^(?Phub.jazz.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`, + vcs: "git", + repo: "https://{root}", + check: noVCSSuffix, + }, + + // General syntax for any server. + { + re: `^(?P(?P([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?Pbzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`, + ping: true, + }, +} + +func init() { + // fill in cached regexps. + // Doing this eagerly discovers invalid regexp syntax + // without having to run a command that needs that regexp. + for _, srv := range vcsPaths { + srv.regexp = regexp.MustCompile(srv.re) + } +} + +// noVCSSuffix checks that the repository name does not +// end in .foo for any version control system foo. +// The usual culprit is ".git". +func noVCSSuffix(match map[string]string) error { + repo := match["repo"] + for _, vcs := range vcsList { + if strings.HasSuffix(repo, "."+vcs.cmd) { + return fmt.Errorf("invalid version control suffix in %s path", match["prefix"]) + } + } + return nil +} + +var googleCheckout = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`) + +// googleCodeVCS determines the version control system for +// a code.google.com repository, by scraping the project's +// /source/checkout page. +func googleCodeVCS(match map[string]string) error { + if err := noVCSSuffix(match); err != nil { + return err + } + data, err := httpGET(expand(match, "https://code.google.com/p/{project}/source/checkout?repo={subrepo}")) + if err != nil { + return err + } + + if m := googleCheckout.FindSubmatch(data); m != nil { + if vcs := vcsByCmd(string(m[1])); vcs != nil { + // Subversion requires the old URLs. + // TODO: Test. + if vcs == vcsSvn { + if match["subrepo"] != "" { + return fmt.Errorf("sub-repositories not supported in Google Code Subversion projects") + } + match["repo"] = expand(match, "https://{project}.googlecode.com/svn") + } + match["vcs"] = vcs.cmd + return nil + } + } + + return fmt.Errorf("unable to detect version control system for code.google.com/ path") +} + +// oldGoogleCode is invoked for old-style foo.googlecode.com paths. +// It prints an error giving the equivalent new path. +func oldGoogleCode(match map[string]string) error { + return fmt.Errorf("invalid Google Code import path: use %s instead", + expand(match, "code.google.com/p/{project}{path}")) +} + +// bitbucketVCS determines the version control system for a +// Bitbucket repository, by using the Bitbucket API. +func bitbucketVCS(match map[string]string) error { + if err := noVCSSuffix(match); err != nil { + return err + } + + var resp struct { + SCM string `json:"scm"` + } + url := expand(match, "https://api.bitbucket.org/1.0/repositories/{bitname}") + data, err := httpGET(url) + if err != nil { + return err + } + if err := json.Unmarshal(data, &resp); err != nil { + return fmt.Errorf("decoding %s: %v", url, err) + } + + if vcsByCmd(resp.SCM) != nil { + match["vcs"] = resp.SCM + if resp.SCM == "git" { + match["repo"] += ".git" + } + return nil + } + + return fmt.Errorf("unable to detect version control system for bitbucket.org/ path") +} + +// launchpadVCS solves the ambiguity for "lp.net/project/foo". In this case, +// "foo" could be a series name registered in Launchpad with its own branch, +// and it could also be the name of a directory within the main project +// branch one level up. +func launchpadVCS(match map[string]string) error { + if match["project"] == "" || match["series"] == "" { + return nil + } + _, err := httpGET(expand(match, "https://code.launchpad.net/{project}{series}/.bzr/branch-format")) + if err != nil { + match["root"] = expand(match, "launchpad.net/{project}") + match["repo"] = expand(match, "https://{root}") + } + return nil +} diff --git a/libgo/go/cmd/go/vcs_test.go b/libgo/go/cmd/go/vcs_test.go new file mode 100644 index 0000000000..14d681ba6a --- /dev/null +++ b/libgo/go/cmd/go/vcs_test.go @@ -0,0 +1,124 @@ +// 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 main + +import ( + "runtime" + "testing" +) + +// Test that RepoRootForImportPath creates the correct RepoRoot for a given importPath. +// TODO(cmang): Add tests for SVN and BZR. +func TestRepoRootForImportPath(t *testing.T) { + if testing.Short() { + t.Skip("skipping test to avoid external network") + } + switch runtime.GOOS { + case "nacl", "android": + t.Skipf("no networking available on %s", runtime.GOOS) + } + tests := []struct { + path string + want *repoRoot + }{ + { + "code.google.com/p/go", + &repoRoot{ + vcs: vcsHg, + repo: "https://code.google.com/p/go", + }, + }, + /*{ + "code.google.com/r/go", + &repoRoot{ + vcs: vcsHg, + repo: "https://code.google.com/r/go", + }, + },*/ + { + "github.com/golang/groupcache", + &repoRoot{ + vcs: vcsGit, + repo: "https://github.com/golang/groupcache", + }, + }, + // IBM DevOps Services tests + { + "hub.jazz.net/git/user1/pkgname", + &repoRoot{ + vcs: vcsGit, + repo: "https://hub.jazz.net/git/user1/pkgname", + }, + }, + { + "hub.jazz.net/git/user1/pkgname/submodule/submodule/submodule", + &repoRoot{ + vcs: vcsGit, + repo: "https://hub.jazz.net/git/user1/pkgname", + }, + }, + { + "hub.jazz.net", + nil, + }, + { + "hub2.jazz.net", + nil, + }, + { + "hub.jazz.net/someotherprefix", + nil, + }, + { + "hub.jazz.net/someotherprefix/user1/pkgname", + nil, + }, + // Spaces are not valid in user names or package names + { + "hub.jazz.net/git/User 1/pkgname", + nil, + }, + { + "hub.jazz.net/git/user1/pkg name", + nil, + }, + // Dots are not valid in user names + { + "hub.jazz.net/git/user.1/pkgname", + nil, + }, + { + "hub.jazz.net/git/user/pkg.name", + &repoRoot{ + vcs: vcsGit, + repo: "https://hub.jazz.net/git/user/pkg.name", + }, + }, + // User names cannot have uppercase letters + { + "hub.jazz.net/git/USER/pkgname", + nil, + }, + } + + for _, test := range tests { + got, err := repoRootForImportPath(test.path) + want := test.want + + if want == nil { + if err == nil { + t.Errorf("RepoRootForImport(%q): Error expected but not received", test.path) + } + continue + } + if err != nil { + t.Errorf("RepoRootForImport(%q): %v", test.path, err) + continue + } + if got.vcs.name != want.vcs.name || got.repo != want.repo { + t.Errorf("RepoRootForImport(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.vcs, got.repo, want.vcs, want.repo) + } + } +} diff --git a/libgo/go/cmd/go/version.go b/libgo/go/cmd/go/version.go new file mode 100644 index 0000000000..a41f4a7361 --- /dev/null +++ b/libgo/go/cmd/go/version.go @@ -0,0 +1,25 @@ +// 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 main + +import ( + "fmt" + "runtime" +) + +var cmdVersion = &Command{ + Run: runVersion, + UsageLine: "version", + Short: "print Go version", + Long: `Version prints the Go version, as reported by runtime.Version.`, +} + +func runVersion(cmd *Command, args []string) { + if len(args) != 0 { + cmd.Usage() + } + + fmt.Printf("go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH) +} diff --git a/libgo/go/cmd/go/vet.go b/libgo/go/cmd/go/vet.go new file mode 100644 index 0000000000..02ff54b2ac --- /dev/null +++ b/libgo/go/cmd/go/vet.go @@ -0,0 +1,50 @@ +// 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 main + +import "path/filepath" + +func init() { + addBuildFlagsNX(cmdVet) +} + +var cmdVet = &Command{ + Run: runVet, + UsageLine: "vet [-n] [-x] [packages]", + Short: "run go tool vet on packages", + Long: ` +Vet runs the Go vet command on the packages named by the import paths. + +For more about vet, see 'godoc golang.org/x/tools/cmd/vet'. +For more about specifying packages, see 'go help packages'. + +To run the vet tool with specific options, run 'go tool vet'. + +The -n flag prints commands that would be executed. +The -x flag prints commands as they are executed. + +See also: go fmt, go fix. + `, +} + +func runVet(cmd *Command, args []string) { + for _, p := range packages(args) { + // Vet expects to be given a set of files all from the same package. + // Run once for package p and once for package p_test. + if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles) > 0 { + runVetFiles(p, stringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.SFiles)) + } + if len(p.XTestGoFiles) > 0 { + runVetFiles(p, stringList(p.XTestGoFiles)) + } + } +} + +func runVetFiles(p *Package, files []string) { + for i := range files { + files[i] = filepath.Join(p.Dir, files[i]) + } + run(tool("vet"), relPaths(files)) +} diff --git a/libgo/go/cmd/gofmt/doc.go b/libgo/go/cmd/gofmt/doc.go new file mode 100644 index 0000000000..3fc0439548 --- /dev/null +++ b/libgo/go/cmd/gofmt/doc.go @@ -0,0 +1,93 @@ +// 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. + +/* +Gofmt formats Go programs. +It uses tabs (width = 8) for indentation and blanks for alignment. + +Without an explicit path, it processes the standard input. Given a file, +it operates on that file; given a directory, it operates on all .go files in +that directory, recursively. (Files starting with a period are ignored.) +By default, gofmt prints the reformatted sources to standard output. + +Usage: + gofmt [flags] [path ...] + +The flags are: + -d + Do not print reformatted sources to standard output. + If a file's formatting is different than gofmt's, print diffs + to standard output. + -e + Print all (including spurious) errors. + -l + Do not print reformatted sources to standard output. + If a file's formatting is different from gofmt's, print its name + to standard output. + -r rule + Apply the rewrite rule to the source before reformatting. + -s + Try to simplify code (after applying the rewrite rule, if any). + -w + Do not print reformatted sources to standard output. + If a file's formatting is different from gofmt's, overwrite it + with gofmt's version. + +Debugging support: + -cpuprofile filename + Write cpu profile to the specified file. + + +The rewrite rule specified with the -r flag must be a string of the form: + + pattern -> replacement + +Both pattern and replacement must be valid Go expressions. +In the pattern, single-character lowercase identifiers serve as +wildcards matching arbitrary sub-expressions; those expressions +will be substituted for the same identifiers in the replacement. + +When gofmt reads from standard input, it accepts either a full Go program +or a program fragment. A program fragment must be a syntactically +valid declaration list, statement list, or expression. When formatting +such a fragment, gofmt preserves leading indentation as well as leading +and trailing spaces, so that individual sections of a Go program can be +formatted by piping them through gofmt. + +Examples + +To check files for unnecessary parentheses: + + gofmt -r '(a) -> a' -l *.go + +To remove the parentheses: + + gofmt -r '(a) -> a' -w *.go + +To convert the package tree from explicit slice upper bounds to implicit ones: + + gofmt -r 'α[β:len(α)] -> α[β:]' -w $GOROOT/src + +The simplify command + +When invoked with -s gofmt will make the following source transformations where possible. + + An array, slice, or map composite literal of the form: + []T{T{}, T{}} + will be simplified to: + []T{{}, {}} + + A slice expression of the form: + s[a:len(s)] + will be simplified to: + s[a:] + + A range of the form: + for x, _ = range v {...} + will be simplified to: + for x = range v {...} +*/ +package main + +// BUG(rsc): The implementation of -r is a bit slow. diff --git a/libgo/go/cmd/gofmt/gofmt.go b/libgo/go/cmd/gofmt/gofmt.go new file mode 100644 index 0000000000..81da21ff10 --- /dev/null +++ b/libgo/go/cmd/gofmt/gofmt.go @@ -0,0 +1,387 @@ +// 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 main + +import ( + "bytes" + "flag" + "fmt" + "go/ast" + "go/parser" + "go/printer" + "go/scanner" + "go/token" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime/pprof" + "strings" +) + +var ( + // main operation modes + list = flag.Bool("l", false, "list files whose formatting differs from gofmt's") + write = flag.Bool("w", false, "write result to (source) file instead of stdout") + rewriteRule = flag.String("r", "", "rewrite rule (e.g., 'a[b:len(a)] -> a[b:]')") + simplifyAST = flag.Bool("s", false, "simplify code") + doDiff = flag.Bool("d", false, "display diffs instead of rewriting files") + allErrors = flag.Bool("e", false, "report all errors (not just the first 10 on different lines)") + + // debugging + cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file") +) + +const ( + tabWidth = 8 + printerMode = printer.UseSpaces | printer.TabIndent +) + +var ( + fileSet = token.NewFileSet() // per process FileSet + exitCode = 0 + rewrite func(*ast.File) *ast.File + parserMode parser.Mode +) + +func report(err error) { + scanner.PrintError(os.Stderr, err) + exitCode = 2 +} + +func usage() { + fmt.Fprintf(os.Stderr, "usage: gofmt [flags] [path ...]\n") + flag.PrintDefaults() + os.Exit(2) +} + +func initParserMode() { + parserMode = parser.ParseComments + if *allErrors { + parserMode |= parser.AllErrors + } +} + +func isGoFile(f os.FileInfo) bool { + // ignore non-Go files + name := f.Name() + return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") +} + +// If in == nil, the source is the contents of the file with the given filename. +func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error { + if in == nil { + f, err := os.Open(filename) + if err != nil { + return err + } + defer f.Close() + in = f + } + + src, err := ioutil.ReadAll(in) + if err != nil { + return err + } + + file, sourceAdj, indentAdj, err := parse(fileSet, filename, src, stdin) + if err != nil { + return err + } + + if rewrite != nil { + if sourceAdj == nil { + file = rewrite(file) + } else { + fmt.Fprintf(os.Stderr, "warning: rewrite ignored for incomplete programs\n") + } + } + + ast.SortImports(fileSet, file) + + if *simplifyAST { + simplify(file) + } + + res, err := format(fileSet, file, sourceAdj, indentAdj, src, printer.Config{Mode: printerMode, Tabwidth: tabWidth}) + if err != nil { + return err + } + + if !bytes.Equal(src, res) { + // formatting has changed + if *list { + fmt.Fprintln(out, filename) + } + if *write { + err = ioutil.WriteFile(filename, res, 0644) + if err != nil { + return err + } + } + if *doDiff { + data, err := diff(src, res) + if err != nil { + return fmt.Errorf("computing diff: %s", err) + } + fmt.Printf("diff %s gofmt/%s\n", filename, filename) + out.Write(data) + } + } + + if !*list && !*write && !*doDiff { + _, err = out.Write(res) + } + + return err +} + +func visitFile(path string, f os.FileInfo, err error) error { + if err == nil && isGoFile(f) { + err = processFile(path, nil, os.Stdout, false) + } + if err != nil { + report(err) + } + return nil +} + +func walkDir(path string) { + filepath.Walk(path, visitFile) +} + +func main() { + // call gofmtMain in a separate function + // so that it can use defer and have them + // run before the exit. + gofmtMain() + os.Exit(exitCode) +} + +func gofmtMain() { + flag.Usage = usage + flag.Parse() + + if *cpuprofile != "" { + f, err := os.Create(*cpuprofile) + if err != nil { + fmt.Fprintf(os.Stderr, "creating cpu profile: %s\n", err) + exitCode = 2 + return + } + defer f.Close() + pprof.StartCPUProfile(f) + defer pprof.StopCPUProfile() + } + + initParserMode() + initRewrite() + + if flag.NArg() == 0 { + if *write { + fmt.Fprintln(os.Stderr, "error: cannot use -w with standard input") + exitCode = 2 + return + } + if err := processFile("", os.Stdin, os.Stdout, true); err != nil { + report(err) + } + return + } + + for i := 0; i < flag.NArg(); i++ { + path := flag.Arg(i) + switch dir, err := os.Stat(path); { + case err != nil: + report(err) + case dir.IsDir(): + walkDir(path) + default: + if err := processFile(path, nil, os.Stdout, false); err != nil { + report(err) + } + } + } +} + +func diff(b1, b2 []byte) (data []byte, err error) { + f1, err := ioutil.TempFile("", "gofmt") + if err != nil { + return + } + defer os.Remove(f1.Name()) + defer f1.Close() + + f2, err := ioutil.TempFile("", "gofmt") + if err != nil { + return + } + defer os.Remove(f2.Name()) + defer f2.Close() + + f1.Write(b1) + f2.Write(b2) + + data, err = exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput() + if len(data) > 0 { + // diff exits with a non-zero status when the files don't match. + // Ignore that failure as long as we get output. + err = nil + } + return + +} + +// ---------------------------------------------------------------------------- +// Support functions +// +// The functions parse, format, and isSpace below are identical to the +// respective functions in src/go/format/format.go - keep them in sync! +// +// TODO(gri) Factor out this functionality, eventually. + +// parse parses src, which was read from the named file, +// as a Go source file, declaration, or statement list. +func parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) ( + file *ast.File, + sourceAdj func(src []byte, indent int) []byte, + indentAdj int, + err error, +) { + // Try as whole source file. + file, err = parser.ParseFile(fset, filename, src, parserMode) + // If there's no error, return. If the error is that the source file didn't begin with a + // package line and source fragments are ok, fall through to + // try as a source fragment. Stop and return on any other error. + if err == nil || !fragmentOk || !strings.Contains(err.Error(), "expected 'package'") { + return + } + + // If this is a declaration list, make it a source file + // by inserting a package clause. + // Insert using a ;, not a newline, so that the line numbers + // in psrc match the ones in src. + psrc := append([]byte("package p;"), src...) + file, err = parser.ParseFile(fset, filename, psrc, parserMode) + if err == nil { + sourceAdj = func(src []byte, indent int) []byte { + // Remove the package clause. + // Gofmt has turned the ; into a \n. + src = src[indent+len("package p\n"):] + return bytes.TrimSpace(src) + } + return + } + // If the error is that the source file didn't begin with a + // declaration, fall through to try as a statement list. + // Stop and return on any other error. + if !strings.Contains(err.Error(), "expected declaration") { + return + } + + // If this is a statement list, make it a source file + // by inserting a package clause and turning the list + // into a function body. This handles expressions too. + // Insert using a ;, not a newline, so that the line numbers + // in fsrc match the ones in src. + fsrc := append(append([]byte("package p; func _() {"), src...), '\n', '}') + file, err = parser.ParseFile(fset, filename, fsrc, parserMode) + if err == nil { + sourceAdj = func(src []byte, indent int) []byte { + // Cap adjusted indent to zero. + if indent < 0 { + indent = 0 + } + // Remove the wrapping. + // Gofmt has turned the ; into a \n\n. + // There will be two non-blank lines with indent, hence 2*indent. + src = src[2*indent+len("package p\n\nfunc _() {"):] + src = src[:len(src)-(indent+len("\n}\n"))] + return bytes.TrimSpace(src) + } + // Gofmt has also indented the function body one level. + // Adjust that with indentAdj. + indentAdj = -1 + } + + // Succeeded, or out of options. + return +} + +// format formats the given package file originally obtained from src +// and adjusts the result based on the original source via sourceAdj +// and indentAdj. +func format( + fset *token.FileSet, + file *ast.File, + sourceAdj func(src []byte, indent int) []byte, + indentAdj int, + src []byte, + cfg printer.Config, +) ([]byte, error) { + if sourceAdj == nil { + // Complete source file. + var buf bytes.Buffer + err := cfg.Fprint(&buf, fset, file) + if err != nil { + return nil, err + } + return buf.Bytes(), nil + } + + // Partial source file. + // Determine and prepend leading space. + i, j := 0, 0 + for j < len(src) && isSpace(src[j]) { + if src[j] == '\n' { + i = j + 1 // byte offset of last line in leading space + } + j++ + } + var res []byte + res = append(res, src[:i]...) + + // Determine and prepend indentation of first code line. + // Spaces are ignored unless there are no tabs, + // in which case spaces count as one tab. + indent := 0 + hasSpace := false + for _, b := range src[i:j] { + switch b { + case ' ': + hasSpace = true + case '\t': + indent++ + } + } + if indent == 0 && hasSpace { + indent = 1 + } + for i := 0; i < indent; i++ { + res = append(res, '\t') + } + + // Format the source. + // Write it without any leading and trailing space. + cfg.Indent = indent + indentAdj + var buf bytes.Buffer + err := cfg.Fprint(&buf, fset, file) + if err != nil { + return nil, err + } + res = append(res, sourceAdj(buf.Bytes(), cfg.Indent)...) + + // Determine and append trailing space. + i = len(src) + for i > 0 && isSpace(src[i-1]) { + i-- + } + return append(res, src[i:]...), nil +} + +func isSpace(b byte) bool { + return b == ' ' || b == '\t' || b == '\n' || b == '\r' +} diff --git a/libgo/go/cmd/gofmt/gofmt_test.go b/libgo/go/cmd/gofmt/gofmt_test.go new file mode 100644 index 0000000000..d1edb7bcc1 --- /dev/null +++ b/libgo/go/cmd/gofmt/gofmt_test.go @@ -0,0 +1,173 @@ +// 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 main + +import ( + "bytes" + "flag" + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + "text/scanner" +) + +var update = flag.Bool("update", false, "update .golden files") + +// gofmtFlags looks for a comment of the form +// +// //gofmt flags +// +// within the first maxLines lines of the given file, +// and returns the flags string, if any. Otherwise it +// returns the empty string. +func gofmtFlags(filename string, maxLines int) string { + f, err := os.Open(filename) + if err != nil { + return "" // ignore errors - they will be found later + } + defer f.Close() + + // initialize scanner + var s scanner.Scanner + s.Init(f) + s.Error = func(*scanner.Scanner, string) {} // ignore errors + s.Mode = scanner.GoTokens &^ scanner.SkipComments // want comments + + // look for //gofmt comment + for s.Line <= maxLines { + switch s.Scan() { + case scanner.Comment: + const prefix = "//gofmt " + if t := s.TokenText(); strings.HasPrefix(t, prefix) { + return strings.TrimSpace(t[len(prefix):]) + } + case scanner.EOF: + return "" + } + + } + + return "" +} + +func runTest(t *testing.T, in, out string) { + // process flags + *simplifyAST = false + *rewriteRule = "" + stdin := false + for _, flag := range strings.Split(gofmtFlags(in, 20), " ") { + elts := strings.SplitN(flag, "=", 2) + name := elts[0] + value := "" + if len(elts) == 2 { + value = elts[1] + } + switch name { + case "": + // no flags + case "-r": + *rewriteRule = value + case "-s": + *simplifyAST = true + case "-stdin": + // fake flag - pretend input is from stdin + stdin = true + default: + t.Errorf("unrecognized flag name: %s", name) + } + } + + initParserMode() + initRewrite() + + var buf bytes.Buffer + err := processFile(in, nil, &buf, stdin) + if err != nil { + t.Error(err) + return + } + + expected, err := ioutil.ReadFile(out) + if err != nil { + t.Error(err) + return + } + + if got := buf.Bytes(); !bytes.Equal(got, expected) { + if *update { + if in != out { + if err := ioutil.WriteFile(out, got, 0666); err != nil { + t.Error(err) + } + return + } + // in == out: don't accidentally destroy input + t.Errorf("WARNING: -update did not rewrite input file %s", in) + } + + t.Errorf("(gofmt %s) != %s (see %s.gofmt)", in, out, in) + d, err := diff(expected, got) + if err == nil { + t.Errorf("%s", d) + } + if err := ioutil.WriteFile(in+".gofmt", got, 0666); err != nil { + t.Error(err) + } + } +} + +// TestRewrite processes testdata/*.input files and compares them to the +// corresponding testdata/*.golden files. The gofmt flags used to process +// a file must be provided via a comment of the form +// +// //gofmt flags +// +// in the processed file within the first 20 lines, if any. +func TestRewrite(t *testing.T) { + // determine input files + match, err := filepath.Glob("testdata/*.input") + if err != nil { + t.Fatal(err) + } + + // add larger examples + match = append(match, "gofmt.go", "gofmt_test.go") + + for _, in := range match { + out := in // for files where input and output are identical + if strings.HasSuffix(in, ".input") { + out = in[:len(in)-len(".input")] + ".golden" + } + runTest(t, in, out) + if in != out { + // Check idempotence. + runTest(t, out, out) + } + } +} + +// Test case for issue 3961. +func TestCRLF(t *testing.T) { + const input = "testdata/crlf.input" // must contain CR/LF's + const golden = "testdata/crlf.golden" // must not contain any CR's + + data, err := ioutil.ReadFile(input) + if err != nil { + t.Error(err) + } + if bytes.Index(data, []byte("\r\n")) < 0 { + t.Errorf("%s contains no CR/LF's", input) + } + + data, err = ioutil.ReadFile(golden) + if err != nil { + t.Error(err) + } + if bytes.Index(data, []byte("\r")) >= 0 { + t.Errorf("%s contains CR's", golden) + } +} diff --git a/libgo/go/cmd/gofmt/long_test.go b/libgo/go/cmd/gofmt/long_test.go new file mode 100644 index 0000000000..237b86021b --- /dev/null +++ b/libgo/go/cmd/gofmt/long_test.go @@ -0,0 +1,159 @@ +// 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. + +// This test applies gofmt to all Go files under -root. +// To test specific files provide a list of comma-separated +// filenames via the -files flag: go test -files=gofmt.go . + +package main + +import ( + "bytes" + "flag" + "fmt" + "go/ast" + "go/printer" + "go/token" + "io" + "os" + "path/filepath" + "runtime" + "strings" + "testing" +) + +var ( + root = flag.String("root", runtime.GOROOT(), "test root directory") + files = flag.String("files", "", "comma-separated list of files to test") + ngo = flag.Int("n", runtime.NumCPU(), "number of goroutines used") + verbose = flag.Bool("verbose", false, "verbose mode") + nfiles int // number of files processed +) + +func gofmt(fset *token.FileSet, filename string, src *bytes.Buffer) error { + f, _, _, err := parse(fset, filename, src.Bytes(), false) + if err != nil { + return err + } + ast.SortImports(fset, f) + src.Reset() + return (&printer.Config{Mode: printerMode, Tabwidth: tabWidth}).Fprint(src, fset, f) +} + +func testFile(t *testing.T, b1, b2 *bytes.Buffer, filename string) { + // open file + f, err := os.Open(filename) + if err != nil { + t.Error(err) + return + } + + // read file + b1.Reset() + _, err = io.Copy(b1, f) + f.Close() + if err != nil { + t.Error(err) + return + } + + // exclude files w/ syntax errors (typically test cases) + fset := token.NewFileSet() + if _, _, _, err = parse(fset, filename, b1.Bytes(), false); err != nil { + if *verbose { + fmt.Fprintf(os.Stderr, "ignoring %s\n", err) + } + return + } + + // gofmt file + if err = gofmt(fset, filename, b1); err != nil { + t.Errorf("1st gofmt failed: %v", err) + return + } + + // make a copy of the result + b2.Reset() + b2.Write(b1.Bytes()) + + // gofmt result again + if err = gofmt(fset, filename, b2); err != nil { + t.Errorf("2nd gofmt failed: %v", err) + return + } + + // the first and 2nd result should be identical + if !bytes.Equal(b1.Bytes(), b2.Bytes()) { + t.Errorf("gofmt %s not idempotent", filename) + } +} + +func testFiles(t *testing.T, filenames <-chan string, done chan<- int) { + b1 := new(bytes.Buffer) + b2 := new(bytes.Buffer) + for filename := range filenames { + testFile(t, b1, b2, filename) + } + done <- 0 +} + +func genFilenames(t *testing.T, filenames chan<- string) { + defer close(filenames) + + handleFile := func(filename string, fi os.FileInfo, err error) error { + if err != nil { + t.Error(err) + return nil + } + if isGoFile(fi) { + filenames <- filename + nfiles++ + } + return nil + } + + // test Go files provided via -files, if any + if *files != "" { + for _, filename := range strings.Split(*files, ",") { + fi, err := os.Stat(filename) + handleFile(filename, fi, err) + } + return // ignore files under -root + } + + // otherwise, test all Go files under *root + filepath.Walk(*root, handleFile) +} + +func TestAll(t *testing.T) { + if testing.Short() { + return + } + + if *ngo < 1 { + *ngo = 1 // make sure test is run + } + if *verbose { + fmt.Printf("running test using %d goroutines\n", *ngo) + } + + // generate filenames + filenames := make(chan string, 32) + go genFilenames(t, filenames) + + // launch test goroutines + done := make(chan int) + for i := 0; i < *ngo; i++ { + go testFiles(t, filenames, done) + } + + // wait for all test goroutines to complete + for i := 0; i < *ngo; i++ { + <-done + } + + if *verbose { + fmt.Printf("processed %d files\n", nfiles) + } +} diff --git a/libgo/go/cmd/gofmt/rewrite.go b/libgo/go/cmd/gofmt/rewrite.go new file mode 100644 index 0000000000..d267cfcc1d --- /dev/null +++ b/libgo/go/cmd/gofmt/rewrite.go @@ -0,0 +1,303 @@ +// 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 main + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "os" + "reflect" + "strings" + "unicode" + "unicode/utf8" +) + +func initRewrite() { + if *rewriteRule == "" { + rewrite = nil // disable any previous rewrite + return + } + f := strings.Split(*rewriteRule, "->") + if len(f) != 2 { + fmt.Fprintf(os.Stderr, "rewrite rule must be of the form 'pattern -> replacement'\n") + os.Exit(2) + } + pattern := parseExpr(f[0], "pattern") + replace := parseExpr(f[1], "replacement") + rewrite = func(p *ast.File) *ast.File { return rewriteFile(pattern, replace, p) } +} + +// parseExpr parses s as an expression. +// It might make sense to expand this to allow statement patterns, +// but there are problems with preserving formatting and also +// with what a wildcard for a statement looks like. +func parseExpr(s, what string) ast.Expr { + x, err := parser.ParseExpr(s) + if err != nil { + fmt.Fprintf(os.Stderr, "parsing %s %s at %s\n", what, s, err) + os.Exit(2) + } + return x +} + +// Keep this function for debugging. +/* +func dump(msg string, val reflect.Value) { + fmt.Printf("%s:\n", msg) + ast.Print(fileSet, val.Interface()) + fmt.Println() +} +*/ + +// rewriteFile applies the rewrite rule 'pattern -> replace' to an entire file. +func rewriteFile(pattern, replace ast.Expr, p *ast.File) *ast.File { + cmap := ast.NewCommentMap(fileSet, p, p.Comments) + m := make(map[string]reflect.Value) + pat := reflect.ValueOf(pattern) + repl := reflect.ValueOf(replace) + + var rewriteVal func(val reflect.Value) reflect.Value + rewriteVal = func(val reflect.Value) reflect.Value { + // don't bother if val is invalid to start with + if !val.IsValid() { + return reflect.Value{} + } + for k := range m { + delete(m, k) + } + val = apply(rewriteVal, val) + if match(m, pat, val) { + val = subst(m, repl, reflect.ValueOf(val.Interface().(ast.Node).Pos())) + } + return val + } + + r := apply(rewriteVal, reflect.ValueOf(p)).Interface().(*ast.File) + r.Comments = cmap.Filter(r).Comments() // recreate comments list + return r +} + +// set is a wrapper for x.Set(y); it protects the caller from panics if x cannot be changed to y. +func set(x, y reflect.Value) { + // don't bother if x cannot be set or y is invalid + if !x.CanSet() || !y.IsValid() { + return + } + defer func() { + if x := recover(); x != nil { + if s, ok := x.(string); ok && + (strings.Contains(s, "type mismatch") || strings.Contains(s, "not assignable")) { + // x cannot be set to y - ignore this rewrite + return + } + panic(x) + } + }() + x.Set(y) +} + +// Values/types for special cases. +var ( + objectPtrNil = reflect.ValueOf((*ast.Object)(nil)) + scopePtrNil = reflect.ValueOf((*ast.Scope)(nil)) + + identType = reflect.TypeOf((*ast.Ident)(nil)) + objectPtrType = reflect.TypeOf((*ast.Object)(nil)) + positionType = reflect.TypeOf(token.NoPos) + callExprType = reflect.TypeOf((*ast.CallExpr)(nil)) + scopePtrType = reflect.TypeOf((*ast.Scope)(nil)) +) + +// apply replaces each AST field x in val with f(x), returning val. +// To avoid extra conversions, f operates on the reflect.Value form. +func apply(f func(reflect.Value) reflect.Value, val reflect.Value) reflect.Value { + if !val.IsValid() { + return reflect.Value{} + } + + // *ast.Objects introduce cycles and are likely incorrect after + // rewrite; don't follow them but replace with nil instead + if val.Type() == objectPtrType { + return objectPtrNil + } + + // similarly for scopes: they are likely incorrect after a rewrite; + // replace them with nil + if val.Type() == scopePtrType { + return scopePtrNil + } + + switch v := reflect.Indirect(val); v.Kind() { + case reflect.Slice: + for i := 0; i < v.Len(); i++ { + e := v.Index(i) + set(e, f(e)) + } + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + e := v.Field(i) + set(e, f(e)) + } + case reflect.Interface: + e := v.Elem() + set(v, f(e)) + } + return val +} + +func isWildcard(s string) bool { + rune, size := utf8.DecodeRuneInString(s) + return size == len(s) && unicode.IsLower(rune) +} + +// match returns true if pattern matches val, +// recording wildcard submatches in m. +// If m == nil, match checks whether pattern == val. +func match(m map[string]reflect.Value, pattern, val reflect.Value) bool { + // Wildcard matches any expression. If it appears multiple + // times in the pattern, it must match the same expression + // each time. + if m != nil && pattern.IsValid() && pattern.Type() == identType { + name := pattern.Interface().(*ast.Ident).Name + if isWildcard(name) && val.IsValid() { + // wildcards only match valid (non-nil) expressions. + if _, ok := val.Interface().(ast.Expr); ok && !val.IsNil() { + if old, ok := m[name]; ok { + return match(nil, old, val) + } + m[name] = val + return true + } + } + } + + // Otherwise, pattern and val must match recursively. + if !pattern.IsValid() || !val.IsValid() { + return !pattern.IsValid() && !val.IsValid() + } + if pattern.Type() != val.Type() { + return false + } + + // Special cases. + switch pattern.Type() { + case identType: + // For identifiers, only the names need to match + // (and none of the other *ast.Object information). + // This is a common case, handle it all here instead + // of recursing down any further via reflection. + p := pattern.Interface().(*ast.Ident) + v := val.Interface().(*ast.Ident) + return p == nil && v == nil || p != nil && v != nil && p.Name == v.Name + case objectPtrType, positionType: + // object pointers and token positions always match + return true + case callExprType: + // For calls, the Ellipsis fields (token.Position) must + // match since that is how f(x) and f(x...) are different. + // Check them here but fall through for the remaining fields. + p := pattern.Interface().(*ast.CallExpr) + v := val.Interface().(*ast.CallExpr) + if p.Ellipsis.IsValid() != v.Ellipsis.IsValid() { + return false + } + } + + p := reflect.Indirect(pattern) + v := reflect.Indirect(val) + if !p.IsValid() || !v.IsValid() { + return !p.IsValid() && !v.IsValid() + } + + switch p.Kind() { + case reflect.Slice: + if p.Len() != v.Len() { + return false + } + for i := 0; i < p.Len(); i++ { + if !match(m, p.Index(i), v.Index(i)) { + return false + } + } + return true + + case reflect.Struct: + for i := 0; i < p.NumField(); i++ { + if !match(m, p.Field(i), v.Field(i)) { + return false + } + } + return true + + case reflect.Interface: + return match(m, p.Elem(), v.Elem()) + } + + // Handle token integers, etc. + return p.Interface() == v.Interface() +} + +// subst returns a copy of pattern with values from m substituted in place +// of wildcards and pos used as the position of tokens from the pattern. +// if m == nil, subst returns a copy of pattern and doesn't change the line +// number information. +func subst(m map[string]reflect.Value, pattern reflect.Value, pos reflect.Value) reflect.Value { + if !pattern.IsValid() { + return reflect.Value{} + } + + // Wildcard gets replaced with map value. + if m != nil && pattern.Type() == identType { + name := pattern.Interface().(*ast.Ident).Name + if isWildcard(name) { + if old, ok := m[name]; ok { + return subst(nil, old, reflect.Value{}) + } + } + } + + if pos.IsValid() && pattern.Type() == positionType { + // use new position only if old position was valid in the first place + if old := pattern.Interface().(token.Pos); !old.IsValid() { + return pattern + } + return pos + } + + // Otherwise copy. + switch p := pattern; p.Kind() { + case reflect.Slice: + v := reflect.MakeSlice(p.Type(), p.Len(), p.Len()) + for i := 0; i < p.Len(); i++ { + v.Index(i).Set(subst(m, p.Index(i), pos)) + } + return v + + case reflect.Struct: + v := reflect.New(p.Type()).Elem() + for i := 0; i < p.NumField(); i++ { + v.Field(i).Set(subst(m, p.Field(i), pos)) + } + return v + + case reflect.Ptr: + v := reflect.New(p.Type()).Elem() + if elem := p.Elem(); elem.IsValid() { + v.Set(subst(m, elem, pos).Addr()) + } + return v + + case reflect.Interface: + v := reflect.New(p.Type()).Elem() + if elem := p.Elem(); elem.IsValid() { + v.Set(subst(m, elem, pos)) + } + return v + } + + return pattern +} diff --git a/libgo/go/cmd/gofmt/simplify.go b/libgo/go/cmd/gofmt/simplify.go new file mode 100644 index 0000000000..69f7bf23c0 --- /dev/null +++ b/libgo/go/cmd/gofmt/simplify.go @@ -0,0 +1,161 @@ +// Copyright 2010 The Go Authors. 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 ( + "go/ast" + "go/token" + "reflect" +) + +type simplifier struct { + hasDotImport bool // package file contains: import . "some/import/path" +} + +func (s *simplifier) Visit(node ast.Node) ast.Visitor { + switch n := node.(type) { + case *ast.CompositeLit: + // array, slice, and map composite literals may be simplified + outer := n + var eltType ast.Expr + switch typ := outer.Type.(type) { + case *ast.ArrayType: + eltType = typ.Elt + case *ast.MapType: + eltType = typ.Value + } + + if eltType != nil { + typ := reflect.ValueOf(eltType) + for i, x := range outer.Elts { + px := &outer.Elts[i] + // look at value of indexed/named elements + if t, ok := x.(*ast.KeyValueExpr); ok { + x = t.Value + px = &t.Value + } + ast.Walk(s, x) // simplify x + // if the element is a composite literal and its literal type + // matches the outer literal's element type exactly, the inner + // literal type may be omitted + if inner, ok := x.(*ast.CompositeLit); ok { + if match(nil, typ, reflect.ValueOf(inner.Type)) { + inner.Type = nil + } + } + // if the outer literal's element type is a pointer type *T + // and the element is & of a composite literal of type T, + // the inner &T may be omitted. + if ptr, ok := eltType.(*ast.StarExpr); ok { + if addr, ok := x.(*ast.UnaryExpr); ok && addr.Op == token.AND { + if inner, ok := addr.X.(*ast.CompositeLit); ok { + if match(nil, reflect.ValueOf(ptr.X), reflect.ValueOf(inner.Type)) { + inner.Type = nil // drop T + *px = inner // drop & + } + } + } + } + } + + // node was simplified - stop walk (there are no subnodes to simplify) + return nil + } + + case *ast.SliceExpr: + // a slice expression of the form: s[a:len(s)] + // can be simplified to: s[a:] + // if s is "simple enough" (for now we only accept identifiers) + if n.Max != nil || s.hasDotImport { + // - 3-index slices always require the 2nd and 3rd index + // - if dot imports are present, we cannot be certain that an + // unresolved "len" identifier refers to the predefined len() + break + } + if s, _ := n.X.(*ast.Ident); s != nil && s.Obj != nil { + // the array/slice object is a single, resolved identifier + if call, _ := n.High.(*ast.CallExpr); call != nil && len(call.Args) == 1 && !call.Ellipsis.IsValid() { + // the high expression is a function call with a single argument + if fun, _ := call.Fun.(*ast.Ident); fun != nil && fun.Name == "len" && fun.Obj == nil { + // the function called is "len" and it is not locally defined; and + // because we don't have dot imports, it must be the predefined len() + if arg, _ := call.Args[0].(*ast.Ident); arg != nil && arg.Obj == s.Obj { + // the len argument is the array/slice object + n.High = nil + } + } + } + } + // Note: We could also simplify slice expressions of the form s[0:b] to s[:b] + // but we leave them as is since sometimes we want to be very explicit + // about the lower bound. + // An example where the 0 helps: + // x, y, z := b[0:2], b[2:4], b[4:6] + // An example where it does not: + // x, y := b[:n], b[n:] + + case *ast.RangeStmt: + // - a range of the form: for x, _ = range v {...} + // can be simplified to: for x = range v {...} + // - a range of the form: for _ = range v {...} + // can be simplified to: for range v {...} + if isBlank(n.Value) { + n.Value = nil + } + if isBlank(n.Key) && n.Value == nil { + n.Key = nil + } + } + + return s +} + +func isBlank(x ast.Expr) bool { + ident, ok := x.(*ast.Ident) + return ok && ident.Name == "_" +} + +func simplify(f *ast.File) { + var s simplifier + + // determine if f contains dot imports + for _, imp := range f.Imports { + if imp.Name != nil && imp.Name.Name == "." { + s.hasDotImport = true + break + } + } + + // remove empty declarations such as "const ()", etc + removeEmptyDeclGroups(f) + + ast.Walk(&s, f) +} + +func removeEmptyDeclGroups(f *ast.File) { + i := 0 + for _, d := range f.Decls { + if g, ok := d.(*ast.GenDecl); !ok || !isEmpty(f, g) { + f.Decls[i] = d + i++ + } + } + f.Decls = f.Decls[:i] +} + +func isEmpty(f *ast.File, g *ast.GenDecl) bool { + if g.Doc != nil || g.Specs != nil { + return false + } + + for _, c := range f.Comments { + // if there is a comment in the declaration, it is not considered empty + if g.Pos() <= c.Pos() && c.End() <= g.End() { + return false + } + } + + return true +} diff --git a/libgo/go/cmd/gofmt/testdata/comments.golden b/libgo/go/cmd/gofmt/testdata/comments.golden new file mode 100644 index 0000000000..ad6bcafafa --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/comments.golden @@ -0,0 +1,9 @@ +package main + +func main() {} + +// comment here + +func f() {} + +//line foo.go:1 diff --git a/libgo/go/cmd/gofmt/testdata/comments.input b/libgo/go/cmd/gofmt/testdata/comments.input new file mode 100644 index 0000000000..ad6bcafafa --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/comments.input @@ -0,0 +1,9 @@ +package main + +func main() {} + +// comment here + +func f() {} + +//line foo.go:1 diff --git a/libgo/go/cmd/gofmt/testdata/composites.golden b/libgo/go/cmd/gofmt/testdata/composites.golden new file mode 100644 index 0000000000..fc9c98e625 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/composites.golden @@ -0,0 +1,204 @@ +//gofmt -s + +package P + +type T struct { + x, y int +} + +var _ = [42]T{ + {}, + {1, 2}, + {3, 4}, +} + +var _ = [...]T{ + {}, + {1, 2}, + {3, 4}, +} + +var _ = []T{ + {}, + {1, 2}, + {3, 4}, +} + +var _ = []T{ + {}, + 10: {1, 2}, + 20: {3, 4}, +} + +var _ = []struct { + x, y int +}{ + {}, + 10: {1, 2}, + 20: {3, 4}, +} + +var _ = []interface{}{ + T{}, + 10: T{1, 2}, + 20: T{3, 4}, +} + +var _ = [][]int{ + {}, + {1, 2}, + {3, 4}, +} + +var _ = [][]int{ + ([]int{}), + ([]int{1, 2}), + {3, 4}, +} + +var _ = [][][]int{ + {}, + { + {}, + {0, 1, 2, 3}, + {4, 5}, + }, +} + +var _ = map[string]T{ + "foo": {}, + "bar": {1, 2}, + "bal": {3, 4}, +} + +var _ = map[string]struct { + x, y int +}{ + "foo": {}, + "bar": {1, 2}, + "bal": {3, 4}, +} + +var _ = map[string]interface{}{ + "foo": T{}, + "bar": T{1, 2}, + "bal": T{3, 4}, +} + +var _ = map[string][]int{ + "foo": {}, + "bar": {1, 2}, + "bal": {3, 4}, +} + +var _ = map[string][]int{ + "foo": ([]int{}), + "bar": ([]int{1, 2}), + "bal": {3, 4}, +} + +// from exp/4s/data.go +var pieces4 = []Piece{ + {0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, + {1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, + {2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, + {3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, +} + +var _ = [42]*T{ + {}, + {1, 2}, + {3, 4}, +} + +var _ = [...]*T{ + {}, + {1, 2}, + {3, 4}, +} + +var _ = []*T{ + {}, + {1, 2}, + {3, 4}, +} + +var _ = []*T{ + {}, + 10: {1, 2}, + 20: {3, 4}, +} + +var _ = []*struct { + x, y int +}{ + {}, + 10: {1, 2}, + 20: {3, 4}, +} + +var _ = []interface{}{ + &T{}, + 10: &T{1, 2}, + 20: &T{3, 4}, +} + +var _ = []*[]int{ + {}, + {1, 2}, + {3, 4}, +} + +var _ = []*[]int{ + (&[]int{}), + (&[]int{1, 2}), + {3, 4}, +} + +var _ = []*[]*[]int{ + {}, + { + {}, + {0, 1, 2, 3}, + {4, 5}, + }, +} + +var _ = map[string]*T{ + "foo": {}, + "bar": {1, 2}, + "bal": {3, 4}, +} + +var _ = map[string]*struct { + x, y int +}{ + "foo": {}, + "bar": {1, 2}, + "bal": {3, 4}, +} + +var _ = map[string]interface{}{ + "foo": &T{}, + "bar": &T{1, 2}, + "bal": &T{3, 4}, +} + +var _ = map[string]*[]int{ + "foo": {}, + "bar": {1, 2}, + "bal": {3, 4}, +} + +var _ = map[string]*[]int{ + "foo": (&[]int{}), + "bar": (&[]int{1, 2}), + "bal": {3, 4}, +} + +var pieces4 = []*Piece{ + {0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, + {1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, + {2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, + {3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, +} diff --git a/libgo/go/cmd/gofmt/testdata/composites.input b/libgo/go/cmd/gofmt/testdata/composites.input new file mode 100644 index 0000000000..fc7598af99 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/composites.input @@ -0,0 +1,204 @@ +//gofmt -s + +package P + +type T struct { + x, y int +} + +var _ = [42]T{ + T{}, + T{1, 2}, + T{3, 4}, +} + +var _ = [...]T{ + T{}, + T{1, 2}, + T{3, 4}, +} + +var _ = []T{ + T{}, + T{1, 2}, + T{3, 4}, +} + +var _ = []T{ + T{}, + 10: T{1, 2}, + 20: T{3, 4}, +} + +var _ = []struct { + x, y int +}{ + struct{ x, y int }{}, + 10: struct{ x, y int }{1, 2}, + 20: struct{ x, y int }{3, 4}, +} + +var _ = []interface{}{ + T{}, + 10: T{1, 2}, + 20: T{3, 4}, +} + +var _ = [][]int{ + []int{}, + []int{1, 2}, + []int{3, 4}, +} + +var _ = [][]int{ + ([]int{}), + ([]int{1, 2}), + []int{3, 4}, +} + +var _ = [][][]int{ + [][]int{}, + [][]int{ + []int{}, + []int{0, 1, 2, 3}, + []int{4, 5}, + }, +} + +var _ = map[string]T{ + "foo": T{}, + "bar": T{1, 2}, + "bal": T{3, 4}, +} + +var _ = map[string]struct { + x, y int +}{ + "foo": struct{ x, y int }{}, + "bar": struct{ x, y int }{1, 2}, + "bal": struct{ x, y int }{3, 4}, +} + +var _ = map[string]interface{}{ + "foo": T{}, + "bar": T{1, 2}, + "bal": T{3, 4}, +} + +var _ = map[string][]int{ + "foo": []int{}, + "bar": []int{1, 2}, + "bal": []int{3, 4}, +} + +var _ = map[string][]int{ + "foo": ([]int{}), + "bar": ([]int{1, 2}), + "bal": []int{3, 4}, +} + +// from exp/4s/data.go +var pieces4 = []Piece{ + Piece{0, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, + Piece{1, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, + Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, + Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, +} + +var _ = [42]*T{ + &T{}, + &T{1, 2}, + &T{3, 4}, +} + +var _ = [...]*T{ + &T{}, + &T{1, 2}, + &T{3, 4}, +} + +var _ = []*T{ + &T{}, + &T{1, 2}, + &T{3, 4}, +} + +var _ = []*T{ + &T{}, + 10: &T{1, 2}, + 20: &T{3, 4}, +} + +var _ = []*struct { + x, y int +}{ + &struct{ x, y int }{}, + 10: &struct{ x, y int }{1, 2}, + 20: &struct{ x, y int }{3, 4}, +} + +var _ = []interface{}{ + &T{}, + 10: &T{1, 2}, + 20: &T{3, 4}, +} + +var _ = []*[]int{ + &[]int{}, + &[]int{1, 2}, + &[]int{3, 4}, +} + +var _ = []*[]int{ + (&[]int{}), + (&[]int{1, 2}), + &[]int{3, 4}, +} + +var _ = []*[]*[]int{ + &[]*[]int{}, + &[]*[]int{ + &[]int{}, + &[]int{0, 1, 2, 3}, + &[]int{4, 5}, + }, +} + +var _ = map[string]*T{ + "foo": &T{}, + "bar": &T{1, 2}, + "bal": &T{3, 4}, +} + +var _ = map[string]*struct { + x, y int +}{ + "foo": &struct{ x, y int }{}, + "bar": &struct{ x, y int }{1, 2}, + "bal": &struct{ x, y int }{3, 4}, +} + +var _ = map[string]interface{}{ + "foo": &T{}, + "bar": &T{1, 2}, + "bal": &T{3, 4}, +} + +var _ = map[string]*[]int{ + "foo": &[]int{}, + "bar": &[]int{1, 2}, + "bal": &[]int{3, 4}, +} + +var _ = map[string]*[]int{ + "foo": (&[]int{}), + "bar": (&[]int{1, 2}), + "bal": &[]int{3, 4}, +} + +var pieces4 = []*Piece{ + &Piece{0, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, + &Piece{1, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, + &Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, + &Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, +} diff --git a/libgo/go/cmd/gofmt/testdata/crlf.golden b/libgo/go/cmd/gofmt/testdata/crlf.golden new file mode 100644 index 0000000000..193dbacc72 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/crlf.golden @@ -0,0 +1,13 @@ +/* + Source containing CR/LF line endings. + The gofmt'ed output must only have LF + line endings. + Test case for issue 3961. +*/ +package main + +func main() { + // line comment + println("hello, world!") // another line comment + println() +} diff --git a/libgo/go/cmd/gofmt/testdata/crlf.input b/libgo/go/cmd/gofmt/testdata/crlf.input new file mode 100644 index 0000000000..ae7e14dbf1 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/crlf.input @@ -0,0 +1,13 @@ +/* + Source containing CR/LF line endings. + The gofmt'ed output must only have LF + line endings. + Test case for issue 3961. +*/ +package main + +func main() { + // line comment + println("hello, world!") // another line comment + println() +} diff --git a/libgo/go/cmd/gofmt/testdata/import.golden b/libgo/go/cmd/gofmt/testdata/import.golden new file mode 100644 index 0000000000..51d7be79df --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/import.golden @@ -0,0 +1,126 @@ +package main + +import ( + "errors" + "fmt" + "io" + "log" + "math" +) + +import ( + "fmt" + + "math" + + "log" + + "errors" + + "io" +) + +import ( + "errors" + "fmt" + "io" + "log" + "math" + + "fmt" + + "math" + + "log" + + "errors" + + "io" +) + +import ( + // a block with comments + "errors" + "fmt" // for Printf + "io" // for Reader + "log" // for Fatal + "math" +) + +import ( + "fmt" // for Printf + + "math" + + "log" // for Fatal + + "errors" + + "io" // for Reader +) + +import ( + // for Printf + "fmt" + + "math" + + // for Fatal + "log" + + "errors" + + // for Reader + "io" +) + +import ( + "errors" + "fmt" // for Printf + "io" // for Reader + "log" // for Fatal + "math" + + "fmt" // for Printf + + "math" + + "log" // for Fatal + + "errors" + + "io" // for Reader +) + +import ( + "fmt" // for Printf + + "errors" + "io" // for Reader + "log" // for Fatal + "math" + + "errors" + "fmt" // for Printf + "io" // for Reader + "log" // for Fatal + "math" +) + +// Test deduping and extended sorting +import ( + a "A" // aA + b "A" // bA1 + b "A" // bA2 + "B" // B + . "B" // .B + _ "B" // _b + "C" + a "D" // aD +) + +import ( + "dedup_by_group" + + "dedup_by_group" +) diff --git a/libgo/go/cmd/gofmt/testdata/import.input b/libgo/go/cmd/gofmt/testdata/import.input new file mode 100644 index 0000000000..9a4b09dbf9 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/import.input @@ -0,0 +1,131 @@ +package main + +import ( + "fmt" + "math" + "log" + "errors" + "io" +) + +import ( + "fmt" + + "math" + + "log" + + "errors" + + "io" +) + +import ( + "fmt" + "math" + "log" + "errors" + "io" + + "fmt" + + "math" + + "log" + + "errors" + + "io" +) + +import ( + // a block with comments + "fmt" // for Printf + "math" + "log" // for Fatal + "errors" + "io" // for Reader +) + +import ( + "fmt" // for Printf + + "math" + + "log" // for Fatal + + "errors" + + "io" // for Reader +) + +import ( + // for Printf + "fmt" + + "math" + + // for Fatal + "log" + + "errors" + + // for Reader + "io" +) + +import ( + "fmt" // for Printf + "math" + "log" // for Fatal + "errors" + "io" // for Reader + + "fmt" // for Printf + + "math" + + "log" // for Fatal + + "errors" + + "io" // for Reader +) + +import ( + "fmt" // for Printf + + "math" + "log" // for Fatal + "errors" + "io" // for Reader + + "fmt" // for Printf + "math" + "log" // for Fatal + "errors" + "io" // for Reader +) + +// Test deduping and extended sorting +import ( + "B" // B + a "A" // aA + b "A" // bA2 + b "A" // bA1 + . "B" // .B + . "B" + "C" + "C" + "C" + a "D" // aD + "B" + _ "B" // _b +) + +import ( + "dedup_by_group" + "dedup_by_group" + + "dedup_by_group" +) diff --git a/libgo/go/cmd/gofmt/testdata/old.golden b/libgo/go/cmd/gofmt/testdata/old.golden new file mode 100644 index 0000000000..95a0b72a0e --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/old.golden @@ -0,0 +1,9 @@ +package P + +func f() { + if x { + y + } else { + z + } +} diff --git a/libgo/go/cmd/gofmt/testdata/old.input b/libgo/go/cmd/gofmt/testdata/old.input new file mode 100644 index 0000000000..e24eed215d --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/old.input @@ -0,0 +1,8 @@ +package P + +func f() { + if x { + y + } else + z +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite1.golden b/libgo/go/cmd/gofmt/testdata/rewrite1.golden new file mode 100644 index 0000000000..3ee5373a79 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite1.golden @@ -0,0 +1,14 @@ +//gofmt -r=Foo->Bar + +// 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 main + +type Bar int + +func main() { + var a Bar + println(a) +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite1.input b/libgo/go/cmd/gofmt/testdata/rewrite1.input new file mode 100644 index 0000000000..a84c8f7816 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite1.input @@ -0,0 +1,14 @@ +//gofmt -r=Foo->Bar + +// 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 main + +type Foo int + +func main() { + var a Foo + println(a) +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite2.golden b/libgo/go/cmd/gofmt/testdata/rewrite2.golden new file mode 100644 index 0000000000..f980e03530 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite2.golden @@ -0,0 +1,12 @@ +//gofmt -r=int->bool + +// 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 p + +// Slices have nil Len values in the corresponding ast.ArrayType +// node and reflect.NewValue(slice.Len) is an invalid reflect.Value. +// The rewriter must not crash in that case. Was issue 1696. +func f() []bool {} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite2.input b/libgo/go/cmd/gofmt/testdata/rewrite2.input new file mode 100644 index 0000000000..489be4e07d --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite2.input @@ -0,0 +1,12 @@ +//gofmt -r=int->bool + +// 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 p + +// Slices have nil Len values in the corresponding ast.ArrayType +// node and reflect.NewValue(slice.Len) is an invalid reflect.Value. +// The rewriter must not crash in that case. Was issue 1696. +func f() []int {} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite3.golden b/libgo/go/cmd/gofmt/testdata/rewrite3.golden new file mode 100644 index 0000000000..261a220c65 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite3.golden @@ -0,0 +1,14 @@ +//gofmt -r=x->x + +// 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 main + +// Field tags are *ast.BasicLit nodes that are nil when the tag is +// absent. These nil nodes must not be mistaken for expressions, +// the rewriter should not try to dereference them. Was issue 2410. +type Foo struct { + Field int +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite3.input b/libgo/go/cmd/gofmt/testdata/rewrite3.input new file mode 100644 index 0000000000..261a220c65 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite3.input @@ -0,0 +1,14 @@ +//gofmt -r=x->x + +// 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 main + +// Field tags are *ast.BasicLit nodes that are nil when the tag is +// absent. These nil nodes must not be mistaken for expressions, +// the rewriter should not try to dereference them. Was issue 2410. +type Foo struct { + Field int +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite4.golden b/libgo/go/cmd/gofmt/testdata/rewrite4.golden new file mode 100644 index 0000000000..b05547b4bf --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite4.golden @@ -0,0 +1,76 @@ +//gofmt -r=(x)->x + +// 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. + +// Rewriting of parenthesized expressions (x) -> x +// must not drop parentheses if that would lead to +// wrong association of the operands. +// Was issue 1847. + +package main + +// From example 1 of issue 1847. +func _() { + var t = (&T{1000}).Id() +} + +// From example 2 of issue 1847. +func _() { + fmt.Println((*xpp).a) +} + +// Some more test cases. +func _() { + _ = (-x).f + _ = (*x).f + _ = (&x).f + _ = (!x).f + _ = -x.f + _ = *x.f + _ = &x.f + _ = !x.f + (-x).f() + (*x).f() + (&x).f() + (!x).f() + _ = -x.f() + _ = *x.f() + _ = &x.f() + _ = !x.f() + + _ = (-x).f + _ = (*x).f + _ = (&x).f + _ = (!x).f + _ = -x.f + _ = *x.f + _ = &x.f + _ = !x.f + (-x).f() + (*x).f() + (&x).f() + (!x).f() + _ = -x.f() + _ = *x.f() + _ = &x.f() + _ = !x.f() + + _ = -x.f + _ = *x.f + _ = &x.f + _ = !x.f + _ = -x.f + _ = *x.f + _ = &x.f + _ = !x.f + _ = -x.f() + _ = *x.f() + _ = &x.f() + _ = !x.f() + _ = -x.f() + _ = *x.f() + _ = &x.f() + _ = !x.f() +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite4.input b/libgo/go/cmd/gofmt/testdata/rewrite4.input new file mode 100644 index 0000000000..0817099209 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite4.input @@ -0,0 +1,76 @@ +//gofmt -r=(x)->x + +// 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. + +// Rewriting of parenthesized expressions (x) -> x +// must not drop parentheses if that would lead to +// wrong association of the operands. +// Was issue 1847. + +package main + +// From example 1 of issue 1847. +func _() { + var t = (&T{1000}).Id() +} + +// From example 2 of issue 1847. +func _() { + fmt.Println((*xpp).a) +} + +// Some more test cases. +func _() { + _ = (-x).f + _ = (*x).f + _ = (&x).f + _ = (!x).f + _ = (-x.f) + _ = (*x.f) + _ = (&x.f) + _ = (!x.f) + (-x).f() + (*x).f() + (&x).f() + (!x).f() + _ = (-x.f()) + _ = (*x.f()) + _ = (&x.f()) + _ = (!x.f()) + + _ = ((-x)).f + _ = ((*x)).f + _ = ((&x)).f + _ = ((!x)).f + _ = ((-x.f)) + _ = ((*x.f)) + _ = ((&x.f)) + _ = ((!x.f)) + ((-x)).f() + ((*x)).f() + ((&x)).f() + ((!x)).f() + _ = ((-x.f())) + _ = ((*x.f())) + _ = ((&x.f())) + _ = ((!x.f())) + + _ = -(x).f + _ = *(x).f + _ = &(x).f + _ = !(x).f + _ = -x.f + _ = *x.f + _ = &x.f + _ = !x.f + _ = -(x).f() + _ = *(x).f() + _ = &(x).f() + _ = !(x).f() + _ = -x.f() + _ = *x.f() + _ = &x.f() + _ = !x.f() +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite5.golden b/libgo/go/cmd/gofmt/testdata/rewrite5.golden new file mode 100644 index 0000000000..9beb34aee7 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite5.golden @@ -0,0 +1,17 @@ +//gofmt -r=x+x->2*x + +// 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. + +// Rewriting of expressions containing nodes with associated comments to +// expressions without those nodes must also eliminate the associated +// comments. + +package p + +func f(x int) int { + _ = 2 * x // this comment remains in the rewrite + _ = 2 * x + return 2 * x +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite5.input b/libgo/go/cmd/gofmt/testdata/rewrite5.input new file mode 100644 index 0000000000..d7a6122d07 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite5.input @@ -0,0 +1,17 @@ +//gofmt -r=x+x->2*x + +// 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. + +// Rewriting of expressions containing nodes with associated comments to +// expressions without those nodes must also eliminate the associated +// comments. + +package p + +func f(x int) int { + _ = x + x // this comment remains in the rewrite + _ = x /* this comment must not be in the rewrite */ + x + return x /* this comment must not be in the rewrite */ + x +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite6.golden b/libgo/go/cmd/gofmt/testdata/rewrite6.golden new file mode 100644 index 0000000000..48ec9aa0df --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite6.golden @@ -0,0 +1,17 @@ +//gofmt -r=fun(x)->Fun(x) + +// 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. + +// Rewriting of calls must take the ... (ellipsis) +// attribute for the last argument into account. + +package p + +func fun(x []int) {} + +func g(x []int) { + Fun(x) // -r='fun(x)->Fun(x)' should rewrite this to Fun(x) + fun(x...) // -r='fun(x)->Fun(x)' should not rewrite this +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite6.input b/libgo/go/cmd/gofmt/testdata/rewrite6.input new file mode 100644 index 0000000000..b085a84fef --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite6.input @@ -0,0 +1,17 @@ +//gofmt -r=fun(x)->Fun(x) + +// 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. + +// Rewriting of calls must take the ... (ellipsis) +// attribute for the last argument into account. + +package p + +func fun(x []int) {} + +func g(x []int) { + fun(x) // -r='fun(x)->Fun(x)' should rewrite this to Fun(x) + fun(x...) // -r='fun(x)->Fun(x)' should not rewrite this +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite7.golden b/libgo/go/cmd/gofmt/testdata/rewrite7.golden new file mode 100644 index 0000000000..8386a0b2a3 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite7.golden @@ -0,0 +1,17 @@ +//gofmt -r=fun(x...)->Fun(x) + +// 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. + +// Rewriting of calls must take the ... (ellipsis) +// attribute for the last argument into account. + +package p + +func fun(x []int) {} + +func g(x []int) { + fun(x) // -r='fun(x...)->Fun(x)' should not rewrite this + Fun(x) // -r='fun(x...)->Fun(x)' should rewrite this to Fun(x) +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite7.input b/libgo/go/cmd/gofmt/testdata/rewrite7.input new file mode 100644 index 0000000000..c1984708e7 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite7.input @@ -0,0 +1,17 @@ +//gofmt -r=fun(x...)->Fun(x) + +// 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. + +// Rewriting of calls must take the ... (ellipsis) +// attribute for the last argument into account. + +package p + +func fun(x []int) {} + +func g(x []int) { + fun(x) // -r='fun(x...)->Fun(x)' should not rewrite this + fun(x...) // -r='fun(x...)->Fun(x)' should rewrite this to Fun(x) +} diff --git a/libgo/go/cmd/gofmt/testdata/rewrite8.golden b/libgo/go/cmd/gofmt/testdata/rewrite8.golden new file mode 100644 index 0000000000..62f0419dfb --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite8.golden @@ -0,0 +1,12 @@ +//gofmt -r=interface{}->int + +// 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. + +// Check that literal type expression rewrites are accepted. +// Was issue 4406. + +package p + +type T int diff --git a/libgo/go/cmd/gofmt/testdata/rewrite8.input b/libgo/go/cmd/gofmt/testdata/rewrite8.input new file mode 100644 index 0000000000..7964c5c75c --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/rewrite8.input @@ -0,0 +1,12 @@ +//gofmt -r=interface{}->int + +// 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. + +// Check that literal type expression rewrites are accepted. +// Was issue 4406. + +package p + +type T interface{} diff --git a/libgo/go/cmd/gofmt/testdata/slices1.golden b/libgo/go/cmd/gofmt/testdata/slices1.golden new file mode 100644 index 0000000000..04bc16f216 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/slices1.golden @@ -0,0 +1,66 @@ +//gofmt -s + +// Test cases for slice expression simplification. +package p + +var ( + a [10]byte + b [20]float32 + s []int + t struct { + s []byte + } + + _ = a[0:] + _ = a[1:10] + _ = a[2:] + _ = a[3:(len(a))] + _ = a[len(a) : len(a)-1] + _ = a[0:len(b)] + _ = a[2:len(a):len(a)] + + _ = a[:] + _ = a[:10] + _ = a[:] + _ = a[:(len(a))] + _ = a[:len(a)-1] + _ = a[:len(b)] + _ = a[:len(a):len(a)] + + _ = s[0:] + _ = s[1:10] + _ = s[2:] + _ = s[3:(len(s))] + _ = s[len(a) : len(s)-1] + _ = s[0:len(b)] + _ = s[2:len(s):len(s)] + + _ = s[:] + _ = s[:10] + _ = s[:] + _ = s[:(len(s))] + _ = s[:len(s)-1] + _ = s[:len(b)] + _ = s[:len(s):len(s)] + + _ = t.s[0:] + _ = t.s[1:10] + _ = t.s[2:len(t.s)] + _ = t.s[3:(len(t.s))] + _ = t.s[len(a) : len(t.s)-1] + _ = t.s[0:len(b)] + _ = t.s[2:len(t.s):len(t.s)] + + _ = t.s[:] + _ = t.s[:10] + _ = t.s[:len(t.s)] + _ = t.s[:(len(t.s))] + _ = t.s[:len(t.s)-1] + _ = t.s[:len(b)] + _ = t.s[:len(t.s):len(t.s)] +) + +func _() { + s := s[0:] + _ = s +} diff --git a/libgo/go/cmd/gofmt/testdata/slices1.input b/libgo/go/cmd/gofmt/testdata/slices1.input new file mode 100644 index 0000000000..1f25c43ccb --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/slices1.input @@ -0,0 +1,66 @@ +//gofmt -s + +// Test cases for slice expression simplification. +package p + +var ( + a [10]byte + b [20]float32 + s []int + t struct { + s []byte + } + + _ = a[0:] + _ = a[1:10] + _ = a[2:len(a)] + _ = a[3:(len(a))] + _ = a[len(a) : len(a)-1] + _ = a[0:len(b)] + _ = a[2:len(a):len(a)] + + _ = a[:] + _ = a[:10] + _ = a[:len(a)] + _ = a[:(len(a))] + _ = a[:len(a)-1] + _ = a[:len(b)] + _ = a[:len(a):len(a)] + + _ = s[0:] + _ = s[1:10] + _ = s[2:len(s)] + _ = s[3:(len(s))] + _ = s[len(a) : len(s)-1] + _ = s[0:len(b)] + _ = s[2:len(s):len(s)] + + _ = s[:] + _ = s[:10] + _ = s[:len(s)] + _ = s[:(len(s))] + _ = s[:len(s)-1] + _ = s[:len(b)] + _ = s[:len(s):len(s)] + + _ = t.s[0:] + _ = t.s[1:10] + _ = t.s[2:len(t.s)] + _ = t.s[3:(len(t.s))] + _ = t.s[len(a) : len(t.s)-1] + _ = t.s[0:len(b)] + _ = t.s[2:len(t.s):len(t.s)] + + _ = t.s[:] + _ = t.s[:10] + _ = t.s[:len(t.s)] + _ = t.s[:(len(t.s))] + _ = t.s[:len(t.s)-1] + _ = t.s[:len(b)] + _ = t.s[:len(t.s):len(t.s)] +) + +func _() { + s := s[0:len(s)] + _ = s +} diff --git a/libgo/go/cmd/gofmt/testdata/slices2.golden b/libgo/go/cmd/gofmt/testdata/slices2.golden new file mode 100644 index 0000000000..ab657004e6 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/slices2.golden @@ -0,0 +1,63 @@ +//gofmt -s + +// Test cases for slice expression simplification. +// Because of a dot import, these slices must remain untouched. +package p + +import . "math" + +var ( + a [10]byte + b [20]float32 + s []int + t struct { + s []byte + } + + _ = a[0:] + _ = a[1:10] + _ = a[2:len(a)] + _ = a[3:(len(a))] + _ = a[len(a) : len(a)-1] + _ = a[0:len(b)] + + _ = a[:] + _ = a[:10] + _ = a[:len(a)] + _ = a[:(len(a))] + _ = a[:len(a)-1] + _ = a[:len(b)] + + _ = s[0:] + _ = s[1:10] + _ = s[2:len(s)] + _ = s[3:(len(s))] + _ = s[len(a) : len(s)-1] + _ = s[0:len(b)] + + _ = s[:] + _ = s[:10] + _ = s[:len(s)] + _ = s[:(len(s))] + _ = s[:len(s)-1] + _ = s[:len(b)] + + _ = t.s[0:] + _ = t.s[1:10] + _ = t.s[2:len(t.s)] + _ = t.s[3:(len(t.s))] + _ = t.s[len(a) : len(t.s)-1] + _ = t.s[0:len(b)] + + _ = t.s[:] + _ = t.s[:10] + _ = t.s[:len(t.s)] + _ = t.s[:(len(t.s))] + _ = t.s[:len(t.s)-1] + _ = t.s[:len(b)] +) + +func _() { + s := s[0:len(s)] + _ = s +} diff --git a/libgo/go/cmd/gofmt/testdata/slices2.input b/libgo/go/cmd/gofmt/testdata/slices2.input new file mode 100644 index 0000000000..ab657004e6 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/slices2.input @@ -0,0 +1,63 @@ +//gofmt -s + +// Test cases for slice expression simplification. +// Because of a dot import, these slices must remain untouched. +package p + +import . "math" + +var ( + a [10]byte + b [20]float32 + s []int + t struct { + s []byte + } + + _ = a[0:] + _ = a[1:10] + _ = a[2:len(a)] + _ = a[3:(len(a))] + _ = a[len(a) : len(a)-1] + _ = a[0:len(b)] + + _ = a[:] + _ = a[:10] + _ = a[:len(a)] + _ = a[:(len(a))] + _ = a[:len(a)-1] + _ = a[:len(b)] + + _ = s[0:] + _ = s[1:10] + _ = s[2:len(s)] + _ = s[3:(len(s))] + _ = s[len(a) : len(s)-1] + _ = s[0:len(b)] + + _ = s[:] + _ = s[:10] + _ = s[:len(s)] + _ = s[:(len(s))] + _ = s[:len(s)-1] + _ = s[:len(b)] + + _ = t.s[0:] + _ = t.s[1:10] + _ = t.s[2:len(t.s)] + _ = t.s[3:(len(t.s))] + _ = t.s[len(a) : len(t.s)-1] + _ = t.s[0:len(b)] + + _ = t.s[:] + _ = t.s[:10] + _ = t.s[:len(t.s)] + _ = t.s[:(len(t.s))] + _ = t.s[:len(t.s)-1] + _ = t.s[:len(b)] +) + +func _() { + s := s[0:len(s)] + _ = s +} diff --git a/libgo/go/cmd/gofmt/testdata/stdin1.golden b/libgo/go/cmd/gofmt/testdata/stdin1.golden new file mode 100644 index 0000000000..9e4dcd20fe --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/stdin1.golden @@ -0,0 +1,5 @@ + //gofmt -stdin + + if x { + y + } diff --git a/libgo/go/cmd/gofmt/testdata/stdin1.input b/libgo/go/cmd/gofmt/testdata/stdin1.input new file mode 100644 index 0000000000..9e4dcd20fe --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/stdin1.input @@ -0,0 +1,5 @@ + //gofmt -stdin + + if x { + y + } diff --git a/libgo/go/cmd/gofmt/testdata/stdin2.golden b/libgo/go/cmd/gofmt/testdata/stdin2.golden new file mode 100644 index 0000000000..57df355403 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/stdin2.golden @@ -0,0 +1,11 @@ +//gofmt -stdin + +var x int + +func f() { + y := z + /* this is a comment */ + // this is a comment too +} + + diff --git a/libgo/go/cmd/gofmt/testdata/stdin2.input b/libgo/go/cmd/gofmt/testdata/stdin2.input new file mode 100644 index 0000000000..69d6bdd682 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/stdin2.input @@ -0,0 +1,11 @@ +//gofmt -stdin + +var x int + + +func f() { y := z + /* this is a comment */ + // this is a comment too +} + + diff --git a/libgo/go/cmd/gofmt/testdata/stdin3.golden b/libgo/go/cmd/gofmt/testdata/stdin3.golden new file mode 100644 index 0000000000..d6da0e417a --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/stdin3.golden @@ -0,0 +1,7 @@ + //gofmt -stdin + + /* note: no newline at end of file */ + for i := 0; i < 10; i++ { + s += i + } + \ No newline at end of file diff --git a/libgo/go/cmd/gofmt/testdata/stdin3.input b/libgo/go/cmd/gofmt/testdata/stdin3.input new file mode 100644 index 0000000000..ab46c1063b --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/stdin3.input @@ -0,0 +1,5 @@ + //gofmt -stdin + + /* note: no newline at end of file */ + for i := 0; i < 10; i++ { s += i } + \ No newline at end of file diff --git a/libgo/go/cmd/gofmt/testdata/stdin4.golden b/libgo/go/cmd/gofmt/testdata/stdin4.golden new file mode 100644 index 0000000000..0c7acace5d --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/stdin4.golden @@ -0,0 +1,5 @@ + //gofmt -stdin + + // comment + + i := 0 diff --git a/libgo/go/cmd/gofmt/testdata/stdin4.input b/libgo/go/cmd/gofmt/testdata/stdin4.input new file mode 100644 index 0000000000..1fc73f31e5 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/stdin4.input @@ -0,0 +1,5 @@ + //gofmt -stdin + + // comment + + i := 0 diff --git a/libgo/go/cmd/gofmt/testdata/typeswitch.golden b/libgo/go/cmd/gofmt/testdata/typeswitch.golden new file mode 100644 index 0000000000..2b1905edd3 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/typeswitch.golden @@ -0,0 +1,60 @@ +/* + Parenthesized type switch expressions originally + accepted by gofmt must continue to be rewritten + into the correct unparenthesized form. + + Only type-switches that didn't declare a variable + in the type switch type assertion and which + contained only "expression-like" (named) types in their + cases were permitted to have their type assertion parenthesized + by go/parser (due to a weak predicate in the parser). All others + were rejected always, either with a syntax error in the + type switch header or in the case. + + See also issue 4470. +*/ +package p + +func f() { + var x interface{} + switch x.(type) { // should remain the same + } + switch x.(type) { // should become: switch x.(type) { + } + + switch x.(type) { // should remain the same + case int: + } + switch x.(type) { // should become: switch x.(type) { + case int: + } + + switch x.(type) { // should remain the same + case []int: + } + + // Parenthesized (x.(type)) in type switches containing cases + // with unnamed (literal) types were never permitted by gofmt; + // thus there won't be any code in the wild using this style if + // the code was gofmt-ed. + /* + switch (x.(type)) { + case []int: + } + */ + + switch t := x.(type) { // should remain the same + default: + _ = t + } + + // Parenthesized (x.(type)) in type switches declaring a variable + // were never permitted by gofmt; thus there won't be any code in + // the wild using this style if the code was gofmt-ed. + /* + switch t := (x.(type)) { + default: + _ = t + } + */ +} diff --git a/libgo/go/cmd/gofmt/testdata/typeswitch.input b/libgo/go/cmd/gofmt/testdata/typeswitch.input new file mode 100644 index 0000000000..8f8cba9b85 --- /dev/null +++ b/libgo/go/cmd/gofmt/testdata/typeswitch.input @@ -0,0 +1,60 @@ +/* + Parenthesized type switch expressions originally + accepted by gofmt must continue to be rewritten + into the correct unparenthesized form. + + Only type-switches that didn't declare a variable + in the type switch type assertion and which + contained only "expression-like" (named) types in their + cases were permitted to have their type assertion parenthesized + by go/parser (due to a weak predicate in the parser). All others + were rejected always, either with a syntax error in the + type switch header or in the case. + + See also issue 4470. +*/ +package p + +func f() { + var x interface{} + switch x.(type) { // should remain the same + } + switch (x.(type)) { // should become: switch x.(type) { + } + + switch x.(type) { // should remain the same + case int: + } + switch (x.(type)) { // should become: switch x.(type) { + case int: + } + + switch x.(type) { // should remain the same + case []int: + } + + // Parenthesized (x.(type)) in type switches containing cases + // with unnamed (literal) types were never permitted by gofmt; + // thus there won't be any code in the wild using this style if + // the code was gofmt-ed. + /* + switch (x.(type)) { + case []int: + } + */ + + switch t := x.(type) { // should remain the same + default: + _ = t + } + + // Parenthesized (x.(type)) in type switches declaring a variable + // were never permitted by gofmt; thus there won't be any code in + // the wild using this style if the code was gofmt-ed. + /* + switch t := (x.(type)) { + default: + _ = t + } + */ +} diff --git a/libgo/go/compress/bzip2/bzip2.go b/libgo/go/compress/bzip2/bzip2.go index 82e30c7c9d..15575d2202 100644 --- a/libgo/go/compress/bzip2/bzip2.go +++ b/libgo/go/compress/bzip2/bzip2.go @@ -42,6 +42,8 @@ type reader struct { } // NewReader returns an io.Reader which decompresses bzip2 data from r. +// If r does not also implement io.ByteReader, +// the decompressor may read more data than necessary from r. func NewReader(r io.Reader) io.Reader { bz2 := new(reader) bz2.br = newBitReader(r) @@ -261,6 +263,11 @@ func (bz2 *reader) readBlock() (err error) { } } + if numSymbols == 0 { + // There must be an EOF symbol. + return StructuralError("no symbols in input") + } + // A block uses between two and six different Huffman trees. numHuffmanTrees := br.ReadBits(3) if numHuffmanTrees < 2 || numHuffmanTrees > 6 { @@ -307,10 +314,10 @@ func (bz2 *reader) readBlock() (err error) { // Now we decode the arrays of code-lengths for each tree. lengths := make([]uint8, numSymbols) - for i := 0; i < numHuffmanTrees; i++ { + for i := range huffmanTrees { // The code lengths are delta encoded from a 5-bit base value. length := br.ReadBits(5) - for j := 0; j < numSymbols; j++ { + for j := range lengths { for { if !br.ReadBit() { break @@ -333,6 +340,12 @@ func (bz2 *reader) readBlock() (err error) { } selectorIndex := 1 // the next tree index to use + if len(treeIndexes) == 0 { + return StructuralError("no tree selectors given") + } + if int(treeIndexes[0]) >= len(huffmanTrees) { + return StructuralError("tree selector out of range") + } currentHuffmanTree := huffmanTrees[treeIndexes[0]] bufIndex := 0 // indexes bz2.buf, the output buffer. // The output of the move-to-front transform is run-length encoded and @@ -350,6 +363,12 @@ func (bz2 *reader) readBlock() (err error) { decoded := 0 // counts the number of symbols decoded by the current tree. for { if decoded == 50 { + if selectorIndex >= numSelectors { + return StructuralError("insufficient selector indices for number of symbols") + } + if int(treeIndexes[selectorIndex]) >= len(huffmanTrees) { + return StructuralError("tree selector out of range") + } currentHuffmanTree = huffmanTrees[treeIndexes[selectorIndex]] selectorIndex++ decoded = 0 diff --git a/libgo/go/compress/bzip2/bzip2_test.go b/libgo/go/compress/bzip2/bzip2_test.go index ada1f9a001..fb79d089eb 100644 --- a/libgo/go/compress/bzip2/bzip2_test.go +++ b/libgo/go/compress/bzip2/bzip2_test.go @@ -14,7 +14,7 @@ import ( ) func TestBitReader(t *testing.T) { - buf := bytes.NewBuffer([]byte{0xaa}) + buf := bytes.NewReader([]byte{0xaa}) br := newBitReader(buf) if n := br.ReadBits(1); n != 1 { t.Errorf("read 1 wrong") @@ -31,7 +31,7 @@ func TestBitReader(t *testing.T) { } func TestBitReaderLarge(t *testing.T) { - buf := bytes.NewBuffer([]byte{0x12, 0x34, 0x56, 0x78}) + buf := bytes.NewReader([]byte{0x12, 0x34, 0x56, 0x78}) br := newBitReader(buf) if n := br.ReadBits(32); n != 0x12345678 { t.Errorf("got: %x want: %x", n, 0x12345678) @@ -43,7 +43,7 @@ func readerFromHex(s string) io.Reader { if err != nil { panic("readerFromHex: bad input") } - return bytes.NewBuffer(data) + return bytes.NewReader(data) } func decompressHex(s string) (out []byte, err error) { @@ -177,7 +177,7 @@ const ( var testfiles = []string{ // Digits is the digits of the irrational number e. Its decimal representation - // does not repeat, but there are only 10 posible digits, so it should be + // does not repeat, but there are only 10 possible digits, so it should be // reasonably compressible. digits: "testdata/e.txt.bz2", // Twain is Project Gutenberg's edition of Mark Twain's classic English novel. @@ -191,7 +191,7 @@ func benchmarkDecode(b *testing.B, testfile int) { } b.SetBytes(int64(len(compressed))) for i := 0; i < b.N; i++ { - r := bytes.NewBuffer(compressed) + r := bytes.NewReader(compressed) io.Copy(ioutil.Discard, NewReader(r)) } } @@ -201,13 +201,59 @@ func BenchmarkDecodeTwain(b *testing.B) { benchmarkDecode(b, twain) } func TestBufferOverrun(t *testing.T) { // Tests https://code.google.com/p/go/issues/detail?id=5747. - buffer := bytes.NewBuffer([]byte(bufferOverrunBase64)) + buffer := bytes.NewReader([]byte(bufferOverrunBase64)) decoder := base64.NewDecoder(base64.StdEncoding, buffer) decompressor := NewReader(decoder) // This shouldn't panic. ioutil.ReadAll(decompressor) } +func TestOutOfRangeSelector(t *testing.T) { + // Tests https://code.google.com/p/go/issues/detail?id=8363. + buffer := bytes.NewReader(outOfRangeSelector) + decompressor := NewReader(buffer) + // This shouldn't panic. + ioutil.ReadAll(decompressor) +} + +func TestMTF(t *testing.T) { + mtf := newMTFDecoderWithRange(5) + + // 0 1 2 3 4 + expect := byte(1) + x := mtf.Decode(1) + if x != expect { + t.Errorf("expected %v, got %v", expect, x) + } + + // 1 0 2 3 4 + x = mtf.Decode(0) + if x != expect { + t.Errorf("expected %v, got %v", expect, x) + } + + // 1 0 2 3 4 + expect = byte(0) + x = mtf.Decode(1) + if x != expect { + t.Errorf("expected %v, got %v", expect, x) + } + + // 0 1 2 3 4 + expect = byte(4) + x = mtf.Decode(4) + if x != expect { + t.Errorf("expected %v, got %v", expect, x) + } + + // 4 0 1 2 3 + expect = byte(0) + x = mtf.Decode(1) + if x != expect { + t.Errorf("expected %v, got %v", expect, x) + } +} + var bufferOverrunBase64 string = ` QlpoNTFBWSZTWTzyiGcACMP/////////////////////////////////3/7f3/// ////4N/fCZODak2Xo44GIHZgkGzDRbFAuwAAKoFV7T6AO6qwA6APb6s2rOoAkAAD @@ -361,3 +407,13 @@ O0A8s/iua5oFdNZTWvbVI4FUH9sKcLiB3/fIAF+sB4n8q6L+UCfmbPcAo/crQ6b3 HqhDBMY9J0q/jdz9GNYZ/1fbXdkUqAQKFePhtzJDRBZba27+LPQNMCcrHMq06F1T 4QmLmkHt7LxB2pAczUO+T2O9bHEw/HWw+dYf2MoRDUw= ` + +var outOfRangeSelector = []byte{ + 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, + 0x53, 0x59, 0x4e, 0xec, 0xe8, 0x36, 0x00, 0x00, + 0x02, 0x51, 0x80, 0x00, 0x10, 0x40, 0x00, 0x06, + 0x44, 0x90, 0x80, 0x20, 0x00, 0x31, 0x06, 0x4c, + 0x41, 0x01, 0xa7, 0xa9, 0xa5, 0x80, 0xbb, 0x94, + 0x31, 0x17, 0x72, 0x45, 0x38, 0x50, 0x90, 0x00, + 0x00, 0x00, 0x00, +} diff --git a/libgo/go/compress/bzip2/huffman.go b/libgo/go/compress/bzip2/huffman.go index 8f6b0c9cad..75a6223d81 100644 --- a/libgo/go/compress/bzip2/huffman.go +++ b/libgo/go/compress/bzip2/huffman.go @@ -190,7 +190,37 @@ func buildHuffmanNode(t *huffmanTree, codes []huffmanCode, level uint32) (nodeIn right := codes[firstRightIndex:] if len(left) == 0 || len(right) == 0 { - return 0, StructuralError("superfluous level in Huffman tree") + // There is a superfluous level in the Huffman tree indicating + // a bug in the encoder. However, this bug has been observed in + // the wild so we handle it. + + // If this function was called recursively then we know that + // len(codes) >= 2 because, otherwise, we would have hit the + // "leaf node" case, below, and not recursed. + // + // However, for the initial call it's possible that len(codes) + // is zero or one. Both cases are invalid because a zero length + // tree cannot encode anything and a length-1 tree can only + // encode EOF and so is superfluous. We reject both. + if len(codes) < 2 { + return 0, StructuralError("empty Huffman tree") + } + + // In this case the recursion doesn't always reduce the length + // of codes so we need to ensure termination via another + // mechanism. + if level == 31 { + // Since len(codes) >= 2 the only way that the values + // can match at all 32 bits is if they are equal, which + // is invalid. This ensures that we never enter + // infinite recursion. + return 0, StructuralError("equal symbols in Huffman tree") + } + + if len(left) == 0 { + return buildHuffmanNode(t, right, level+1) + } + return buildHuffmanNode(t, left, level+1) } nodeIndex = uint16(t.nextNode) diff --git a/libgo/go/compress/bzip2/move_to_front.go b/libgo/go/compress/bzip2/move_to_front.go index b7e75a700a..526dfb34cc 100644 --- a/libgo/go/compress/bzip2/move_to_front.go +++ b/libgo/go/compress/bzip2/move_to_front.go @@ -11,88 +11,43 @@ package bzip2 // index into that list. When a symbol is referenced, it's moved to the front // of the list. Thus, a repeated symbol ends up being encoded with many zeros, // as the symbol will be at the front of the list after the first access. -type moveToFrontDecoder struct { - // Rather than actually keep the list in memory, the symbols are stored - // as a circular, double linked list with the symbol indexed by head - // at the front of the list. - symbols [256]byte - next [256]uint8 - prev [256]uint8 - head uint8 - len int -} +type moveToFrontDecoder []byte // newMTFDecoder creates a move-to-front decoder with an explicit initial list // of symbols. -func newMTFDecoder(symbols []byte) *moveToFrontDecoder { +func newMTFDecoder(symbols []byte) moveToFrontDecoder { if len(symbols) > 256 { panic("too many symbols") } - - m := new(moveToFrontDecoder) - copy(m.symbols[:], symbols) - m.len = len(symbols) - m.threadLinkedList() - return m + return moveToFrontDecoder(symbols) } // newMTFDecoderWithRange creates a move-to-front decoder with an initial // symbol list of 0...n-1. -func newMTFDecoderWithRange(n int) *moveToFrontDecoder { +func newMTFDecoderWithRange(n int) moveToFrontDecoder { if n > 256 { panic("newMTFDecoderWithRange: cannot have > 256 symbols") } - m := new(moveToFrontDecoder) + m := make([]byte, n) for i := 0; i < n; i++ { - m.symbols[byte(i)] = byte(i) - } - m.len = n - m.threadLinkedList() - return m -} - -// threadLinkedList creates the initial linked-list pointers. -func (m *moveToFrontDecoder) threadLinkedList() { - if m.len == 0 { - return - } - - m.prev[0] = uint8(m.len - 1) - - for i := byte(0); int(i) < m.len-1; i++ { - m.next[i] = uint8(i + 1) - m.prev[i+1] = uint8(i) + m[i] = byte(i) } - - m.next[m.len-1] = 0 + return moveToFrontDecoder(m) } -func (m *moveToFrontDecoder) Decode(n int) (b byte) { - // Most of the time, n will be zero so it's worth dealing with this - // simple case. - if n == 0 { - return m.symbols[m.head] - } - - i := m.head - for j := 0; j < n; j++ { - i = m.next[i] - } - b = m.symbols[i] - - m.next[m.prev[i]] = m.next[i] - m.prev[m.next[i]] = m.prev[i] - m.next[i] = m.head - m.prev[i] = m.prev[m.head] - m.next[m.prev[m.head]] = i - m.prev[m.head] = i - m.head = i - +func (m moveToFrontDecoder) Decode(n int) (b byte) { + // Implement move-to-front with a simple copy. This approach + // beats more sophisticated approaches in benchmarking, probably + // because it has high locality of reference inside of a + // single cache line (most move-to-front operations have n < 64). + b = m[n] + copy(m[1:], m[:n]) + m[0] = b return } // First returns the symbol at the front of the list. -func (m *moveToFrontDecoder) First() byte { - return m.symbols[m.head] +func (m moveToFrontDecoder) First() byte { + return m[0] } diff --git a/libgo/go/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 b/libgo/go/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 new file mode 100644 index 0000000000..0bd61a6d4e Binary files /dev/null and b/libgo/go/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 differ diff --git a/libgo/go/compress/bzip2/testdata/e.txt.bz2 b/libgo/go/compress/bzip2/testdata/e.txt.bz2 new file mode 100644 index 0000000000..65bf3b4c32 Binary files /dev/null and b/libgo/go/compress/bzip2/testdata/e.txt.bz2 differ diff --git a/libgo/go/compress/flate/fixedhuff.go b/libgo/go/compress/flate/fixedhuff.go index 41a6b25dfd..7df8b9a293 100644 --- a/libgo/go/compress/flate/fixedhuff.go +++ b/libgo/go/compress/flate/fixedhuff.go @@ -1,6 +1,10 @@ +// 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 flate -// autogenerated by gen.go, DO NOT EDIT +// autogenerated by go run gen.go -output fixedhuff.go, DO NOT EDIT var fixedHuffmanDecoder = huffmanDecoder{ 7, diff --git a/libgo/go/compress/flate/flate_test.go b/libgo/go/compress/flate/flate_test.go index 57fea5ab4d..0687663233 100644 --- a/libgo/go/compress/flate/flate_test.go +++ b/libgo/go/compress/flate/flate_test.go @@ -14,7 +14,7 @@ import ( ) func TestUncompressedSource(t *testing.T) { - decoder := NewReader(bytes.NewBuffer([]byte{0x01, 0x01, 0x00, 0xfe, 0xff, 0x11})) + decoder := NewReader(bytes.NewReader([]byte{0x01, 0x01, 0x00, 0xfe, 0xff, 0x11})) output := make([]byte, 1) n, error := decoder.Read(output) if n != 1 || error != nil { diff --git a/libgo/go/compress/flate/gen.go b/libgo/go/compress/flate/gen.go index 1427557f80..6288ecddd0 100644 --- a/libgo/go/compress/flate/gen.go +++ b/libgo/go/compress/flate/gen.go @@ -7,14 +7,21 @@ // This program generates fixedhuff.go // Invoke as // -// go run gen.go |gofmt >fixedhuff.go +// go run gen.go -output fixedhuff.go package main import ( + "bytes" + "flag" "fmt" + "go/format" + "io/ioutil" + "log" ) +var filename = flag.String("output", "fixedhuff.go", "output file name") + const maxCodeLen = 16 // Note: the definition of the huffmanDecoder struct is copied from @@ -113,6 +120,8 @@ func (h *huffmanDecoder) init(bits []int) bool { } func main() { + flag.Parse() + var h huffmanDecoder var bits [288]int initReverseByte() @@ -129,27 +138,43 @@ func main() { bits[i] = 8 } h.init(bits[:]) - fmt.Println("package flate") - fmt.Println() - fmt.Println("// autogenerated by gen.go, DO NOT EDIT") - fmt.Println() - fmt.Println("var fixedHuffmanDecoder = huffmanDecoder{") - fmt.Printf("\t%d,\n", h.min) - fmt.Println("\t[huffmanNumChunks]uint32{") + + var buf bytes.Buffer + + fmt.Fprintf(&buf, `// 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.`+"\n\n") + + fmt.Fprintln(&buf, "package flate") + fmt.Fprintln(&buf) + fmt.Fprintln(&buf, "// autogenerated by go run gen.go -output fixedhuff.go, DO NOT EDIT") + fmt.Fprintln(&buf) + fmt.Fprintln(&buf, "var fixedHuffmanDecoder = huffmanDecoder{") + fmt.Fprintf(&buf, "\t%d,\n", h.min) + fmt.Fprintln(&buf, "\t[huffmanNumChunks]uint32{") for i := 0; i < huffmanNumChunks; i++ { if i&7 == 0 { - fmt.Printf("\t\t") + fmt.Fprintf(&buf, "\t\t") } else { - fmt.Printf(" ") + fmt.Fprintf(&buf, " ") } - fmt.Printf("0x%04x,", h.chunks[i]) + fmt.Fprintf(&buf, "0x%04x,", h.chunks[i]) if i&7 == 7 { - fmt.Println() + fmt.Fprintln(&buf) } } - fmt.Println("\t},") - fmt.Println("\tnil, 0,") - fmt.Println("}") + fmt.Fprintln(&buf, "\t},") + fmt.Fprintln(&buf, "\tnil, 0,") + fmt.Fprintln(&buf, "}") + + data, err := format.Source(buf.Bytes()) + if err != nil { + log.Fatal(err) + } + err = ioutil.WriteFile(*filename, data, 0644) + if err != nil { + log.Fatal(err) + } } var reverseByte [256]byte diff --git a/libgo/go/compress/flate/inflate.go b/libgo/go/compress/flate/inflate.go index 3eb3b2b83e..76519bbf42 100644 --- a/libgo/go/compress/flate/inflate.go +++ b/libgo/go/compress/flate/inflate.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:generate go run gen.go -output fixedhuff.go + // Package flate implements the DEFLATE compressed data format, described in // RFC 1951. The gzip and zlib packages implement access to DEFLATE-based file // formats. @@ -54,7 +56,16 @@ func (e *WriteError) Error() string { return "flate: write error at offset " + strconv.FormatInt(e.Offset, 10) + ": " + e.Err.Error() } -// Note that much of the implemenation of huffmanDecoder is also copied +// Resetter resets a ReadCloser returned by NewReader or NewReaderDict to +// to switch to a new underlying Reader. This permits reusing a ReadCloser +// instead of allocating a new one. +type Resetter interface { + // Reset discards any buffered data and resets the Resetter as if it was + // newly initialized with the given reader. + Reset(r io.Reader, dict []byte) error +} + +// Note that much of the implementation of huffmanDecoder is also copied // into gen.go (in package main) for the purpose of precomputing the // fixed huffman tables so they can be included statically. @@ -180,7 +191,7 @@ func (h *huffmanDecoder) init(bits []int) bool { // the NewReader will introduce its own buffering. type Reader interface { io.Reader - ReadByte() (c byte, err error) + io.ByteReader } // Decompress state. @@ -677,10 +688,28 @@ func makeReader(r io.Reader) Reader { return bufio.NewReader(r) } +func (f *decompressor) Reset(r io.Reader, dict []byte) error { + *f = decompressor{ + r: makeReader(r), + bits: f.bits, + codebits: f.codebits, + hist: f.hist, + step: (*decompressor).nextBlock, + } + if dict != nil { + f.setDict(dict) + } + return nil +} + // NewReader returns a new ReadCloser that can be used -// to read the uncompressed version of r. It is the caller's -// responsibility to call Close on the ReadCloser when -// finished reading. +// to read the uncompressed version of r. +// If r does not also implement io.ByteReader, +// the decompressor may read more data than necessary from r. +// It is the caller's responsibility to call Close on the ReadCloser +// when finished reading. +// +// The ReadCloser returned by NewReader also implements Resetter. func NewReader(r io.Reader) io.ReadCloser { var f decompressor f.bits = new([maxLit + maxDist]int) @@ -696,6 +725,8 @@ func NewReader(r io.Reader) io.ReadCloser { // the uncompressed data stream started with the given dictionary, // which has already been read. NewReaderDict is typically used // to read data compressed by NewWriterDict. +// +// The ReadCloser returned by NewReader also implements Resetter. func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser { var f decompressor f.r = makeReader(r) diff --git a/libgo/go/compress/flate/inflate_test.go b/libgo/go/compress/flate/inflate_test.go new file mode 100644 index 0000000000..9f25d30b35 --- /dev/null +++ b/libgo/go/compress/flate/inflate_test.go @@ -0,0 +1,39 @@ +// 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 flate + +import ( + "bytes" + "io" + "testing" +) + +func TestReset(t *testing.T) { + ss := []string{ + "lorem ipsum izzle fo rizzle", + "the quick brown fox jumped over", + } + + deflated := make([]bytes.Buffer, 2) + for i, s := range ss { + w, _ := NewWriter(&deflated[i], 1) + w.Write([]byte(s)) + w.Close() + } + + inflated := make([]bytes.Buffer, 2) + + f := NewReader(&deflated[0]) + io.Copy(&inflated[0], f) + f.(Resetter).Reset(&deflated[1], nil) + io.Copy(&inflated[1], f) + f.Close() + + for i, s := range ss { + if s != inflated[i].String() { + t.Errorf("inflated[%d]:\ngot %q\nwant %q", i, inflated[i], s) + } + } +} diff --git a/libgo/go/compress/flate/reader_test.go b/libgo/go/compress/flate/reader_test.go index 2a8ebbc943..a62ef741df 100644 --- a/libgo/go/compress/flate/reader_test.go +++ b/libgo/go/compress/flate/reader_test.go @@ -29,7 +29,7 @@ const ( var testfiles = []string{ // Digits is the digits of the irrational number e. Its decimal representation - // does not repeat, but there are only 10 posible digits, so it should be + // does not repeat, but there are only 10 possible digits, so it should be // reasonably compressible. digits: "../testdata/e.txt", // Twain is Project Gutenberg's edition of Mark Twain's classic English novel. diff --git a/libgo/go/compress/gzip/gunzip.go b/libgo/go/compress/gzip/gunzip.go index 1fb9b0964c..72ee55c4fa 100644 --- a/libgo/go/compress/gzip/gunzip.go +++ b/libgo/go/compress/gzip/gunzip.go @@ -74,14 +74,17 @@ type Reader struct { flg byte buf [512]byte err error + multistream bool } // NewReader creates a new Reader reading the given reader. -// The implementation buffers input and may read more data than necessary from r. +// If r does not also implement io.ByteReader, +// the decompressor may read more data than necessary from r. // It is the caller's responsibility to call Close on the Reader when done. func NewReader(r io.Reader) (*Reader, error) { z := new(Reader) z.r = makeReader(r) + z.multistream = true z.digest = crc32.NewIEEE() if err := z.readHeader(true); err != nil { return nil, err @@ -89,6 +92,42 @@ func NewReader(r io.Reader) (*Reader, error) { return z, nil } +// Reset discards the Reader z's state and makes it equivalent to the +// result of its original state from NewReader, but reading from r instead. +// This permits reusing a Reader rather than allocating a new one. +func (z *Reader) Reset(r io.Reader) error { + z.r = makeReader(r) + if z.digest == nil { + z.digest = crc32.NewIEEE() + } else { + z.digest.Reset() + } + z.size = 0 + z.err = nil + z.multistream = true + return z.readHeader(true) +} + +// Multistream controls whether the reader supports multistream files. +// +// If enabled (the default), the Reader expects the input to be a sequence +// of individually gzipped data streams, each with its own header and +// trailer, ending at EOF. The effect is that the concatenation of a sequence +// of gzipped files is treated as equivalent to the gzip of the concatenation +// of the sequence. This is standard behavior for gzip readers. +// +// Calling Multistream(false) disables this behavior; disabling the behavior +// can be useful when reading file formats that distinguish individual gzip +// data streams or mix gzip data streams with other data streams. +// In this mode, when the Reader reaches the end of the data stream, +// Read returns io.EOF. If the underlying reader implements io.ByteReader, +// it will be left positioned just after the gzip stream. +// To start the next stream, call z.Reset(r) followed by z.Multistream(false). +// If there is no next stream, z.Reset(r) will return io.EOF. +func (z *Reader) Multistream(ok bool) { + z.multistream = ok +} + // GZIP (RFC 1952) is little-endian, unlike ZLIB (RFC 1950). func get4(p []byte) uint32 { return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24 @@ -192,7 +231,11 @@ func (z *Reader) readHeader(save bool) error { } z.digest.Reset() - z.decompressor = flate.NewReader(z.r) + if z.decompressor == nil { + z.decompressor = flate.NewReader(z.r) + } else { + z.decompressor.(flate.Resetter).Reset(z.r, nil) + } return nil } @@ -225,6 +268,10 @@ func (z *Reader) Read(p []byte) (n int, err error) { } // File is ok; is there another? + if !z.multistream { + return 0, io.EOF + } + if err = z.readHeader(false); err != nil { z.err = err return diff --git a/libgo/go/compress/gzip/gunzip_test.go b/libgo/go/compress/gzip/gunzip_test.go index 572fb58488..0636dec9ab 100644 --- a/libgo/go/compress/gzip/gunzip_test.go +++ b/libgo/go/compress/gzip/gunzip_test.go @@ -9,6 +9,7 @@ import ( "io" "io/ioutil" "os" + "strings" "testing" "time" ) @@ -284,7 +285,7 @@ var gunzipTests = []gunzipTest{ func TestDecompressor(t *testing.T) { b := new(bytes.Buffer) for _, tt := range gunzipTests { - in := bytes.NewBuffer(tt.gzip) + in := bytes.NewReader(tt.gzip) gzip, err := NewReader(in) if err != nil { t.Errorf("%s: NewReader: %s", tt.name, err) @@ -303,6 +304,26 @@ func TestDecompressor(t *testing.T) { if s != tt.raw { t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.name, n, s, len(tt.raw), tt.raw) } + + // Test Reader Reset. + in = bytes.NewReader(tt.gzip) + err = gzip.Reset(in) + if err != nil { + t.Errorf("%s: Reset: %s", tt.name, err) + continue + } + if tt.name != gzip.Name { + t.Errorf("%s: got name %s", tt.name, gzip.Name) + } + b.Reset() + n, err = io.Copy(b, gzip) + if err != tt.err { + t.Errorf("%s: io.Copy: %v want %v", tt.name, err, tt.err) + } + s = b.String() + if s != tt.raw { + t.Errorf("%s: got %d-byte %q want %d-byte %q", tt.name, n, s, len(tt.raw), tt.raw) + } } } @@ -333,3 +354,57 @@ func TestIssue6550(t *testing.T) { // ok } } + +func TestInitialReset(t *testing.T) { + var r Reader + if err := r.Reset(bytes.NewReader(gunzipTests[1].gzip)); err != nil { + t.Error(err) + } + var buf bytes.Buffer + if _, err := io.Copy(&buf, &r); err != nil { + t.Error(err) + } + if s := buf.String(); s != gunzipTests[1].raw { + t.Errorf("got %q want %q", s, gunzipTests[1].raw) + } +} + +func TestMultistreamFalse(t *testing.T) { + // Find concatenation test. + var tt gunzipTest + for _, tt = range gunzipTests { + if strings.HasSuffix(tt.desc, " x2") { + goto Found + } + } + t.Fatal("cannot find hello.txt x2 in gunzip tests") + +Found: + br := bytes.NewReader(tt.gzip) + var r Reader + if err := r.Reset(br); err != nil { + t.Fatalf("first reset: %v", err) + } + + // Expect two streams with "hello world\n", then real EOF. + const hello = "hello world\n" + + r.Multistream(false) + data, err := ioutil.ReadAll(&r) + if string(data) != hello || err != nil { + t.Fatalf("first stream = %q, %v, want %q, %v", string(data), err, hello, nil) + } + + if err := r.Reset(br); err != nil { + t.Fatalf("second reset: %v", err) + } + r.Multistream(false) + data, err = ioutil.ReadAll(&r) + if string(data) != hello || err != nil { + t.Fatalf("second stream = %q, %v, want %q, %v", string(data), err, hello, nil) + } + + if err := r.Reset(br); err != io.EOF { + t.Fatalf("third reset: err=%v, want io.EOF", err) + } +} diff --git a/libgo/go/compress/gzip/gzip.go b/libgo/go/compress/gzip/gzip.go index fe32d6871a..5131d128e4 100644 --- a/libgo/go/compress/gzip/gzip.go +++ b/libgo/go/compress/gzip/gzip.go @@ -22,8 +22,8 @@ const ( DefaultCompression = flate.DefaultCompression ) -// A Writer is an io.WriteCloser that satisfies writes by compressing data written -// to its wrapped io.Writer. +// A Writer is an io.WriteCloser. +// Writes to a Writer are compressed and written to w. type Writer struct { Header w io.Writer @@ -37,8 +37,8 @@ type Writer struct { err error } -// NewWriter creates a new Writer that satisfies writes by compressing data -// written to w. +// NewWriter returns a new Writer. +// Writes to the returned writer are compressed and written to w. // // It is the caller's responsibility to call Close on the WriteCloser when done. // Writes may be buffered and not flushed until Close. @@ -245,7 +245,8 @@ func (z *Writer) Flush() error { return z.err } -// Close closes the Writer. It does not close the underlying io.Writer. +// Close closes the Writer, flushing any unwritten data to the underlying +// io.Writer, but does not close the underlying io.Writer. func (z *Writer) Close() error { if z.err != nil { return z.err diff --git a/libgo/go/compress/gzip/gzip_test.go b/libgo/go/compress/gzip/gzip_test.go index 119be2e135..09271b24e9 100644 --- a/libgo/go/compress/gzip/gzip_test.go +++ b/libgo/go/compress/gzip/gzip_test.go @@ -85,7 +85,7 @@ func TestRoundTrip(t *testing.T) { func TestLatin1(t *testing.T) { latin1 := []byte{0xc4, 'u', 0xdf, 'e', 'r', 'u', 'n', 'g', 0} utf8 := "Äußerung" - z := Reader{r: bufio.NewReader(bytes.NewBuffer(latin1))} + z := Reader{r: bufio.NewReader(bytes.NewReader(latin1))} s, err := z.readString() if err != nil { t.Fatalf("readString: %v", err) diff --git a/libgo/go/compress/lzw/reader.go b/libgo/go/compress/lzw/reader.go index efbc758f94..526620c827 100644 --- a/libgo/go/compress/lzw/reader.go +++ b/libgo/go/compress/lzw/reader.go @@ -6,12 +6,16 @@ // described in T. A. Welch, ``A Technique for High-Performance Data // Compression'', Computer, 17(6) (June 1984), pp 8-19. // -// In particular, it implements LZW as used by the GIF, TIFF and PDF file +// In particular, it implements LZW as used by the GIF and PDF file // formats, which means variable-width codes up to 12 bits and the first // two non-literal codes are a clear code and an EOF code. +// +// The TIFF file format uses a similar but incompatible version of the LZW +// algorithm. See the golang.org/x/image/tiff/lzw package for an +// implementation. package lzw -// TODO(nigeltao): check that TIFF and PDF use LZW in the same way as GIF, +// TODO(nigeltao): check that PDF uses LZW in the same way as GIF, // modulo LSB/MSB packing order. import ( @@ -216,8 +220,10 @@ func (d *decoder) Close() error { return nil } -// NewReader creates a new io.ReadCloser that satisfies reads by decompressing -// the data read from r. +// 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, +// the decompressor may read more data than necessary from r. // It is the caller's responsibility to call Close on the ReadCloser when // finished reading. // The number of bits to use for literal codes, litWidth, must be in the diff --git a/libgo/go/compress/lzw/reader_test.go b/libgo/go/compress/lzw/reader_test.go index 6f155b1bde..9006c91c23 100644 --- a/libgo/go/compress/lzw/reader_test.go +++ b/libgo/go/compress/lzw/reader_test.go @@ -127,7 +127,7 @@ func benchmarkDecoder(b *testing.B, n int) { if len(buf0) > n-i { buf0 = buf0[:n-i] } - io.Copy(w, bytes.NewBuffer(buf0)) + w.Write(buf0) } w.Close() buf1 := compressed.Bytes() @@ -135,7 +135,7 @@ func benchmarkDecoder(b *testing.B, n int) { runtime.GC() b.StartTimer() for i := 0; i < b.N; i++ { - io.Copy(ioutil.Discard, NewReader(bytes.NewBuffer(buf1), LSB, 8)) + io.Copy(ioutil.Discard, NewReader(bytes.NewReader(buf1), LSB, 8)) } } diff --git a/libgo/go/compress/lzw/writer.go b/libgo/go/compress/lzw/writer.go index b20691864b..961b25f94f 100644 --- a/libgo/go/compress/lzw/writer.go +++ b/libgo/go/compress/lzw/writer.go @@ -225,8 +225,8 @@ func (e *encoder) Close() error { return e.w.Flush() } -// NewWriter creates a new io.WriteCloser that satisfies writes by compressing -// the data and writing it to w. +// NewWriter creates a new io.WriteCloser. +// Writes to the returned io.WriteCloser are compressed and written to w. // It is the caller's responsibility to call Close on the WriteCloser when // finished writing. // The number of bits to use for literal codes, litWidth, must be in the diff --git a/libgo/go/compress/zlib/reader.go b/libgo/go/compress/zlib/reader.go index d54746f4c0..816f1bf6bd 100644 --- a/libgo/go/compress/zlib/reader.go +++ b/libgo/go/compress/zlib/reader.go @@ -51,44 +51,36 @@ type reader struct { scratch [4]byte } -// NewReader creates a new io.ReadCloser that satisfies reads by decompressing data read from r. +// Resetter resets a ReadCloser returned by NewReader or NewReaderDict to +// to switch to a new underlying Reader. This permits reusing a ReadCloser +// instead of allocating a new one. +type Resetter interface { + // Reset discards any buffered data and resets the Resetter as if it was + // newly initialized with the given reader. + Reset(r io.Reader, dict []byte) error +} + +// NewReader creates a new ReadCloser. +// Reads from the returned ReadCloser read and decompress data from r. // The implementation buffers input and may read more data than necessary from r. // It is the caller's responsibility to call Close on the ReadCloser when done. +// +// The ReadCloser returned by NewReader also implements Resetter. func NewReader(r io.Reader) (io.ReadCloser, error) { return NewReaderDict(r, nil) } // NewReaderDict is like NewReader but uses a preset dictionary. // NewReaderDict ignores the dictionary if the compressed data does not refer to it. +// If the compressed data refers to a different dictionary, NewReaderDict returns ErrDictionary. +// +// The ReadCloser returned by NewReaderDict also implements Resetter. func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) { z := new(reader) - if fr, ok := r.(flate.Reader); ok { - z.r = fr - } else { - z.r = bufio.NewReader(r) - } - _, err := io.ReadFull(z.r, z.scratch[0:2]) + err := z.Reset(r, dict) if err != nil { return nil, err } - h := uint(z.scratch[0])<<8 | uint(z.scratch[1]) - if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) { - return nil, ErrHeader - } - if z.scratch[1]&0x20 != 0 { - _, err = io.ReadFull(z.r, z.scratch[0:4]) - if err != nil { - return nil, err - } - checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3]) - if checksum != adler32.Checksum(dict) { - return nil, ErrDictionary - } - z.decompressor = flate.NewReaderDict(z.r, dict) - } else { - z.decompressor = flate.NewReader(z.r) - } - z.digest = adler32.New() return z, nil } @@ -129,3 +121,41 @@ func (z *reader) Close() error { z.err = z.decompressor.Close() return z.err } + +func (z *reader) Reset(r io.Reader, dict []byte) error { + if fr, ok := r.(flate.Reader); ok { + z.r = fr + } else { + z.r = bufio.NewReader(r) + } + _, err := io.ReadFull(z.r, z.scratch[0:2]) + if err != nil { + return err + } + h := uint(z.scratch[0])<<8 | uint(z.scratch[1]) + if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) { + return ErrHeader + } + haveDict := z.scratch[1]&0x20 != 0 + if haveDict { + _, err = io.ReadFull(z.r, z.scratch[0:4]) + if err != nil { + return err + } + checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3]) + if checksum != adler32.Checksum(dict) { + return ErrDictionary + } + } + if z.decompressor == nil { + if haveDict { + z.decompressor = flate.NewReaderDict(z.r, dict) + } else { + z.decompressor = flate.NewReader(z.r) + } + } else { + z.decompressor.(flate.Resetter).Reset(z.r, dict) + } + z.digest = adler32.New() + return nil +} diff --git a/libgo/go/compress/zlib/reader_test.go b/libgo/go/compress/zlib/reader_test.go index 3b02a08684..218ccba141 100644 --- a/libgo/go/compress/zlib/reader_test.go +++ b/libgo/go/compress/zlib/reader_test.go @@ -102,7 +102,7 @@ var zlibTests = []zlibTest{ func TestDecompressor(t *testing.T) { b := new(bytes.Buffer) for _, tt := range zlibTests { - in := bytes.NewBuffer(tt.compressed) + in := bytes.NewReader(tt.compressed) zlib, err := NewReaderDict(in, tt.dict) if err != nil { if err != tt.err { diff --git a/libgo/go/compress/zlib/writer.go b/libgo/go/compress/zlib/writer.go index 99ff6549ac..3b4313a8be 100644 --- a/libgo/go/compress/zlib/writer.go +++ b/libgo/go/compress/zlib/writer.go @@ -34,8 +34,8 @@ type Writer struct { wroteHeader bool } -// NewWriter creates a new Writer that satisfies writes by compressing data -// written to w. +// NewWriter creates a new Writer. +// Writes to the returned Writer are compressed and written to w. // // It is the caller's responsibility to call Close on the WriteCloser when done. // Writes may be buffered and not flushed until Close. @@ -174,7 +174,8 @@ func (z *Writer) Flush() error { return z.err } -// Calling Close does not close the wrapped io.Writer originally passed to NewWriter. +// Close closes the Writer, flushing any unwritten data to the underlying +// io.Writer, but does not close the underlying io.Writer. func (z *Writer) Close() error { if !z.wroteHeader { z.err = z.writeHeader() diff --git a/libgo/go/compress/zlib/writer_test.go b/libgo/go/compress/zlib/writer_test.go index cf9c832545..71ba81aaa7 100644 --- a/libgo/go/compress/zlib/writer_test.go +++ b/libgo/go/compress/zlib/writer_test.go @@ -120,7 +120,7 @@ func testFileLevelDictReset(t *testing.T, fn string, level int, dict []byte) { } out := buf.String() - // Reset and comprses again. + // Reset and compress again. buf2 := new(bytes.Buffer) zlibw.Reset(buf2) _, err = zlibw.Write(b0) diff --git a/libgo/go/container/heap/heap.go b/libgo/go/container/heap/heap.go index 52c8507b42..c467a11910 100644 --- a/libgo/go/container/heap/heap.go +++ b/libgo/go/container/heap/heap.go @@ -22,7 +22,7 @@ import "sort" // min-heap with the following invariants (established after // Init has been called or if the data is empty or sorted): // -// !h.Less(j, i) for 0 <= i < h.Len() and j = 2*i+1 or 2*i+2 and j < h.Len() +// !h.Less(j, i) for 0 <= i < h.Len() and 2*i+1 <= j <= 2*i+2 and j < h.Len() // // Note that Push and Pop in this interface are for package heap's // implementation to call. To add and remove things from the heap, @@ -78,7 +78,7 @@ func Remove(h Interface, i int) interface{} { return h.Pop() } -// Fix reestablishes the heap ordering after the element at index i has changed its value. +// Fix re-establishes the heap ordering after the element at index i has changed its value. // Changing the value of the element at index i and then calling Fix is equivalent to, // but less expensive than, calling Remove(h, i) followed by a Push of the new value. // The complexity is O(log(n)) where n = h.Len(). diff --git a/libgo/go/container/list/list.go b/libgo/go/container/list/list.go index ed2d15a457..0256768efe 100755 --- a/libgo/go/container/list/list.go +++ b/libgo/go/container/list/list.go @@ -65,7 +65,7 @@ func New() *List { return new(List).Init() } // The complexity is O(1). func (l *List) Len() int { return l.len } -// Front returns the first element of list l or nil +// Front returns the first element of list l or nil. func (l *List) Front() *Element { if l.len == 0 { return nil @@ -180,18 +180,18 @@ func (l *List) MoveToBack(e *Element) { } // MoveBefore moves element e to its new position before mark. -// If e is not an element of l, or e == mark, the list is not modified. +// If e or mark is not an element of l, or e == mark, the list is not modified. func (l *List) MoveBefore(e, mark *Element) { - if e.list != l || e == mark { + if e.list != l || e == mark || mark.list != l { return } l.insert(l.remove(e), mark.prev) } // MoveAfter moves element e to its new position after mark. -// If e is not an element of l, or e == mark, the list is not modified. +// If e or mark is not an element of l, or e == mark, the list is not modified. func (l *List) MoveAfter(e, mark *Element) { - if e.list != l || e == mark { + if e.list != l || e == mark || mark.list != l { return } l.insert(l.remove(e), mark) diff --git a/libgo/go/container/list/list_test.go b/libgo/go/container/list/list_test.go index ee52afe82b..4d8bfc2bf0 100755 --- a/libgo/go/container/list/list_test.go +++ b/libgo/go/container/list/list_test.go @@ -285,3 +285,59 @@ func TestMove(t *testing.T) { checkListPointers(t, l, []*Element{e1, e3, e2, e4}) e1, e2, e3, e4 = e1, e3, e2, e4 } + +// Test PushFront, PushBack, PushFrontList, PushBackList with uninitialized List +func TestZeroList(t *testing.T) { + var l1 = new(List) + l1.PushFront(1) + checkList(t, l1, []interface{}{1}) + + var l2 = new(List) + l2.PushBack(1) + checkList(t, l2, []interface{}{1}) + + var l3 = new(List) + l3.PushFrontList(l1) + checkList(t, l3, []interface{}{1}) + + var l4 = new(List) + l4.PushBackList(l2) + checkList(t, l4, []interface{}{1}) +} + +// Test that a list l is not modified when calling InsertBefore with a mark that is not an element of l. +func TestInsertBeforeUnknownMark(t *testing.T) { + var l List + l.PushBack(1) + l.PushBack(2) + l.PushBack(3) + l.InsertBefore(1, new(Element)) + checkList(t, &l, []interface{}{1, 2, 3}) +} + +// Test that a list l is not modified when calling InsertAfter with a mark that is not an element of l. +func TestInsertAfterUnknownMark(t *testing.T) { + var l List + l.PushBack(1) + l.PushBack(2) + l.PushBack(3) + l.InsertAfter(1, new(Element)) + checkList(t, &l, []interface{}{1, 2, 3}) +} + +// Test that a list l is not modified when calling MoveAfter or MoveBefore with a mark that is not an element of l. +func TestMoveUnkownMark(t *testing.T) { + var l1 List + e1 := l1.PushBack(1) + + var l2 List + e2 := l2.PushBack(2) + + l1.MoveAfter(e1, e2) + checkList(t, &l1, []interface{}{1}) + checkList(t, &l2, []interface{}{2}) + + l1.MoveBefore(e1, e2) + checkList(t, &l1, []interface{}{1}) + checkList(t, &l2, []interface{}{2}) +} diff --git a/libgo/go/container/ring/ring_test.go b/libgo/go/container/ring/ring_test.go index 099d92b25b..552f0e24b5 100644 --- a/libgo/go/container/ring/ring_test.go +++ b/libgo/go/container/ring/ring_test.go @@ -218,3 +218,11 @@ func TestLinkUnlink(t *testing.T) { } } } + +// Test that calling Move() on an empty Ring initializes it. +func TestMoveEmptyRing(t *testing.T) { + var r Ring + + r.Move(1) + verify(t, &r, 1, 0) +} diff --git a/libgo/go/crypto/aes/aes_test.go b/libgo/go/crypto/aes/aes_test.go index 6261dd09fb..363180931c 100644 --- a/libgo/go/crypto/aes/aes_test.go +++ b/libgo/go/crypto/aes/aes_test.go @@ -354,6 +354,34 @@ func TestCipherDecrypt(t *testing.T) { } } +// Test short input/output. +// Assembly used to not notice. +// See issue 7928. +func TestShortBlocks(t *testing.T) { + bytes := func(n int) []byte { return make([]byte, n) } + + c, _ := NewCipher(bytes(16)) + + mustPanic(t, "crypto/aes: input not full block", func() { c.Encrypt(bytes(1), bytes(1)) }) + mustPanic(t, "crypto/aes: input not full block", func() { c.Decrypt(bytes(1), bytes(1)) }) + mustPanic(t, "crypto/aes: input not full block", func() { c.Encrypt(bytes(100), bytes(1)) }) + mustPanic(t, "crypto/aes: input not full block", func() { c.Decrypt(bytes(100), bytes(1)) }) + mustPanic(t, "crypto/aes: output not full block", func() { c.Encrypt(bytes(1), bytes(100)) }) + mustPanic(t, "crypto/aes: output not full block", func() { c.Decrypt(bytes(1), bytes(100)) }) +} + +func mustPanic(t *testing.T, msg string, f func()) { + defer func() { + err := recover() + if err == nil { + t.Errorf("function did not panic, wanted %q", msg) + } else if err != msg { + t.Errorf("got panic %v, wanted %q", err, msg) + } + }() + f() +} + func BenchmarkEncrypt(b *testing.B) { tt := encryptTests[0] c, err := NewCipher(tt.key) diff --git a/libgo/go/crypto/aes/cipher.go b/libgo/go/crypto/aes/cipher.go index d931134a70..2c6bb0a89c 100644 --- a/libgo/go/crypto/aes/cipher.go +++ b/libgo/go/crypto/aes/cipher.go @@ -46,9 +46,21 @@ func NewCipher(key []byte) (cipher.Block, error) { func (c *aesCipher) BlockSize() int { return BlockSize } func (c *aesCipher) Encrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } encryptBlock(c.enc, dst, src) } func (c *aesCipher) Decrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/aes: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/aes: output not full block") + } decryptBlock(c.dec, dst, src) } diff --git a/libgo/go/crypto/aes/cipher_asm.go b/libgo/go/crypto/aes/cipher_asm.go index 21369fc382..964eaaa6f8 100644 --- a/libgo/go/crypto/aes/cipher_asm.go +++ b/libgo/go/crypto/aes/cipher_asm.go @@ -21,6 +21,7 @@ func encryptBlock(xk []uint32, dst, src []byte) { encryptBlockGo(xk, dst, src) } } + func decryptBlock(xk []uint32, dst, src []byte) { if useAsm { decryptBlockAsm(len(xk)/4-1, &xk[0], &dst[0], &src[0]) @@ -28,6 +29,7 @@ func decryptBlock(xk []uint32, dst, src []byte) { decryptBlockGo(xk, dst, src) } } + func expandKey(key []byte, enc, dec []uint32) { if useAsm { rounds := 10 diff --git a/libgo/go/crypto/cipher/benchmark_test.go b/libgo/go/crypto/cipher/benchmark_test.go new file mode 100644 index 0000000000..027b248510 --- /dev/null +++ b/libgo/go/crypto/cipher/benchmark_test.go @@ -0,0 +1,139 @@ +// 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 cipher_test + +import ( + "crypto/aes" + "crypto/cipher" + "testing" +) + +func BenchmarkAESGCMSeal1K(b *testing.B) { + buf := make([]byte, 1024) + 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[:], buf, nonce[:]) + } +} + +func BenchmarkAESGCMOpen1K(b *testing.B) { + buf := make([]byte, 1024) + b.SetBytes(int64(len(buf))) + + var key [16]byte + var nonce [12]byte + aes, _ := aes.NewCipher(key[:]) + aesgcm, _ := cipher.NewGCM(aes) + var out []byte + out = aesgcm.Seal(out[:0], nonce[:], buf, nonce[:]) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := aesgcm.Open(buf[:0], nonce[:], out, nonce[:]) + if err != nil { + b.Errorf("Open: %v", err) + } + } +} + +// If we test exactly 1K blocks, we would generate exact multiples of +// the cipher's block size, and the cipher stream fragments would +// always be wordsize aligned, whereas non-aligned is a more typical +// use-case. +const almost1K = 1024 - 5 + +func BenchmarkAESCFBEncrypt1K(b *testing.B) { + buf := make([]byte, almost1K) + b.SetBytes(int64(len(buf))) + + var key [16]byte + var iv [16]byte + aes, _ := aes.NewCipher(key[:]) + ctr := cipher.NewCFBEncrypter(aes, iv[:]) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + ctr.XORKeyStream(buf, buf) + } +} + +func BenchmarkAESCFBDecrypt1K(b *testing.B) { + buf := make([]byte, almost1K) + b.SetBytes(int64(len(buf))) + + var key [16]byte + var iv [16]byte + aes, _ := aes.NewCipher(key[:]) + ctr := cipher.NewCFBDecrypter(aes, iv[:]) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + ctr.XORKeyStream(buf, buf) + } +} + +func BenchmarkAESOFB1K(b *testing.B) { + buf := make([]byte, almost1K) + b.SetBytes(int64(len(buf))) + + var key [16]byte + var iv [16]byte + aes, _ := aes.NewCipher(key[:]) + ctr := cipher.NewOFB(aes, iv[:]) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + ctr.XORKeyStream(buf, buf) + } +} + +func BenchmarkAESCTR1K(b *testing.B) { + buf := make([]byte, almost1K) + b.SetBytes(int64(len(buf))) + + var key [16]byte + var iv [16]byte + aes, _ := aes.NewCipher(key[:]) + ctr := cipher.NewCTR(aes, iv[:]) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + ctr.XORKeyStream(buf, buf) + } +} + +func BenchmarkAESCBCEncrypt1K(b *testing.B) { + buf := make([]byte, 1024) + b.SetBytes(int64(len(buf))) + + var key [16]byte + var iv [16]byte + aes, _ := aes.NewCipher(key[:]) + cbc := cipher.NewCBCEncrypter(aes, iv[:]) + for i := 0; i < b.N; i++ { + cbc.CryptBlocks(buf, buf) + } +} + +func BenchmarkAESCBCDecrypt1K(b *testing.B) { + buf := make([]byte, 1024) + b.SetBytes(int64(len(buf))) + + var key [16]byte + var iv [16]byte + aes, _ := aes.NewCipher(key[:]) + cbc := cipher.NewCBCDecrypter(aes, iv[:]) + for i := 0; i < b.N; i++ { + cbc.CryptBlocks(buf, buf) + } +} diff --git a/libgo/go/crypto/cipher/cbc.go b/libgo/go/crypto/cipher/cbc.go index 4189677e39..241e122ee8 100644 --- a/libgo/go/crypto/cipher/cbc.go +++ b/libgo/go/crypto/cipher/cbc.go @@ -48,17 +48,22 @@ func (x *cbcEncrypter) CryptBlocks(dst, src []byte) { if len(dst) < len(src) { panic("crypto/cipher: output smaller than input") } + + iv := x.iv + for len(src) > 0 { - for i := 0; i < x.blockSize; i++ { - x.iv[i] ^= src[i] - } - x.b.Encrypt(x.iv, x.iv) - for i := 0; i < x.blockSize; i++ { - dst[i] = x.iv[i] - } + // Write the xor to dst, then encrypt in place. + xorBytes(dst[:x.blockSize], src[:x.blockSize], iv) + x.b.Encrypt(dst[:x.blockSize], dst[:x.blockSize]) + + // Move to the next block with this block as the next iv. + iv = dst[:x.blockSize] src = src[x.blockSize:] dst = dst[x.blockSize:] } + + // Save the iv for the next CryptBlocks call. + copy(x.iv, iv) } func (x *cbcEncrypter) SetIV(iv []byte) { @@ -89,17 +94,35 @@ func (x *cbcDecrypter) CryptBlocks(dst, src []byte) { if len(dst) < len(src) { panic("crypto/cipher: output smaller than input") } - for len(src) > 0 { - x.b.Decrypt(x.tmp, src[:x.blockSize]) - for i := 0; i < x.blockSize; i++ { - x.tmp[i] ^= x.iv[i] - x.iv[i] = src[i] - dst[i] = x.tmp[i] - } + if len(src) == 0 { + return + } - src = src[x.blockSize:] - dst = dst[x.blockSize:] + // For each block, we need to xor the decrypted data with the previous block's ciphertext (the iv). + // To avoid making a copy each time, we loop over the blocks BACKWARDS. + end := len(src) + start := end - x.blockSize + prev := start - x.blockSize + + // Copy the last block of ciphertext in preparation as the new iv. + copy(x.tmp, src[start:end]) + + // Loop over all but the first block. + for start > 0 { + x.b.Decrypt(dst[start:end], src[start:end]) + xorBytes(dst[start:end], dst[start:end], src[prev:start]) + + end = start + start = prev + prev -= x.blockSize } + + // The first block is special because it uses the saved iv. + x.b.Decrypt(dst[start:end], src[start:end]) + xorBytes(dst[start:end], dst[start:end], x.iv) + + // Set the new iv to the first block we copied earlier. + x.iv, x.tmp = x.tmp, x.iv } func (x *cbcDecrypter) SetIV(iv []byte) { diff --git a/libgo/go/crypto/cipher/cbc_aes_test.go b/libgo/go/crypto/cipher/cbc_aes_test.go index cee3a784b5..bf9e7ad701 100644 --- a/libgo/go/crypto/cipher/cbc_aes_test.go +++ b/libgo/go/crypto/cipher/cbc_aes_test.go @@ -63,28 +63,42 @@ var cbcAESTests = []struct { }, } -func TestCBC_AES(t *testing.T) { - for _, tt := range cbcAESTests { - test := tt.name - - c, err := aes.NewCipher(tt.key) +func TestCBCEncrypterAES(t *testing.T) { + for _, test := range cbcAESTests { + c, err := aes.NewCipher(test.key) if err != nil { - t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err) + t.Errorf("%s: NewCipher(%d bytes) = %s", test.name, len(test.key), err) continue } - encrypter := cipher.NewCBCEncrypter(c, tt.iv) - d := make([]byte, len(tt.in)) - encrypter.CryptBlocks(d, tt.in) - if !bytes.Equal(tt.out, d) { - t.Errorf("%s: CBCEncrypter\nhave %x\nwant %x", test, d, tt.out) + encrypter := cipher.NewCBCEncrypter(c, test.iv) + + data := make([]byte, len(test.in)) + copy(data, test.in) + + encrypter.CryptBlocks(data, data) + if !bytes.Equal(test.out, data) { + t.Errorf("%s: CBCEncrypter\nhave %x\nwant %x", test.name, data, test.out) } + } +} + +func TestCBCDecrypterAES(t *testing.T) { + for _, test := range cbcAESTests { + c, err := aes.NewCipher(test.key) + if err != nil { + t.Errorf("%s: NewCipher(%d bytes) = %s", test.name, len(test.key), err) + continue + } + + decrypter := cipher.NewCBCDecrypter(c, test.iv) + + data := make([]byte, len(test.out)) + copy(data, test.out) - decrypter := cipher.NewCBCDecrypter(c, tt.iv) - p := make([]byte, len(d)) - decrypter.CryptBlocks(p, d) - if !bytes.Equal(tt.in, p) { - t.Errorf("%s: CBCDecrypter\nhave %x\nwant %x", test, d, tt.in) + decrypter.CryptBlocks(data, data) + if !bytes.Equal(test.in, data) { + t.Errorf("%s: CBCDecrypter\nhave %x\nwant %x", test.name, data, test.in) } } } diff --git a/libgo/go/crypto/cipher/cfb.go b/libgo/go/crypto/cipher/cfb.go index 99006b546d..9b4eebf5b4 100644 --- a/libgo/go/crypto/cipher/cfb.go +++ b/libgo/go/crypto/cipher/cfb.go @@ -8,18 +8,41 @@ package cipher type cfb struct { b Block + next []byte out []byte outUsed int + decrypt bool } +func (x *cfb) XORKeyStream(dst, src []byte) { + for len(src) > 0 { + if x.outUsed == len(x.out) { + x.b.Encrypt(x.out, x.next) + x.outUsed = 0 + } + + if x.decrypt { + // We can precompute a larger segment of the + // keystream on decryption. This will allow + // larger batches for xor, and we should be + // able to match CTR/OFB performance. + copy(x.next[x.outUsed:], src) + } + n := xorBytes(dst, src, x.out[x.outUsed:]) + if !x.decrypt { + copy(x.next[x.outUsed:], dst) + } + dst = dst[n:] + src = src[n:] + x.outUsed += n + } +} + // NewCFBEncrypter returns a Stream which encrypts with cipher feedback mode, // using the given Block. The iv must be the same length as the Block's block // size. func NewCFBEncrypter(block Block, iv []byte) Stream { - if len(iv) != block.BlockSize() { - panic("cipher.NewCBFEncrypter: IV length must equal block size") - } return newCFB(block, iv, false) } @@ -27,44 +50,23 @@ func NewCFBEncrypter(block Block, iv []byte) Stream { // using the given Block. The iv must be the same length as the Block's block // size. func NewCFBDecrypter(block Block, iv []byte) Stream { - if len(iv) != block.BlockSize() { - panic("cipher.NewCBFEncrypter: IV length must equal block size") - } return newCFB(block, iv, true) } func newCFB(block Block, iv []byte, decrypt bool) Stream { blockSize := block.BlockSize() if len(iv) != blockSize { - return nil + // stack trace will indicate whether it was de or encryption + panic("cipher.newCFB: IV length must equal block size") } - x := &cfb{ b: block, out: make([]byte, blockSize), - outUsed: 0, + next: make([]byte, blockSize), + outUsed: blockSize, decrypt: decrypt, } - block.Encrypt(x.out, iv) + copy(x.next, iv) return x } - -func (x *cfb) XORKeyStream(dst, src []byte) { - for i := 0; i < len(src); i++ { - if x.outUsed == len(x.out) { - x.b.Encrypt(x.out, x.out) - x.outUsed = 0 - } - - if x.decrypt { - t := src[i] - dst[i] = src[i] ^ x.out[x.outUsed] - x.out[x.outUsed] = t - } else { - x.out[x.outUsed] ^= src[i] - dst[i] = x.out[x.outUsed] - } - x.outUsed++ - } -} diff --git a/libgo/go/crypto/cipher/cfb_test.go b/libgo/go/crypto/cipher/cfb_test.go index f704b337e4..9b544bb211 100644 --- a/libgo/go/crypto/cipher/cfb_test.go +++ b/libgo/go/crypto/cipher/cfb_test.go @@ -9,26 +9,103 @@ import ( "crypto/aes" "crypto/cipher" "crypto/rand" + "encoding/hex" "testing" ) -func TestCFB(t *testing.T) { +// cfbTests contains the test vectors from +// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, section +// F.3.13. +var cfbTests = []struct { + key, iv, plaintext, ciphertext string +}{ + { + "2b7e151628aed2a6abf7158809cf4f3c", + "000102030405060708090a0b0c0d0e0f", + "6bc1bee22e409f96e93d7e117393172a", + "3b3fd92eb72dad20333449f8e83cfb4a", + }, + { + "2b7e151628aed2a6abf7158809cf4f3c", + "3B3FD92EB72DAD20333449F8E83CFB4A", + "ae2d8a571e03ac9c9eb76fac45af8e51", + "c8a64537a0b3a93fcde3cdad9f1ce58b", + }, + { + "2b7e151628aed2a6abf7158809cf4f3c", + "C8A64537A0B3A93FCDE3CDAD9F1CE58B", + "30c81c46a35ce411e5fbc1191a0a52ef", + "26751f67a3cbb140b1808cf187a4f4df", + }, + { + "2b7e151628aed2a6abf7158809cf4f3c", + "26751F67A3CBB140B1808CF187A4F4DF", + "f69f2445df4f9b17ad2b417be66c3710", + "c04b05357c5d1c0eeac4c66f9ff7f2e6", + }, +} + +func TestCFBVectors(t *testing.T) { + for i, test := range cfbTests { + key, err := hex.DecodeString(test.key) + if err != nil { + t.Fatal(err) + } + iv, err := hex.DecodeString(test.iv) + if err != nil { + t.Fatal(err) + } + plaintext, err := hex.DecodeString(test.plaintext) + if err != nil { + t.Fatal(err) + } + expected, err := hex.DecodeString(test.ciphertext) + if err != nil { + t.Fatal(err) + } + + block, err := aes.NewCipher(key) + if err != nil { + t.Fatal(err) + } + + ciphertext := make([]byte, len(plaintext)) + cfb := cipher.NewCFBEncrypter(block, iv) + cfb.XORKeyStream(ciphertext, plaintext) + + if !bytes.Equal(ciphertext, expected) { + t.Errorf("#%d: wrong output: got %x, expected %x", i, ciphertext, expected) + } + + cfbdec := cipher.NewCFBDecrypter(block, iv) + plaintextCopy := make([]byte, len(ciphertext)) + cfbdec.XORKeyStream(plaintextCopy, ciphertext) + + if !bytes.Equal(plaintextCopy, plaintextCopy) { + t.Errorf("#%d: wrong plaintext: got %x, expected %x", i, plaintextCopy, plaintext) + } + } +} + +func TestCFBInverse(t *testing.T) { block, err := aes.NewCipher(commonKey128) if err != nil { t.Error(err) return } - plaintext := []byte("this is the plaintext") + plaintext := []byte("this is the plaintext. this is the plaintext.") iv := make([]byte, block.BlockSize()) rand.Reader.Read(iv) cfb := cipher.NewCFBEncrypter(block, iv) ciphertext := make([]byte, len(plaintext)) - cfb.XORKeyStream(ciphertext, plaintext) + copy(ciphertext, plaintext) + cfb.XORKeyStream(ciphertext, ciphertext) cfbdec := cipher.NewCFBDecrypter(block, iv) plaintextCopy := make([]byte, len(plaintext)) - cfbdec.XORKeyStream(plaintextCopy, ciphertext) + copy(plaintextCopy, ciphertext) + cfbdec.XORKeyStream(plaintextCopy, plaintextCopy) if !bytes.Equal(plaintextCopy, plaintext) { t.Errorf("got: %x, want: %x", plaintextCopy, plaintext) diff --git a/libgo/go/crypto/cipher/cipher.go b/libgo/go/crypto/cipher/cipher.go index 1ffaa8c2c3..67afdb1e05 100644 --- a/libgo/go/crypto/cipher/cipher.go +++ b/libgo/go/crypto/cipher/cipher.go @@ -46,16 +46,6 @@ type BlockMode interface { // Utility routines -func shift1(dst, src []byte) byte { - var b byte - for i := len(src) - 1; i >= 0; i-- { - bb := src[i] >> 7 - dst[i] = src[i]<<1 | b - b = bb - } - return b -} - func dup(p []byte) []byte { q := make([]byte, len(p)) copy(q, p) diff --git a/libgo/go/crypto/cipher/ctr.go b/libgo/go/crypto/cipher/ctr.go index d9ee9d8272..70ac40f6a7 100644 --- a/libgo/go/crypto/cipher/ctr.go +++ b/libgo/go/crypto/cipher/ctr.go @@ -19,37 +19,58 @@ type ctr struct { outUsed int } +const streamBufferSize = 512 + // NewCTR returns a Stream which encrypts/decrypts using the given Block in // counter mode. The length of iv must be the same as the Block's block size. func NewCTR(block Block, iv []byte) Stream { if len(iv) != block.BlockSize() { panic("cipher.NewCTR: IV length must equal block size") } - + bufSize := streamBufferSize + if bufSize < block.BlockSize() { + bufSize = block.BlockSize() + } return &ctr{ b: block, ctr: dup(iv), - out: make([]byte, len(iv)), - outUsed: len(iv), + out: make([]byte, 0, bufSize), + outUsed: 0, } } -func (x *ctr) XORKeyStream(dst, src []byte) { - for i := 0; i < len(src); i++ { - if x.outUsed == len(x.ctr) { - x.b.Encrypt(x.out, x.ctr) - x.outUsed = 0 - - // Increment counter - for i := len(x.ctr) - 1; i >= 0; i-- { - x.ctr[i]++ - if x.ctr[i] != 0 { - break - } +func (x *ctr) refill() { + remain := len(x.out) - x.outUsed + if remain > x.outUsed { + return + } + copy(x.out, x.out[x.outUsed:]) + x.out = x.out[:cap(x.out)] + bs := x.b.BlockSize() + for remain < len(x.out)-bs { + x.b.Encrypt(x.out[remain:], x.ctr) + remain += bs + + // Increment counter + for i := len(x.ctr) - 1; i >= 0; i-- { + x.ctr[i]++ + if x.ctr[i] != 0 { + break } } + } + x.out = x.out[:remain] + x.outUsed = 0 +} - dst[i] = src[i] ^ x.out[x.outUsed] - x.outUsed++ +func (x *ctr) XORKeyStream(dst, src []byte) { + for len(src) > 0 { + if x.outUsed >= len(x.out)-x.b.BlockSize() { + x.refill() + } + n := xorBytes(dst, src, x.out[x.outUsed:]) + dst = dst[n:] + src = src[n:] + x.outUsed += n } } diff --git a/libgo/go/crypto/cipher/example_test.go b/libgo/go/crypto/cipher/example_test.go index 373f6791be..1cfa982df4 100644 --- a/libgo/go/crypto/cipher/example_test.go +++ b/libgo/go/crypto/cipher/example_test.go @@ -240,7 +240,7 @@ func ExampleStreamReader() { } // Note that this example is simplistic in that it omits any - // authentication of the encrypted data. It you were actually to use + // authentication of the encrypted data. If you were actually to use // StreamReader in this manner, an attacker could flip arbitrary bits in // the output. } @@ -277,7 +277,7 @@ func ExampleStreamWriter() { } // Note that this example is simplistic in that it omits any - // authentication of the encrypted data. It you were actually to use + // authentication of the encrypted data. If you were actually to use // StreamReader in this manner, an attacker could flip arbitrary bits in // the decrypted result. } diff --git a/libgo/go/crypto/cipher/gcm.go b/libgo/go/crypto/cipher/gcm.go index 2bcb469852..bdafd85fc3 100644 --- a/libgo/go/crypto/cipher/gcm.go +++ b/libgo/go/crypto/cipher/gcm.go @@ -30,9 +30,9 @@ type AEAD interface { // Open decrypts and authenticates ciphertext, authenticates the // additional data and, if successful, appends the resulting plaintext - // to dst, returning the updated slice and true. On error, nil and - // false is returned. The nonce must be NonceSize() bytes long and both - // it and the additional data must match the value passed to Seal. + // to dst, returning the updated slice. The nonce must be NonceSize() + // bytes long and both it and the additional data must match the + // value passed to Seal. // // The ciphertext and dst may alias exactly or not at all. Open(dst, nonce, ciphertext, data []byte) ([]byte, error) @@ -258,11 +258,11 @@ func (g *gcm) update(y *gcmFieldElement, data []byte) { // gcmInc32 treats the final four bytes of counterBlock as a big-endian value // and increments it. func gcmInc32(counterBlock *[16]byte) { - c := 1 for i := gcmBlockSize - 1; i >= gcmBlockSize-4; i-- { - c += int(counterBlock[i]) - counterBlock[i] = byte(c) - c >>= 8 + counterBlock[i]++ + if counterBlock[i] != 0 { + break + } } } @@ -289,9 +289,7 @@ func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) { g.cipher.Encrypt(mask[:], counter[:]) gcmInc32(counter) - for i := range mask { - out[i] = in[i] ^ mask[i] - } + xorWords(out, in, mask[:]) out = out[gcmBlockSize:] in = in[gcmBlockSize:] } @@ -299,10 +297,7 @@ func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) { if len(in) > 0 { g.cipher.Encrypt(mask[:], counter[:]) gcmInc32(counter) - - for i := range in { - out[i] = in[i] ^ mask[i] - } + xorBytes(out, in, mask[:]) } } @@ -321,9 +316,7 @@ func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize] putUint64(out, y.low) putUint64(out[8:], y.high) - for i := range tagMask { - out[i] ^= tagMask[i] - } + xorWords(out, out, tagMask[:]) } func getUint64(data []byte) uint64 { diff --git a/libgo/go/crypto/cipher/gcm_test.go b/libgo/go/crypto/cipher/gcm_test.go index 02d4215900..0c502ce405 100644 --- a/libgo/go/crypto/cipher/gcm_test.go +++ b/libgo/go/crypto/cipher/gcm_test.go @@ -157,19 +157,3 @@ func TestAESGCM(t *testing.T) { ct[0] ^= 0x80 } } - -func BenchmarkAESGCM(b *testing.B) { - buf := make([]byte, 1024) - 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[:], buf, nonce[:]) - } -} diff --git a/libgo/go/crypto/cipher/ofb.go b/libgo/go/crypto/cipher/ofb.go index 85e5f02b0a..e86ebcb237 100644 --- a/libgo/go/crypto/cipher/ofb.go +++ b/libgo/go/crypto/cipher/ofb.go @@ -8,6 +8,7 @@ package cipher type ofb struct { b Block + cipher []byte out []byte outUsed int } @@ -20,25 +21,46 @@ func NewOFB(b Block, iv []byte) Stream { if len(iv) != blockSize { return nil } - + bufSize := streamBufferSize + if bufSize < blockSize { + bufSize = blockSize + } x := &ofb{ b: b, - out: make([]byte, blockSize), + cipher: make([]byte, blockSize), + out: make([]byte, 0, bufSize), outUsed: 0, } - b.Encrypt(x.out, iv) + copy(x.cipher, iv) return x } +func (x *ofb) refill() { + bs := x.b.BlockSize() + remain := len(x.out) - x.outUsed + if remain > x.outUsed { + return + } + copy(x.out, x.out[x.outUsed:]) + x.out = x.out[:cap(x.out)] + for remain < len(x.out)-bs { + x.b.Encrypt(x.cipher, x.cipher) + copy(x.out[remain:], x.cipher) + remain += bs + } + x.out = x.out[:remain] + x.outUsed = 0 +} + func (x *ofb) XORKeyStream(dst, src []byte) { - for i, s := range src { - if x.outUsed == len(x.out) { - x.b.Encrypt(x.out, x.out) - x.outUsed = 0 + for len(src) > 0 { + if x.outUsed >= len(x.out)-x.b.BlockSize() { + x.refill() } - - dst[i] = s ^ x.out[x.outUsed] - x.outUsed++ + n := xorBytes(dst, src, x.out[x.outUsed:]) + dst = dst[n:] + src = src[n:] + x.outUsed += n } } diff --git a/libgo/go/crypto/cipher/xor.go b/libgo/go/crypto/cipher/xor.go new file mode 100644 index 0000000000..f88dc8914a --- /dev/null +++ b/libgo/go/crypto/cipher/xor.go @@ -0,0 +1,84 @@ +// 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 cipher + +import ( + "runtime" + "unsafe" +) + +const wordSize = int(unsafe.Sizeof(uintptr(0))) +const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" + +// fastXORBytes xors in bulk. It only works on architectures that +// support unaligned read/writes. +func fastXORBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + + w := n / wordSize + if w > 0 { + dw := *(*[]uintptr)(unsafe.Pointer(&dst)) + aw := *(*[]uintptr)(unsafe.Pointer(&a)) + bw := *(*[]uintptr)(unsafe.Pointer(&b)) + for i := 0; i < w; i++ { + dw[i] = aw[i] ^ bw[i] + } + } + + for i := (n - n%wordSize); i < n; i++ { + dst[i] = a[i] ^ b[i] + } + + return n +} + +func safeXORBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + for i := 0; i < n; i++ { + dst[i] = a[i] ^ b[i] + } + return n +} + +// xorBytes xors the bytes in a and b. The destination is assumed to have enough +// space. Returns the number of bytes xor'd. +func xorBytes(dst, a, b []byte) int { + if supportsUnaligned { + return fastXORBytes(dst, a, b) + } else { + // TODO(hanwen): if (dst, a, b) have common alignment + // we could still try fastXORBytes. It is not clear + // how often this happens, and it's only worth it if + // the block encryption itself is hardware + // accelerated. + return safeXORBytes(dst, a, b) + } +} + +// fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.) +// The arguments are assumed to be of equal length. +func fastXORWords(dst, a, b []byte) { + dw := *(*[]uintptr)(unsafe.Pointer(&dst)) + aw := *(*[]uintptr)(unsafe.Pointer(&a)) + bw := *(*[]uintptr)(unsafe.Pointer(&b)) + n := len(b) / wordSize + for i := 0; i < n; i++ { + dw[i] = aw[i] ^ bw[i] + } +} + +func xorWords(dst, a, b []byte) { + if supportsUnaligned { + fastXORWords(dst, a, b) + } else { + safeXORBytes(dst, a, b) + } +} diff --git a/libgo/go/crypto/cipher/xor_test.go b/libgo/go/crypto/cipher/xor_test.go new file mode 100644 index 0000000000..cc1c9d72d5 --- /dev/null +++ b/libgo/go/crypto/cipher/xor_test.go @@ -0,0 +1,28 @@ +// 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 cipher + +import ( + "bytes" + "testing" +) + +func TestXOR(t *testing.T) { + for alignP := 0; alignP < 2; alignP++ { + for alignQ := 0; alignQ < 2; alignQ++ { + for alignD := 0; alignD < 2; alignD++ { + p := make([]byte, 1024)[alignP:] + q := make([]byte, 1024)[alignQ:] + d1 := make([]byte, 1024+alignD)[alignD:] + d2 := make([]byte, 1024+alignD)[alignD:] + xorBytes(d1, p, q) + safeXORBytes(d2, p, q) + if bytes.Compare(d1, d2) != 0 { + t.Error("not equal") + } + } + } + } +} diff --git a/libgo/go/crypto/crypto.go b/libgo/go/crypto/crypto.go index 4b03628e69..59b23e93f5 100644 --- a/libgo/go/crypto/crypto.go +++ b/libgo/go/crypto/crypto.go @@ -7,6 +7,7 @@ package crypto import ( "hash" + "io" "strconv" ) @@ -14,8 +15,13 @@ import ( // package. type Hash uint +// HashFunc simply returns the value of h so that Hash implements SignerOpts. +func (h Hash) HashFunc() Hash { + return h +} + const ( - MD4 Hash = 1 + iota // import code.google.com/p/go.crypto/md4 + MD4 Hash = 1 + iota // import golang.org/x/crypto/md4 MD5 // import crypto/md5 SHA1 // import crypto/sha1 SHA224 // import crypto/sha256 @@ -23,7 +29,11 @@ const ( SHA384 // import crypto/sha512 SHA512 // import crypto/sha512 MD5SHA1 // no implementation; MD5+SHA1 used for TLS RSA - RIPEMD160 // import code.google.com/p/go.crypto/ripemd160 + RIPEMD160 // import golang.org/x/crypto/ripemd160 + SHA3_224 // import golang.org/x/crypto/sha3 + SHA3_256 // import golang.org/x/crypto/sha3 + SHA3_384 // import golang.org/x/crypto/sha3 + SHA3_512 // import golang.org/x/crypto/sha3 maxHash ) @@ -35,6 +45,10 @@ var digestSizes = []uint8{ SHA256: 32, SHA384: 48, SHA512: 64, + SHA3_224: 28, + SHA3_256: 32, + SHA3_384: 48, + SHA3_512: 64, MD5SHA1: 36, RIPEMD160: 20, } @@ -83,3 +97,30 @@ type PublicKey interface{} // PrivateKey represents a private key using an unspecified algorithm. type PrivateKey interface{} + +// Signer is an interface for an opaque private key that can be used for +// signing operations. For example, an RSA key kept in a hardware module. +type Signer interface { + // Public returns the public key corresponding to the opaque, + // private key. + Public() PublicKey + + // Sign signs msg with the private key, possibly using entropy from + // rand. For an RSA key, the resulting signature should be either a + // PKCS#1 v1.5 or PSS signature (as indicated by opts). For an (EC)DSA + // key, it should be a DER-serialised, ASN.1 signature structure. + // + // Hash implements the SignerOpts interface and, in most cases, one can + // simply pass in the hash function used as opts. Sign may also attempt + // to type assert opts to other types in order to obtain algorithm + // specific values. See the documentation in each package for details. + Sign(rand io.Reader, msg []byte, opts SignerOpts) (signature []byte, err error) +} + +// SignerOpts contains options for signing with a Signer. +type SignerOpts interface { + // HashFunc returns an identifier for the hash function used to produce + // the message passed to Signer.Sign, or else zero to indicate that no + // hashing was done. + HashFunc() Hash +} diff --git a/libgo/go/crypto/dsa/dsa.go b/libgo/go/crypto/dsa/dsa.go index 5a2a65744e..b7565a61b0 100644 --- a/libgo/go/crypto/dsa/dsa.go +++ b/libgo/go/crypto/dsa/dsa.go @@ -173,6 +173,16 @@ func GenerateKey(priv *PrivateKey, rand io.Reader) error { return nil } +// fermatInverse calculates the inverse of k in GF(P) using Fermat's method. +// This has better constant-time properties than Euclid's method (implemented +// in math/big.Int.ModInverse) although math/big itself isn't strictly +// constant-time so it's not perfect. +func fermatInverse(k, P *big.Int) *big.Int { + two := big.NewInt(2) + pMinus2 := new(big.Int).Sub(P, two) + return new(big.Int).Exp(k, pMinus2, P) +} + // Sign signs an arbitrary length hash (which should be the result of hashing a // larger message) using the private key, priv. It returns the signature as a // pair of integers. The security of the private key depends on the entropy of @@ -205,7 +215,7 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err } } - kInv := new(big.Int).ModInverse(k, priv.Q) + kInv := fermatInverse(k, priv.Q) r = new(big.Int).Exp(priv.G, k, priv.P) r.Mod(r, priv.Q) diff --git a/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go index d02f15c34d..d6135531bf 100644 --- a/libgo/go/crypto/ecdsa/ecdsa.go +++ b/libgo/go/crypto/ecdsa/ecdsa.go @@ -13,7 +13,9 @@ package ecdsa // http://www.secg.org/download/aid-780/sec1-v2.pdf import ( + "crypto" "crypto/elliptic" + "encoding/asn1" "io" "math/big" ) @@ -30,6 +32,28 @@ type PrivateKey struct { D *big.Int } +type ecdsaSignature struct { + R, S *big.Int +} + +// Public returns the public key corresponding to priv. +func (priv *PrivateKey) Public() crypto.PublicKey { + return &priv.PublicKey +} + +// Sign signs msg with priv, reading randomness from rand. This method is +// intended to support keys where the private part is kept in, for example, a +// hardware module. Common uses should use the Sign function in this package +// directly. +func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) { + r, s, err := Sign(rand, priv, msg) + if err != nil { + return nil, err + } + + return asn1.Marshal(ecdsaSignature{r, s}) +} + var one = new(big.Int).SetInt64(1) // randFieldElement returns a random element of the field underlying the given @@ -84,6 +108,16 @@ func hashToInt(hash []byte, c elliptic.Curve) *big.Int { return ret } +// fermatInverse calculates the inverse of k in GF(P) using Fermat's method. +// This has better constant-time properties than Euclid's method (implemented +// in math/big.Int.ModInverse) although math/big itself isn't strictly +// constant-time so it's not perfect. +func fermatInverse(k, N *big.Int) *big.Int { + two := big.NewInt(2) + nMinus2 := new(big.Int).Sub(N, two) + return new(big.Int).Exp(k, nMinus2, N) +} + // Sign signs an arbitrary length hash (which should be the result of hashing a // larger message) using the private key, priv. It returns the signature as a // pair of integers. The security of the private key depends on the entropy of @@ -102,7 +136,7 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err return } - kInv = new(big.Int).ModInverse(k, N) + kInv = fermatInverse(k, N) r, _ = priv.Curve.ScalarBaseMult(k.Bytes()) r.Mod(r, N) if r.Sign() != 0 { diff --git a/libgo/go/crypto/hmac/hmac_test.go b/libgo/go/crypto/hmac/hmac_test.go index d4860424eb..e80b7e0baa 100644 --- a/libgo/go/crypto/hmac/hmac_test.go +++ b/libgo/go/crypto/hmac/hmac_test.go @@ -15,10 +15,12 @@ import ( ) type hmacTest struct { - hash func() hash.Hash - key []byte - in []byte - out string + hash func() hash.Hash + key []byte + in []byte + out string + size int + blocksize int } var hmacTests = []hmacTest{ @@ -38,6 +40,8 @@ var hmacTests = []hmacTest{ }, []byte("Sample #1"), "4f4ca3d5d68ba7cc0a1208c9c61e9c5da0403c0a", + sha1.Size, + sha1.BlockSize, }, { sha1.New, @@ -48,6 +52,8 @@ var hmacTests = []hmacTest{ }, []byte("Sample #2"), "0922d3405faa3d194f82a45830737d5cc6c75d24", + sha1.Size, + sha1.BlockSize, }, { sha1.New, @@ -68,6 +74,8 @@ var hmacTests = []hmacTest{ }, []byte("Sample #3"), "bcf41eab8bb2d802f3d05caf7cb092ecf8d1a3aa", + sha1.Size, + sha1.BlockSize, }, // Test from Plan 9. @@ -76,6 +84,8 @@ var hmacTests = []hmacTest{ []byte("Jefe"), []byte("what do ya want for nothing?"), "750c783e6ab0b503eaa86e310a5db738", + md5.Size, + md5.BlockSize, }, // Tests from RFC 4231 @@ -88,12 +98,16 @@ var hmacTests = []hmacTest{ }, []byte("Hi There"), "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7", + sha256.Size, + sha256.BlockSize, }, { sha256.New, []byte("Jefe"), []byte("what do ya want for nothing?"), "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843", + sha256.Size, + sha256.BlockSize, }, { sha256.New, @@ -112,6 +126,8 @@ var hmacTests = []hmacTest{ 0xdd, 0xdd, }, "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe", + sha256.Size, + sha256.BlockSize, }, { sha256.New, @@ -131,6 +147,8 @@ var hmacTests = []hmacTest{ 0xcd, 0xcd, }, "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b", + sha256.Size, + sha256.BlockSize, }, { sha256.New, @@ -155,6 +173,8 @@ var hmacTests = []hmacTest{ }, []byte("Test Using Larger Than Block-Size Key - Hash Key First"), "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54", + sha256.Size, + sha256.BlockSize, }, { sha256.New, @@ -181,6 +201,8 @@ var hmacTests = []hmacTest{ "and a larger than block-size data. The key needs to " + "be hashed before being used by the HMAC algorithm."), "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2", + sha256.Size, + sha256.BlockSize, }, // Tests from http://csrc.nist.gov/groups/ST/toolkit/examples.html @@ -199,6 +221,8 @@ var hmacTests = []hmacTest{ }, []byte("Sample message for keylen=blocklen"), "5fd596ee78d5553c8ff4e72d266dfd192366da29", + sha1.Size, + sha1.BlockSize, }, { sha1.New, @@ -209,6 +233,8 @@ var hmacTests = []hmacTest{ }, []byte("Sample message for keylenmd5block.go +// go run gen.go [-full] -output md5block.go // // The -full flag causes the generated code to do a full // (16x) unrolling instead of a 4x unrolling. @@ -15,18 +15,33 @@ package main import ( + "bytes" "flag" + "go/format" + "io/ioutil" "log" - "os" "strings" "text/template" ) +var filename = flag.String("output", "md5block.go", "output file name") + func main() { flag.Parse() + var buf bytes.Buffer + t := template.Must(template.New("main").Funcs(funcs).Parse(program)) - if err := t.Execute(os.Stdout, data); err != nil { + if err := t.Execute(&buf, data); err != nil { + log.Fatal(err) + } + + data, err := format.Source(buf.Bytes()) + if err != nil { + log.Fatal(err) + } + err = ioutil.WriteFile(*filename, data, 0644) + if err != nil { log.Fatal(err) } } @@ -160,11 +175,12 @@ var data = Data{ }, } -var program = ` -// DO NOT EDIT. -// Generate with: go run gen.go{{if .Full}} -full{{end}} | gofmt >md5block.go +var program = `// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. -// +build !amd64,!386,!arm +// DO NOT EDIT. +// Generate with: go run gen.go{{if .Full}} -full{{end}} -output md5block.go package md5 @@ -201,7 +217,7 @@ func init() { littleEndian = *(*[4]byte)(unsafe.Pointer(&x)) == y } -func block(dig *digest, p []byte) { +func blockGeneric(dig *digest, p []byte) { a := dig.s[0] b := dig.s[1] c := dig.s[2] diff --git a/libgo/go/crypto/md5/md5.go b/libgo/go/crypto/md5/md5.go index 1a1f35fabc..8c50c6d0bf 100644 --- a/libgo/go/crypto/md5/md5.go +++ b/libgo/go/crypto/md5/md5.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:generate go run gen.go -full -output md5block.go + // Package md5 implements the MD5 hash algorithm as defined in RFC 1321. package md5 diff --git a/libgo/go/crypto/md5/md5_test.go b/libgo/go/crypto/md5/md5_test.go index a8b7a1a525..e7faf4961e 100644 --- a/libgo/go/crypto/md5/md5_test.go +++ b/libgo/go/crypto/md5/md5_test.go @@ -5,6 +5,7 @@ package md5 import ( + "crypto/rand" "fmt" "io" "testing" @@ -105,6 +106,18 @@ func TestLarge(t *testing.T) { } } +// Tests that blockGeneric (pure Go) and block (in assembly for amd64, 386, arm) match. +func TestBlockGeneric(t *testing.T) { + gen, asm := New().(*digest), New().(*digest) + buf := make([]byte, BlockSize*20) // arbitrary factor + rand.Read(buf) + blockGeneric(gen, buf) + block(asm, buf) + if *gen != *asm { + t.Error("block and blockGeneric resulted in different states") + } +} + var bench = New() var buf = make([]byte, 8192+1) var sum = make([]byte, bench.Size()) diff --git a/libgo/go/crypto/md5/md5block.go b/libgo/go/crypto/md5/md5block.go index 3e739e36ff..64e1e7c1ef 100644 --- a/libgo/go/crypto/md5/md5block.go +++ b/libgo/go/crypto/md5/md5block.go @@ -1,7 +1,9 @@ -// DO NOT EDIT. -// Generate with: go run gen.go -full | gofmt >md5block.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. -// +build !amd64,!386,!arm +// DO NOT EDIT. +// Generate with: go run gen.go -full -output md5block.go package md5 @@ -20,7 +22,7 @@ func init() { littleEndian = *(*[4]byte)(unsafe.Pointer(&x)) == y } -func block(dig *digest, p []byte) { +func blockGeneric(dig *digest, p []byte) { a := dig.s[0] b := dig.s[1] c := dig.s[2] diff --git a/libgo/go/crypto/md5/md5block_decl.go b/libgo/go/crypto/md5/md5block_decl.go index c4d6aaaf03..d7956a6d20 100644 --- a/libgo/go/crypto/md5/md5block_decl.go +++ b/libgo/go/crypto/md5/md5block_decl.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64 386 arm +// +build amd64 amd64p32 386 arm package md5 diff --git a/libgo/go/crypto/md5/md5block_generic.go b/libgo/go/crypto/md5/md5block_generic.go new file mode 100644 index 0000000000..263463e51c --- /dev/null +++ b/libgo/go/crypto/md5/md5block_generic.go @@ -0,0 +1,9 @@ +// 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. + +// +build !amd64,!amd64p32,!386,!arm + +package md5 + +var block = blockGeneric diff --git a/libgo/go/crypto/rand/rand_linux.go b/libgo/go/crypto/rand/rand_linux.go new file mode 100644 index 0000000000..8cb59c75df --- /dev/null +++ b/libgo/go/crypto/rand/rand_linux.go @@ -0,0 +1,39 @@ +// 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 rand + +import ( + "internal/syscall" + "sync" +) + +func init() { + altGetRandom = getRandomLinux +} + +var ( + once sync.Once + useSyscall bool +) + +func pickStrategy() { + // Test whether we should use the system call or /dev/urandom. + // We'll fall back to urandom if: + // - the kernel is too old (before 3.17) + // - the machine has no entropy available (early boot + no hardware + // entropy source?) and we want to avoid blocking later. + var buf [1]byte + n, err := syscall.GetRandom(buf[:], syscall.GRND_NONBLOCK) + useSyscall = n == 1 && err == nil +} + +func getRandomLinux(p []byte) (ok bool) { + once.Do(pickStrategy) + if !useSyscall { + return false + } + n, err := syscall.GetRandom(p, 0) + return n == len(p) && err == nil +} diff --git a/libgo/go/crypto/rand/rand_unix.go b/libgo/go/crypto/rand/rand_unix.go index 238ceee557..62d0fbdb35 100644 --- a/libgo/go/crypto/rand/rand_unix.go +++ b/libgo/go/crypto/rand/rand_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin dragonfly freebsd linux netbsd openbsd plan9 +// +build darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris // Unix cryptographically secure pseudorandom number // generator. @@ -20,6 +20,8 @@ import ( "time" ) +const urandomDevice = "/dev/urandom" + // Easy implementation: read from /dev/urandom. // This is sufficient on Linux, OS X, and FreeBSD. @@ -27,7 +29,7 @@ func init() { if runtime.GOOS == "plan9" { Reader = newReader(nil) } else { - Reader = &devReader{name: "/dev/urandom"} + Reader = &devReader{name: urandomDevice} } } @@ -38,7 +40,14 @@ type devReader struct { mu sync.Mutex } +// altGetRandom if non-nil specifies an OS-specific function to get +// urandom-style randomness. +var altGetRandom func([]byte) (ok bool) + func (r *devReader) Read(b []byte) (n int, err error) { + if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) { + return len(b), nil + } r.mu.Lock() defer r.mu.Unlock() if r.f == nil { diff --git a/libgo/go/crypto/rand/util.go b/libgo/go/crypto/rand/util.go index 0cd5e0e022..5f74407850 100644 --- a/libgo/go/crypto/rand/util.go +++ b/libgo/go/crypto/rand/util.go @@ -27,9 +27,11 @@ var smallPrimesProduct = new(big.Int).SetUint64(16294579238595022365) // Prime returns a number, p, of the given size, such that p is prime // with high probability. +// Prime will return error for any error returned by rand.Read or if bits < 2. func Prime(rand io.Reader, bits int) (p *big.Int, err error) { - if bits < 1 { - err = errors.New("crypto/rand: prime size must be positive") + if bits < 2 { + err = errors.New("crypto/rand: prime size must be at least 2-bit") + return } b := uint(bits % 8) @@ -79,7 +81,7 @@ func Prime(rand io.Reader, bits int) (p *big.Int, err error) { for delta := uint64(0); delta < 1<<20; delta += 2 { m := mod + delta for _, prime := range smallPrimes { - if m%uint64(prime) == 0 { + if m%uint64(prime) == 0 && (bits > 6 || m != uint64(prime)) { continue NextDelta } } diff --git a/libgo/go/crypto/rand/util_test.go b/libgo/go/crypto/rand/util_test.go new file mode 100644 index 0000000000..1e2a4dd84b --- /dev/null +++ b/libgo/go/crypto/rand/util_test.go @@ -0,0 +1,65 @@ +// 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 rand_test + +import ( + "crypto/rand" + "math/big" + "testing" +) + +// http://golang.org/issue/6849. +func TestPrimeSmall(t *testing.T) { + for n := 2; n < 10; n++ { + p, err := rand.Prime(rand.Reader, n) + if err != nil { + t.Fatalf("Can't generate %d-bit prime: %v", n, err) + } + if p.BitLen() != n { + t.Fatalf("%v is not %d-bit", p, n) + } + if !p.ProbablyPrime(32) { + t.Fatalf("%v is not prime", p) + } + } +} + +// Test that passing bits < 2 causes Prime to return nil, error +func TestPrimeBitsLt2(t *testing.T) { + if p, err := rand.Prime(rand.Reader, 1); p != nil || err == nil { + t.Errorf("Prime should return nil, error when called with bits < 2") + } +} + +func TestInt(t *testing.T) { + // start at 128 so the case of (max.BitLen() % 8) == 0 is covered + for n := 128; n < 140; n++ { + b := new(big.Int).SetInt64(int64(n)) + if i, err := rand.Int(rand.Reader, b); err != nil { + t.Fatalf("Can't generate random value: %v, %v", i, err) + } + } +} + +func testIntPanics(t *testing.T, b *big.Int) { + defer func() { + if err := recover(); err == nil { + t.Errorf("Int should panic when called with max <= 0: %v", b) + } + }() + rand.Int(rand.Reader, b) +} + +// Test that passing a new big.Int as max causes Int to panic +func TestIntEmptyMaxPanics(t *testing.T) { + b := new(big.Int) + testIntPanics(t, b) +} + +// Test that passing a negative value as max causes Int to panic +func TestIntNegativeMaxPanics(t *testing.T) { + b := new(big.Int).SetInt64(int64(-1)) + testIntPanics(t, b) +} diff --git a/libgo/go/crypto/rc4/rc4.go b/libgo/go/crypto/rc4/rc4.go index 3d717c63b0..9acb681bfb 100644 --- a/libgo/go/crypto/rc4/rc4.go +++ b/libgo/go/crypto/rc4/rc4.go @@ -50,3 +50,20 @@ func (c *Cipher) Reset() { } c.i, c.j = 0, 0 } + +// xorKeyStreamGeneric sets dst to the result of XORing src with the +// key stream. Dst and src may be the same slice but otherwise should +// not overlap. +// +// This is the pure Go version. rc4_{amd64,386,arm}* contain assembly +// implementations. This is here for tests and to prevent bitrot. +func (c *Cipher) xorKeyStreamGeneric(dst, src []byte) { + i, j := c.i, c.j + for k, v := range src { + i += 1 + j += uint8(c.s[i]) + c.s[i], c.s[j] = c.s[j], c.s[i] + dst[k] = v ^ uint8(c.s[uint8(c.s[i]+c.s[j])]) + } + c.i, c.j = i, j +} diff --git a/libgo/go/crypto/rc4/rc4_asm.go b/libgo/go/crypto/rc4/rc4_asm.go index c582a4488b..02e5b67d55 100644 --- a/libgo/go/crypto/rc4/rc4_asm.go +++ b/libgo/go/crypto/rc4/rc4_asm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64 arm 386 +// +build amd64 amd64p32 arm,!nacl 386 package rc4 diff --git a/libgo/go/crypto/rc4/rc4_ref.go b/libgo/go/crypto/rc4/rc4_ref.go index 13d52b95dd..e34bd34cf1 100644 --- a/libgo/go/crypto/rc4/rc4_ref.go +++ b/libgo/go/crypto/rc4/rc4_ref.go @@ -2,19 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64,!arm,!386 +// +build !amd64,!amd64p32,!arm,!386 arm,nacl package rc4 // XORKeyStream sets dst to the result of XORing src with the key stream. // Dst and src may be the same slice but otherwise should not overlap. func (c *Cipher) XORKeyStream(dst, src []byte) { - i, j := c.i, c.j - for k, v := range src { - i += 1 - j += uint8(c.s[i]) - c.s[i], c.s[j] = c.s[j], c.s[i] - dst[k] = v ^ byte(c.s[byte(c.s[i]+c.s[j])]) - } - c.i, c.j = i, j + c.xorKeyStreamGeneric(dst, src) } diff --git a/libgo/go/crypto/rc4/rc4_test.go b/libgo/go/crypto/rc4/rc4_test.go index 7b4df6791d..af79882463 100644 --- a/libgo/go/crypto/rc4/rc4_test.go +++ b/libgo/go/crypto/rc4/rc4_test.go @@ -117,19 +117,30 @@ func TestGolden(t *testing.T) { } func TestBlock(t *testing.T) { + testBlock(t, (*Cipher).XORKeyStream) +} + +// Test the pure Go version. +// Because we have assembly for amd64, 386, and arm, this prevents +// bitrot of the reference implementations. +func TestBlockGeneric(t *testing.T) { + testBlock(t, (*Cipher).xorKeyStreamGeneric) +} + +func testBlock(t *testing.T, xor func(c *Cipher, dst, src []byte)) { c1a, _ := NewCipher(golden[0].key) c1b, _ := NewCipher(golden[1].key) data1 := make([]byte, 1<<20) for i := range data1 { - c1a.XORKeyStream(data1[i:i+1], data1[i:i+1]) - c1b.XORKeyStream(data1[i:i+1], data1[i:i+1]) + xor(c1a, data1[i:i+1], data1[i:i+1]) + xor(c1b, data1[i:i+1], data1[i:i+1]) } c2a, _ := NewCipher(golden[0].key) c2b, _ := NewCipher(golden[1].key) data2 := make([]byte, 1<<20) - c2a.XORKeyStream(data2, data2) - c2b.XORKeyStream(data2, data2) + xor(c2a, data2, data2) + xor(c2b, data2, data2) if !bytes.Equal(data1, data2) { t.Fatalf("bad block") diff --git a/libgo/go/crypto/rsa/pkcs1v15.go b/libgo/go/crypto/rsa/pkcs1v15.go index 1a055a3d62..59e8bb5b7b 100644 --- a/libgo/go/crypto/rsa/pkcs1v15.go +++ b/libgo/go/crypto/rsa/pkcs1v15.go @@ -53,11 +53,14 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [ if err := checkPub(&priv.PublicKey); err != nil { return nil, err } - valid, out, err := decryptPKCS1v15(rand, priv, ciphertext) - if err == nil && valid == 0 { - err = ErrDecryption + valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext) + if err != nil { + return } - + if valid == 0 { + return nil, ErrDecryption + } + out = out[index:] return } @@ -80,21 +83,32 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by } k := (priv.N.BitLen() + 7) / 8 if k-(len(key)+3+8) < 0 { - err = ErrDecryption - return + return ErrDecryption } - valid, msg, err := decryptPKCS1v15(rand, priv, ciphertext) + valid, em, index, err := decryptPKCS1v15(rand, priv, ciphertext) if err != nil { return } - valid &= subtle.ConstantTimeEq(int32(len(msg)), int32(len(key))) - subtle.ConstantTimeCopy(valid, key, msg) + if len(em) != k { + // This should be impossible because decryptPKCS1v15 always + // returns the full slice. + return ErrDecryption + } + + valid &= subtle.ConstantTimeEq(int32(len(em)-index), int32(len(key))) + subtle.ConstantTimeCopy(valid, key, em[len(em)-len(key):]) return } -func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, msg []byte, err error) { +// decryptPKCS1v15 decrypts ciphertext using priv and blinds the operation if +// rand is not nil. It returns one or zero in valid that indicates whether the +// plaintext was correctly structured. In either case, the plaintext is +// returned in em so that it may be read independently of whether it was valid +// in order to maintain constant memory access patterns. If the plaintext was +// valid then index contains the index of the original message in em. +func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) { k := (priv.N.BitLen() + 7) / 8 if k < 11 { err = ErrDecryption @@ -107,7 +121,7 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid return } - em := leftPad(m.Bytes(), k) + em = leftPad(m.Bytes(), k) firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0) secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2) @@ -115,8 +129,7 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid // octets, followed by a 0, followed by the message. // lookingForIndex: 1 iff we are still looking for the zero. // index: the offset of the first zero byte. - var lookingForIndex, index int - lookingForIndex = 1 + lookingForIndex := 1 for i := 2; i < len(em); i++ { equals0 := subtle.ConstantTimeByteEq(em[i], 0) @@ -129,8 +142,8 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid validPS := subtle.ConstantTimeLessOrEq(2+8, index) valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS - msg = em[index+1:] - return + index = subtle.ConstantTimeSelect(valid, index+1, 0) + return valid, em, index, nil } // nonZeroRandomBytes fills the given slice with non-zero random octets. @@ -176,7 +189,8 @@ var hashPrefixes = map[crypto.Hash][]byte{ // SignPKCS1v15 calculates the signature of hashed using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5. // Note that hashed must be the result of hashing the input message using the -// given hash function. +// given hash function. If hash is zero, hashed is signed directly. This isn't +// advisable except for interoperability. func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error) { hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed)) if err != nil { @@ -212,7 +226,8 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b // VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature. // hashed is the result of hashing the input message using the given hash // function and sig is the signature. A valid signature is indicated by -// returning a nil error. +// returning a nil error. If hash is zero then hashed is used directly. This +// isn't advisable except for interoperability. func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (err error) { hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed)) if err != nil { @@ -249,6 +264,12 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) } func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) { + // Special case: crypto.Hash(0) is used to indicate that the data is + // signed directly. + if hash == 0 { + return inLen, nil, nil + } + hashLen = hash.Size() if inLen != hashLen { return 0, nil, errors.New("crypto/rsa: input must be hashed message") diff --git a/libgo/go/crypto/rsa/pkcs1v15_test.go b/libgo/go/crypto/rsa/pkcs1v15_test.go index 70bb228899..2dc5dbc2c8 100644 --- a/libgo/go/crypto/rsa/pkcs1v15_test.go +++ b/libgo/go/crypto/rsa/pkcs1v15_test.go @@ -205,6 +205,48 @@ func TestOverlongMessagePKCS1v15(t *testing.T) { } } +func TestUnpaddedSignature(t *testing.T) { + msg := []byte("Thu Dec 19 18:06:16 EST 2013\n") + // This base64 value was generated with: + // % echo Thu Dec 19 18:06:16 EST 2013 > /tmp/msg + // % openssl rsautl -sign -inkey key -out /tmp/sig -in /tmp/msg + // + // Where "key" contains the RSA private key given at the bottom of this + // file. + expectedSig := decodeBase64("pX4DR8azytjdQ1rtUiC040FjkepuQut5q2ZFX1pTjBrOVKNjgsCDyiJDGZTCNoh9qpXYbhl7iEym30BWWwuiZg==") + + sig, err := SignPKCS1v15(nil, rsaPrivateKey, crypto.Hash(0), msg) + if err != nil { + t.Fatalf("SignPKCS1v15 failed: %s", err) + } + if !bytes.Equal(sig, expectedSig) { + t.Fatalf("signature is not expected value: got %x, want %x", sig, expectedSig) + } + if err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.Hash(0), msg, sig); err != nil { + t.Fatalf("signature failed to verify: %s", err) + } +} + +func TestShortSessionKey(t *testing.T) { + // This tests that attempting to decrypt a session key where the + // ciphertext is too small doesn't run outside the array bounds. + ciphertext, err := EncryptPKCS1v15(rand.Reader, &rsaPrivateKey.PublicKey, []byte{1}) + if err != nil { + t.Fatalf("Failed to encrypt short message: %s", err) + } + + var key [32]byte + if err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, ciphertext, key[:]); err != nil { + t.Fatalf("Failed to decrypt short message: %s", err) + } + + for _, v := range key { + if v != 0 { + t.Fatal("key was modified when ciphertext was invalid") + } + } +} + // In order to generate new test vectors you'll need the PEM form of this key: // -----BEGIN RSA PRIVATE KEY----- // MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 diff --git a/libgo/go/crypto/rsa/pss.go b/libgo/go/crypto/rsa/pss.go index f9abec3949..e9f2908250 100644 --- a/libgo/go/crypto/rsa/pss.go +++ b/libgo/go/crypto/rsa/pss.go @@ -4,7 +4,7 @@ package rsa -// This file implementes the PSS signature scheme [1]. +// This file implements the PSS signature scheme [1]. // // [1] http://www.rsa.com/rsalabs/pkcs/files/h11300-wp-pkcs-1v2-2-rsa-cryptography-standard.pdf @@ -189,7 +189,7 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error { // signPSSWithSalt calculates the signature of hashed using PSS [1] with specified salt. // Note that hashed must be the result of hashing the input message using the -// given hash funcion. salt is a random sequence of bytes whose length will be +// given hash function. salt is a random sequence of bytes whose length will be // later used to verify the signature. func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) { nBits := priv.N.BitLen() @@ -222,6 +222,17 @@ type PSSOptions struct { // signature. It can either be a number of bytes, or one of the special // PSSSaltLength constants. SaltLength int + + // Hash, if not zero, overrides the hash function passed to SignPSS. + // This is the only way to specify the hash function when using the + // crypto.Signer interface. + Hash crypto.Hash +} + +// HashFunc returns pssOpts.Hash so that PSSOptions implements +// crypto.SignerOpts. +func (pssOpts *PSSOptions) HashFunc() crypto.Hash { + return pssOpts.Hash } func (opts *PSSOptions) saltLength() int { @@ -233,7 +244,7 @@ func (opts *PSSOptions) saltLength() int { // SignPSS calculates the signature of hashed using RSASSA-PSS [1]. // Note that hashed must be the result of hashing the input message using the -// given hash funcion. The opts argument may be nil, in which case sensible +// given hash function. The opts argument may be nil, in which case sensible // defaults are used. func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) (s []byte, err error) { saltLength := opts.saltLength() @@ -244,6 +255,10 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, saltLength = hash.Size() } + if opts.Hash != 0 { + hash = opts.Hash + } + salt := make([]byte, saltLength) if _, err = io.ReadFull(rand, salt); err != nil { return diff --git a/libgo/go/crypto/rsa/rsa.go b/libgo/go/crypto/rsa/rsa.go index c7353ea311..2702311281 100644 --- a/libgo/go/crypto/rsa/rsa.go +++ b/libgo/go/crypto/rsa/rsa.go @@ -6,6 +6,7 @@ package rsa import ( + "crypto" "crypto/rand" "crypto/subtle" "errors" @@ -58,9 +59,27 @@ type PrivateKey struct { Precomputed PrecomputedValues } +// Public returns the public key corresponding to priv. +func (priv *PrivateKey) Public() crypto.PublicKey { + return &priv.PublicKey +} + +// Sign signs msg with priv, reading randomness from rand. If opts is a +// *PSSOptions then the PSS algorithm will be used, otherwise PKCS#1 v1.5 will +// be used. This method is intended to support keys where the private part is +// kept in, for example, a hardware module. Common uses should use the Sign* +// functions in this package. +func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) { + if pssOpts, ok := opts.(*PSSOptions); ok { + return SignPSS(rand, priv, pssOpts.Hash, msg, pssOpts) + } + + return SignPKCS1v15(rand, priv, opts.HashFunc(), msg) +} + type PrecomputedValues struct { Dp, Dq *big.Int // D mod (P-1) (or mod Q-1) - Qinv *big.Int // Q^-1 mod Q + Qinv *big.Int // Q^-1 mod P // CRTValues is used for the 3rd and subsequent primes. Due to a // historical accident, the CRT for the first two primes is handled @@ -120,16 +139,18 @@ func (priv *PrivateKey) Validate() error { return nil } -// GenerateKey generates an RSA keypair of the given bit size. +// GenerateKey generates an RSA keypair of the given bit size using the +// random source random (for example, crypto/rand.Reader). func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err error) { return GenerateMultiPrimeKey(random, 2, bits) } // GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit -// size, as suggested in [1]. Although the public keys are compatible -// (actually, indistinguishable) from the 2-prime case, the private keys are -// not. Thus it may not be possible to export multi-prime private keys in -// certain formats or to subsequently import them into other code. +// size and the given random source, as suggested in [1]. Although the public +// keys are compatible (actually, indistinguishable) from the 2-prime case, +// the private keys are not. Thus it may not be possible to export multi-prime +// private keys in certain formats or to subsequently import them into other +// code. // // Table 1 in [2] suggests maximum numbers of primes for a given size. // diff --git a/libgo/go/crypto/rsa/rsa_test.go b/libgo/go/crypto/rsa/rsa_test.go index cf193c669f..4ee1c3a8b2 100644 --- a/libgo/go/crypto/rsa/rsa_test.go +++ b/libgo/go/crypto/rsa/rsa_test.go @@ -197,7 +197,7 @@ func TestEncryptOAEP(t *testing.T) { public := PublicKey{n, test.e} for j, message := range test.msgs { - randomSource := bytes.NewBuffer(message.seed) + randomSource := bytes.NewReader(message.seed) out, err := EncryptOAEP(sha1, randomSource, &public, message.in, nil) if err != nil { t.Errorf("#%d,%d error: %s", i, j, err) diff --git a/libgo/go/crypto/sha1/sha1.go b/libgo/go/crypto/sha1/sha1.go index 8eb3f7a798..9f1a96e364 100644 --- a/libgo/go/crypto/sha1/sha1.go +++ b/libgo/go/crypto/sha1/sha1.go @@ -62,16 +62,10 @@ func (d *digest) Write(p []byte) (nn int, err error) { nn = len(p) d.len += uint64(nn) if d.nx > 0 { - n := len(p) - if n > chunk-d.nx { - n = chunk - d.nx - } - for i := 0; i < n; i++ { - d.x[d.nx+i] = p[i] - } + n := copy(d.x[d.nx:], p) d.nx += n if d.nx == chunk { - block(d, d.x[0:]) + block(d, d.x[:]) d.nx = 0 } p = p[n:] diff --git a/libgo/go/crypto/sha1/sha1_test.go b/libgo/go/crypto/sha1/sha1_test.go index c3868d702a..4a629518b7 100644 --- a/libgo/go/crypto/sha1/sha1_test.go +++ b/libgo/go/crypto/sha1/sha1_test.go @@ -7,6 +7,7 @@ package sha1 import ( + "crypto/rand" "fmt" "io" "testing" @@ -76,6 +77,32 @@ func TestGolden(t *testing.T) { } } +func TestSize(t *testing.T) { + c := New() + if got := c.Size(); got != Size { + t.Errorf("Size = %d; want %d", got, Size) + } +} + +func TestBlockSize(t *testing.T) { + c := New() + if got := c.BlockSize(); got != BlockSize { + t.Errorf("BlockSize = %d; want %d", got, BlockSize) + } +} + +// Tests that blockGeneric (pure Go) and block (in assembly for amd64, 386, arm) match. +func TestBlockGeneric(t *testing.T) { + gen, asm := New().(*digest), New().(*digest) + buf := make([]byte, BlockSize*20) // arbitrary factor + rand.Read(buf) + blockGeneric(gen, buf) + block(asm, buf) + if *gen != *asm { + t.Error("block and blockGeneric resulted in different states") + } +} + var bench = New() var buf = make([]byte, 8192) diff --git a/libgo/go/crypto/sha1/sha1block.go b/libgo/go/crypto/sha1/sha1block.go index 92224fc0ef..fde3c981c0 100644 --- a/libgo/go/crypto/sha1/sha1block.go +++ b/libgo/go/crypto/sha1/sha1block.go @@ -2,12 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64,!386 - -// SHA1 block step. -// In its own file so that a faster assembly or C version -// can be substituted easily. - package sha1 const ( @@ -17,7 +11,9 @@ const ( _K3 = 0xCA62C1D6 ) -func block(dig *digest, p []byte) { +// blockGeneric is a portable, pure Go version of the SHA1 block step. +// It's used by sha1block_generic.go and tests. +func blockGeneric(dig *digest, p []byte) { var w [16]uint32 h0, h1, h2, h3, h4 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4] diff --git a/libgo/go/crypto/sha1/sha1block_decl.go b/libgo/go/crypto/sha1/sha1block_decl.go index 4cb157fff6..24e521af1f 100644 --- a/libgo/go/crypto/sha1/sha1block_decl.go +++ b/libgo/go/crypto/sha1/sha1block_decl.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build amd64 386 +// +build amd64 amd64p32 arm 386 package sha1 diff --git a/libgo/go/crypto/sha1/sha1block_generic.go b/libgo/go/crypto/sha1/sha1block_generic.go new file mode 100644 index 0000000000..696e26b625 --- /dev/null +++ b/libgo/go/crypto/sha1/sha1block_generic.go @@ -0,0 +1,9 @@ +// 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. + +// +build !amd64,!amd64p32,!386,!arm + +package sha1 + +var block = blockGeneric diff --git a/libgo/go/crypto/sha256/sha256.go b/libgo/go/crypto/sha256/sha256.go index d69ed24a3b..d84cebf2ff 100644 --- a/libgo/go/crypto/sha256/sha256.go +++ b/libgo/go/crypto/sha256/sha256.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // Package sha256 implements the SHA224 and SHA256 hash algorithms as defined -// in FIPS 180-2. +// in FIPS 180-4. package sha256 import ( @@ -106,16 +106,10 @@ func (d *digest) Write(p []byte) (nn int, err error) { nn = len(p) d.len += uint64(nn) if d.nx > 0 { - n := len(p) - if n > chunk-d.nx { - n = chunk - d.nx - } - for i := 0; i < n; i++ { - d.x[d.nx+i] = p[i] - } + n := copy(d.x[d.nx:], p) d.nx += n if d.nx == chunk { - block(d, d.x[0:]) + block(d, d.x[:]) d.nx = 0 } p = p[n:] diff --git a/libgo/go/crypto/sha256/sha256_test.go b/libgo/go/crypto/sha256/sha256_test.go index bb1ec3b162..1d883d3905 100644 --- a/libgo/go/crypto/sha256/sha256_test.go +++ b/libgo/go/crypto/sha256/sha256_test.go @@ -132,6 +132,24 @@ func TestGolden(t *testing.T) { } } +func TestSize(t *testing.T) { + c := New() + if got := c.Size(); got != Size { + t.Errorf("Size = %d; want %d", got, Size) + } + c = New224() + if got := c.Size(); got != Size224 { + t.Errorf("New224.Size = %d; want %d", got, Size224) + } +} + +func TestBlockSize(t *testing.T) { + c := New() + if got := c.BlockSize(); got != BlockSize { + t.Errorf("BlockSize = %d want %d", got, BlockSize) + } +} + var bench = New() var buf = make([]byte, 8192) diff --git a/libgo/go/crypto/sha256/sha256block.go b/libgo/go/crypto/sha256/sha256block.go index 2ac49100ac..ca5efd156a 100644 --- a/libgo/go/crypto/sha256/sha256block.go +++ b/libgo/go/crypto/sha256/sha256block.go @@ -2,6 +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 + // SHA256 block step. // In its own file so that a faster assembly or C version // can be substituted easily. diff --git a/libgo/go/crypto/sha256/sha256block_decl.go b/libgo/go/crypto/sha256/sha256block_decl.go new file mode 100644 index 0000000000..a50c978710 --- /dev/null +++ b/libgo/go/crypto/sha256/sha256block_decl.go @@ -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. + +// +build 386 amd64 + +package sha256 + +//go:noescape + +func block(dig *digest, p []byte) diff --git a/libgo/go/crypto/sha512/sha512.go b/libgo/go/crypto/sha512/sha512.go index d2ada51373..bca7a91e22 100644 --- a/libgo/go/crypto/sha512/sha512.go +++ b/libgo/go/crypto/sha512/sha512.go @@ -106,16 +106,10 @@ func (d *digest) Write(p []byte) (nn int, err error) { nn = len(p) d.len += uint64(nn) if d.nx > 0 { - n := len(p) - if n > chunk-d.nx { - n = chunk - d.nx - } - for i := 0; i < n; i++ { - d.x[d.nx+i] = p[i] - } + n := copy(d.x[d.nx:], p) d.nx += n if d.nx == chunk { - block(d, d.x[0:]) + block(d, d.x[:]) d.nx = 0 } p = p[n:] diff --git a/libgo/go/crypto/sha512/sha512_test.go b/libgo/go/crypto/sha512/sha512_test.go index 167c20ad07..541860f701 100644 --- a/libgo/go/crypto/sha512/sha512_test.go +++ b/libgo/go/crypto/sha512/sha512_test.go @@ -132,6 +132,24 @@ func TestGolden(t *testing.T) { } } +func TestSize(t *testing.T) { + c := New() + if got := c.Size(); got != Size { + t.Errorf("Size = %d; want %d", got, Size) + } + c = New384() + if got := c.Size(); got != Size384 { + t.Errorf("New384.Size = %d; want %d", got, Size384) + } +} + +func TestBlockSize(t *testing.T) { + c := New() + if got := c.BlockSize(); got != BlockSize { + t.Errorf("BlockSize = %d; want %d", got, BlockSize) + } +} + var bench = New() var buf = make([]byte, 8192) diff --git a/libgo/go/crypto/sha512/sha512block.go b/libgo/go/crypto/sha512/sha512block.go index 3577b4f3df..648ae8f7e1 100644 --- a/libgo/go/crypto/sha512/sha512block.go +++ b/libgo/go/crypto/sha512/sha512block.go @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build !amd64 + // SHA512 block step. // In its own file so that a faster assembly or C version // can be substituted easily. diff --git a/libgo/go/crypto/sha512/sha512block_decl.go b/libgo/go/crypto/sha512/sha512block_decl.go new file mode 100644 index 0000000000..bef99de2e4 --- /dev/null +++ b/libgo/go/crypto/sha512/sha512block_decl.go @@ -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. + +// +build amd64 + +package sha512 + +//go:noescape + +func block(dig *digest, p []byte) diff --git a/libgo/go/crypto/subtle/constant_time.go b/libgo/go/crypto/subtle/constant_time.go index dfb658465e..6f80e7c58d 100644 --- a/libgo/go/crypto/subtle/constant_time.go +++ b/libgo/go/crypto/subtle/constant_time.go @@ -6,10 +6,14 @@ // code but require careful thought to use correctly. package subtle -// ConstantTimeCompare returns 1 iff the two equal length slices, x +// ConstantTimeCompare returns 1 iff the two slices, x // and y, have equal contents. The time taken is a function of the length of // the slices and is independent of the contents. func ConstantTimeCompare(x, y []byte) int { + if len(x) != len(y) { + return 0 + } + var v byte for i := 0; i < len(x); i++ { @@ -45,15 +49,19 @@ func ConstantTimeEq(x, y int32) int { return int(z & 1) } -// ConstantTimeCopy copies the contents of y into x iff v == 1. If v == 0, x is left unchanged. -// Its behavior is undefined if v takes any other value. +// ConstantTimeCopy copies the contents of y into x (a slice of equal length) +// if v == 1. If v == 0, x is left unchanged. Its behavior is undefined if v +// takes any other value. func ConstantTimeCopy(v int, x, y []byte) { + if len(x) != len(y) { + panic("subtle: slices have different lengths") + } + xmask := byte(v - 1) ymask := byte(^(v - 1)) for i := 0; i < len(x); i++ { x[i] = x[i]&xmask | y[i]&ymask } - return } // ConstantTimeLessOrEq returns 1 if x <= y and 0 otherwise. diff --git a/libgo/go/crypto/subtle/constant_time_test.go b/libgo/go/crypto/subtle/constant_time_test.go index d8e321ec04..619a454441 100644 --- a/libgo/go/crypto/subtle/constant_time_test.go +++ b/libgo/go/crypto/subtle/constant_time_test.go @@ -18,6 +18,8 @@ var testConstantTimeCompareData = []TestConstantTimeCompareStruct{ {[]byte{}, []byte{}, 1}, {[]byte{0x11}, []byte{0x11}, 1}, {[]byte{0x12}, []byte{0x11}, 0}, + {[]byte{0x11}, []byte{0x11, 0x12}, 0}, + {[]byte{0x11, 0x12}, []byte{0x11}, 0}, } func TestConstantTimeCompare(t *testing.T) { diff --git a/libgo/go/crypto/tls/alert.go b/libgo/go/crypto/tls/alert.go index 0856311e4c..3de4834d3f 100644 --- a/libgo/go/crypto/tls/alert.go +++ b/libgo/go/crypto/tls/alert.go @@ -35,6 +35,7 @@ const ( alertProtocolVersion alert = 70 alertInsufficientSecurity alert = 71 alertInternalError alert = 80 + alertInappropriateFallback alert = 86 alertUserCanceled alert = 90 alertNoRenegotiation alert = 100 ) @@ -60,6 +61,7 @@ var alertText = map[alert]string{ alertProtocolVersion: "protocol version not supported", alertInsufficientSecurity: "insufficient security level", alertInternalError: "internal error", + alertInappropriateFallback: "inappropriate fallback", alertUserCanceled: "user canceled", alertNoRenegotiation: "no renegotiation", } diff --git a/libgo/go/crypto/tls/cipher_suites.go b/libgo/go/crypto/tls/cipher_suites.go index 39a51459d2..226e06d68d 100644 --- a/libgo/go/crypto/tls/cipher_suites.go +++ b/libgo/go/crypto/tls/cipher_suites.go @@ -267,4 +267,9 @@ const ( TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b + + // TLS_FALLBACK_SCSV isn't a standard cipher suite but an indicator + // that the client is doing version fallback. See + // https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00. + TLS_FALLBACK_SCSV uint16 = 0x5600 ) diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go index b7229d29f8..776b70c93c 100644 --- a/libgo/go/crypto/tls/common.go +++ b/libgo/go/crypto/tls/common.go @@ -5,9 +5,11 @@ package tls import ( + "container/list" "crypto" "crypto/rand" "crypto/x509" + "fmt" "io" "math/big" "strings" @@ -64,27 +66,36 @@ const ( ) // TLS extension numbers -var ( +const ( extensionServerName uint16 = 0 extensionStatusRequest uint16 = 5 extensionSupportedCurves uint16 = 10 extensionSupportedPoints uint16 = 11 extensionSignatureAlgorithms uint16 = 13 + extensionALPN uint16 = 16 extensionSessionTicket uint16 = 35 extensionNextProtoNeg uint16 = 13172 // not IANA assigned + extensionRenegotiationInfo uint16 = 0xff01 ) -// TLS Elliptic Curves +// TLS signaling cipher suite values +const ( + scsvRenegotiation uint16 = 0x00ff +) + +// CurveID is the type of a TLS identifier for an elliptic curve. See // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 -var ( - curveP256 uint16 = 23 - curveP384 uint16 = 24 - curveP521 uint16 = 25 +type CurveID uint16 + +const ( + CurveP256 CurveID = 23 + CurveP384 CurveID = 24 + CurveP521 CurveID = 25 ) // TLS Elliptic Curve Point Formats // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9 -var ( +const ( pointFormatUncompressed uint8 = 0 ) @@ -145,6 +156,7 @@ var supportedClientCertSignatureAlgorithms = []signatureAndHash{ // ConnectionState records basic TLS details about the connection. type ConnectionState struct { + Version uint16 // TLS version used by the connection (e.g. VersionTLS12) HandshakeComplete bool // TLS handshake is complete DidResume bool // connection resumes a previous TLS connection CipherSuite uint16 // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...) @@ -153,6 +165,14 @@ type ConnectionState struct { ServerName string // server name requested by client, if any (server side only) PeerCertificates []*x509.Certificate // certificate chain presented by remote peer VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates + + // TLSUnique contains the "tls-unique" channel binding value (see RFC + // 5929, section 3). For resumed sessions this value will be nil + // because resumption does not include enough context (see + // https://secure-resumption.com/#channelbindings). This will change in + // future versions of Go once the TLS master-secret fix has been + // standardized and implemented. + TLSUnique []byte } // ClientAuthType declares the policy the server will follow for @@ -167,12 +187,64 @@ const ( RequireAndVerifyClientCert ) -// A Config structure is used to configure a TLS client or server. After one -// has been passed to a TLS function it must not be modified. +// ClientSessionState contains the state needed by clients to resume TLS +// sessions. +type ClientSessionState struct { + sessionTicket []uint8 // Encrypted ticket used for session resumption with server + vers uint16 // SSL/TLS version negotiated for the session + cipherSuite uint16 // Ciphersuite negotiated for the session + masterSecret []byte // MasterSecret generated by client on a full handshake + serverCertificates []*x509.Certificate // Certificate chain presented by the server +} + +// ClientSessionCache is a cache of ClientSessionState objects that can be used +// by a client to resume a TLS session with a given server. ClientSessionCache +// implementations should expect to be called concurrently from different +// goroutines. +type ClientSessionCache interface { + // Get searches for a ClientSessionState associated with the given key. + // On return, ok is true if one was found. + Get(sessionKey string) (session *ClientSessionState, ok bool) + + // Put adds the ClientSessionState to the cache with the given key. + Put(sessionKey string, cs *ClientSessionState) +} + +// ClientHelloInfo contains information from a ClientHello message in order to +// guide certificate selection in the GetCertificate callback. +type ClientHelloInfo struct { + // CipherSuites lists the CipherSuites supported by the client (e.g. + // TLS_RSA_WITH_RC4_128_SHA). + CipherSuites []uint16 + + // ServerName indicates the name of the server requested by the client + // in order to support virtual hosting. ServerName is only set if the + // client is using SNI (see + // http://tools.ietf.org/html/rfc4366#section-3.1). + ServerName string + + // SupportedCurves lists the elliptic curves supported by the client. + // SupportedCurves is set only if the Supported Elliptic Curves + // Extension is being used (see + // http://tools.ietf.org/html/rfc4492#section-5.1.1). + SupportedCurves []CurveID + + // SupportedPoints lists the point formats supported by the client. + // SupportedPoints is set only if the Supported Point Formats Extension + // is being used (see + // http://tools.ietf.org/html/rfc4492#section-5.1.2). + SupportedPoints []uint8 +} + +// A Config structure is used to configure a TLS client or server. +// After one has been passed to a TLS function it must not be +// modified. A Config may be reused; the tls package will also not +// modify it. type Config struct { // Rand provides the source of entropy for nonces and RSA blinding. // If Rand is nil, TLS uses the cryptographic random reader in package // crypto/rand. + // The Reader must be safe for use by multiple goroutines. Rand io.Reader // Time returns the current time as the number of seconds since the epoch. @@ -192,6 +264,13 @@ type Config struct { // for all connections. NameToCertificate map[string]*Certificate + // GetCertificate returns a Certificate based on the given + // ClientHelloInfo. If GetCertificate is nil or returns nil, then the + // certificate is retrieved from NameToCertificate. If + // NameToCertificate is nil, the first element of Certificates will be + // used. + GetCertificate func(clientHello *ClientHelloInfo) (*Certificate, error) + // RootCAs defines the set of root certificate authorities // that clients use when verifying server certificates. // If RootCAs is nil, TLS uses the host's root CA set. @@ -200,8 +279,9 @@ type Config struct { // NextProtos is a list of supported, application level protocols. NextProtos []string - // ServerName is included in the client's handshake to support virtual - // hosting. + // ServerName is used to verify the hostname on the returned + // certificates unless InsecureSkipVerify is given. It is also included + // in the client's handshake to support virtual hosting. ServerName string // ClientAuth determines the server's policy for @@ -245,6 +325,10 @@ type Config struct { // connections using that key are compromised. SessionTicketKey [32]byte + // SessionCache is a cache of ClientSessionState entries for TLS session + // resumption. + ClientSessionCache ClientSessionCache + // MinVersion contains the minimum SSL/TLS version that is acceptable. // If zero, then SSLv3 is taken as the minimum. MinVersion uint16 @@ -254,6 +338,11 @@ type Config struct { // which is currently TLS 1.2. MaxVersion uint16 + // CurvePreferences contains the elliptic curves that will be used in + // an ECDHE handshake, in preference order. If empty, the default will + // be used. + CurvePreferences []CurveID + serverInitOnce sync.Once // guards calling (*Config).serverInit } @@ -312,6 +401,15 @@ func (c *Config) maxVersion() uint16 { return c.MaxVersion } +var defaultCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521} + +func (c *Config) curvePreferences() []CurveID { + if c == nil || len(c.CurvePreferences) == 0 { + return defaultCurvePreferences + } + return c.CurvePreferences +} + // mutualVersion returns the protocol version to use given the advertised // version of the peer. func (c *Config) mutualVersion(vers uint16) (uint16, bool) { @@ -327,22 +425,28 @@ func (c *Config) mutualVersion(vers uint16) (uint16, bool) { return vers, true } -// getCertificateForName returns the best certificate for the given name, -// defaulting to the first element of c.Certificates if there are no good -// options. -func (c *Config) getCertificateForName(name string) *Certificate { +// getCertificate returns the best certificate for the given ClientHelloInfo, +// defaulting to the first element of c.Certificates. +func (c *Config) getCertificate(clientHello *ClientHelloInfo) (*Certificate, error) { + if c.GetCertificate != nil { + cert, err := c.GetCertificate(clientHello) + if cert != nil || err != nil { + return cert, err + } + } + if len(c.Certificates) == 1 || c.NameToCertificate == nil { // There's only one choice, so no point doing any work. - return &c.Certificates[0] + return &c.Certificates[0], nil } - name = strings.ToLower(name) + name := strings.ToLower(clientHello.ServerName) for len(name) > 0 && name[len(name)-1] == '.' { name = name[:len(name)-1] } if cert, ok := c.NameToCertificate[name]; ok { - return cert + return cert, nil } // try replacing labels in the name with wildcards until we get a @@ -352,12 +456,12 @@ func (c *Config) getCertificateForName(name string) *Certificate { labels[i] = "*" candidate := strings.Join(labels, ".") if cert, ok := c.NameToCertificate[candidate]; ok { - return cert + return cert, nil } } // If nothing matches, return the first certificate. - return &c.Certificates[0] + return &c.Certificates[0], nil } // BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate @@ -383,7 +487,12 @@ func (c *Config) BuildNameToCertificate() { // A Certificate is a chain of one or more certificates, leaf first. type Certificate struct { Certificate [][]byte - PrivateKey crypto.PrivateKey // supported types: *rsa.PrivateKey, *ecdsa.PrivateKey + // PrivateKey contains the private key corresponding to the public key + // in Leaf. For a server, this must be a *rsa.PrivateKey or + // *ecdsa.PrivateKey. For a client doing client authentication, this + // can be any type that implements crypto.Signer (which includes RSA + // and ECDSA private keys). + PrivateKey crypto.PrivateKey // OCSPStaple contains an optional OCSP response which will be served // to clients that request it. OCSPStaple []byte @@ -406,6 +515,77 @@ type handshakeMessage interface { unmarshal([]byte) bool } +// lruSessionCache is a ClientSessionCache implementation that uses an LRU +// caching strategy. +type lruSessionCache struct { + sync.Mutex + + m map[string]*list.Element + q *list.List + capacity int +} + +type lruSessionCacheEntry struct { + sessionKey string + state *ClientSessionState +} + +// NewLRUClientSessionCache returns a ClientSessionCache with the given +// capacity that uses an LRU strategy. If capacity is < 1, a default capacity +// is used instead. +func NewLRUClientSessionCache(capacity int) ClientSessionCache { + const defaultSessionCacheCapacity = 64 + + if capacity < 1 { + capacity = defaultSessionCacheCapacity + } + return &lruSessionCache{ + m: make(map[string]*list.Element), + q: list.New(), + capacity: capacity, + } +} + +// Put adds the provided (sessionKey, cs) pair to the cache. +func (c *lruSessionCache) Put(sessionKey string, cs *ClientSessionState) { + c.Lock() + defer c.Unlock() + + if elem, ok := c.m[sessionKey]; ok { + entry := elem.Value.(*lruSessionCacheEntry) + entry.state = cs + c.q.MoveToFront(elem) + return + } + + if c.q.Len() < c.capacity { + entry := &lruSessionCacheEntry{sessionKey, cs} + c.m[sessionKey] = c.q.PushFront(entry) + return + } + + elem := c.q.Back() + entry := elem.Value.(*lruSessionCacheEntry) + delete(c.m, entry.sessionKey) + entry.sessionKey = sessionKey + entry.state = cs + c.q.MoveToFront(elem) + c.m[sessionKey] = elem +} + +// Get returns the ClientSessionState value associated with a given key. It +// returns (nil, false) if no value is found. +func (c *lruSessionCache) Get(sessionKey string) (*ClientSessionState, bool) { + c.Lock() + defer c.Unlock() + + if elem, ok := c.m[sessionKey]; ok { + c.q.MoveToFront(elem) + return elem.Value.(*lruSessionCacheEntry).state, true + } + return nil, false +} + // TODO(jsing): Make these available to both crypto/x509 and crypto/tls. type dsaSignature struct { R, S *big.Int @@ -435,3 +615,7 @@ func initDefaultCipherSuites() { varDefaultCipherSuites[i] = 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) +} diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go index 2e64b88a68..ba8e4c22b7 100644 --- a/libgo/go/crypto/tls/conn.go +++ b/libgo/go/crypto/tls/conn.go @@ -12,6 +12,7 @@ import ( "crypto/subtle" "crypto/x509" "errors" + "fmt" "io" "net" "sync" @@ -27,6 +28,7 @@ type Conn struct { // constant after handshake; protected by handshakeMutex handshakeMutex sync.Mutex // handshakeMutex < in.Mutex, out.Mutex, errMutex + handshakeErr error // error resulting from handshake vers uint16 // TLS version haveVers bool // version has been negotiated config *Config // configuration passed to constructor @@ -40,13 +42,13 @@ type Conn struct { verifiedChains [][]*x509.Certificate // serverName contains the server name indicated by the client, if any. serverName string + // firstFinished contains the first Finished hash sent during the + // handshake. This is the "tls-unique" channel binding value. + firstFinished [12]byte clientProtocol string clientProtocolFallback bool - // first permanent error - connErr - // input/output in, out halfConn // in.Mutex < out.Mutex rawInput *block // raw input, right off the wire @@ -56,27 +58,6 @@ type Conn struct { tmp [16]byte } -type connErr struct { - mu sync.Mutex - value error -} - -func (e *connErr) setError(err error) error { - e.mu.Lock() - defer e.mu.Unlock() - - if e.value == nil { - e.value = err - } - return err -} - -func (e *connErr) error() error { - e.mu.Lock() - defer e.mu.Unlock() - return e.value -} - // Access to net.Conn methods. // Cannot just embed net.Conn because that would // export the struct field too. @@ -104,7 +85,7 @@ func (c *Conn) SetReadDeadline(t time.Time) error { return c.conn.SetReadDeadline(t) } -// SetWriteDeadline sets the write deadline on the underlying conneciton. +// SetWriteDeadline sets the write deadline on the underlying connection. // A zero value for t means Write will not time out. // After a Write has timed out, the TLS state is corrupt and all future writes will return the same error. func (c *Conn) SetWriteDeadline(t time.Time) error { @@ -115,6 +96,8 @@ func (c *Conn) SetWriteDeadline(t time.Time) error { // connection, either sending or receiving. type halfConn struct { sync.Mutex + + err error // first permanent error version uint16 // protocol version cipher interface{} // cipher algorithm mac macFunction @@ -128,6 +111,18 @@ type halfConn struct { inDigestBuf, outDigestBuf []byte } +func (hc *halfConn) setErrorLocked(err error) error { + hc.err = err + return err +} + +func (hc *halfConn) error() error { + hc.Lock() + err := hc.err + hc.Unlock() + return err +} + // prepareCipherSpec sets the encryption and MAC states // that a subsequent changeCipherSpec will use. func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac macFunction) { @@ -459,6 +454,8 @@ func (b *block) readFromUntil(r io.Reader, n int) error { m, err := r.Read(b.data[len(b.data):cap(b.data)]) b.data = b.data[0 : len(b.data)+m] if len(b.data) >= n { + // TODO(bradfitz,agl): slightly suspicious + // that we're throwing away r.Read's err here. break } if err != nil { @@ -518,14 +515,17 @@ func (c *Conn) readRecord(want recordType) error { // else application data. (We don't support renegotiation.) switch want { default: - return c.sendAlert(alertInternalError) + c.sendAlert(alertInternalError) + return c.in.setErrorLocked(errors.New("tls: unknown record type requested")) case recordTypeHandshake, recordTypeChangeCipherSpec: if c.handshakeComplete { - return c.sendAlert(alertInternalError) + c.sendAlert(alertInternalError) + return c.in.setErrorLocked(errors.New("tls: handshake or ChangeCipherSpec requested after handshake complete")) } case recordTypeApplicationData: if !c.handshakeComplete { - return c.sendAlert(alertInternalError) + c.sendAlert(alertInternalError) + return c.in.setErrorLocked(errors.New("tls: application data record requested before handshake complete")) } } @@ -544,7 +544,7 @@ Again: // err = io.ErrUnexpectedEOF // } if e, ok := err.(net.Error); !ok || !e.Temporary() { - c.setError(err) + c.in.setErrorLocked(err) } return err } @@ -556,16 +556,18 @@ Again: // an SSLv2 client. if want == recordTypeHandshake && typ == 0x80 { c.sendAlert(alertProtocolVersion) - return errors.New("tls: unsupported SSLv2 handshake received") + return c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received")) } vers := uint16(b.data[1])<<8 | uint16(b.data[2]) n := int(b.data[3])<<8 | int(b.data[4]) if c.haveVers && vers != c.vers { - return c.sendAlert(alertProtocolVersion) + c.sendAlert(alertProtocolVersion) + return c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, c.vers)) } if n > maxCiphertext { - return c.sendAlert(alertRecordOverflow) + c.sendAlert(alertRecordOverflow) + return c.in.setErrorLocked(fmt.Errorf("tls: oversized record received with length %d", n)) } if !c.haveVers { // First message, be extra suspicious: @@ -577,7 +579,8 @@ Again: // well under a kilobyte. If the length is >= 12 kB, // it's probably not real. if (typ != recordTypeAlert && typ != want) || vers >= 0x1000 || n >= 0x3000 { - return c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertUnexpectedMessage) + return c.in.setErrorLocked(fmt.Errorf("tls: first record does not look like a TLS handshake")) } } if err := b.readFromUntil(c.conn, recordHeaderLen+n); err != nil { @@ -585,7 +588,7 @@ Again: err = io.ErrUnexpectedEOF } if e, ok := err.(net.Error); !ok || !e.Temporary() { - c.setError(err) + c.in.setErrorLocked(err) } return err } @@ -594,27 +597,27 @@ Again: b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n) ok, off, err := c.in.decrypt(b) if !ok { - return c.sendAlert(err) + c.in.setErrorLocked(c.sendAlert(err)) } b.off = off data := b.data[b.off:] if len(data) > maxPlaintext { - c.sendAlert(alertRecordOverflow) + err := c.sendAlert(alertRecordOverflow) c.in.freeBlock(b) - return c.error() + return c.in.setErrorLocked(err) } switch typ { default: - c.sendAlert(alertUnexpectedMessage) + c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) case recordTypeAlert: if len(data) != 2 { - c.sendAlert(alertUnexpectedMessage) + c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) break } if alert(data[1]) == alertCloseNotify { - c.setError(io.EOF) + c.in.setErrorLocked(io.EOF) break } switch data[0] { @@ -623,24 +626,24 @@ Again: c.in.freeBlock(b) goto Again case alertLevelError: - c.setError(&net.OpError{Op: "remote error", Err: alert(data[1])}) + c.in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert(data[1])}) default: - c.sendAlert(alertUnexpectedMessage) + c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) } case recordTypeChangeCipherSpec: if typ != want || len(data) != 1 || data[0] != 1 { - c.sendAlert(alertUnexpectedMessage) + c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) break } err := c.in.changeCipherSpec() if err != nil { - c.sendAlert(err.(alert)) + c.in.setErrorLocked(c.sendAlert(err.(alert))) } case recordTypeApplicationData: if typ != want { - c.sendAlert(alertUnexpectedMessage) + c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) break } c.input = b @@ -649,7 +652,7 @@ Again: case recordTypeHandshake: // TODO(rsc): Should at least pick off connection close. if typ != want { - return c.sendAlert(alertNoRenegotiation) + return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation)) } c.hand.Write(data) } @@ -657,7 +660,7 @@ Again: if b != nil { c.in.freeBlock(b) } - return c.error() + return c.in.err } // sendAlert sends a TLS alert message. @@ -673,7 +676,7 @@ func (c *Conn) sendAlertLocked(err alert) error { c.writeRecord(recordTypeAlert, c.tmp[0:2]) // closeNotify is a special case in that it isn't an error: if err != alertCloseNotify { - return c.setError(&net.OpError{Op: "local error", Err: err}) + return c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) } return nil } @@ -759,7 +762,7 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) { c.tmp[0] = alertLevelError c.tmp[1] = byte(err.(alert)) c.writeRecord(recordTypeAlert, c.tmp[0:2]) - return n, c.setError(&net.OpError{Op: "local error", Err: err}) + return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err}) } } return @@ -770,7 +773,7 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) { // c.in.Mutex < L; c.out.Mutex < L. func (c *Conn) readHandshake() (interface{}, error) { for c.hand.Len() < 4 { - if err := c.error(); err != nil { + if err := c.in.err; err != nil { return nil, err } if err := c.readRecord(recordTypeHandshake); err != nil { @@ -781,11 +784,10 @@ func (c *Conn) readHandshake() (interface{}, error) { data := c.hand.Bytes() n := int(data[1])<<16 | int(data[2])<<8 | int(data[3]) if n > maxHandshake { - c.sendAlert(alertInternalError) - return nil, c.error() + return nil, c.in.setErrorLocked(c.sendAlert(alertInternalError)) } for c.hand.Len() < 4+n { - if err := c.error(); err != nil { + if err := c.in.err; err != nil { return nil, err } if err := c.readRecord(recordTypeHandshake); err != nil { @@ -799,6 +801,8 @@ func (c *Conn) readHandshake() (interface{}, error) { m = new(clientHelloMsg) case typeServerHello: m = new(serverHelloMsg) + case typeNewSessionTicket: + m = new(newSessionTicketMsg) case typeCertificate: m = new(certificateMsg) case typeCertificateRequest: @@ -822,8 +826,7 @@ func (c *Conn) readHandshake() (interface{}, error) { case typeFinished: m = new(finishedMsg) default: - c.sendAlert(alertUnexpectedMessage) - return nil, alertUnexpectedMessage + return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) } // The handshake message unmarshallers @@ -832,25 +835,24 @@ func (c *Conn) readHandshake() (interface{}, error) { data = append([]byte(nil), data...) if !m.unmarshal(data) { - c.sendAlert(alertUnexpectedMessage) - return nil, alertUnexpectedMessage + return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage)) } return m, nil } // Write writes data to the connection. func (c *Conn) Write(b []byte) (int, error) { - if err := c.error(); err != nil { - return 0, err - } - if err := c.Handshake(); err != nil { - return 0, c.setError(err) + return 0, err } c.out.Lock() defer c.out.Unlock() + if err := c.out.err; err != nil { + return 0, err + } + if !c.handshakeComplete { return 0, alertInternalError } @@ -869,14 +871,14 @@ func (c *Conn) Write(b []byte) (int, error) { if _, ok := c.out.cipher.(cipher.BlockMode); ok { n, err := c.writeRecord(recordTypeApplicationData, b[:1]) if err != nil { - return n, c.setError(err) + return n, c.out.setErrorLocked(err) } m, b = 1, b[1:] } } n, err := c.writeRecord(recordTypeApplicationData, b) - return n + m, c.setError(err) + return n + m, c.out.setErrorLocked(err) } // Read can be made to time out and return a net.Error with Timeout() == true @@ -885,6 +887,11 @@ func (c *Conn) Read(b []byte) (n int, err error) { if err = c.Handshake(); err != nil { return } + if len(b) == 0 { + // Put this after Handshake, in case people were calling + // Read(nil) for the side effect of the Handshake. + return + } c.in.Lock() defer c.in.Unlock() @@ -893,13 +900,13 @@ func (c *Conn) Read(b []byte) (n int, err error) { // CBC IV. So this loop ignores a limited number of empty records. const maxConsecutiveEmptyRecords = 100 for emptyRecordCount := 0; emptyRecordCount <= maxConsecutiveEmptyRecords; emptyRecordCount++ { - for c.input == nil && c.error() == nil { + for c.input == nil && c.in.err == nil { if err := c.readRecord(recordTypeApplicationData); err != nil { // Soft error, like EAGAIN return 0, err } } - if err := c.error(); err != nil { + if err := c.in.err; err != nil { return 0, err } @@ -909,6 +916,25 @@ func (c *Conn) Read(b []byte) (n int, err error) { c.input = nil } + // If a close-notify alert is waiting, read it so that + // we can return (n, EOF) instead of (n, nil), to signal + // to the HTTP response reading goroutine that the + // connection is now closed. This eliminates a race + // where the HTTP response reading goroutine would + // otherwise not observe the EOF until its next read, + // by which time a client goroutine might have already + // tried to reuse the HTTP connection for a new + // request. + // See https://codereview.appspot.com/76400046 + // and http://golang.org/issue/3514 + if ri := c.rawInput; ri != nil && + n != 0 && err == nil && + c.input == nil && len(ri.data) > 0 && recordType(ri.data[0]) == recordTypeAlert { + if recErr := c.readRecord(recordTypeApplicationData); recErr != nil { + err = recErr // will be io.EOF on closeNotify + } + } + if n != 0 || err != nil { return n, err } @@ -940,16 +966,19 @@ func (c *Conn) Close() error { func (c *Conn) Handshake() error { c.handshakeMutex.Lock() defer c.handshakeMutex.Unlock() - if err := c.error(); err != nil { + if err := c.handshakeErr; err != nil { return err } if c.handshakeComplete { return nil } + if c.isClient { - return c.clientHandshake() + c.handshakeErr = c.clientHandshake() + } else { + c.handshakeErr = c.serverHandshake() } - return c.serverHandshake() + return c.handshakeErr } // ConnectionState returns basic TLS details about the connection. @@ -960,6 +989,7 @@ func (c *Conn) ConnectionState() ConnectionState { var state ConnectionState state.HandshakeComplete = c.handshakeComplete if c.handshakeComplete { + state.Version = c.vers state.NegotiatedProtocol = c.clientProtocol state.DidResume = c.didResume state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback @@ -967,6 +997,9 @@ func (c *Conn) ConnectionState() ConnectionState { state.PeerCertificates = c.peerCertificates state.VerifiedChains = c.verifiedChains state.ServerName = c.serverName + if !c.didResume { + state.TLSUnique = c.firstFinished[:] + } } return state @@ -988,10 +1021,10 @@ func (c *Conn) VerifyHostname(host string) error { c.handshakeMutex.Lock() defer c.handshakeMutex.Unlock() if !c.isClient { - return errors.New("VerifyHostname called on TLS server connection") + return errors.New("tls: VerifyHostname called on TLS server connection") } if !c.handshakeComplete { - return errors.New("TLS handshake has not yet been performed") + return errors.New("tls: handshake has not yet been performed") } return c.peerCertificates[0].VerifyHostname(host) } diff --git a/libgo/go/crypto/tls/conn_test.go b/libgo/go/crypto/tls/conn_test.go index 5c555147ca..ec802cad70 100644 --- a/libgo/go/crypto/tls/conn_test.go +++ b/libgo/go/crypto/tls/conn_test.go @@ -88,19 +88,31 @@ func TestCertificateSelection(t *testing.T) { return -1 } - if n := pointerToIndex(config.getCertificateForName("example.com")); n != 0 { + certificateForName := func(name string) *Certificate { + clientHello := &ClientHelloInfo{ + ServerName: name, + } + if cert, err := config.getCertificate(clientHello); err != nil { + t.Errorf("unable to get certificate for name '%s': %s", name, err) + return nil + } else { + return cert + } + } + + if n := pointerToIndex(certificateForName("example.com")); n != 0 { t.Errorf("example.com returned certificate %d, not 0", n) } - if n := pointerToIndex(config.getCertificateForName("bar.example.com")); n != 1 { + if n := pointerToIndex(certificateForName("bar.example.com")); n != 1 { t.Errorf("bar.example.com returned certificate %d, not 1", n) } - if n := pointerToIndex(config.getCertificateForName("foo.example.com")); n != 2 { + if n := pointerToIndex(certificateForName("foo.example.com")); n != 2 { t.Errorf("foo.example.com returned certificate %d, not 2", n) } - if n := pointerToIndex(config.getCertificateForName("foo.bar.example.com")); n != 3 { + if n := pointerToIndex(certificateForName("foo.bar.example.com")); n != 3 { t.Errorf("foo.bar.example.com returned certificate %d, not 3", n) } - if n := pointerToIndex(config.getCertificateForName("foo.bar.baz.example.com")); n != 0 { + if n := pointerToIndex(certificateForName("foo.bar.baz.example.com")); n != 0 { t.Errorf("foo.bar.baz.example.com returned certificate %d, not 0", n) } } diff --git a/libgo/go/crypto/tls/generate_cert.go b/libgo/go/crypto/tls/generate_cert.go index b417ea4640..83f9916ff9 100644 --- a/libgo/go/crypto/tls/generate_cert.go +++ b/libgo/go/crypto/tls/generate_cert.go @@ -10,6 +10,8 @@ package main import ( + "crypto/ecdsa" + "crypto/elliptic" "crypto/rand" "crypto/rsa" "crypto/x509" @@ -26,13 +28,41 @@ import ( ) var ( - host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for") - validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011") - validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for") - isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority") - rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate") + host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for") + validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011") + validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for") + isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority") + rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set") + ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521") ) +func publicKey(priv interface{}) interface{} { + switch k := priv.(type) { + case *rsa.PrivateKey: + return &k.PublicKey + case *ecdsa.PrivateKey: + return &k.PublicKey + default: + return nil + } +} + +func pemBlockForKey(priv interface{}) *pem.Block { + switch k := priv.(type) { + case *rsa.PrivateKey: + return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)} + case *ecdsa.PrivateKey: + b, err := x509.MarshalECPrivateKey(k) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err) + os.Exit(2) + } + return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b} + default: + return nil + } +} + func main() { flag.Parse() @@ -40,10 +70,25 @@ func main() { log.Fatalf("Missing required --host parameter") } - priv, err := rsa.GenerateKey(rand.Reader, *rsaBits) + var priv interface{} + var err error + switch *ecdsaCurve { + case "": + priv, err = rsa.GenerateKey(rand.Reader, *rsaBits) + case "P224": + priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) + case "P256": + priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + case "P384": + priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + case "P521": + priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) + default: + fmt.Fprintf(os.Stderr, "Unrecognized elliptic curve: %q", *ecdsaCurve) + os.Exit(1) + } if err != nil { log.Fatalf("failed to generate private key: %s", err) - return } var notBefore time.Time @@ -59,14 +104,14 @@ func main() { notAfter := notBefore.Add(*validFor) - // end of ASN.1 time - endOfTime := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC) - if notAfter.After(endOfTime) { - notAfter = endOfTime + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + log.Fatalf("failed to generate serial number: %s", err) } template := x509.Certificate{ - SerialNumber: new(big.Int).SetInt64(0), + SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"Acme Co"}, }, @@ -92,16 +137,14 @@ func main() { template.KeyUsage |= x509.KeyUsageCertSign } - derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) if err != nil { log.Fatalf("Failed to create certificate: %s", err) - return } certOut, err := os.Create("cert.pem") if err != nil { log.Fatalf("failed to open cert.pem for writing: %s", err) - return } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() @@ -112,7 +155,7 @@ func main() { log.Print("failed to open key.pem for writing:", err) return } - pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) + pem.Encode(keyOut, pemBlockForKey(priv)) keyOut.Close() log.Print("written key.pem\n") } diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go index 85e4adefcb..7f662e9c9f 100644 --- a/libgo/go/crypto/tls/handshake_client.go +++ b/libgo/go/crypto/tls/handshake_client.go @@ -6,30 +6,60 @@ package tls import ( "bytes" + "crypto" "crypto/ecdsa" "crypto/rsa" "crypto/subtle" "crypto/x509" - "encoding/asn1" "errors" + "fmt" "io" + "net" "strconv" ) +type clientHandshakeState struct { + c *Conn + serverHello *serverHelloMsg + hello *clientHelloMsg + suite *cipherSuite + finishedHash finishedHash + masterSecret []byte + session *ClientSessionState +} + func (c *Conn) clientHandshake() error { if c.config == nil { c.config = defaultConfig() } + if len(c.config.ServerName) == 0 && !c.config.InsecureSkipVerify { + return errors.New("tls: either ServerName or InsecureSkipVerify must be specified in the tls.Config") + } + + nextProtosLength := 0 + for _, proto := range c.config.NextProtos { + if l := len(proto); l == 0 || l > 255 { + return errors.New("tls: invalid NextProtos value") + } else { + nextProtosLength += 1 + l + } + } + if nextProtosLength > 0xffff { + return errors.New("tls: NextProtos values too large") + } + hello := &clientHelloMsg{ - vers: c.config.maxVersion(), - compressionMethods: []uint8{compressionNone}, - random: make([]byte, 32), - ocspStapling: true, - serverName: c.config.ServerName, - supportedCurves: []uint16{curveP256, curveP384, curveP521}, - supportedPoints: []uint8{pointFormatUncompressed}, - nextProtoNeg: len(c.config.NextProtos) > 0, + vers: c.config.maxVersion(), + compressionMethods: []uint8{compressionNone}, + random: make([]byte, 32), + ocspStapling: true, + serverName: c.config.ServerName, + supportedCurves: c.config.curvePreferences(), + supportedPoints: []uint8{pointFormatUncompressed}, + nextProtoNeg: len(c.config.NextProtos) > 0, + secureRenegotiation: true, + alpnProtocols: c.config.NextProtos, } possibleCipherSuites := c.config.cipherSuites() @@ -51,21 +81,61 @@ NextCipherSuite: } } - t := uint32(c.config.time().Unix()) - hello.random[0] = byte(t >> 24) - hello.random[1] = byte(t >> 16) - hello.random[2] = byte(t >> 8) - hello.random[3] = byte(t) - _, err := io.ReadFull(c.config.rand(), hello.random[4:]) + _, err := io.ReadFull(c.config.rand(), hello.random) if err != nil { c.sendAlert(alertInternalError) - return errors.New("short read from Rand") + return errors.New("tls: short read from Rand: " + err.Error()) } if hello.vers >= VersionTLS12 { hello.signatureAndHashes = supportedSKXSignatureAlgorithms } + var session *ClientSessionState + var cacheKey string + sessionCache := c.config.ClientSessionCache + if c.config.SessionTicketsDisabled { + sessionCache = nil + } + + if sessionCache != nil { + hello.ticketSupported = true + + // Try to resume a previously negotiated TLS session, if + // available. + cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config) + candidateSession, ok := sessionCache.Get(cacheKey) + if ok { + // Check that the ciphersuite/version used for the + // previous session are still valid. + cipherSuiteOk := false + for _, id := range hello.cipherSuites { + if id == candidateSession.cipherSuite { + cipherSuiteOk = true + break + } + } + + versOk := candidateSession.vers >= c.config.minVersion() && + candidateSession.vers <= c.config.maxVersion() + if versOk && cipherSuiteOk { + session = candidateSession + } + } + } + + if session != nil { + hello.sessionTicket = session.sessionTicket + // A random session ID is used to detect when the + // server accepted the ticket and is resuming a session + // (see RFC 5077). + hello.sessionId = make([]byte, 16) + if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil { + c.sendAlert(alertInternalError) + return errors.New("tls: short read from Rand: " + err.Error()) + } + } + c.writeRecord(recordTypeHandshake, hello.marshal()) msg, err := c.readHandshake() @@ -74,51 +144,103 @@ NextCipherSuite: } serverHello, ok := msg.(*serverHelloMsg) if !ok { - return c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(serverHello, msg) } vers, ok := c.config.mutualVersion(serverHello.vers) if !ok || vers < VersionTLS10 { // TLS 1.0 is the minimum version supported as a client. - return c.sendAlert(alertProtocolVersion) + c.sendAlert(alertProtocolVersion) + return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers) } c.vers = vers c.haveVers = true - finishedHash := newFinishedHash(c.vers) - finishedHash.Write(hello.marshal()) - finishedHash.Write(serverHello.marshal()) + suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite) + if suite == nil { + c.sendAlert(alertHandshakeFailure) + return fmt.Errorf("tls: server selected an unsupported cipher suite") + } - if serverHello.compressionMethod != compressionNone { - return c.sendAlert(alertUnexpectedMessage) + hs := &clientHandshakeState{ + c: c, + serverHello: serverHello, + hello: hello, + suite: suite, + finishedHash: newFinishedHash(c.vers), + session: session, } - if !hello.nextProtoNeg && serverHello.nextProtoNeg { - c.sendAlert(alertHandshakeFailure) - return errors.New("server advertised unrequested NPN") + hs.finishedHash.Write(hs.hello.marshal()) + hs.finishedHash.Write(hs.serverHello.marshal()) + + isResume, err := hs.processServerHello() + if err != nil { + return err } - suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite) - if suite == nil { - return c.sendAlert(alertHandshakeFailure) + if isResume { + if err := hs.establishKeys(); err != nil { + return err + } + if err := hs.readSessionTicket(); err != nil { + return err + } + if err := hs.readFinished(c.firstFinished[:]); err != nil { + return err + } + if err := hs.sendFinished(nil); err != nil { + return err + } + } else { + if err := hs.doFullHandshake(); err != nil { + return err + } + if err := hs.establishKeys(); err != nil { + return err + } + if err := hs.sendFinished(c.firstFinished[:]); err != nil { + return err + } + if err := hs.readSessionTicket(); err != nil { + return err + } + if err := hs.readFinished(nil); err != nil { + return err + } } - msg, err = c.readHandshake() + if sessionCache != nil && hs.session != nil && session != hs.session { + sessionCache.Put(cacheKey, hs.session) + } + + c.didResume = isResume + c.handshakeComplete = true + c.cipherSuite = suite.id + return nil +} + +func (hs *clientHandshakeState) doFullHandshake() error { + c := hs.c + + msg, err := c.readHandshake() if err != nil { return err } certMsg, ok := msg.(*certificateMsg) if !ok || len(certMsg.certificates) == 0 { - return c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certMsg, msg) } - finishedHash.Write(certMsg.marshal()) + hs.finishedHash.Write(certMsg.marshal()) certs := make([]*x509.Certificate, len(certMsg.certificates)) for i, asn1Data := range certMsg.certificates { cert, err := x509.ParseCertificate(asn1Data) if err != nil { c.sendAlert(alertBadCertificate) - return errors.New("failed to parse certificate from server: " + err.Error()) + return errors.New("tls: failed to parse certificate from server: " + err.Error()) } certs[i] = cert } @@ -148,21 +270,23 @@ NextCipherSuite: case *rsa.PublicKey, *ecdsa.PublicKey: break default: - return c.sendAlert(alertUnsupportedCertificate) + c.sendAlert(alertUnsupportedCertificate) + return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey) } c.peerCertificates = certs - if serverHello.ocspStapling { + if hs.serverHello.ocspStapling { msg, err = c.readHandshake() if err != nil { return err } cs, ok := msg.(*certificateStatusMsg) if !ok { - return c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(cs, msg) } - finishedHash.Write(cs.marshal()) + hs.finishedHash.Write(cs.marshal()) if cs.statusType == statusTypeOCSP { c.ocspResponse = cs.response @@ -174,12 +298,12 @@ NextCipherSuite: return err } - keyAgreement := suite.ka(c.vers) + keyAgreement := hs.suite.ka(c.vers) skx, ok := msg.(*serverKeyExchangeMsg) if ok { - finishedHash.Write(skx.marshal()) - err = keyAgreement.processServerKeyExchange(c.config, hello, serverHello, certs[0], skx) + hs.finishedHash.Write(skx.marshal()) + err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, certs[0], skx) if err != nil { c.sendAlert(alertUnexpectedMessage) return err @@ -208,7 +332,7 @@ NextCipherSuite: // ClientCertificateType, unless there is some external // arrangement to the contrary. - finishedHash.Write(certReq.marshal()) + hs.finishedHash.Write(certReq.marshal()) var rsaAvail, ecdsaAvail bool for _, certType := range certReq.certificateTypes { @@ -221,8 +345,8 @@ NextCipherSuite: } // We need to search our list of client certs for one - // where SignatureAlgorithm is RSA and the Issuer is in - // certReq.certificateAuthorities + // where SignatureAlgorithm is acceptable to the server and the + // Issuer is in certReq.certificateAuthorities findCert: for i, chain := range c.config.Certificates { if !rsaAvail && !ecdsaAvail { @@ -249,7 +373,7 @@ NextCipherSuite: if len(certReq.certificateAuthorities) == 0 { // they gave us an empty list, so just take the - // first RSA cert from c.config.Certificates + // first cert from c.config.Certificates chainToSend = &chain break findCert } @@ -271,9 +395,10 @@ NextCipherSuite: shd, ok := msg.(*serverHelloDoneMsg) if !ok { - return c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(shd, msg) } - finishedHash.Write(shd.marshal()) + hs.finishedHash.Write(shd.marshal()) // If the server requested a certificate then we have to send a // Certificate message, even if it's empty because we don't have a @@ -283,17 +408,17 @@ NextCipherSuite: if chainToSend != nil { certMsg.certificates = chainToSend.Certificate } - finishedHash.Write(certMsg.marshal()) + hs.finishedHash.Write(certMsg.marshal()) c.writeRecord(recordTypeHandshake, certMsg.marshal()) } - preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hello, certs[0]) + preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, certs[0]) if err != nil { c.sendAlert(alertInternalError) return err } if ckx != nil { - finishedHash.Write(ckx.marshal()) + hs.finishedHash.Write(ckx.marshal()) c.writeRecord(recordTypeHandshake, ckx.marshal()) } @@ -303,109 +428,211 @@ NextCipherSuite: hasSignatureAndHash: c.vers >= VersionTLS12, } - switch key := c.config.Certificates[0].PrivateKey.(type) { - case *ecdsa.PrivateKey: - digest, _, hashId := finishedHash.hashForClientCertificate(signatureECDSA) - r, s, err := ecdsa.Sign(c.config.rand(), key, digest) - if err == nil { - signed, err = asn1.Marshal(ecdsaSignature{r, s}) - } + key, ok := chainToSend.PrivateKey.(crypto.Signer) + if !ok { + c.sendAlert(alertInternalError) + return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey) + } + switch key.Public().(type) { + case *ecdsa.PublicKey: + digest, hashFunc, hashId := hs.finishedHash.hashForClientCertificate(signatureECDSA) + signed, err = key.Sign(c.config.rand(), digest, hashFunc) certVerify.signatureAndHash.signature = signatureECDSA certVerify.signatureAndHash.hash = hashId - case *rsa.PrivateKey: - digest, hashFunc, hashId := finishedHash.hashForClientCertificate(signatureRSA) - signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest) + case *rsa.PublicKey: + digest, hashFunc, hashId := hs.finishedHash.hashForClientCertificate(signatureRSA) + signed, err = key.Sign(c.config.rand(), digest, hashFunc) certVerify.signatureAndHash.signature = signatureRSA certVerify.signatureAndHash.hash = hashId default: - err = errors.New("unknown private key type") + err = fmt.Errorf("tls: unknown client certificate key type: %T", key) } if err != nil { - return c.sendAlert(alertInternalError) + c.sendAlert(alertInternalError) + return errors.New("tls: failed to sign handshake with client certificate: " + err.Error()) } certVerify.signature = signed - finishedHash.Write(certVerify.marshal()) + hs.finishedHash.Write(certVerify.marshal()) c.writeRecord(recordTypeHandshake, certVerify.marshal()) } - masterSecret := masterFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random) - clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := - keysFromMasterSecret(c.vers, masterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen) + hs.masterSecret = masterFromPreMasterSecret(c.vers, preMasterSecret, hs.hello.random, hs.serverHello.random) + return nil +} - var clientCipher interface{} - var clientHash macFunction - if suite.cipher != nil { - clientCipher = suite.cipher(clientKey, clientIV, false /* not for reading */) - clientHash = suite.mac(c.vers, clientMAC) +func (hs *clientHandshakeState) establishKeys() error { + c := hs.c + + clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := + keysFromMasterSecret(c.vers, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) + var clientCipher, serverCipher interface{} + var clientHash, serverHash macFunction + if hs.suite.cipher != nil { + clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) + clientHash = hs.suite.mac(c.vers, clientMAC) + serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */) + serverHash = hs.suite.mac(c.vers, serverMAC) } else { - clientCipher = suite.aead(clientKey, clientIV) + clientCipher = hs.suite.aead(clientKey, clientIV) + serverCipher = hs.suite.aead(serverKey, serverIV) } + + c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) c.out.prepareCipherSpec(c.vers, clientCipher, clientHash) - c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + return nil +} - if serverHello.nextProtoNeg { - nextProto := new(nextProtoMsg) - proto, fallback := mutualProtocol(c.config.NextProtos, serverHello.nextProtos) - nextProto.proto = proto - c.clientProtocol = proto - c.clientProtocolFallback = fallback +func (hs *clientHandshakeState) serverResumedSession() bool { + // If the server responded with the same sessionId then it means the + // sessionTicket is being used to resume a TLS session. + return hs.session != nil && hs.hello.sessionId != nil && + bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId) +} - finishedHash.Write(nextProto.marshal()) - c.writeRecord(recordTypeHandshake, nextProto.marshal()) +func (hs *clientHandshakeState) processServerHello() (bool, error) { + c := hs.c + + if hs.serverHello.compressionMethod != compressionNone { + c.sendAlert(alertUnexpectedMessage) + return false, errors.New("tls: server selected unsupported compression format") } - finished := new(finishedMsg) - finished.verifyData = finishedHash.clientSum(masterSecret) - finishedHash.Write(finished.marshal()) - c.writeRecord(recordTypeHandshake, finished.marshal()) + clientDidNPN := hs.hello.nextProtoNeg + clientDidALPN := len(hs.hello.alpnProtocols) > 0 + serverHasNPN := hs.serverHello.nextProtoNeg + serverHasALPN := len(hs.serverHello.alpnProtocol) > 0 - var serverCipher interface{} - var serverHash macFunction - if suite.cipher != nil { - serverCipher = suite.cipher(serverKey, serverIV, true /* for reading */) - serverHash = suite.mac(c.vers, serverMAC) - } else { - serverCipher = suite.aead(serverKey, serverIV) + if !clientDidNPN && serverHasNPN { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("server advertised unrequested NPN extension") } - c.in.prepareCipherSpec(c.vers, serverCipher, serverHash) + + if !clientDidALPN && serverHasALPN { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("server advertised unrequested ALPN extension") + } + + if serverHasNPN && serverHasALPN { + c.sendAlert(alertHandshakeFailure) + return false, errors.New("server advertised both NPN and ALPN extensions") + } + + if serverHasALPN { + c.clientProtocol = hs.serverHello.alpnProtocol + c.clientProtocolFallback = false + } + + if hs.serverResumedSession() { + // Restore masterSecret and peerCerts from previous state + hs.masterSecret = hs.session.masterSecret + c.peerCertificates = hs.session.serverCertificates + return true, nil + } + return false, nil +} + +func (hs *clientHandshakeState) readFinished(out []byte) error { + c := hs.c + c.readRecord(recordTypeChangeCipherSpec) - if err := c.error(); err != nil { + if err := c.in.error(); err != nil { return err } - msg, err = c.readHandshake() + msg, err := c.readHandshake() if err != nil { return err } serverFinished, ok := msg.(*finishedMsg) if !ok { - return c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(serverFinished, msg) } - verify := finishedHash.serverSum(masterSecret) + verify := hs.finishedHash.serverSum(hs.masterSecret) if len(verify) != len(serverFinished.verifyData) || subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 { - return c.sendAlert(alertHandshakeFailure) + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: server's Finished message was incorrect") + } + hs.finishedHash.Write(serverFinished.marshal()) + copy(out, verify) + return nil +} + +func (hs *clientHandshakeState) readSessionTicket() error { + if !hs.serverHello.ticketSupported { + return nil + } + + c := hs.c + msg, err := c.readHandshake() + if err != nil { + return err + } + sessionTicketMsg, ok := msg.(*newSessionTicketMsg) + if !ok { + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(sessionTicketMsg, msg) + } + hs.finishedHash.Write(sessionTicketMsg.marshal()) + + hs.session = &ClientSessionState{ + sessionTicket: sessionTicketMsg.ticket, + vers: c.vers, + cipherSuite: hs.suite.id, + masterSecret: hs.masterSecret, + serverCertificates: c.peerCertificates, } - c.handshakeComplete = true - c.cipherSuite = suite.id return nil } -// mutualProtocol finds the mutual Next Protocol Negotiation protocol given the -// set of client and server supported protocols. The set of client supported -// protocols must not be empty. It returns the resulting protocol and flag +func (hs *clientHandshakeState) sendFinished(out []byte) error { + c := hs.c + + c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) + if hs.serverHello.nextProtoNeg { + nextProto := new(nextProtoMsg) + proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos) + nextProto.proto = proto + c.clientProtocol = proto + c.clientProtocolFallback = fallback + + hs.finishedHash.Write(nextProto.marshal()) + c.writeRecord(recordTypeHandshake, nextProto.marshal()) + } + + finished := new(finishedMsg) + finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret) + hs.finishedHash.Write(finished.marshal()) + c.writeRecord(recordTypeHandshake, finished.marshal()) + copy(out, finished.verifyData) + return nil +} + +// clientSessionCacheKey returns a key used to cache sessionTickets that could +// be used to resume previously negotiated TLS sessions with a server. +func clientSessionCacheKey(serverAddr net.Addr, config *Config) string { + if len(config.ServerName) > 0 { + return config.ServerName + } + return serverAddr.String() +} + +// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol +// given list of possible protocols and a list of the preference order. The +// first list must not be empty. It returns the resulting protocol and flag // indicating if the fallback case was reached. -func mutualProtocol(clientProtos, serverProtos []string) (string, bool) { - for _, s := range serverProtos { - for _, c := range clientProtos { +func mutualProtocol(protos, preferenceProtos []string) (string, bool) { + for _, s := range preferenceProtos { + for _, c := range protos { if s == c { return s, false } } } - return clientProtos[0], true + return protos[0], true } diff --git a/libgo/go/crypto/tls/handshake_client_test.go b/libgo/go/crypto/tls/handshake_client_test.go index 6c564001b0..e5eaa7de20 100644 --- a/libgo/go/crypto/tls/handshake_client_test.go +++ b/libgo/go/crypto/tls/handshake_client_test.go @@ -6,3045 +6,485 @@ package tls import ( "bytes" - "flag" + "crypto/ecdsa" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "fmt" "io" "net" "os" + "os/exec" + "path/filepath" + "strconv" "testing" + "time" ) -func testClientScript(t *testing.T, name string, clientScript [][]byte, config *Config) { - c, s := net.Pipe() - cli := Client(c, config) - go func() { - cli.Write([]byte("hello\n")) - cli.Close() - c.Close() - }() +// Note: see comment in handshake_test.go for details of how the reference +// tests work. - defer c.Close() - for i, b := range clientScript { - if i%2 == 1 { - s.Write(b) - continue - } - bb := make([]byte, len(b)) - _, err := io.ReadFull(s, bb) +// blockingSource is an io.Reader that blocks a Read call until it's closed. +type blockingSource chan bool + +func (b blockingSource) Read([]byte) (n int, err error) { + <-b + return 0, io.EOF +} + +// clientTest represents a test of the TLS client handshake against a reference +// implementation. +type clientTest struct { + // name is a freeform string identifying the test and the file in which + // the expected results will be stored. + name string + // command, if not empty, contains a series of arguments for the + // command to run for the reference server. + command []string + // config, if not nil, contains a custom Config to use for this test. + config *Config + // cert, if not empty, contains a DER-encoded certificate for the + // reference server. + cert []byte + // key, if not nil, contains either a *rsa.PrivateKey or + // *ecdsa.PrivateKey which is the private key for the reference server. + key interface{} + // validate, if not nil, is a function that will be called with the + // ConnectionState of the resulting connection. It returns a non-nil + // error if the ConnectionState is unacceptable. + validate func(ConnectionState) error +} + +var defaultServerCommand = []string{"openssl", "s_server"} + +// connFromCommand starts the reference server process, connects to it and +// returns a recordingConn for the connection. The stdin return value is a +// blockingSource for the stdin of the child process. It must be closed before +// Waiting for child. +func (test *clientTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, stdin blockingSource, err error) { + cert := testRSACertificate + if len(test.cert) > 0 { + cert = test.cert + } + certPath := tempFile(string(cert)) + defer os.Remove(certPath) + + var key interface{} = testRSAPrivateKey + if test.key != nil { + key = test.key + } + var pemType string + var derBytes []byte + switch key := key.(type) { + case *rsa.PrivateKey: + pemType = "RSA" + derBytes = x509.MarshalPKCS1PrivateKey(key) + case *ecdsa.PrivateKey: + pemType = "EC" + var err error + derBytes, err = x509.MarshalECPrivateKey(key) if err != nil { - t.Fatalf("%s #%d: %s", name, i, err) + panic(err) } - if !bytes.Equal(b, bb) { - t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", name, i, bb, b) + default: + panic("unknown key type") + } + + var pemOut bytes.Buffer + pem.Encode(&pemOut, &pem.Block{Type: pemType + " PRIVATE KEY", Bytes: derBytes}) + + keyPath := tempFile(string(pemOut.Bytes())) + defer os.Remove(keyPath) + + var command []string + if len(test.command) > 0 { + command = append(command, test.command...) + } else { + command = append(command, defaultServerCommand...) + } + command = append(command, "-cert", certPath, "-certform", "DER", "-key", keyPath) + // serverPort contains the port that OpenSSL will listen on. OpenSSL + // can't take "0" as an argument here so we have to pick a number and + // hope that it's not in use on the machine. Since this only occurs + // when -update is given and thus when there's a human watching the + // test, this isn't too bad. + const serverPort = 24323 + command = append(command, "-accept", strconv.Itoa(serverPort)) + + cmd := exec.Command(command[0], command[1:]...) + stdin = blockingSource(make(chan bool)) + cmd.Stdin = stdin + var out bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &out + if err := cmd.Start(); err != nil { + return nil, nil, nil, err + } + + // OpenSSL does print an "ACCEPT" banner, but it does so *before* + // opening the listening socket, so we can't use that to wait until it + // has started listening. Thus we are forced to poll until we get a + // connection. + var tcpConn net.Conn + for i := uint(0); i < 5; i++ { + var err error + tcpConn, err = net.DialTCP("tcp", nil, &net.TCPAddr{ + IP: net.IPv4(127, 0, 0, 1), + Port: serverPort, + }) + if err == nil { + break } + time.Sleep((1 << i) * 5 * time.Millisecond) + } + if tcpConn == nil { + close(stdin) + out.WriteTo(os.Stdout) + cmd.Process.Kill() + return nil, nil, nil, cmd.Wait() + } + + record := &recordingConn{ + Conn: tcpConn, } + + return record, cmd, stdin, nil } -func TestHandshakeClientRSARC4(t *testing.T) { - var config = *testConfig - config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA} - testClientScript(t, "RSA-RC4", rsaRC4ClientScript, &config) +func (test *clientTest) dataPath() string { + return filepath.Join("testdata", "Client-"+test.name) } -func TestHandshakeClientECDHERSAAES(t *testing.T) { - var config = *testConfig - config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA} - testClientScript(t, "ECDHE-RSA-AES", ecdheRSAAESClientScript, &config) +func (test *clientTest) loadData() (flows [][]byte, err error) { + in, err := os.Open(test.dataPath()) + if err != nil { + return nil, err + } + defer in.Close() + return parseTestData(in) } -func TestHandshakeClientECDHECDSAAES(t *testing.T) { - var config = *testConfig - config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA} - config.Certificates = nil - config.BuildNameToCertificate() - testClientScript(t, "ECDHE-ECDSA-AES", ecdheECDSAAESClientScript, &config) +func (test *clientTest) run(t *testing.T, write bool) { + var clientConn, serverConn net.Conn + var recordingConn *recordingConn + var childProcess *exec.Cmd + var stdin blockingSource + + if write { + var err error + recordingConn, childProcess, stdin, err = test.connFromCommand() + if err != nil { + t.Fatalf("Failed to start subcommand: %s", err) + } + clientConn = recordingConn + } else { + clientConn, serverConn = net.Pipe() + } + + config := test.config + if config == nil { + config = testConfig + } + client := Client(clientConn, config) + + doneChan := make(chan bool) + go func() { + if _, err := client.Write([]byte("hello\n")); err != nil { + t.Logf("Client.Write failed: %s", err) + } + if test.validate != nil { + if err := test.validate(client.ConnectionState()); err != nil { + t.Logf("validate callback returned error: %s", err) + } + } + client.Close() + clientConn.Close() + doneChan <- true + }() + + if !write { + flows, err := test.loadData() + if err != nil { + t.Fatalf("%s: failed to load data from %s: %v", test.name, test.dataPath(), err) + } + for i, b := range flows { + if i%2 == 1 { + serverConn.Write(b) + continue + } + bb := make([]byte, len(b)) + _, err := io.ReadFull(serverConn, bb) + if err != nil { + t.Fatalf("%s #%d: %s", test.name, i, err) + } + if !bytes.Equal(b, bb) { + t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", test.name, i, bb, b) + } + } + serverConn.Close() + } + + <-doneChan + + if write { + path := test.dataPath() + out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + t.Fatalf("Failed to create output file: %s", err) + } + defer out.Close() + recordingConn.Close() + close(stdin) + childProcess.Process.Kill() + childProcess.Wait() + if len(recordingConn.flows) < 3 { + childProcess.Stdout.(*bytes.Buffer).WriteTo(os.Stdout) + t.Fatalf("Client connection didn't work") + } + recordingConn.WriteTo(out) + fmt.Printf("Wrote %s\n", path) + } } -func TestLongClientCerticiateChain(t *testing.T) { - config := *testConfig - cert, _ := X509KeyPair(testClientChainCertificate, testClientChainCertificate) - config.Certificates = []Certificate{cert} - testClientScript(t, "Long client certificate chains", clientChainCertificateScript, &config) +func runClientTestForVersion(t *testing.T, template *clientTest, prefix, option string) { + test := *template + test.name = prefix + test.name + if len(test.command) == 0 { + test.command = defaultClientCommand + } + test.command = append([]string(nil), test.command...) + test.command = append(test.command, option) + test.run(t, *update) } -func TestHandshakeClientTLS11(t *testing.T) { - var config = *testConfig - config.MaxVersion = VersionTLS11 - config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA} - testClientScript(t, "TLS11-ECDHE-AES", tls11ECDHEAESClientScript, &config) +func runClientTestTLS10(t *testing.T, template *clientTest) { + runClientTestForVersion(t, template, "TLSv10-", "-tls1") } -func TestHandshakeClientTLS12(t *testing.T) { - config := *testConfig - config.MaxVersion = VersionTLS12 - config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA} - cert, _ := X509KeyPair(testClientChainCertificate, testClientChainCertificate) - config.Certificates = []Certificate{cert} - testClientScript(t, "TLS12", clientTLS12Script, &config) +func runClientTestTLS11(t *testing.T, template *clientTest) { + runClientTestForVersion(t, template, "TLSv11-", "-tls1_1") } -func TestHandshakeClientTLS12ClientCert(t *testing.T) { - config := *testConfig - config.MaxVersion = VersionTLS12 - config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256} - cert, _ := X509KeyPair(testClientChainCertificate, testClientChainCertificate) - config.Certificates = []Certificate{cert} - testClientScript(t, "TLS12ClientCert", clientTLS12ClientCertScript, &config) +func runClientTestTLS12(t *testing.T, template *clientTest) { + runClientTestForVersion(t, template, "TLSv12-", "-tls1_2") } -var connect = flag.Bool("connect", false, "connect to a TLS server on :10443") +func TestHandshakeClientRSARC4(t *testing.T) { + test := &clientTest{ + name: "RSA-RC4", + command: []string{"openssl", "s_server", "-cipher", "RC4-SHA"}, + } + runClientTestTLS10(t, test) + runClientTestTLS11(t, test) + runClientTestTLS12(t, test) +} -func TestRunClient(t *testing.T) { - if !*connect { - return +func TestHandshakeClientECDHERSAAES(t *testing.T) { + test := &clientTest{ + name: "ECDHE-RSA-AES", + command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES128-SHA"}, } + runClientTestTLS10(t, test) + runClientTestTLS11(t, test) + runClientTestTLS12(t, test) +} - tcpConn, err := net.Dial("tcp", "127.0.0.1:10443") - if err != nil { - t.Fatal(err) +func TestHandshakeClientECDHEECDSAAES(t *testing.T) { + test := &clientTest{ + name: "ECDHE-ECDSA-AES", + command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA"}, + cert: testECDSACertificate, + key: testECDSAPrivateKey, } + runClientTestTLS10(t, test) + runClientTestTLS11(t, test) + runClientTestTLS12(t, test) +} - record := &recordingConn{ - Conn: tcpConn, +func TestHandshakeClientECDHEECDSAAESGCM(t *testing.T) { + test := &clientTest{ + name: "ECDHE-ECDSA-AES-GCM", + command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-GCM-SHA256"}, + cert: testECDSACertificate, + key: testECDSAPrivateKey, } + runClientTestTLS12(t, test) +} + +func TestHandshakeClientCertRSA(t *testing.T) { + config := *testConfig + cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM)) + config.Certificates = []Certificate{cert} - config := GetTestConfig() - conn := Client(record, config) - if err := conn.Handshake(); err != nil { - t.Fatalf("error from TLS handshake: %s", err) + test := &clientTest{ + name: "ClientCert-RSA-RSA", + command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"}, + config: &config, } - conn.Write([]byte("hello\n")) - conn.Close() + runClientTestTLS10(t, test) + runClientTestTLS12(t, test) + + test = &clientTest{ + name: "ClientCert-RSA-ECDSA", + command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"}, + config: &config, + cert: testECDSACertificate, + key: testECDSAPrivateKey, + } - record.WriteTo(os.Stdout) + runClientTestTLS10(t, test) + runClientTestTLS12(t, test) } -func TestEmptyRecords(t *testing.T) { - // emptyRecordScript contains a TLS connection with an empty record as - // the first application data from the server. This test ensures that - // the empty record doesn't cause (0, nil) to be returned from - // Conn.Read. +func TestHandshakeClientCertECDSA(t *testing.T) { config := *testConfig - config.CipherSuites = []uint16{TLS_RSA_WITH_AES_256_CBC_SHA} + cert, _ := X509KeyPair([]byte(clientECDSACertificatePEM), []byte(clientECDSAKeyPEM)) + config.Certificates = []Certificate{cert} - c, s := net.Pipe() - cli := Client(c, &config) - go func() { - buf := make([]byte, 1024) - n, err := cli.Read(buf) - defer c.Close() - defer cli.Close() + test := &clientTest{ + name: "ClientCert-ECDSA-RSA", + command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"}, + config: &config, + } - if err != nil { - t.Fatalf("error reading from tls.Client: %s", err) - } - const expectedLength = 197 - if n != expectedLength { - t.Fatalf("incorrect length reading from tls.Client, got %d, want %d", n, expectedLength) - } - }() + runClientTestTLS10(t, test) + runClientTestTLS12(t, test) - defer c.Close() - for i, b := range emptyRecordScript { - if i%2 == 1 { - s.Write(b) - continue - } - bb := make([]byte, len(b)) - _, err := io.ReadFull(s, bb) + test = &clientTest{ + name: "ClientCert-ECDSA-ECDSA", + command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA", "-verify", "1"}, + config: &config, + cert: testECDSACertificate, + key: testECDSAPrivateKey, + } + + runClientTestTLS10(t, test) + runClientTestTLS12(t, test) +} + +func TestClientResumption(t *testing.T) { + serverConfig := &Config{ + CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, + Certificates: testConfig.Certificates, + } + clientConfig := &Config{ + CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + InsecureSkipVerify: true, + ClientSessionCache: NewLRUClientSessionCache(32), + } + + testResumeState := func(test string, didResume bool) { + hs, err := testHandshake(clientConfig, serverConfig) if err != nil { - t.Fatalf("#%d: %s", i, err) + t.Fatalf("%s: handshake failed: %s", test, err) } - if !bytes.Equal(b, bb) { - t.Fatalf("#%d: mismatch on read: got:%x want:%x", i, bb, b) + if hs.DidResume != didResume { + t.Fatalf("%s resumed: %v, expected: %v", test, hs.DidResume, didResume) } } -} -// Script of interaction with gnutls implementation. -// The values for this test are obtained by building and running in client mode: -// % go test -test.run "TestRunClient" -connect -// The recorded bytes are written to stdout. -// -// The server private key is: -// -----BEGIN RSA PRIVATE KEY----- -// MIIBPAIBAAJBAJ+zw4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVD -// TGiXav6ooKXfX3j/7tdkuD8Ey2//Kv7+ue0CAwEAAQJAN6W31vDEP2DjdqhzCDDu -// OA4NACqoiFqyblo7yc2tM4h4xMbC3Yx5UKMN9ZkCtX0gzrz6DyF47bdKcWBzNWCj -// gQIhANEoojVt7hq+SQ6MCN6FTAysGgQf56Q3TYoJMoWvdiXVAiEAw3e3rc+VJpOz -// rHuDo6bgpjUAAXM+v3fcpsfZSNO6V7kCIQCtbVjanpUwvZkMI9by02oUk9taki3b -// PzPfAfNPYAbCJQIhAJXNQDWyqwn/lGmR11cqY2y9nZ1+5w3yHGatLrcDnQHxAiEA -// vnlEGo8K85u+KwIOimM48ZG8oTk7iFdkqLJR1utT3aU= -// -----END RSA PRIVATE KEY----- -// -// and certificate is: -// -----BEGIN CERTIFICATE----- -// MIICKzCCAdWgAwIBAgIJALE1E2URIMWSMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV -// BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX -// aWRnaXRzIFB0eSBMdGQwHhcNMTIwNDA2MTcxMDEzWhcNMTUwNDA2MTcxMDEzWjBF -// MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50 -// ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ+z -// w4Qnlf8SMVIPFe9GEcStgOY2Ww/dgNdhjeD8ckUJNP5VZkVDTGiXav6ooKXfX3j/ -// 7tdkuD8Ey2//Kv7+ue0CAwEAAaOBpzCBpDAdBgNVHQ4EFgQUeKaXmmO1xaGlM7oi -// fCNuWxt6zCswdQYDVR0jBG4wbIAUeKaXmmO1xaGlM7oifCNuWxt6zCuhSaRHMEUx -// CzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRl -// cm5ldCBXaWRnaXRzIFB0eSBMdGSCCQCxNRNlESDFkjAMBgNVHRMEBTADAQH/MA0G -// CSqGSIb3DQEBBQUAA0EAhTZAc8G7GtrUWZ8tonAxRnTsg26oyDxRrzms7EC86CJG -// HZnWRiok1IsFCEv7NRFukrt3uuQSu/TIXpyBqJdgTA== -// -----END CERTIFICATE----- -var rsaRC4ClientScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00, - 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, - 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, - 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, - }, + testResumeState("Handshake", false) + testResumeState("Resume", true) - { - 0x16, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00, - 0x46, 0x03, 0x01, 0x4d, 0x0a, 0x56, 0x16, 0xb5, - 0x91, 0xd1, 0xcb, 0x80, 0x4d, 0xc7, 0x46, 0xf3, - 0x37, 0x0c, 0xef, 0xea, 0x64, 0x11, 0x14, 0x56, - 0x97, 0x9b, 0xc5, 0x67, 0x08, 0xb7, 0x13, 0xea, - 0xf8, 0xc9, 0xb3, 0x20, 0xe2, 0xfc, 0x41, 0xf6, - 0x96, 0x90, 0x9d, 0x43, 0x9b, 0xe9, 0x6e, 0xf8, - 0x41, 0x16, 0xcc, 0xf3, 0xc7, 0xde, 0xda, 0x5a, - 0xa1, 0x33, 0x69, 0xe2, 0xde, 0x5b, 0xaf, 0x2a, - 0x92, 0xe7, 0xd4, 0xa0, 0x00, 0x05, 0x00, 0x16, - 0x03, 0x01, 0x01, 0xf7, 0x0b, 0x00, 0x01, 0xf3, - 0x00, 0x01, 0xf0, 0x00, 0x01, 0xed, 0x30, 0x82, - 0x01, 0xe9, 0x30, 0x82, 0x01, 0x52, 0x02, 0x01, - 0x06, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, - 0x30, 0x5b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x0a, 0x51, 0x75, 0x65, 0x65, 0x6e, 0x73, - 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x1a, 0x30, 0x18, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, - 0x72, 0x79, 0x70, 0x74, 0x53, 0x6f, 0x66, 0x74, - 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, - 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x13, 0x12, 0x54, 0x65, 0x73, 0x74, 0x20, - 0x43, 0x41, 0x20, 0x28, 0x31, 0x30, 0x32, 0x34, - 0x20, 0x62, 0x69, 0x74, 0x29, 0x30, 0x1e, 0x17, - 0x0d, 0x30, 0x30, 0x31, 0x30, 0x31, 0x36, 0x32, - 0x32, 0x33, 0x31, 0x30, 0x33, 0x5a, 0x17, 0x0d, - 0x30, 0x33, 0x30, 0x31, 0x31, 0x34, 0x32, 0x32, - 0x33, 0x31, 0x30, 0x33, 0x5a, 0x30, 0x63, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x51, - 0x75, 0x65, 0x65, 0x6e, 0x73, 0x6c, 0x61, 0x6e, - 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x11, 0x43, 0x72, 0x79, 0x70, - 0x74, 0x53, 0x6f, 0x66, 0x74, 0x20, 0x50, 0x74, - 0x79, 0x20, 0x4c, 0x74, 0x64, 0x31, 0x23, 0x30, - 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1a, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x74, - 0x65, 0x73, 0x74, 0x20, 0x63, 0x65, 0x72, 0x74, - 0x20, 0x28, 0x35, 0x31, 0x32, 0x20, 0x62, 0x69, - 0x74, 0x29, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, - 0x02, 0x41, 0x00, 0x9f, 0xb3, 0xc3, 0x84, 0x27, - 0x95, 0xff, 0x12, 0x31, 0x52, 0x0f, 0x15, 0xef, - 0x46, 0x11, 0xc4, 0xad, 0x80, 0xe6, 0x36, 0x5b, - 0x0f, 0xdd, 0x80, 0xd7, 0x61, 0x8d, 0xe0, 0xfc, - 0x72, 0x45, 0x09, 0x34, 0xfe, 0x55, 0x66, 0x45, - 0x43, 0x4c, 0x68, 0x97, 0x6a, 0xfe, 0xa8, 0xa0, - 0xa5, 0xdf, 0x5f, 0x78, 0xff, 0xee, 0xd7, 0x64, - 0xb8, 0x3f, 0x04, 0xcb, 0x6f, 0xff, 0x2a, 0xfe, - 0xfe, 0xb9, 0xed, 0x02, 0x03, 0x01, 0x00, 0x01, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, - 0x81, 0x81, 0x00, 0x93, 0xd2, 0x0a, 0xc5, 0x41, - 0xe6, 0x5a, 0xa9, 0x86, 0xf9, 0x11, 0x87, 0xe4, - 0xdb, 0x45, 0xe2, 0xc5, 0x95, 0x78, 0x1a, 0x6c, - 0x80, 0x6d, 0x73, 0x1f, 0xb4, 0x6d, 0x44, 0xa3, - 0xba, 0x86, 0x88, 0xc8, 0x58, 0xcd, 0x1c, 0x06, - 0x35, 0x6c, 0x44, 0x62, 0x88, 0xdf, 0xe4, 0xf6, - 0x64, 0x61, 0x95, 0xef, 0x4a, 0xa6, 0x7f, 0x65, - 0x71, 0xd7, 0x6b, 0x88, 0x39, 0xf6, 0x32, 0xbf, - 0xac, 0x93, 0x67, 0x69, 0x51, 0x8c, 0x93, 0xec, - 0x48, 0x5f, 0xc9, 0xb1, 0x42, 0xf9, 0x55, 0xd2, - 0x7e, 0x4e, 0xf4, 0xf2, 0x21, 0x6b, 0x90, 0x57, - 0xe6, 0xd7, 0x99, 0x9e, 0x41, 0xca, 0x80, 0xbf, - 0x1a, 0x28, 0xa2, 0xca, 0x5b, 0x50, 0x4a, 0xed, - 0x84, 0xe7, 0x82, 0xc7, 0xd2, 0xcf, 0x36, 0x9e, - 0x6a, 0x67, 0xb9, 0x88, 0xa7, 0xf3, 0x8a, 0xd0, - 0x04, 0xf8, 0xe8, 0xc6, 0x17, 0xe3, 0xc5, 0x29, - 0xbc, 0x17, 0xf1, 0x16, 0x03, 0x01, 0x00, 0x04, - 0x0e, 0x00, 0x00, 0x00, - }, + if _, err := io.ReadFull(serverConfig.rand(), serverConfig.SessionTicketKey[:]); err != nil { + t.Fatalf("Failed to invalidate SessionTicketKey") + } + testResumeState("InvalidSessionTicketKey", false) + testResumeState("ResumeAfterInvalidSessionTicketKey", true) - { - 0x16, 0x03, 0x01, 0x00, 0x46, 0x10, 0x00, 0x00, - 0x42, 0x00, 0x40, 0x87, 0xa1, 0x1f, 0x14, 0xe1, - 0xfb, 0x91, 0xac, 0x58, 0x2e, 0xf3, 0x71, 0xce, - 0x01, 0x85, 0x2c, 0xc7, 0xfe, 0x84, 0x87, 0x82, - 0xb7, 0x57, 0xdb, 0x37, 0x4d, 0x46, 0x83, 0x67, - 0x52, 0x82, 0x51, 0x01, 0x95, 0x23, 0x68, 0x69, - 0x6b, 0xd0, 0xa7, 0xa7, 0xe5, 0x88, 0xd0, 0x47, - 0x71, 0xb8, 0xd2, 0x03, 0x05, 0x25, 0x56, 0x5c, - 0x10, 0x08, 0xc6, 0x9b, 0xd4, 0x67, 0xcd, 0x28, - 0xbe, 0x9c, 0x48, 0x14, 0x03, 0x01, 0x00, 0x01, - 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xc1, 0xb8, - 0xd3, 0x7f, 0xc5, 0xc2, 0x5a, 0x1d, 0x6d, 0x5b, - 0x2d, 0x5c, 0x82, 0x87, 0xc2, 0x6f, 0x0d, 0x63, - 0x7b, 0x72, 0x2b, 0xda, 0x69, 0xc4, 0xfe, 0x3c, - 0x84, 0xa1, 0x5a, 0x62, 0x38, 0x37, 0xc6, 0x54, - 0x25, 0x2a, - }, + clientConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA} + testResumeState("DifferentCipherSuite", false) + testResumeState("DifferentCipherSuiteRecovers", true) - { - 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x01, 0x00, 0x24, 0xea, 0x88, 0x9c, 0x00, 0xf6, - 0x35, 0xb8, 0x42, 0x7f, 0x15, 0x17, 0x76, 0x5e, - 0x4b, 0x24, 0xcb, 0x7e, 0xa0, 0x7b, 0xc3, 0x70, - 0x52, 0x0a, 0x88, 0x2a, 0x7a, 0x45, 0x59, 0x90, - 0x59, 0xac, 0xc6, 0xb5, 0x56, 0x55, 0x96, - }, + clientConfig.ClientSessionCache = nil + testResumeState("WithoutSessionCache", false) } -var ecdheRSAAESClientScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00, - 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x13, - 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, - 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, - 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x52, 0x02, 0x00, 0x00, - 0x4e, 0x03, 0x01, 0x50, 0xad, 0x72, 0xb1, 0x14, - 0x45, 0xce, 0x0a, 0x95, 0xf9, 0x63, 0xef, 0xa8, - 0xe5, 0x07, 0x34, 0x04, 0xe9, 0x08, 0x0f, 0x38, - 0xe4, 0x28, 0x27, 0x91, 0x07, 0x03, 0xe2, 0xfe, - 0xe3, 0x25, 0xf7, 0x20, 0x08, 0x42, 0xa2, 0x01, - 0x69, 0x53, 0xf0, 0xd9, 0x4c, 0xfa, 0x01, 0xa1, - 0xce, 0x4b, 0xf8, 0x28, 0x21, 0xad, 0x06, 0xbe, - 0xe0, 0x1b, 0x3b, 0xf7, 0xec, 0xd2, 0x52, 0xae, - 0x2a, 0x57, 0xb7, 0xa8, 0xc0, 0x13, 0x00, 0x00, - 0x06, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x16, - 0x03, 0x01, 0x02, 0x39, 0x0b, 0x00, 0x02, 0x35, - 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f, 0x30, 0x82, - 0x02, 0x2b, 0x30, 0x82, 0x01, 0xd5, 0xa0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xb1, 0x35, - 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x32, 0x30, 0x34, 0x30, 0x36, 0x31, 0x37, - 0x31, 0x30, 0x31, 0x33, 0x5a, 0x17, 0x0d, 0x31, - 0x35, 0x30, 0x34, 0x30, 0x36, 0x31, 0x37, 0x31, - 0x30, 0x31, 0x33, 0x5a, 0x30, 0x45, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, - 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, - 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, - 0x4c, 0x74, 0x64, 0x30, 0x5c, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, - 0x48, 0x02, 0x41, 0x00, 0x9f, 0xb3, 0xc3, 0x84, - 0x27, 0x95, 0xff, 0x12, 0x31, 0x52, 0x0f, 0x15, - 0xef, 0x46, 0x11, 0xc4, 0xad, 0x80, 0xe6, 0x36, - 0x5b, 0x0f, 0xdd, 0x80, 0xd7, 0x61, 0x8d, 0xe0, - 0xfc, 0x72, 0x45, 0x09, 0x34, 0xfe, 0x55, 0x66, - 0x45, 0x43, 0x4c, 0x68, 0x97, 0x6a, 0xfe, 0xa8, - 0xa0, 0xa5, 0xdf, 0x5f, 0x78, 0xff, 0xee, 0xd7, - 0x64, 0xb8, 0x3f, 0x04, 0xcb, 0x6f, 0xff, 0x2a, - 0xfe, 0xfe, 0xb9, 0xed, 0x02, 0x03, 0x01, 0x00, - 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, 0xa4, 0x30, - 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, - 0x04, 0x14, 0x78, 0xa6, 0x97, 0x9a, 0x63, 0xb5, - 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22, 0x7c, 0x23, - 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b, 0x30, 0x75, - 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x6e, 0x30, - 0x6c, 0x80, 0x14, 0x78, 0xa6, 0x97, 0x9a, 0x63, - 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22, 0x7c, - 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b, 0xa1, - 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, - 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, - 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, - 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, - 0x74, 0x64, 0x82, 0x09, 0x00, 0xb1, 0x35, 0x13, - 0x65, 0x11, 0x20, 0xc5, 0x92, 0x30, 0x0c, 0x06, - 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, - 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x03, 0x41, 0x00, 0x85, 0x36, 0x40, - 0x73, 0xc1, 0xbb, 0x1a, 0xda, 0xd4, 0x59, 0x9f, - 0x2d, 0xa2, 0x70, 0x31, 0x46, 0x74, 0xec, 0x83, - 0x6e, 0xa8, 0xc8, 0x3c, 0x51, 0xaf, 0x39, 0xac, - 0xec, 0x40, 0xbc, 0xe8, 0x22, 0x46, 0x1d, 0x99, - 0xd6, 0x46, 0x2a, 0x24, 0xd4, 0x8b, 0x05, 0x08, - 0x4b, 0xfb, 0x35, 0x11, 0x6e, 0x92, 0xbb, 0x77, - 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8, 0x5e, 0x9c, - 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16, 0x03, 0x01, - 0x00, 0x8b, 0x0c, 0x00, 0x00, 0x87, 0x03, 0x00, - 0x17, 0x41, 0x04, 0x1c, 0x8f, 0x9c, 0x6d, 0xe7, - 0xab, 0x3e, 0xf8, 0x0a, 0x5d, 0xe1, 0x86, 0xb4, - 0xe2, 0x8e, 0xb2, 0x1c, 0x3b, 0xd9, 0xb6, 0x08, - 0x80, 0x58, 0x21, 0xe9, 0x0e, 0xc6, 0x66, 0x67, - 0x97, 0xcb, 0xb9, 0x92, 0x07, 0x00, 0xc4, 0xe5, - 0xec, 0x5f, 0xb4, 0xe2, 0x20, 0xa9, 0xc9, 0x62, - 0xd0, 0x98, 0xd5, 0xe3, 0x53, 0xff, 0xd0, 0x0a, - 0x6e, 0x29, 0x69, 0x39, 0x2a, 0x4b, 0x5c, 0xd8, - 0x6c, 0xf5, 0xfe, 0x00, 0x40, 0x35, 0xa7, 0x26, - 0x2e, 0xc2, 0x48, 0x93, 0x32, 0xf7, 0x7d, 0x0f, - 0x0d, 0x77, 0x56, 0x9a, 0x85, 0x0c, 0xa6, 0x74, - 0x06, 0xb8, 0x3d, 0x90, 0x56, 0x12, 0x63, 0xff, - 0x00, 0x5e, 0x0f, 0xf7, 0x24, 0xf7, 0xdb, 0x48, - 0x71, 0xe9, 0x2e, 0x03, 0xd3, 0xfa, 0x3a, 0xae, - 0xa0, 0xc1, 0x77, 0x3c, 0x4c, 0x59, 0xce, 0x33, - 0x1a, 0xd2, 0x47, 0x83, 0xfa, 0xea, 0xd8, 0x1e, - 0x06, 0xe7, 0x7d, 0xa0, 0x9b, 0x16, 0x03, 0x01, - 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x46, 0x10, 0x00, 0x00, - 0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d, - 0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5, - 0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd, - 0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce, - 0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e, - 0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56, - 0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49, - 0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b, - 0xdc, 0x5a, 0x89, 0x14, 0x03, 0x01, 0x00, 0x01, - 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0xd9, 0xa7, - 0x80, 0x56, 0x3f, 0xa3, 0x8f, 0x96, 0x72, 0x4e, - 0x4e, 0x6e, 0x23, 0x41, 0x8f, 0xda, 0x91, 0xb2, - 0x9e, 0x63, 0x23, 0x82, 0x64, 0xcd, 0x07, 0x24, - 0xd3, 0x40, 0x20, 0x22, 0x4c, 0xe3, 0xff, 0x38, - 0xbb, 0x43, 0x9d, 0x57, 0x11, 0xd5, 0x46, 0xa5, - 0x05, 0x29, 0x92, 0x02, 0xce, 0xdf, - }, - { - 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x01, 0x00, 0x90, 0xe7, 0xba, 0x0e, 0xb1, 0xda, - 0x92, 0xb5, 0x77, 0x56, 0x38, 0xa6, 0x22, 0xc1, - 0x72, 0xeb, 0x8a, 0x68, 0x09, 0xb6, 0x74, 0xad, - 0xb3, 0x4a, 0xf2, 0xdd, 0x09, 0x9b, 0xc9, 0x4f, - 0x84, 0x73, 0x8b, 0xd6, 0x97, 0x50, 0x23, 0x1c, - 0xa0, 0xc2, 0x0c, 0x25, 0x18, 0xdd, 0x5e, 0x15, - 0x4d, 0xd9, 0xef, 0x4f, 0x6a, 0x43, 0x61, 0x9c, - 0x95, 0xde, 0x3c, 0x66, 0xc4, 0xc1, 0x33, 0x56, - 0xdd, 0x2f, 0x90, 0xaf, 0x68, 0x5c, 0x9c, 0xa4, - 0x90, 0x6d, 0xbf, 0x51, 0x1d, 0x68, 0xcb, 0x81, - 0x77, 0x52, 0xa0, 0x93, 0x2a, 0xf8, 0xc7, 0x61, - 0x87, 0x76, 0xca, 0x93, 0x9e, 0xd6, 0xee, 0x6f, - 0x3f, 0xeb, 0x7d, 0x06, 0xdd, 0x73, 0x4e, 0x27, - 0x16, 0x63, 0x92, 0xe4, 0xb2, 0x3f, 0x91, 0x23, - 0x21, 0x97, 0x90, 0xce, 0x53, 0xb8, 0xb0, 0x9d, - 0xbd, 0xbd, 0x33, 0x84, 0xad, 0x6b, 0x2e, 0x7b, - 0xf5, 0xeb, 0x1d, 0x64, 0x37, 0x2e, 0x29, 0x4e, - 0xb0, 0x93, 0xdb, 0x92, 0xc7, 0xaa, 0x94, 0xa5, - 0x3b, 0x64, 0xd0, - }, - { - 0x17, 0x03, 0x01, 0x00, 0x20, 0x11, 0xd8, 0x6b, - 0x3c, 0xf6, 0xbe, 0xf4, 0x54, 0x87, 0xec, 0x75, - 0x0c, 0x44, 0xdb, 0x92, 0xfc, 0xde, 0x7e, 0x0f, - 0x9f, 0x87, 0x87, 0x9c, 0x03, 0xd5, 0x07, 0x84, - 0xe0, 0x3a, 0xf8, 0xae, 0x14, 0x17, 0x03, 0x01, - 0x00, 0x20, 0xba, 0x54, 0xef, 0x5b, 0xce, 0xfd, - 0x47, 0x76, 0x6d, 0xa1, 0x8b, 0xfd, 0x48, 0xde, - 0x6e, 0x26, 0xc1, 0x0c, 0x9d, 0x54, 0xbf, 0x98, - 0xf6, 0x1c, 0x80, 0xb9, 0xca, 0x93, 0x81, 0x0a, - 0x2e, 0x06, 0x15, 0x03, 0x01, 0x00, 0x20, 0x93, - 0x3e, 0x38, 0x17, 0xc9, 0x0a, 0xc3, 0xea, 0xd3, - 0x92, 0x75, 0xa6, 0x53, 0x37, 0x4d, 0x74, 0x94, - 0xbe, 0x01, 0xdc, 0x5c, 0x5a, 0x0f, 0x09, 0xf6, - 0x57, 0x33, 0xc3, 0xbc, 0x3f, 0x7a, 0x4d, - }, -} +func TestLRUClientSessionCache(t *testing.T) { + // Initialize cache of capacity 4. + cache := NewLRUClientSessionCache(4) + cs := make([]ClientSessionState, 6) + keys := []string{"0", "1", "2", "3", "4", "5", "6"} -var emptyRecordScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00, - 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x35, - 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, - 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, - 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00, - 0x46, 0x03, 0x01, 0x51, 0x71, 0x8e, 0x03, 0x02, - 0xef, 0x09, 0xf2, 0x0e, 0xf5, 0x3b, 0x29, 0x9a, - 0xa8, 0x8b, 0x46, 0xa3, 0xd4, 0xb4, 0xc1, 0x14, - 0xc3, 0x19, 0x99, 0xba, 0x3d, 0x78, 0xcf, 0x50, - 0xd1, 0xe7, 0x26, 0x20, 0xa0, 0x37, 0x6d, 0xc9, - 0xae, 0x93, 0x33, 0x81, 0x20, 0xe3, 0xc1, 0x90, - 0x64, 0x6e, 0x67, 0x93, 0xdb, 0xb4, 0x04, 0x16, - 0xc4, 0x25, 0xdd, 0x10, 0x79, 0x3c, 0x18, 0x0a, - 0x7c, 0xfd, 0x28, 0x65, 0x00, 0x35, 0x00, 0x16, - 0x03, 0x01, 0x09, 0x9e, 0x0b, 0x00, 0x09, 0x9a, - 0x00, 0x09, 0x97, 0x00, 0x04, 0xea, 0x30, 0x82, - 0x04, 0xe6, 0x30, 0x82, 0x03, 0xce, 0xa0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x11, 0x00, 0xff, 0xab, - 0x02, 0x93, 0xe0, 0x72, 0x99, 0x18, 0x6c, 0x9e, - 0x96, 0xb8, 0xb9, 0xf7, 0x47, 0xcb, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x41, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x09, 0x47, - 0x41, 0x4e, 0x44, 0x49, 0x20, 0x53, 0x41, 0x53, - 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x13, 0x15, 0x47, 0x61, 0x6e, 0x64, 0x69, - 0x20, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, - 0x64, 0x20, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41, - 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x31, - 0x31, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x31, 0x31, - 0x34, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, - 0x30, 0x62, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x13, 0x18, 0x44, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x20, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x20, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x31, 0x24, 0x30, - 0x22, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x1b, - 0x47, 0x61, 0x6e, 0x64, 0x69, 0x20, 0x53, 0x74, - 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, 0x57, - 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x20, - 0x53, 0x53, 0x4c, 0x31, 0x17, 0x30, 0x15, 0x06, - 0x03, 0x55, 0x04, 0x03, 0x14, 0x0e, 0x2a, 0x2e, - 0x66, 0x72, 0x65, 0x65, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x6e, 0x65, 0x74, 0x30, 0x82, 0x01, 0x22, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, - 0x02, 0x82, 0x01, 0x01, 0x00, 0xdc, 0xe3, 0xfd, - 0xce, 0xc1, 0x66, 0x62, 0x28, 0x8b, 0x99, 0x65, - 0x72, 0x52, 0x88, 0x93, 0x5b, 0x3f, 0x8d, 0xde, - 0x2b, 0xb0, 0xa0, 0xf4, 0xbd, 0xb4, 0x07, 0x5f, - 0x9e, 0x01, 0x47, 0x60, 0x57, 0x5f, 0xdf, 0xdc, - 0x63, 0x28, 0x1c, 0x1e, 0x5b, 0xc8, 0xe6, 0x29, - 0xdd, 0xeb, 0x26, 0x63, 0xd5, 0xbf, 0x83, 0xb2, - 0x2d, 0xcd, 0x2c, 0xa0, 0xb6, 0x91, 0xad, 0xaf, - 0x95, 0x21, 0x1d, 0x1f, 0x39, 0x8d, 0x3e, 0x17, - 0xd6, 0xbd, 0x99, 0xf5, 0x6c, 0xd4, 0xcb, 0x79, - 0x12, 0x3e, 0x11, 0xb9, 0x7e, 0x62, 0xbc, 0x2d, - 0xbf, 0xe0, 0x55, 0x1b, 0x5c, 0x1e, 0xce, 0x31, - 0xd9, 0xf8, 0x56, 0x68, 0x95, 0x2b, 0x15, 0x84, - 0x35, 0xae, 0x98, 0x2c, 0x63, 0x01, 0xb2, 0x0d, - 0xab, 0xa8, 0x61, 0xef, 0x7f, 0x15, 0x2c, 0x6d, - 0xf7, 0x67, 0x1d, 0xb8, 0x8d, 0xf6, 0xa2, 0x1c, - 0x4e, 0x85, 0xf0, 0xea, 0x1a, 0x2b, 0xc8, 0xac, - 0x70, 0x86, 0x9a, 0xbb, 0x9e, 0x9d, 0xbd, 0xc9, - 0x87, 0x2b, 0x9f, 0x5e, 0x40, 0x44, 0x9b, 0xba, - 0x96, 0x45, 0x24, 0xbc, 0x49, 0xb8, 0xfe, 0x26, - 0x3a, 0x1d, 0x1a, 0x0a, 0x3a, 0x90, 0x9c, 0x75, - 0x51, 0x59, 0x89, 0x98, 0x1a, 0x56, 0xe1, 0x3a, - 0x1a, 0xba, 0xff, 0xb4, 0x37, 0x7d, 0xd8, 0x99, - 0xe2, 0xeb, 0x45, 0x27, 0xe2, 0x42, 0x42, 0x46, - 0xbb, 0x00, 0x29, 0x9f, 0x30, 0xc9, 0x1e, 0x6c, - 0xce, 0x59, 0x0e, 0xbe, 0x16, 0x03, 0x31, 0xec, - 0x10, 0xc1, 0x6d, 0xca, 0x9d, 0x5f, 0x6d, 0xf1, - 0x26, 0x11, 0xe5, 0x50, 0xa1, 0xbb, 0x67, 0xb2, - 0xe0, 0x2b, 0xed, 0x76, 0x5b, 0xc7, 0x68, 0xc0, - 0x18, 0xad, 0x91, 0x9e, 0xb5, 0xd4, 0x4d, 0x21, - 0xcd, 0x98, 0xd9, 0xe0, 0x05, 0x0a, 0x4d, 0x24, - 0xa3, 0xe6, 0x12, 0x04, 0xdd, 0x50, 0xe6, 0xc8, - 0x7a, 0x69, 0xb9, 0x32, 0x43, 0x02, 0x03, 0x01, - 0x00, 0x01, 0xa3, 0x82, 0x01, 0xb6, 0x30, 0x82, - 0x01, 0xb2, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, - 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb6, - 0xa8, 0xff, 0xa2, 0xa8, 0x2f, 0xd0, 0xa6, 0xcd, - 0x4b, 0xb1, 0x68, 0xf3, 0xe7, 0x50, 0x10, 0x31, - 0xa7, 0x79, 0x21, 0x30, 0x1d, 0x06, 0x03, 0x55, - 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x62, 0x37, - 0xd4, 0x3c, 0xbf, 0xd9, 0xc2, 0x99, 0xf3, 0x28, - 0x3e, 0xdb, 0xca, 0xee, 0xf3, 0xb3, 0xc8, 0x73, - 0xb0, 0x3c, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, - 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, - 0x05, 0xa0, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, - 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, - 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, - 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, - 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, - 0x60, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x59, - 0x30, 0x57, 0x30, 0x4b, 0x06, 0x0b, 0x2b, 0x06, - 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, 0x02, - 0x1a, 0x30, 0x3c, 0x30, 0x3a, 0x06, 0x08, 0x2b, - 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, - 0x2e, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, - 0x77, 0x77, 0x77, 0x2e, 0x67, 0x61, 0x6e, 0x64, - 0x69, 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x2f, - 0x66, 0x72, 0x2f, 0x73, 0x73, 0x6c, 0x2f, 0x63, - 0x70, 0x73, 0x2f, 0x70, 0x64, 0x66, 0x2f, 0x30, - 0x08, 0x06, 0x06, 0x67, 0x81, 0x0c, 0x01, 0x02, - 0x01, 0x30, 0x3c, 0x06, 0x03, 0x55, 0x1d, 0x1f, - 0x04, 0x35, 0x30, 0x33, 0x30, 0x31, 0xa0, 0x2f, - 0xa0, 0x2d, 0x86, 0x2b, 0x68, 0x74, 0x74, 0x70, - 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x67, - 0x61, 0x6e, 0x64, 0x69, 0x2e, 0x6e, 0x65, 0x74, - 0x2f, 0x47, 0x61, 0x6e, 0x64, 0x69, 0x53, 0x74, - 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x53, 0x53, - 0x4c, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c, 0x30, - 0x6a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x01, 0x01, 0x04, 0x5e, 0x30, 0x5c, 0x30, - 0x37, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x30, 0x02, 0x86, 0x2b, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, 0x2e, - 0x67, 0x61, 0x6e, 0x64, 0x69, 0x2e, 0x6e, 0x65, - 0x74, 0x2f, 0x47, 0x61, 0x6e, 0x64, 0x69, 0x53, - 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x53, - 0x53, 0x4c, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, - 0x30, 0x21, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x30, 0x01, 0x86, 0x15, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, - 0x70, 0x2e, 0x67, 0x61, 0x6e, 0x64, 0x69, 0x2e, - 0x6e, 0x65, 0x74, 0x30, 0x27, 0x06, 0x03, 0x55, - 0x1d, 0x11, 0x04, 0x20, 0x30, 0x1e, 0x82, 0x0e, - 0x2a, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x82, 0x0c, - 0x66, 0x72, 0x65, 0x65, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x6e, 0x65, 0x74, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, - 0x5b, 0x4a, 0x3a, 0x1d, 0x75, 0xe0, 0xc0, 0x9e, - 0xc9, 0x16, 0x66, 0x7f, 0x73, 0x95, 0x6e, 0x35, - 0xe4, 0x27, 0xfa, 0x8c, 0x9d, 0xee, 0xb1, 0x37, - 0x42, 0x3f, 0x54, 0x6a, 0x9d, 0x41, 0x84, 0x57, - 0xe1, 0x03, 0x3d, 0x69, 0x61, 0x77, 0x3b, 0x91, - 0xa2, 0x70, 0x94, 0xb6, 0x8e, 0x41, 0x63, 0x70, - 0xf2, 0x16, 0x04, 0x50, 0x05, 0x14, 0xfb, 0x59, - 0x7d, 0x89, 0x09, 0x3f, 0xb6, 0xef, 0xca, 0x3c, - 0x89, 0x88, 0x08, 0xe9, 0xa1, 0xf3, 0x33, 0x31, - 0x05, 0x4d, 0x70, 0xff, 0xdd, 0xa7, 0xd2, 0xe2, - 0xa0, 0x94, 0x3a, 0xf7, 0xc2, 0x9f, 0xad, 0x2b, - 0x2e, 0x20, 0xfa, 0x6c, 0xe1, 0xfc, 0xe6, 0x62, - 0x22, 0xa1, 0x38, 0x93, 0xec, 0x3e, 0xce, 0xfd, - 0x1f, 0xdd, 0xd4, 0x7c, 0x39, 0x46, 0x8b, 0xb4, - 0x64, 0xfa, 0xa1, 0x46, 0x87, 0x78, 0x2c, 0xd7, - 0x9c, 0xdd, 0x60, 0xd6, 0xda, 0x8e, 0xd8, 0x29, - 0x6d, 0x61, 0xa7, 0x29, 0x07, 0x76, 0xfc, 0xf9, - 0xbd, 0xfd, 0x14, 0xeb, 0x44, 0x70, 0xff, 0xd0, - 0x23, 0x99, 0x83, 0xc5, 0x5c, 0x56, 0x88, 0xaa, - 0x34, 0xda, 0xa6, 0xb3, 0x9a, 0xbf, 0xda, 0x58, - 0x1e, 0xa4, 0xb8, 0xc0, 0x40, 0x9d, 0xf0, 0xfc, - 0xf1, 0x23, 0xc2, 0xbc, 0x59, 0xe1, 0x82, 0xed, - 0x5d, 0xfb, 0x99, 0xaf, 0xf5, 0xf5, 0x15, 0xb8, - 0x8b, 0x59, 0xce, 0xaa, 0xca, 0xdf, 0xdc, 0x94, - 0x11, 0xe0, 0x96, 0xbf, 0x9f, 0x54, 0xa4, 0x9f, - 0x54, 0x36, 0x4a, 0xe8, 0x93, 0xda, 0xf4, 0x8c, - 0xb0, 0x6b, 0x8d, 0x4a, 0x9e, 0x11, 0xae, 0xcb, - 0xcb, 0x33, 0x8a, 0x4d, 0xcd, 0x4e, 0xa5, 0x9b, - 0xe9, 0x14, 0x46, 0x43, 0x9b, 0x96, 0x5f, 0x6d, - 0xf2, 0xea, 0x40, 0xef, 0x14, 0xc3, 0x99, 0x9f, - 0x23, 0x1e, 0xa5, 0x13, 0xab, 0x08, 0xea, 0x8f, - 0x68, 0x5b, 0x7d, 0x71, 0xdf, 0x18, 0xd1, 0x57, - 0x00, 0x04, 0xa7, 0x30, 0x82, 0x04, 0xa3, 0x30, - 0x82, 0x03, 0x8b, 0xa0, 0x03, 0x02, 0x01, 0x02, - 0x02, 0x10, 0x5a, 0xb6, 0x1d, 0xac, 0x1e, 0x4d, - 0xa2, 0x06, 0x14, 0xc7, 0x55, 0x3d, 0x3d, 0xa9, - 0xb2, 0xdc, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, - 0x00, 0x30, 0x81, 0x97, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, - 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, - 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, - 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, - 0x6b, 0x65, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, - 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, - 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, - 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, - 0x13, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, - 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, 0x65, - 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, - 0x6f, 0x6d, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, 0x4e, - 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, - 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, 0x77, - 0x61, 0x72, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x30, - 0x38, 0x31, 0x30, 0x32, 0x33, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x30, - 0x30, 0x35, 0x33, 0x30, 0x31, 0x30, 0x34, 0x38, - 0x33, 0x38, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x13, 0x09, 0x47, 0x41, 0x4e, - 0x44, 0x49, 0x20, 0x53, 0x41, 0x53, 0x31, 0x1e, - 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, - 0x15, 0x47, 0x61, 0x6e, 0x64, 0x69, 0x20, 0x53, - 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x20, - 0x53, 0x53, 0x4c, 0x20, 0x43, 0x41, 0x30, 0x82, - 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, - 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, - 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb6, - 0x54, 0x3d, 0xa5, 0xdb, 0x0d, 0x22, 0x78, 0x50, - 0x6a, 0x5a, 0x23, 0x89, 0x3f, 0x97, 0xa1, 0xd4, - 0x07, 0x1a, 0xa9, 0x58, 0x08, 0x9b, 0xa0, 0x15, - 0xc3, 0x32, 0xb6, 0xb7, 0xf1, 0xe8, 0xb9, 0xa5, - 0x6f, 0xad, 0x37, 0xf6, 0x6e, 0x71, 0x1b, 0xb4, - 0x75, 0x2d, 0x48, 0x5e, 0x9f, 0xc6, 0x15, 0xaa, - 0x81, 0xef, 0xe5, 0xc4, 0x88, 0x95, 0x8a, 0x3a, - 0x6c, 0x77, 0xcc, 0xb5, 0xcd, 0x65, 0xe4, 0x67, - 0xe5, 0x73, 0xc9, 0x50, 0x52, 0x94, 0xc1, 0x27, - 0x49, 0x3e, 0xa0, 0x6b, 0x41, 0x16, 0x41, 0xb6, - 0x94, 0x99, 0x41, 0xae, 0x3e, 0xcb, 0xe2, 0x06, - 0x46, 0x09, 0xe9, 0x4d, 0xbe, 0xc9, 0x4c, 0x55, - 0xa9, 0x18, 0x7e, 0xa6, 0xdf, 0x6e, 0xfd, 0x4a, - 0xb2, 0xcc, 0x6c, 0x4e, 0xd9, 0xc8, 0x50, 0x15, - 0x93, 0xb3, 0xf2, 0xe9, 0xe3, 0xc2, 0x6a, 0xad, - 0x3a, 0xd5, 0xfb, 0xc3, 0x79, 0x50, 0x9f, 0x25, - 0x79, 0x29, 0xb2, 0x47, 0x64, 0x7c, 0x20, 0x3e, - 0xe2, 0x08, 0x4d, 0x93, 0x29, 0x14, 0xb6, 0x34, - 0x6e, 0xcf, 0x71, 0x46, 0x7e, 0x76, 0x10, 0xf4, - 0xfd, 0x6c, 0xaa, 0x01, 0xd2, 0xc2, 0x06, 0xde, - 0x92, 0x83, 0xcc, 0x58, 0x90, 0x2e, 0x92, 0xde, - 0x1e, 0x65, 0xb7, 0x63, 0x2f, 0x3d, 0xb2, 0xeb, - 0x70, 0x8c, 0x4c, 0xe0, 0xbe, 0x15, 0x9d, 0xde, - 0xc1, 0x4d, 0x56, 0xf8, 0x0b, 0xc6, 0x8e, 0x07, - 0xb9, 0x5d, 0xdf, 0x95, 0xf0, 0x7b, 0x40, 0x1f, - 0x1a, 0x2c, 0xd7, 0x9c, 0x2b, 0x4b, 0x76, 0xf4, - 0x59, 0xf5, 0x43, 0xc1, 0x2c, 0x66, 0x10, 0x9e, - 0x9e, 0x66, 0x96, 0x60, 0x9d, 0x1c, 0x74, 0x1b, - 0x4e, 0x18, 0x5c, 0x08, 0xb0, 0x6e, 0x6c, 0xca, - 0x69, 0x1a, 0x02, 0xe9, 0xbb, 0xca, 0x78, 0xef, - 0x66, 0x2e, 0xe3, 0x32, 0xfd, 0x41, 0x5c, 0x95, - 0x74, 0x81, 0x4d, 0xf4, 0xda, 0xfe, 0x4b, 0x02, - 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x3e, - 0x30, 0x82, 0x01, 0x3a, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, - 0x14, 0xa1, 0x72, 0x5f, 0x26, 0x1b, 0x28, 0x98, - 0x43, 0x95, 0x5d, 0x07, 0x37, 0xd5, 0x85, 0x96, - 0x9d, 0x4b, 0xd2, 0xc3, 0x45, 0x30, 0x1d, 0x06, - 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, - 0xb6, 0xa8, 0xff, 0xa2, 0xa8, 0x2f, 0xd0, 0xa6, - 0xcd, 0x4b, 0xb1, 0x68, 0xf3, 0xe7, 0x50, 0x10, - 0x31, 0xa7, 0x79, 0x21, 0x30, 0x0e, 0x06, 0x03, - 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, - 0x03, 0x02, 0x01, 0x06, 0x30, 0x12, 0x06, 0x03, - 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, - 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, - 0x30, 0x18, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, - 0x11, 0x30, 0x0f, 0x30, 0x0d, 0x06, 0x0b, 0x2b, - 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x01, 0x02, - 0x02, 0x1a, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, - 0x1f, 0x04, 0x3d, 0x30, 0x3b, 0x30, 0x39, 0xa0, - 0x37, 0xa0, 0x35, 0x86, 0x33, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, - 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, - 0x72, 0x73, 0x74, 0x2d, 0x48, 0x61, 0x72, 0x64, - 0x77, 0x61, 0x72, 0x65, 0x2e, 0x63, 0x72, 0x6c, - 0x30, 0x74, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x01, 0x01, 0x04, 0x68, 0x30, 0x66, - 0x30, 0x3d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, - 0x05, 0x07, 0x30, 0x02, 0x86, 0x31, 0x68, 0x74, - 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x74, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, - 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, - 0x54, 0x4e, 0x41, 0x64, 0x64, 0x54, 0x72, 0x75, - 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x5f, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, - 0x25, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, - 0x07, 0x30, 0x01, 0x86, 0x19, 0x68, 0x74, 0x74, - 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, - 0x2e, 0x75, 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, - 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, - 0x01, 0x00, 0x19, 0x53, 0xbf, 0x03, 0x3d, 0x9b, - 0xe2, 0x6b, 0x5a, 0xfd, 0xba, 0x49, 0x1f, 0x4f, - 0xec, 0xe1, 0xc6, 0x82, 0x39, 0x3c, 0xd2, 0x03, - 0x04, 0x0f, 0xab, 0x7b, 0x3e, 0x82, 0xa9, 0x85, - 0x10, 0x1f, 0xf4, 0xde, 0x32, 0xaf, 0x58, 0x3f, - 0xff, 0x70, 0xf3, 0x30, 0x1d, 0x97, 0x2d, 0x4c, - 0x9a, 0xe2, 0xec, 0x0c, 0x3e, 0x14, 0x2d, 0x2f, - 0x98, 0x48, 0x9d, 0xae, 0x16, 0x6a, 0xac, 0x2d, - 0x42, 0xaa, 0xb5, 0x64, 0xa4, 0x70, 0xbb, 0xeb, - 0x73, 0x94, 0x7b, 0x46, 0x4c, 0xe7, 0x7a, 0x14, - 0x76, 0x5b, 0x4c, 0x1d, 0x84, 0xa1, 0x20, 0x74, - 0x1f, 0x2e, 0x4b, 0x5c, 0x70, 0x88, 0xdc, 0xbd, - 0xf7, 0x19, 0x3d, 0xed, 0x59, 0x0d, 0xe2, 0x3f, - 0x26, 0xe2, 0x9c, 0xac, 0xa4, 0x3c, 0x95, 0x1c, - 0xf8, 0xbe, 0x8c, 0x03, 0xae, 0xf0, 0xe5, 0x9c, - 0x4d, 0xbc, 0xc7, 0x9b, 0x58, 0x00, 0xbf, 0xaf, - 0xad, 0xfa, 0x37, 0x6e, 0x71, 0x6d, 0x18, 0x34, - 0x0e, 0xc1, 0xea, 0x6a, 0xf8, 0x0d, 0xdf, 0x69, - 0x54, 0x56, 0x15, 0xf2, 0x28, 0xb3, 0xfe, 0xa4, - 0x63, 0xec, 0xc5, 0x04, 0x64, 0x60, 0xbb, 0xfe, - 0x2a, 0xf0, 0xf4, 0x87, 0xa1, 0xb0, 0xae, 0xbd, - 0xaa, 0xe4, 0x2f, 0xe3, 0x03, 0x0b, 0x2f, 0x66, - 0x5f, 0x85, 0xa4, 0x32, 0x7b, 0x46, 0xed, 0x25, - 0x0c, 0xe7, 0xf1, 0xb7, 0xe7, 0x19, 0xfd, 0x60, - 0xba, 0x5f, 0x87, 0x77, 0xde, 0x98, 0x07, 0x96, - 0xe4, 0x5e, 0xea, 0x63, 0x7d, 0xa8, 0xde, 0x55, - 0xda, 0x61, 0x5c, 0x3c, 0x90, 0x83, 0x43, 0x04, - 0x07, 0x3c, 0xdd, 0xf3, 0xf8, 0x9f, 0x06, 0x52, - 0x0a, 0xde, 0xc7, 0xb6, 0x7b, 0x8f, 0xe1, 0x11, - 0xf7, 0x04, 0x7a, 0x35, 0xff, 0x6a, 0xbc, 0x5b, - 0xc7, 0x50, 0x49, 0x08, 0x70, 0x6f, 0x94, 0x43, - 0xcd, 0x9e, 0xc7, 0x70, 0xf1, 0xdb, 0xd0, 0x6d, - 0xda, 0x8f, 0x16, 0x03, 0x01, 0x00, 0x0e, 0x0d, - 0x00, 0x00, 0x06, 0x03, 0x01, 0x02, 0x40, 0x00, - 0x00, 0x0e, 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, - 0xba, 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, - 0x82, 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, - 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, - 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, - 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, - 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, - 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, - 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, - 0x39, 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, - 0x31, 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, - 0x30, 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, - 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, - 0x00, 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, - 0xbf, 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, - 0x2b, 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, - 0x7a, 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, - 0x65, 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, - 0xb4, 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, - 0x62, 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, - 0x5c, 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, - 0x58, 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, - 0xd0, 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, - 0x9f, 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, - 0x18, 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, - 0xf1, 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, - 0xc9, 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, - 0x01, 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, - 0x1d, 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, - 0x79, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, - 0xa7, 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, - 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, - 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, - 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, - 0x18, 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, - 0x1d, 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, - 0xb1, 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, - 0xdb, 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, - 0x8e, 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, - 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, - 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, - 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, - 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, - 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, - 0xb8, 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, - 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, - 0x81, 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, - 0x6b, 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, - 0xb0, 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, - 0xb5, 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, - 0xae, 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, - 0x6e, 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, - 0xb5, 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, - 0x30, 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, - 0xe7, 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, - 0x78, 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, - 0x2d, 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, - 0x75, 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, - 0xcd, 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, - 0x1c, 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, - 0x57, 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, - 0x9b, 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, - 0xa7, 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x01, 0x06, - 0x10, 0x00, 0x01, 0x02, 0x01, 0x00, 0x25, 0x48, - 0x6c, 0x0a, 0xde, 0x9d, 0x3a, 0x57, 0xe4, 0x2e, - 0xb9, 0xfc, 0xb4, 0x46, 0x1f, 0x20, 0x4f, 0x58, - 0x4d, 0x12, 0x08, 0xb4, 0x3e, 0x4c, 0xf5, 0xa8, - 0xa5, 0x16, 0x40, 0x29, 0x19, 0x04, 0x4d, 0xf9, - 0x54, 0x3a, 0x32, 0xd7, 0x79, 0xf2, 0x0e, 0xc1, - 0x7b, 0x0c, 0x62, 0x71, 0xbb, 0xb4, 0x8c, 0xe7, - 0x84, 0xd5, 0xf8, 0x11, 0x77, 0x7f, 0x87, 0x6c, - 0xfc, 0x25, 0xf3, 0x2d, 0x97, 0x3d, 0x1f, 0xf5, - 0xfc, 0x64, 0x94, 0x9f, 0xdd, 0x90, 0x82, 0xdd, - 0x11, 0x74, 0x74, 0x59, 0xa2, 0x1a, 0x71, 0xb2, - 0x55, 0x6d, 0x18, 0xca, 0x85, 0x47, 0x8b, 0x79, - 0x73, 0x06, 0x24, 0x38, 0xc3, 0x34, 0x98, 0x84, - 0x62, 0x81, 0xd8, 0xad, 0x54, 0xad, 0x13, 0xa5, - 0xf4, 0xe4, 0x82, 0x85, 0xd3, 0xe3, 0x9e, 0xeb, - 0xb5, 0xf5, 0x95, 0x83, 0x0e, 0xb9, 0x7d, 0xb6, - 0xda, 0x0c, 0xf6, 0x14, 0x6a, 0x60, 0x8c, 0x75, - 0x56, 0xf0, 0xe9, 0x60, 0xe0, 0x4c, 0xf4, 0x4e, - 0x84, 0x8b, 0x4f, 0xf4, 0x2f, 0xde, 0xb7, 0xec, - 0x61, 0xd3, 0x77, 0x07, 0x6e, 0x41, 0x57, 0xc9, - 0xd9, 0x1d, 0x75, 0xee, 0x42, 0x63, 0xdc, 0x58, - 0xad, 0xfc, 0xc7, 0xe1, 0x77, 0x49, 0xb1, 0x58, - 0x21, 0x96, 0x00, 0x55, 0x90, 0x6b, 0xf6, 0x2a, - 0x5a, 0x19, 0x25, 0x93, 0x59, 0x9d, 0xaf, 0x79, - 0x9b, 0x18, 0x5d, 0xf6, 0x5d, 0x64, 0x4b, 0x9a, - 0xf4, 0xde, 0xf2, 0x7f, 0xbd, 0x93, 0x7e, 0x45, - 0x3e, 0x17, 0xae, 0xbf, 0x52, 0xe1, 0xba, 0x8e, - 0x0b, 0xbc, 0x1e, 0x91, 0x9d, 0xf1, 0x4e, 0x0b, - 0xab, 0x9e, 0x5c, 0x4c, 0x6f, 0xf7, 0xf3, 0x8d, - 0x8c, 0x6d, 0xeb, 0x46, 0x05, 0x36, 0x7e, 0x2f, - 0x9c, 0xa1, 0x86, 0x15, 0xe1, 0xe4, 0xb4, 0x20, - 0x06, 0x44, 0x7b, 0x3c, 0x8b, 0x13, 0x96, 0xf5, - 0x02, 0xb1, 0x4f, 0x3c, 0x2d, 0x4a, 0x16, 0x03, - 0x01, 0x00, 0x86, 0x0f, 0x00, 0x00, 0x82, 0x00, - 0x80, 0x52, 0xb1, 0x0d, 0xfc, 0x85, 0x34, 0x56, - 0xb9, 0xdf, 0xa7, 0x8e, 0xf4, 0xfd, 0x02, 0x46, - 0x8a, 0x23, 0xcc, 0x53, 0x3b, 0x0f, 0xa7, 0x61, - 0xf3, 0xb5, 0xbf, 0xfe, 0x59, 0x77, 0x10, 0xd6, - 0x56, 0x93, 0x19, 0x6b, 0x2c, 0xf1, 0x35, 0x71, - 0xe3, 0x36, 0x2f, 0xa0, 0x90, 0x4e, 0x5a, 0xdf, - 0x8d, 0x06, 0x88, 0xcf, 0xb1, 0x06, 0x56, 0x8b, - 0x74, 0x8f, 0x02, 0x8e, 0x10, 0xd2, 0xab, 0x8d, - 0x3f, 0x3e, 0x02, 0xf1, 0x1a, 0x80, 0x6d, 0x0f, - 0x9e, 0x77, 0xd8, 0xfa, 0x92, 0xb3, 0x16, 0x40, - 0xeb, 0x9e, 0xca, 0xd7, 0xe4, 0x31, 0xcc, 0x63, - 0x5f, 0xe2, 0x4c, 0x85, 0x0e, 0xf2, 0xdd, 0xd3, - 0xfe, 0x7e, 0xa7, 0x60, 0x1c, 0xb4, 0x00, 0xd8, - 0xbe, 0x4b, 0x9b, 0x66, 0x78, 0x0f, 0xfb, 0x3b, - 0x52, 0x30, 0x2b, 0x8b, 0xd9, 0xef, 0x82, 0x0a, - 0xa4, 0x18, 0x1d, 0xb0, 0xb5, 0xbf, 0x54, 0x97, - 0x0c, 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, - 0x03, 0x01, 0x00, 0x30, 0xa1, 0x74, 0x22, 0xd8, - 0x86, 0x6a, 0xbe, 0x53, 0x34, 0x1d, 0xb3, 0x73, - 0xff, 0x51, 0xc0, 0xce, 0x8e, 0x7d, 0x9b, 0xab, - 0xcb, 0x8b, 0x79, 0xae, 0x04, 0x01, 0xa7, 0xf2, - 0x8e, 0x9d, 0xab, 0xa3, 0x73, 0x80, 0x5c, 0xff, - 0x96, 0x20, 0xbb, 0x8d, 0xc0, 0x02, 0x66, 0x6c, - 0x83, 0x4b, 0x78, 0x20, - }, - { - 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x01, 0x00, 0x30, 0x29, 0xd4, 0xfd, 0x03, 0x8b, - 0x30, 0x20, 0xf7, 0xca, 0xc0, 0x6c, 0x83, 0x5d, - 0x73, 0xcb, 0x81, 0x60, 0xe0, 0x9a, 0x09, 0xcb, - 0x33, 0x03, 0x80, 0x81, 0x4e, 0x84, 0x47, 0xd5, - 0x74, 0x6c, 0x3b, 0xb5, 0xc0, 0x48, 0x0d, 0x52, - 0xdd, 0xbe, 0xc2, 0x06, 0xf5, 0x79, 0x2b, 0x3e, - 0x99, 0x56, 0x94, 0x17, 0x03, 0x01, 0x00, 0x20, - 0x26, 0x46, 0x90, 0x9d, 0xef, 0x59, 0x00, 0xb6, - 0x70, 0xe8, 0x1e, 0x1a, 0x80, 0x8b, 0x04, 0xb2, - 0xfc, 0x51, 0xf8, 0x93, 0xbe, 0x00, 0x28, 0xba, - 0xb8, 0xdc, 0x51, 0x7e, 0x92, 0x80, 0xfa, 0xf2, - 0x17, 0x03, 0x01, 0x00, 0xe0, 0xb8, 0x2e, 0xc4, - 0x6b, 0x3f, 0xda, 0x39, 0x87, 0x7f, 0x03, 0x43, - 0x28, 0xdd, 0xb9, 0xf9, 0x9e, 0x16, 0xf5, 0xce, - 0x3f, 0x7e, 0x6a, 0x7b, 0xb3, 0x60, 0x14, 0xe1, - 0xea, 0x54, 0xc5, 0xe6, 0x05, 0x0a, 0x6c, 0xe0, - 0xef, 0x58, 0x29, 0x8a, 0x77, 0x64, 0x77, 0x5d, - 0x9c, 0xe2, 0xe0, 0x3c, 0x6d, 0x87, 0x82, 0xbe, - 0x47, 0x63, 0xd4, 0xfd, 0x0c, 0x25, 0xc4, 0xb1, - 0xfe, 0x29, 0x6f, 0x84, 0xfb, 0xab, 0x6e, 0xa7, - 0xf9, 0x22, 0x89, 0x97, 0x5b, 0x91, 0x0a, 0x07, - 0xe0, 0xef, 0x3d, 0x67, 0xee, 0x87, 0xa8, 0x33, - 0x02, 0x64, 0x33, 0xca, 0x15, 0x10, 0xb9, 0x57, - 0xd8, 0xe5, 0x1a, 0x4b, 0xe3, 0x45, 0xc1, 0x62, - 0x85, 0x50, 0xf1, 0x79, 0x54, 0xe1, 0x2e, 0x25, - 0x01, 0x3c, 0xdb, 0x2d, 0x39, 0x14, 0x2f, 0x9b, - 0xd0, 0x1d, 0xc1, 0xac, 0x73, 0x7d, 0xa4, 0xed, - 0x89, 0x98, 0xb1, 0xae, 0x8a, 0x9e, 0xc8, 0xa7, - 0xfe, 0x55, 0x27, 0xb5, 0xb5, 0xa2, 0xec, 0x7e, - 0xe3, 0x6b, 0x45, 0x19, 0xfa, 0x20, 0x1c, 0x33, - 0x83, 0x22, 0x33, 0x97, 0xd2, 0x5a, 0xc4, 0xf8, - 0x9a, 0x03, 0x13, 0x85, 0xf2, 0x2b, 0x04, 0x59, - 0x27, 0xd7, 0x0b, 0x42, 0x47, 0x9b, 0x7d, 0x4d, - 0xb2, 0x1a, 0x85, 0x7f, 0x97, 0xc2, 0xf2, 0x10, - 0xf0, 0xfa, 0x4e, 0x4b, 0x62, 0x43, 0x3a, 0x09, - 0x2e, 0xcd, 0x8f, 0xa8, 0xb6, 0x0b, 0x5f, 0x34, - 0xd7, 0x3b, 0xba, 0xd9, 0xe5, 0x01, 0x2d, 0x35, - 0xae, 0xc5, 0x4c, 0xab, 0x40, 0x64, 0xc2, 0xc9, - 0x8c, 0x69, 0x44, 0xf4, 0xb8, 0xb5, 0x3a, 0x05, - 0x3c, 0x29, 0x19, 0xb4, 0x09, 0x17, 0x03, 0x01, - 0x00, 0x20, 0xc8, 0xc5, 0xb7, 0xe3, 0xd2, 0x3e, - 0x27, 0xb5, 0x71, 0x8f, 0x52, 0x0b, 0xce, 0x17, - 0x64, 0x86, 0xa4, 0x34, 0x16, 0x1b, 0x61, 0x64, - 0x7c, 0xb3, 0xf2, 0xe5, 0x3e, 0xfd, 0xdd, 0xfb, - 0x40, 0x78, 0x17, 0x03, 0x01, 0x00, 0x50, 0x8e, - 0x79, 0xf0, 0x8e, 0x76, 0x5d, 0x34, 0x09, 0xdc, - 0xec, 0x6d, 0xc3, 0x43, 0x1d, 0xcb, 0x2d, 0xaa, - 0x08, 0x7a, 0x51, 0x94, 0x4e, 0xc5, 0x26, 0xe4, - 0x0b, 0x8e, 0x8f, 0x51, 0xf2, 0x9f, 0xeb, 0xc3, - 0x18, 0x43, 0x95, 0x15, 0xfc, 0x59, 0x18, 0x25, - 0x47, 0xb6, 0x4a, 0x6e, 0xa3, 0xa4, 0x3b, 0xa3, - 0x47, 0x34, 0x74, 0x6b, 0xc5, 0x3d, 0x41, 0x14, - 0x64, 0xd5, 0x69, 0x5f, 0x77, 0xf3, 0x7c, 0x41, - 0xc6, 0xed, 0x2e, 0xcf, 0xff, 0x40, 0xf2, 0xce, - 0xbb, 0xa7, 0x4e, 0x73, 0x88, 0x98, 0x10, - }, - { - 0x15, 0x03, 0x01, 0x00, 0x20, 0x1a, 0xbc, 0x70, - 0x24, 0xf8, 0xfb, 0xf2, 0x4a, 0xf9, 0x44, 0x1e, - 0x58, 0xf8, 0xaa, 0x41, 0x24, 0xe8, 0x80, 0x33, - 0x45, 0x18, 0xa1, 0x5d, 0xee, 0x16, 0x80, 0xae, - 0x40, 0x41, 0x8e, 0x41, 0x9b, - }, -} + // Add 4 entries to the cache and look them up. + for i := 0; i < 4; i++ { + cache.Put(keys[i], &cs[i]) + } + for i := 0; i < 4; i++ { + if s, ok := cache.Get(keys[i]); !ok || s != &cs[i] { + t.Fatalf("session cache failed lookup for added key: %s", keys[i]) + } + } -var tls11ECDHEAESClientScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00, - 0x46, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x13, - 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, - 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, - 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, - }, - { - 0x16, 0x03, 0x02, 0x00, 0x54, 0x02, 0x00, 0x00, - 0x50, 0x03, 0x02, 0x51, 0x9f, 0xa2, 0x21, 0x1a, - 0xb7, 0x75, 0x42, 0x69, 0xd3, 0x14, 0xdd, 0x05, - 0x1e, 0xda, 0x13, 0x71, 0x8d, 0x6a, 0x45, 0x97, - 0xcb, 0xee, 0x0e, 0x77, 0x01, 0x0d, 0x6e, 0xe5, - 0x22, 0x70, 0x16, 0x20, 0x69, 0xfc, 0xa6, 0x9a, - 0xe8, 0x21, 0xcc, 0x46, 0x65, 0x05, 0xb4, 0x48, - 0x0f, 0x34, 0x63, 0x2c, 0xac, 0xa4, 0xf5, 0x4b, - 0x64, 0xd1, 0x07, 0x13, 0xa7, 0xe4, 0x5b, 0xa3, - 0x4d, 0x31, 0x41, 0x53, 0xc0, 0x13, 0x00, 0x00, - 0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01, - 0x02, 0x16, 0x03, 0x02, 0x02, 0x39, 0x0b, 0x00, - 0x02, 0x35, 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f, - 0x30, 0x82, 0x02, 0x2b, 0x30, 0x82, 0x01, 0xd5, - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, - 0xb1, 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, - 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, - 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, - 0x17, 0x0d, 0x31, 0x32, 0x30, 0x34, 0x30, 0x36, - 0x31, 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x17, - 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30, 0x36, 0x31, - 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x30, 0x45, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, - 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, - 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, - 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, - 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x5c, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, - 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0x9f, 0xb3, - 0xc3, 0x84, 0x27, 0x95, 0xff, 0x12, 0x31, 0x52, - 0x0f, 0x15, 0xef, 0x46, 0x11, 0xc4, 0xad, 0x80, - 0xe6, 0x36, 0x5b, 0x0f, 0xdd, 0x80, 0xd7, 0x61, - 0x8d, 0xe0, 0xfc, 0x72, 0x45, 0x09, 0x34, 0xfe, - 0x55, 0x66, 0x45, 0x43, 0x4c, 0x68, 0x97, 0x6a, - 0xfe, 0xa8, 0xa0, 0xa5, 0xdf, 0x5f, 0x78, 0xff, - 0xee, 0xd7, 0x64, 0xb8, 0x3f, 0x04, 0xcb, 0x6f, - 0xff, 0x2a, 0xfe, 0xfe, 0xb9, 0xed, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, - 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0x78, 0xa6, 0x97, 0x9a, - 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22, - 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b, - 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x6e, 0x30, 0x6c, 0x80, 0x14, 0x78, 0xa6, 0x97, - 0x9a, 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, - 0x22, 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, - 0x2b, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0xb1, - 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x85, - 0x36, 0x40, 0x73, 0xc1, 0xbb, 0x1a, 0xda, 0xd4, - 0x59, 0x9f, 0x2d, 0xa2, 0x70, 0x31, 0x46, 0x74, - 0xec, 0x83, 0x6e, 0xa8, 0xc8, 0x3c, 0x51, 0xaf, - 0x39, 0xac, 0xec, 0x40, 0xbc, 0xe8, 0x22, 0x46, - 0x1d, 0x99, 0xd6, 0x46, 0x2a, 0x24, 0xd4, 0x8b, - 0x05, 0x08, 0x4b, 0xfb, 0x35, 0x11, 0x6e, 0x92, - 0xbb, 0x77, 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8, - 0x5e, 0x9c, 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16, - 0x03, 0x02, 0x00, 0x8b, 0x0c, 0x00, 0x00, 0x87, - 0x03, 0x00, 0x17, 0x41, 0x04, 0x34, 0xde, 0x50, - 0x32, 0x8f, 0x25, 0x6b, 0x37, 0x2c, 0x36, 0x24, - 0x27, 0x0e, 0xf9, 0x67, 0xb4, 0xf8, 0x29, 0x1c, - 0xa5, 0xa4, 0x59, 0x9a, 0xca, 0x40, 0x26, 0x15, - 0x61, 0x72, 0x34, 0x4a, 0xd3, 0x0c, 0xac, 0x69, - 0xcb, 0x2a, 0x9e, 0xf8, 0x80, 0xfb, 0x7a, 0xc4, - 0xd4, 0x4b, 0x91, 0x1b, 0xbe, 0x24, 0x26, 0xad, - 0x19, 0x24, 0xbe, 0x32, 0x58, 0xfb, 0xc7, 0x77, - 0xce, 0x7e, 0x71, 0x51, 0x1a, 0x00, 0x40, 0x1a, - 0x0b, 0xe8, 0x91, 0x84, 0x64, 0x54, 0xb6, 0x19, - 0xe8, 0xd4, 0x43, 0x7c, 0x09, 0x0c, 0x2e, 0xba, - 0x42, 0xb9, 0x74, 0xc3, 0x6c, 0x06, 0x9b, 0xa6, - 0x7e, 0x92, 0xe9, 0xee, 0x7c, 0x74, 0xa9, 0xd3, - 0x63, 0xf0, 0x16, 0x20, 0x60, 0x71, 0x8e, 0x24, - 0xc7, 0x7f, 0xc5, 0x5b, 0x9c, 0x19, 0x0c, 0x80, - 0x15, 0x61, 0xbf, 0xb6, 0xed, 0x5b, 0x7b, 0x90, - 0xc5, 0x05, 0x13, 0x72, 0x45, 0x79, 0xdf, 0x16, - 0x03, 0x02, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x02, 0x00, 0x46, 0x10, 0x00, 0x00, - 0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d, - 0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5, - 0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd, - 0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce, - 0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e, - 0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56, - 0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49, - 0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b, - 0xdc, 0x5a, 0x89, 0x14, 0x03, 0x02, 0x00, 0x01, - 0x01, 0x16, 0x03, 0x02, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x50, - 0x32, 0x26, 0x51, 0xbd, 0xbd, 0x3c, 0x4f, 0x72, - 0xbf, 0xbc, 0x91, 0x70, 0x4b, 0x5d, 0x43, 0x4a, - 0x65, 0x26, 0x0d, 0xaa, 0xed, 0x00, 0x91, 0xaf, - 0x4f, 0x47, 0x09, 0xaa, 0x79, 0xc4, 0x47, 0x21, - 0x71, 0xd8, 0x2b, 0xc1, 0x51, 0xc8, 0xef, 0xed, - 0x67, 0xde, 0x97, 0xef, 0x18, 0x53, - }, - { - 0x14, 0x03, 0x02, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x02, 0x00, 0x40, 0x72, 0x20, 0xbf, 0xd1, 0xbd, - 0x83, 0x53, 0x57, 0xb0, 0x4e, 0xac, 0xba, 0x1a, - 0x2b, 0x2d, 0xeb, 0x8a, 0x48, 0x17, 0xfa, 0x69, - 0xf9, 0xb5, 0x94, 0x8e, 0x6f, 0x9c, 0xda, 0x59, - 0xba, 0x6c, 0x7c, 0x82, 0xe2, 0x53, 0xa9, 0x46, - 0xdc, 0x33, 0xa0, 0x9b, 0xf0, 0x1e, 0xf1, 0x53, - 0x83, 0x48, 0xbf, 0x5e, 0xef, 0x03, 0x2b, 0x50, - 0x7a, 0xa6, 0xf8, 0xc3, 0x9e, 0x24, 0x43, 0x3a, - 0xdf, 0x44, 0x3e, - }, - { - 0x17, 0x03, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x0b, 0x8f, - 0x6b, 0xf9, 0xd3, 0x9f, 0x2b, 0x49, 0xe0, 0x62, - 0x9a, 0x0b, 0x3e, 0xa2, 0x72, 0x8b, 0x96, 0x0c, - 0x41, 0x09, 0x95, 0x9e, 0x6b, 0x26, 0xa1, 0x46, - 0xca, 0xb8, 0xb6, 0xd2, 0xd4, 0x15, 0x03, 0x02, - 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xa0, 0xd4, 0x84, 0xc6, 0x7e, 0x1c, - 0x2f, 0xbd, 0x6b, 0x45, 0x31, 0x1d, 0x7d, 0x8f, - 0x31, 0x39, 0x5a, 0x4e, 0xaa, 0xf1, 0x0a, 0x8a, - 0x6c, 0x33, 0x59, 0x19, 0xd8, 0x75, 0x80, 0xab, - 0x93, 0x81, - }, -} + // Add 2 more entries to the cache. First 2 should be evicted. + for i := 4; i < 6; i++ { + cache.Put(keys[i], &cs[i]) + } + for i := 0; i < 2; i++ { + if s, ok := cache.Get(keys[i]); ok || s != nil { + t.Fatalf("session cache should have evicted key: %s", keys[i]) + } + } -var clientChainCertificateScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00, - 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, - 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, - 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00, - 0x46, 0x03, 0x01, 0x51, 0xa2, 0x9b, 0x8b, 0xd4, - 0xe6, 0x33, 0xa2, 0x70, 0x38, 0x37, 0xba, 0x55, - 0x86, 0xcf, 0x87, 0xea, 0x6d, 0x2c, 0x3e, 0x17, - 0xc2, 0x09, 0xf8, 0x4d, 0xb0, 0x5d, 0x93, 0x2b, - 0x15, 0x99, 0x0c, 0x20, 0x5d, 0x61, 0x21, 0x2c, - 0xed, 0x49, 0x32, 0x29, 0x08, 0x6e, 0x21, 0x58, - 0x00, 0xdb, 0x34, 0xb7, 0x37, 0xcd, 0x27, 0x75, - 0x31, 0x1e, 0x6c, 0x74, 0xa6, 0xef, 0xa2, 0xc4, - 0x2b, 0x6c, 0xc3, 0x03, 0x00, 0x05, 0x00, 0x16, - 0x03, 0x01, 0x03, 0xef, 0x0b, 0x00, 0x03, 0xeb, - 0x00, 0x03, 0xe8, 0x00, 0x03, 0xe5, 0x30, 0x82, - 0x03, 0xe1, 0x30, 0x82, 0x02, 0xc9, 0xa0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xcc, 0x22, - 0x4c, 0x4b, 0x98, 0xa2, 0x88, 0xfc, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x86, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, - 0x4e, 0x59, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, - 0x55, 0x04, 0x07, 0x0c, 0x08, 0x42, 0x72, 0x6f, - 0x6f, 0x6b, 0x6c, 0x79, 0x6e, 0x31, 0x21, 0x30, - 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, - 0x4d, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x0c, 0x08, 0x6d, 0x79, 0x63, 0x61, 0x2e, - 0x6f, 0x72, 0x67, 0x31, 0x21, 0x30, 0x1f, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x01, 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, - 0x61, 0x68, 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, - 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, - 0x17, 0x0d, 0x31, 0x33, 0x30, 0x35, 0x32, 0x36, - 0x32, 0x31, 0x30, 0x35, 0x30, 0x31, 0x5a, 0x17, - 0x0d, 0x32, 0x33, 0x30, 0x35, 0x32, 0x34, 0x32, - 0x31, 0x30, 0x35, 0x30, 0x31, 0x5a, 0x30, 0x81, - 0x86, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, - 0x02, 0x4e, 0x59, 0x31, 0x11, 0x30, 0x0f, 0x06, - 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x42, 0x72, - 0x6f, 0x6f, 0x6b, 0x6c, 0x79, 0x6e, 0x31, 0x21, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, - 0x18, 0x4d, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x0c, 0x08, 0x6d, 0x79, 0x63, 0x61, - 0x2e, 0x6f, 0x72, 0x67, 0x31, 0x21, 0x30, 0x1f, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x09, 0x01, 0x16, 0x12, 0x6a, 0x76, 0x73, - 0x68, 0x61, 0x68, 0x69, 0x64, 0x40, 0x67, 0x6d, - 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30, - 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, - 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, - 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, - 0xf0, 0xfb, 0xad, 0x80, 0x5e, 0x37, 0xd3, 0x6d, - 0xee, 0x2e, 0xcc, 0xbc, 0x0c, 0xd7, 0x56, 0x4b, - 0x56, 0x45, 0xcd, 0x28, 0xb6, 0x22, 0xe9, 0xe2, - 0x0f, 0xd1, 0x87, 0x2a, 0x27, 0xce, 0x77, 0x8d, - 0x6e, 0x0e, 0x0f, 0xfb, 0x66, 0xe1, 0xb5, 0x0e, - 0x9a, 0xb6, 0x05, 0x8e, 0xb3, 0xe1, 0xc5, 0x77, - 0x86, 0x5b, 0x46, 0xd2, 0x0b, 0x92, 0x03, 0x1b, - 0x89, 0x0c, 0x1b, 0x10, 0x0e, 0x99, 0x8f, 0xe2, - 0x17, 0xe8, 0xc2, 0x30, 0x00, 0x47, 0xd6, 0xfc, - 0xf9, 0x0f, 0x3b, 0x75, 0x34, 0x8d, 0x4d, 0xb0, - 0x99, 0xb7, 0xa0, 0x6d, 0xa0, 0xb6, 0xad, 0xda, - 0x07, 0x5e, 0x38, 0x2e, 0x02, 0xe4, 0x30, 0x6d, - 0xae, 0x13, 0x72, 0xd4, 0xc8, 0xce, 0x14, 0x07, - 0xae, 0x23, 0x8c, 0x8f, 0x9e, 0x8c, 0x60, 0xd6, - 0x06, 0xb9, 0xef, 0x00, 0x18, 0xc0, 0x1d, 0x25, - 0x1e, 0xda, 0x3e, 0x2f, 0xcf, 0x2b, 0x56, 0x84, - 0x9e, 0x30, 0x21, 0xc7, 0x29, 0xf6, 0x03, 0x8a, - 0x24, 0xf9, 0x34, 0xac, 0x65, 0x9d, 0x80, 0x36, - 0xc8, 0x3b, 0x15, 0x10, 0xbd, 0x51, 0xe9, 0xbc, - 0x02, 0xe1, 0xe9, 0xb3, 0x5a, 0x9a, 0x99, 0x41, - 0x1b, 0x27, 0xa0, 0x4d, 0x50, 0x9e, 0x27, 0x7f, - 0xa1, 0x7d, 0x09, 0x87, 0xbd, 0x8a, 0xca, 0x5f, - 0xb1, 0xa5, 0x08, 0xb8, 0x04, 0xd4, 0x52, 0x89, - 0xaa, 0xe0, 0x7d, 0x42, 0x2e, 0x2f, 0x15, 0xee, - 0x66, 0x57, 0x0f, 0x13, 0x19, 0x45, 0xa8, 0x4b, - 0x5d, 0x81, 0x66, 0xcc, 0x12, 0x37, 0x94, 0x5e, - 0xfd, 0x3c, 0x10, 0x81, 0x51, 0x3f, 0xfa, 0x0f, - 0xdd, 0xa1, 0x89, 0x03, 0xa9, 0x78, 0x91, 0xf5, - 0x3b, 0xf3, 0xbc, 0xac, 0xbe, 0x93, 0x30, 0x2e, - 0xbe, 0xca, 0x7f, 0x46, 0xd3, 0x28, 0xb4, 0x4e, - 0x91, 0x7b, 0x5b, 0x43, 0x6c, 0xaf, 0x9b, 0x5c, - 0x6a, 0x6d, 0x5a, 0xdb, 0x79, 0x5e, 0x6a, 0x6b, - 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, - 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0x6b, 0x1e, 0x00, 0xa8, - 0x9f, 0xfa, 0x7d, 0x00, 0xf9, 0xe0, 0x9d, 0x0f, - 0x90, 0x8c, 0x90, 0xa8, 0xa1, 0x37, 0x6b, 0xda, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x18, 0x30, 0x16, 0x80, 0x14, 0x6b, 0x1e, 0x00, - 0xa8, 0x9f, 0xfa, 0x7d, 0x00, 0xf9, 0xe0, 0x9d, - 0x0f, 0x90, 0x8c, 0x90, 0xa8, 0xa1, 0x37, 0x6b, - 0xda, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, - 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, - 0x01, 0x01, 0x00, 0xcd, 0x6f, 0x73, 0x4d, 0x56, - 0x0b, 0xf3, 0x2e, 0x1c, 0xe2, 0x02, 0x0c, 0x14, - 0xbb, 0x2f, 0xdd, 0x3c, 0x43, 0xfe, 0xdf, 0x94, - 0x2d, 0xa9, 0x89, 0x81, 0x51, 0xf8, 0x5f, 0xa7, - 0xa0, 0x13, 0xaa, 0xcc, 0xb0, 0x18, 0xe2, 0x57, - 0x3e, 0x0d, 0x29, 0x93, 0xe8, 0x95, 0xd5, 0x1b, - 0x53, 0xd2, 0x51, 0xf2, 0xbd, 0xf5, 0x9e, 0x7b, - 0x22, 0x65, 0x62, 0x5c, 0xc4, 0x4c, 0x1d, 0xe8, - 0xe9, 0xc3, 0xd4, 0x2b, 0xe7, 0x78, 0xcb, 0x10, - 0xf3, 0xfe, 0x06, 0x83, 0xdc, 0x3a, 0x1e, 0x62, - 0x10, 0xc0, 0x46, 0x77, 0xc6, 0x9d, 0x9f, 0xab, - 0x96, 0x25, 0x5c, 0xfb, 0x26, 0xc1, 0x15, 0x1f, - 0xa5, 0x33, 0xee, 0x4f, 0x9a, 0x14, 0x6a, 0x14, - 0x97, 0x93, 0x2b, 0x95, 0x0b, 0xdc, 0xa8, 0xd7, - 0x69, 0x2e, 0xf0, 0x01, 0x0e, 0xfd, 0x4e, 0xd0, - 0xd9, 0xa8, 0xe5, 0x65, 0xde, 0xfb, 0xca, 0xca, - 0x1c, 0x5f, 0xf9, 0x53, 0xa0, 0x87, 0xe7, 0x33, - 0x9b, 0x2f, 0xcf, 0xe4, 0x13, 0xfc, 0xec, 0x7a, - 0x6c, 0xb0, 0x90, 0x13, 0x9b, 0xb6, 0xc5, 0x03, - 0xf6, 0x0e, 0x5e, 0xe2, 0xe4, 0x26, 0xc1, 0x7e, - 0x53, 0xfe, 0x69, 0xa3, 0xc7, 0xd8, 0x8e, 0x6e, - 0x94, 0x32, 0xa0, 0xde, 0xca, 0xb6, 0xcc, 0xd6, - 0x01, 0xd5, 0x78, 0x40, 0x28, 0x63, 0x9b, 0xee, - 0xcf, 0x09, 0x3b, 0x35, 0x04, 0xf0, 0x14, 0x02, - 0xf6, 0x80, 0x0e, 0x90, 0xb2, 0x94, 0xd2, 0x25, - 0x16, 0xb8, 0x7a, 0x76, 0x87, 0x84, 0x9f, 0x84, - 0xc5, 0xaf, 0xc2, 0x6d, 0x68, 0x7a, 0x84, 0x9c, - 0xc6, 0x8a, 0x63, 0x60, 0x87, 0x6a, 0x25, 0xc1, - 0xa1, 0x78, 0x0f, 0xba, 0xe8, 0x5f, 0xe1, 0xba, - 0xac, 0xa4, 0x6f, 0xdd, 0x09, 0x3f, 0x12, 0xcb, - 0x1d, 0xf3, 0xcf, 0x48, 0xd7, 0xd3, 0x26, 0xe8, - 0x9c, 0xc3, 0x53, 0xb3, 0xba, 0xdc, 0x32, 0x99, - 0x98, 0x96, 0xd6, 0x16, 0x03, 0x01, 0x00, 0x99, - 0x0d, 0x00, 0x00, 0x91, 0x03, 0x01, 0x02, 0x40, - 0x00, 0x8b, 0x00, 0x89, 0x30, 0x81, 0x86, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, - 0x59, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, - 0x04, 0x07, 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, - 0x6b, 0x6c, 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, - 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, - 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, - 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x0c, 0x08, 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, - 0x72, 0x67, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, - 0x01, 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, - 0x68, 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, - 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x0e, 0x00, 0x00, - 0x00, - }, - { - 0x16, 0x03, 0x01, 0x0a, 0xfb, 0x0b, 0x00, 0x0a, - 0xf7, 0x00, 0x0a, 0xf4, 0x00, 0x03, 0x7e, 0x30, - 0x82, 0x03, 0x7a, 0x30, 0x82, 0x02, 0x62, 0x02, - 0x09, 0x00, 0xb4, 0x47, 0x58, 0x57, 0x2b, 0x67, - 0xc8, 0xc2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, - 0x00, 0x30, 0x81, 0x80, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, - 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, 0x31, 0x11, - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, - 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c, 0x79, - 0x6e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x0c, 0x0c, 0x4d, 0x79, 0x20, 0x43, - 0x41, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x0c, 0x0e, 0x6d, 0x79, 0x63, 0x61, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x6f, - 0x6d, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, - 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, - 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x33, 0x30, 0x35, 0x32, 0x36, 0x32, 0x31, - 0x34, 0x34, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, - 0x33, 0x30, 0x36, 0x32, 0x35, 0x32, 0x31, 0x34, - 0x34, 0x30, 0x30, 0x5a, 0x30, 0x7d, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0f, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x0c, 0x08, 0x4e, 0x65, - 0x77, 0x20, 0x59, 0x6f, 0x72, 0x6b, 0x31, 0x11, - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, - 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c, 0x79, - 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x0c, 0x07, 0x4d, 0x79, 0x20, 0x4c, - 0x65, 0x61, 0x66, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x6d, 0x79, - 0x6c, 0x65, 0x61, 0x66, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, - 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, 0x69, - 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e, - 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, - 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, - 0x82, 0x01, 0x01, 0x00, 0xa0, 0xa3, 0xef, 0xc1, - 0x44, 0x7d, 0xa2, 0xe3, 0x71, 0x98, 0x27, 0x63, - 0xb3, 0x1d, 0x71, 0x50, 0xa6, 0x34, 0x15, 0xcb, - 0xc9, 0x2a, 0xc3, 0xea, 0xe4, 0x9e, 0x9c, 0x49, - 0xa6, 0x01, 0x9b, 0x7e, 0xa9, 0xb5, 0x7a, 0xff, - 0x15, 0x92, 0x71, 0xc8, 0x97, 0x9c, 0x25, 0xb7, - 0x79, 0x2b, 0xff, 0xab, 0xc6, 0xb1, 0xa7, 0x00, - 0x90, 0xb2, 0x8b, 0xd7, 0x71, 0xd5, 0xc2, 0x3a, - 0xe6, 0x82, 0x42, 0x37, 0x89, 0x41, 0x04, 0xb0, - 0xba, 0xc7, 0x5b, 0x8a, 0x43, 0x9f, 0x97, 0x39, - 0x0c, 0x0f, 0xd5, 0x6d, 0x9e, 0x8d, 0xeb, 0xc0, - 0x26, 0xc5, 0x18, 0xe8, 0x7a, 0x3d, 0x32, 0x2e, - 0x38, 0x90, 0x40, 0x5b, 0x39, 0x2c, 0x07, 0xcb, - 0x24, 0x10, 0xc5, 0xc9, 0x3b, 0xe3, 0x66, 0x47, - 0x57, 0xb9, 0x6a, 0xad, 0x44, 0xf8, 0xd0, 0x70, - 0x62, 0x3b, 0x8e, 0xed, 0x60, 0x5f, 0x22, 0xf8, - 0xb8, 0x0c, 0xc9, 0x41, 0x2b, 0xc9, 0x80, 0x6e, - 0x4e, 0x1b, 0xe1, 0x20, 0xfc, 0x47, 0xa4, 0xac, - 0xc3, 0x3f, 0xe6, 0xc2, 0x81, 0x79, 0x03, 0x37, - 0x25, 0x89, 0xca, 0xd6, 0xa5, 0x46, 0x91, 0x63, - 0x41, 0xc5, 0x3e, 0xd5, 0xed, 0x7f, 0x4f, 0x8d, - 0x06, 0xc0, 0x89, 0x00, 0xbe, 0x37, 0x7b, 0x7e, - 0x73, 0xca, 0x70, 0x00, 0x14, 0x34, 0xbe, 0x47, - 0xbc, 0xb2, 0x6a, 0x28, 0xa5, 0x29, 0x84, 0xa8, - 0x9d, 0xc8, 0x1e, 0x77, 0x66, 0x1f, 0x9f, 0xaa, - 0x2b, 0x47, 0xdb, 0xdd, 0x6b, 0x9c, 0xa8, 0xfc, - 0x82, 0x36, 0x94, 0x62, 0x0d, 0x5c, 0x3f, 0xb2, - 0x01, 0xb4, 0xa5, 0xb8, 0xc6, 0x0e, 0x94, 0x5b, - 0xec, 0x5e, 0xbb, 0x7a, 0x63, 0x24, 0xf1, 0xf9, - 0xd6, 0x50, 0x08, 0xc1, 0xa3, 0xcc, 0x90, 0x07, - 0x5b, 0x04, 0x04, 0x42, 0x74, 0xcf, 0x37, 0xfa, - 0xf0, 0xa5, 0xd9, 0xd3, 0x86, 0x89, 0x89, 0x18, - 0xf3, 0x4c, 0xe2, 0x11, 0x02, 0x03, 0x01, 0x00, - 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, - 0x03, 0x82, 0x01, 0x01, 0x00, 0x90, 0xbb, 0xf9, - 0x5e, 0xba, 0x17, 0x1f, 0xac, 0x21, 0x9f, 0x6b, - 0x4a, 0x46, 0xd0, 0x6d, 0x3c, 0x8f, 0x3d, 0xf8, - 0x5e, 0x3e, 0x72, 0xaf, 0xa0, 0x1a, 0xf3, 0xff, - 0x89, 0xac, 0x5b, 0x7a, 0xe2, 0x91, 0x2a, 0x23, - 0x85, 0xc6, 0x4d, 0x47, 0x67, 0x01, 0x08, 0xa8, - 0x05, 0x1d, 0x01, 0x60, 0x50, 0x5f, 0x59, 0xad, - 0xfe, 0x7b, 0xc6, 0x0c, 0x54, 0x90, 0x68, 0x70, - 0x67, 0x2e, 0xed, 0x87, 0xf8, 0x69, 0x8a, 0xac, - 0x32, 0xfe, 0x6f, 0x90, 0x19, 0x2a, 0x64, 0x8d, - 0x82, 0x66, 0x05, 0x43, 0x88, 0xee, 0xf2, 0x30, - 0xed, 0xa4, 0x8f, 0xbf, 0xd6, 0x57, 0x20, 0xd4, - 0x43, 0x1d, 0x52, 0x96, 0x6f, 0xae, 0x09, 0x96, - 0x01, 0x52, 0x38, 0xe3, 0xaf, 0x99, 0xd7, 0xdc, - 0x14, 0x99, 0xc4, 0x8b, 0x0e, 0x04, 0x0f, 0xb3, - 0x14, 0x14, 0xd4, 0xa5, 0x93, 0xe1, 0xc9, 0x8a, - 0x81, 0xef, 0x63, 0xfc, 0x36, 0x77, 0x05, 0x06, - 0xf0, 0x2a, 0x04, 0x0a, 0xbe, 0x2e, 0xce, 0x81, - 0x3d, 0x23, 0xa1, 0xda, 0xd8, 0xeb, 0xc6, 0xea, - 0x5e, 0xcf, 0x28, 0x36, 0x51, 0x31, 0x95, 0x5e, - 0x40, 0x04, 0xed, 0xac, 0xc1, 0xc8, 0x56, 0x69, - 0x87, 0xec, 0x3b, 0x03, 0x3e, 0x9d, 0x0f, 0x4c, - 0x4c, 0xeb, 0xd7, 0xba, 0x26, 0xdf, 0xe3, 0xde, - 0x10, 0xee, 0x93, 0x62, 0x8d, 0x73, 0x52, 0x6e, - 0xff, 0x37, 0x36, 0x98, 0x7b, 0x2d, 0x56, 0x4c, - 0xba, 0x09, 0xb8, 0xa7, 0xf0, 0x3b, 0x16, 0x81, - 0xca, 0xdb, 0x43, 0xab, 0xec, 0x4c, 0x6e, 0x7c, - 0xc1, 0x0b, 0x22, 0x22, 0x43, 0x1d, 0xb6, 0x0c, - 0xc1, 0xb9, 0xcf, 0xe4, 0x53, 0xee, 0x1d, 0x3e, - 0x88, 0xa7, 0x13, 0xbe, 0x7f, 0xbd, 0xae, 0x72, - 0xcf, 0xcd, 0x63, 0xd2, 0xc3, 0x18, 0x58, 0x92, - 0xa2, 0xad, 0xb5, 0x09, 0x9d, 0x91, 0x03, 0xdd, - 0x3c, 0xe2, 0x1c, 0xde, 0x78, 0x00, 0x03, 0x88, - 0x30, 0x82, 0x03, 0x84, 0x30, 0x82, 0x02, 0x6c, - 0x02, 0x09, 0x00, 0xab, 0xed, 0xa6, 0xe4, 0x4a, - 0x2b, 0x2b, 0xf8, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x30, 0x81, 0x86, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, 0x31, - 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c, - 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x79, 0x20, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, - 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, - 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, 0x72, 0x67, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, - 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, 0x69, - 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e, - 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, - 0x33, 0x30, 0x35, 0x32, 0x36, 0x32, 0x31, 0x31, - 0x38, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x33, - 0x30, 0x36, 0x32, 0x35, 0x32, 0x31, 0x31, 0x38, - 0x34, 0x30, 0x5a, 0x30, 0x81, 0x80, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, - 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, - 0x6c, 0x79, 0x6e, 0x31, 0x15, 0x30, 0x13, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0c, 0x4d, 0x79, - 0x20, 0x43, 0x41, 0x20, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x6d, 0x79, 0x63, - 0x61, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, - 0x63, 0x6f, 0x6d, 0x31, 0x21, 0x30, 0x1f, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x01, 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, - 0x61, 0x68, 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, - 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, - 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, - 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, - 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xce, - 0x13, 0xf0, 0x72, 0xb0, 0x61, 0xc8, 0x18, 0x37, - 0x8a, 0x41, 0x3d, 0x20, 0xa1, 0x1c, 0xcb, 0xbf, - 0xf6, 0x3b, 0x74, 0x26, 0x2a, 0x96, 0x11, 0xec, - 0x53, 0xa1, 0xcc, 0x7d, 0x77, 0x56, 0x45, 0x0f, - 0x36, 0xb7, 0xf2, 0x48, 0x92, 0x1a, 0x62, 0xcc, - 0xb6, 0xc0, 0xa1, 0x2f, 0x44, 0x2b, 0xc1, 0x89, - 0xcb, 0x6e, 0x1e, 0xdb, 0x57, 0x92, 0xd5, 0x97, - 0x60, 0x8c, 0x41, 0x2c, 0xd9, 0x20, 0xfe, 0xe9, - 0x1f, 0x8e, 0xfc, 0x7f, 0x02, 0x44, 0x0f, 0x28, - 0x81, 0xd6, 0x0c, 0xcd, 0xbc, 0xf0, 0x57, 0x6c, - 0xcc, 0xa7, 0xba, 0x06, 0xa0, 0xa6, 0x91, 0xda, - 0xef, 0x46, 0x8a, 0x60, 0x0f, 0x52, 0x6c, 0x90, - 0x6c, 0x8c, 0x44, 0xaf, 0xb0, 0x9d, 0x90, 0xba, - 0x21, 0x58, 0xa0, 0x3c, 0xee, 0x54, 0xb5, 0x29, - 0x26, 0x1f, 0x0a, 0xac, 0xef, 0x48, 0x68, 0x33, - 0xd0, 0x33, 0xd0, 0x8b, 0x1a, 0xec, 0x6e, 0x2f, - 0xb5, 0x4a, 0x53, 0xc2, 0x1a, 0xd2, 0xf1, 0x50, - 0x05, 0x59, 0x5c, 0xd9, 0xda, 0x03, 0x0a, 0x47, - 0xb7, 0xdd, 0xf7, 0x3a, 0x69, 0xf5, 0x4e, 0xea, - 0x4a, 0xc2, 0xca, 0x54, 0xb0, 0x8b, 0x76, 0xe1, - 0x02, 0x2d, 0x52, 0x67, 0xb9, 0xdd, 0x50, 0xc9, - 0x3b, 0x07, 0x24, 0x22, 0x6a, 0x00, 0x1d, 0x58, - 0x83, 0xa8, 0xec, 0x95, 0xf1, 0xda, 0xe2, 0x73, - 0xa0, 0xa1, 0x72, 0x60, 0x9e, 0x86, 0x53, 0xcb, - 0x45, 0xa8, 0xc2, 0xa0, 0x50, 0xa0, 0x53, 0xd6, - 0xfc, 0x18, 0x84, 0xb5, 0x4a, 0x26, 0xd0, 0xa2, - 0xaa, 0xd0, 0xff, 0xb6, 0xfe, 0x3a, 0x9c, 0xb5, - 0x19, 0x3b, 0x3f, 0xe1, 0x48, 0x0d, 0xa4, 0x09, - 0x4f, 0x83, 0xc9, 0xc0, 0xc9, 0xa6, 0x0b, 0x58, - 0x1f, 0x1c, 0x7b, 0xac, 0xa2, 0x42, 0xbc, 0x61, - 0xf4, 0x21, 0x8a, 0x00, 0xda, 0x14, 0xa0, 0x60, - 0x03, 0xfe, 0x93, 0x12, 0x6c, 0x56, 0xcd, 0x02, - 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, - 0x25, 0x29, 0x3b, 0x1e, 0xc3, 0x58, 0x32, 0xe6, - 0x23, 0xc8, 0xee, 0x18, 0xf0, 0x1d, 0x62, 0x6d, - 0x3b, 0x59, 0x99, 0x3a, 0xfe, 0x49, 0x72, 0x07, - 0x3f, 0x58, 0x93, 0xdb, 0xc0, 0xaf, 0xb0, 0xb3, - 0x5c, 0xd1, 0x5c, 0x98, 0xc8, 0xea, 0x4a, 0xe4, - 0x58, 0x73, 0x0d, 0x57, 0xc5, 0x13, 0x7c, 0x5c, - 0x79, 0x66, 0xda, 0x04, 0x1d, 0xe5, 0x98, 0xda, - 0x35, 0x47, 0x44, 0xb0, 0xd2, 0x7a, 0x66, 0x9d, - 0xcd, 0x41, 0xa5, 0x8f, 0xa1, 0x11, 0xb2, 0x1a, - 0x87, 0xc0, 0xcd, 0x55, 0xed, 0xb4, 0x7b, 0x33, - 0x72, 0xeb, 0xf7, 0xe3, 0x7b, 0x8b, 0x02, 0x86, - 0xe9, 0x2b, 0x26, 0x32, 0x9f, 0x99, 0xf1, 0xcb, - 0x93, 0xab, 0xb9, 0x16, 0xb3, 0x9a, 0xb2, 0x22, - 0x13, 0x21, 0x1f, 0x5b, 0xcc, 0xa2, 0x59, 0xbb, - 0x69, 0xf2, 0xb8, 0x07, 0x80, 0xce, 0x0c, 0xf7, - 0x98, 0x4c, 0x85, 0xc2, 0x96, 0x6a, 0x22, 0x05, - 0xe9, 0xbe, 0x48, 0xb0, 0x02, 0x5b, 0x69, 0x28, - 0x18, 0x88, 0x96, 0xe3, 0xd7, 0xc6, 0x7a, 0xd3, - 0xe9, 0x99, 0xff, 0x9d, 0xc3, 0x61, 0x4d, 0x9a, - 0x96, 0xf2, 0xc6, 0x33, 0x4d, 0xe5, 0x5d, 0x5a, - 0x68, 0x64, 0x5a, 0x82, 0x35, 0x65, 0x25, 0xe3, - 0x8c, 0x5b, 0xb0, 0xf6, 0x96, 0x56, 0xbc, 0xbf, - 0x97, 0x76, 0x4b, 0x66, 0x44, 0x81, 0xa4, 0xc4, - 0xa7, 0x31, 0xc5, 0xa1, 0x4f, 0xe8, 0xa4, 0xca, - 0x20, 0xf5, 0x01, 0x5b, 0x99, 0x4f, 0x5a, 0xf4, - 0xf0, 0x78, 0xbf, 0x71, 0x49, 0xd5, 0xf1, 0xc1, - 0xa2, 0x18, 0xfd, 0x72, 0x5b, 0x16, 0xe8, 0x92, - 0xc7, 0x37, 0x48, 0xaf, 0xee, 0x24, 0xfc, 0x35, - 0x0b, 0xc2, 0xdd, 0x05, 0xc7, 0x6e, 0xa3, 0x29, - 0xbb, 0x29, 0x7d, 0xd3, 0x2b, 0x94, 0x80, 0xc3, - 0x40, 0x53, 0x0e, 0x03, 0x54, 0x3d, 0x7b, 0x8b, - 0xce, 0xf9, 0xa4, 0x03, 0x27, 0x63, 0xec, 0x51, - 0x00, 0x03, 0xe5, 0x30, 0x82, 0x03, 0xe1, 0x30, - 0x82, 0x02, 0xc9, 0xa0, 0x03, 0x02, 0x01, 0x02, - 0x02, 0x09, 0x00, 0xcc, 0x22, 0x4c, 0x4b, 0x98, - 0xa2, 0x88, 0xfc, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x30, 0x81, 0x86, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, 0x31, - 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c, - 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x79, 0x20, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, - 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, - 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, 0x72, 0x67, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, - 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, 0x69, - 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e, - 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, - 0x33, 0x30, 0x35, 0x32, 0x36, 0x32, 0x31, 0x30, - 0x35, 0x30, 0x31, 0x5a, 0x17, 0x0d, 0x32, 0x33, - 0x30, 0x35, 0x32, 0x34, 0x32, 0x31, 0x30, 0x35, - 0x30, 0x31, 0x5a, 0x30, 0x81, 0x86, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, - 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, - 0x6c, 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x79, - 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, - 0x08, 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, 0x72, - 0x67, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, - 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, - 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, - 0x02, 0x82, 0x01, 0x01, 0x00, 0xf0, 0xfb, 0xad, - 0x80, 0x5e, 0x37, 0xd3, 0x6d, 0xee, 0x2e, 0xcc, - 0xbc, 0x0c, 0xd7, 0x56, 0x4b, 0x56, 0x45, 0xcd, - 0x28, 0xb6, 0x22, 0xe9, 0xe2, 0x0f, 0xd1, 0x87, - 0x2a, 0x27, 0xce, 0x77, 0x8d, 0x6e, 0x0e, 0x0f, - 0xfb, 0x66, 0xe1, 0xb5, 0x0e, 0x9a, 0xb6, 0x05, - 0x8e, 0xb3, 0xe1, 0xc5, 0x77, 0x86, 0x5b, 0x46, - 0xd2, 0x0b, 0x92, 0x03, 0x1b, 0x89, 0x0c, 0x1b, - 0x10, 0x0e, 0x99, 0x8f, 0xe2, 0x17, 0xe8, 0xc2, - 0x30, 0x00, 0x47, 0xd6, 0xfc, 0xf9, 0x0f, 0x3b, - 0x75, 0x34, 0x8d, 0x4d, 0xb0, 0x99, 0xb7, 0xa0, - 0x6d, 0xa0, 0xb6, 0xad, 0xda, 0x07, 0x5e, 0x38, - 0x2e, 0x02, 0xe4, 0x30, 0x6d, 0xae, 0x13, 0x72, - 0xd4, 0xc8, 0xce, 0x14, 0x07, 0xae, 0x23, 0x8c, - 0x8f, 0x9e, 0x8c, 0x60, 0xd6, 0x06, 0xb9, 0xef, - 0x00, 0x18, 0xc0, 0x1d, 0x25, 0x1e, 0xda, 0x3e, - 0x2f, 0xcf, 0x2b, 0x56, 0x84, 0x9e, 0x30, 0x21, - 0xc7, 0x29, 0xf6, 0x03, 0x8a, 0x24, 0xf9, 0x34, - 0xac, 0x65, 0x9d, 0x80, 0x36, 0xc8, 0x3b, 0x15, - 0x10, 0xbd, 0x51, 0xe9, 0xbc, 0x02, 0xe1, 0xe9, - 0xb3, 0x5a, 0x9a, 0x99, 0x41, 0x1b, 0x27, 0xa0, - 0x4d, 0x50, 0x9e, 0x27, 0x7f, 0xa1, 0x7d, 0x09, - 0x87, 0xbd, 0x8a, 0xca, 0x5f, 0xb1, 0xa5, 0x08, - 0xb8, 0x04, 0xd4, 0x52, 0x89, 0xaa, 0xe0, 0x7d, - 0x42, 0x2e, 0x2f, 0x15, 0xee, 0x66, 0x57, 0x0f, - 0x13, 0x19, 0x45, 0xa8, 0x4b, 0x5d, 0x81, 0x66, - 0xcc, 0x12, 0x37, 0x94, 0x5e, 0xfd, 0x3c, 0x10, - 0x81, 0x51, 0x3f, 0xfa, 0x0f, 0xdd, 0xa1, 0x89, - 0x03, 0xa9, 0x78, 0x91, 0xf5, 0x3b, 0xf3, 0xbc, - 0xac, 0xbe, 0x93, 0x30, 0x2e, 0xbe, 0xca, 0x7f, - 0x46, 0xd3, 0x28, 0xb4, 0x4e, 0x91, 0x7b, 0x5b, - 0x43, 0x6c, 0xaf, 0x9b, 0x5c, 0x6a, 0x6d, 0x5a, - 0xdb, 0x79, 0x5e, 0x6a, 0x6b, 0x02, 0x03, 0x01, - 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, - 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, - 0x14, 0x6b, 0x1e, 0x00, 0xa8, 0x9f, 0xfa, 0x7d, - 0x00, 0xf9, 0xe0, 0x9d, 0x0f, 0x90, 0x8c, 0x90, - 0xa8, 0xa1, 0x37, 0x6b, 0xda, 0x30, 0x1f, 0x06, - 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, - 0x80, 0x14, 0x6b, 0x1e, 0x00, 0xa8, 0x9f, 0xfa, - 0x7d, 0x00, 0xf9, 0xe0, 0x9d, 0x0f, 0x90, 0x8c, - 0x90, 0xa8, 0xa1, 0x37, 0x6b, 0xda, 0x30, 0x0c, - 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, - 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, - 0xcd, 0x6f, 0x73, 0x4d, 0x56, 0x0b, 0xf3, 0x2e, - 0x1c, 0xe2, 0x02, 0x0c, 0x14, 0xbb, 0x2f, 0xdd, - 0x3c, 0x43, 0xfe, 0xdf, 0x94, 0x2d, 0xa9, 0x89, - 0x81, 0x51, 0xf8, 0x5f, 0xa7, 0xa0, 0x13, 0xaa, - 0xcc, 0xb0, 0x18, 0xe2, 0x57, 0x3e, 0x0d, 0x29, - 0x93, 0xe8, 0x95, 0xd5, 0x1b, 0x53, 0xd2, 0x51, - 0xf2, 0xbd, 0xf5, 0x9e, 0x7b, 0x22, 0x65, 0x62, - 0x5c, 0xc4, 0x4c, 0x1d, 0xe8, 0xe9, 0xc3, 0xd4, - 0x2b, 0xe7, 0x78, 0xcb, 0x10, 0xf3, 0xfe, 0x06, - 0x83, 0xdc, 0x3a, 0x1e, 0x62, 0x10, 0xc0, 0x46, - 0x77, 0xc6, 0x9d, 0x9f, 0xab, 0x96, 0x25, 0x5c, - 0xfb, 0x26, 0xc1, 0x15, 0x1f, 0xa5, 0x33, 0xee, - 0x4f, 0x9a, 0x14, 0x6a, 0x14, 0x97, 0x93, 0x2b, - 0x95, 0x0b, 0xdc, 0xa8, 0xd7, 0x69, 0x2e, 0xf0, - 0x01, 0x0e, 0xfd, 0x4e, 0xd0, 0xd9, 0xa8, 0xe5, - 0x65, 0xde, 0xfb, 0xca, 0xca, 0x1c, 0x5f, 0xf9, - 0x53, 0xa0, 0x87, 0xe7, 0x33, 0x9b, 0x2f, 0xcf, - 0xe4, 0x13, 0xfc, 0xec, 0x7a, 0x6c, 0xb0, 0x90, - 0x13, 0x9b, 0xb6, 0xc5, 0x03, 0xf6, 0x0e, 0x5e, - 0xe2, 0xe4, 0x26, 0xc1, 0x7e, 0x53, 0xfe, 0x69, - 0xa3, 0xc7, 0xd8, 0x8e, 0x6e, 0x94, 0x32, 0xa0, - 0xde, 0xca, 0xb6, 0xcc, 0xd6, 0x01, 0xd5, 0x78, - 0x40, 0x28, 0x63, 0x9b, 0xee, 0xcf, 0x09, 0x3b, - 0x35, 0x04, 0xf0, 0x14, 0x02, 0xf6, 0x80, 0x0e, - 0x90, 0xb2, 0x94, 0xd2, 0x25, 0x16, 0xb8, 0x7a, - 0x76, 0x87, 0x84, 0x9f, 0x84, 0xc5, 0xaf, 0xc2, - 0x6d, 0x68, 0x7a, 0x84, 0x9c, 0xc6, 0x8a, 0x63, - 0x60, 0x87, 0x6a, 0x25, 0xc1, 0xa1, 0x78, 0x0f, - 0xba, 0xe8, 0x5f, 0xe1, 0xba, 0xac, 0xa4, 0x6f, - 0xdd, 0x09, 0x3f, 0x12, 0xcb, 0x1d, 0xf3, 0xcf, - 0x48, 0xd7, 0xd3, 0x26, 0xe8, 0x9c, 0xc3, 0x53, - 0xb3, 0xba, 0xdc, 0x32, 0x99, 0x98, 0x96, 0xd6, - 0x16, 0x03, 0x01, 0x01, 0x06, 0x10, 0x00, 0x01, - 0x02, 0x01, 0x00, 0x6e, 0xea, 0x15, 0x6f, 0x21, - 0xbd, 0x2d, 0x14, 0xde, 0x9d, 0x02, 0xeb, 0xdf, - 0x3b, 0x09, 0x75, 0xaf, 0x32, 0x80, 0x0c, 0xe2, - 0xc2, 0x7b, 0x0d, 0xca, 0x24, 0x96, 0xf6, 0x3e, - 0xa5, 0x97, 0xba, 0x0c, 0x50, 0x7e, 0xb3, 0x68, - 0x58, 0xc6, 0xd8, 0xec, 0xab, 0xa9, 0xd9, 0x3a, - 0xb1, 0x49, 0xea, 0x2f, 0xd7, 0xdb, 0x15, 0x1b, - 0xb5, 0xaf, 0xec, 0xcc, 0x40, 0x5c, 0xe6, 0x0f, - 0xc4, 0x33, 0x71, 0xe7, 0x41, 0xc0, 0x04, 0x89, - 0x60, 0x3e, 0xb7, 0xe6, 0xda, 0x38, 0x62, 0x27, - 0x6a, 0xd9, 0xfb, 0x93, 0x94, 0x9d, 0xc1, 0x63, - 0x92, 0x5c, 0x88, 0x19, 0x38, 0x81, 0x79, 0x9d, - 0x59, 0x48, 0x5e, 0xd3, 0xc8, 0xea, 0xcb, 0x6e, - 0x66, 0x66, 0x03, 0xdc, 0x0c, 0x2d, 0x95, 0xb1, - 0x4d, 0x68, 0xc7, 0xc5, 0x6e, 0xfa, 0x94, 0x14, - 0xdf, 0x2c, 0x70, 0x69, 0x04, 0xf4, 0x69, 0xf1, - 0xf0, 0x07, 0xbd, 0x23, 0x53, 0x63, 0xb3, 0x41, - 0xec, 0xa7, 0x10, 0xa5, 0x04, 0x84, 0x24, 0xb5, - 0xf5, 0x0c, 0x0f, 0x5d, 0x02, 0x47, 0x79, 0x60, - 0x76, 0xbb, 0xdf, 0x60, 0xa6, 0xd7, 0x4d, 0x08, - 0x7d, 0xa6, 0x85, 0x4f, 0x61, 0xac, 0x96, 0x3d, - 0xbc, 0xaf, 0x07, 0xb0, 0x7c, 0xb6, 0x23, 0x3e, - 0x1f, 0x0a, 0x62, 0x77, 0x97, 0x77, 0xae, 0x33, - 0x55, 0x0f, 0x85, 0xdf, 0xdc, 0xbe, 0xc6, 0xe0, - 0xe0, 0x14, 0x83, 0x4c, 0x50, 0xf0, 0xe5, 0x2d, - 0xdc, 0x0b, 0x74, 0x7f, 0xc3, 0x28, 0x98, 0x16, - 0xda, 0x74, 0xe6, 0x40, 0xc2, 0xf0, 0xea, 0xc0, - 0x00, 0xd5, 0xfc, 0x16, 0xe4, 0x43, 0xa1, 0xfc, - 0x31, 0x19, 0x81, 0x62, 0xec, 0x2b, 0xfe, 0xcc, - 0xe8, 0x19, 0xed, 0xa1, 0x1e, 0x6a, 0x49, 0x73, - 0xde, 0xc4, 0xe9, 0x22, 0x0a, 0x21, 0xde, 0x45, - 0x1e, 0x55, 0x12, 0xd9, 0x44, 0xef, 0x4e, 0xaa, - 0x5e, 0x26, 0x57, 0x16, 0x03, 0x01, 0x01, 0x06, - 0x0f, 0x00, 0x01, 0x02, 0x01, 0x00, 0x23, 0xde, - 0xb0, 0x39, 0x60, 0xe9, 0x82, 0xb8, 0xed, 0x17, - 0x78, 0xd2, 0x37, 0x0e, 0x85, 0x69, 0xda, 0xcc, - 0x9f, 0x54, 0x4d, 0xda, 0xce, 0xe8, 0x5a, 0xeb, - 0x3c, 0x61, 0x4c, 0x7a, 0x84, 0x1f, 0x21, 0x03, - 0xb3, 0x8a, 0x74, 0x3b, 0x6a, 0x9e, 0x4f, 0x44, - 0xd9, 0x75, 0x0a, 0xd8, 0x7e, 0x56, 0xa3, 0xef, - 0x5a, 0xfe, 0x8a, 0x35, 0xce, 0x29, 0x18, 0xfe, - 0xa6, 0x61, 0x8e, 0x8f, 0x00, 0x90, 0x2d, 0x85, - 0xe3, 0x6c, 0x0e, 0x8d, 0x8c, 0x27, 0x80, 0x8c, - 0x9f, 0x51, 0xe9, 0xd3, 0xe6, 0x7d, 0x70, 0xe9, - 0xfb, 0xcb, 0xb8, 0x24, 0x94, 0x30, 0x9b, 0xba, - 0x01, 0x14, 0x49, 0x9f, 0xaf, 0x09, 0xd8, 0x26, - 0x1b, 0x23, 0xa4, 0xb8, 0xd9, 0x44, 0x0a, 0xdc, - 0x4e, 0x27, 0xe7, 0x32, 0xf5, 0x9c, 0xf3, 0x8d, - 0xa0, 0xc5, 0xc4, 0xbe, 0x92, 0x02, 0x85, 0x4f, - 0x33, 0x8f, 0xa7, 0xf7, 0x87, 0xa9, 0x44, 0xf3, - 0x64, 0xbd, 0x32, 0x04, 0xeb, 0xc5, 0xc3, 0x62, - 0xe9, 0xda, 0x2f, 0x95, 0x5c, 0xf7, 0x58, 0x3e, - 0xad, 0x35, 0xd7, 0x7e, 0xad, 0xdd, 0x32, 0x8d, - 0xce, 0x81, 0x08, 0xad, 0x49, 0xf7, 0xdb, 0xf7, - 0xaf, 0xe3, 0xc6, 0xb2, 0xdd, 0x76, 0x0c, 0xcf, - 0x0f, 0x87, 0x79, 0x90, 0x10, 0x79, 0xc6, 0xc8, - 0x7b, 0xe6, 0x23, 0xf2, 0xda, 0x33, 0xca, 0xe1, - 0xf0, 0x59, 0x42, 0x43, 0x03, 0x56, 0x19, 0xe3, - 0x8b, 0xe6, 0xa8, 0x70, 0xbc, 0x80, 0xfa, 0x24, - 0xae, 0x03, 0x13, 0x30, 0x0d, 0x1f, 0xab, 0xb7, - 0x82, 0xd9, 0x24, 0x90, 0x80, 0xbf, 0x75, 0xe1, - 0x0d, 0x1c, 0xb2, 0xfe, 0x92, 0x2c, 0x4d, 0x21, - 0xe9, 0x5d, 0xa1, 0x68, 0xf3, 0x16, 0xd8, 0x3f, - 0xb2, 0xc3, 0x00, 0x3e, 0xd8, 0x42, 0x25, 0x5c, - 0x90, 0x11, 0xc0, 0x1b, 0xd4, 0x26, 0x5c, 0x37, - 0x47, 0xbd, 0xf8, 0x1e, 0x34, 0xa9, 0x14, 0x03, - 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00, - 0x24, 0x8f, 0x94, 0x7e, 0x01, 0xee, 0xd5, 0x4f, - 0x83, 0x41, 0x31, 0xc0, 0x36, 0x81, 0x46, 0xc3, - 0xc0, 0xcc, 0x9c, 0xea, 0x0f, 0x29, 0x04, 0x10, - 0x43, 0x1e, 0x08, 0x6e, 0x08, 0xce, 0xb2, 0x62, - 0xa6, 0x0f, 0x68, 0x9f, 0x99, - }, - { - 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x01, 0x00, 0x24, 0xd9, 0x46, 0x5b, 0xbf, 0xfd, - 0x8a, 0xa1, 0x08, 0xd5, 0xf3, 0x0c, 0x1c, 0xd8, - 0xa8, 0xb3, 0xe5, 0x89, 0x83, 0x9e, 0x23, 0x47, - 0x81, 0x66, 0x77, 0x11, 0x98, 0xe5, 0xf4, 0xac, - 0x06, 0xe9, 0x4c, 0x05, 0x8b, 0xc4, 0x16, - }, - { - 0x17, 0x03, 0x01, 0x00, 0x1a, 0xc5, 0x28, 0xfd, - 0x71, 0xc0, 0xe6, 0x89, 0xb8, 0x82, 0x92, 0x1b, - 0xdd, 0x39, 0xe5, 0xbf, 0x41, 0x82, 0x1f, 0xc1, - 0xbc, 0x85, 0xe5, 0x32, 0x1b, 0x93, 0x46, 0x15, - 0x03, 0x01, 0x00, 0x16, 0x1a, 0x8b, 0x10, 0x42, - 0x12, 0xb2, 0xbd, 0xd3, 0xf1, 0x74, 0x1f, 0xc2, - 0x10, 0x08, 0xc2, 0x79, 0x99, 0x2c, 0x55, 0xef, - 0x4a, 0xbd, - }, -} + // Touch entry 2. LRU should evict 3 next. + cache.Get(keys[2]) + cache.Put(keys[0], &cs[0]) + if s, ok := cache.Get(keys[3]); ok || s != nil { + t.Fatalf("session cache should have evicted key 3") + } -// $ openssl s_server -tls1_2 -cert server.crt -key server.key \ -// -cipher ECDHE-RSA-AES128-SHA -port 10443 -// $ go test -test.run "TestRunClient" -connect -ciphersuites=0xc013 \ -// -minversion=0x0303 -maxversion=0x0303 -var clientTLS12Script = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0x58, 0x01, 0x00, 0x00, - 0x54, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x13, - 0x01, 0x00, 0x00, 0x29, 0x00, 0x05, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, - 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, - 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, - 0x0d, 0x00, 0x0a, 0x00, 0x08, 0x04, 0x01, 0x04, - 0x03, 0x02, 0x01, 0x02, 0x03, - }, - { - 0x16, 0x03, 0x03, 0x00, 0x54, 0x02, 0x00, 0x00, - 0x50, 0x03, 0x03, 0x52, 0x65, 0x67, 0xbd, 0xe8, - 0x72, 0x03, 0x6a, 0x52, 0x8d, 0x28, 0x2c, 0x9a, - 0x53, 0xff, 0xc2, 0xa1, 0x62, 0x5f, 0x54, 0xfb, - 0x73, 0x00, 0xcf, 0x4d, 0x28, 0x36, 0xc2, 0xee, - 0xfd, 0x78, 0xf0, 0x20, 0x6f, 0xbe, 0x49, 0xec, - 0x5b, 0x6f, 0xf9, 0x53, 0x42, 0x69, 0x0d, 0x6d, - 0x8b, 0x68, 0x2e, 0xca, 0x3c, 0x3c, 0x88, 0x9e, - 0x8b, 0xf9, 0x32, 0x65, 0x09, 0xd6, 0xa0, 0x7d, - 0xea, 0xc6, 0xd5, 0xc4, 0xc0, 0x13, 0x00, 0x00, - 0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01, - 0x02, 0x16, 0x03, 0x03, 0x02, 0x39, 0x0b, 0x00, - 0x02, 0x35, 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f, - 0x30, 0x82, 0x02, 0x2b, 0x30, 0x82, 0x01, 0xd5, - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, - 0xb1, 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, - 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, - 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, - 0x17, 0x0d, 0x31, 0x32, 0x30, 0x34, 0x30, 0x36, - 0x31, 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x17, - 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30, 0x36, 0x31, - 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x30, 0x45, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, - 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, - 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, - 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, - 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x5c, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, - 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0x9f, 0xb3, - 0xc3, 0x84, 0x27, 0x95, 0xff, 0x12, 0x31, 0x52, - 0x0f, 0x15, 0xef, 0x46, 0x11, 0xc4, 0xad, 0x80, - 0xe6, 0x36, 0x5b, 0x0f, 0xdd, 0x80, 0xd7, 0x61, - 0x8d, 0xe0, 0xfc, 0x72, 0x45, 0x09, 0x34, 0xfe, - 0x55, 0x66, 0x45, 0x43, 0x4c, 0x68, 0x97, 0x6a, - 0xfe, 0xa8, 0xa0, 0xa5, 0xdf, 0x5f, 0x78, 0xff, - 0xee, 0xd7, 0x64, 0xb8, 0x3f, 0x04, 0xcb, 0x6f, - 0xff, 0x2a, 0xfe, 0xfe, 0xb9, 0xed, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, - 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0x78, 0xa6, 0x97, 0x9a, - 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22, - 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b, - 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x6e, 0x30, 0x6c, 0x80, 0x14, 0x78, 0xa6, 0x97, - 0x9a, 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, - 0x22, 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, - 0x2b, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0xb1, - 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x85, - 0x36, 0x40, 0x73, 0xc1, 0xbb, 0x1a, 0xda, 0xd4, - 0x59, 0x9f, 0x2d, 0xa2, 0x70, 0x31, 0x46, 0x74, - 0xec, 0x83, 0x6e, 0xa8, 0xc8, 0x3c, 0x51, 0xaf, - 0x39, 0xac, 0xec, 0x40, 0xbc, 0xe8, 0x22, 0x46, - 0x1d, 0x99, 0xd6, 0x46, 0x2a, 0x24, 0xd4, 0x8b, - 0x05, 0x08, 0x4b, 0xfb, 0x35, 0x11, 0x6e, 0x92, - 0xbb, 0x77, 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8, - 0x5e, 0x9c, 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16, - 0x03, 0x03, 0x00, 0x8d, 0x0c, 0x00, 0x00, 0x89, - 0x03, 0x00, 0x17, 0x41, 0x04, 0x48, 0x93, 0x62, - 0x6a, 0xf8, 0x7c, 0x94, 0xcc, 0xcc, 0x0a, 0x9b, - 0x5e, 0x11, 0xad, 0x0b, 0x30, 0xc4, 0x5d, 0xf7, - 0x63, 0x24, 0xc1, 0xb0, 0x40, 0x5f, 0xff, 0x9f, - 0x0d, 0x7e, 0xd5, 0xa5, 0xd0, 0x4f, 0x80, 0x16, - 0xa8, 0x66, 0x18, 0x31, 0x1f, 0x81, 0xb2, 0x9a, - 0x41, 0x62, 0x5b, 0xcf, 0x73, 0xac, 0x4a, 0x64, - 0xb5, 0xc1, 0x46, 0x4d, 0x8a, 0xac, 0x25, 0xba, - 0x81, 0x7f, 0xbe, 0x64, 0x68, 0x04, 0x01, 0x00, - 0x40, 0x4e, 0x3f, 0x1e, 0x04, 0x4c, 0xef, 0xd2, - 0xa6, 0x82, 0xe6, 0x7c, 0x76, 0x23, 0x17, 0xb9, - 0xe7, 0x52, 0x15, 0x6b, 0x3d, 0xb2, 0xb1, 0x17, - 0x7d, 0xe6, 0xde, 0x06, 0x87, 0x30, 0xb0, 0xb5, - 0x57, 0xae, 0xdf, 0xb2, 0xdc, 0x8d, 0xab, 0x76, - 0x9c, 0xaa, 0x45, 0x6d, 0x23, 0x5d, 0xc1, 0xa8, - 0x7b, 0x79, 0x79, 0xb1, 0x3c, 0xdc, 0xf5, 0x33, - 0x2c, 0xa1, 0x62, 0x3e, 0xbd, 0xf5, 0x5d, 0x6c, - 0x87, 0x16, 0x03, 0x03, 0x00, 0x04, 0x0e, 0x00, - 0x00, 0x00, - }, - { - 0x16, 0x03, 0x03, 0x00, 0x46, 0x10, 0x00, 0x00, - 0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d, - 0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5, - 0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd, - 0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce, - 0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e, - 0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56, - 0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49, - 0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b, - 0xdc, 0x5a, 0x89, 0x14, 0x03, 0x03, 0x00, 0x01, - 0x01, 0x16, 0x03, 0x03, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x17, - 0x54, 0x51, 0xb6, 0x1d, 0x8e, 0xe4, 0x6b, 0xed, - 0x5b, 0xa1, 0x27, 0x7f, 0xdc, 0xa9, 0xa5, 0xcf, - 0x38, 0xe6, 0x5d, 0x17, 0x34, 0xf9, 0xc0, 0x07, - 0xb8, 0xbe, 0x56, 0xe6, 0xd6, 0x6a, 0xb6, 0x26, - 0x4e, 0x45, 0x8d, 0x48, 0xe9, 0xc6, 0xb1, 0xa1, - 0xea, 0xdc, 0xb1, 0x37, 0xd9, 0xf6, - }, - { - 0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x03, 0x00, 0x40, 0x00, 0x68, 0xc5, 0x27, 0xd5, - 0x3d, 0xba, 0x04, 0xde, 0x63, 0xf1, 0x5b, 0xc3, - 0x86, 0xb9, 0x82, 0xc7, 0xb3, 0x90, 0x31, 0xea, - 0x15, 0xe1, 0x42, 0x76, 0x7d, 0x90, 0xcb, 0xc9, - 0xd1, 0x05, 0xe6, 0x8c, 0x76, 0xc7, 0x9a, 0x35, - 0x67, 0xa2, 0x70, 0x9a, 0x8a, 0x6c, 0xb5, 0x6b, - 0xc7, 0x87, 0xf3, 0x65, 0x0a, 0xa0, 0x98, 0xba, - 0x57, 0xbb, 0x31, 0x7b, 0x1f, 0x1a, 0xf7, 0x2a, - 0xf3, 0x12, 0xf6, - }, - { - 0x17, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x80, - 0x54, 0x1e, 0x72, 0xd3, 0x1a, 0x86, 0x1c, 0xc4, - 0x4a, 0x9b, 0xd4, 0x80, 0xd2, 0x03, 0x35, 0x0d, - 0xe4, 0x12, 0xc2, 0x3d, 0x79, 0x4a, 0x2c, 0xba, - 0xc2, 0xad, 0xf3, 0xd2, 0x16, 0x15, 0x03, 0x03, - 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x9b, 0x68, 0x78, 0x92, 0x28, - 0x62, 0x02, 0x65, 0x87, 0x90, 0xe4, 0x32, 0xd7, - 0x72, 0x08, 0x70, 0xb8, 0x52, 0x32, 0x1f, 0x97, - 0xd4, 0x6a, 0xc6, 0x28, 0x83, 0xb0, 0x1d, 0x6e, - 0x16, 0xd5, - }, -} + // Update entry 0 in place. + cache.Put(keys[0], &cs[3]) + if s, ok := cache.Get(keys[0]); !ok || s != &cs[3] { + t.Fatalf("session cache failed update for key 0") + } -// $ openssl s_server -tls1_2 -cert server.crt -key server.key \ -// -port 10443 -verify 0 -// $ go test -test.run "TestRunClient" -connect -ciphersuites=0xc02f \ -// -maxversion=0x0303 -var clientTLS12ClientCertScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0x58, 0x01, 0x00, 0x00, - 0x54, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x2f, - 0x01, 0x00, 0x00, 0x29, 0x00, 0x05, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, - 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, - 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, - 0x0d, 0x00, 0x0a, 0x00, 0x08, 0x04, 0x01, 0x04, - 0x03, 0x02, 0x01, 0x02, 0x03, - }, - { - 0x16, 0x03, 0x03, 0x00, 0x54, 0x02, 0x00, 0x00, - 0x50, 0x03, 0x03, 0x52, 0x65, 0x67, 0xe0, 0xe8, - 0xf1, 0x13, 0x2a, 0x83, 0x28, 0xa8, 0x2e, 0x76, - 0x69, 0xe6, 0x89, 0x55, 0x6c, 0x48, 0x49, 0x2e, - 0x00, 0xf6, 0x87, 0x6c, 0x13, 0xa1, 0xd4, 0xaa, - 0xd0, 0x76, 0x3b, 0x20, 0xe4, 0xd6, 0x5b, 0x1d, - 0x11, 0xf2, 0x42, 0xf2, 0x82, 0x0c, 0x0d, 0x66, - 0x6d, 0xec, 0x52, 0xf8, 0x4a, 0xd9, 0x45, 0xcf, - 0xe4, 0x4a, 0xba, 0x8b, 0xf1, 0xab, 0x55, 0xe4, - 0x57, 0x18, 0xa9, 0x36, 0xc0, 0x2f, 0x00, 0x00, - 0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01, - 0x02, 0x16, 0x03, 0x03, 0x02, 0x39, 0x0b, 0x00, - 0x02, 0x35, 0x00, 0x02, 0x32, 0x00, 0x02, 0x2f, - 0x30, 0x82, 0x02, 0x2b, 0x30, 0x82, 0x01, 0xd5, - 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, - 0xb1, 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, - 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, - 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, - 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, - 0x17, 0x0d, 0x31, 0x32, 0x30, 0x34, 0x30, 0x36, - 0x31, 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x17, - 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30, 0x36, 0x31, - 0x37, 0x31, 0x30, 0x31, 0x33, 0x5a, 0x30, 0x45, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, - 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, - 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, - 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, - 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x5c, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, - 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0x9f, 0xb3, - 0xc3, 0x84, 0x27, 0x95, 0xff, 0x12, 0x31, 0x52, - 0x0f, 0x15, 0xef, 0x46, 0x11, 0xc4, 0xad, 0x80, - 0xe6, 0x36, 0x5b, 0x0f, 0xdd, 0x80, 0xd7, 0x61, - 0x8d, 0xe0, 0xfc, 0x72, 0x45, 0x09, 0x34, 0xfe, - 0x55, 0x66, 0x45, 0x43, 0x4c, 0x68, 0x97, 0x6a, - 0xfe, 0xa8, 0xa0, 0xa5, 0xdf, 0x5f, 0x78, 0xff, - 0xee, 0xd7, 0x64, 0xb8, 0x3f, 0x04, 0xcb, 0x6f, - 0xff, 0x2a, 0xfe, 0xfe, 0xb9, 0xed, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, - 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0x78, 0xa6, 0x97, 0x9a, - 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, 0x22, - 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, 0x2b, - 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x6e, 0x30, 0x6c, 0x80, 0x14, 0x78, 0xa6, 0x97, - 0x9a, 0x63, 0xb5, 0xc5, 0xa1, 0xa5, 0x33, 0xba, - 0x22, 0x7c, 0x23, 0x6e, 0x5b, 0x1b, 0x7a, 0xcc, - 0x2b, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0xb1, - 0x35, 0x13, 0x65, 0x11, 0x20, 0xc5, 0x92, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x85, - 0x36, 0x40, 0x73, 0xc1, 0xbb, 0x1a, 0xda, 0xd4, - 0x59, 0x9f, 0x2d, 0xa2, 0x70, 0x31, 0x46, 0x74, - 0xec, 0x83, 0x6e, 0xa8, 0xc8, 0x3c, 0x51, 0xaf, - 0x39, 0xac, 0xec, 0x40, 0xbc, 0xe8, 0x22, 0x46, - 0x1d, 0x99, 0xd6, 0x46, 0x2a, 0x24, 0xd4, 0x8b, - 0x05, 0x08, 0x4b, 0xfb, 0x35, 0x11, 0x6e, 0x92, - 0xbb, 0x77, 0xba, 0xe4, 0x12, 0xbb, 0xf4, 0xc8, - 0x5e, 0x9c, 0x81, 0xa8, 0x97, 0x60, 0x4c, 0x16, - 0x03, 0x03, 0x00, 0x8d, 0x0c, 0x00, 0x00, 0x89, - 0x03, 0x00, 0x17, 0x41, 0x04, 0xaa, 0xf0, 0x0c, - 0xa3, 0x60, 0xcf, 0x69, 0x1e, 0xad, 0x16, 0x9a, - 0x01, 0x40, 0xc6, 0x22, 0xc4, 0xbb, 0x06, 0x3b, - 0x84, 0x65, 0xea, 0xc7, 0xa2, 0x96, 0x79, 0x17, - 0x2f, 0xc7, 0xbe, 0x56, 0x39, 0xe4, 0x79, 0xf3, - 0xad, 0x17, 0xf3, 0x7e, 0xe2, 0x7b, 0xa2, 0x6f, - 0x3f, 0x96, 0xea, 0xe5, 0x0e, 0xea, 0x39, 0x79, - 0x77, 0xeb, 0x14, 0x18, 0xbb, 0x7c, 0x95, 0xda, - 0xa7, 0x51, 0x09, 0xba, 0xd7, 0x04, 0x01, 0x00, - 0x40, 0x82, 0x3e, 0xce, 0xee, 0x7e, 0xba, 0x3b, - 0x51, 0xb1, 0xba, 0x71, 0x2e, 0x54, 0xa9, 0xb9, - 0xe2, 0xb1, 0x59, 0x17, 0xa1, 0xac, 0x76, 0xb4, - 0x4e, 0xf1, 0xae, 0x65, 0x17, 0x2b, 0x43, 0x06, - 0x31, 0x29, 0x0b, 0xa0, 0x1e, 0xb6, 0xfa, 0x35, - 0xe8, 0x63, 0x06, 0xde, 0x13, 0x89, 0x83, 0x69, - 0x3b, 0xc2, 0x15, 0x73, 0x1c, 0xc5, 0x07, 0xe9, - 0x38, 0x9b, 0x06, 0x81, 0x1b, 0x97, 0x7c, 0xa6, - 0x89, 0x16, 0x03, 0x03, 0x00, 0x30, 0x0d, 0x00, - 0x00, 0x28, 0x03, 0x01, 0x02, 0x40, 0x00, 0x20, - 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, - 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, - 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, - 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x03, 0x0a, 0xfb, 0x0b, 0x00, 0x0a, - 0xf7, 0x00, 0x0a, 0xf4, 0x00, 0x03, 0x7e, 0x30, - 0x82, 0x03, 0x7a, 0x30, 0x82, 0x02, 0x62, 0x02, - 0x09, 0x00, 0xb4, 0x47, 0x58, 0x57, 0x2b, 0x67, - 0xc8, 0xc2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, - 0x00, 0x30, 0x81, 0x80, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, - 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, 0x31, 0x11, - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, - 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c, 0x79, - 0x6e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x0c, 0x0c, 0x4d, 0x79, 0x20, 0x43, - 0x41, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x0c, 0x0e, 0x6d, 0x79, 0x63, 0x61, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x63, 0x6f, - 0x6d, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, - 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, - 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x33, 0x30, 0x35, 0x32, 0x36, 0x32, 0x31, - 0x34, 0x34, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, - 0x33, 0x30, 0x36, 0x32, 0x35, 0x32, 0x31, 0x34, - 0x34, 0x30, 0x30, 0x5a, 0x30, 0x7d, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0f, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x0c, 0x08, 0x4e, 0x65, - 0x77, 0x20, 0x59, 0x6f, 0x72, 0x6b, 0x31, 0x11, - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, - 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c, 0x79, - 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x0c, 0x07, 0x4d, 0x79, 0x20, 0x4c, - 0x65, 0x61, 0x66, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x6d, 0x79, - 0x6c, 0x65, 0x61, 0x66, 0x2e, 0x63, 0x6f, 0x6d, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, - 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, 0x69, - 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e, - 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, - 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, - 0x82, 0x01, 0x01, 0x00, 0xa0, 0xa3, 0xef, 0xc1, - 0x44, 0x7d, 0xa2, 0xe3, 0x71, 0x98, 0x27, 0x63, - 0xb3, 0x1d, 0x71, 0x50, 0xa6, 0x34, 0x15, 0xcb, - 0xc9, 0x2a, 0xc3, 0xea, 0xe4, 0x9e, 0x9c, 0x49, - 0xa6, 0x01, 0x9b, 0x7e, 0xa9, 0xb5, 0x7a, 0xff, - 0x15, 0x92, 0x71, 0xc8, 0x97, 0x9c, 0x25, 0xb7, - 0x79, 0x2b, 0xff, 0xab, 0xc6, 0xb1, 0xa7, 0x00, - 0x90, 0xb2, 0x8b, 0xd7, 0x71, 0xd5, 0xc2, 0x3a, - 0xe6, 0x82, 0x42, 0x37, 0x89, 0x41, 0x04, 0xb0, - 0xba, 0xc7, 0x5b, 0x8a, 0x43, 0x9f, 0x97, 0x39, - 0x0c, 0x0f, 0xd5, 0x6d, 0x9e, 0x8d, 0xeb, 0xc0, - 0x26, 0xc5, 0x18, 0xe8, 0x7a, 0x3d, 0x32, 0x2e, - 0x38, 0x90, 0x40, 0x5b, 0x39, 0x2c, 0x07, 0xcb, - 0x24, 0x10, 0xc5, 0xc9, 0x3b, 0xe3, 0x66, 0x47, - 0x57, 0xb9, 0x6a, 0xad, 0x44, 0xf8, 0xd0, 0x70, - 0x62, 0x3b, 0x8e, 0xed, 0x60, 0x5f, 0x22, 0xf8, - 0xb8, 0x0c, 0xc9, 0x41, 0x2b, 0xc9, 0x80, 0x6e, - 0x4e, 0x1b, 0xe1, 0x20, 0xfc, 0x47, 0xa4, 0xac, - 0xc3, 0x3f, 0xe6, 0xc2, 0x81, 0x79, 0x03, 0x37, - 0x25, 0x89, 0xca, 0xd6, 0xa5, 0x46, 0x91, 0x63, - 0x41, 0xc5, 0x3e, 0xd5, 0xed, 0x7f, 0x4f, 0x8d, - 0x06, 0xc0, 0x89, 0x00, 0xbe, 0x37, 0x7b, 0x7e, - 0x73, 0xca, 0x70, 0x00, 0x14, 0x34, 0xbe, 0x47, - 0xbc, 0xb2, 0x6a, 0x28, 0xa5, 0x29, 0x84, 0xa8, - 0x9d, 0xc8, 0x1e, 0x77, 0x66, 0x1f, 0x9f, 0xaa, - 0x2b, 0x47, 0xdb, 0xdd, 0x6b, 0x9c, 0xa8, 0xfc, - 0x82, 0x36, 0x94, 0x62, 0x0d, 0x5c, 0x3f, 0xb2, - 0x01, 0xb4, 0xa5, 0xb8, 0xc6, 0x0e, 0x94, 0x5b, - 0xec, 0x5e, 0xbb, 0x7a, 0x63, 0x24, 0xf1, 0xf9, - 0xd6, 0x50, 0x08, 0xc1, 0xa3, 0xcc, 0x90, 0x07, - 0x5b, 0x04, 0x04, 0x42, 0x74, 0xcf, 0x37, 0xfa, - 0xf0, 0xa5, 0xd9, 0xd3, 0x86, 0x89, 0x89, 0x18, - 0xf3, 0x4c, 0xe2, 0x11, 0x02, 0x03, 0x01, 0x00, - 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, - 0x03, 0x82, 0x01, 0x01, 0x00, 0x90, 0xbb, 0xf9, - 0x5e, 0xba, 0x17, 0x1f, 0xac, 0x21, 0x9f, 0x6b, - 0x4a, 0x46, 0xd0, 0x6d, 0x3c, 0x8f, 0x3d, 0xf8, - 0x5e, 0x3e, 0x72, 0xaf, 0xa0, 0x1a, 0xf3, 0xff, - 0x89, 0xac, 0x5b, 0x7a, 0xe2, 0x91, 0x2a, 0x23, - 0x85, 0xc6, 0x4d, 0x47, 0x67, 0x01, 0x08, 0xa8, - 0x05, 0x1d, 0x01, 0x60, 0x50, 0x5f, 0x59, 0xad, - 0xfe, 0x7b, 0xc6, 0x0c, 0x54, 0x90, 0x68, 0x70, - 0x67, 0x2e, 0xed, 0x87, 0xf8, 0x69, 0x8a, 0xac, - 0x32, 0xfe, 0x6f, 0x90, 0x19, 0x2a, 0x64, 0x8d, - 0x82, 0x66, 0x05, 0x43, 0x88, 0xee, 0xf2, 0x30, - 0xed, 0xa4, 0x8f, 0xbf, 0xd6, 0x57, 0x20, 0xd4, - 0x43, 0x1d, 0x52, 0x96, 0x6f, 0xae, 0x09, 0x96, - 0x01, 0x52, 0x38, 0xe3, 0xaf, 0x99, 0xd7, 0xdc, - 0x14, 0x99, 0xc4, 0x8b, 0x0e, 0x04, 0x0f, 0xb3, - 0x14, 0x14, 0xd4, 0xa5, 0x93, 0xe1, 0xc9, 0x8a, - 0x81, 0xef, 0x63, 0xfc, 0x36, 0x77, 0x05, 0x06, - 0xf0, 0x2a, 0x04, 0x0a, 0xbe, 0x2e, 0xce, 0x81, - 0x3d, 0x23, 0xa1, 0xda, 0xd8, 0xeb, 0xc6, 0xea, - 0x5e, 0xcf, 0x28, 0x36, 0x51, 0x31, 0x95, 0x5e, - 0x40, 0x04, 0xed, 0xac, 0xc1, 0xc8, 0x56, 0x69, - 0x87, 0xec, 0x3b, 0x03, 0x3e, 0x9d, 0x0f, 0x4c, - 0x4c, 0xeb, 0xd7, 0xba, 0x26, 0xdf, 0xe3, 0xde, - 0x10, 0xee, 0x93, 0x62, 0x8d, 0x73, 0x52, 0x6e, - 0xff, 0x37, 0x36, 0x98, 0x7b, 0x2d, 0x56, 0x4c, - 0xba, 0x09, 0xb8, 0xa7, 0xf0, 0x3b, 0x16, 0x81, - 0xca, 0xdb, 0x43, 0xab, 0xec, 0x4c, 0x6e, 0x7c, - 0xc1, 0x0b, 0x22, 0x22, 0x43, 0x1d, 0xb6, 0x0c, - 0xc1, 0xb9, 0xcf, 0xe4, 0x53, 0xee, 0x1d, 0x3e, - 0x88, 0xa7, 0x13, 0xbe, 0x7f, 0xbd, 0xae, 0x72, - 0xcf, 0xcd, 0x63, 0xd2, 0xc3, 0x18, 0x58, 0x92, - 0xa2, 0xad, 0xb5, 0x09, 0x9d, 0x91, 0x03, 0xdd, - 0x3c, 0xe2, 0x1c, 0xde, 0x78, 0x00, 0x03, 0x88, - 0x30, 0x82, 0x03, 0x84, 0x30, 0x82, 0x02, 0x6c, - 0x02, 0x09, 0x00, 0xab, 0xed, 0xa6, 0xe4, 0x4a, - 0x2b, 0x2b, 0xf8, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x30, 0x81, 0x86, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, 0x31, - 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c, - 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x79, 0x20, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, - 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, - 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, 0x72, 0x67, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, - 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, 0x69, - 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e, - 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, - 0x33, 0x30, 0x35, 0x32, 0x36, 0x32, 0x31, 0x31, - 0x38, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x33, - 0x30, 0x36, 0x32, 0x35, 0x32, 0x31, 0x31, 0x38, - 0x34, 0x30, 0x5a, 0x30, 0x81, 0x80, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, - 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, - 0x6c, 0x79, 0x6e, 0x31, 0x15, 0x30, 0x13, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0c, 0x4d, 0x79, - 0x20, 0x43, 0x41, 0x20, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x6d, 0x79, 0x63, - 0x61, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, - 0x63, 0x6f, 0x6d, 0x31, 0x21, 0x30, 0x1f, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x01, 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, - 0x61, 0x68, 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, - 0x69, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, - 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, - 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, - 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xce, - 0x13, 0xf0, 0x72, 0xb0, 0x61, 0xc8, 0x18, 0x37, - 0x8a, 0x41, 0x3d, 0x20, 0xa1, 0x1c, 0xcb, 0xbf, - 0xf6, 0x3b, 0x74, 0x26, 0x2a, 0x96, 0x11, 0xec, - 0x53, 0xa1, 0xcc, 0x7d, 0x77, 0x56, 0x45, 0x0f, - 0x36, 0xb7, 0xf2, 0x48, 0x92, 0x1a, 0x62, 0xcc, - 0xb6, 0xc0, 0xa1, 0x2f, 0x44, 0x2b, 0xc1, 0x89, - 0xcb, 0x6e, 0x1e, 0xdb, 0x57, 0x92, 0xd5, 0x97, - 0x60, 0x8c, 0x41, 0x2c, 0xd9, 0x20, 0xfe, 0xe9, - 0x1f, 0x8e, 0xfc, 0x7f, 0x02, 0x44, 0x0f, 0x28, - 0x81, 0xd6, 0x0c, 0xcd, 0xbc, 0xf0, 0x57, 0x6c, - 0xcc, 0xa7, 0xba, 0x06, 0xa0, 0xa6, 0x91, 0xda, - 0xef, 0x46, 0x8a, 0x60, 0x0f, 0x52, 0x6c, 0x90, - 0x6c, 0x8c, 0x44, 0xaf, 0xb0, 0x9d, 0x90, 0xba, - 0x21, 0x58, 0xa0, 0x3c, 0xee, 0x54, 0xb5, 0x29, - 0x26, 0x1f, 0x0a, 0xac, 0xef, 0x48, 0x68, 0x33, - 0xd0, 0x33, 0xd0, 0x8b, 0x1a, 0xec, 0x6e, 0x2f, - 0xb5, 0x4a, 0x53, 0xc2, 0x1a, 0xd2, 0xf1, 0x50, - 0x05, 0x59, 0x5c, 0xd9, 0xda, 0x03, 0x0a, 0x47, - 0xb7, 0xdd, 0xf7, 0x3a, 0x69, 0xf5, 0x4e, 0xea, - 0x4a, 0xc2, 0xca, 0x54, 0xb0, 0x8b, 0x76, 0xe1, - 0x02, 0x2d, 0x52, 0x67, 0xb9, 0xdd, 0x50, 0xc9, - 0x3b, 0x07, 0x24, 0x22, 0x6a, 0x00, 0x1d, 0x58, - 0x83, 0xa8, 0xec, 0x95, 0xf1, 0xda, 0xe2, 0x73, - 0xa0, 0xa1, 0x72, 0x60, 0x9e, 0x86, 0x53, 0xcb, - 0x45, 0xa8, 0xc2, 0xa0, 0x50, 0xa0, 0x53, 0xd6, - 0xfc, 0x18, 0x84, 0xb5, 0x4a, 0x26, 0xd0, 0xa2, - 0xaa, 0xd0, 0xff, 0xb6, 0xfe, 0x3a, 0x9c, 0xb5, - 0x19, 0x3b, 0x3f, 0xe1, 0x48, 0x0d, 0xa4, 0x09, - 0x4f, 0x83, 0xc9, 0xc0, 0xc9, 0xa6, 0x0b, 0x58, - 0x1f, 0x1c, 0x7b, 0xac, 0xa2, 0x42, 0xbc, 0x61, - 0xf4, 0x21, 0x8a, 0x00, 0xda, 0x14, 0xa0, 0x60, - 0x03, 0xfe, 0x93, 0x12, 0x6c, 0x56, 0xcd, 0x02, - 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, - 0x25, 0x29, 0x3b, 0x1e, 0xc3, 0x58, 0x32, 0xe6, - 0x23, 0xc8, 0xee, 0x18, 0xf0, 0x1d, 0x62, 0x6d, - 0x3b, 0x59, 0x99, 0x3a, 0xfe, 0x49, 0x72, 0x07, - 0x3f, 0x58, 0x93, 0xdb, 0xc0, 0xaf, 0xb0, 0xb3, - 0x5c, 0xd1, 0x5c, 0x98, 0xc8, 0xea, 0x4a, 0xe4, - 0x58, 0x73, 0x0d, 0x57, 0xc5, 0x13, 0x7c, 0x5c, - 0x79, 0x66, 0xda, 0x04, 0x1d, 0xe5, 0x98, 0xda, - 0x35, 0x47, 0x44, 0xb0, 0xd2, 0x7a, 0x66, 0x9d, - 0xcd, 0x41, 0xa5, 0x8f, 0xa1, 0x11, 0xb2, 0x1a, - 0x87, 0xc0, 0xcd, 0x55, 0xed, 0xb4, 0x7b, 0x33, - 0x72, 0xeb, 0xf7, 0xe3, 0x7b, 0x8b, 0x02, 0x86, - 0xe9, 0x2b, 0x26, 0x32, 0x9f, 0x99, 0xf1, 0xcb, - 0x93, 0xab, 0xb9, 0x16, 0xb3, 0x9a, 0xb2, 0x22, - 0x13, 0x21, 0x1f, 0x5b, 0xcc, 0xa2, 0x59, 0xbb, - 0x69, 0xf2, 0xb8, 0x07, 0x80, 0xce, 0x0c, 0xf7, - 0x98, 0x4c, 0x85, 0xc2, 0x96, 0x6a, 0x22, 0x05, - 0xe9, 0xbe, 0x48, 0xb0, 0x02, 0x5b, 0x69, 0x28, - 0x18, 0x88, 0x96, 0xe3, 0xd7, 0xc6, 0x7a, 0xd3, - 0xe9, 0x99, 0xff, 0x9d, 0xc3, 0x61, 0x4d, 0x9a, - 0x96, 0xf2, 0xc6, 0x33, 0x4d, 0xe5, 0x5d, 0x5a, - 0x68, 0x64, 0x5a, 0x82, 0x35, 0x65, 0x25, 0xe3, - 0x8c, 0x5b, 0xb0, 0xf6, 0x96, 0x56, 0xbc, 0xbf, - 0x97, 0x76, 0x4b, 0x66, 0x44, 0x81, 0xa4, 0xc4, - 0xa7, 0x31, 0xc5, 0xa1, 0x4f, 0xe8, 0xa4, 0xca, - 0x20, 0xf5, 0x01, 0x5b, 0x99, 0x4f, 0x5a, 0xf4, - 0xf0, 0x78, 0xbf, 0x71, 0x49, 0xd5, 0xf1, 0xc1, - 0xa2, 0x18, 0xfd, 0x72, 0x5b, 0x16, 0xe8, 0x92, - 0xc7, 0x37, 0x48, 0xaf, 0xee, 0x24, 0xfc, 0x35, - 0x0b, 0xc2, 0xdd, 0x05, 0xc7, 0x6e, 0xa3, 0x29, - 0xbb, 0x29, 0x7d, 0xd3, 0x2b, 0x94, 0x80, 0xc3, - 0x40, 0x53, 0x0e, 0x03, 0x54, 0x3d, 0x7b, 0x8b, - 0xce, 0xf9, 0xa4, 0x03, 0x27, 0x63, 0xec, 0x51, - 0x00, 0x03, 0xe5, 0x30, 0x82, 0x03, 0xe1, 0x30, - 0x82, 0x02, 0xc9, 0xa0, 0x03, 0x02, 0x01, 0x02, - 0x02, 0x09, 0x00, 0xcc, 0x22, 0x4c, 0x4b, 0x98, - 0xa2, 0x88, 0xfc, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x05, 0x00, 0x30, 0x81, 0x86, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, 0x31, - 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, - 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, 0x6c, - 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x79, 0x20, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, - 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, - 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, 0x72, 0x67, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, - 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, 0x69, - 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, 0x2e, - 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, - 0x33, 0x30, 0x35, 0x32, 0x36, 0x32, 0x31, 0x30, - 0x35, 0x30, 0x31, 0x5a, 0x17, 0x0d, 0x32, 0x33, - 0x30, 0x35, 0x32, 0x34, 0x32, 0x31, 0x30, 0x35, - 0x30, 0x31, 0x5a, 0x30, 0x81, 0x86, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4e, 0x59, - 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, - 0x07, 0x0c, 0x08, 0x42, 0x72, 0x6f, 0x6f, 0x6b, - 0x6c, 0x79, 0x6e, 0x31, 0x21, 0x30, 0x1f, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x79, - 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, - 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, - 0x08, 0x6d, 0x79, 0x63, 0x61, 0x2e, 0x6f, 0x72, - 0x67, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, - 0x16, 0x12, 0x6a, 0x76, 0x73, 0x68, 0x61, 0x68, - 0x69, 0x64, 0x40, 0x67, 0x6d, 0x61, 0x69, 0x6c, - 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, - 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, - 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, - 0x02, 0x82, 0x01, 0x01, 0x00, 0xf0, 0xfb, 0xad, - 0x80, 0x5e, 0x37, 0xd3, 0x6d, 0xee, 0x2e, 0xcc, - 0xbc, 0x0c, 0xd7, 0x56, 0x4b, 0x56, 0x45, 0xcd, - 0x28, 0xb6, 0x22, 0xe9, 0xe2, 0x0f, 0xd1, 0x87, - 0x2a, 0x27, 0xce, 0x77, 0x8d, 0x6e, 0x0e, 0x0f, - 0xfb, 0x66, 0xe1, 0xb5, 0x0e, 0x9a, 0xb6, 0x05, - 0x8e, 0xb3, 0xe1, 0xc5, 0x77, 0x86, 0x5b, 0x46, - 0xd2, 0x0b, 0x92, 0x03, 0x1b, 0x89, 0x0c, 0x1b, - 0x10, 0x0e, 0x99, 0x8f, 0xe2, 0x17, 0xe8, 0xc2, - 0x30, 0x00, 0x47, 0xd6, 0xfc, 0xf9, 0x0f, 0x3b, - 0x75, 0x34, 0x8d, 0x4d, 0xb0, 0x99, 0xb7, 0xa0, - 0x6d, 0xa0, 0xb6, 0xad, 0xda, 0x07, 0x5e, 0x38, - 0x2e, 0x02, 0xe4, 0x30, 0x6d, 0xae, 0x13, 0x72, - 0xd4, 0xc8, 0xce, 0x14, 0x07, 0xae, 0x23, 0x8c, - 0x8f, 0x9e, 0x8c, 0x60, 0xd6, 0x06, 0xb9, 0xef, - 0x00, 0x18, 0xc0, 0x1d, 0x25, 0x1e, 0xda, 0x3e, - 0x2f, 0xcf, 0x2b, 0x56, 0x84, 0x9e, 0x30, 0x21, - 0xc7, 0x29, 0xf6, 0x03, 0x8a, 0x24, 0xf9, 0x34, - 0xac, 0x65, 0x9d, 0x80, 0x36, 0xc8, 0x3b, 0x15, - 0x10, 0xbd, 0x51, 0xe9, 0xbc, 0x02, 0xe1, 0xe9, - 0xb3, 0x5a, 0x9a, 0x99, 0x41, 0x1b, 0x27, 0xa0, - 0x4d, 0x50, 0x9e, 0x27, 0x7f, 0xa1, 0x7d, 0x09, - 0x87, 0xbd, 0x8a, 0xca, 0x5f, 0xb1, 0xa5, 0x08, - 0xb8, 0x04, 0xd4, 0x52, 0x89, 0xaa, 0xe0, 0x7d, - 0x42, 0x2e, 0x2f, 0x15, 0xee, 0x66, 0x57, 0x0f, - 0x13, 0x19, 0x45, 0xa8, 0x4b, 0x5d, 0x81, 0x66, - 0xcc, 0x12, 0x37, 0x94, 0x5e, 0xfd, 0x3c, 0x10, - 0x81, 0x51, 0x3f, 0xfa, 0x0f, 0xdd, 0xa1, 0x89, - 0x03, 0xa9, 0x78, 0x91, 0xf5, 0x3b, 0xf3, 0xbc, - 0xac, 0xbe, 0x93, 0x30, 0x2e, 0xbe, 0xca, 0x7f, - 0x46, 0xd3, 0x28, 0xb4, 0x4e, 0x91, 0x7b, 0x5b, - 0x43, 0x6c, 0xaf, 0x9b, 0x5c, 0x6a, 0x6d, 0x5a, - 0xdb, 0x79, 0x5e, 0x6a, 0x6b, 0x02, 0x03, 0x01, - 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, - 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, - 0x14, 0x6b, 0x1e, 0x00, 0xa8, 0x9f, 0xfa, 0x7d, - 0x00, 0xf9, 0xe0, 0x9d, 0x0f, 0x90, 0x8c, 0x90, - 0xa8, 0xa1, 0x37, 0x6b, 0xda, 0x30, 0x1f, 0x06, - 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, - 0x80, 0x14, 0x6b, 0x1e, 0x00, 0xa8, 0x9f, 0xfa, - 0x7d, 0x00, 0xf9, 0xe0, 0x9d, 0x0f, 0x90, 0x8c, - 0x90, 0xa8, 0xa1, 0x37, 0x6b, 0xda, 0x30, 0x0c, - 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, - 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, - 0xcd, 0x6f, 0x73, 0x4d, 0x56, 0x0b, 0xf3, 0x2e, - 0x1c, 0xe2, 0x02, 0x0c, 0x14, 0xbb, 0x2f, 0xdd, - 0x3c, 0x43, 0xfe, 0xdf, 0x94, 0x2d, 0xa9, 0x89, - 0x81, 0x51, 0xf8, 0x5f, 0xa7, 0xa0, 0x13, 0xaa, - 0xcc, 0xb0, 0x18, 0xe2, 0x57, 0x3e, 0x0d, 0x29, - 0x93, 0xe8, 0x95, 0xd5, 0x1b, 0x53, 0xd2, 0x51, - 0xf2, 0xbd, 0xf5, 0x9e, 0x7b, 0x22, 0x65, 0x62, - 0x5c, 0xc4, 0x4c, 0x1d, 0xe8, 0xe9, 0xc3, 0xd4, - 0x2b, 0xe7, 0x78, 0xcb, 0x10, 0xf3, 0xfe, 0x06, - 0x83, 0xdc, 0x3a, 0x1e, 0x62, 0x10, 0xc0, 0x46, - 0x77, 0xc6, 0x9d, 0x9f, 0xab, 0x96, 0x25, 0x5c, - 0xfb, 0x26, 0xc1, 0x15, 0x1f, 0xa5, 0x33, 0xee, - 0x4f, 0x9a, 0x14, 0x6a, 0x14, 0x97, 0x93, 0x2b, - 0x95, 0x0b, 0xdc, 0xa8, 0xd7, 0x69, 0x2e, 0xf0, - 0x01, 0x0e, 0xfd, 0x4e, 0xd0, 0xd9, 0xa8, 0xe5, - 0x65, 0xde, 0xfb, 0xca, 0xca, 0x1c, 0x5f, 0xf9, - 0x53, 0xa0, 0x87, 0xe7, 0x33, 0x9b, 0x2f, 0xcf, - 0xe4, 0x13, 0xfc, 0xec, 0x7a, 0x6c, 0xb0, 0x90, - 0x13, 0x9b, 0xb6, 0xc5, 0x03, 0xf6, 0x0e, 0x5e, - 0xe2, 0xe4, 0x26, 0xc1, 0x7e, 0x53, 0xfe, 0x69, - 0xa3, 0xc7, 0xd8, 0x8e, 0x6e, 0x94, 0x32, 0xa0, - 0xde, 0xca, 0xb6, 0xcc, 0xd6, 0x01, 0xd5, 0x78, - 0x40, 0x28, 0x63, 0x9b, 0xee, 0xcf, 0x09, 0x3b, - 0x35, 0x04, 0xf0, 0x14, 0x02, 0xf6, 0x80, 0x0e, - 0x90, 0xb2, 0x94, 0xd2, 0x25, 0x16, 0xb8, 0x7a, - 0x76, 0x87, 0x84, 0x9f, 0x84, 0xc5, 0xaf, 0xc2, - 0x6d, 0x68, 0x7a, 0x84, 0x9c, 0xc6, 0x8a, 0x63, - 0x60, 0x87, 0x6a, 0x25, 0xc1, 0xa1, 0x78, 0x0f, - 0xba, 0xe8, 0x5f, 0xe1, 0xba, 0xac, 0xa4, 0x6f, - 0xdd, 0x09, 0x3f, 0x12, 0xcb, 0x1d, 0xf3, 0xcf, - 0x48, 0xd7, 0xd3, 0x26, 0xe8, 0x9c, 0xc3, 0x53, - 0xb3, 0xba, 0xdc, 0x32, 0x99, 0x98, 0x96, 0xd6, - 0x16, 0x03, 0x03, 0x00, 0x46, 0x10, 0x00, 0x00, - 0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d, - 0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5, - 0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd, - 0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce, - 0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e, - 0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56, - 0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49, - 0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b, - 0xdc, 0x5a, 0x89, 0x16, 0x03, 0x03, 0x01, 0x08, - 0x0f, 0x00, 0x01, 0x04, 0x04, 0x01, 0x01, 0x00, - 0x7e, 0xe4, 0x65, 0x02, 0x8e, 0xb3, 0x34, 0x6a, - 0x47, 0x71, 0xd1, 0xb0, 0x8d, 0x3c, 0x0c, 0xe1, - 0xde, 0x7e, 0x5f, 0xb4, 0x15, 0x2d, 0x32, 0x0a, - 0x2a, 0xdb, 0x9b, 0x40, 0xba, 0xce, 0x8b, 0xf5, - 0x74, 0xc1, 0x68, 0x20, 0x7c, 0x87, 0x23, 0x13, - 0xc3, 0x13, 0xa7, 0xdb, 0xec, 0x59, 0xa0, 0x40, - 0x9e, 0x64, 0x03, 0x60, 0xac, 0x76, 0xff, 0x01, - 0x34, 0x7b, 0x32, 0x26, 0xd9, 0x41, 0x31, 0x93, - 0xaa, 0x30, 0x51, 0x83, 0x85, 0x40, 0xeb, 0x4e, - 0x66, 0x39, 0x83, 0xb1, 0x30, 0x0d, 0x96, 0x01, - 0xee, 0x81, 0x53, 0x5e, 0xec, 0xa9, 0xc9, 0xdf, - 0x7e, 0xc1, 0x09, 0x47, 0x8b, 0x35, 0xdb, 0x10, - 0x15, 0xd4, 0xc7, 0x5a, 0x39, 0xe3, 0xc0, 0xf3, - 0x93, 0x38, 0x11, 0xdc, 0x71, 0xbb, 0xc7, 0x62, - 0x2b, 0x85, 0xad, 0x6b, 0x4f, 0x09, 0xb3, 0x31, - 0xa8, 0xe5, 0xd1, 0xb3, 0xa9, 0x21, 0x37, 0x50, - 0xc8, 0x7d, 0xc3, 0xd2, 0xf7, 0x00, 0xd3, 0xdb, - 0x0f, 0x82, 0xf2, 0x43, 0xcf, 0x36, 0x6c, 0x98, - 0x63, 0xd8, 0x1d, 0xb3, 0xf3, 0xde, 0x63, 0x79, - 0x64, 0xf0, 0xdb, 0x46, 0x04, 0xe1, 0x1c, 0x57, - 0x0f, 0x9e, 0x96, 0xb9, 0x93, 0x45, 0x71, 0x1c, - 0x8b, 0x65, 0x7d, 0x1e, 0xad, 0xbd, 0x03, 0x51, - 0xae, 0x44, 0xef, 0x97, 0x45, 0x0d, 0x8d, 0x41, - 0x5c, 0x80, 0x7b, 0xe6, 0xe0, 0xbc, 0xa6, 0x72, - 0x95, 0xa0, 0x97, 0xe1, 0xbb, 0xc0, 0xcc, 0xe5, - 0x1e, 0xc3, 0xbe, 0xd7, 0x42, 0x2a, 0xf3, 0x75, - 0x8a, 0x44, 0x67, 0x3c, 0xe5, 0x68, 0x78, 0xe5, - 0x40, 0x1f, 0xf0, 0x89, 0x57, 0xda, 0xee, 0x45, - 0xf4, 0x44, 0x81, 0x01, 0x77, 0xf0, 0x4a, 0x14, - 0xb1, 0x3f, 0x60, 0x2b, 0xeb, 0x42, 0x38, 0xa6, - 0xfb, 0xe5, 0x4d, 0x71, 0xdc, 0x7d, 0x0a, 0x72, - 0x56, 0x28, 0x9d, 0xa6, 0x8e, 0x74, 0x2d, 0xbd, - 0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x31, 0x4d, 0x58, 0x94, 0x0b, - 0x0b, 0x06, 0x5f, 0xae, 0x57, 0x17, 0x98, 0x86, - 0xaa, 0x49, 0x17, 0x7f, 0xbd, 0x41, 0x05, 0xa5, - 0x74, 0x1c, 0x58, 0xc8, 0x38, 0x2d, 0x99, 0x5d, - 0xe5, 0x12, 0x43, - }, - { - 0x14, 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x03, 0x00, 0x28, 0xf2, 0x60, 0xc2, 0x75, 0x27, - 0x64, 0xf4, 0x05, 0x98, 0xc9, 0xd3, 0xa8, 0x00, - 0x4c, 0xa0, 0x49, 0x82, 0x68, 0xf1, 0x21, 0x05, - 0x7b, 0x4b, 0x25, 0x3e, 0xe1, 0x5f, 0x0f, 0x84, - 0x26, 0x2d, 0x16, 0x2e, 0xc0, 0xfd, 0xdf, 0x0a, - 0xf4, 0xba, 0x19, - }, - { - 0x17, 0x03, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x35, 0xef, 0x9d, - 0x6a, 0x86, 0x98, 0xc5, 0xca, 0x55, 0xca, 0x89, - 0x29, 0xb4, 0x55, 0xd4, 0x41, 0x08, 0x96, 0xe0, - 0xf3, 0x39, 0xfc, 0x15, 0x03, 0x03, 0x00, 0x1a, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x02, 0x63, 0x1b, 0xaa, 0xc6, 0xc9, 0x6d, 0x72, - 0x24, 0x10, 0x55, 0xa9, 0x8c, 0x3b, 0x23, 0xce, - 0xd8, 0x4a, - }, + // Adding a nil entry is valid. + cache.Put(keys[0], nil) + if s, ok := cache.Get(keys[0]); !ok || s != nil { + t.Fatalf("failed to add nil entry to cache") + } } -var testClientChainCertificate = fromHex( - "2d2d2d2d2d424547494e2050524956415445204b" + - "45592d2d2d2d2d0a4d494945766749424144414e" + - "42676b71686b6947397730424151454641415343" + - "424b67776767536b41674541416f494241514367" + - "6f2b2f4252483269343347590a4a324f7a485846" + - "51706a515679386b71772b726b6e70784a706747" + - "6266716d31657638566b6e48496c35776c74336b" + - "722f367647736163416b4c4b4c313348560a776a" + - "726d676b493369554545734c7248573470446e35" + - "633544412f56625a364e3638416d78526a6f656a" + - "30794c6a6951514673354c41664c4a4244467954" + - "766a0a5a6b64587557717452506a51634749376a" + - "75316758794c3475417a4a5153764a6747354f47" + - "2b45672f45656b724d4d2f35734b4265514d334a" + - "596e4b317156470a6b574e427854375637583950" + - "6a5162416951432b4e33742b6338707741425130" + - "766b6538736d6f6f70536d45714a3349486e646d" + - "48352b714b306662335775630a715079434e7052" + - "694456772f7367473070626a4744705262374636" + - "37656d4d6b38666e5755416a426f387951423173" + - "4542454a307a7a6636384b585a3034614a0a6952" + - "6a7a544f495241674d424141454367674542414a" + - "4b613676326b5a3144596146786e586d7369624c" + - "386734426f67514c6a42307362524a6d746b6b4d" + - "54370a685343325873537551522f446c654d7148" + - "664555786731784a717579597643544d44585972" + - "473667354a5051744d4432465a424a7239626c65" + - "467138386c706a0a543766514e793571354c2b4f" + - "682f6b62433835436e623641753641656978776d" + - "2b6e77665a4f3766726b6278306d35516b715975" + - "5739392f452b69502b454e570a76396a68773436" + - "76515065563236494b79717656462b4f7362722f" + - "6152316138707948336361566e3579594a433346" + - "5855756c6f5a77516331714a6b4c434c4c0a375a" + - "49744f525a78514c486d4d4a654d44722f5a4942" + - "34675467645650636145375a4d5141714d6d3066" + - "4c6b6d7671723149526b77642f6831455a645650" + - "79320a742f6b6b43413039566336663749556575" + - "6f67706d705a50303130564e376b6277394a6348" + - "75544561564543675945417a47395679426e6d62" + - "6858496c57764f0a71583747524f2f5231636a2b" + - "6b564e35377876674b54756b35592b7a4d774a48" + - "32626c57435945513251753974446c476854756b" + - "664273385746772b6e6263460a7a6f706d535245" + - "6c6d464d2f6141536d464733574e5a7072696a68" + - "504b77726338376470636b31703131635a415478" + - "5a413168566d43743457616343673634690a4d74" + - "64507a334e2f34416147664956794d2b69624949" + - "35332f515543675945417953693556735a356f6a" + - "644a795077426e6c6142554231686f2b336b7068" + - "70770a7264572b2b4d796b51494a345564534437" + - "3052486e5a315839754359713978616671746c51" + - "664c44395963442f436d665264706461586c5673" + - "5249467a5a556c0a454630557149644e77337046" + - "68634f4a6d6e5a3241434470434342476f763542" + - "6e3068302b3137686a4b376f69315833716e4542" + - "7857326c7462593476556a500a44394c5330666e" + - "4a76703043675942504a527330714c4a4a464333" + - "6669796b712f57574d38727474354b364a584b50" + - "734b674b53644144577a7463316645434d0a7a65" + - "2b394a6a5a376b4d77557063666a644c2b745047" + - "3455563048326c524375635735414131396d7058" + - "50367454494733713737655a6b416e65516f6163" + - "41340a716c3073583051476c6a5763414e30464b" + - "6f4759733975582b6378445a6e7265362f52392f" + - "3930567766443237454c57546373677734633463" + - "514b42675143420a6f5432326e745a5a59396d6e" + - "72455a36752f492f4a332f35664e396737783733" + - "3177746e463745745a5361575453587364597256" + - "466b564f6362505135494a6f0a714a6a7249372b" + - "474a4d69376f6a4c69642f4c45656f31764f3163" + - "454158334f43723236554e38612f6c7434394f5a" + - "69354c337348556b756c475951755671650a6737" + - "6e6e4632437749544c34503645486443575a4461" + - "7a4136626d7375524f2b6462536e335a6c567651" + - "4b42674859524c5a665458536c44755264776977" + - "746b0a513148546b6d6b57694156726c4f577864" + - "5858456d546130303045574c46446145797a7358" + - "7834424863357166776b5a4e746b634a56396e58" + - "63536e647441530a35767a427a676e797a4f7962" + - "68315878484a3966427472414f3847555878446c" + - "6634394457616753393449763072596e616b7656" + - "2f673039786875415763366e0a5365757230576b" + - "5376453847666653734d485149584c456b0a2d2d" + - "2d2d2d454e442050524956415445204b45592d2d" + - "2d2d2d0a2d2d2d2d2d424547494e204345525449" + - "4649434154452d2d2d2d2d0a4d494944656a4343" + - "416d494343514330523168584b326649776a414e" + - "42676b71686b6947397730424151554641444342" + - "6744454c4d416b474131554542684d430a56564d" + - "78437a414a42674e564241674d416b355a4d5245" + - "77447759445651514844416843636d3976613278" + - "35626a45564d424d47413155454367774d54586b" + - "670a51304567513278705a5735304d5263774651" + - "5944565151444441357465574e68593278705a57" + - "35304c6d4e76625445684d423847435371475349" + - "62334451454a0a41525953616e5a7a6147466f61" + - "5752415a32316861577775593239744d42345844" + - "54457a4d4455794e6a49784e4451774d466f5844" + - "54457a4d4459794e5449780a4e4451774d466f77" + - "6654454c4d416b474131554542684d4356564d78" + - "4554415042674e564241674d4345356c6479425a" + - "62334a724d52457744775944565151480a444168" + - "43636d397661327835626a45514d413447413155" + - "454367774854586b67544756685a6a45544d4245" + - "47413155454177774b62586c735a57466d4c6d4e" + - "760a625445684d42384743537147534962334451" + - "454a41525953616e5a7a6147466f615752415a32" + - "316861577775593239744d494942496a414e4267" + - "6b71686b69470a397730424151454641414f4341" + - "5138414d49494243674b43415145416f4b507677" + - "5552396f754e786d43646a73783178554b593046" + - "63764a4b735071354a36630a536159426d333670" + - "7458722f465a4a78794a65634a6264354b2f2b72" + - "7872476e414a43796939647831634936356f4a43" + - "4e346c42424c43367831754b51352b580a4f5177" + - "50315732656a6576414a73555936486f394d6934" + - "346b4542624f5377487979515178636b3734325a" + - "4856376c7172555434304842694f343774594638" + - "690a2b4c674d7955457279594275546876684950" + - "7848704b7a44502b624367586b444e79574a7974" + - "616c5270466a5163552b3165312f543430477749" + - "6b41766a64370a666e504b634141554e4c354876" + - "4c4a714b4b5570684b6964794235335a682b6671" + - "697448323931726e4b6a38676a61555967316350" + - "374942744b5734786736550a572b78657533706a" + - "4a504835316c41497761504d6b41646242415243" + - "644d38332b76436c32644f4769596b5938307a69" + - "45514944415141424d413047435371470a534962" + - "3344514542425155414134494241514351752f6c" + - "65756863667243476661307047304730386a7a33" + - "34586a357972364161382f2b4a72467436347045" + - "710a493458475455646e4151696f425230425946" + - "42665761332b6538594d564a426f634763753759" + - "6634615971734d7635766b426b715a4932435a67" + - "5644694f37790a4d4f326b6a372f575679445551" + - "7831536c6d2b75435a5942556a6a6a72356e5833" + - "42535a7849734f42412b7a46425455705a506879" + - "597142373250384e6e63460a427641714241712b" + - "4c73364250534f6832746a72787570657a796732" + - "55544756586b414537617a4279465a70682b7737" + - "417a36644430784d363965364a742f6a0a336844" + - "756b324b4e63314a752f7a63326d487374566b79" + - "364362696e384473576763726251367673544735" + - "3877517369496b4d6474677a4275632f6b552b34" + - "640a506f696e4537352f766135797a38316a3073" + - "4d59574a4b697262554a6e5a454433547a69484e" + - "35340a2d2d2d2d2d454e44204345525449464943" + - "4154452d2d2d2d2d0a2d2d2d2d2d424547494e20" + - "43455254494649434154452d2d2d2d2d0a4d4949" + - "4468444343416d7743435143723761626b536973" + - "722b44414e42676b71686b694739773042415155" + - "4641444342686a454c4d416b474131554542684d" + - "430a56564d78437a414a42674e564241674d416b" + - "355a4d524577447759445651514844416843636d" + - "397661327835626a45684d423847413155454367" + - "775954586b670a5132567964476c6d61574e6864" + - "4755675158563061473979615852354d52457744" + - "775944565151444441687465574e684c6d39795a" + - "7a45684d423847435371470a534962334451454a" + - "41525953616e5a7a6147466f615752415a323168" + - "61577775593239744d4234584454457a4d445579" + - "4e6a49784d5467304d466f584454457a0a4d4459" + - "794e5449784d5467304d466f7767594178437a41" + - "4a42674e5642415954416c56544d517377435159" + - "445651514944414a4f575445524d413847413155" + - "450a42777749516e4a7662327473655734784654" + - "415442674e5642416f4d4445313549454e424945" + - "4e7361575675644445584d425547413155454177" + - "774f62586c6a0a59574e73615756756443356a62" + - "3230784954416642676b71686b69473977304243" + - "514557456d70326332686861476c6b5147647459" + - "576c734c6d4e76625443430a415349774451594a" + - "4b6f5a496876634e415145424251414467674550" + - "4144434341516f4367674542414d345438484b77" + - "596367594e34704250534368484d752f0a396a74" + - "304a697157456578546f63783964315a46447a61" + - "33386b6953476d4c4d747343684c30517277596e" + - "4c6268376256354c566c32434d51537a5a495037" + - "700a4834373866774a454479694231677a4e7650" + - "4258624d796e75676167707048613730614b5941" + - "3953624a42736a455376734a3251756946596f44" + - "7a75564c55700a4a68384b724f3949614450514d" + - "39434c477578754c37564b553849613076465142" + - "566c6332646f44436b6533336663366166564f36" + - "6b7243796c5377693362680a416931535a376e64" + - "554d6b37427951696167416457494f6f374a5878" + - "32754a7a6f4b4679594a364755387446714d4b67" + - "554b425431767759684c564b4a7443690a717444" + - "2f747634366e4c555a4f7a2f685341326b43552b" + - "447963444a7067745948787837724b4a43764748" + - "3049596f41326853675941502b6b784a73567330" + - "430a417745414154414e42676b71686b69473977" + - "30424151554641414f43415145414a536b374873" + - "4e594d75596a794f3459384231696254745a6d54" + - "722b535849480a5031695432384376734c4e6330" + - "567959794f704b3546687a445666464533786365" + - "5762614242336c6d4e6f3152305377306e706d6e" + - "63314270592b68456249610a6838444e56653230" + - "657a4e79362f666a6534734368756b724a6a4b66" + - "6d66484c6b36753546724f617369495449523962" + - "7a4b4a5a75326e79754165417a677a330a6d4579" + - "4677705a7149675870766b6977416c74704b4269" + - "496c755058786e7254365a6e2f6e634e68545a71" + - "573873597a54655664576d686b576f49315a5358" + - "6a0a6a46757739705a57764c2b58646b746d5249" + - "476b784b637878614650364b544b495055425735" + - "6c5057765477654c397853645878776149592f58" + - "4a62467569530a787a6449722b346b2f44554c77" + - "7430467832366a4b62737066644d726c49444451" + - "464d4f413151396534764f2b6151444a32507355" + - "513d3d0a2d2d2d2d2d454e442043455254494649" + - "434154452d2d2d2d2d0a2d2d2d2d2d424547494e" + - "2043455254494649434154452d2d2d2d2d0a4d49" + - "49443454434341736d67417749424167494a414d" + - "7769544575596f6f6a384d413047435371475349" + - "623344514542425155414d4947474d5173774351" + - "59440a5651514745774a56557a454c4d416b4741" + - "31554543417743546c6b784554415042674e5642" + - "41634d43454a796232397262486c754d53457748" + - "7759445651514b0a4442684e655342445a584a30" + - "61575a70593246305a5342426458526f62334a70" + - "64486b784554415042674e5642414d4d43473135" + - "5932457562334a6e4d5345770a4877594a4b6f5a" + - "496876634e41516b4246684a71646e4e6f595768" + - "705a45426e625746706243356a62323077486863" + - "4e4d544d774e5449324d6a45774e5441780a5768" + - "634e4d6a4d774e5449304d6a45774e544178576a" + - "4342686a454c4d416b474131554542684d435656" + - "4d78437a414a42674e564241674d416b355a4d52" + - "45770a447759445651514844416843636d397661" + - "327835626a45684d423847413155454367775954" + - "586b675132567964476c6d61574e686447556751" + - "585630614739790a615852354d52457744775944" + - "565151444441687465574e684c6d39795a7a4568" + - "4d42384743537147534962334451454a41525953" + - "616e5a7a6147466f615752410a5a323168615777" + - "75593239744d494942496a414e42676b71686b69" + - "47397730424151454641414f43415138414d4949" + - "4243674b434151454138507574674634330a3032" + - "33754c737938444e645753315a467a5369324975" + - "6e69443947484b69664f6434317544672f375a75" + - "4731447071324259367a34635633686c74473067" + - "75530a4178754a4442735144706d503468666f77" + - "6a4141523962382b5138376454534e5462435a74" + - "3642746f4c6174326764654f4334433544427472" + - "684e79314d6a4f0a46416575493479506e6f7867" + - "31676135377741597742306c48746f2b4c383872" + - "566f53654d4348484b665944696954354e4b786c" + - "6e59413279447356454c31520a3662774334656d" + - "7a5770715a5152736e6f4531516e69642f6f5830" + - "4a6837324b796c2b7870516934424e5253696172" + - "67665549754c7858755a6c635045786c460a7145" + - "74646757624d456a65555876303845494652502f" + - "6f503361474a41366c346b665537383779737670" + - "4d774c72374b663062544b4c524f6b5874625132" + - "79760a6d31787162567262655635716177494441" + - "5141426f314177546a416442674e564851344546" + - "67515561783441714a2f3666514435344a30506b" + - "497951714b45330a61396f77487759445652306a" + - "42426777466f415561783441714a2f3666514435" + - "344a30506b497951714b453361396f7744415944" + - "5652305442415577417745420a2f7a414e42676b" + - "71686b6947397730424151554641414f43415145" + - "417a57397a5456594c387934633467494d464c73" + - "76335478442f742b554c616d4a675648340a5836" + - "65674536724d73426a69567a344e4b5a506f6c64" + - "556255394a52387233316e6e73695a574a637845" + - "7764364f6e443143766e654d7351382f34476739" + - "77360a486d495177455a33787032667135596c58" + - "50736d775255667054507554356f55616853586b" + - "7975564339796f31326b753841454f2f55375132" + - "616a6c5a6437370a79736f63582f6c546f49666e" + - "4d3573767a2b51542f4f7836624c435145357532" + - "78515032446c376935436242666c502b61615048" + - "324935756c444b67337371320a7a4e5942315868" + - "414b474f623773384a4f7a554538425143396f41" + - "4f6b4c4b55306955577548703268345366684d57" + - "76776d316f656f5363786f706a594964710a4a63" + - "476865412b3636462f687571796b6239304a5078" + - "4c4c48665050534e66544a75696377314f7a7574" + - "77796d5a695731673d3d0a2d2d2d2d2d454e4420" + - "43455254494649434154452d2d2d2d2d0a", -) +func TestHandshakeClientALPNMatch(t *testing.T) { + config := *testConfig + config.NextProtos = []string{"proto2", "proto1"} + + test := &clientTest{ + name: "ALPN", + // Note that this needs OpenSSL 1.0.2 because that is the first + // version that supports the -alpn flag. + command: []string{"openssl", "s_server", "-alpn", "proto1,proto2"}, + config: &config, + validate: func(state ConnectionState) error { + // The server's preferences should override the client. + if state.NegotiatedProtocol != "proto1" { + return fmt.Errorf("Got protocol %q, wanted proto1", state.NegotiatedProtocol) + } + return nil + }, + } + runClientTestTLS12(t, test) +} -// Script of interaction with openssl implementation: -// -// openssl s_server -cipher ECDHE-ECDSA-AES128-SHA \ -// -key server.key -cert server.crt -port 10443 -// -// The values for this test are obtained by building and running in client mode: -// % go test -test.run "TestRunClient" -connect -ciphersuites=0xc009 -// The recorded bytes are written to stdout. -// -// The server private key is: -// -// -----BEGIN EC PARAMETERS----- -// BgUrgQQAIw== -// -----END EC PARAMETERS----- -// -----BEGIN EC PRIVATE KEY----- -// MIHcAgEBBEIBmIPpCa0Kyeo9M/nq5mHxeFIGlw+MqakWcvHu3Keo7xK9ZWG7JG3a -// XfS01efjqSZJvF2DoL+Sly4A5iBn0Me9mdegBwYFK4EEACOhgYkDgYYABADEoe2+ -// mPkLSHM2fsMWVhEi8j1TwztNIT3Na3Xm9rDcmt8mwbyyh/ByMnyzZC8ckLzqaCMQ -// fv7jJcBIOmngKG3TNwDvBGLdDaCccGKD2IHTZDGqnpcxvZawaMCbI952ZD8aXH/p -// Eg5YWLZfcN2b2OrV1/XVzLm2nzBmW2aaIOIn5b/+Ow== -// -----END EC PRIVATE KEY----- -// -// and certificate is: -// -// -----BEGIN CERTIFICATE----- -// MIICADCCAWICCQC4vy1HoNLr9DAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw -// EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0 -// eSBMdGQwHhcNMTIxMTIyMTUwNjMyWhcNMjIxMTIwMTUwNjMyWjBFMQswCQYDVQQG -// EwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lk -// Z2l0cyBQdHkgTHRkMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAxKHtvpj5C0hz -// Nn7DFlYRIvI9U8M7TSE9zWt15vaw3JrfJsG8sofwcjJ8s2QvHJC86mgjEH7+4yXA -// SDpp4Cht0zcA7wRi3Q2gnHBig9iB02Qxqp6XMb2WsGjAmyPedmQ/Glx/6RIOWFi2 -// X3Ddm9jq1df11cy5tp8wZltmmiDiJ+W//jswCQYHKoZIzj0EAQOBjAAwgYgCQgGI -// ok/r4kXFSH0brPXtmJ2uR3DAXhu2L73xtk23YUDTEaLO7gt+kn7/dp3DO36lP876 -// EOJZ7EctfKzaTpcOFaBv0AJCAU38vmcTnC0FDr0/o4wlwTMTgw2UBrvUN3r27HrJ -// hi7d1xFpf4V8Vt77MXgr5Md4Da7Lvp5ONiQxe2oPOZUSB48q -// -----END CERTIFICATE----- -var ecdheECDSAAESClientScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0x4a, 0x01, 0x00, 0x00, - 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x09, - 0x01, 0x00, 0x00, 0x1b, 0x00, 0x05, 0x00, 0x05, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, - 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00, - 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x54, 0x02, 0x00, 0x00, - 0x50, 0x03, 0x01, 0x50, 0xd7, 0x19, 0xc9, 0x03, - 0xc2, 0x3a, 0xc6, 0x1f, 0x0a, 0x84, 0x9e, 0xd7, - 0xf4, 0x7e, 0x07, 0x6d, 0xa8, 0xe4, 0xa9, 0x4f, - 0x22, 0x50, 0xa2, 0x19, 0x24, 0x44, 0x42, 0x65, - 0xaa, 0xba, 0x3a, 0x20, 0x90, 0x70, 0xb7, 0xe5, - 0x57, 0xed, 0xb1, 0xb1, 0x43, 0x4b, 0xa1, 0x4e, - 0xee, 0x7a, 0x5b, 0x88, 0xf6, 0xa6, 0x73, 0x3b, - 0xcb, 0xa7, 0xbd, 0x57, 0x50, 0xf2, 0x72, 0x8c, - 0xbc, 0x45, 0x73, 0xaa, 0xc0, 0x09, 0x00, 0x00, - 0x08, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, 0x01, - 0x02, 0x16, 0x03, 0x01, 0x02, 0x0e, 0x0b, 0x00, - 0x02, 0x0a, 0x00, 0x02, 0x07, 0x00, 0x02, 0x04, - 0x30, 0x82, 0x02, 0x00, 0x30, 0x82, 0x01, 0x62, - 0x02, 0x09, 0x00, 0xb8, 0xbf, 0x2d, 0x47, 0xa0, - 0xd2, 0xeb, 0xf4, 0x30, 0x09, 0x06, 0x07, 0x2a, - 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01, 0x30, 0x45, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, - 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, - 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, - 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, - 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, - 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, - 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x32, 0x31, 0x31, 0x32, 0x32, 0x31, - 0x35, 0x30, 0x36, 0x33, 0x32, 0x5a, 0x17, 0x0d, - 0x32, 0x32, 0x31, 0x31, 0x32, 0x30, 0x31, 0x35, - 0x30, 0x36, 0x33, 0x32, 0x5a, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9b, 0x30, - 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, - 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, - 0x23, 0x03, 0x81, 0x86, 0x00, 0x04, 0x00, 0xc4, - 0xa1, 0xed, 0xbe, 0x98, 0xf9, 0x0b, 0x48, 0x73, - 0x36, 0x7e, 0xc3, 0x16, 0x56, 0x11, 0x22, 0xf2, - 0x3d, 0x53, 0xc3, 0x3b, 0x4d, 0x21, 0x3d, 0xcd, - 0x6b, 0x75, 0xe6, 0xf6, 0xb0, 0xdc, 0x9a, 0xdf, - 0x26, 0xc1, 0xbc, 0xb2, 0x87, 0xf0, 0x72, 0x32, - 0x7c, 0xb3, 0x64, 0x2f, 0x1c, 0x90, 0xbc, 0xea, - 0x68, 0x23, 0x10, 0x7e, 0xfe, 0xe3, 0x25, 0xc0, - 0x48, 0x3a, 0x69, 0xe0, 0x28, 0x6d, 0xd3, 0x37, - 0x00, 0xef, 0x04, 0x62, 0xdd, 0x0d, 0xa0, 0x9c, - 0x70, 0x62, 0x83, 0xd8, 0x81, 0xd3, 0x64, 0x31, - 0xaa, 0x9e, 0x97, 0x31, 0xbd, 0x96, 0xb0, 0x68, - 0xc0, 0x9b, 0x23, 0xde, 0x76, 0x64, 0x3f, 0x1a, - 0x5c, 0x7f, 0xe9, 0x12, 0x0e, 0x58, 0x58, 0xb6, - 0x5f, 0x70, 0xdd, 0x9b, 0xd8, 0xea, 0xd5, 0xd7, - 0xf5, 0xd5, 0xcc, 0xb9, 0xb6, 0x9f, 0x30, 0x66, - 0x5b, 0x66, 0x9a, 0x20, 0xe2, 0x27, 0xe5, 0xbf, - 0xfe, 0x3b, 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, - 0x48, 0xce, 0x3d, 0x04, 0x01, 0x03, 0x81, 0x8c, - 0x00, 0x30, 0x81, 0x88, 0x02, 0x42, 0x01, 0x88, - 0xa2, 0x4f, 0xeb, 0xe2, 0x45, 0xc5, 0x48, 0x7d, - 0x1b, 0xac, 0xf5, 0xed, 0x98, 0x9d, 0xae, 0x47, - 0x70, 0xc0, 0x5e, 0x1b, 0xb6, 0x2f, 0xbd, 0xf1, - 0xb6, 0x4d, 0xb7, 0x61, 0x40, 0xd3, 0x11, 0xa2, - 0xce, 0xee, 0x0b, 0x7e, 0x92, 0x7e, 0xff, 0x76, - 0x9d, 0xc3, 0x3b, 0x7e, 0xa5, 0x3f, 0xce, 0xfa, - 0x10, 0xe2, 0x59, 0xec, 0x47, 0x2d, 0x7c, 0xac, - 0xda, 0x4e, 0x97, 0x0e, 0x15, 0xa0, 0x6f, 0xd0, - 0x02, 0x42, 0x01, 0x4d, 0xfc, 0xbe, 0x67, 0x13, - 0x9c, 0x2d, 0x05, 0x0e, 0xbd, 0x3f, 0xa3, 0x8c, - 0x25, 0xc1, 0x33, 0x13, 0x83, 0x0d, 0x94, 0x06, - 0xbb, 0xd4, 0x37, 0x7a, 0xf6, 0xec, 0x7a, 0xc9, - 0x86, 0x2e, 0xdd, 0xd7, 0x11, 0x69, 0x7f, 0x85, - 0x7c, 0x56, 0xde, 0xfb, 0x31, 0x78, 0x2b, 0xe4, - 0xc7, 0x78, 0x0d, 0xae, 0xcb, 0xbe, 0x9e, 0x4e, - 0x36, 0x24, 0x31, 0x7b, 0x6a, 0x0f, 0x39, 0x95, - 0x12, 0x07, 0x8f, 0x2a, 0x16, 0x03, 0x01, 0x00, - 0xd6, 0x0c, 0x00, 0x00, 0xd2, 0x03, 0x00, 0x17, - 0x41, 0x04, 0x33, 0xed, 0xe1, 0x10, 0x3d, 0xe2, - 0xb0, 0x81, 0x5e, 0x01, 0x1b, 0x00, 0x4a, 0x7d, - 0xdc, 0xc5, 0x78, 0x02, 0xb1, 0x9a, 0x78, 0x92, - 0x34, 0xd9, 0x23, 0xcc, 0x01, 0xfb, 0x0c, 0x49, - 0x1c, 0x4a, 0x59, 0x8a, 0x80, 0x1b, 0x34, 0xf0, - 0xe8, 0x87, 0x1b, 0x7c, 0xfb, 0x72, 0xf5, 0xea, - 0xf9, 0xf3, 0xff, 0xa6, 0x3e, 0x4e, 0xac, 0xbc, - 0xee, 0x14, 0x2b, 0x87, 0xd4, 0x0b, 0xda, 0x19, - 0x60, 0x2b, 0x00, 0x8b, 0x30, 0x81, 0x88, 0x02, - 0x42, 0x01, 0x75, 0x46, 0x4f, 0x97, 0x9f, 0xc5, - 0xf9, 0x4c, 0x38, 0xcf, 0x3b, 0x37, 0x1a, 0x6b, - 0x53, 0xfc, 0x05, 0x73, 0x7d, 0x98, 0x2c, 0x5b, - 0x76, 0xd4, 0x37, 0x1f, 0x50, 0x6d, 0xad, 0xc6, - 0x0f, 0x8f, 0x7b, 0xcc, 0x60, 0x8e, 0x04, 0x00, - 0x21, 0x80, 0xa8, 0xa5, 0x98, 0xf2, 0x42, 0xf2, - 0xc3, 0xf6, 0x44, 0x50, 0xc4, 0x7a, 0xae, 0x6f, - 0x74, 0xa0, 0x7f, 0x07, 0x7a, 0x0b, 0xbb, 0x41, - 0x9e, 0x3c, 0x0b, 0x02, 0x42, 0x01, 0xbe, 0x64, - 0xaa, 0x12, 0x03, 0xfb, 0xd8, 0x4f, 0x93, 0xf9, - 0x92, 0x54, 0x0d, 0x9c, 0x9d, 0x53, 0x88, 0x19, - 0x69, 0x94, 0xfc, 0xd6, 0xf7, 0x60, 0xcf, 0x70, - 0x64, 0x15, 0x1b, 0x02, 0x22, 0x56, 0xb0, 0x2c, - 0xb1, 0x72, 0x4c, 0x9e, 0x7b, 0xf0, 0x53, 0x97, - 0x43, 0xac, 0x11, 0x62, 0xe5, 0x5a, 0xf1, 0x7e, - 0x87, 0x8f, 0x5c, 0x43, 0x1d, 0xae, 0x56, 0x28, - 0xdb, 0x76, 0x15, 0xd8, 0x1c, 0x73, 0xce, 0x16, - 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x46, 0x10, 0x00, 0x00, - 0x42, 0x41, 0x04, 0x1e, 0x18, 0x37, 0xef, 0x0d, - 0x19, 0x51, 0x88, 0x35, 0x75, 0x71, 0xb5, 0xe5, - 0x54, 0x5b, 0x12, 0x2e, 0x8f, 0x09, 0x67, 0xfd, - 0xa7, 0x24, 0x20, 0x3e, 0xb2, 0x56, 0x1c, 0xce, - 0x97, 0x28, 0x5e, 0xf8, 0x2b, 0x2d, 0x4f, 0x9e, - 0xf1, 0x07, 0x9f, 0x6c, 0x4b, 0x5b, 0x83, 0x56, - 0xe2, 0x32, 0x42, 0xe9, 0x58, 0xb6, 0xd7, 0x49, - 0xa6, 0xb5, 0x68, 0x1a, 0x41, 0x03, 0x56, 0x6b, - 0xdc, 0x5a, 0x89, 0x14, 0x03, 0x01, 0x00, 0x01, - 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0x1a, 0x45, - 0x92, 0x3b, 0xac, 0x8d, 0x91, 0x89, 0xd3, 0x2c, - 0xf4, 0x3c, 0x5f, 0x70, 0xf1, 0x79, 0xa5, 0x6a, - 0xcf, 0x97, 0x8f, 0x3f, 0x73, 0x08, 0xca, 0x3f, - 0x55, 0xb0, 0x28, 0xd1, 0x6f, 0xcd, 0x9b, 0xca, - 0xb6, 0xb7, 0xd0, 0xa5, 0x21, 0x5b, 0x08, 0xf8, - 0x42, 0xe2, 0xdf, 0x25, 0x6a, 0x16, - }, - { - 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x01, 0x00, 0x30, 0x30, 0x83, 0xb6, 0x51, 0x8a, - 0x85, 0x4a, 0xee, 0xe4, 0xb6, 0xae, 0xf3, 0xc1, - 0xdc, 0xd2, 0x04, 0xb3, 0xd0, 0x25, 0x47, 0x5f, - 0xac, 0x83, 0xa3, 0x7d, 0xcf, 0x47, 0x92, 0xed, - 0x92, 0x6c, 0xd1, 0x6e, 0xfd, 0x63, 0xf5, 0x2d, - 0x89, 0xd8, 0x04, 0x8c, 0x62, 0x71, 0xae, 0x5e, - 0x32, 0x48, 0xf8, - }, - { - 0x17, 0x03, 0x01, 0x00, 0x20, 0xcf, 0x5e, 0xba, - 0xf4, 0x47, 0x32, 0x35, 0x9b, 0x85, 0xdc, 0xb3, - 0xff, 0x77, 0x90, 0xd9, 0x2b, 0xbd, 0x59, 0x2a, - 0x33, 0xe4, 0x6e, 0x9b, 0xfc, 0x1c, 0x73, 0x3f, - 0x5e, 0x1e, 0xe3, 0xa4, 0xc2, 0x17, 0x03, 0x01, - 0x00, 0x20, 0x05, 0xdf, 0x2d, 0x9b, 0x29, 0x7f, - 0x97, 0xcd, 0x49, 0x04, 0x53, 0x22, 0x1a, 0xa1, - 0xa1, 0xe6, 0x38, 0x3a, 0x56, 0x37, 0x1f, 0xd8, - 0x3a, 0x12, 0x2c, 0xf0, 0xeb, 0x61, 0x35, 0x76, - 0xe5, 0xf0, 0x15, 0x03, 0x01, 0x00, 0x20, 0xa5, - 0x56, 0xb5, 0x49, 0x4b, 0xc2, 0xd4, 0x4c, 0xf6, - 0x95, 0x15, 0x7d, 0x41, 0x1d, 0x5c, 0x00, 0x0e, - 0x20, 0xb1, 0x0a, 0xbc, 0xc9, 0x2a, 0x09, 0x17, - 0xb4, 0xaa, 0x1c, 0x79, 0xda, 0x79, 0x27, - }, +func TestHandshakeClientALPNNoMatch(t *testing.T) { + config := *testConfig + config.NextProtos = []string{"proto3"} + + test := &clientTest{ + 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_server", "-alpn", "proto1,proto2"}, + config: &config, + validate: func(state ConnectionState) error { + // There's no overlap so OpenSSL will not select a protocol. + if state.NegotiatedProtocol != "" { + return fmt.Errorf("Got protocol %q, wanted ''", state.NegotiatedProtocol) + } + return nil + }, + } + runClientTestTLS12(t, test) } diff --git a/libgo/go/crypto/tls/handshake_messages.go b/libgo/go/crypto/tls/handshake_messages.go index 83952000f6..5d14871a34 100644 --- a/libgo/go/crypto/tls/handshake_messages.go +++ b/libgo/go/crypto/tls/handshake_messages.go @@ -7,20 +7,22 @@ package tls import "bytes" type clientHelloMsg struct { - raw []byte - vers uint16 - random []byte - sessionId []byte - cipherSuites []uint16 - compressionMethods []uint8 - nextProtoNeg bool - serverName string - ocspStapling bool - supportedCurves []uint16 - supportedPoints []uint8 - ticketSupported bool - sessionTicket []uint8 - signatureAndHashes []signatureAndHash + raw []byte + vers uint16 + random []byte + sessionId []byte + cipherSuites []uint16 + compressionMethods []uint8 + nextProtoNeg bool + serverName string + ocspStapling bool + supportedCurves []CurveID + supportedPoints []uint8 + ticketSupported bool + sessionTicket []uint8 + signatureAndHashes []signatureAndHash + secureRenegotiation bool + alpnProtocols []string } func (m *clientHelloMsg) equal(i interface{}) bool { @@ -38,11 +40,13 @@ func (m *clientHelloMsg) equal(i interface{}) bool { m.nextProtoNeg == m1.nextProtoNeg && m.serverName == m1.serverName && m.ocspStapling == m1.ocspStapling && - eqUint16s(m.supportedCurves, m1.supportedCurves) && + eqCurveIDs(m.supportedCurves, m1.supportedCurves) && bytes.Equal(m.supportedPoints, m1.supportedPoints) && m.ticketSupported == m1.ticketSupported && bytes.Equal(m.sessionTicket, m1.sessionTicket) && - eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) + eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) && + m.secureRenegotiation == m1.secureRenegotiation && + eqStrings(m.alpnProtocols, m1.alpnProtocols) } func (m *clientHelloMsg) marshal() []byte { @@ -80,6 +84,21 @@ func (m *clientHelloMsg) marshal() []byte { extensionsLength += 2 + 2*len(m.signatureAndHashes) numExtensions++ } + if m.secureRenegotiation { + extensionsLength += 1 + numExtensions++ + } + if len(m.alpnProtocols) > 0 { + extensionsLength += 2 + for _, s := range m.alpnProtocols { + if l := len(s); l == 0 || l > 255 { + panic("invalid ALPN protocol") + } + extensionsLength++ + extensionsLength += len(s) + } + numExtensions++ + } if numExtensions > 0 { extensionsLength += 4 * numExtensions length += 2 + extensionsLength @@ -114,13 +133,13 @@ func (m *clientHelloMsg) marshal() []byte { } if m.nextProtoNeg { z[0] = byte(extensionNextProtoNeg >> 8) - z[1] = byte(extensionNextProtoNeg) + z[1] = byte(extensionNextProtoNeg & 0xff) // The length is always 0 z = z[4:] } if len(m.serverName) > 0 { z[0] = byte(extensionServerName >> 8) - z[1] = byte(extensionServerName) + z[1] = byte(extensionServerName & 0xff) l := len(m.serverName) + 5 z[2] = byte(l >> 8) z[3] = byte(l) @@ -224,6 +243,34 @@ func (m *clientHelloMsg) marshal() []byte { z = z[2:] } } + if m.secureRenegotiation { + z[0] = byte(extensionRenegotiationInfo >> 8) + z[1] = byte(extensionRenegotiationInfo & 0xff) + z[2] = 0 + z[3] = 1 + z = z[5:] + } + if len(m.alpnProtocols) > 0 { + z[0] = byte(extensionALPN >> 8) + z[1] = byte(extensionALPN & 0xff) + lengths := z[2:] + z = z[6:] + + stringsLength := 0 + for _, s := range m.alpnProtocols { + l := len(s) + z[0] = byte(l) + copy(z[1:], s) + z = z[1+l:] + stringsLength += 1 + l + } + + lengths[2] = byte(stringsLength >> 8) + lengths[3] = byte(stringsLength) + stringsLength += 2 + lengths[0] = byte(stringsLength >> 8) + lengths[1] = byte(stringsLength) + } m.raw = x @@ -256,6 +303,9 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { m.cipherSuites = make([]uint16, numCipherSuites) for i := 0; i < numCipherSuites; i++ { m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i]) + if m.cipherSuites[i] == scsvRenegotiation { + m.secureRenegotiation = true + } } data = data[2+cipherSuiteLen:] if len(data) < 1 { @@ -275,6 +325,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { m.ticketSupported = false m.sessionTicket = nil m.signatureAndHashes = nil + m.alpnProtocols = nil if len(data) == 0 { // ClientHello is optionally followed by extension data @@ -341,10 +392,10 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { return false } numCurves := l / 2 - m.supportedCurves = make([]uint16, numCurves) + m.supportedCurves = make([]CurveID, numCurves) d := data[2:] for i := 0; i < numCurves; i++ { - m.supportedCurves[i] = uint16(d[0])<<8 | uint16(d[1]) + m.supportedCurves[i] = CurveID(d[0])<<8 | CurveID(d[1]) d = d[2:] } case extensionSupportedPoints: @@ -379,6 +430,29 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { m.signatureAndHashes[i].signature = d[1] d = d[2:] } + case extensionRenegotiationInfo + 1: + if length != 1 || data[0] != 0 { + return false + } + m.secureRenegotiation = true + case extensionALPN: + if length < 2 { + return false + } + l := int(data[0])<<8 | int(data[1]) + if l != length-2 { + return false + } + d := data[2:length] + for len(d) != 0 { + stringLen := int(d[0]) + d = d[1:] + if stringLen == 0 || stringLen > len(d) { + return false + } + m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen])) + d = d[stringLen:] + } } data = data[length:] } @@ -387,16 +461,18 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { } type serverHelloMsg struct { - raw []byte - vers uint16 - random []byte - sessionId []byte - cipherSuite uint16 - compressionMethod uint8 - nextProtoNeg bool - nextProtos []string - ocspStapling bool - ticketSupported bool + raw []byte + vers uint16 + random []byte + sessionId []byte + cipherSuite uint16 + compressionMethod uint8 + nextProtoNeg bool + nextProtos []string + ocspStapling bool + ticketSupported bool + secureRenegotiation bool + alpnProtocol string } func (m *serverHelloMsg) equal(i interface{}) bool { @@ -414,7 +490,9 @@ func (m *serverHelloMsg) equal(i interface{}) bool { m.nextProtoNeg == m1.nextProtoNeg && eqStrings(m.nextProtos, m1.nextProtos) && m.ocspStapling == m1.ocspStapling && - m.ticketSupported == m1.ticketSupported + m.ticketSupported == m1.ticketSupported && + m.secureRenegotiation == m1.secureRenegotiation && + m.alpnProtocol == m1.alpnProtocol } func (m *serverHelloMsg) marshal() []byte { @@ -441,6 +519,18 @@ func (m *serverHelloMsg) marshal() []byte { if m.ticketSupported { numExtensions++ } + if m.secureRenegotiation { + extensionsLength += 1 + numExtensions++ + } + if alpnLen := len(m.alpnProtocol); alpnLen > 0 { + if alpnLen >= 256 { + panic("invalid ALPN protocol") + } + extensionsLength += 2 + 1 + alpnLen + numExtensions++ + } + if numExtensions > 0 { extensionsLength += 4 * numExtensions length += 2 + extensionsLength @@ -469,7 +559,7 @@ func (m *serverHelloMsg) marshal() []byte { } if m.nextProtoNeg { z[0] = byte(extensionNextProtoNeg >> 8) - z[1] = byte(extensionNextProtoNeg) + z[1] = byte(extensionNextProtoNeg & 0xff) z[2] = byte(nextProtoLen >> 8) z[3] = byte(nextProtoLen) z = z[4:] @@ -494,6 +584,27 @@ func (m *serverHelloMsg) marshal() []byte { z[1] = byte(extensionSessionTicket) z = z[4:] } + if m.secureRenegotiation { + z[0] = byte(extensionRenegotiationInfo >> 8) + z[1] = byte(extensionRenegotiationInfo & 0xff) + z[2] = 0 + z[3] = 1 + z = z[5:] + } + if alpnLen := len(m.alpnProtocol); alpnLen > 0 { + z[0] = byte(extensionALPN >> 8) + z[1] = byte(extensionALPN & 0xff) + l := 2 + 1 + alpnLen + z[2] = byte(l >> 8) + z[3] = byte(l) + l -= 2 + z[4] = byte(l >> 8) + z[5] = byte(l) + l -= 1 + z[6] = byte(l) + copy(z[7:], []byte(m.alpnProtocol)) + z = z[7+alpnLen:] + } m.raw = x @@ -524,6 +635,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { m.nextProtos = nil m.ocspStapling = false m.ticketSupported = false + m.alpnProtocol = "" if len(data) == 0 { // ServerHello is optionally followed by extension data @@ -573,6 +685,27 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { return false } m.ticketSupported = true + case extensionRenegotiationInfo: + if length != 1 || data[0] != 0 { + return false + } + m.secureRenegotiation = true + case extensionALPN: + d := data[:length] + if len(d) < 3 { + return false + } + l := int(d[0])<<8 | int(d[1]) + if l != len(d)-2 { + return false + } + d = d[2:] + l = int(d[0]) + if l != len(d)-1 { + return false + } + d = d[1:] + m.alpnProtocol = string(d) } data = data[length:] } @@ -1255,6 +1388,18 @@ func eqUint16s(x, y []uint16) bool { return true } +func eqCurveIDs(x, y []CurveID) bool { + if len(x) != len(y) { + return false + } + for i, v := range x { + if y[i] != v { + return false + } + } + return true +} + func eqStrings(x, y []string) bool { if len(x) != len(y) { return false diff --git a/libgo/go/crypto/tls/handshake_messages_test.go b/libgo/go/crypto/tls/handshake_messages_test.go index 4f569eeb13..a96e95c3f0 100644 --- a/libgo/go/crypto/tls/handshake_messages_test.go +++ b/libgo/go/crypto/tls/handshake_messages_test.go @@ -125,9 +125,9 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value { } m.ocspStapling = rand.Intn(10) > 5 m.supportedPoints = randomBytes(rand.Intn(5)+1, rand) - m.supportedCurves = make([]uint16, rand.Intn(5)+1) + m.supportedCurves = make([]CurveID, rand.Intn(5)+1) for i := range m.supportedCurves { - m.supportedCurves[i] = uint16(rand.Intn(30000)) + m.supportedCurves[i] = CurveID(rand.Intn(30000)) } if rand.Intn(10) > 5 { m.ticketSupported = true @@ -138,6 +138,10 @@ func (*clientHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value { if rand.Intn(10) > 5 { m.signatureAndHashes = supportedSKXSignatureAlgorithms } + m.alpnProtocols = make([]string, rand.Intn(5)) + for i := range m.alpnProtocols { + m.alpnProtocols[i] = randomString(rand.Intn(20)+1, rand) + } return reflect.ValueOf(m) } @@ -166,6 +170,7 @@ func (*serverHelloMsg) Generate(rand *rand.Rand, size int) reflect.Value { if rand.Intn(10) > 5 { m.ticketSupported = true } + m.alpnProtocol = randomString(rand.Intn(32)+1, rand) return reflect.ValueOf(m) } diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go index c9ccf675cd..0d907656c6 100644 --- a/libgo/go/crypto/tls/handshake_server.go +++ b/libgo/go/crypto/tls/handshake_server.go @@ -12,6 +12,7 @@ import ( "crypto/x509" "encoding/asn1" "errors" + "fmt" "io" ) @@ -56,10 +57,10 @@ func (c *Conn) serverHandshake() error { if err := hs.establishKeys(); err != nil { return err } - if err := hs.sendFinished(); err != nil { + if err := hs.sendFinished(c.firstFinished[:]); err != nil { return err } - if err := hs.readFinished(); err != nil { + if err := hs.readFinished(nil); err != nil { return err } c.didResume = true @@ -72,13 +73,13 @@ func (c *Conn) serverHandshake() error { if err := hs.establishKeys(); err != nil { return err } - if err := hs.readFinished(); err != nil { + if err := hs.readFinished(c.firstFinished[:]); err != nil { return err } if err := hs.sendSessionTicket(); err != nil { return err } - if err := hs.sendFinished(); err != nil { + if err := hs.sendFinished(nil); err != nil { return err } } @@ -100,11 +101,13 @@ func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) { var ok bool hs.clientHello, ok = msg.(*clientHelloMsg) if !ok { - return false, c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertUnexpectedMessage) + return false, unexpectedMessageError(hs.clientHello, msg) } c.vers, ok = config.mutualVersion(hs.clientHello.vers) if !ok { - return false, c.sendAlert(alertProtocolVersion) + c.sendAlert(alertProtocolVersion) + return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers) } c.haveVers = true @@ -114,12 +117,14 @@ func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) { hs.hello = new(serverHelloMsg) supportedCurve := false + preferredCurves := config.curvePreferences() Curves: for _, curve := range hs.clientHello.supportedCurves { - switch curve { - case curveP256, curveP384, curveP521: - supportedCurve = true - break Curves + for _, supported := range preferredCurves { + if supported == curve { + supportedCurve = true + break Curves + } } } @@ -142,39 +147,55 @@ Curves: } if !foundCompression { - return false, c.sendAlert(alertHandshakeFailure) + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: client does not support uncompressed connections") } hs.hello.vers = c.vers - t := uint32(config.time().Unix()) hs.hello.random = make([]byte, 32) - hs.hello.random[0] = byte(t >> 24) - hs.hello.random[1] = byte(t >> 16) - hs.hello.random[2] = byte(t >> 8) - hs.hello.random[3] = byte(t) - _, err = io.ReadFull(config.rand(), hs.hello.random[4:]) + _, err = io.ReadFull(config.rand(), hs.hello.random) if err != nil { - return false, c.sendAlert(alertInternalError) + c.sendAlert(alertInternalError) + return false, err } + hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation hs.hello.compressionMethod = compressionNone if len(hs.clientHello.serverName) > 0 { c.serverName = hs.clientHello.serverName } - // Although sending an empty NPN extension is reasonable, Firefox has - // had a bug around this. Best to send nothing at all if - // config.NextProtos is empty. See - // https://code.google.com/p/go/issues/detail?id=5445. - if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 { - hs.hello.nextProtoNeg = true - hs.hello.nextProtos = config.NextProtos + + if len(hs.clientHello.alpnProtocols) > 0 { + if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback { + hs.hello.alpnProtocol = selectedProto + c.clientProtocol = selectedProto + } + } else { + // Although sending an empty NPN extension is reasonable, Firefox has + // had a bug around this. Best to send nothing at all if + // config.NextProtos is empty. See + // https://code.google.com/p/go/issues/detail?id=5445. + if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 { + hs.hello.nextProtoNeg = true + hs.hello.nextProtos = config.NextProtos + } } if len(config.Certificates) == 0 { - return false, c.sendAlert(alertInternalError) + c.sendAlert(alertInternalError) + return false, errors.New("tls: no certificates configured") } hs.cert = &config.Certificates[0] if len(hs.clientHello.serverName) > 0 { - hs.cert = config.getCertificateForName(hs.clientHello.serverName) + chi := &ClientHelloInfo{ + CipherSuites: hs.clientHello.cipherSuites, + ServerName: hs.clientHello.serverName, + SupportedCurves: hs.clientHello.supportedCurves, + SupportedPoints: hs.clientHello.supportedPoints, + } + if hs.cert, err = config.getCertificate(chi); err != nil { + c.sendAlert(alertInternalError) + return false, err + } } _, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey) @@ -199,7 +220,20 @@ Curves: } if hs.suite == nil { - return false, c.sendAlert(alertHandshakeFailure) + c.sendAlert(alertHandshakeFailure) + return false, errors.New("tls: no cipher suite supported by both client and server") + } + + // See https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00. + for _, id := range hs.clientHello.cipherSuites { + if id == TLS_FALLBACK_SCSV { + // The client is doing a fallback connection. + if hs.clientHello.vers < c.config.MaxVersion { + c.sendAlert(alertInappropriateFallback) + return false, errors.New("tls: client using inppropriate protocol fallback") + } + break + } } return false, nil @@ -209,6 +243,10 @@ Curves: func (hs *serverHandshakeState) checkForResumption() bool { c := hs.c + if c.config.SessionTicketsDisabled { + return false + } + var ok bool if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok { return false @@ -349,7 +387,8 @@ func (hs *serverHandshakeState) doFullHandshake() error { // certificate message, even if it's empty. if config.ClientAuth >= RequestClientCert { if certMsg, ok = msg.(*certificateMsg); !ok { - return c.sendAlert(alertHandshakeFailure) + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certMsg, msg) } hs.finishedHash.Write(certMsg.marshal()) @@ -376,7 +415,8 @@ func (hs *serverHandshakeState) doFullHandshake() error { // Get client key exchange ckx, ok := msg.(*clientKeyExchangeMsg) if !ok { - return c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(ckx, msg) } hs.finishedHash.Write(ckx.marshal()) @@ -393,7 +433,8 @@ func (hs *serverHandshakeState) doFullHandshake() error { } certVerify, ok := msg.(*certificateVerifyMsg) if !ok { - return c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(certVerify, msg) } switch key := pub.(type) { @@ -458,11 +499,11 @@ func (hs *serverHandshakeState) establishKeys() error { return nil } -func (hs *serverHandshakeState) readFinished() error { +func (hs *serverHandshakeState) readFinished(out []byte) error { c := hs.c c.readRecord(recordTypeChangeCipherSpec) - if err := c.error(); err != nil { + if err := c.in.error(); err != nil { return err } @@ -473,7 +514,8 @@ func (hs *serverHandshakeState) readFinished() error { } nextProto, ok := msg.(*nextProtoMsg) if !ok { - return c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(nextProto, msg) } hs.finishedHash.Write(nextProto.marshal()) c.clientProtocol = nextProto.proto @@ -485,16 +527,19 @@ func (hs *serverHandshakeState) readFinished() error { } clientFinished, ok := msg.(*finishedMsg) if !ok { - return c.sendAlert(alertUnexpectedMessage) + c.sendAlert(alertUnexpectedMessage) + return unexpectedMessageError(clientFinished, msg) } verify := hs.finishedHash.clientSum(hs.masterSecret) if len(verify) != len(clientFinished.verifyData) || subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 { - return c.sendAlert(alertHandshakeFailure) + c.sendAlert(alertHandshakeFailure) + return errors.New("tls: client's Finished message is incorrect") } hs.finishedHash.Write(clientFinished.marshal()) + copy(out, verify) return nil } @@ -524,7 +569,7 @@ func (hs *serverHandshakeState) sendSessionTicket() error { return nil } -func (hs *serverHandshakeState) sendFinished() error { +func (hs *serverHandshakeState) sendFinished(out []byte) error { c := hs.c c.writeRecord(recordTypeChangeCipherSpec, []byte{1}) @@ -535,6 +580,7 @@ func (hs *serverHandshakeState) sendFinished() error { c.writeRecord(recordTypeHandshake, finished.marshal()) c.cipherSuite = hs.suite.id + copy(out, finished.verifyData) return nil } @@ -594,7 +640,8 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (c case *ecdsa.PublicKey, *rsa.PublicKey: pub = key default: - return nil, c.sendAlert(alertUnsupportedCertificate) + c.sendAlert(alertUnsupportedCertificate) + return nil, fmt.Errorf("tls: client's certificate contains an unsupported public key of type %T", certs[0].PublicKey) } c.peerCertificates = certs return pub, nil diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go index c08eba7f17..0338af457e 100644 --- a/libgo/go/crypto/tls/handshake_server_test.go +++ b/libgo/go/crypto/tls/handshake_server_test.go @@ -9,23 +9,22 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rsa" - "crypto/x509" "encoding/hex" "encoding/pem" - "flag" + "errors" "fmt" "io" - "log" "math/big" "net" "os" - "strconv" + "os/exec" + "path/filepath" "strings" - "sync" "testing" "time" ) +// zeroSource is an io.Reader that returns an unlimited number of zero bytes. type zeroSource struct{} func (zeroSource) Read(b []byte) (n int, err error) { @@ -39,22 +38,22 @@ func (zeroSource) Read(b []byte) (n int, err error) { var testConfig *Config func init() { - testConfig = new(Config) - testConfig.Time = func() time.Time { return time.Unix(0, 0) } - testConfig.Rand = zeroSource{} - testConfig.Certificates = make([]Certificate, 2) + testConfig = &Config{ + Time: func() time.Time { return time.Unix(0, 0) }, + Rand: zeroSource{}, + Certificates: make([]Certificate, 2), + InsecureSkipVerify: true, + MinVersion: VersionSSL30, + MaxVersion: VersionTLS12, + } testConfig.Certificates[0].Certificate = [][]byte{testRSACertificate} testConfig.Certificates[0].PrivateKey = testRSAPrivateKey testConfig.Certificates[1].Certificate = [][]byte{testSNICertificate} testConfig.Certificates[1].PrivateKey = testRSAPrivateKey testConfig.BuildNameToCertificate() - testConfig.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA} - testConfig.InsecureSkipVerify = true - testConfig.MinVersion = VersionSSL30 - testConfig.MaxVersion = VersionTLS10 } -func testClientHelloFailure(t *testing.T, m handshakeMessage, expected error) { +func testClientHelloFailure(t *testing.T, m handshakeMessage, expectedSubStr string) { // Create in-memory network connection, // send message to server. Should return // expected error. @@ -69,20 +68,20 @@ func testClientHelloFailure(t *testing.T, m handshakeMessage, expected error) { }() err := Server(s, testConfig).Handshake() s.Close() - if e, ok := err.(*net.OpError); !ok || e.Err != expected { - t.Errorf("Got error: %s; expected: %s", err, expected) + if err == nil || !strings.Contains(err.Error(), expectedSubStr) { + t.Errorf("Got error: %s; expected to match substring '%s'", err, expectedSubStr) } } func TestSimpleError(t *testing.T) { - testClientHelloFailure(t, &serverHelloDoneMsg{}, alertUnexpectedMessage) + testClientHelloFailure(t, &serverHelloDoneMsg{}, "unexpected handshake message") } var badProtocolVersions = []uint16{0x0000, 0x0005, 0x0100, 0x0105, 0x0200, 0x0205} func TestRejectBadProtocolVersion(t *testing.T) { for _, v := range badProtocolVersions { - testClientHelloFailure(t, &clientHelloMsg{vers: v}, alertProtocolVersion) + testClientHelloFailure(t, &clientHelloMsg{vers: v}, "unsupported, maximum protocol version") } } @@ -92,7 +91,7 @@ func TestNoSuiteOverlap(t *testing.T) { cipherSuites: []uint16{0xff00}, compressionMethods: []uint8{0}, } - testClientHelloFailure(t, clientHello, alertHandshakeFailure) + testClientHelloFailure(t, clientHello, "no cipher suite supported by both client and server") } func TestNoCompressionOverlap(t *testing.T) { @@ -101,7 +100,7 @@ func TestNoCompressionOverlap(t *testing.T) { cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, compressionMethods: []uint8{0xff}, } - testClientHelloFailure(t, clientHello, alertHandshakeFailure) + testClientHelloFailure(t, clientHello, "client does not support uncompressed connections") } func TestTLS12OnlyCipherSuites(t *testing.T) { @@ -121,7 +120,7 @@ func TestTLS12OnlyCipherSuites(t *testing.T) { TLS_RSA_WITH_RC4_128_SHA, }, compressionMethods: []uint8{compressionNone}, - supportedCurves: []uint16{curveP256, curveP384, curveP521}, + supportedCurves: []CurveID{CurveP256, CurveP384, CurveP521}, supportedPoints: []uint8{pointFormatUncompressed}, } @@ -178,10 +177,12 @@ func TestClose(t *testing.T) { func testHandshake(clientConfig, serverConfig *Config) (state ConnectionState, err error) { c, s := net.Pipe() + done := make(chan bool) go func() { cli := Client(c, clientConfig) cli.Handshake() c.Close() + done <- true }() server := Server(s, serverConfig) err = server.Handshake() @@ -189,9 +190,27 @@ func testHandshake(clientConfig, serverConfig *Config) (state ConnectionState, e state = server.ConnectionState() } s.Close() + <-done return } +func TestVersion(t *testing.T) { + serverConfig := &Config{ + Certificates: testConfig.Certificates, + MaxVersion: VersionTLS11, + } + clientConfig := &Config{ + InsecureSkipVerify: true, + } + state, err := testHandshake(clientConfig, serverConfig) + if err != nil { + t.Fatalf("handshake failed: %s", err) + } + if state.Version != VersionTLS11 { + t.Fatalf("Incorrect version %x, should be %x", state.Version, VersionTLS11) + } +} + 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}, @@ -221,2920 +240,496 @@ func TestCipherSuitePreference(t *testing.T) { } } -func testServerScript(t *testing.T, name string, serverScript [][]byte, config *Config, peers []*x509.Certificate) { - c, s := net.Pipe() - srv := Server(s, config) - pchan := make(chan []*x509.Certificate, 1) - go func() { - srv.Write([]byte("hello, world\n")) - srv.Close() - s.Close() - st := srv.ConnectionState() - pchan <- st.PeerCertificates - }() +// Note: see comment in handshake_test.go for details of how the reference +// tests work. + +// serverTest represents a test of the TLS server handshake against a reference +// implementation. +type serverTest struct { + // name is a freeform string identifying the test and the file in which + // the expected results will be stored. + name string + // command, if not empty, contains a series of arguments for the + // command to run for the reference server. + command []string + // expectedPeerCerts contains a list of PEM blocks of expected + // certificates from the client. + expectedPeerCerts []string + // config, if not nil, contains a custom Config to use for this test. + config *Config + // expectAlert, if true, indicates that a fatal alert should be returned + // when handshaking with the server. + expectAlert bool + // expectHandshakeErrorIncluding, when not empty, contains a string + // that must be a substring of the error resulting from the handshake. + expectHandshakeErrorIncluding string + // validate, if not nil, is a function that will be called with the + // ConnectionState of the resulting connection. It returns false if the + // ConnectionState is unacceptable. + validate func(ConnectionState) error +} + +var defaultClientCommand = []string{"openssl", "s_client", "-no_ticket"} + +// connFromCommand starts opens a listening socket and starts the reference +// client to connect to it. It returns a recordingConn that wraps the resulting +// connection. +func (test *serverTest) connFromCommand() (conn *recordingConn, child *exec.Cmd, err error) { + l, err := net.ListenTCP("tcp", &net.TCPAddr{ + IP: net.IPv4(127, 0, 0, 1), + Port: 0, + }) + if err != nil { + return nil, nil, err + } + defer l.Close() - for i, b := range serverScript { - if i%2 == 0 { - c.Write(b) - continue - } - bb := make([]byte, len(b)) - n, err := io.ReadFull(c, bb) + port := l.Addr().(*net.TCPAddr).Port + + var command []string + command = append(command, test.command...) + if len(command) == 0 { + command = defaultClientCommand + } + command = append(command, "-connect") + command = append(command, fmt.Sprintf("127.0.0.1:%d", port)) + cmd := exec.Command(command[0], command[1:]...) + cmd.Stdin = nil + var output bytes.Buffer + cmd.Stdout = &output + cmd.Stderr = &output + if err := cmd.Start(); err != nil { + return nil, nil, err + } + + connChan := make(chan interface{}) + go func() { + tcpConn, err := l.Accept() if err != nil { - t.Fatalf("%s #%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", name, i, err, n, len(bb), bb[:n], b) + connChan <- err } - if !bytes.Equal(b, bb) { - t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", name, i, bb, b) - } - } - c.Close() - - if peers != nil { - gotpeers := <-pchan - if len(peers) == len(gotpeers) { - for i := range peers { - if !peers[i].Equal(gotpeers[i]) { - t.Fatalf("%s: mismatch on peer cert %d", name, i) - } - } - } else { - t.Fatalf("%s: mismatch on peer list length: %d (wanted) != %d (got)", name, len(peers), len(gotpeers)) + connChan <- tcpConn + }() + + var tcpConn net.Conn + select { + case connOrError := <-connChan: + if err, ok := connOrError.(error); ok { + return nil, nil, err } + tcpConn = connOrError.(net.Conn) + case <-time.After(2 * time.Second): + output.WriteTo(os.Stdout) + return nil, nil, errors.New("timed out waiting for connection from child process") } -} -func TestHandshakeServerRSARC4(t *testing.T) { - testServerScript(t, "RSA-RC4", rsaRC4ServerScript, testConfig, nil) -} - -func TestHandshakeServerRSA3DES(t *testing.T) { - des3Config := new(Config) - *des3Config = *testConfig - des3Config.CipherSuites = []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA} - testServerScript(t, "RSA-3DES", rsaDES3ServerScript, des3Config, nil) -} + record := &recordingConn{ + Conn: tcpConn, + } -func TestHandshakeServerRSAAES(t *testing.T) { - aesConfig := new(Config) - *aesConfig = *testConfig - aesConfig.CipherSuites = []uint16{TLS_RSA_WITH_AES_128_CBC_SHA} - testServerScript(t, "RSA-AES", rsaAESServerScript, aesConfig, nil) + return record, cmd, nil } -func TestHandshakeServerECDHEECDSAAES(t *testing.T) { - ecdsaConfig := new(Config) - *ecdsaConfig = *testConfig - ecdsaConfig.Certificates = make([]Certificate, 1) - ecdsaConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate} - ecdsaConfig.Certificates[0].PrivateKey = testECDSAPrivateKey - ecdsaConfig.BuildNameToCertificate() - ecdsaConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA} - testServerScript(t, "ECDHE-ECDSA-AES", ecdheECDSAAESServerScript, ecdsaConfig, nil) +func (test *serverTest) dataPath() string { + return filepath.Join("testdata", "Server-"+test.name) } -func TestHandshakeServerSSLv3(t *testing.T) { - testServerScript(t, "SSLv3", sslv3ServerScript, testConfig, nil) +func (test *serverTest) loadData() (flows [][]byte, err error) { + in, err := os.Open(test.dataPath()) + if err != nil { + return nil, err + } + defer in.Close() + return parseTestData(in) } -// TestHandshakeServerSNI involves a client sending an SNI extension of -// "snitest.com", which happens to match the CN of testSNICertificate. The test -// verifies that the server correctly selects that certificate. -func TestHandshakeServerSNI(t *testing.T) { - testServerScript(t, "SNI", selectCertificateBySNIScript, testConfig, nil) -} +func (test *serverTest) run(t *testing.T, write bool) { + var clientConn, serverConn net.Conn + var recordingConn *recordingConn + var childProcess *exec.Cmd -func TestResumption(t *testing.T) { - testServerScript(t, "IssueTicket", issueSessionTicketTest, testConfig, nil) - testServerScript(t, "Resume", serverResumeTest, testConfig, nil) -} + if write { + var err error + recordingConn, childProcess, err = test.connFromCommand() + if err != nil { + t.Fatalf("Failed to start subcommand: %s", err) + } + serverConn = recordingConn + } else { + clientConn, serverConn = net.Pipe() + } + config := test.config + if config == nil { + config = testConfig + } + server := Server(serverConn, config) + connStateChan := make(chan ConnectionState, 1) + go func() { + var err error + if _, err = server.Write([]byte("hello, world\n")); err != nil { + t.Logf("Error from Server.Write: %s", err) + } + if len(test.expectHandshakeErrorIncluding) > 0 { + if err == nil { + t.Errorf("Error expected, but no error returned") + } else if s := err.Error(); !strings.Contains(s, test.expectHandshakeErrorIncluding) { + t.Errorf("Error expected containing '%s' but got '%s'", test.expectHandshakeErrorIncluding, s) + } + } + server.Close() + serverConn.Close() + connStateChan <- server.ConnectionState() + }() -func TestTLS12ClientCertServer(t *testing.T) { - config := *testConfig - config.MaxVersion = VersionTLS12 - config.ClientAuth = RequireAnyClientCert - config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA} + if !write { + flows, err := test.loadData() + if err != nil { + if !test.expectAlert { + t.Fatalf("%s: failed to load data from %s", test.name, test.dataPath()) + } + } + for i, b := range flows { + if i%2 == 0 { + clientConn.Write(b) + continue + } + bb := make([]byte, len(b)) + n, err := io.ReadFull(clientConn, bb) + if test.expectAlert { + if err == nil { + t.Fatal("Expected read failure but read succeeded") + } + } else { + if err != nil { + t.Fatalf("%s #%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", test.name, i+1, err, n, len(bb), bb[:n], b) + } + if !bytes.Equal(b, bb) { + t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", test.name, i+1, bb, b) + } + } + } + clientConn.Close() + } - testServerScript(t, "TLS12", tls12ServerScript, &config, nil) -} + connState := <-connStateChan + peerCerts := connState.PeerCertificates + if len(peerCerts) == len(test.expectedPeerCerts) { + for i, peerCert := range peerCerts { + block, _ := pem.Decode([]byte(test.expectedPeerCerts[i])) + if !bytes.Equal(block.Bytes, peerCert.Raw) { + t.Fatalf("%s: mismatch on peer cert %d", test.name, i+1) + } + } + } else { + t.Fatalf("%s: mismatch on peer list length: %d (wanted) != %d (got)", test.name, len(test.expectedPeerCerts), len(peerCerts)) + } -type clientauthTest struct { - name string - clientauth ClientAuthType - peers []*x509.Certificate - script [][]byte -} + if test.validate != nil { + if err := test.validate(connState); err != nil { + t.Fatalf("validate callback returned error: %s", err) + } + } -func TestClientAuthRSA(t *testing.T) { - for _, cat := range clientauthRSATests { - t.Log("running", cat.name) - cfg := new(Config) - *cfg = *testConfig - cfg.ClientAuth = cat.clientauth - testServerScript(t, cat.name, cat.script, cfg, cat.peers) + if write { + path := test.dataPath() + out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + t.Fatalf("Failed to create output file: %s", err) + } + defer out.Close() + recordingConn.Close() + if len(recordingConn.flows) < 3 { + childProcess.Stdout.(*bytes.Buffer).WriteTo(os.Stdout) + if len(test.expectHandshakeErrorIncluding) == 0 { + t.Fatalf("Handshake failed") + } + } + recordingConn.WriteTo(out) + fmt.Printf("Wrote %s\n", path) + childProcess.Wait() } } -func TestClientAuthECDSA(t *testing.T) { - for _, cat := range clientauthECDSATests { - t.Log("running", cat.name) - cfg := new(Config) - *cfg = *testConfig - cfg.Certificates = make([]Certificate, 1) - cfg.Certificates[0].Certificate = [][]byte{testECDSACertificate} - cfg.Certificates[0].PrivateKey = testECDSAPrivateKey - cfg.BuildNameToCertificate() - cfg.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA} - cfg.ClientAuth = cat.clientauth - testServerScript(t, cat.name, cat.script, cfg, cat.peers) +func runServerTestForVersion(t *testing.T, template *serverTest, prefix, option string) { + test := *template + test.name = prefix + test.name + if len(test.command) == 0 { + test.command = defaultClientCommand } + test.command = append([]string(nil), test.command...) + test.command = append(test.command, option) + test.run(t, *update) } -// TestCipherSuiteCertPreferance ensures that we select an RSA ciphersuite with -// an RSA certificate and an ECDSA ciphersuite with an ECDSA certificate. -func TestCipherSuiteCertPreferance(t *testing.T) { - var config = *testConfig - config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA} - config.MaxVersion = VersionTLS11 - config.PreferServerCipherSuites = true - testServerScript(t, "CipherSuiteCertPreference", tls11ECDHEAESServerScript, &config, nil) - - config = *testConfig - config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA} - config.Certificates = []Certificate{ - Certificate{ - Certificate: [][]byte{testECDSACertificate}, - PrivateKey: testECDSAPrivateKey, - }, - } - config.BuildNameToCertificate() - config.PreferServerCipherSuites = true - testServerScript(t, "CipherSuiteCertPreference2", ecdheECDSAAESServerScript, &config, nil) +func runServerTestSSLv3(t *testing.T, template *serverTest) { + runServerTestForVersion(t, template, "SSLv3-", "-ssl3") } -func TestTLS11Server(t *testing.T) { - var config = *testConfig - config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA} - config.MaxVersion = VersionTLS11 - testServerScript(t, "TLS11", tls11ECDHEAESServerScript, &config, nil) +func runServerTestTLS10(t *testing.T, template *serverTest) { + runServerTestForVersion(t, template, "TLSv10-", "-tls1") } -func TestAESGCM(t *testing.T) { - var config = *testConfig - config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256} - config.MaxVersion = VersionTLS12 - testServerScript(t, "AES-GCM", aesGCMServerScript, &config, nil) +func runServerTestTLS11(t *testing.T, template *serverTest) { + runServerTestForVersion(t, template, "TLSv11-", "-tls1_1") } -// recordingConn is a net.Conn that records the traffic that passes through it. -// WriteTo can be used to produce Go code that contains the recorded traffic. -type recordingConn struct { - net.Conn - lock sync.Mutex - flows [][]byte - currentlyReading bool +func runServerTestTLS12(t *testing.T, template *serverTest) { + runServerTestForVersion(t, template, "TLSv12-", "-tls1_2") } -func (r *recordingConn) Read(b []byte) (n int, err error) { - if n, err = r.Conn.Read(b); n == 0 { - return +func TestHandshakeServerRSARC4(t *testing.T) { + test := &serverTest{ + name: "RSA-RC4", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA"}, } - b = b[:n] + runServerTestSSLv3(t, test) + runServerTestTLS10(t, test) + runServerTestTLS11(t, test) + runServerTestTLS12(t, test) +} - r.lock.Lock() - defer r.lock.Unlock() +func TestHandshakeServerRSA3DES(t *testing.T) { + test := &serverTest{ + name: "RSA-3DES", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "DES-CBC3-SHA"}, + } + runServerTestSSLv3(t, test) + runServerTestTLS10(t, test) + runServerTestTLS12(t, test) +} - if l := len(r.flows); l == 0 || !r.currentlyReading { - buf := make([]byte, len(b)) - copy(buf, b) - r.flows = append(r.flows, buf) - } else { - r.flows[l-1] = append(r.flows[l-1], b[:n]...) +func TestHandshakeServerRSAAES(t *testing.T) { + test := &serverTest{ + name: "RSA-AES", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA"}, } - r.currentlyReading = true - return + runServerTestSSLv3(t, test) + runServerTestTLS10(t, test) + runServerTestTLS12(t, test) } -func (r *recordingConn) Write(b []byte) (n int, err error) { - if n, err = r.Conn.Write(b); n == 0 { - return +func TestHandshakeServerAESGCM(t *testing.T) { + test := &serverTest{ + name: "RSA-AES-GCM", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-RSA-AES128-GCM-SHA256"}, } - b = b[:n] + runServerTestTLS12(t, test) +} - r.lock.Lock() - defer r.lock.Unlock() +func TestHandshakeServerECDHEECDSAAES(t *testing.T) { + config := *testConfig + config.Certificates = make([]Certificate, 1) + config.Certificates[0].Certificate = [][]byte{testECDSACertificate} + config.Certificates[0].PrivateKey = testECDSAPrivateKey + config.BuildNameToCertificate() - if l := len(r.flows); l == 0 || r.currentlyReading { - buf := make([]byte, len(b)) - copy(buf, b) - r.flows = append(r.flows, buf) - } else { - r.flows[l-1] = append(r.flows[l-1], b[:n]...) + test := &serverTest{ + name: "ECDHE-ECDSA-AES", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-ECDSA-AES256-SHA"}, + config: &config, } - r.currentlyReading = false - return + runServerTestTLS10(t, test) + runServerTestTLS12(t, test) } -// WriteTo writes Go source code to w that contains the recorded traffic. -func (r *recordingConn) WriteTo(w io.Writer) { - fmt.Fprintf(w, "var changeMe = [][]byte {\n") - for _, buf := range r.flows { - fmt.Fprintf(w, "\t{") - for i, b := range buf { - if i%8 == 0 { - fmt.Fprintf(w, "\n\t\t") +func TestHandshakeServerALPN(t *testing.T) { + config := *testConfig + config.NextProtos = []string{"proto1", "proto2"} + + test := &serverTest{ + name: "ALPN", + // 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"}, + config: &config, + validate: func(state ConnectionState) error { + // The server's preferences should override the client. + if state.NegotiatedProtocol != "proto1" { + return fmt.Errorf("Got protocol %q, wanted proto1", state.NegotiatedProtocol) } - fmt.Fprintf(w, "0x%02x, ", b) - } - fmt.Fprintf(w, "\n\t},\n") + return nil + }, } - fmt.Fprintf(w, "}\n") + runServerTestTLS12(t, test) } -var serve = flag.Bool("serve", false, "run a TLS server on :10443") -var testCipherSuites = flag.String("ciphersuites", - "0x"+strconv.FormatInt(int64(TLS_RSA_WITH_RC4_128_SHA), 16), - "cipher suites to accept in serving mode") -var testMinVersion = flag.String("minversion", - "0x"+strconv.FormatInt(int64(VersionSSL30), 16), - "minimum version to negotiate") -var testMaxVersion = flag.String("maxversion", - "0x"+strconv.FormatInt(int64(VersionTLS10), 16), - "maximum version to negotiate") -var testClientAuth = flag.Int("clientauth", 0, "value for tls.Config.ClientAuth") - -func GetTestConfig() *Config { - var config = *testConfig - - minVersion, err := strconv.ParseUint(*testMinVersion, 0, 64) - if err != nil { - panic(err) - } - config.MinVersion = uint16(minVersion) - maxVersion, err := strconv.ParseUint(*testMaxVersion, 0, 64) - if err != nil { - panic(err) +func TestHandshakeServerALPNNoMatch(t *testing.T) { + config := *testConfig + config.NextProtos = []string{"proto3"} + + test := &serverTest{ + 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"}, + 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 nil + }, } - config.MaxVersion = uint16(maxVersion) + runServerTestTLS12(t, test) +} - suites := strings.Split(*testCipherSuites, ",") - config.CipherSuites = make([]uint16, len(suites)) - for i := range suites { - suite, err := strconv.ParseUint(suites[i], 0, 64) - if err != nil { - panic(err) - } - config.CipherSuites[i] = uint16(suite) +// TestHandshakeServerSNI involves a client sending an SNI extension of +// "snitest.com", which happens to match the CN of testSNICertificate. The test +// verifies that the server correctly selects that certificate. +func TestHandshakeServerSNI(t *testing.T) { + test := &serverTest{ + name: "SNI", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"}, } + runServerTestTLS12(t, test) +} - ecdsa := false - for _, suite := range config.CipherSuites { - switch suite { - case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - ecdsa = true - } +// TestHandshakeServerSNICertForName is similar to TestHandshakeServerSNI, but +// tests the dynamic GetCertificate method +func TestHandshakeServerSNIGetCertificate(t *testing.T) { + config := *testConfig + + // Replace the NameToCertificate map with a GetCertificate function + nameToCert := config.NameToCertificate + config.NameToCertificate = nil + config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { + cert, _ := nameToCert[clientHello.ServerName] + return cert, nil } - if ecdsa { - config.Certificates = nil - if !*connect { - config.Certificates = make([]Certificate, 1) - config.Certificates[0].Certificate = [][]byte{testECDSACertificate} - config.Certificates[0].PrivateKey = testECDSAPrivateKey - } - config.BuildNameToCertificate() + test := &serverTest{ + name: "SNI", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"}, + config: &config, } - - config.ClientAuth = ClientAuthType(*testClientAuth) - return &config + runServerTestTLS12(t, test) } -func TestRunServer(t *testing.T) { - if !*serve { - return - } - - config := GetTestConfig() +// TestHandshakeServerSNICertForNameNotFound is similar to +// TestHandshakeServerSNICertForName, but tests to make sure that when the +// GetCertificate method doesn't return a cert, we fall back to what's in +// the NameToCertificate map. +func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) { + config := *testConfig - const addr = ":10443" - l, err := net.Listen("tcp", addr) - if err != nil { - t.Fatal(err) + config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { + return nil, nil } - log.Printf("Now listening for connections on %s", addr) - - for { - tcpConn, err := l.Accept() - if err != nil { - log.Printf("error accepting connection: %s", err) - break - } - - record := &recordingConn{ - Conn: tcpConn, - } - - conn := Server(record, config) - if err := conn.Handshake(); err != nil { - log.Printf("error from TLS handshake: %s", err) - break - } - - _, err = conn.Write([]byte("hello, world\n")) - if err != nil { - log.Printf("error from Write: %s", err) - continue - } - - conn.Close() - - record.WriteTo(os.Stdout) + test := &serverTest{ + name: "SNI", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"}, + config: &config, } + runServerTestTLS12(t, test) } -func bigFromString(s string) *big.Int { - ret := new(big.Int) - ret.SetString(s, 10) - return ret -} +// TestHandshakeServerSNICertForNameError tests to make sure that errors in +// GetCertificate result in a tls alert. +func TestHandshakeServerSNIGetCertificateError(t *testing.T) { + config := *testConfig -func fromHex(s string) []byte { - b, _ := hex.DecodeString(s) - return b + config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) { + return nil, fmt.Errorf("Test error in GetCertificate") + } + test := &serverTest{ + name: "SNI", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-servername", "snitest.com"}, + config: &config, + expectAlert: true, + } + runServerTestTLS12(t, test) } -var testRSACertificate = fromHex("308202b030820219a00302010202090085b0bba48a7fb8ca300d06092a864886f70d01010505003045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3130303432343039303933385a170d3131303432343039303933385a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819f300d06092a864886f70d010101050003818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a381a73081a4301d0603551d0e04160414b1ade2855acfcb28db69ce2369ded3268e18883930750603551d23046e306c8014b1ade2855acfcb28db69ce2369ded3268e188839a149a4473045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746482090085b0bba48a7fb8ca300c0603551d13040530030101ff300d06092a864886f70d010105050003818100086c4524c76bb159ab0c52ccf2b014d7879d7a6475b55a9566e4c52b8eae12661feb4f38b36e60d392fdf74108b52513b1187a24fb301dbaed98b917ece7d73159db95d31d78ea50565cd5825a2d5a5f33c4b6d8c97590968c0f5298b5cd981f89205ff2a01ca31b9694dda9fd57e970e8266d71999b266e3850296c90a7bdd9") - -var testECDSACertificate = fromHex("3082020030820162020900b8bf2d47a0d2ebf4300906072a8648ce3d04013045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3132313132323135303633325a170d3232313132303135303633325a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819b301006072a8648ce3d020106052b81040023038186000400c4a1edbe98f90b4873367ec316561122f23d53c33b4d213dcd6b75e6f6b0dc9adf26c1bcb287f072327cb3642f1c90bcea6823107efee325c0483a69e0286dd33700ef0462dd0da09c706283d881d36431aa9e9731bd96b068c09b23de76643f1a5c7fe9120e5858b65f70dd9bd8ead5d7f5d5ccb9b69f30665b669a20e227e5bffe3b300906072a8648ce3d040103818c0030818802420188a24febe245c5487d1bacf5ed989dae4770c05e1bb62fbdf1b64db76140d311a2ceee0b7e927eff769dc33b7ea53fcefa10e259ec472d7cacda4e970e15a06fd00242014dfcbe67139c2d050ebd3fa38c25c13313830d9406bbd4377af6ec7ac9862eddd711697f857c56defb31782be4c7780daecbbe9e4e3624317b6a0f399512078f2a") - -var testSNICertificate = fromHex("308201f23082015da003020102020100300b06092a864886f70d01010530283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d301e170d3132303431313137343033355a170d3133303431313137343533355a30283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d30819d300b06092a864886f70d01010103818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a3323030300e0603551d0f0101ff0404030200a0300d0603551d0e0406040401020304300f0603551d2304083006800401020304300b06092a864886f70d0101050381810089c6455f1c1f5ef8eb1ab174ee2439059f5c4259bb1a8d86cdb1d056f56a717da40e95ab90f59e8deaf627c157995094db0802266eb34fc6842dea8a4b68d9c1389103ab84fb9e1f85d9b5d23ff2312c8670fbb540148245a4ebafe264d90c8a4cf4f85b0fac12ac2fc4a3154bad52462868af96c62c6525d652b6e31845bdcc") +// 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 + config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA} + config.PreferServerCipherSuites = true -var testRSAPrivateKey = &rsa.PrivateKey{ - PublicKey: rsa.PublicKey{ - N: bigFromString("131650079503776001033793877885499001334664249354723305978524647182322416328664556247316495448366990052837680518067798333412266673813370895702118944398081598789828837447552603077848001020611640547221687072142537202428102790818451901395596882588063427854225330436740647715202971973145151161964464812406232198521"), - E: 65537, - }, - D: bigFromString("29354450337804273969007277378287027274721892607543397931919078829901848876371746653677097639302788129485893852488285045793268732234230875671682624082413996177431586734171663258657462237320300610850244186316880055243099640544518318093544057213190320837094958164973959123058337475052510833916491060913053867729"), - Primes: []*big.Int{ - bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"), - bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"), - }, -} + test := &serverTest{ + name: "CipherSuiteCertPreferenceRSA", + config: &config, + } + runServerTestTLS12(t, test) -var testECDSAPrivateKey = &ecdsa.PrivateKey{ - PublicKey: ecdsa.PublicKey{ - Curve: &elliptic.CurveParams{ - P: bigFromString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151"), - N: bigFromString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449"), - B: bigFromString("1093849038073734274511112390766805569936207598951683748994586394495953116150735016013708737573759623248592132296706313309438452531591012912142327488478985984"), - Gx: bigFromString("2661740802050217063228768716723360960729859168756973147706671368418802944996427808491545080627771902352094241225065558662157113545570916814161637315895999846"), - Gy: bigFromString("3757180025770020463545507224491183603594455134769762486694567779615544477440556316691234405012945539562144444537289428522585666729196580810124344277578376784"), - BitSize: 521, + config = *testConfig + 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, }, - X: bigFromString("2636411247892461147287360222306590634450676461695221912739908880441342231985950069527906976759812296359387337367668045707086543273113073382714101597903639351"), - Y: bigFromString("3204695818431246682253994090650952614555094516658732116404513121125038617915183037601737180082382202488628239201196033284060130040574800684774115478859677243"), - }, - D: bigFromString("5477294338614160138026852784385529180817726002953041720191098180813046231640184669647735805135001309477695746518160084669446643325196003346204701381388769751"), -} - -func loadPEMCert(in string) *x509.Certificate { - block, _ := pem.Decode([]byte(in)) - if block.Type == "CERTIFICATE" && len(block.Headers) == 0 { - cert, err := x509.ParseCertificate(block.Bytes) - if err == nil { - return cert - } - panic("error parsing cert") } - panic("error parsing PEM") -} + config.BuildNameToCertificate() + config.PreferServerCipherSuites = true -// Script of interaction with gnutls implementation. -// The values for this test are obtained by building and running in server mode: -// % go test -test.run "TestRunServer" -serve -// The recorded bytes are written to stdout. -var rsaRC4ServerScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0x54, 0x01, 0x00, 0x00, - 0x50, 0x03, 0x01, 0x50, 0x77, 0x3d, 0xbd, 0x32, - 0x13, 0xd7, 0xea, 0x33, 0x65, 0x02, 0xb8, 0x70, - 0xb7, 0x84, 0xc4, 0x05, 0x1f, 0xa4, 0x24, 0xc4, - 0x91, 0x69, 0x04, 0x32, 0x96, 0xfe, 0x5b, 0x49, - 0x71, 0x60, 0x9a, 0x00, 0x00, 0x28, 0x00, 0x39, - 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13, - 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f, - 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08, - 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01, - 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00, - 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16, - 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, - 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, - 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, - 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, - 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, - 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, - 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, - 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, - 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, - 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, - 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, - 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, - 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, - 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, - 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, - 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, - 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, - 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, - 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, - 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, - 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, - 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, - 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, - 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, - 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, - 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, - 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, - 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, - 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, - 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, - 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, - 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, - 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, - 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, - 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, - 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, - 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, - 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, - 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, - 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, - 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, - 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, - 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, - 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, - 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, - 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, - 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, - 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, - 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, - 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, - 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, - 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, - 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, - 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, - 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, - 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, - 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, - 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, - 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, - 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e, - 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00, - 0x82, 0x00, 0x80, 0x2d, 0x09, 0x7c, 0x7f, 0xfc, - 0x84, 0xce, 0xb3, 0x30, 0x9b, 0xf9, 0xb7, 0xc8, - 0xc3, 0xff, 0xee, 0x6f, 0x20, 0x8a, 0xf4, 0xfb, - 0x86, 0x55, 0x1f, 0x6a, 0xb4, 0x81, 0x50, 0x3a, - 0x46, 0x1b, 0xd3, 0xca, 0x4b, 0x11, 0xff, 0xef, - 0x02, 0xbc, 0x18, 0xb8, 0x4a, 0x7d, 0x43, 0x23, - 0x96, 0x92, 0x27, 0x7c, 0xca, 0xcf, 0xe6, 0x91, - 0xe8, 0x14, 0x97, 0x68, 0xb4, 0xe5, 0xc0, 0xc9, - 0x23, 0xdd, 0x54, 0x07, 0xa6, 0x2e, 0x8c, 0x98, - 0xfc, 0xc6, 0x8c, 0x04, 0x6b, 0x1b, 0x5f, 0xd5, - 0x3d, 0x8b, 0x6c, 0x55, 0x4f, 0x7a, 0xe6, 0x6c, - 0x74, 0x2c, 0x1e, 0x34, 0xdb, 0xfb, 0x00, 0xb1, - 0x4e, 0x10, 0x21, 0x16, 0xe0, 0x3e, 0xc5, 0x64, - 0x84, 0x28, 0x2b, 0x2b, 0x29, 0x47, 0x51, 0x34, - 0x76, 0x15, 0x20, 0x71, 0x0b, 0x30, 0xa1, 0x85, - 0xd5, 0x15, 0x18, 0x14, 0x64, 0x4b, 0x40, 0x7c, - 0x4f, 0xb3, 0x7b, 0x14, 0x03, 0x01, 0x00, 0x01, - 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xab, 0xee, - 0xf5, 0x97, 0x5f, 0xc6, 0x78, 0xf3, 0xc6, 0x83, - 0x5b, 0x55, 0x4f, 0xcb, 0x45, 0x3f, 0xfa, 0xf7, - 0x05, 0x02, 0xc2, 0x63, 0x87, 0x18, 0xb5, 0x9a, - 0x62, 0xe2, 0x3f, 0x88, 0x5a, 0x60, 0x61, 0x72, - 0xfa, 0x9c, - }, - { - 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x01, 0x00, 0x24, 0x72, 0xa4, 0xe4, 0xaa, 0xd2, - 0xc4, 0x39, 0x7e, 0x2a, 0xc1, 0x6f, 0x34, 0x42, - 0x28, 0xcb, 0x9d, 0x7a, 0x09, 0xca, 0x96, 0xad, - 0x0e, 0x11, 0x51, 0x8a, 0x06, 0xb0, 0xe9, 0xca, - 0xeb, 0xce, 0xe2, 0xd5, 0x2e, 0xc1, 0x8d, 0x17, - 0x03, 0x01, 0x00, 0x21, 0x2e, 0x61, 0x86, 0x17, - 0xdb, 0xa6, 0x30, 0xe2, 0x62, 0x06, 0x2a, 0x8b, - 0x75, 0x2c, 0x2d, 0xcf, 0xf5, 0x01, 0x11, 0x52, - 0x81, 0x38, 0xcf, 0xd5, 0xf7, 0xdc, 0x52, 0x31, - 0x1f, 0x97, 0x43, 0xc2, 0x71, 0x15, 0x03, 0x01, - 0x00, 0x16, 0xe0, 0x21, 0xfe, 0x36, 0x2e, 0x68, - 0x2c, 0xf1, 0xbe, 0x04, 0xec, 0xd4, 0xc6, 0xdd, - 0xac, 0x6f, 0x4c, 0x85, 0x32, 0x3f, 0x87, 0x1b, - }, + test = &serverTest{ + name: "CipherSuiteCertPreferenceECDSA", + config: &config, + } + runServerTestTLS12(t, test) } -var rsaDES3ServerScript = [][]byte{ - { - 0x16, 0x03, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x00, - 0xc1, 0x03, 0x03, 0x50, 0xae, 0x5d, 0x38, 0xec, - 0xaa, 0x2f, 0x41, 0xf9, 0xd2, 0x7b, 0xa1, 0xfd, - 0x0f, 0xff, 0x4e, 0x54, 0x0e, 0x15, 0x57, 0xaf, - 0x2c, 0x91, 0xb5, 0x35, 0x5b, 0x2e, 0xb0, 0xec, - 0x20, 0xe5, 0xd2, 0x00, 0x00, 0x50, 0xc0, 0x09, - 0xc0, 0x23, 0xc0, 0x2b, 0xc0, 0x0a, 0xc0, 0x24, - 0xc0, 0x2c, 0xc0, 0x08, 0xc0, 0x13, 0xc0, 0x27, - 0xc0, 0x2f, 0xc0, 0x14, 0xc0, 0x30, 0xc0, 0x12, - 0x00, 0x33, 0x00, 0x67, 0x00, 0x45, 0x00, 0x9e, - 0x00, 0x39, 0x00, 0x6b, 0x00, 0x88, 0x00, 0x16, - 0x00, 0x32, 0x00, 0x40, 0x00, 0x44, 0x00, 0xa2, - 0x00, 0x38, 0x00, 0x6a, 0x00, 0x87, 0x00, 0x13, - 0x00, 0x66, 0x00, 0x2f, 0x00, 0x3c, 0x00, 0x41, - 0x00, 0x9c, 0x00, 0x35, 0x00, 0x3d, 0x00, 0x84, - 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x01, 0x00, - 0x00, 0x48, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x01, 0x00, - 0x00, 0x23, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, - 0x00, 0x0a, 0x00, 0x13, 0x00, 0x15, 0x00, 0x17, - 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02, - 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a, - 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x05, 0x01, - 0x05, 0x03, 0x06, 0x01, 0x06, 0x03, 0x03, 0x01, - 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, - 0x02, 0x03, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00, - 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01, - 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02, - 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0, - 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4, - 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, - 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, - 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, - 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, - 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, - 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, - 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30, - 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33, - 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, - 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, - 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, - 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, - 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, - 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79, - 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10, - 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43, - 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85, - 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c, - 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5, - 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c, - 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56, - 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26, - 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21, - 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf, - 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07, - 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39, - 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3, - 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf, - 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb, - 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, - 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85, - 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23, - 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39, - 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2, - 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, - 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, - 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85, - 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, - 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59, - 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7, - 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95, - 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66, - 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3, - 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13, - 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba, - 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31, - 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50, - 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f, - 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96, - 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f, - 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b, - 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70, - 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e, - 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9, - 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, - 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00, - 0x82, 0x00, 0x80, 0x51, 0x04, 0xf1, 0x7a, 0xbf, - 0xe8, 0xa5, 0x86, 0x09, 0xa7, 0xf3, 0xcc, 0x93, - 0x00, 0x10, 0x5b, 0xb8, 0xc1, 0x51, 0x0d, 0x5b, - 0xcd, 0xed, 0x26, 0x01, 0x69, 0x73, 0xf4, 0x05, - 0x8a, 0x6a, 0xc3, 0xb1, 0x9e, 0x84, 0x4e, 0x39, - 0xcf, 0x5e, 0x55, 0xa9, 0x70, 0x19, 0x96, 0x91, - 0xcd, 0x2c, 0x78, 0x3c, 0xa2, 0x6d, 0xb0, 0x49, - 0x86, 0xf6, 0xd1, 0x3a, 0xde, 0x00, 0x4b, 0xa6, - 0x25, 0xbf, 0x85, 0x39, 0xce, 0xb1, 0xcf, 0xbc, - 0x16, 0xc7, 0x66, 0xac, 0xf8, 0xd2, 0x3b, 0xd1, - 0xcc, 0x16, 0xac, 0x63, 0x3c, 0xbe, 0xd9, 0xb6, - 0x6a, 0xe4, 0x13, 0x8a, 0xf4, 0x56, 0x2f, 0x92, - 0x54, 0xd8, 0xf0, 0x84, 0x01, 0x32, 0x1a, 0xa9, - 0x2d, 0xaf, 0x82, 0x0e, 0x00, 0xfa, 0x07, 0x88, - 0xd9, 0x87, 0xe7, 0xdc, 0x9e, 0xe9, 0x72, 0x49, - 0xb8, 0xfa, 0x8c, 0x7b, 0x07, 0x0b, 0x03, 0x7c, - 0x10, 0x8c, 0x8a, 0x14, 0x03, 0x01, 0x00, 0x01, - 0x01, 0x16, 0x03, 0x01, 0x00, 0xa8, 0x61, 0xa4, - 0xf4, 0x5f, 0x8a, 0x1f, 0x5c, 0x92, 0x3f, 0x8c, - 0xdb, 0xd6, 0x10, 0xcd, 0x9e, 0xe7, 0xf0, 0xc4, - 0x3c, 0xb6, 0x1c, 0x9a, 0x56, 0x73, 0x7f, 0xa6, - 0x14, 0x24, 0xcb, 0x96, 0x1f, 0xe0, 0xaf, 0xcd, - 0x3c, 0x66, 0x43, 0xb7, 0x37, 0x65, 0x34, 0x47, - 0xf8, 0x43, 0xf1, 0xcc, 0x15, 0xb8, 0xdc, 0x35, - 0xe0, 0xa4, 0x2d, 0x78, 0x94, 0xe0, 0x02, 0xf3, - 0x76, 0x46, 0xf7, 0x9b, 0x8d, 0x0d, 0x5d, 0x0b, - 0xd3, 0xdd, 0x9a, 0x9e, 0x62, 0x2e, 0xc5, 0x98, - 0x75, 0x63, 0x0c, 0xbf, 0x8e, 0x49, 0x33, 0x23, - 0x7c, 0x00, 0xcf, 0xfb, 0xcf, 0xba, 0x0f, 0x41, - 0x39, 0x89, 0xb9, 0xcc, 0x59, 0xd0, 0x2b, 0xb6, - 0xec, 0x04, 0xe2, 0xc0, 0x52, 0xc7, 0xcf, 0x71, - 0x47, 0xff, 0x70, 0x7e, 0xa9, 0xbd, 0x1c, 0xdd, - 0x17, 0xa5, 0x6c, 0xb7, 0x10, 0x4f, 0x42, 0x18, - 0x37, 0x69, 0xa9, 0xd2, 0xb3, 0x18, 0x84, 0x92, - 0xa7, 0x47, 0x21, 0xf6, 0x95, 0x63, 0x29, 0xd6, - 0xa5, 0xb6, 0xda, 0x65, 0x67, 0x69, 0xc4, 0x26, - 0xac, 0x8b, 0x08, 0x58, 0xdd, 0x3c, 0x31, 0x20, - 0xd5, 0x0c, 0x88, 0x72, 0x18, 0x16, 0x88, 0x1e, - 0x4a, 0x0f, 0xe1, 0xcf, 0x95, 0x24, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00, - 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, - 0xe8, 0x4b, 0xde, 0xef, 0xba, 0x3e, 0x18, 0x1c, - 0x1e, 0x5e, 0xbc, 0x87, 0xf1, 0x87, 0x8d, 0x72, - 0xe3, 0xbe, 0x0f, 0xdf, 0xfd, 0xd0, 0xb2, 0x89, - 0xf8, 0x05, 0x9a, 0x52, 0x47, 0x77, 0x9e, 0xe8, - 0xb1, 0x1d, 0x18, 0xed, 0x6a, 0x4b, 0x63, 0x1d, - 0xf1, 0x62, 0xd2, 0x65, 0x21, 0x26, 0x73, 0xd4, - 0x35, 0x5b, 0x95, 0x89, 0x12, 0x59, 0x23, 0x8c, - 0xc3, 0xfc, 0xf9, 0x4d, 0x21, 0x79, 0xa0, 0xbd, - 0xff, 0x33, 0xa2, 0x3d, 0x0b, 0x6f, 0x89, 0xc9, - 0x23, 0xe4, 0xe7, 0x9f, 0x1d, 0x98, 0xf6, 0xed, - 0x02, 0x8d, 0xac, 0x1a, 0xf9, 0xcb, 0xa5, 0x14, - 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, - 0x00, 0x28, 0x91, 0x56, 0x80, 0xe2, 0x6d, 0x51, - 0x88, 0x03, 0xf8, 0x49, 0xe6, 0x6a, 0x5a, 0xfb, - 0x2f, 0x0b, 0xb5, 0xa1, 0x0d, 0x63, 0x83, 0xae, - 0xb9, 0xbc, 0x05, 0xf0, 0x81, 0x00, 0x61, 0x83, - 0x38, 0xda, 0x14, 0xf6, 0xea, 0xd8, 0x78, 0x65, - 0xc7, 0x26, 0x17, 0x03, 0x01, 0x00, 0x18, 0x81, - 0x30, 0x8b, 0x22, 0x5a, 0xd3, 0x7f, 0xc8, 0xf2, - 0x8a, 0x6b, 0xa3, 0xba, 0x4d, 0xe7, 0x6e, 0xd2, - 0xfd, 0xbf, 0xf2, 0xc5, 0x28, 0xa0, 0x62, 0x17, - 0x03, 0x01, 0x00, 0x28, 0x17, 0x83, 0x3c, 0x78, - 0x18, 0xfa, 0x8d, 0x58, 0x5c, 0xaa, 0x05, 0x7d, - 0x67, 0x96, 0x11, 0x60, 0x11, 0xc0, 0x1e, 0x0d, - 0x6a, 0x6e, 0x5f, 0x1d, 0x98, 0x4b, 0xff, 0x82, - 0xee, 0x21, 0x06, 0x29, 0xd3, 0x8b, 0x80, 0x78, - 0x39, 0x05, 0x34, 0x9b, 0x15, 0x03, 0x01, 0x00, - 0x18, 0xa9, 0x38, 0x18, 0x4f, 0x9d, 0x84, 0x75, - 0x88, 0x53, 0xd6, 0x85, 0xc2, 0x15, 0x4b, 0xe3, - 0xe3, 0x35, 0x9a, 0x74, 0xc9, 0x3e, 0x13, 0xc1, - 0x8c, - }, -} +func TestResumption(t *testing.T) { + sessionFilePath := tempFile("") + defer os.Remove(sessionFilePath) -var rsaAESServerScript = [][]byte{ - { - 0x16, 0x03, 0x00, 0x00, 0xc5, 0x01, 0x00, 0x00, - 0xc1, 0x03, 0x03, 0x50, 0xae, 0x5c, 0xe9, 0x5e, - 0x31, 0x93, 0x82, 0xa5, 0x6f, 0x51, 0x82, 0xc8, - 0x55, 0x4f, 0x1f, 0x2e, 0x90, 0x98, 0x81, 0x13, - 0x27, 0x80, 0x68, 0xb4, 0x2d, 0xba, 0x3a, 0x76, - 0xd8, 0xd7, 0x2c, 0x00, 0x00, 0x50, 0xc0, 0x09, - 0xc0, 0x23, 0xc0, 0x2b, 0xc0, 0x0a, 0xc0, 0x24, - 0xc0, 0x2c, 0xc0, 0x08, 0xc0, 0x13, 0xc0, 0x27, - 0xc0, 0x2f, 0xc0, 0x14, 0xc0, 0x30, 0xc0, 0x12, - 0x00, 0x33, 0x00, 0x67, 0x00, 0x45, 0x00, 0x9e, - 0x00, 0x39, 0x00, 0x6b, 0x00, 0x88, 0x00, 0x16, - 0x00, 0x32, 0x00, 0x40, 0x00, 0x44, 0x00, 0xa2, - 0x00, 0x38, 0x00, 0x6a, 0x00, 0x87, 0x00, 0x13, - 0x00, 0x66, 0x00, 0x2f, 0x00, 0x3c, 0x00, 0x41, - 0x00, 0x9c, 0x00, 0x35, 0x00, 0x3d, 0x00, 0x84, - 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x01, 0x00, - 0x00, 0x48, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x01, 0x00, - 0x00, 0x23, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, - 0x00, 0x0a, 0x00, 0x13, 0x00, 0x15, 0x00, 0x17, - 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02, - 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a, - 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x05, 0x01, - 0x05, 0x03, 0x06, 0x01, 0x06, 0x03, 0x03, 0x01, - 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, - 0x02, 0x03, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00, - 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, - 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01, - 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02, - 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0, - 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4, - 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, - 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, - 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, - 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, - 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, - 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, - 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30, - 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33, - 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, - 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, - 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, - 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, - 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, - 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79, - 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10, - 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43, - 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85, - 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c, - 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5, - 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c, - 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56, - 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26, - 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21, - 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf, - 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07, - 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39, - 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3, - 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf, - 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb, - 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, - 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85, - 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23, - 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39, - 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2, - 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, - 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, - 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85, - 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, - 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59, - 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7, - 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95, - 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66, - 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3, - 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13, - 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba, - 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31, - 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50, - 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f, - 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96, - 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f, - 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b, - 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70, - 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e, - 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9, - 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, - 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00, - 0x82, 0x00, 0x80, 0x51, 0x2e, 0xec, 0x0d, 0x86, - 0xf3, 0x9f, 0xf2, 0x77, 0x04, 0x27, 0x2b, 0x0e, - 0x9c, 0xab, 0x35, 0x84, 0x65, 0xff, 0x36, 0xef, - 0xc0, 0x08, 0xc9, 0x1d, 0x9f, 0x29, 0xae, 0x8d, - 0xc5, 0x66, 0x81, 0x31, 0x92, 0x5e, 0x3d, 0xac, - 0xaa, 0x37, 0x28, 0x2c, 0x06, 0x91, 0xa6, 0xc2, - 0xd0, 0x83, 0x34, 0x24, 0x1c, 0x88, 0xfc, 0x0a, - 0xcf, 0xbf, 0xc2, 0x94, 0xe2, 0xed, 0xa7, 0x6a, - 0xa8, 0x8d, 0x3d, 0xf7, 0x06, 0x7d, 0x69, 0xf8, - 0x0d, 0xb2, 0xf7, 0xe4, 0x45, 0xcb, 0x0a, 0x25, - 0xcb, 0xb2, 0x2e, 0x38, 0x9a, 0x84, 0x75, 0xe8, - 0xe1, 0x42, 0x39, 0xa2, 0x18, 0x0e, 0x48, 0xca, - 0x33, 0x16, 0x4e, 0xf6, 0x2f, 0xec, 0x07, 0xe7, - 0x57, 0xe1, 0x20, 0x40, 0x40, 0x6d, 0x4e, 0x29, - 0x04, 0x1a, 0x8c, 0x99, 0xfb, 0x19, 0x3c, 0xaa, - 0x75, 0x64, 0xd3, 0xa6, 0xe6, 0xed, 0x3f, 0x5a, - 0xd2, 0xc9, 0x80, 0x14, 0x03, 0x01, 0x00, 0x01, - 0x01, 0x16, 0x03, 0x01, 0x01, 0x10, 0xe9, 0x9e, - 0x06, 0x92, 0x18, 0xbf, 0x5e, 0xaf, 0x33, 0xc1, - 0xbf, 0x0e, 0x12, 0x07, 0x48, 0x4f, 0x6b, 0x6c, - 0xf5, 0x23, 0x5e, 0x87, 0xa7, 0xd3, 0x50, 0x79, - 0x38, 0xdc, 0xe0, 0x49, 0xd3, 0x81, 0x21, 0x12, - 0xd0, 0x3d, 0x9a, 0xfb, 0x83, 0xc1, 0x8b, 0xfc, - 0x14, 0xd5, 0xd5, 0xa7, 0xa3, 0x34, 0x14, 0x71, - 0xbe, 0xea, 0x37, 0x18, 0x12, 0x7f, 0x41, 0xfb, - 0xc5, 0x51, 0x17, 0x9d, 0x96, 0x58, 0x14, 0xfb, - 0x4f, 0xd7, 0xd3, 0x15, 0x0f, 0xec, 0x5a, 0x0d, - 0x35, 0xbb, 0x3c, 0x81, 0x5b, 0x3f, 0xdf, 0x52, - 0xa4, 0x4c, 0xcd, 0x13, 0xe1, 0x10, 0x37, 0x34, - 0xbf, 0xb4, 0x80, 0x1e, 0x8d, 0xe2, 0xc3, 0x7a, - 0x0f, 0x7b, 0x7d, 0x23, 0xeb, 0xd0, 0x99, 0x69, - 0xad, 0x0a, 0x2d, 0xb3, 0x6c, 0xd6, 0x80, 0x11, - 0x7f, 0x6c, 0xed, 0x1b, 0xcd, 0x08, 0x22, 0x56, - 0x90, 0x0e, 0xa4, 0xc3, 0x29, 0x33, 0x96, 0x30, - 0x34, 0x94, 0xa1, 0xeb, 0x9c, 0x1b, 0x5a, 0xd1, - 0x03, 0x61, 0xf9, 0xdd, 0xf3, 0x64, 0x8a, 0xfd, - 0x5f, 0x44, 0xdb, 0x2e, 0xa7, 0xfd, 0xe1, 0x1a, - 0x66, 0xc5, 0x01, 0x9c, 0xc7, 0xd1, 0xc4, 0xd3, - 0xea, 0x14, 0x3c, 0xed, 0x74, 0xbb, 0x1b, 0x97, - 0x8f, 0xf1, 0x29, 0x39, 0x33, 0x92, 0x93, 0x4e, - 0xf5, 0x87, 0x91, 0x61, 0x65, 0x8d, 0x27, 0x8d, - 0x76, 0xc1, 0xfa, 0x6a, 0x99, 0x80, 0xb1, 0x9b, - 0x29, 0x53, 0xce, 0x3e, 0xb6, 0x9a, 0xce, 0x3c, - 0x19, 0x5e, 0x48, 0x83, 0xaa, 0xa7, 0x66, 0x98, - 0x59, 0xf4, 0xbb, 0xf2, 0xbc, 0xd9, 0xc5, 0x9a, - 0xc8, 0x2c, 0x63, 0x58, 0xd5, 0xd4, 0xbc, 0x03, - 0xa9, 0x06, 0xa9, 0x80, 0x0d, 0xb3, 0x46, 0x2d, - 0xe3, 0xc6, 0xaf, 0x1a, 0x39, 0x18, 0x7e, 0x1e, - 0x83, 0x80, 0x46, 0x11, 0xd2, 0x13, 0x9f, 0xda, - 0xfc, 0x2d, 0x42, 0xaa, 0x5a, 0x1d, 0x4c, 0x31, - 0xe5, 0x58, 0x78, 0x5e, 0xe2, 0x04, 0xd6, 0x23, - 0x7f, 0x3f, 0x06, 0xc0, 0x54, 0xf8, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00, - 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, - 0xe8, 0x4b, 0xfb, 0xef, 0xba, 0xed, 0xc5, 0x36, - 0xc8, 0x5a, 0x41, 0x3f, 0x05, 0xfa, 0xfe, 0x48, - 0xc3, 0x91, 0x12, 0x8b, 0xe8, 0x32, 0x6a, 0x9f, - 0xdc, 0x97, 0xe2, 0x77, 0xb9, 0x96, 0x2d, 0xd4, - 0xe5, 0xbd, 0xa1, 0xfd, 0x94, 0xbb, 0x74, 0x63, - 0xb1, 0x0c, 0x38, 0xbc, 0x6f, 0x69, 0xaf, 0xa3, - 0x46, 0x9c, 0x96, 0x41, 0xde, 0x59, 0x23, 0xff, - 0x15, 0x6b, 0x3a, 0xef, 0x91, 0x6d, 0x92, 0x44, - 0xdc, 0x72, 0x1f, 0x40, 0x3d, 0xb5, 0x34, 0x8f, - 0x2a, 0xac, 0x21, 0x69, 0x05, 0x6f, 0xb2, 0x60, - 0x32, 0x5d, 0x3d, 0x97, 0xb4, 0x24, 0x99, 0x14, - 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, - 0x00, 0x30, 0x68, 0x27, 0x97, 0xca, 0x63, 0x09, - 0x22, 0xed, 0x0e, 0x61, 0x7c, 0x76, 0x31, 0x9c, - 0xbe, 0x27, 0xc9, 0xe6, 0x09, 0xc3, 0xc3, 0xc2, - 0xf4, 0xa2, 0x32, 0xba, 0x7c, 0xf2, 0x0f, 0xb8, - 0x3d, 0xcb, 0xe2, 0x4c, 0xc0, 0x7d, 0x8e, 0x5b, - 0x5a, 0xed, 0x05, 0x5c, 0x15, 0x96, 0x69, 0xc2, - 0x6f, 0x5f, 0x17, 0x03, 0x01, 0x00, 0x20, 0x5a, - 0xfe, 0x0b, 0xe1, 0x6f, 0xa8, 0x54, 0x19, 0x78, - 0xca, 0xba, 0x2e, 0x1e, 0x2e, 0xe1, 0x5d, 0x17, - 0xe5, 0x97, 0x05, 0x2c, 0x08, 0x0c, 0xff, 0xa8, - 0x59, 0xa9, 0xde, 0x5e, 0x21, 0x34, 0x04, 0x17, - 0x03, 0x01, 0x00, 0x30, 0x86, 0xb1, 0x3f, 0x88, - 0x43, 0xf0, 0x07, 0xee, 0xa8, 0xf4, 0xbc, 0xe7, - 0x5f, 0xc6, 0x8c, 0x86, 0x4c, 0xca, 0x70, 0x88, - 0xcc, 0x6a, 0xb4, 0x3d, 0x40, 0xe8, 0x54, 0x89, - 0x19, 0x43, 0x1f, 0x76, 0xe2, 0xac, 0xb2, 0x5b, - 0x92, 0xf8, 0x57, 0x39, 0x2a, 0xc3, 0x6d, 0x13, - 0x45, 0xfa, 0x36, 0x9e, 0x15, 0x03, 0x01, 0x00, - 0x20, 0x6d, 0xed, 0x7b, 0x59, 0x28, 0x2a, 0x27, - 0x04, 0x15, 0x07, 0x4e, 0xeb, 0x13, 0x00, 0xe3, - 0x3a, 0x3f, 0xf8, 0xaa, 0x2b, 0x3b, 0x1a, 0x8c, - 0x12, 0xd6, 0x4c, 0xec, 0x2a, 0xaf, 0x33, 0x60, - 0xaf, - }, -} + test := &serverTest{ + name: "IssueTicket", + command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_out", sessionFilePath}, + } + runServerTestTLS12(t, test) -// Generated using: -// $ go test -test.run TestRunServer -serve -ciphersuites=0xc00a -// $ openssl s_client -host 127.0.0.1 -port 10443 -cipher ECDHE-ECDSA-AES256-SHA -var ecdheECDSAAESServerScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0xa0, 0x01, 0x00, 0x00, - 0x9c, 0x03, 0x03, 0x50, 0xd7, 0x18, 0x31, 0x49, - 0xde, 0x19, 0x8d, 0x08, 0x5c, 0x4b, 0x60, 0x67, - 0x0f, 0xfe, 0xd0, 0x62, 0xf9, 0x31, 0x48, 0x17, - 0x9e, 0x50, 0xc1, 0xd8, 0x35, 0x24, 0x0e, 0xa6, - 0x09, 0x06, 0x51, 0x00, 0x00, 0x04, 0xc0, 0x0a, - 0x00, 0xff, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x0b, - 0x00, 0x04, 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a, - 0x00, 0x34, 0x00, 0x32, 0x00, 0x0e, 0x00, 0x0d, - 0x00, 0x19, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x18, - 0x00, 0x09, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x17, - 0x00, 0x08, 0x00, 0x06, 0x00, 0x07, 0x00, 0x14, - 0x00, 0x15, 0x00, 0x04, 0x00, 0x05, 0x00, 0x12, - 0x00, 0x13, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, - 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x23, - 0x00, 0x00, 0x00, 0x0d, 0x00, 0x22, 0x00, 0x20, - 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, - 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, - 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, - 0x00, 0x0f, 0x00, 0x01, 0x01, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00, - 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0a, 0x00, 0x00, - 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01, - 0x02, 0x0e, 0x0b, 0x00, 0x02, 0x0a, 0x00, 0x02, - 0x07, 0x00, 0x02, 0x04, 0x30, 0x82, 0x02, 0x00, - 0x30, 0x82, 0x01, 0x62, 0x02, 0x09, 0x00, 0xb8, - 0xbf, 0x2d, 0x47, 0xa0, 0xd2, 0xeb, 0xf4, 0x30, - 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, - 0x04, 0x01, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, - 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, - 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, - 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, - 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x31, - 0x31, 0x32, 0x32, 0x31, 0x35, 0x30, 0x36, 0x33, - 0x32, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x31, 0x31, - 0x32, 0x30, 0x31, 0x35, 0x30, 0x36, 0x33, 0x32, - 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, - 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, - 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, - 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, - 0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a, - 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, - 0x2b, 0x81, 0x04, 0x00, 0x23, 0x03, 0x81, 0x86, - 0x00, 0x04, 0x00, 0xc4, 0xa1, 0xed, 0xbe, 0x98, - 0xf9, 0x0b, 0x48, 0x73, 0x36, 0x7e, 0xc3, 0x16, - 0x56, 0x11, 0x22, 0xf2, 0x3d, 0x53, 0xc3, 0x3b, - 0x4d, 0x21, 0x3d, 0xcd, 0x6b, 0x75, 0xe6, 0xf6, - 0xb0, 0xdc, 0x9a, 0xdf, 0x26, 0xc1, 0xbc, 0xb2, - 0x87, 0xf0, 0x72, 0x32, 0x7c, 0xb3, 0x64, 0x2f, - 0x1c, 0x90, 0xbc, 0xea, 0x68, 0x23, 0x10, 0x7e, - 0xfe, 0xe3, 0x25, 0xc0, 0x48, 0x3a, 0x69, 0xe0, - 0x28, 0x6d, 0xd3, 0x37, 0x00, 0xef, 0x04, 0x62, - 0xdd, 0x0d, 0xa0, 0x9c, 0x70, 0x62, 0x83, 0xd8, - 0x81, 0xd3, 0x64, 0x31, 0xaa, 0x9e, 0x97, 0x31, - 0xbd, 0x96, 0xb0, 0x68, 0xc0, 0x9b, 0x23, 0xde, - 0x76, 0x64, 0x3f, 0x1a, 0x5c, 0x7f, 0xe9, 0x12, - 0x0e, 0x58, 0x58, 0xb6, 0x5f, 0x70, 0xdd, 0x9b, - 0xd8, 0xea, 0xd5, 0xd7, 0xf5, 0xd5, 0xcc, 0xb9, - 0xb6, 0x9f, 0x30, 0x66, 0x5b, 0x66, 0x9a, 0x20, - 0xe2, 0x27, 0xe5, 0xbf, 0xfe, 0x3b, 0x30, 0x09, - 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, - 0x01, 0x03, 0x81, 0x8c, 0x00, 0x30, 0x81, 0x88, - 0x02, 0x42, 0x01, 0x88, 0xa2, 0x4f, 0xeb, 0xe2, - 0x45, 0xc5, 0x48, 0x7d, 0x1b, 0xac, 0xf5, 0xed, - 0x98, 0x9d, 0xae, 0x47, 0x70, 0xc0, 0x5e, 0x1b, - 0xb6, 0x2f, 0xbd, 0xf1, 0xb6, 0x4d, 0xb7, 0x61, - 0x40, 0xd3, 0x11, 0xa2, 0xce, 0xee, 0x0b, 0x7e, - 0x92, 0x7e, 0xff, 0x76, 0x9d, 0xc3, 0x3b, 0x7e, - 0xa5, 0x3f, 0xce, 0xfa, 0x10, 0xe2, 0x59, 0xec, - 0x47, 0x2d, 0x7c, 0xac, 0xda, 0x4e, 0x97, 0x0e, - 0x15, 0xa0, 0x6f, 0xd0, 0x02, 0x42, 0x01, 0x4d, - 0xfc, 0xbe, 0x67, 0x13, 0x9c, 0x2d, 0x05, 0x0e, - 0xbd, 0x3f, 0xa3, 0x8c, 0x25, 0xc1, 0x33, 0x13, - 0x83, 0x0d, 0x94, 0x06, 0xbb, 0xd4, 0x37, 0x7a, - 0xf6, 0xec, 0x7a, 0xc9, 0x86, 0x2e, 0xdd, 0xd7, - 0x11, 0x69, 0x7f, 0x85, 0x7c, 0x56, 0xde, 0xfb, - 0x31, 0x78, 0x2b, 0xe4, 0xc7, 0x78, 0x0d, 0xae, - 0xcb, 0xbe, 0x9e, 0x4e, 0x36, 0x24, 0x31, 0x7b, - 0x6a, 0x0f, 0x39, 0x95, 0x12, 0x07, 0x8f, 0x2a, - 0x16, 0x03, 0x01, 0x01, 0x1a, 0x0c, 0x00, 0x01, - 0x16, 0x03, 0x00, 0x19, 0x85, 0x04, 0x01, 0x39, - 0xdc, 0xee, 0x44, 0x17, 0x5e, 0xdb, 0xd7, 0x27, - 0xaf, 0xb6, 0x56, 0xd9, 0xb4, 0x43, 0x5a, 0x99, - 0xcf, 0xaa, 0x31, 0x37, 0x0c, 0x6f, 0x3a, 0xa0, - 0xf8, 0x53, 0xc4, 0x74, 0xd1, 0x91, 0x0a, 0x46, - 0xf5, 0x38, 0x3b, 0x5c, 0x09, 0xd8, 0x97, 0xdc, - 0x4b, 0xaa, 0x70, 0x26, 0x48, 0xf2, 0xd6, 0x0b, - 0x31, 0xc9, 0xf8, 0xd4, 0x98, 0x43, 0xe1, 0x6c, - 0xd5, 0xc7, 0xb2, 0x8e, 0x0b, 0x01, 0xe6, 0xb6, - 0x00, 0x28, 0x80, 0x7b, 0xfc, 0x96, 0x8f, 0x0d, - 0xa2, 0x4f, 0xb0, 0x79, 0xaf, 0xdc, 0x61, 0x28, - 0x63, 0x33, 0x78, 0xf6, 0x31, 0x39, 0xfd, 0x8a, - 0xf4, 0x15, 0x18, 0x11, 0xfe, 0xdb, 0xd5, 0x07, - 0xda, 0x2c, 0xed, 0x49, 0xa0, 0x23, 0xbf, 0xd0, - 0x3a, 0x38, 0x1d, 0x54, 0xae, 0x1c, 0x7b, 0xea, - 0x29, 0xee, 0xd0, 0x38, 0xc1, 0x76, 0xa7, 0x7f, - 0x2a, 0xf4, 0xce, 0x1e, 0xac, 0xcc, 0x94, 0x79, - 0x90, 0x33, 0x00, 0x8b, 0x30, 0x81, 0x88, 0x02, - 0x42, 0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, - 0x04, 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, - 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, - 0x3f, 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, - 0x4d, 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, - 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, - 0xff, 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, - 0x6a, 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, - 0xe5, 0xbd, 0x66, 0x02, 0x42, 0x00, 0xad, 0x7d, - 0x06, 0x35, 0xab, 0xec, 0x8d, 0xac, 0xd4, 0xba, - 0x1b, 0x49, 0x5e, 0x05, 0x5f, 0xf0, 0x97, 0x93, - 0x82, 0xb8, 0x2b, 0x8d, 0x91, 0x98, 0x63, 0x8e, - 0xb4, 0x14, 0x62, 0xdb, 0x1e, 0xc9, 0x2b, 0x30, - 0xf8, 0x41, 0x9b, 0xa6, 0xe6, 0xbc, 0xde, 0x0e, - 0x68, 0x30, 0x22, 0x50, 0xe6, 0x98, 0x97, 0x7b, - 0x69, 0xf7, 0x93, 0xed, 0xcd, 0x19, 0x2f, 0x44, - 0x6c, 0x2e, 0xdf, 0x25, 0xee, 0xcc, 0x46, 0x16, - 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x8a, 0x10, 0x00, 0x00, - 0x86, 0x85, 0x04, 0x00, 0x1c, 0xc5, 0xe8, 0xb3, - 0x42, 0xb4, 0xad, 0xca, 0x45, 0xcd, 0x42, 0x7b, - 0xfb, 0x0c, 0xea, 0x32, 0x26, 0xd4, 0x8a, 0xef, - 0xdf, 0xc9, 0xff, 0xd2, 0xe0, 0x36, 0xea, 0x4e, - 0xbb, 0x3e, 0xf4, 0x9c, 0x76, 0x4f, 0x44, 0xbd, - 0x84, 0x72, 0xdd, 0xcb, 0xe5, 0x28, 0x8d, 0x31, - 0x72, 0x3b, 0xd3, 0xf2, 0x9a, 0x13, 0xfb, 0x8a, - 0xa7, 0x72, 0xca, 0x21, 0x6c, 0xea, 0xbf, 0xe9, - 0x8c, 0x0a, 0xcc, 0x8f, 0xd6, 0x00, 0x20, 0x87, - 0xf3, 0x7d, 0x18, 0xc5, 0xfd, 0x9e, 0xdd, 0x6b, - 0x06, 0xdc, 0x52, 0xeb, 0x14, 0xc0, 0x67, 0x5a, - 0x06, 0xd8, 0x98, 0x19, 0x14, 0xe7, 0xd4, 0x36, - 0x32, 0xee, 0xb7, 0xfa, 0xe2, 0x85, 0x4a, 0x16, - 0x42, 0x0c, 0xa6, 0x21, 0xcf, 0x1f, 0xae, 0x10, - 0x8b, 0x28, 0x32, 0x19, 0xa4, 0x0a, 0xd7, 0xce, - 0xe6, 0xe1, 0x93, 0xfb, 0x5f, 0x08, 0x8b, 0x42, - 0xa2, 0x20, 0xed, 0x0d, 0x62, 0xca, 0xed, 0x14, - 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, - 0x00, 0x30, 0x2e, 0x33, 0xc0, 0x57, 0x6c, 0xb4, - 0x1b, 0xd2, 0x63, 0xe8, 0x67, 0x10, 0x2d, 0x87, - 0x71, 0x6e, 0x19, 0x60, 0xf4, 0xa4, 0x10, 0x52, - 0x73, 0x2d, 0x09, 0x5e, 0xdb, 0x6c, 0xdc, 0xcf, - 0x2d, 0xff, 0x03, 0x11, 0x95, 0x76, 0x90, 0xd7, - 0x87, 0x54, 0x43, 0xed, 0xc2, 0x36, 0x69, 0x14, - 0x72, 0x4a, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00, - 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, - 0xe8, 0x8b, 0xde, 0xef, 0xba, 0xc5, 0x7e, 0x04, - 0xab, 0xfd, 0x79, 0x56, 0xf3, 0xe1, 0xa5, 0x3e, - 0x02, 0xdf, 0x69, 0x6d, 0x1f, 0x41, 0x9f, 0xbc, - 0x93, 0xe2, 0x6c, 0xf1, 0xb1, 0x38, 0xf5, 0x2b, - 0x8c, 0x4c, 0xf4, 0x74, 0xe1, 0x79, 0x35, 0x34, - 0x97, 0x9b, 0xd5, 0xba, 0xfd, 0xf7, 0x2f, 0x2d, - 0x9e, 0x84, 0x54, 0xee, 0x77, 0x59, 0x23, 0x8f, - 0xc8, 0x84, 0xb4, 0xd6, 0xea, 0x4c, 0x44, 0x8a, - 0xc6, 0x9c, 0xf9, 0x9b, 0x27, 0xea, 0x4f, 0x28, - 0x72, 0x33, 0x12, 0x20, 0x7c, 0xd7, 0x3f, 0x56, - 0xa6, 0x76, 0xc7, 0x48, 0xe4, 0x2d, 0x6f, 0x14, - 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, - 0x00, 0x30, 0x36, 0xe3, 0xd4, 0xf7, 0xb1, 0x69, - 0x18, 0x8d, 0x09, 0xba, 0x52, 0x1e, 0xd5, 0x7d, - 0x2c, 0x15, 0x3a, 0xd6, 0xe3, 0x99, 0x30, 0x2c, - 0x99, 0x97, 0xbc, 0x19, 0x3c, 0x63, 0xa1, 0x25, - 0x68, 0xbc, 0x8a, 0x16, 0x47, 0xec, 0xae, 0x13, - 0xa4, 0x03, 0x96, 0x29, 0x11, 0x92, 0x90, 0x1a, - 0xc8, 0xa4, 0x17, 0x03, 0x01, 0x00, 0x20, 0xc1, - 0x10, 0x1d, 0xa6, 0xf1, 0xe2, 0x8a, 0xcc, 0x37, - 0x7d, 0x8e, 0x05, 0x00, 0xfb, 0xd1, 0x9f, 0xc7, - 0x11, 0xd2, 0x00, 0xb4, 0x27, 0x0a, 0x25, 0x14, - 0xd9, 0x79, 0x1b, 0xcb, 0x4d, 0x81, 0x61, 0x17, - 0x03, 0x01, 0x00, 0x30, 0x5c, 0x7c, 0x2d, 0xc0, - 0x9e, 0xa6, 0xc4, 0x8e, 0xfd, 0xf4, 0xe2, 0xe5, - 0xe4, 0xe6, 0x56, 0x9f, 0x7d, 0x4c, 0x4c, 0x2d, - 0xb7, 0xa9, 0xac, 0xfa, 0x9f, 0x12, 0x7f, 0x2d, - 0x30, 0x57, 0xe4, 0x8e, 0x30, 0x86, 0x65, 0x59, - 0xcd, 0x24, 0xda, 0xe2, 0x8a, 0x7b, 0x0c, 0x5e, - 0x86, 0x05, 0x06, 0x2a, 0x15, 0x03, 0x01, 0x00, - 0x20, 0xd6, 0xb7, 0x70, 0xf8, 0x47, 0xbc, 0x0f, - 0xf4, 0x66, 0x98, 0x1b, 0x1e, 0x8a, 0x8c, 0x0b, - 0xa1, 0x4a, 0x04, 0x29, 0x60, 0x72, 0x8b, 0xc4, - 0x73, 0xc1, 0xd6, 0x41, 0x72, 0xb7, 0x17, 0x39, - 0xda, - }, + test = &serverTest{ + name: "Resume", + command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_in", sessionFilePath}, + } + runServerTestTLS12(t, test) } -var sslv3ServerScript = [][]byte{ - { - 0x16, 0x03, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, - 0x50, 0x03, 0x00, 0x50, 0x77, 0x3d, 0x42, 0xae, - 0x84, 0xbd, 0xc5, 0x07, 0xa5, 0xc4, 0xd6, 0x16, - 0x4e, 0xd5, 0xc5, 0xfa, 0x02, 0x7a, 0x0f, 0x1d, - 0xc1, 0xe1, 0xaa, 0xe3, 0x3b, 0x4b, 0x6f, 0x11, - 0xfa, 0x1a, 0xa4, 0x00, 0x00, 0x28, 0x00, 0x39, - 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13, - 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f, - 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08, - 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01, - 0x00, - }, - { - 0x16, 0x03, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00, - 0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16, - 0x03, 0x00, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, - 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, - 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, - 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, - 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, - 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, - 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, - 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, - 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, - 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, - 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, - 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, - 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, - 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, - 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, - 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, - 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, - 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, - 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, - 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, - 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, - 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, - 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, - 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, - 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, - 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, - 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, - 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, - 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, - 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, - 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, - 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, - 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, - 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, - 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, - 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, - 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, - 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, - 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, - 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, - 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, - 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, - 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, - 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, - 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, - 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, - 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, - 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, - 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, - 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, - 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, - 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, - 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, - 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, - 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, - 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, - 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, - 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, - 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, - 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, - 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, - 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, - 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, - 0xbd, 0xd9, 0x16, 0x03, 0x00, 0x00, 0x04, 0x0e, - 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00, - 0x80, 0x4a, 0x8d, 0xc4, 0x38, 0x7a, 0x9c, 0xd6, - 0xe8, 0x72, 0x9e, 0xa3, 0xdf, 0x37, 0xb4, 0x6c, - 0x58, 0x33, 0x59, 0xd9, 0xc9, 0x4b, 0x50, 0x33, - 0x6c, 0xed, 0x73, 0x38, 0x2a, 0x46, 0x55, 0x31, - 0xa9, 0x8e, 0x8e, 0xfc, 0x0b, 0x5d, 0x5f, 0x3c, - 0x88, 0x28, 0x3f, 0x60, 0x51, 0x13, 0xf1, 0x59, - 0x0c, 0xa3, 0x5e, 0xe0, 0xa3, 0x35, 0x06, 0xb1, - 0x71, 0x59, 0x24, 0x4e, 0xed, 0x07, 0x15, 0x88, - 0x50, 0xef, 0xc2, 0xb2, 0x2a, 0x52, 0x30, 0x6a, - 0x7c, 0xbe, 0x2f, 0xc6, 0x8f, 0xa8, 0x83, 0xc5, - 0x80, 0x14, 0x62, 0x74, 0x7f, 0x96, 0x9f, 0x41, - 0x32, 0x74, 0xdd, 0x76, 0x2d, 0x7b, 0xeb, 0x7b, - 0xea, 0xd0, 0x4f, 0x0c, 0xcf, 0x9a, 0x9c, 0xc5, - 0x7a, 0xe4, 0xbc, 0xf8, 0xa6, 0xe1, 0x09, 0x8e, - 0x7c, 0x53, 0x3a, 0xe3, 0x30, 0x8f, 0x76, 0xee, - 0x58, 0xbb, 0xfd, 0x0b, 0x06, 0xb8, 0xdf, 0xb7, - 0x31, 0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16, - 0x03, 0x00, 0x00, 0x3c, 0x13, 0x91, 0xc6, 0x4a, - 0x0c, 0x59, 0x25, 0xce, 0x54, 0xc0, 0x1d, 0xb9, - 0x2a, 0xff, 0x4d, 0xca, 0x26, 0x0c, 0x8c, 0x04, - 0x98, 0x7c, 0x7c, 0x38, 0xa3, 0xf5, 0xf9, 0x36, - 0x1c, 0x04, 0x32, 0x47, 0x2d, 0x48, 0x0e, 0x96, - 0xe8, 0x2b, 0x5e, 0x5a, 0xc6, 0x0a, 0x48, 0x41, - 0x34, 0x5e, 0x62, 0xd5, 0x68, 0x4e, 0x44, 0x1d, - 0xb2, 0xa1, 0x11, 0xad, 0x6e, 0x14, 0x85, 0x61, - }, - { - 0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x00, 0x00, 0x3c, 0x88, 0xae, 0xa9, 0xd4, 0xa8, - 0x10, 0x8d, 0x65, 0xa6, 0x3e, 0x1e, 0xed, 0xd2, - 0xfc, 0xc4, 0x7c, 0xa8, 0x94, 0x4f, 0x11, 0xaf, - 0xa6, 0x87, 0x09, 0x37, 0x54, 0xf7, 0x69, 0xd1, - 0xb5, 0x25, 0x6b, 0xb5, 0xed, 0xcb, 0x25, 0x39, - 0x73, 0xeb, 0x53, 0x6c, 0xc7, 0xb4, 0x29, 0x8f, - 0xd6, 0x49, 0xd1, 0x95, 0x59, 0x80, 0x9a, 0x67, - 0x5c, 0xb2, 0xe0, 0xbd, 0x1e, 0xff, 0xaa, 0x17, - 0x03, 0x00, 0x00, 0x21, 0x65, 0x7b, 0x99, 0x09, - 0x02, 0xc3, 0x9d, 0x54, 0xd6, 0xe7, 0x32, 0x62, - 0xab, 0xc1, 0x09, 0x91, 0x30, 0x0a, 0xc9, 0xfa, - 0x70, 0xec, 0x06, 0x7b, 0xa3, 0xe1, 0x5f, 0xb4, - 0x63, 0xe6, 0x5c, 0xba, 0x1f, 0x15, 0x03, 0x00, - 0x00, 0x16, 0x40, 0x70, 0xbe, 0xe6, 0xa6, 0xee, - 0x8f, 0xd0, 0x87, 0xa0, 0x43, 0xa1, 0x92, 0xd7, - 0xd0, 0x1a, 0x0c, 0x20, 0x7c, 0xbf, 0xa2, 0xb5, - }, -} +func TestResumptionDisabled(t *testing.T) { + sessionFilePath := tempFile("") + defer os.Remove(sessionFilePath) -var selectCertificateBySNIScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0x6a, 0x01, 0x00, 0x00, - 0x66, 0x03, 0x01, 0x50, 0x77, 0x3d, 0xfe, 0xfb, - 0x8d, 0xc2, 0x68, 0xeb, 0xf9, 0xfa, 0x54, 0x97, - 0x86, 0x45, 0xa2, 0xa3, 0xed, 0xb1, 0x91, 0xb8, - 0x28, 0xc0, 0x47, 0xaf, 0xfb, 0xcd, 0xdc, 0x0e, - 0xb3, 0xea, 0xa5, 0x00, 0x00, 0x28, 0x00, 0x39, - 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13, - 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f, - 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08, - 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01, - 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x0e, 0x00, 0x00, 0x0b, 0x73, 0x6e, 0x69, 0x74, - 0x65, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00, - 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16, - 0x03, 0x01, 0x02, 0x00, 0x0b, 0x00, 0x01, 0xfc, - 0x00, 0x01, 0xf9, 0x00, 0x01, 0xf6, 0x30, 0x82, - 0x01, 0xf2, 0x30, 0x82, 0x01, 0x5d, 0xa0, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, 0x0b, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x30, 0x28, 0x31, 0x10, 0x30, - 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, - 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f, 0x31, - 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, - 0x13, 0x0b, 0x73, 0x6e, 0x69, 0x74, 0x65, 0x73, - 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, - 0x0d, 0x31, 0x32, 0x30, 0x34, 0x31, 0x31, 0x31, - 0x37, 0x34, 0x30, 0x33, 0x35, 0x5a, 0x17, 0x0d, - 0x31, 0x33, 0x30, 0x34, 0x31, 0x31, 0x31, 0x37, - 0x34, 0x35, 0x33, 0x35, 0x5a, 0x30, 0x28, 0x31, - 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x13, 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, - 0x6f, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x13, 0x0b, 0x73, 0x6e, 0x69, 0x74, - 0x65, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, - 0x81, 0x9d, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x03, - 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, - 0x81, 0x00, 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, - 0xe5, 0xbf, 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, - 0xe6, 0x2b, 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, - 0x8a, 0x7a, 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, - 0xa5, 0x65, 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, - 0xb5, 0xb4, 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, - 0x7e, 0x62, 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, - 0x12, 0x5c, 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, - 0xfa, 0x58, 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, - 0xd3, 0xd0, 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, - 0x54, 0x9f, 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, - 0xfe, 0x18, 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, - 0x7d, 0xf1, 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, - 0x51, 0xc9, 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, - 0x66, 0x01, 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, - 0x9a, 0x1d, 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, - 0x2d, 0x79, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, - 0x32, 0x30, 0x30, 0x30, 0x0e, 0x06, 0x03, 0x55, - 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, - 0x02, 0x00, 0xa0, 0x30, 0x0d, 0x06, 0x03, 0x55, - 0x1d, 0x0e, 0x04, 0x06, 0x04, 0x04, 0x01, 0x02, - 0x03, 0x04, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, - 0x23, 0x04, 0x08, 0x30, 0x06, 0x80, 0x04, 0x01, - 0x02, 0x03, 0x04, 0x30, 0x0b, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, - 0x03, 0x81, 0x81, 0x00, 0x89, 0xc6, 0x45, 0x5f, - 0x1c, 0x1f, 0x5e, 0xf8, 0xeb, 0x1a, 0xb1, 0x74, - 0xee, 0x24, 0x39, 0x05, 0x9f, 0x5c, 0x42, 0x59, - 0xbb, 0x1a, 0x8d, 0x86, 0xcd, 0xb1, 0xd0, 0x56, - 0xf5, 0x6a, 0x71, 0x7d, 0xa4, 0x0e, 0x95, 0xab, - 0x90, 0xf5, 0x9e, 0x8d, 0xea, 0xf6, 0x27, 0xc1, - 0x57, 0x99, 0x50, 0x94, 0xdb, 0x08, 0x02, 0x26, - 0x6e, 0xb3, 0x4f, 0xc6, 0x84, 0x2d, 0xea, 0x8a, - 0x4b, 0x68, 0xd9, 0xc1, 0x38, 0x91, 0x03, 0xab, - 0x84, 0xfb, 0x9e, 0x1f, 0x85, 0xd9, 0xb5, 0xd2, - 0x3f, 0xf2, 0x31, 0x2c, 0x86, 0x70, 0xfb, 0xb5, - 0x40, 0x14, 0x82, 0x45, 0xa4, 0xeb, 0xaf, 0xe2, - 0x64, 0xd9, 0x0c, 0x8a, 0x4c, 0xf4, 0xf8, 0x5b, - 0x0f, 0xac, 0x12, 0xac, 0x2f, 0xc4, 0xa3, 0x15, - 0x4b, 0xad, 0x52, 0x46, 0x28, 0x68, 0xaf, 0x96, - 0xc6, 0x2c, 0x65, 0x25, 0xd6, 0x52, 0xb6, 0xe3, - 0x18, 0x45, 0xbd, 0xcc, 0x16, 0x03, 0x01, 0x00, - 0x04, 0x0e, 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00, - 0x82, 0x00, 0x80, 0x69, 0xc3, 0xd4, 0x0e, 0xcc, - 0xdc, 0xbc, 0x5e, 0xc2, 0x64, 0xa6, 0xde, 0x3c, - 0x0c, 0x7e, 0x0c, 0x6b, 0x80, 0x0f, 0xd4, 0x8f, - 0x02, 0x4b, 0xb2, 0xba, 0x8d, 0x01, 0xeb, 0x6b, - 0xa1, 0x2e, 0x79, 0x37, 0xba, 0xae, 0x24, 0xc2, - 0x26, 0x72, 0x51, 0xe1, 0x82, 0x8e, 0x51, 0x41, - 0x1c, 0x54, 0xa4, 0x26, 0xbe, 0x13, 0xcd, 0x1b, - 0xc6, 0xed, 0x3d, 0x1f, 0xfd, 0x72, 0x80, 0x90, - 0xdb, 0xbf, 0xd6, 0x39, 0x94, 0x5f, 0x48, 0xfb, - 0x25, 0x5a, 0xc9, 0x60, 0x9b, 0xd7, 0xc6, 0x20, - 0xa8, 0x66, 0x64, 0x13, 0xf3, 0x65, 0xc8, 0xb1, - 0xd5, 0x33, 0x21, 0x0e, 0x73, 0x41, 0xc0, 0x18, - 0x1a, 0x37, 0xfe, 0xcf, 0x28, 0x2a, 0xcd, 0xe4, - 0x0b, 0xac, 0xdd, 0x25, 0x5e, 0xcb, 0x17, 0x51, - 0x69, 0xd5, 0x8c, 0xf4, 0xb6, 0x21, 0x98, 0xef, - 0x20, 0xdb, 0x14, 0x67, 0xf3, 0x7c, 0x95, 0x6a, - 0x48, 0x2a, 0x6a, 0x14, 0x03, 0x01, 0x00, 0x01, - 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0x36, 0x1b, - 0x09, 0xe5, 0xb9, 0xb9, 0x4d, 0x7d, 0xae, 0x87, - 0xb6, 0x0f, 0xaf, 0xec, 0x22, 0xba, 0x0d, 0xa5, - 0x96, 0x5e, 0x64, 0x65, 0xe7, 0xfb, 0xe3, 0xf3, - 0x6b, 0x72, 0xa8, 0xdb, 0xed, 0xd8, 0x69, 0x9c, - 0x08, 0xd8, - }, - { - 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x01, 0x00, 0x24, 0x60, 0xf7, 0x09, 0x5f, 0xd1, - 0xcb, 0xc9, 0xe1, 0x22, 0xb5, 0x2a, 0xcc, 0xde, - 0x7c, 0xa7, 0xb8, 0x85, 0x00, 0xbc, 0xfd, 0x85, - 0xe1, 0x91, 0x36, 0xbb, 0x07, 0x42, 0xad, 0x3d, - 0x29, 0x62, 0x69, 0xc1, 0x45, 0x92, 0x6f, 0x17, - 0x03, 0x01, 0x00, 0x21, 0x0d, 0xf9, 0xd5, 0x87, - 0xb9, 0x57, 0x3c, 0x50, 0x19, 0xe4, 0x3a, 0x50, - 0x45, 0xcc, 0x86, 0x89, 0xd4, 0x32, 0x79, 0x45, - 0x7c, 0x9f, 0x96, 0xd4, 0x54, 0x56, 0x0c, 0x63, - 0x72, 0x81, 0xc3, 0xd3, 0xe3, 0x15, 0x03, 0x01, - 0x00, 0x16, 0x84, 0xec, 0x2e, 0xf6, 0xaf, 0x4f, - 0xee, 0x48, 0x0f, 0xbe, 0xcd, 0x82, 0x5c, 0x56, - 0x16, 0xe4, 0xfb, 0x89, 0xc5, 0x57, 0x3e, 0x91, - }, -} + config := *testConfig -var issueSessionTicketTest = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x00, - 0x56, 0x03, 0x01, 0x50, 0x77, 0x3e, 0x49, 0x7a, - 0xb7, 0x86, 0x5c, 0x27, 0xd2, 0x97, 0x61, 0xe3, - 0x49, 0x41, 0x48, 0xe7, 0x0e, 0xaa, 0x7e, 0x4d, - 0xb8, 0xdc, 0x01, 0x97, 0xfb, 0xab, 0x53, 0xb2, - 0x5e, 0x36, 0xf6, 0x00, 0x00, 0x28, 0x00, 0x39, - 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13, - 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f, - 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08, - 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01, - 0x00, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00, - 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01, - 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02, - 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0, - 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4, - 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, - 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, - 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, - 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, - 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, - 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, - 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30, - 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33, - 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, - 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, - 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, - 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, - 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, - 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79, - 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10, - 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43, - 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85, - 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c, - 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5, - 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c, - 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56, - 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26, - 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21, - 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf, - 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07, - 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39, - 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3, - 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf, - 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb, - 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, - 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85, - 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23, - 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39, - 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2, - 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, - 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, - 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85, - 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, - 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59, - 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7, - 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95, - 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66, - 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3, - 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13, - 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba, - 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31, - 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50, - 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f, - 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96, - 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f, - 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b, - 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70, - 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e, - 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9, - 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, - 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00, - 0x82, 0x00, 0x80, 0x68, 0x10, 0xdc, 0x80, 0xbc, - 0xb3, 0x5a, 0x10, 0x75, 0x89, 0xcc, 0xe5, 0x9f, - 0xbf, 0xe2, 0xce, 0xa4, 0x9f, 0x7f, 0x60, 0xc4, - 0xfe, 0x5c, 0xb5, 0x02, 0x2d, 0xa5, 0xa9, 0x1e, - 0x2c, 0x10, 0x79, 0x15, 0x0f, 0xed, 0x96, 0xb3, - 0xa8, 0x5e, 0x21, 0xbc, 0x5b, 0xdc, 0x58, 0x04, - 0x7d, 0x37, 0xdb, 0xa0, 0x31, 0xe8, 0x4f, 0x04, - 0xbc, 0x46, 0x7c, 0xdb, 0x2e, 0x93, 0x07, 0xaf, - 0xa6, 0x36, 0xd3, 0x39, 0x8d, 0x1d, 0x95, 0xa8, - 0x50, 0x4b, 0xc4, 0x2b, 0xde, 0xd7, 0x04, 0x6d, - 0x77, 0x6c, 0x4d, 0x70, 0x51, 0x88, 0x16, 0x31, - 0x40, 0xb5, 0xba, 0x90, 0x47, 0x64, 0x0c, 0x87, - 0xa5, 0x19, 0xf9, 0x89, 0x24, 0x3c, 0x5e, 0x4b, - 0xaa, 0xe0, 0x60, 0x47, 0x0f, 0x2e, 0xcc, 0xc2, - 0xd5, 0x21, 0xed, 0x72, 0xd0, 0xa9, 0xdd, 0x2a, - 0x2b, 0xef, 0x08, 0x3a, 0x65, 0xea, 0x8b, 0x52, - 0x77, 0x2d, 0xcc, 0x14, 0x03, 0x01, 0x00, 0x01, - 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0xe2, 0x95, - 0x62, 0x3c, 0x18, 0xe5, 0xc7, 0x2c, 0xda, 0x16, - 0x9b, 0x28, 0x0d, 0xf7, 0x88, 0x7b, 0x5d, 0x33, - 0x55, 0x3b, 0x01, 0x73, 0xf2, 0xc6, 0x4e, 0x96, - 0x01, 0x01, 0x83, 0x65, 0xd4, 0xef, 0x12, 0x13, - 0x1d, 0x42, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00, - 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, - 0xe8, 0x4b, 0xd1, 0xef, 0xba, 0xfb, 0x41, 0x92, - 0x6d, 0x37, 0x5f, 0xf8, 0x7d, 0x90, 0x0f, 0x01, - 0xf8, 0x8c, 0xee, 0xbc, 0xd9, 0x0c, 0x97, 0x7e, - 0x23, 0x46, 0xe2, 0x6b, 0x52, 0xc6, 0xc6, 0x97, - 0x1d, 0xab, 0xde, 0xa0, 0x86, 0x94, 0xc8, 0x2e, - 0x8b, 0x2e, 0x42, 0x5f, 0xc2, 0x70, 0x35, 0xc9, - 0xee, 0x37, 0xeb, 0x70, 0xaa, 0x59, 0x23, 0x6c, - 0xc8, 0xc1, 0x84, 0x89, 0x39, 0x87, 0x73, 0x0a, - 0x7e, 0xba, 0xca, 0xed, 0x63, 0xba, 0x4e, 0x4f, - 0xf3, 0x31, 0x4b, 0xf0, 0xee, 0x91, 0xa5, 0xb4, - 0x62, 0x01, 0x9e, 0xbd, 0xbc, 0xb3, 0x35, 0x14, - 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, - 0x00, 0x24, 0x3f, 0x66, 0xe4, 0x98, 0xc1, 0x3f, - 0xc6, 0x2c, 0x81, 0xfb, 0xa9, 0x9f, 0x27, 0xe9, - 0x63, 0x20, 0x1e, 0x0e, 0x4f, 0xfc, 0x5d, 0x12, - 0xee, 0x77, 0x73, 0xc6, 0x96, 0x51, 0xf2, 0x26, - 0x35, 0x3f, 0xce, 0x6a, 0xa9, 0xfd, 0x17, 0x03, - 0x01, 0x00, 0x21, 0x8d, 0xd5, 0x67, 0x60, 0x5d, - 0xa7, 0x93, 0xcc, 0x39, 0x78, 0x59, 0xab, 0xdb, - 0x10, 0x96, 0xf2, 0xad, 0xa2, 0x85, 0xe2, 0x93, - 0x43, 0x43, 0xcf, 0x82, 0xbd, 0x1f, 0xdc, 0x7a, - 0x72, 0xd6, 0x83, 0x3b, 0x15, 0x03, 0x01, 0x00, - 0x16, 0x89, 0x55, 0xf6, 0x42, 0x71, 0xa9, 0xe9, - 0x05, 0x68, 0xe8, 0xce, 0x0d, 0x21, 0xe9, 0xec, - 0xf2, 0x27, 0x67, 0xa7, 0x94, 0xf8, 0x34, - }, -} -var serverResumeTest = [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0xc2, 0x01, 0x00, 0x00, - 0xbe, 0x03, 0x01, 0x50, 0x77, 0x3e, 0x4f, 0x1f, - 0x6f, 0xa5, 0x81, 0xeb, 0xb8, 0x80, 0x55, 0xa4, - 0x76, 0xc2, 0x7f, 0x27, 0xf2, 0xe7, 0xc9, 0x7a, - 0x01, 0x3c, 0xd8, 0xc1, 0xde, 0x99, 0x1f, 0x7c, - 0xab, 0x35, 0x98, 0x00, 0x00, 0x28, 0x00, 0x39, - 0x00, 0x38, 0x00, 0x35, 0x00, 0x16, 0x00, 0x13, - 0x00, 0x0a, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2f, - 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08, - 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x02, 0x01, - 0x00, 0x00, 0x6c, 0x00, 0x23, 0x00, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, - 0xe8, 0x4b, 0xd1, 0xef, 0xba, 0xfb, 0x41, 0x92, - 0x6d, 0x37, 0x5f, 0xf8, 0x7d, 0x90, 0x0f, 0x01, - 0xf8, 0x8c, 0xee, 0xbc, 0xd9, 0x0c, 0x97, 0x7e, - 0x23, 0x46, 0xe2, 0x6b, 0x52, 0xc6, 0xc6, 0x97, - 0x1d, 0xab, 0xde, 0xa0, 0x86, 0x94, 0xc8, 0x2e, - 0x8b, 0x2e, 0x42, 0x5f, 0xc2, 0x70, 0x35, 0xc9, - 0xee, 0x37, 0xeb, 0x70, 0xaa, 0x59, 0x23, 0x6c, - 0xc8, 0xc1, 0x84, 0x89, 0x39, 0x87, 0x73, 0x0a, - 0x7e, 0xba, 0xca, 0xed, 0x63, 0xba, 0x4e, 0x4f, - 0xf3, 0x31, 0x4b, 0xf0, 0xee, 0x91, 0xa5, 0xb4, - 0x62, 0x01, 0x9e, 0xbd, 0xbc, 0xb3, 0x35, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00, - 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x14, - 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, - 0x00, 0x24, 0xc5, 0x35, 0x74, 0x19, 0x05, 0xc5, - 0x85, 0x68, 0x48, 0xe8, 0xb5, 0xe9, 0xaf, 0x78, - 0xbd, 0x35, 0x6f, 0xe9, 0x79, 0x34, 0x1b, 0xf0, - 0x35, 0xd4, 0x4e, 0x55, 0x2e, 0x3c, 0xd5, 0xaf, - 0xfc, 0xba, 0xf5, 0x1e, 0x83, 0x32, - }, - { - 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, - 0x01, 0x00, 0x24, 0x27, 0x28, 0x88, 0xe1, 0x7e, - 0x0d, 0x9c, 0x12, 0x50, 0xf6, 0x7a, 0xa7, 0x32, - 0x21, 0x68, 0xba, 0xd8, 0x0a, 0xdc, 0x39, 0xef, - 0x68, 0x95, 0x82, 0xae, 0xbd, 0x12, 0x79, 0xa1, - 0x99, 0xfd, 0xd0, 0x10, 0x8e, 0x4b, 0xd8, - }, - { - 0x17, 0x03, 0x01, 0x00, 0x21, 0xc5, 0x7e, 0x0a, - 0x52, 0x6a, 0xb9, 0xaa, 0x1d, 0xae, 0x9e, 0x24, - 0x9c, 0x34, 0x1e, 0xdb, 0x50, 0x95, 0xee, 0x76, - 0xd7, 0x28, 0x88, 0x08, 0xe3, 0x2e, 0x58, 0xf7, - 0xdb, 0x34, 0x75, 0xa5, 0x7f, 0x9d, 0x15, 0x03, - 0x01, 0x00, 0x16, 0x2c, 0xc1, 0x29, 0x5f, 0x12, - 0x1d, 0x19, 0xab, 0xb3, 0xf4, 0x35, 0x1c, 0x62, - 0x6a, 0x80, 0x29, 0x0d, 0x0e, 0xef, 0x7d, 0x6e, - 0x50, - }, -} + test := &serverTest{ + name: "IssueTicketPreDisable", + command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_out", sessionFilePath}, + config: &config, + } + runServerTestTLS12(t, test) -var clientauthRSATests = []clientauthTest{ - // Server asks for cert with empty CA list, client doesn't give it. - // go test -run "TestRunServer" -serve -clientauth 1 - {"RequestClientCert, none given", RequestClientCert, nil, [][]byte{ - { - 0x16, 0x03, 0x01, 0x01, 0x1e, 0x01, 0x00, 0x01, - 0x1a, 0x03, 0x03, 0x51, 0xe5, 0x6c, 0xb5, 0x5a, - 0xc2, 0xf5, 0xf0, 0x92, 0x94, 0x8a, 0x64, 0x18, - 0xa4, 0x2b, 0x82, 0x07, 0xbc, 0xd9, 0xd9, 0xf9, - 0x7b, 0xd2, 0xd0, 0xee, 0xa2, 0x70, 0x4e, 0x23, - 0x88, 0x7c, 0x95, 0x00, 0x00, 0x82, 0xc0, 0x30, - 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, - 0xc0, 0x0a, 0x00, 0xa3, 0x00, 0x9f, 0x00, 0x6b, - 0x00, 0x6a, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x32, - 0xc0, 0x2e, 0xc0, 0x2a, 0xc0, 0x26, 0xc0, 0x0f, - 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, - 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x13, - 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, 0xc0, 0x2f, - 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13, - 0xc0, 0x09, 0x00, 0xa2, 0x00, 0x9e, 0x00, 0x67, - 0x00, 0x40, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x31, - 0xc0, 0x2d, 0xc0, 0x29, 0xc0, 0x25, 0xc0, 0x0e, - 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, - 0x00, 0x07, 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c, - 0xc0, 0x02, 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, - 0x00, 0x12, 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, - 0x00, 0x08, 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, - 0x01, 0x00, 0x00, 0x6f, 0x00, 0x0b, 0x00, 0x04, - 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a, 0x00, 0x34, - 0x00, 0x32, 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x19, - 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x09, - 0x00, 0x0a, 0x00, 0x16, 0x00, 0x17, 0x00, 0x08, - 0x00, 0x06, 0x00, 0x07, 0x00, 0x14, 0x00, 0x15, - 0x00, 0x04, 0x00, 0x05, 0x00, 0x12, 0x00, 0x13, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x0f, - 0x00, 0x10, 0x00, 0x11, 0x00, 0x23, 0x00, 0x00, - 0x00, 0x0d, 0x00, 0x22, 0x00, 0x20, 0x06, 0x01, - 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, 0x05, 0x02, - 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, - 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x00, 0x0f, - 0x00, 0x01, 0x01, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00, - 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01, - 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02, - 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0, - 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4, - 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, - 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, - 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, - 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, - 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, - 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, - 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30, - 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33, - 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, - 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, - 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, - 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, - 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, - 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79, - 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10, - 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43, - 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85, - 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c, - 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5, - 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c, - 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56, - 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26, - 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21, - 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf, - 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07, - 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39, - 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3, - 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf, - 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb, - 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, - 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85, - 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23, - 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39, - 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2, - 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, - 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, - 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85, - 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, - 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59, - 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7, - 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95, - 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66, - 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3, - 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13, - 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba, - 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31, - 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50, - 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f, - 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96, - 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f, - 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b, - 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70, - 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e, - 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9, - 0x16, 0x03, 0x01, 0x00, 0x09, 0x0d, 0x00, 0x00, - 0x05, 0x02, 0x01, 0x40, 0x00, 0x00, 0x16, 0x03, - 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x07, 0x0b, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x16, 0x03, 0x01, 0x00, - 0x86, 0x10, 0x00, 0x00, 0x82, 0x00, 0x80, 0x36, - 0xfc, 0xd8, 0xc8, 0xa2, 0x67, 0xc8, 0xc6, 0xf4, - 0x28, 0x70, 0xe1, 0x5a, 0x02, 0x8f, 0xef, 0x42, - 0xe0, 0xd3, 0xb8, 0xd6, 0x6b, 0xe4, 0xee, 0x5c, - 0xcf, 0x42, 0xc4, 0xfa, 0xcd, 0x0f, 0xfe, 0xf4, - 0x76, 0x76, 0x47, 0x73, 0xa8, 0x72, 0x8f, 0xa2, - 0x56, 0x81, 0x83, 0xb8, 0x84, 0x72, 0x67, 0xdd, - 0xbe, 0x05, 0x4b, 0x84, 0xd9, 0xd2, 0xb6, 0xc2, - 0xe7, 0x20, 0xac, 0x1f, 0x46, 0x9d, 0x05, 0x47, - 0x8e, 0x89, 0xc0, 0x42, 0x57, 0x4a, 0xa2, 0x98, - 0xe5, 0x39, 0x4f, 0xc4, 0x27, 0x6d, 0x43, 0xa8, - 0x83, 0x76, 0xe6, 0xad, 0xe3, 0x17, 0x68, 0x31, - 0xcb, 0x7e, 0xfc, 0xe7, 0x4b, 0x76, 0x3d, 0x3c, - 0xfa, 0x77, 0x65, 0xc9, 0x4c, 0x5b, 0xce, 0x5e, - 0xf7, 0x8b, 0xa8, 0xa6, 0xdd, 0xb2, 0xef, 0x0b, - 0x46, 0x83, 0xdf, 0x0a, 0x8c, 0x22, 0x12, 0x6e, - 0xe1, 0x45, 0x54, 0x88, 0xd1, 0xe8, 0xd2, 0x14, - 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, - 0x00, 0x24, 0x30, 0x8c, 0x7d, 0x40, 0xfc, 0x5e, - 0x80, 0x9c, 0xc4, 0x7c, 0x62, 0x01, 0xa1, 0x37, - 0xcf, 0x1a, 0x75, 0x28, 0x8d, 0xeb, 0x63, 0xcc, - 0x02, 0xa6, 0x66, 0xdf, 0x36, 0x01, 0xb3, 0x9d, - 0x38, 0x42, 0x16, 0x91, 0xf0, 0x02, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x72, 0x04, 0x00, 0x00, - 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, - 0xe8, 0x4b, 0xd1, 0xef, 0xba, 0x96, 0x9a, 0x2a, - 0x6c, 0x8c, 0x7e, 0x38, 0x10, 0x46, 0x86, 0x1d, - 0x19, 0x1d, 0x62, 0x29, 0x3f, 0x58, 0xfb, 0x6d, - 0x89, 0xd2, 0x81, 0x9a, 0x1c, 0xb3, 0x58, 0xb3, - 0x19, 0x39, 0x17, 0x47, 0x49, 0xc9, 0xfe, 0x4a, - 0x7a, 0x32, 0xac, 0x2c, 0x43, 0xf9, 0xa9, 0xea, - 0xec, 0x51, 0x46, 0xf1, 0xb8, 0x59, 0x23, 0x70, - 0xce, 0x7c, 0xb9, 0x47, 0x70, 0xa3, 0xc9, 0xae, - 0x47, 0x7b, 0x7e, 0xc7, 0xcf, 0x76, 0x12, 0x76, - 0x18, 0x90, 0x12, 0xcd, 0xf3, 0xd4, 0x27, 0x81, - 0xfc, 0x46, 0x03, 0x3e, 0x05, 0x87, 0x6f, 0x14, - 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, - 0x00, 0x24, 0xc3, 0xa0, 0x29, 0xb1, 0x52, 0x82, - 0xef, 0x85, 0xa1, 0x64, 0x0f, 0xe4, 0xa3, 0xfb, - 0xa7, 0x1d, 0x22, 0x4c, 0xcb, 0xd6, 0x5b, 0x18, - 0x61, 0xc7, 0x7c, 0xf2, 0x67, 0x4a, 0xc7, 0x11, - 0x9d, 0x8e, 0x0e, 0x15, 0x22, 0xcf, 0x17, 0x03, - 0x01, 0x00, 0x21, 0xfd, 0xbb, 0xf1, 0xa9, 0x7c, - 0xbf, 0x92, 0xb3, 0xfa, 0x2c, 0x08, 0x6f, 0x22, - 0x78, 0x80, 0xf2, 0x2e, 0x86, 0x26, 0x21, 0x36, - 0x3f, 0x32, 0xdf, 0xb6, 0x47, 0xa5, 0xf8, 0x27, - 0xc1, 0xe9, 0x53, 0x90, 0x15, 0x03, 0x01, 0x00, - 0x16, 0xfe, 0xef, 0x2e, 0xa0, 0x5d, 0xe0, 0xce, - 0x94, 0x20, 0x56, 0x61, 0x6e, 0xe5, 0x62, 0xce, - 0x27, 0x57, 0x3e, 0x30, 0x32, 0x77, 0x53, - }, - }}, + config.SessionTicketsDisabled = true - // Server asks for cert with empty CA list, client gives one - // go test -run "TestRunServer" -serve -clientauth 1 - {"RequestClientCert, client gives it", RequestClientCert, []*x509.Certificate{clientCertificate}, [][]byte{ - { - 0x16, 0x03, 0x01, 0x01, 0x1e, 0x01, 0x00, 0x01, - 0x1a, 0x03, 0x03, 0x51, 0xe5, 0x74, 0x0e, 0x95, - 0x6f, 0x4f, 0x4a, 0xbf, 0xb7, 0xc0, 0x6c, 0xac, - 0xd9, 0xfe, 0x7d, 0xd0, 0x51, 0x19, 0x62, 0x62, - 0x1c, 0x6e, 0x57, 0x77, 0xd2, 0x31, 0xaf, 0x88, - 0xb9, 0xc0, 0x1d, 0x00, 0x00, 0x82, 0xc0, 0x30, - 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, - 0xc0, 0x0a, 0x00, 0xa3, 0x00, 0x9f, 0x00, 0x6b, - 0x00, 0x6a, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x32, - 0xc0, 0x2e, 0xc0, 0x2a, 0xc0, 0x26, 0xc0, 0x0f, - 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, - 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x13, - 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, 0xc0, 0x2f, - 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13, - 0xc0, 0x09, 0x00, 0xa2, 0x00, 0x9e, 0x00, 0x67, - 0x00, 0x40, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x31, - 0xc0, 0x2d, 0xc0, 0x29, 0xc0, 0x25, 0xc0, 0x0e, - 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, - 0x00, 0x07, 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c, - 0xc0, 0x02, 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, - 0x00, 0x12, 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, - 0x00, 0x08, 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, - 0x01, 0x00, 0x00, 0x6f, 0x00, 0x0b, 0x00, 0x04, - 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a, 0x00, 0x34, - 0x00, 0x32, 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x19, - 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x09, - 0x00, 0x0a, 0x00, 0x16, 0x00, 0x17, 0x00, 0x08, - 0x00, 0x06, 0x00, 0x07, 0x00, 0x14, 0x00, 0x15, - 0x00, 0x04, 0x00, 0x05, 0x00, 0x12, 0x00, 0x13, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x0f, - 0x00, 0x10, 0x00, 0x11, 0x00, 0x23, 0x00, 0x00, - 0x00, 0x0d, 0x00, 0x22, 0x00, 0x20, 0x06, 0x01, - 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, 0x05, 0x02, - 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, - 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x00, 0x0f, - 0x00, 0x01, 0x01, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00, - 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01, - 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02, - 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0, - 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4, - 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, - 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, - 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, - 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, - 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, - 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, - 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30, - 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33, - 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, - 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, - 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, - 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, - 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, - 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79, - 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10, - 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43, - 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85, - 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c, - 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5, - 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c, - 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56, - 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26, - 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21, - 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf, - 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07, - 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39, - 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3, - 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf, - 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb, - 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, - 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85, - 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23, - 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39, - 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2, - 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, - 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, - 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85, - 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, - 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59, - 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7, - 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95, - 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66, - 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3, - 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13, - 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba, - 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31, - 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50, - 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f, - 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96, - 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f, - 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b, - 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70, - 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e, - 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9, - 0x16, 0x03, 0x01, 0x00, 0x09, 0x0d, 0x00, 0x00, - 0x05, 0x02, 0x01, 0x40, 0x00, 0x00, 0x16, 0x03, - 0x01, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x01, 0xfb, 0x0b, 0x00, 0x01, - 0xf7, 0x00, 0x01, 0xf4, 0x00, 0x01, 0xf1, 0x30, - 0x82, 0x01, 0xed, 0x30, 0x82, 0x01, 0x58, 0xa0, - 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, - 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05, 0x30, 0x26, 0x31, 0x10, - 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f, - 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, - 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x31, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37, - 0x35, 0x35, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x31, - 0x32, 0x31, 0x32, 0x30, 0x37, 0x30, 0x38, 0x30, - 0x30, 0x31, 0x32, 0x5a, 0x30, 0x26, 0x31, 0x10, - 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f, - 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, - 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, 0x9c, 0x30, - 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x03, 0x81, 0x8c, 0x00, - 0x30, 0x81, 0x88, 0x02, 0x81, 0x80, 0x4e, 0xd0, - 0x7b, 0x31, 0xe3, 0x82, 0x64, 0xd9, 0x59, 0xc0, - 0xc2, 0x87, 0xa4, 0x5e, 0x1e, 0x8b, 0x73, 0x33, - 0xc7, 0x63, 0x53, 0xdf, 0x66, 0x92, 0x06, 0x84, - 0xf6, 0x64, 0xd5, 0x8f, 0xe4, 0x36, 0xa7, 0x1d, - 0x2b, 0xe8, 0xb3, 0x20, 0x36, 0x45, 0x23, 0xb5, - 0xe3, 0x95, 0xae, 0xed, 0xe0, 0xf5, 0x20, 0x9c, - 0x8d, 0x95, 0xdf, 0x7f, 0x5a, 0x12, 0xef, 0x87, - 0xe4, 0x5b, 0x68, 0xe4, 0xe9, 0x0e, 0x74, 0xec, - 0x04, 0x8a, 0x7f, 0xde, 0x93, 0x27, 0xc4, 0x01, - 0x19, 0x7a, 0xbd, 0xf2, 0xdc, 0x3d, 0x14, 0xab, - 0xd0, 0x54, 0xca, 0x21, 0x0c, 0xd0, 0x4d, 0x6e, - 0x87, 0x2e, 0x5c, 0xc5, 0xd2, 0xbb, 0x4d, 0x4b, - 0x4f, 0xce, 0xb6, 0x2c, 0xf7, 0x7e, 0x88, 0xec, - 0x7c, 0xd7, 0x02, 0x91, 0x74, 0xa6, 0x1e, 0x0c, - 0x1a, 0xda, 0xe3, 0x4a, 0x5a, 0x2e, 0xde, 0x13, - 0x9c, 0x4c, 0x40, 0x88, 0x59, 0x93, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x32, 0x30, 0x30, 0x30, - 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, - 0xff, 0x04, 0x04, 0x03, 0x02, 0x00, 0xa0, 0x30, - 0x0d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x06, - 0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30, 0x0f, - 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x08, 0x30, - 0x06, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30, - 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05, 0x03, 0x81, 0x81, 0x00, - 0x36, 0x1f, 0xb3, 0x7a, 0x0c, 0x75, 0xc9, 0x6e, - 0x37, 0x46, 0x61, 0x2b, 0xd5, 0xbd, 0xc0, 0xa7, - 0x4b, 0xcc, 0x46, 0x9a, 0x81, 0x58, 0x7c, 0x85, - 0x79, 0x29, 0xc8, 0xc8, 0xc6, 0x67, 0xdd, 0x32, - 0x56, 0x45, 0x2b, 0x75, 0xb6, 0xe9, 0x24, 0xa9, - 0x50, 0x9a, 0xbe, 0x1f, 0x5a, 0xfa, 0x1a, 0x15, - 0xd9, 0xcc, 0x55, 0x95, 0x72, 0x16, 0x83, 0xb9, - 0xc2, 0xb6, 0x8f, 0xfd, 0x88, 0x8c, 0x38, 0x84, - 0x1d, 0xab, 0x5d, 0x92, 0x31, 0x13, 0x4f, 0xfd, - 0x83, 0x3b, 0xc6, 0x9d, 0xf1, 0x11, 0x62, 0xb6, - 0x8b, 0xec, 0xab, 0x67, 0xbe, 0xc8, 0x64, 0xb0, - 0x11, 0x50, 0x46, 0x58, 0x17, 0x6b, 0x99, 0x1c, - 0xd3, 0x1d, 0xfc, 0x06, 0xf1, 0x0e, 0xe5, 0x96, - 0xa8, 0x0c, 0xf9, 0x78, 0x20, 0xb7, 0x44, 0x18, - 0x51, 0x8d, 0x10, 0x7e, 0x4f, 0x94, 0x67, 0xdf, - 0xa3, 0x4e, 0x70, 0x73, 0x8e, 0x90, 0x91, 0x85, - 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00, - 0x82, 0x00, 0x80, 0x0a, 0x4e, 0x89, 0xdf, 0x3a, - 0x3f, 0xf0, 0x4f, 0xef, 0x1a, 0x90, 0xd4, 0x3c, - 0xaf, 0x10, 0x57, 0xb0, 0xa1, 0x5f, 0xcd, 0x62, - 0x01, 0xe9, 0x0c, 0x36, 0x42, 0xfd, 0xaf, 0x23, - 0xf9, 0x14, 0xa6, 0x72, 0x26, 0x4e, 0x01, 0xdb, - 0xac, 0xb7, 0x4c, 0xe6, 0xa9, 0x52, 0xe2, 0xec, - 0x26, 0x8c, 0x7a, 0x64, 0xf8, 0x0b, 0x4c, 0x2f, - 0xa9, 0xcb, 0x75, 0xaf, 0x60, 0xd4, 0xb4, 0xe6, - 0xe8, 0xdb, 0x78, 0x78, 0x85, 0xf6, 0x0c, 0x95, - 0xcc, 0xb6, 0x55, 0xb9, 0xba, 0x9e, 0x91, 0xbc, - 0x66, 0xdb, 0x1e, 0x28, 0xab, 0x73, 0xce, 0x8b, - 0xd0, 0xd3, 0xe8, 0xbc, 0xd0, 0x21, 0x28, 0xbd, - 0xfb, 0x74, 0x64, 0xde, 0x3b, 0x3b, 0xd3, 0x4c, - 0x32, 0x40, 0x82, 0xba, 0x91, 0x1e, 0xe8, 0x47, - 0xc2, 0x09, 0xb7, 0x16, 0xaa, 0x25, 0xa9, 0x3c, - 0x6c, 0xa7, 0xf8, 0xc9, 0x54, 0x84, 0xc6, 0xf7, - 0x56, 0x05, 0xa4, 0x16, 0x03, 0x01, 0x00, 0x86, - 0x0f, 0x00, 0x00, 0x82, 0x00, 0x80, 0x4b, 0xab, - 0xda, 0xac, 0x2a, 0xb3, 0xe6, 0x34, 0x55, 0xcd, - 0xf2, 0x4b, 0x67, 0xe3, 0xd3, 0xff, 0xa3, 0xf4, - 0x79, 0x82, 0x01, 0x47, 0x8a, 0xe3, 0x9f, 0x89, - 0x70, 0xbe, 0x24, 0x24, 0xb7, 0x69, 0x60, 0xed, - 0x55, 0xa0, 0xca, 0x72, 0xb6, 0x4a, 0xbc, 0x1d, - 0xe2, 0x3f, 0xb5, 0x31, 0xda, 0x02, 0xf6, 0x37, - 0x51, 0xf8, 0x4c, 0x88, 0x2e, 0xb3, 0x8a, 0xe8, - 0x7b, 0x4a, 0x90, 0x36, 0xe4, 0xa6, 0x31, 0x95, - 0x8b, 0xa0, 0xc6, 0x91, 0x12, 0xb9, 0x35, 0x4e, - 0x72, 0xeb, 0x5c, 0xa2, 0xe8, 0x4c, 0x68, 0xf9, - 0x69, 0xfa, 0x70, 0x60, 0x6c, 0x7f, 0x32, 0x99, - 0xf1, 0xc3, 0x2d, 0xb4, 0x59, 0x58, 0x87, 0xaf, - 0x67, 0x62, 0x90, 0xe7, 0x8d, 0xd0, 0xa3, 0x77, - 0x33, 0xc2, 0x9b, 0xd5, 0x9c, 0xc7, 0xea, 0x25, - 0x98, 0x76, 0x9c, 0xe0, 0x6a, 0x03, 0x3a, 0x10, - 0xfd, 0x10, 0x3d, 0x55, 0x53, 0xa0, 0x14, 0x03, - 0x01, 0x00, 0x01, 0x01, 0x16, 0x03, 0x01, 0x00, - 0x24, 0xd5, 0x12, 0xfc, 0xb9, 0x5a, 0xe3, 0x27, - 0x01, 0xbe, 0xc3, 0x77, 0x17, 0x1a, 0xbb, 0x4f, - 0xae, 0xd5, 0xa7, 0xee, 0x56, 0x61, 0x0d, 0x40, - 0xf4, 0xa4, 0xb5, 0xcc, 0x76, 0xfd, 0xbd, 0x13, - 0x04, 0xe1, 0xb8, 0xc7, 0x36, - }, - { - 0x16, 0x03, 0x01, 0x02, 0x67, 0x04, 0x00, 0x02, - 0x63, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5d, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, - 0xe8, 0x4b, 0xd1, 0xef, 0xba, 0x1f, 0xe2, 0x69, - 0x07, 0x7f, 0x85, 0x2d, 0x4e, 0x2a, 0x2e, 0xbd, - 0x05, 0xe9, 0xc1, 0x6c, 0x9e, 0xbf, 0x47, 0x18, - 0x91, 0x77, 0xf7, 0xe8, 0xb6, 0x27, 0x37, 0xa6, - 0x6b, 0x87, 0x29, 0xbb, 0x3b, 0xe5, 0x68, 0x62, - 0x04, 0x3e, 0xad, 0x4d, 0xff, 0xad, 0xf1, 0x22, - 0x87, 0x8d, 0xf6, 0x04, 0x3b, 0x59, 0x22, 0xf7, - 0xfd, 0x88, 0x0e, 0xa4, 0x09, 0xc0, 0x0d, 0x10, - 0x80, 0x10, 0x79, 0xee, 0x70, 0x96, 0xdb, 0x22, - 0x8b, 0xb7, 0xac, 0xe0, 0x98, 0xad, 0xe9, 0xe3, - 0xcb, 0xea, 0x9f, 0xe6, 0x83, 0x28, 0x7c, 0x7e, - 0x4e, 0x9a, 0x8d, 0xd9, 0xf3, 0x86, 0xf4, 0x89, - 0x8b, 0x79, 0x8f, 0xbb, 0xe9, 0x74, 0x02, 0x02, - 0x14, 0x04, 0xea, 0xba, 0x16, 0x10, 0xa1, 0x85, - 0xbe, 0x4e, 0x4e, 0x92, 0xc5, 0x83, 0xf6, 0x1e, - 0x1f, 0xd4, 0x25, 0xc2, 0xc2, 0xb9, 0xce, 0x33, - 0x63, 0x66, 0x79, 0x1f, 0x54, 0x35, 0xc1, 0xe8, - 0x89, 0x34, 0x78, 0x94, 0x36, 0x14, 0xef, 0x01, - 0x1f, 0xf1, 0xbd, 0x77, 0x2c, 0x4d, 0xac, 0x5c, - 0x5c, 0x4a, 0xc6, 0xed, 0xd8, 0x0e, 0x72, 0x84, - 0x83, 0xdc, 0x56, 0x84, 0xc8, 0xf3, 0x89, 0x56, - 0xfd, 0x89, 0xc1, 0xc9, 0x9a, 0x29, 0x91, 0x7e, - 0x19, 0xe9, 0x8b, 0x5b, 0x11, 0x15, 0x4e, 0x6c, - 0xf4, 0x89, 0xe7, 0x6d, 0x68, 0x1e, 0xf9, 0x6c, - 0x23, 0x72, 0x05, 0x68, 0x82, 0x60, 0x84, 0x1f, - 0x83, 0x20, 0x09, 0x86, 0x10, 0x81, 0xec, 0xec, - 0xdc, 0x25, 0x53, 0x20, 0xfa, 0xa9, 0x41, 0x64, - 0xd6, 0x20, 0xf3, 0xf4, 0x52, 0xf2, 0x80, 0x62, - 0x83, 0xc9, 0x23, 0x66, 0x44, 0x95, 0x5a, 0x99, - 0x8a, 0xe1, 0x26, 0x63, 0xc1, 0x8b, 0x31, 0xf9, - 0x21, 0x06, 0x77, 0x04, 0x27, 0xf2, 0x0c, 0x63, - 0x83, 0x45, 0xa0, 0xa9, 0x7b, 0xcf, 0xdf, 0xd7, - 0x56, 0x75, 0xbc, 0xdd, 0x95, 0x36, 0xb1, 0x75, - 0x39, 0x05, 0x00, 0x3c, 0x8a, 0x79, 0xd6, 0xe9, - 0xf0, 0x4b, 0xdc, 0x51, 0x6b, 0x01, 0x94, 0x16, - 0x87, 0x12, 0x92, 0x6c, 0x07, 0xc1, 0xf5, 0x58, - 0xb7, 0x2a, 0x81, 0xf5, 0xa0, 0x37, 0x8b, 0xa6, - 0x22, 0xfe, 0x28, 0x0a, 0x7e, 0x68, 0xe2, 0xda, - 0x6c, 0x53, 0xee, 0x0e, 0x8d, 0x2d, 0x8b, 0x0b, - 0xda, 0xf8, 0x99, 0x3e, 0x0e, 0xed, 0x9f, 0xc1, - 0x2b, 0xf6, 0xfe, 0xe9, 0x52, 0x38, 0x7b, 0x83, - 0x9a, 0x50, 0xa6, 0xd7, 0x49, 0x83, 0x43, 0x7e, - 0x82, 0xec, 0xc7, 0x09, 0x3d, 0x3d, 0xb1, 0xee, - 0xe8, 0xc5, 0x6a, 0xc3, 0x3d, 0x4b, 0x4c, 0x6a, - 0xbb, 0x0b, 0x2c, 0x24, 0x2e, 0xdb, 0x7d, 0x57, - 0x87, 0xb4, 0x80, 0xa5, 0xae, 0xff, 0x54, 0xa8, - 0xa5, 0x27, 0x69, 0x95, 0xc8, 0xe7, 0x79, 0xc7, - 0x89, 0x2a, 0x73, 0x49, 0xcb, 0xf5, 0xc5, 0xbc, - 0x4a, 0xe0, 0x73, 0xa9, 0xbc, 0x88, 0x64, 0x96, - 0x98, 0xa5, 0x1e, 0xe3, 0x43, 0xc1, 0x7d, 0x78, - 0xc7, 0x94, 0x72, 0xd4, 0x2c, 0x6e, 0x85, 0x39, - 0x9a, 0xaf, 0xdb, 0xa1, 0xe9, 0xe2, 0xcb, 0x37, - 0x04, 0xc6, 0x8c, 0x81, 0xd3, 0x2a, 0xb7, 0xbe, - 0x6c, 0x07, 0x1f, 0x5e, 0xd9, 0x00, 0xd2, 0xf7, - 0xe1, 0xa7, 0xbc, 0x0c, 0xb6, 0x6d, 0xfb, 0x3f, - 0x3d, 0x24, 0xaa, 0xfb, 0x7e, 0xe1, 0xb5, 0x1b, - 0xff, 0x38, 0xaa, 0x69, 0x59, 0x38, 0x52, 0x9a, - 0x0e, 0x6d, 0xbc, 0xde, 0x4f, 0x13, 0x09, 0x17, - 0xc4, 0xa9, 0x05, 0x84, 0xbc, 0x50, 0xef, 0x40, - 0xb0, 0x4c, 0x24, 0x32, 0xed, 0x94, 0x2c, 0xdd, - 0xda, 0x20, 0x24, 0x67, 0xe2, 0xea, 0x71, 0x3d, - 0x4a, 0x04, 0x0d, 0x98, 0x29, 0x20, 0x4c, 0xeb, - 0x70, 0xce, 0x45, 0x9e, 0x5a, 0xaf, 0xb6, 0xa3, - 0x92, 0xc8, 0x28, 0xf2, 0xe3, 0xe8, 0x8a, 0x5d, - 0x0a, 0x33, 0x79, 0x9b, 0x6a, 0xf3, 0x30, 0x01, - 0x1d, 0x47, 0xbd, 0x01, 0xcc, 0x4d, 0x71, 0xc0, - 0x56, 0xfa, 0xfd, 0x37, 0xed, 0x0f, 0x27, 0xc0, - 0xbb, 0xa0, 0xee, 0xc3, 0x79, 0x8b, 0xe7, 0x41, - 0x8f, 0xfa, 0x3a, 0xcb, 0x45, 0x3b, 0x85, 0x9f, - 0x06, 0x90, 0xb2, 0x51, 0x7a, 0xc3, 0x11, 0x41, - 0x4b, 0xe3, 0x26, 0x94, 0x3e, 0xa2, 0xfd, 0x0a, - 0xda, 0x50, 0xf6, 0x50, 0x78, 0x19, 0x6c, 0x52, - 0xd1, 0x12, 0x76, 0xc2, 0x50, 0x2f, 0x0b, 0xca, - 0x33, 0xe5, 0x79, 0x93, 0x14, 0x03, 0x01, 0x00, - 0x01, 0x01, 0x16, 0x03, 0x01, 0x00, 0x24, 0x2b, - 0x51, 0x42, 0x95, 0x6b, 0xca, 0x9f, 0x42, 0x5d, - 0xd2, 0xd9, 0x67, 0xf9, 0x49, 0x30, 0xfd, 0x2a, - 0x46, 0xd3, 0x04, 0xf4, 0x86, 0xf9, 0x11, 0x34, - 0x82, 0xac, 0xe2, 0xc2, 0x2d, 0xc4, 0xd0, 0xfe, - 0xa9, 0xc9, 0x4b, 0x17, 0x03, 0x01, 0x00, 0x21, - 0x65, 0x1c, 0xe9, 0x5c, 0xb6, 0xe2, 0x7c, 0x8e, - 0x49, 0x12, 0x1b, 0xe6, 0x40, 0xd3, 0x97, 0x21, - 0x76, 0x01, 0xe5, 0x80, 0x5e, 0xf3, 0x11, 0x47, - 0x25, 0x02, 0x78, 0x8e, 0x6b, 0xae, 0xb3, 0xf3, - 0x59, 0x15, 0x03, 0x01, 0x00, 0x16, 0x38, 0xc1, - 0x99, 0x2e, 0xf8, 0x6f, 0x45, 0xa4, 0x10, 0x79, - 0x5b, 0xc1, 0x47, 0x9a, 0xf6, 0x5c, 0x90, 0xeb, - 0xa6, 0xe3, 0x1a, 0x24, - }, - }}, -} + test = &serverTest{ + name: "ResumeDisabled", + command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_in", sessionFilePath}, + config: &config, + } + runServerTestTLS12(t, test) -var tls11ECDHEAESServerScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x01, 0x46, 0x01, 0x00, 0x01, - 0x42, 0x03, 0x03, 0x51, 0x9f, 0xa3, 0xb0, 0xb7, - 0x1d, 0x26, 0x93, 0x36, 0xc0, 0x8d, 0x7e, 0xf8, - 0x4f, 0x6f, 0xc9, 0x3c, 0x31, 0x1e, 0x7f, 0xb1, - 0xf0, 0xc1, 0x0f, 0xf9, 0x0c, 0xa2, 0xd5, 0xca, - 0x48, 0xe5, 0x35, 0x00, 0x00, 0xd0, 0xc0, 0x30, - 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, - 0xc0, 0x0a, 0xc0, 0x22, 0xc0, 0x21, 0x00, 0xa5, - 0x00, 0xa3, 0x00, 0xa1, 0x00, 0x9f, 0x00, 0x6b, - 0x00, 0x6a, 0x00, 0x69, 0x00, 0x68, 0x00, 0x39, - 0x00, 0x38, 0x00, 0x37, 0x00, 0x36, 0x00, 0x88, - 0x00, 0x87, 0x00, 0x86, 0x00, 0x85, 0xc0, 0x32, - 0xc0, 0x2e, 0xc0, 0x2a, 0xc0, 0x26, 0xc0, 0x0f, - 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, - 0x00, 0x84, 0xc0, 0x12, 0xc0, 0x08, 0xc0, 0x1c, - 0xc0, 0x1b, 0x00, 0x16, 0x00, 0x13, 0x00, 0x10, - 0x00, 0x0d, 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, - 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, - 0xc0, 0x13, 0xc0, 0x09, 0xc0, 0x1f, 0xc0, 0x1e, - 0x00, 0xa4, 0x00, 0xa2, 0x00, 0xa0, 0x00, 0x9e, - 0x00, 0x67, 0x00, 0x40, 0x00, 0x3f, 0x00, 0x3e, - 0x00, 0x33, 0x00, 0x32, 0x00, 0x31, 0x00, 0x30, - 0x00, 0x9a, 0x00, 0x99, 0x00, 0x98, 0x00, 0x97, - 0x00, 0x45, 0x00, 0x44, 0x00, 0x43, 0x00, 0x42, - 0xc0, 0x31, 0xc0, 0x2d, 0xc0, 0x29, 0xc0, 0x25, - 0xc0, 0x0e, 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, - 0x00, 0x2f, 0x00, 0x96, 0x00, 0x41, 0x00, 0x07, - 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c, 0xc0, 0x02, - 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12, - 0x00, 0x0f, 0x00, 0x0c, 0x00, 0x09, 0x00, 0x14, - 0x00, 0x11, 0x00, 0x0e, 0x00, 0x0b, 0x00, 0x08, - 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x01, 0x00, - 0x00, 0x49, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, - 0x01, 0x02, 0x00, 0x0a, 0x00, 0x34, 0x00, 0x32, - 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x0b, - 0x00, 0x0c, 0x00, 0x18, 0x00, 0x09, 0x00, 0x0a, - 0x00, 0x16, 0x00, 0x17, 0x00, 0x08, 0x00, 0x06, - 0x00, 0x07, 0x00, 0x14, 0x00, 0x15, 0x00, 0x04, - 0x00, 0x05, 0x00, 0x12, 0x00, 0x13, 0x00, 0x01, - 0x00, 0x02, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10, - 0x00, 0x11, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0f, - 0x00, 0x01, 0x01, - }, - { - 0x16, 0x03, 0x02, 0x00, 0x30, 0x02, 0x00, 0x00, - 0x2c, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x13, 0x00, 0x00, - 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x02, - 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02, - 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0, - 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4, - 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, - 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, - 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, - 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, - 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, - 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, - 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30, - 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33, - 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, - 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, - 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, - 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, - 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, - 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79, - 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10, - 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43, - 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85, - 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c, - 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5, - 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c, - 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56, - 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26, - 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21, - 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf, - 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07, - 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39, - 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3, - 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf, - 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb, - 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, - 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85, - 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23, - 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39, - 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2, - 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, - 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, - 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85, - 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, - 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59, - 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7, - 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95, - 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66, - 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3, - 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13, - 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba, - 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31, - 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50, - 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f, - 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96, - 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f, - 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b, - 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70, - 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e, - 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9, - 0x16, 0x03, 0x02, 0x01, 0x0f, 0x0c, 0x00, 0x01, - 0x0b, 0x03, 0x00, 0x19, 0x85, 0x04, 0x01, 0x39, - 0xdc, 0xee, 0x44, 0x17, 0x5e, 0xdb, 0xd7, 0x27, - 0xaf, 0xb6, 0x56, 0xd9, 0xb4, 0x43, 0x5a, 0x99, - 0xcf, 0xaa, 0x31, 0x37, 0x0c, 0x6f, 0x3a, 0xa0, - 0xf8, 0x53, 0xc4, 0x74, 0xd1, 0x91, 0x0a, 0x46, - 0xf5, 0x38, 0x3b, 0x5c, 0x09, 0xd8, 0x97, 0xdc, - 0x4b, 0xaa, 0x70, 0x26, 0x48, 0xf2, 0xd6, 0x0b, - 0x31, 0xc9, 0xf8, 0xd4, 0x98, 0x43, 0xe1, 0x6c, - 0xd5, 0xc7, 0xb2, 0x8e, 0x0b, 0x01, 0xe6, 0xb6, - 0x00, 0x28, 0x80, 0x7b, 0xfc, 0x96, 0x8f, 0x0d, - 0xa2, 0x4f, 0xb0, 0x79, 0xaf, 0xdc, 0x61, 0x28, - 0x63, 0x33, 0x78, 0xf6, 0x31, 0x39, 0xfd, 0x8a, - 0xf4, 0x15, 0x18, 0x11, 0xfe, 0xdb, 0xd5, 0x07, - 0xda, 0x2c, 0xed, 0x49, 0xa0, 0x23, 0xbf, 0xd0, - 0x3a, 0x38, 0x1d, 0x54, 0xae, 0x1c, 0x7b, 0xea, - 0x29, 0xee, 0xd0, 0x38, 0xc1, 0x76, 0xa7, 0x7f, - 0x2a, 0xf4, 0xce, 0x1e, 0xac, 0xcc, 0x94, 0x79, - 0x90, 0x33, 0x00, 0x80, 0x16, 0x83, 0x9b, 0xf9, - 0x72, 0xdb, 0x9f, 0x55, 0x02, 0xe1, 0x04, 0xf7, - 0xb5, 0x3f, 0x4c, 0x71, 0x13, 0x5a, 0x91, 0xe9, - 0x1d, 0xeb, 0x9d, 0x9c, 0xfb, 0x88, 0xef, 0xca, - 0xec, 0x7d, 0x9b, 0xdd, 0xd9, 0xee, 0x2b, 0x8e, - 0xef, 0xf8, 0xb6, 0xc7, 0x7d, 0xfe, 0xda, 0x7f, - 0x90, 0x2e, 0x53, 0xf1, 0x64, 0x95, 0xfc, 0x66, - 0xfc, 0x87, 0x27, 0xb6, 0x9f, 0xc8, 0x3a, 0x95, - 0x68, 0x17, 0xe1, 0x7d, 0xf1, 0x88, 0xe8, 0x17, - 0x5f, 0x99, 0x90, 0x3f, 0x47, 0x47, 0x81, 0x06, - 0xe2, 0x8e, 0x22, 0x56, 0x8f, 0xc2, 0x14, 0xe5, - 0x62, 0xa7, 0x0d, 0x41, 0x3c, 0xc7, 0x4a, 0x0a, - 0x74, 0x4b, 0xda, 0x00, 0x8e, 0x4f, 0x90, 0xe6, - 0xd7, 0x68, 0xe5, 0x8b, 0xf2, 0x3f, 0x53, 0x1d, - 0x7a, 0xe6, 0xb3, 0xe9, 0x8a, 0xc9, 0x4d, 0x19, - 0xa6, 0xcf, 0xf9, 0xed, 0x5e, 0x26, 0xdc, 0x90, - 0x1c, 0x41, 0xad, 0x7c, 0x16, 0x03, 0x02, 0x00, - 0x04, 0x0e, 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x02, 0x00, 0x8a, 0x10, 0x00, 0x00, - 0x86, 0x85, 0x04, 0x01, 0x11, 0xf2, 0xa4, 0x2d, - 0x1a, 0x75, 0x6c, 0xbc, 0x2d, 0x91, 0x95, 0x07, - 0xbe, 0xd6, 0x41, 0x7a, 0xbb, 0xc2, 0x7b, 0xa6, - 0x9b, 0xe3, 0xdc, 0x41, 0x7f, 0x1e, 0x2e, 0xcc, - 0x6d, 0xa3, 0x85, 0x53, 0x98, 0x9f, 0x2d, 0xe6, - 0x3c, 0xb9, 0x82, 0xa6, 0x80, 0x53, 0x9b, 0x71, - 0xfd, 0x27, 0xe5, 0xe5, 0xdf, 0x13, 0xba, 0x56, - 0x62, 0x30, 0x4a, 0x57, 0x27, 0xa7, 0xcc, 0x26, - 0x54, 0xe8, 0x65, 0x6e, 0x4d, 0x00, 0xbf, 0x8a, - 0xcc, 0x89, 0x6a, 0x6c, 0x88, 0xda, 0x79, 0x4f, - 0xc5, 0xad, 0x6d, 0x1d, 0x7c, 0x53, 0x7b, 0x1a, - 0x96, 0xf2, 0xf8, 0x30, 0x01, 0x0b, 0xc2, 0xf0, - 0x78, 0x41, 0xf4, 0x0d, 0xe0, 0xbe, 0xb9, 0x36, - 0xe0, 0xb7, 0xee, 0x16, 0xeb, 0x25, 0x67, 0x04, - 0xc0, 0x2e, 0xd8, 0x34, 0x4a, 0x65, 0xa5, 0xf1, - 0x95, 0x75, 0xc7, 0x39, 0xa9, 0x68, 0xa9, 0x53, - 0x93, 0x5b, 0xca, 0x7b, 0x7f, 0xc0, 0x63, 0x14, - 0x03, 0x02, 0x00, 0x01, 0x01, 0x16, 0x03, 0x02, - 0x00, 0x40, 0x01, 0xb1, 0xae, 0x1b, 0x8a, 0x65, - 0xf8, 0x37, 0x50, 0x39, 0x76, 0xef, 0xaa, 0xda, - 0x84, 0xc9, 0x5f, 0x80, 0xdc, 0xfa, 0xe0, 0x46, - 0x5a, 0xc7, 0x77, 0x9d, 0x76, 0x03, 0xa6, 0xd5, - 0x0e, 0xbf, 0x25, 0x30, 0x5c, 0x99, 0x7d, 0xcd, - 0x2b, 0xaa, 0x2e, 0x8c, 0xdd, 0xda, 0xaa, 0xd7, - 0xf1, 0xf6, 0x33, 0x47, 0x51, 0x1e, 0x83, 0xa1, - 0x83, 0x04, 0xd2, 0xb2, 0xc8, 0xbc, 0x11, 0xc5, - 0x1a, 0x87, - }, - { - 0x16, 0x03, 0x02, 0x00, 0x72, 0x04, 0x00, 0x00, - 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, - 0xeb, 0x8b, 0xc7, 0xef, 0xba, 0xe8, 0x0f, 0x69, - 0xfe, 0xfb, 0xc3, 0x3d, 0x90, 0x5d, 0xd7, 0xb2, - 0x51, 0x64, 0xac, 0xc3, 0xae, 0x33, 0x03, 0x42, - 0x45, 0x2d, 0xa7, 0x57, 0xbd, 0xa3, 0x85, 0x64, - 0xa6, 0xfe, 0x5c, 0x33, 0x04, 0x93, 0xf2, 0x7c, - 0x06, 0x6d, 0xd7, 0xd7, 0xcf, 0x4a, 0xaf, 0xb2, - 0xdd, 0x06, 0xdc, 0x28, 0x14, 0x59, 0x23, 0x02, - 0xef, 0x97, 0x6a, 0xe8, 0xec, 0xca, 0x10, 0x44, - 0xcd, 0xb8, 0x50, 0x16, 0x46, 0x5a, 0x05, 0xda, - 0x04, 0xb3, 0x0e, 0xe9, 0xf0, 0x74, 0xc5, 0x23, - 0xc2, 0x0e, 0xa1, 0x54, 0x66, 0x7b, 0xe8, 0x14, - 0x03, 0x02, 0x00, 0x01, 0x01, 0x16, 0x03, 0x02, - 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x6b, 0x43, 0x1c, 0x58, 0xbc, 0x85, - 0xf7, 0xc1, 0x76, 0xbc, 0x72, 0x33, 0x41, 0x6b, - 0xb8, 0xf8, 0xfd, 0x53, 0x21, 0xc2, 0x41, 0x1b, - 0x72, 0x4f, 0xce, 0x97, 0xca, 0x14, 0x23, 0x4d, - 0xbc, 0x44, 0xd6, 0xd7, 0xfc, 0xbc, 0xfd, 0xfd, - 0x5d, 0x33, 0x42, 0x1b, 0x52, 0x40, 0x0a, 0x2b, - 0x6c, 0x98, 0x17, 0x03, 0x02, 0x00, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, - 0x31, 0xef, 0x03, 0x7d, 0xa5, 0x74, 0x92, 0x24, - 0x34, 0xae, 0x4e, 0xc9, 0xfc, 0x59, 0xcb, 0x64, - 0xf4, 0x45, 0xb1, 0xac, 0x02, 0xf2, 0x87, 0xe7, - 0x2f, 0xfd, 0x01, 0xca, 0x78, 0x02, 0x2e, 0x3a, - 0x38, 0xcd, 0xb1, 0xe0, 0xf2, 0x2e, 0xf6, 0x27, - 0xa0, 0xac, 0x1f, 0x91, 0x43, 0xc2, 0x3d, 0x15, - 0x03, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x9f, 0x30, 0x24, 0x56, - 0x2c, 0xde, 0xa0, 0xe6, 0x44, 0x35, 0x30, 0x51, - 0xec, 0xd4, 0x69, 0x2d, 0x46, 0x64, 0x04, 0x21, - 0xfe, 0x7c, 0x4d, 0xc5, 0xd0, 0x8c, 0xf9, 0xd2, - 0x3f, 0x88, 0x69, 0xd5, - }, + // One needs to manually confirm that the handshake in the golden data + // file for ResumeDisabled does not include a resumption handshake. } -// $ go test -run TestRunServer -serve -clientauth 1 \ -// -ciphersuites=0xc011 -minversion=0x0303 -maxversion=0x0303 -var tls12ServerScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x01, 0x1e, 0x01, 0x00, 0x01, - 0x1a, 0x03, 0x03, 0x51, 0xe5, 0x76, 0x84, 0x0e, - 0xb9, 0x17, 0xca, 0x08, 0x47, 0xd9, 0xbd, 0xd0, - 0x94, 0xd1, 0x97, 0xca, 0x5b, 0xe7, 0x20, 0xac, - 0x8e, 0xbb, 0xc7, 0x29, 0xe9, 0x26, 0xcf, 0x7d, - 0xb3, 0xdc, 0x99, 0x00, 0x00, 0x82, 0xc0, 0x30, - 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, - 0xc0, 0x0a, 0x00, 0xa3, 0x00, 0x9f, 0x00, 0x6b, - 0x00, 0x6a, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x32, - 0xc0, 0x2e, 0xc0, 0x2a, 0xc0, 0x26, 0xc0, 0x0f, - 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, - 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x13, - 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, 0xc0, 0x2f, - 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13, - 0xc0, 0x09, 0x00, 0xa2, 0x00, 0x9e, 0x00, 0x67, - 0x00, 0x40, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x31, - 0xc0, 0x2d, 0xc0, 0x29, 0xc0, 0x25, 0xc0, 0x0e, - 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, - 0x00, 0x07, 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c, - 0xc0, 0x02, 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, - 0x00, 0x12, 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, - 0x00, 0x08, 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, - 0x01, 0x00, 0x00, 0x6f, 0x00, 0x0b, 0x00, 0x04, - 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a, 0x00, 0x34, - 0x00, 0x32, 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x19, - 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x18, 0x00, 0x09, - 0x00, 0x0a, 0x00, 0x16, 0x00, 0x17, 0x00, 0x08, - 0x00, 0x06, 0x00, 0x07, 0x00, 0x14, 0x00, 0x15, - 0x00, 0x04, 0x00, 0x05, 0x00, 0x12, 0x00, 0x13, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x0f, - 0x00, 0x10, 0x00, 0x11, 0x00, 0x23, 0x00, 0x00, - 0x00, 0x0d, 0x00, 0x22, 0x00, 0x20, 0x06, 0x01, - 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, 0x05, 0x02, - 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, - 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x00, 0x0f, - 0x00, 0x01, 0x01, - }, - { - 0x16, 0x03, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00, - 0x2c, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x11, 0x00, 0x00, - 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x03, - 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02, - 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0, - 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4, - 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, - 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, - 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, - 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, - 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, - 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, - 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30, - 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33, - 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, - 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, - 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, - 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, - 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, - 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79, - 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10, - 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43, - 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85, - 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c, - 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5, - 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c, - 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56, - 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26, - 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21, - 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf, - 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07, - 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39, - 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3, - 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf, - 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb, - 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, - 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85, - 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23, - 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39, - 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2, - 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, - 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, - 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85, - 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, - 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59, - 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7, - 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95, - 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66, - 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3, - 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13, - 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba, - 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31, - 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50, - 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f, - 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96, - 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f, - 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b, - 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70, - 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e, - 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9, - 0x16, 0x03, 0x03, 0x01, 0x11, 0x0c, 0x00, 0x01, - 0x0d, 0x03, 0x00, 0x19, 0x85, 0x04, 0x01, 0x39, - 0xdc, 0xee, 0x44, 0x17, 0x5e, 0xdb, 0xd7, 0x27, - 0xaf, 0xb6, 0x56, 0xd9, 0xb4, 0x43, 0x5a, 0x99, - 0xcf, 0xaa, 0x31, 0x37, 0x0c, 0x6f, 0x3a, 0xa0, - 0xf8, 0x53, 0xc4, 0x74, 0xd1, 0x91, 0x0a, 0x46, - 0xf5, 0x38, 0x3b, 0x5c, 0x09, 0xd8, 0x97, 0xdc, - 0x4b, 0xaa, 0x70, 0x26, 0x48, 0xf2, 0xd6, 0x0b, - 0x31, 0xc9, 0xf8, 0xd4, 0x98, 0x43, 0xe1, 0x6c, - 0xd5, 0xc7, 0xb2, 0x8e, 0x0b, 0x01, 0xe6, 0xb6, - 0x00, 0x28, 0x80, 0x7b, 0xfc, 0x96, 0x8f, 0x0d, - 0xa2, 0x4f, 0xb0, 0x79, 0xaf, 0xdc, 0x61, 0x28, - 0x63, 0x33, 0x78, 0xf6, 0x31, 0x39, 0xfd, 0x8a, - 0xf4, 0x15, 0x18, 0x11, 0xfe, 0xdb, 0xd5, 0x07, - 0xda, 0x2c, 0xed, 0x49, 0xa0, 0x23, 0xbf, 0xd0, - 0x3a, 0x38, 0x1d, 0x54, 0xae, 0x1c, 0x7b, 0xea, - 0x29, 0xee, 0xd0, 0x38, 0xc1, 0x76, 0xa7, 0x7f, - 0x2a, 0xf4, 0xce, 0x1e, 0xac, 0xcc, 0x94, 0x79, - 0x90, 0x33, 0x04, 0x01, 0x00, 0x80, 0x4a, 0xf9, - 0xf5, 0x0a, 0x61, 0x37, 0x7e, 0x4e, 0x92, 0xb5, - 0x1c, 0x91, 0x21, 0xb2, 0xb5, 0x17, 0x00, 0xbf, - 0x01, 0x5f, 0x30, 0xec, 0x62, 0x08, 0xd6, 0x9d, - 0x1a, 0x08, 0x05, 0x72, 0x8b, 0xf4, 0x49, 0x85, - 0xa7, 0xbf, 0x3f, 0x75, 0x58, 0x3e, 0x26, 0x82, - 0xc3, 0x28, 0x07, 0xf9, 0x41, 0x7d, 0x03, 0x14, - 0x3b, 0xc3, 0x05, 0x64, 0xff, 0x52, 0xf4, 0x75, - 0x6a, 0x87, 0xcd, 0xdf, 0x93, 0x31, 0x0a, 0x71, - 0x60, 0x17, 0xc6, 0x33, 0xf0, 0x79, 0xb6, 0x7b, - 0xd0, 0x9c, 0xa0, 0x5f, 0x74, 0x14, 0x2c, 0x5a, - 0xb4, 0x3f, 0x39, 0xf5, 0xe4, 0x9f, 0xbe, 0x6d, - 0x21, 0xd2, 0xa9, 0x42, 0xf7, 0xdc, 0xa6, 0x65, - 0xb7, 0x6a, 0x7e, 0x2e, 0x14, 0xd3, 0xf6, 0xf3, - 0x4b, 0x4c, 0x5b, 0x1a, 0x70, 0x7a, 0xbc, 0xb0, - 0x12, 0xf3, 0x6e, 0x0c, 0xcf, 0x43, 0x22, 0xae, - 0x5b, 0xba, 0x00, 0xf8, 0xfd, 0xaf, 0x16, 0x03, - 0x03, 0x00, 0x0f, 0x0d, 0x00, 0x00, 0x0b, 0x02, - 0x01, 0x40, 0x00, 0x04, 0x04, 0x01, 0x04, 0x03, - 0x00, 0x00, 0x16, 0x03, 0x03, 0x00, 0x04, 0x0e, - 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x03, 0x01, 0xfb, 0x0b, 0x00, 0x01, - 0xf7, 0x00, 0x01, 0xf4, 0x00, 0x01, 0xf1, 0x30, - 0x82, 0x01, 0xed, 0x30, 0x82, 0x01, 0x58, 0xa0, - 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, - 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05, 0x30, 0x26, 0x31, 0x10, - 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f, - 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, - 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x31, 0x31, 0x32, 0x30, 0x38, 0x30, 0x37, - 0x35, 0x35, 0x31, 0x32, 0x5a, 0x17, 0x0d, 0x31, - 0x32, 0x31, 0x32, 0x30, 0x37, 0x30, 0x38, 0x30, - 0x30, 0x31, 0x32, 0x5a, 0x30, 0x26, 0x31, 0x10, - 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x07, 0x41, 0x63, 0x6d, 0x65, 0x20, 0x43, 0x6f, - 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x13, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, - 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81, 0x9c, 0x30, - 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x03, 0x81, 0x8c, 0x00, - 0x30, 0x81, 0x88, 0x02, 0x81, 0x80, 0x4e, 0xd0, - 0x7b, 0x31, 0xe3, 0x82, 0x64, 0xd9, 0x59, 0xc0, - 0xc2, 0x87, 0xa4, 0x5e, 0x1e, 0x8b, 0x73, 0x33, - 0xc7, 0x63, 0x53, 0xdf, 0x66, 0x92, 0x06, 0x84, - 0xf6, 0x64, 0xd5, 0x8f, 0xe4, 0x36, 0xa7, 0x1d, - 0x2b, 0xe8, 0xb3, 0x20, 0x36, 0x45, 0x23, 0xb5, - 0xe3, 0x95, 0xae, 0xed, 0xe0, 0xf5, 0x20, 0x9c, - 0x8d, 0x95, 0xdf, 0x7f, 0x5a, 0x12, 0xef, 0x87, - 0xe4, 0x5b, 0x68, 0xe4, 0xe9, 0x0e, 0x74, 0xec, - 0x04, 0x8a, 0x7f, 0xde, 0x93, 0x27, 0xc4, 0x01, - 0x19, 0x7a, 0xbd, 0xf2, 0xdc, 0x3d, 0x14, 0xab, - 0xd0, 0x54, 0xca, 0x21, 0x0c, 0xd0, 0x4d, 0x6e, - 0x87, 0x2e, 0x5c, 0xc5, 0xd2, 0xbb, 0x4d, 0x4b, - 0x4f, 0xce, 0xb6, 0x2c, 0xf7, 0x7e, 0x88, 0xec, - 0x7c, 0xd7, 0x02, 0x91, 0x74, 0xa6, 0x1e, 0x0c, - 0x1a, 0xda, 0xe3, 0x4a, 0x5a, 0x2e, 0xde, 0x13, - 0x9c, 0x4c, 0x40, 0x88, 0x59, 0x93, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x32, 0x30, 0x30, 0x30, - 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, - 0xff, 0x04, 0x04, 0x03, 0x02, 0x00, 0xa0, 0x30, - 0x0d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x06, - 0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30, 0x0f, - 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x08, 0x30, - 0x06, 0x80, 0x04, 0x01, 0x02, 0x03, 0x04, 0x30, - 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05, 0x03, 0x81, 0x81, 0x00, - 0x36, 0x1f, 0xb3, 0x7a, 0x0c, 0x75, 0xc9, 0x6e, - 0x37, 0x46, 0x61, 0x2b, 0xd5, 0xbd, 0xc0, 0xa7, - 0x4b, 0xcc, 0x46, 0x9a, 0x81, 0x58, 0x7c, 0x85, - 0x79, 0x29, 0xc8, 0xc8, 0xc6, 0x67, 0xdd, 0x32, - 0x56, 0x45, 0x2b, 0x75, 0xb6, 0xe9, 0x24, 0xa9, - 0x50, 0x9a, 0xbe, 0x1f, 0x5a, 0xfa, 0x1a, 0x15, - 0xd9, 0xcc, 0x55, 0x95, 0x72, 0x16, 0x83, 0xb9, - 0xc2, 0xb6, 0x8f, 0xfd, 0x88, 0x8c, 0x38, 0x84, - 0x1d, 0xab, 0x5d, 0x92, 0x31, 0x13, 0x4f, 0xfd, - 0x83, 0x3b, 0xc6, 0x9d, 0xf1, 0x11, 0x62, 0xb6, - 0x8b, 0xec, 0xab, 0x67, 0xbe, 0xc8, 0x64, 0xb0, - 0x11, 0x50, 0x46, 0x58, 0x17, 0x6b, 0x99, 0x1c, - 0xd3, 0x1d, 0xfc, 0x06, 0xf1, 0x0e, 0xe5, 0x96, - 0xa8, 0x0c, 0xf9, 0x78, 0x20, 0xb7, 0x44, 0x18, - 0x51, 0x8d, 0x10, 0x7e, 0x4f, 0x94, 0x67, 0xdf, - 0xa3, 0x4e, 0x70, 0x73, 0x8e, 0x90, 0x91, 0x85, - 0x16, 0x03, 0x03, 0x00, 0x8a, 0x10, 0x00, 0x00, - 0x86, 0x85, 0x04, 0x01, 0x5d, 0x3a, 0x92, 0x59, - 0x7f, 0x9a, 0x22, 0x36, 0x0e, 0x1b, 0x1d, 0x2a, - 0x05, 0xb7, 0xa4, 0xb6, 0x5d, 0xfc, 0x51, 0x6e, - 0x15, 0xe5, 0x89, 0x7c, 0xe2, 0xfa, 0x87, 0x38, - 0x05, 0x79, 0x15, 0x92, 0xb4, 0x8f, 0x88, 0x8f, - 0x9d, 0x5d, 0xa0, 0xaf, 0xf8, 0xce, 0xf9, 0x6f, - 0x83, 0xf4, 0x08, 0x69, 0xe4, 0x91, 0xc5, 0xed, - 0xb9, 0xc5, 0xa8, 0x1f, 0x4b, 0xec, 0xef, 0x91, - 0xc1, 0xa3, 0x34, 0x24, 0x18, 0x00, 0x2d, 0xcd, - 0xe6, 0x44, 0xef, 0x5a, 0x3e, 0x52, 0x63, 0x5b, - 0x36, 0x1f, 0x7e, 0xce, 0x9e, 0xaa, 0xda, 0x8d, - 0xb5, 0xc9, 0xea, 0xd8, 0x1b, 0xd1, 0x1c, 0x7c, - 0x07, 0xfc, 0x3c, 0x2d, 0x70, 0x1f, 0xf9, 0x4d, - 0xcb, 0xaa, 0xad, 0x07, 0xd5, 0x6d, 0xbd, 0xa6, - 0x61, 0xf3, 0x2f, 0xa3, 0x9c, 0x45, 0x02, 0x4a, - 0xac, 0x6c, 0xb6, 0x37, 0x95, 0xb1, 0x4a, 0xb5, - 0x0a, 0x4e, 0x60, 0x67, 0xd7, 0xe0, 0x04, 0x16, - 0x03, 0x03, 0x00, 0x88, 0x0f, 0x00, 0x00, 0x84, - 0x04, 0x01, 0x00, 0x80, 0x08, 0x83, 0x53, 0xf0, - 0xf8, 0x14, 0xf5, 0xc2, 0xd1, 0x8b, 0xf0, 0xa5, - 0xc1, 0xd8, 0x1a, 0x36, 0x4b, 0x75, 0x77, 0x02, - 0x19, 0xd8, 0x11, 0x3f, 0x5a, 0x36, 0xfc, 0xe9, - 0x2b, 0x4b, 0xf9, 0xfe, 0xda, 0x8a, 0x0f, 0x6e, - 0x3d, 0xd3, 0x52, 0x87, 0xf7, 0x9c, 0x78, 0x39, - 0xa8, 0xf1, 0xd7, 0xf7, 0x4e, 0x35, 0x33, 0xf9, - 0xc5, 0x76, 0xa8, 0x12, 0xc4, 0x91, 0x33, 0x1d, - 0x93, 0x8c, 0xbf, 0xb1, 0x83, 0x00, 0x90, 0xc5, - 0x52, 0x3e, 0xe0, 0x0a, 0xe8, 0x92, 0x75, 0xdf, - 0x54, 0x5f, 0x9f, 0x95, 0x76, 0x62, 0xb5, 0x85, - 0x69, 0xa4, 0x86, 0x85, 0x6c, 0xf3, 0x6b, 0x2a, - 0x72, 0x7b, 0x4d, 0x42, 0x33, 0x67, 0x4a, 0xce, - 0xb5, 0xdb, 0x9b, 0xae, 0xc0, 0xb0, 0x10, 0xeb, - 0x3b, 0xf4, 0xc2, 0x9a, 0x64, 0x47, 0x4c, 0x1e, - 0xa5, 0x91, 0x7f, 0x6d, 0xd1, 0x03, 0xf5, 0x4a, - 0x90, 0x69, 0x18, 0xb1, 0x14, 0x03, 0x03, 0x00, - 0x01, 0x01, 0x16, 0x03, 0x03, 0x00, 0x24, 0x59, - 0xfc, 0x7e, 0xae, 0xb3, 0xbf, 0xab, 0x4d, 0xdb, - 0x4e, 0xab, 0xa9, 0x6d, 0x6b, 0x4c, 0x60, 0xb6, - 0x16, 0xe0, 0xab, 0x7f, 0x52, 0x2d, 0xa1, 0xfc, - 0xe1, 0x80, 0xd2, 0x8a, 0xa1, 0xe5, 0x8f, 0xa1, - 0x70, 0x93, 0x23, - }, - { - 0x16, 0x03, 0x03, 0x02, 0x67, 0x04, 0x00, 0x02, - 0x63, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5d, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, - 0xea, 0x8b, 0xc5, 0xef, 0xba, 0x64, 0xb7, 0x23, - 0x08, 0x86, 0x4f, 0x37, 0xe0, 0x8f, 0xbd, 0x75, - 0x71, 0x2b, 0xcb, 0x20, 0x75, 0x11, 0x3b, 0xa2, - 0x9e, 0x39, 0x3c, 0x03, 0xef, 0x6e, 0x41, 0xd7, - 0xcf, 0x1a, 0x2c, 0xf2, 0xfe, 0xc2, 0xd3, 0x65, - 0x59, 0x00, 0x9d, 0x03, 0xb4, 0xf2, 0x20, 0xe4, - 0x33, 0x80, 0xcd, 0xf6, 0xe4, 0x59, 0x22, 0xf7, - 0xfd, 0x88, 0x0e, 0xa4, 0x09, 0xc0, 0x0d, 0x10, - 0x80, 0x10, 0x79, 0xee, 0x70, 0x96, 0xdb, 0x22, - 0x8b, 0xb7, 0xac, 0xe0, 0x98, 0xad, 0xe9, 0xe3, - 0xcb, 0xea, 0x9f, 0xe6, 0x83, 0x28, 0x7c, 0x7e, - 0x4e, 0x9a, 0x8d, 0xd9, 0xf3, 0x86, 0xf4, 0x89, - 0x8b, 0x79, 0x8f, 0xbb, 0xe9, 0x74, 0x02, 0x02, - 0x14, 0x04, 0xea, 0xba, 0x16, 0x10, 0xa1, 0x85, - 0xbe, 0x4e, 0x4e, 0x92, 0xc5, 0x83, 0xf6, 0x1e, - 0x1f, 0xd4, 0x25, 0xc2, 0xc2, 0xb9, 0xce, 0x33, - 0x63, 0x66, 0x79, 0x1f, 0x54, 0x35, 0xc1, 0xe8, - 0x89, 0x34, 0x78, 0x94, 0x36, 0x14, 0xef, 0x01, - 0x1f, 0xf1, 0xbd, 0x77, 0x2c, 0x4d, 0xac, 0x5c, - 0x5c, 0x4a, 0xc6, 0xed, 0xd8, 0x0e, 0x72, 0x84, - 0x83, 0xdc, 0x56, 0x84, 0xc8, 0xf3, 0x89, 0x56, - 0xfd, 0x89, 0xc1, 0xc9, 0x9a, 0x29, 0x91, 0x7e, - 0x19, 0xe9, 0x8b, 0x5b, 0x11, 0x15, 0x4e, 0x6c, - 0xf4, 0x89, 0xe7, 0x6d, 0x68, 0x1e, 0xf9, 0x6c, - 0x23, 0x72, 0x05, 0x68, 0x82, 0x60, 0x84, 0x1f, - 0x83, 0x20, 0x09, 0x86, 0x10, 0x81, 0xec, 0xec, - 0xdc, 0x25, 0x53, 0x20, 0xfa, 0xa9, 0x41, 0x64, - 0xd6, 0x20, 0xf3, 0xf4, 0x52, 0xf2, 0x80, 0x62, - 0x83, 0xc9, 0x23, 0x66, 0x44, 0x95, 0x5a, 0x99, - 0x8a, 0xe1, 0x26, 0x63, 0xc1, 0x8b, 0x31, 0xf9, - 0x21, 0x06, 0x77, 0x04, 0x27, 0xf2, 0x0c, 0x63, - 0x83, 0x45, 0xa0, 0xa9, 0x7b, 0xcf, 0xdf, 0xd7, - 0x56, 0x75, 0xbc, 0xdd, 0x95, 0x36, 0xb1, 0x75, - 0x39, 0x05, 0x00, 0x3c, 0x8a, 0x79, 0xd6, 0xe9, - 0xf0, 0x4b, 0xdc, 0x51, 0x6b, 0x01, 0x94, 0x16, - 0x87, 0x12, 0x92, 0x6c, 0x07, 0xc1, 0xf5, 0x58, - 0xb7, 0x2a, 0x81, 0xf5, 0xa0, 0x37, 0x8b, 0xa6, - 0x22, 0xfe, 0x28, 0x0a, 0x7e, 0x68, 0xe2, 0xda, - 0x6c, 0x53, 0xee, 0x0e, 0x8d, 0x2d, 0x8b, 0x0b, - 0xda, 0xf8, 0x99, 0x3e, 0x0e, 0xed, 0x9f, 0xc1, - 0x2b, 0xf6, 0xfe, 0xe9, 0x52, 0x38, 0x7b, 0x83, - 0x9a, 0x50, 0xa6, 0xd7, 0x49, 0x83, 0x43, 0x7e, - 0x82, 0xec, 0xc7, 0x09, 0x3d, 0x3d, 0xb1, 0xee, - 0xe8, 0xc5, 0x6a, 0xc3, 0x3d, 0x4b, 0x4c, 0x6a, - 0xbb, 0x0b, 0x2c, 0x24, 0x2e, 0xdb, 0x7d, 0x57, - 0x87, 0xb4, 0x80, 0xa5, 0xae, 0xff, 0x54, 0xa8, - 0xa5, 0x27, 0x69, 0x95, 0xc8, 0xe7, 0x79, 0xc7, - 0x89, 0x2a, 0x73, 0x49, 0xcb, 0xf5, 0xc5, 0xbc, - 0x4a, 0xe0, 0x73, 0xa9, 0xbc, 0x88, 0x64, 0x96, - 0x98, 0xa5, 0x1e, 0xe3, 0x43, 0xc1, 0x7d, 0x78, - 0xc7, 0x94, 0x72, 0xd4, 0x2c, 0x6e, 0x85, 0x39, - 0x9a, 0xaf, 0xdb, 0xa1, 0xe9, 0xe2, 0xcb, 0x37, - 0x04, 0xc6, 0x8c, 0x81, 0xd3, 0x2a, 0xb7, 0xbe, - 0x6c, 0x07, 0x1f, 0x5e, 0xd9, 0x00, 0xd2, 0xf7, - 0xe1, 0xa7, 0xbc, 0x0c, 0xb6, 0x6d, 0xfb, 0x3f, - 0x3d, 0x24, 0xaa, 0xfb, 0x7e, 0xe1, 0xb5, 0x1b, - 0xff, 0x38, 0xaa, 0x69, 0x59, 0x38, 0x52, 0x9a, - 0x0e, 0x6d, 0xbc, 0xde, 0x4f, 0x13, 0x09, 0x17, - 0xc4, 0xa9, 0x05, 0x84, 0xbc, 0x50, 0xef, 0x40, - 0xb0, 0x4c, 0x24, 0x32, 0xed, 0x94, 0x2c, 0xdd, - 0xda, 0x20, 0x24, 0x67, 0xe2, 0xea, 0x71, 0x3d, - 0x4a, 0x04, 0x0d, 0x98, 0x29, 0x20, 0x4c, 0xeb, - 0x70, 0xce, 0x45, 0x9e, 0x5a, 0xaf, 0xb6, 0xa3, - 0x92, 0xc8, 0x28, 0xf2, 0xe3, 0xe8, 0x8a, 0x5d, - 0x0a, 0x33, 0x79, 0x9b, 0x6a, 0xf3, 0x30, 0x01, - 0x1d, 0x47, 0xbd, 0x01, 0xcc, 0x4d, 0x71, 0xc0, - 0x56, 0xfa, 0xfd, 0x37, 0xed, 0x0f, 0x27, 0xc0, - 0xbb, 0xa0, 0xee, 0xc3, 0x79, 0x8b, 0xe7, 0x41, - 0x8f, 0xfa, 0x3a, 0xcb, 0x45, 0x3b, 0x85, 0x9f, - 0x06, 0x90, 0xb2, 0x51, 0xc0, 0x48, 0x10, 0xac, - 0x2a, 0xec, 0xec, 0x48, 0x7a, 0x19, 0x47, 0xc4, - 0x2a, 0xeb, 0xb3, 0xa2, 0x07, 0x22, 0x32, 0x78, - 0xf4, 0x73, 0x5e, 0x92, 0x42, 0x15, 0xa1, 0x90, - 0x91, 0xd0, 0xeb, 0x12, 0x14, 0x03, 0x03, 0x00, - 0x01, 0x01, 0x16, 0x03, 0x03, 0x00, 0x24, 0x45, - 0x4b, 0x80, 0x42, 0x46, 0xde, 0xbb, 0xe7, 0x76, - 0xd1, 0x33, 0x92, 0xfc, 0x46, 0x17, 0x6d, 0x21, - 0xf6, 0x0e, 0x16, 0xca, 0x9b, 0x9b, 0x04, 0x65, - 0x16, 0x40, 0x44, 0x64, 0xbc, 0x58, 0xfa, 0x2a, - 0x49, 0xe9, 0xed, 0x17, 0x03, 0x03, 0x00, 0x21, - 0x89, 0x71, 0xcd, 0x56, 0x54, 0xbf, 0x73, 0xde, - 0xfb, 0x4b, 0x4e, 0xf1, 0x7f, 0xc6, 0x75, 0xa6, - 0xbd, 0x6b, 0x6c, 0xd9, 0xdc, 0x0c, 0x71, 0xb4, - 0xb9, 0xbb, 0x6e, 0xfa, 0x9e, 0xc7, 0xc7, 0x4c, - 0x24, 0x15, 0x03, 0x03, 0x00, 0x16, 0x62, 0xea, - 0x65, 0x69, 0x68, 0x4a, 0xce, 0xa7, 0x9e, 0xce, - 0xc0, 0xf1, 0x5c, 0x96, 0xd9, 0x1f, 0x49, 0xac, - 0x2d, 0x05, 0x89, 0x94, - }, +func TestFallbackSCSV(t *testing.T) { + test := &serverTest{ + name: "FallbackSCSV", + // OpenSSL 1.0.1j is needed for the -fallback_scsv option. + command: []string{"openssl", "s_client", "-fallback_scsv"}, + expectHandshakeErrorIncluding: "inppropriate protocol fallback", + } + runServerTestTLS11(t, test) } // cert.pem and key.pem were generated with generate_cert.go // Thus, they have no ExtKeyUsage fields and trigger an error // when verification is turned on. -var clientCertificate = loadPEMCert(` +const clientCertificatePEM = ` -----BEGIN CERTIFICATE----- MIIB7TCCAVigAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTExMTIwODA3NTUxMloXDTEyMTIwNzA4 @@ -3147,10 +742,9 @@ DwYDVR0jBAgwBoAEAQIDBDALBgkqhkiG9w0BAQUDgYEANh+zegx1yW43RmEr1b3A p0vMRpqBWHyFeSnIyMZn3TJWRSt1tukkqVCavh9a+hoV2cxVlXIWg7nCto/9iIw4 hB2rXZIxE0/9gzvGnfERYraL7KtnvshksBFQRlgXa5kc0x38BvEO5ZaoDPl4ILdE GFGNEH5PlGffo05wc46QkYU= ------END CERTIFICATE----- -`) +-----END CERTIFICATE-----` -/* corresponding key.pem for cert.pem is: +const clientKeyPEM = ` -----BEGIN RSA PRIVATE KEY----- MIICWgIBAAKBgE7QezHjgmTZWcDCh6ReHotzM8djU99mkgaE9mTVj+Q2px0r6LMg NkUjteOVru3g9SCcjZXff1oS74fkW2jk6Q507ASKf96TJ8QBGXq98tw9FKvQVMoh @@ -3165,10 +759,9 @@ saG9sF+UEhRt9AxUfW/U/tIQ9V0ZHHcSg1XaCM5Nvp934brdKdvTOKnJAkBD5h/3 Rybatlvg/fzBEaJFyq09zhngkxlZOUtBVTqzl17RVvY2orgH02U4HbCHy4phxOn7 qTdQRYlHRftgnWK1AkANibn9PRYJ7mJyJ9Dyj2QeNcSkSTzrt0tPvUMf4+meJymN 1Ntu5+S1DLLzfxlaljWG6ylW6DNxujCyuXIV2rvA ------END RSA PRIVATE KEY----- -*/ +-----END RSA PRIVATE KEY-----` -var clientECDSACertificate = loadPEMCert(` +const clientECDSACertificatePEM = ` -----BEGIN CERTIFICATE----- MIIB/DCCAV4CCQCaMIRsJjXZFzAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0 @@ -3181,10 +774,9 @@ ixgnTy5w/hOWusPTQBbNZU6sER7m8TAJBgcqhkjOPQQBA4GMADCBiAJCAOAUxGBg C3JosDJdYUoCdFzCgbkWqD8pyDbHgf9stlvZcPE4O1BIKJTLCRpS8V3ujfK58PDa 2RU6+b0DeoeiIzXsAkIBo9SKeDUcSpoj0gq+KxAxnZxfvuiRs9oa9V2jI/Umi0Vw jWVim34BmT0Y9hCaOGGbLlfk+syxis7iI6CH8OFnUes= ------END CERTIFICATE----- -`) +-----END CERTIFICATE-----` -/* corresponding key for cert is: +const clientECDSAKeyPEM = ` -----BEGIN EC PARAMETERS----- BgUrgQQAIw== -----END EC PARAMETERS----- @@ -3194,603 +786,83 @@ k+wLWoqizS3NpQyMtrU8JFdWfj+C57UNkOugBwYFK4EEACOhgYkDgYYABACVjJF1 FMBexFe01MNvja5oHt1vzobhfm6ySD6B5U7ixohLZNz1MLvT/2XMW/TdtWo+PtAd 3kfDdq0Z9kUsjLzYHQFMH3CQRnZIi4+DzEpcj0B22uCJ7B0rxE4wdihBsmKo+1vx +U56jb0JuK7qixgnTy5w/hOWusPTQBbNZU6sER7m8Q== ------END EC PRIVATE KEY----- -*/ -var clientauthECDSATests = []clientauthTest{ - // Server asks for cert with empty CA list, client gives one - // go test -run "TestRunServer" -serve \ - // -clientauth 1 -ciphersuites=0xc00a - // openssl s_client -host 127.0.0.1 -port 10443 \ - // -cipher ECDHE-ECDSA-AES256-SHA -key client.key -cert client.crt - {"RequestClientCert, client gives it", RequestClientCert, []*x509.Certificate{clientECDSACertificate}, [][]byte{ - { - 0x16, 0x03, 0x01, 0x00, 0xa0, 0x01, 0x00, 0x00, - 0x9c, 0x03, 0x03, 0x51, 0xe5, 0x73, 0xc5, 0xae, - 0x51, 0x94, 0xb4, 0xf2, 0xe8, 0xf6, 0x03, 0x0e, - 0x3b, 0x34, 0xaf, 0xf0, 0xdc, 0x1b, 0xcc, 0xd8, - 0x0c, 0x45, 0x82, 0xd4, 0xd6, 0x76, 0x04, 0x6e, - 0x4f, 0x7a, 0x24, 0x00, 0x00, 0x04, 0xc0, 0x0a, - 0x00, 0xff, 0x01, 0x00, 0x00, 0x6f, 0x00, 0x0b, - 0x00, 0x04, 0x03, 0x00, 0x01, 0x02, 0x00, 0x0a, - 0x00, 0x34, 0x00, 0x32, 0x00, 0x0e, 0x00, 0x0d, - 0x00, 0x19, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x18, - 0x00, 0x09, 0x00, 0x0a, 0x00, 0x16, 0x00, 0x17, - 0x00, 0x08, 0x00, 0x06, 0x00, 0x07, 0x00, 0x14, - 0x00, 0x15, 0x00, 0x04, 0x00, 0x05, 0x00, 0x12, - 0x00, 0x13, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, - 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x23, - 0x00, 0x00, 0x00, 0x0d, 0x00, 0x22, 0x00, 0x20, - 0x06, 0x01, 0x06, 0x02, 0x06, 0x03, 0x05, 0x01, - 0x05, 0x02, 0x05, 0x03, 0x04, 0x01, 0x04, 0x02, - 0x04, 0x03, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, - 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, - 0x00, 0x0f, 0x00, 0x01, 0x01, - }, - { - 0x16, 0x03, 0x01, 0x00, 0x30, 0x02, 0x00, 0x00, - 0x2c, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0a, 0x00, 0x00, - 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x01, - 0x02, 0x0e, 0x0b, 0x00, 0x02, 0x0a, 0x00, 0x02, - 0x07, 0x00, 0x02, 0x04, 0x30, 0x82, 0x02, 0x00, - 0x30, 0x82, 0x01, 0x62, 0x02, 0x09, 0x00, 0xb8, - 0xbf, 0x2d, 0x47, 0xa0, 0xd2, 0xeb, 0xf4, 0x30, - 0x09, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, - 0x04, 0x01, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, - 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, - 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, - 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, - 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x31, - 0x31, 0x32, 0x32, 0x31, 0x35, 0x30, 0x36, 0x33, - 0x32, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x31, 0x31, - 0x32, 0x30, 0x31, 0x35, 0x30, 0x36, 0x33, 0x32, - 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, - 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, - 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, - 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, - 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, - 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, - 0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a, - 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, - 0x2b, 0x81, 0x04, 0x00, 0x23, 0x03, 0x81, 0x86, - 0x00, 0x04, 0x00, 0xc4, 0xa1, 0xed, 0xbe, 0x98, - 0xf9, 0x0b, 0x48, 0x73, 0x36, 0x7e, 0xc3, 0x16, - 0x56, 0x11, 0x22, 0xf2, 0x3d, 0x53, 0xc3, 0x3b, - 0x4d, 0x21, 0x3d, 0xcd, 0x6b, 0x75, 0xe6, 0xf6, - 0xb0, 0xdc, 0x9a, 0xdf, 0x26, 0xc1, 0xbc, 0xb2, - 0x87, 0xf0, 0x72, 0x32, 0x7c, 0xb3, 0x64, 0x2f, - 0x1c, 0x90, 0xbc, 0xea, 0x68, 0x23, 0x10, 0x7e, - 0xfe, 0xe3, 0x25, 0xc0, 0x48, 0x3a, 0x69, 0xe0, - 0x28, 0x6d, 0xd3, 0x37, 0x00, 0xef, 0x04, 0x62, - 0xdd, 0x0d, 0xa0, 0x9c, 0x70, 0x62, 0x83, 0xd8, - 0x81, 0xd3, 0x64, 0x31, 0xaa, 0x9e, 0x97, 0x31, - 0xbd, 0x96, 0xb0, 0x68, 0xc0, 0x9b, 0x23, 0xde, - 0x76, 0x64, 0x3f, 0x1a, 0x5c, 0x7f, 0xe9, 0x12, - 0x0e, 0x58, 0x58, 0xb6, 0x5f, 0x70, 0xdd, 0x9b, - 0xd8, 0xea, 0xd5, 0xd7, 0xf5, 0xd5, 0xcc, 0xb9, - 0xb6, 0x9f, 0x30, 0x66, 0x5b, 0x66, 0x9a, 0x20, - 0xe2, 0x27, 0xe5, 0xbf, 0xfe, 0x3b, 0x30, 0x09, - 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, - 0x01, 0x03, 0x81, 0x8c, 0x00, 0x30, 0x81, 0x88, - 0x02, 0x42, 0x01, 0x88, 0xa2, 0x4f, 0xeb, 0xe2, - 0x45, 0xc5, 0x48, 0x7d, 0x1b, 0xac, 0xf5, 0xed, - 0x98, 0x9d, 0xae, 0x47, 0x70, 0xc0, 0x5e, 0x1b, - 0xb6, 0x2f, 0xbd, 0xf1, 0xb6, 0x4d, 0xb7, 0x61, - 0x40, 0xd3, 0x11, 0xa2, 0xce, 0xee, 0x0b, 0x7e, - 0x92, 0x7e, 0xff, 0x76, 0x9d, 0xc3, 0x3b, 0x7e, - 0xa5, 0x3f, 0xce, 0xfa, 0x10, 0xe2, 0x59, 0xec, - 0x47, 0x2d, 0x7c, 0xac, 0xda, 0x4e, 0x97, 0x0e, - 0x15, 0xa0, 0x6f, 0xd0, 0x02, 0x42, 0x01, 0x4d, - 0xfc, 0xbe, 0x67, 0x13, 0x9c, 0x2d, 0x05, 0x0e, - 0xbd, 0x3f, 0xa3, 0x8c, 0x25, 0xc1, 0x33, 0x13, - 0x83, 0x0d, 0x94, 0x06, 0xbb, 0xd4, 0x37, 0x7a, - 0xf6, 0xec, 0x7a, 0xc9, 0x86, 0x2e, 0xdd, 0xd7, - 0x11, 0x69, 0x7f, 0x85, 0x7c, 0x56, 0xde, 0xfb, - 0x31, 0x78, 0x2b, 0xe4, 0xc7, 0x78, 0x0d, 0xae, - 0xcb, 0xbe, 0x9e, 0x4e, 0x36, 0x24, 0x31, 0x7b, - 0x6a, 0x0f, 0x39, 0x95, 0x12, 0x07, 0x8f, 0x2a, - 0x16, 0x03, 0x01, 0x01, 0x1a, 0x0c, 0x00, 0x01, - 0x16, 0x03, 0x00, 0x19, 0x85, 0x04, 0x01, 0x39, - 0xdc, 0xee, 0x44, 0x17, 0x5e, 0xdb, 0xd7, 0x27, - 0xaf, 0xb6, 0x56, 0xd9, 0xb4, 0x43, 0x5a, 0x99, - 0xcf, 0xaa, 0x31, 0x37, 0x0c, 0x6f, 0x3a, 0xa0, - 0xf8, 0x53, 0xc4, 0x74, 0xd1, 0x91, 0x0a, 0x46, - 0xf5, 0x38, 0x3b, 0x5c, 0x09, 0xd8, 0x97, 0xdc, - 0x4b, 0xaa, 0x70, 0x26, 0x48, 0xf2, 0xd6, 0x0b, - 0x31, 0xc9, 0xf8, 0xd4, 0x98, 0x43, 0xe1, 0x6c, - 0xd5, 0xc7, 0xb2, 0x8e, 0x0b, 0x01, 0xe6, 0xb6, - 0x00, 0x28, 0x80, 0x7b, 0xfc, 0x96, 0x8f, 0x0d, - 0xa2, 0x4f, 0xb0, 0x79, 0xaf, 0xdc, 0x61, 0x28, - 0x63, 0x33, 0x78, 0xf6, 0x31, 0x39, 0xfd, 0x8a, - 0xf4, 0x15, 0x18, 0x11, 0xfe, 0xdb, 0xd5, 0x07, - 0xda, 0x2c, 0xed, 0x49, 0xa0, 0x23, 0xbf, 0xd0, - 0x3a, 0x38, 0x1d, 0x54, 0xae, 0x1c, 0x7b, 0xea, - 0x29, 0xee, 0xd0, 0x38, 0xc1, 0x76, 0xa7, 0x7f, - 0x2a, 0xf4, 0xce, 0x1e, 0xac, 0xcc, 0x94, 0x79, - 0x90, 0x33, 0x00, 0x8b, 0x30, 0x81, 0x88, 0x02, - 0x42, 0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, - 0x04, 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, - 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, - 0x3f, 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, - 0x4d, 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, - 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, - 0xff, 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, - 0x6a, 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, - 0xe5, 0xbd, 0x66, 0x02, 0x42, 0x00, 0xad, 0x7d, - 0x06, 0x35, 0xab, 0xec, 0x8d, 0xac, 0xd4, 0xba, - 0x1b, 0x49, 0x5e, 0x05, 0x5f, 0xf0, 0x97, 0x93, - 0x82, 0xb8, 0x2b, 0x8d, 0x91, 0x98, 0x63, 0x8e, - 0xb4, 0x14, 0x62, 0xdb, 0x1e, 0xc9, 0x2b, 0x30, - 0xf8, 0x41, 0x9b, 0xa6, 0xe6, 0xbc, 0xde, 0x0e, - 0x68, 0x30, 0x21, 0xf4, 0xa8, 0xa9, 0x1b, 0xec, - 0x44, 0x4f, 0x5d, 0x02, 0x2f, 0x60, 0x45, 0x60, - 0xba, 0xe0, 0x4e, 0xc0, 0xd4, 0x3b, 0x01, 0x16, - 0x03, 0x01, 0x00, 0x09, 0x0d, 0x00, 0x00, 0x05, - 0x02, 0x01, 0x40, 0x00, 0x00, 0x16, 0x03, 0x01, - 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00, - }, - { - 0x16, 0x03, 0x01, 0x02, 0x0a, 0x0b, 0x00, 0x02, - 0x06, 0x00, 0x02, 0x03, 0x00, 0x02, 0x00, 0x30, - 0x82, 0x01, 0xfc, 0x30, 0x82, 0x01, 0x5e, 0x02, - 0x09, 0x00, 0x9a, 0x30, 0x84, 0x6c, 0x26, 0x35, - 0xd9, 0x17, 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, - 0x48, 0xce, 0x3d, 0x04, 0x01, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, - 0x31, 0x32, 0x31, 0x31, 0x31, 0x34, 0x31, 0x33, - 0x32, 0x35, 0x35, 0x33, 0x5a, 0x17, 0x0d, 0x32, - 0x32, 0x31, 0x31, 0x31, 0x32, 0x31, 0x33, 0x32, - 0x35, 0x35, 0x33, 0x5a, 0x30, 0x41, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x41, 0x55, 0x31, 0x0c, 0x30, 0x0a, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x13, 0x03, 0x4e, 0x53, - 0x57, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, - 0x04, 0x07, 0x13, 0x07, 0x50, 0x79, 0x72, 0x6d, - 0x6f, 0x6e, 0x74, 0x31, 0x12, 0x30, 0x10, 0x06, - 0x03, 0x55, 0x04, 0x03, 0x13, 0x09, 0x4a, 0x6f, - 0x65, 0x6c, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x30, - 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, - 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, - 0x81, 0x04, 0x00, 0x23, 0x03, 0x81, 0x86, 0x00, - 0x04, 0x00, 0x95, 0x8c, 0x91, 0x75, 0x14, 0xc0, - 0x5e, 0xc4, 0x57, 0xb4, 0xd4, 0xc3, 0x6f, 0x8d, - 0xae, 0x68, 0x1e, 0xdd, 0x6f, 0xce, 0x86, 0xe1, - 0x7e, 0x6e, 0xb2, 0x48, 0x3e, 0x81, 0xe5, 0x4e, - 0xe2, 0xc6, 0x88, 0x4b, 0x64, 0xdc, 0xf5, 0x30, - 0xbb, 0xd3, 0xff, 0x65, 0xcc, 0x5b, 0xf4, 0xdd, - 0xb5, 0x6a, 0x3e, 0x3e, 0xd0, 0x1d, 0xde, 0x47, - 0xc3, 0x76, 0xad, 0x19, 0xf6, 0x45, 0x2c, 0x8c, - 0xbc, 0xd8, 0x1d, 0x01, 0x4c, 0x1f, 0x70, 0x90, - 0x46, 0x76, 0x48, 0x8b, 0x8f, 0x83, 0xcc, 0x4a, - 0x5c, 0x8f, 0x40, 0x76, 0xda, 0xe0, 0x89, 0xec, - 0x1d, 0x2b, 0xc4, 0x4e, 0x30, 0x76, 0x28, 0x41, - 0xb2, 0x62, 0xa8, 0xfb, 0x5b, 0xf1, 0xf9, 0x4e, - 0x7a, 0x8d, 0xbd, 0x09, 0xb8, 0xae, 0xea, 0x8b, - 0x18, 0x27, 0x4f, 0x2e, 0x70, 0xfe, 0x13, 0x96, - 0xba, 0xc3, 0xd3, 0x40, 0x16, 0xcd, 0x65, 0x4e, - 0xac, 0x11, 0x1e, 0xe6, 0xf1, 0x30, 0x09, 0x06, - 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01, - 0x03, 0x81, 0x8c, 0x00, 0x30, 0x81, 0x88, 0x02, - 0x42, 0x00, 0xe0, 0x14, 0xc4, 0x60, 0x60, 0x0b, - 0x72, 0x68, 0xb0, 0x32, 0x5d, 0x61, 0x4a, 0x02, - 0x74, 0x5c, 0xc2, 0x81, 0xb9, 0x16, 0xa8, 0x3f, - 0x29, 0xc8, 0x36, 0xc7, 0x81, 0xff, 0x6c, 0xb6, - 0x5b, 0xd9, 0x70, 0xf1, 0x38, 0x3b, 0x50, 0x48, - 0x28, 0x94, 0xcb, 0x09, 0x1a, 0x52, 0xf1, 0x5d, - 0xee, 0x8d, 0xf2, 0xb9, 0xf0, 0xf0, 0xda, 0xd9, - 0x15, 0x3a, 0xf9, 0xbd, 0x03, 0x7a, 0x87, 0xa2, - 0x23, 0x35, 0xec, 0x02, 0x42, 0x01, 0xa3, 0xd4, - 0x8a, 0x78, 0x35, 0x1c, 0x4a, 0x9a, 0x23, 0xd2, - 0x0a, 0xbe, 0x2b, 0x10, 0x31, 0x9d, 0x9c, 0x5f, - 0xbe, 0xe8, 0x91, 0xb3, 0xda, 0x1a, 0xf5, 0x5d, - 0xa3, 0x23, 0xf5, 0x26, 0x8b, 0x45, 0x70, 0x8d, - 0x65, 0x62, 0x9b, 0x7e, 0x01, 0x99, 0x3d, 0x18, - 0xf6, 0x10, 0x9a, 0x38, 0x61, 0x9b, 0x2e, 0x57, - 0xe4, 0xfa, 0xcc, 0xb1, 0x8a, 0xce, 0xe2, 0x23, - 0xa0, 0x87, 0xf0, 0xe1, 0x67, 0x51, 0xeb, 0x16, - 0x03, 0x01, 0x00, 0x8a, 0x10, 0x00, 0x00, 0x86, - 0x85, 0x04, 0x00, 0xcd, 0x1c, 0xe8, 0x66, 0x5b, - 0xa8, 0x9d, 0x83, 0x2f, 0x7e, 0x1d, 0x0b, 0x59, - 0x23, 0xbc, 0x30, 0xcf, 0xa3, 0xaf, 0x21, 0xdc, - 0xf2, 0x57, 0x49, 0x56, 0x30, 0x25, 0x7c, 0x84, - 0x5d, 0xad, 0xaa, 0x9c, 0x7b, 0x2a, 0x95, 0x58, - 0x3d, 0x30, 0x87, 0x01, 0x3b, 0xb7, 0xea, 0xcb, - 0xc4, 0xa3, 0xeb, 0x22, 0xbf, 0x2d, 0x61, 0x17, - 0x8c, 0x9b, 0xe8, 0x1b, 0xb2, 0x87, 0x16, 0x78, - 0xd5, 0xfd, 0x8b, 0xdd, 0x00, 0x0f, 0xda, 0x8e, - 0xfd, 0x28, 0x36, 0xeb, 0xe4, 0xc5, 0x42, 0x14, - 0xc7, 0xbd, 0x29, 0x5e, 0x9a, 0xed, 0x5e, 0xc1, - 0xf7, 0xf4, 0xbd, 0xbd, 0x15, 0x9c, 0xe8, 0x44, - 0x71, 0xa7, 0xb6, 0xe9, 0xfa, 0x7e, 0x97, 0xcb, - 0x96, 0x3e, 0x53, 0x76, 0xfb, 0x11, 0x1f, 0x36, - 0x8f, 0x30, 0xfb, 0x71, 0x3a, 0x75, 0x3a, 0x25, - 0x7b, 0xa2, 0xc1, 0xf9, 0x3e, 0x58, 0x5f, 0x07, - 0x16, 0xed, 0xe1, 0xf7, 0xc1, 0xb1, 0x16, 0x03, - 0x01, 0x00, 0x90, 0x0f, 0x00, 0x00, 0x8c, 0x00, - 0x8a, 0x30, 0x81, 0x87, 0x02, 0x42, 0x00, 0xb2, - 0xd3, 0x91, 0xe6, 0xd5, 0x9b, 0xb2, 0xb8, 0x03, - 0xf4, 0x85, 0x4d, 0x43, 0x79, 0x1f, 0xb6, 0x6f, - 0x0c, 0xcd, 0x67, 0x5f, 0x5e, 0xca, 0xee, 0xb3, - 0xe4, 0xab, 0x1e, 0x58, 0xc3, 0x04, 0xa9, 0x8a, - 0xa7, 0xcf, 0xaa, 0x33, 0x88, 0xd5, 0x35, 0xd2, - 0x80, 0x8f, 0xfa, 0x1b, 0x3c, 0x3d, 0xf7, 0x80, - 0x50, 0xde, 0x80, 0x30, 0x64, 0xee, 0xc0, 0xb3, - 0x91, 0x6e, 0x5d, 0x1e, 0xc0, 0xdc, 0x3a, 0x93, - 0x02, 0x41, 0x4e, 0xca, 0x98, 0x41, 0x8c, 0x36, - 0xf2, 0x12, 0xbf, 0x8e, 0x0f, 0x69, 0x8e, 0xf8, - 0x7b, 0x9d, 0xba, 0x9c, 0x5c, 0x48, 0x79, 0xf4, - 0xba, 0x3d, 0x06, 0xa5, 0xab, 0x47, 0xe0, 0x1a, - 0x45, 0x28, 0x3a, 0x8f, 0xbf, 0x14, 0x24, 0x36, - 0xd1, 0x1d, 0x29, 0xdc, 0xde, 0x72, 0x5b, 0x76, - 0x41, 0x67, 0xe8, 0xe5, 0x71, 0x4a, 0x77, 0xe9, - 0xed, 0x02, 0x19, 0xdd, 0xe4, 0xaa, 0xe9, 0x2d, - 0xe7, 0x47, 0x32, 0x14, 0x03, 0x01, 0x00, 0x01, - 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0xfa, 0xc3, - 0xf2, 0x35, 0xd0, 0x6d, 0x32, 0x78, 0x6a, 0xd6, - 0xe6, 0x70, 0x5e, 0x00, 0x4c, 0x35, 0xf1, 0xe0, - 0x21, 0xcf, 0xc3, 0x78, 0xcd, 0xe0, 0x2b, 0x0b, - 0xf4, 0xeb, 0xf9, 0xc0, 0x38, 0xf2, 0x9a, 0x31, - 0x55, 0x07, 0x2b, 0x8d, 0x68, 0x40, 0x31, 0x08, - 0xaa, 0xe3, 0x16, 0xcf, 0x4b, 0xd4, - }, - { - 0x16, 0x03, 0x01, 0x02, 0x76, 0x04, 0x00, 0x02, - 0x72, 0x00, 0x00, 0x00, 0x00, 0x02, 0x6c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, - 0xe8, 0x8b, 0xde, 0xef, 0xba, 0xf9, 0xdb, 0x95, - 0x24, 0xa5, 0x49, 0xb3, 0x23, 0xd8, 0x73, 0x88, - 0x50, 0x42, 0xed, 0xeb, 0xa3, 0xd8, 0xab, 0x31, - 0x9c, 0xd0, 0x00, 0x01, 0xef, 0xc0, 0xbf, 0xab, - 0x59, 0x55, 0xb5, 0xb9, 0xef, 0xa5, 0xa6, 0xec, - 0x69, 0xed, 0x00, 0x2f, 0x47, 0xdb, 0x75, 0x52, - 0x0c, 0xe5, 0x86, 0xb7, 0x02, 0x59, 0x22, 0xf7, - 0xfd, 0x8b, 0xff, 0xa4, 0x09, 0xc0, 0x1c, 0x10, - 0x80, 0x10, 0x7f, 0x4c, 0x7a, 0x94, 0x40, 0x10, - 0x0d, 0xda, 0x8a, 0xe5, 0x4a, 0xbc, 0xd0, 0xc0, - 0x4b, 0xa5, 0x33, 0x97, 0xc6, 0xe7, 0x40, 0x7f, - 0x7f, 0x8c, 0xf9, 0xf8, 0xc8, 0xb8, 0xfb, 0x8c, - 0xdd, 0x28, 0x81, 0xae, 0xfd, 0x37, 0x20, 0x3a, - 0x40, 0x37, 0x99, 0xc4, 0x21, 0x01, 0xc4, 0x91, - 0xb0, 0x5e, 0x11, 0xc5, 0xa9, 0xfd, 0x9a, 0x02, - 0x7e, 0x97, 0x6a, 0x86, 0x89, 0xb8, 0xc1, 0x32, - 0x4c, 0x7e, 0x6d, 0x47, 0x61, 0x0e, 0xe3, 0xc2, - 0xf0, 0x62, 0x3c, 0xc6, 0x71, 0x4f, 0xbb, 0x47, - 0x65, 0xb1, 0xd9, 0x22, 0x79, 0x15, 0xea, 0x1f, - 0x4b, 0x2a, 0x8a, 0xa4, 0xc8, 0x73, 0x34, 0xba, - 0x83, 0xe4, 0x70, 0x99, 0xc9, 0xcf, 0xbe, 0x64, - 0x99, 0xb9, 0xfa, 0xe9, 0xaf, 0x5d, 0xc7, 0x20, - 0x26, 0xde, 0xc5, 0x06, 0x12, 0x36, 0x4f, 0x4d, - 0xc0, 0xbb, 0x81, 0x5b, 0x5e, 0x38, 0xc3, 0x07, - 0x21, 0x04, 0x1a, 0x53, 0x9c, 0x59, 0xac, 0x2d, - 0xe6, 0xa5, 0x93, 0xa5, 0x19, 0xc6, 0xb0, 0xf7, - 0x56, 0x5d, 0xdf, 0xd1, 0xf4, 0xfd, 0x44, 0x6d, - 0xc6, 0xa2, 0x31, 0xa7, 0x35, 0x42, 0x18, 0x50, - 0x0c, 0x4f, 0x6e, 0xe3, 0x3b, 0xa3, 0xaa, 0x1c, - 0xbe, 0x41, 0x0d, 0xce, 0x6c, 0x62, 0xe1, 0x96, - 0x2d, 0xbd, 0x14, 0x31, 0xe3, 0xc4, 0x5b, 0xbf, - 0xf6, 0xde, 0xec, 0x42, 0xe8, 0xc7, 0x2a, 0x0b, - 0xdb, 0x2d, 0x7c, 0xf0, 0x3f, 0x45, 0x32, 0x45, - 0x09, 0x47, 0x09, 0x0f, 0x21, 0x22, 0x45, 0x06, - 0x11, 0xb8, 0xf9, 0xe6, 0x67, 0x90, 0x4b, 0x4a, - 0xde, 0x81, 0xfb, 0xeb, 0xe7, 0x9a, 0x08, 0x30, - 0xcf, 0x51, 0xe1, 0xd9, 0xfa, 0x79, 0xa3, 0xcc, - 0x65, 0x1a, 0x83, 0x86, 0xc9, 0x7a, 0x41, 0xf5, - 0xdf, 0xa0, 0x7c, 0x44, 0x23, 0x17, 0xf3, 0x62, - 0xe8, 0xa9, 0x31, 0x1e, 0x6b, 0x05, 0x4b, 0x4f, - 0x9d, 0x91, 0x46, 0x92, 0xa6, 0x25, 0x32, 0xca, - 0xa1, 0x75, 0xda, 0xe6, 0x80, 0x3e, 0x7f, 0xd1, - 0x26, 0x57, 0x07, 0x42, 0xe4, 0x91, 0xff, 0xbd, - 0x44, 0xae, 0x98, 0x5c, 0x1d, 0xdf, 0x11, 0xe3, - 0xae, 0x87, 0x5e, 0xb7, 0x69, 0xad, 0x34, 0x7f, - 0x3a, 0x07, 0x7c, 0xdf, 0xfc, 0x76, 0x17, 0x8b, - 0x62, 0xc8, 0xe1, 0x78, 0x2a, 0xc8, 0xb9, 0x8a, - 0xbb, 0x5c, 0xfb, 0x38, 0x74, 0x91, 0x6e, 0x12, - 0x0c, 0x1f, 0x8e, 0xe1, 0xc2, 0x01, 0xd8, 0x9d, - 0x23, 0x0f, 0xc4, 0x67, 0x5d, 0xe5, 0x67, 0x4b, - 0x94, 0x6e, 0x69, 0x72, 0x90, 0x2d, 0x52, 0x78, - 0x8e, 0x61, 0xba, 0xdf, 0x4e, 0xf5, 0xdc, 0xfb, - 0x73, 0xbe, 0x03, 0x70, 0xd9, 0x01, 0x30, 0xf3, - 0xa1, 0xbb, 0x9a, 0x5f, 0xec, 0x9e, 0xed, 0x8d, - 0xdd, 0x53, 0xfd, 0x60, 0xc3, 0x2b, 0x7a, 0x00, - 0x2c, 0xf9, 0x0a, 0x57, 0x47, 0x45, 0x43, 0xb3, - 0x23, 0x01, 0x9c, 0xee, 0x54, 0x4d, 0x58, 0xd3, - 0x71, 0x1c, 0xc9, 0xd3, 0x30, 0x9e, 0x14, 0xa5, - 0xf3, 0xbf, 0x4d, 0x9b, 0xb7, 0x13, 0x21, 0xae, - 0xd2, 0x8d, 0x6e, 0x6f, 0x1c, 0xcc, 0xb2, 0x41, - 0xb2, 0x64, 0x56, 0x83, 0xce, 0xd1, 0x0c, 0x79, - 0x32, 0x78, 0xef, 0xc5, 0x21, 0xb1, 0xe8, 0xc4, - 0x42, 0xa7, 0x8d, 0xc1, 0xfa, 0xa1, 0x9c, 0x3c, - 0x21, 0xd8, 0xe9, 0x90, 0xe2, 0x7c, 0x14, 0x26, - 0xfe, 0x61, 0x3e, 0xf9, 0x71, 0x1d, 0x5d, 0x49, - 0x3b, 0xb1, 0xb8, 0x42, 0xa1, 0xb8, 0x1c, 0x75, - 0x7d, 0xee, 0xed, 0xfc, 0xe6, 0x20, 0x2b, 0x9e, - 0x10, 0x52, 0xda, 0x56, 0x4d, 0x64, 0x6c, 0x41, - 0xc1, 0xf7, 0x60, 0x0c, 0x10, 0x65, 0x6f, 0xd4, - 0xe9, 0x9b, 0x0d, 0x83, 0x13, 0xc8, 0x5a, 0xa3, - 0x56, 0x2a, 0x42, 0xc6, 0x1c, 0xfe, 0xdb, 0xba, - 0x3d, 0x04, 0x12, 0xfd, 0x28, 0xeb, 0x78, 0xdd, - 0xbc, 0xc8, 0x0d, 0xa1, 0xce, 0xd4, 0x54, 0xbf, - 0xaf, 0xe1, 0x60, 0x0c, 0xa3, 0xc3, 0xc3, 0x62, - 0x58, 0xc1, 0x79, 0xa7, 0x95, 0x41, 0x09, 0x24, - 0xc6, 0x9a, 0x50, 0x14, 0x03, 0x01, 0x00, 0x01, - 0x01, 0x16, 0x03, 0x01, 0x00, 0x30, 0x4d, 0x7b, - 0x5f, 0x28, 0x5e, 0x68, 0x6c, 0xa3, 0x65, 0xc7, - 0x7e, 0x49, 0x6c, 0xb3, 0x67, 0xbb, 0xd0, 0x75, - 0xa2, 0x9e, 0x8c, 0x92, 0x4f, 0x8c, 0x33, 0x14, - 0x7c, 0x6c, 0xf1, 0x74, 0x97, 0xc3, 0xe0, 0x10, - 0xe9, 0x0d, 0xc2, 0x30, 0x5c, 0x23, 0xee, 0x1d, - 0x16, 0x2e, 0xb9, 0x96, 0x2b, 0x2d, 0x17, 0x03, - 0x01, 0x00, 0x20, 0xf2, 0xc8, 0xa7, 0x1b, 0x60, - 0x46, 0xee, 0xe5, 0x7e, 0xc9, 0x35, 0xb3, 0xf1, - 0x7c, 0x32, 0x0c, 0x85, 0x94, 0x59, 0x57, 0x27, - 0xb0, 0xbd, 0x52, 0x86, 0x90, 0xf1, 0xb7, 0x4d, - 0x1e, 0xc1, 0x16, 0x17, 0x03, 0x01, 0x00, 0x30, - 0xff, 0x85, 0x50, 0xdf, 0x3f, 0xfc, 0xa2, 0x61, - 0x1a, 0x12, 0xc0, 0x1e, 0x10, 0x32, 0x88, 0x50, - 0xa0, 0x2c, 0x80, 0xda, 0x77, 0xea, 0x09, 0x47, - 0xe0, 0x85, 0x07, 0x29, 0x45, 0x65, 0x19, 0xa3, - 0x8d, 0x99, 0xb8, 0xbf, 0xb6, 0xbc, 0x76, 0xe2, - 0x50, 0x24, 0x82, 0x0a, 0xfd, 0xdd, 0x35, 0x09, - 0x15, 0x03, 0x01, 0x00, 0x20, 0xe7, 0x36, 0xf6, - 0x61, 0xd2, 0x95, 0x3c, 0xb6, 0x65, 0x7b, 0xb2, - 0xb8, 0xdf, 0x03, 0x53, 0xeb, 0xf7, 0x16, 0xe0, - 0xe0, 0x15, 0x22, 0x71, 0x70, 0x62, 0x73, 0xad, - 0xb5, 0x1a, 0x77, 0x44, 0x57, - }, - }}, +-----END EC PRIVATE KEY-----` + +func TestClientAuth(t *testing.T) { + var certPath, keyPath, ecdsaCertPath, ecdsaKeyPath string + + if *update { + certPath = tempFile(clientCertificatePEM) + defer os.Remove(certPath) + keyPath = tempFile(clientKeyPEM) + defer os.Remove(keyPath) + ecdsaCertPath = tempFile(clientECDSACertificatePEM) + defer os.Remove(ecdsaCertPath) + ecdsaKeyPath = tempFile(clientECDSAKeyPEM) + defer os.Remove(ecdsaKeyPath) + } + + config := *testConfig + config.ClientAuth = RequestClientCert + + test := &serverTest{ + name: "ClientAuthRequestedNotGiven", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA"}, + config: &config, + } + runServerTestTLS12(t, test) + + test = &serverTest{ + name: "ClientAuthRequestedAndGiven", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", certPath, "-key", keyPath}, + config: &config, + expectedPeerCerts: []string{clientCertificatePEM}, + } + runServerTestTLS12(t, test) + + test = &serverTest{ + name: "ClientAuthRequestedAndECDSAGiven", + command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", ecdsaCertPath, "-key", ecdsaKeyPath}, + config: &config, + expectedPeerCerts: []string{clientECDSACertificatePEM}, + } + runServerTestTLS12(t, test) } -var aesGCMServerScript = [][]byte{ - { - 0x16, 0x03, 0x01, 0x01, 0x1c, 0x01, 0x00, 0x01, - 0x18, 0x03, 0x03, 0x52, 0x1e, 0x74, 0xf0, 0xb0, - 0xc1, 0x8b, 0x16, 0xf9, 0x74, 0xfc, 0x16, 0xc4, - 0x11, 0x18, 0x96, 0x08, 0x25, 0x38, 0x4f, 0x98, - 0x98, 0xbe, 0xb5, 0x61, 0xdf, 0x94, 0x15, 0xcc, - 0x9b, 0x61, 0xef, 0x00, 0x00, 0x80, 0xc0, 0x30, - 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, - 0xc0, 0x0a, 0x00, 0xa3, 0x00, 0x9f, 0x00, 0x6b, - 0x00, 0x6a, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x32, - 0xc0, 0x2e, 0xc0, 0x2a, 0xc0, 0x26, 0xc0, 0x0f, - 0xc0, 0x05, 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, - 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x13, - 0xc0, 0x0d, 0xc0, 0x03, 0x00, 0x0a, 0xc0, 0x2f, - 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13, - 0xc0, 0x09, 0x00, 0xa2, 0x00, 0x9e, 0x00, 0x67, - 0x00, 0x40, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x31, - 0xc0, 0x2d, 0xc0, 0x29, 0xc0, 0x25, 0xc0, 0x0e, - 0xc0, 0x04, 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, - 0xc0, 0x11, 0xc0, 0x07, 0xc0, 0x0c, 0xc0, 0x02, - 0x00, 0x05, 0x00, 0x04, 0x00, 0x15, 0x00, 0x12, - 0x00, 0x09, 0x00, 0x14, 0x00, 0x11, 0x00, 0x08, - 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x01, 0x00, - 0x00, 0x6f, 0x00, 0x0b, 0x00, 0x04, 0x03, 0x00, - 0x01, 0x02, 0x00, 0x0a, 0x00, 0x34, 0x00, 0x32, - 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x19, 0x00, 0x0b, - 0x00, 0x0c, 0x00, 0x18, 0x00, 0x09, 0x00, 0x0a, - 0x00, 0x16, 0x00, 0x17, 0x00, 0x08, 0x00, 0x06, - 0x00, 0x07, 0x00, 0x14, 0x00, 0x15, 0x00, 0x04, - 0x00, 0x05, 0x00, 0x12, 0x00, 0x13, 0x00, 0x01, - 0x00, 0x02, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x10, - 0x00, 0x11, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, - 0x00, 0x22, 0x00, 0x20, 0x06, 0x01, 0x06, 0x02, - 0x06, 0x03, 0x05, 0x01, 0x05, 0x02, 0x05, 0x03, - 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x03, 0x01, - 0x03, 0x02, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, - 0x02, 0x03, 0x01, 0x01, 0x00, 0x0f, 0x00, 0x01, - 0x01, - }, - { - 0x16, 0x03, 0x03, 0x00, 0x30, 0x02, 0x00, 0x00, - 0x2c, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc0, 0x2f, 0x00, 0x00, - 0x04, 0x00, 0x23, 0x00, 0x00, 0x16, 0x03, 0x03, - 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba, 0x00, 0x02, - 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82, 0x02, 0xb0, - 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03, 0x02, 0x01, - 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0, 0xbb, 0xa4, - 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x05, 0x05, 0x00, 0x30, 0x45, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, - 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, - 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, - 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, - 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, - 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, - 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, - 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30, - 0x34, 0x32, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33, - 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, - 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f, 0x6d, 0x65, - 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, - 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, - 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, - 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, - 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, - 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xbb, 0x79, - 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf, 0x46, 0x10, - 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b, 0x07, 0x43, - 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a, 0x43, 0x85, - 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65, 0x4c, 0x2c, - 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4, 0x82, 0xe5, - 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62, 0xa5, 0x2c, - 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c, 0x7a, 0x56, - 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58, 0x7b, 0x26, - 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0, 0xc9, 0x21, - 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f, 0x5a, 0xbf, - 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18, 0x99, 0x07, - 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1, 0x04, 0x39, - 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9, 0x7c, 0xe3, - 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01, 0xcf, 0xaf, - 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d, 0xdb, 0xdb, - 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79, 0x02, 0x03, - 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7, 0x30, 0x81, - 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, - 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad, 0xe2, 0x85, - 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, 0x23, - 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, 0x39, - 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, - 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1, 0xad, 0xe2, - 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69, 0xce, - 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18, 0x88, - 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30, 0x45, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, - 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, - 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, - 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, - 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, - 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09, 0x00, 0x85, - 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, - 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, - 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, - 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b, 0xb1, 0x59, - 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0, 0x14, 0xd7, - 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5, 0x5a, 0x95, - 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae, 0x12, 0x66, - 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e, 0x60, 0xd3, - 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5, 0x25, 0x13, - 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30, 0x1d, 0xba, - 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7, 0xd7, 0x31, - 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78, 0xea, 0x50, - 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d, 0x5a, 0x5f, - 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75, 0x90, 0x96, - 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd, 0x98, 0x1f, - 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c, 0xa3, 0x1b, - 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57, 0xe9, 0x70, - 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b, 0x26, 0x6e, - 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7, 0xbd, 0xd9, - 0x16, 0x03, 0x03, 0x01, 0x11, 0x0c, 0x00, 0x01, - 0x0d, 0x03, 0x00, 0x19, 0x85, 0x04, 0x01, 0x39, - 0xdc, 0xee, 0x44, 0x17, 0x5e, 0xdb, 0xd7, 0x27, - 0xaf, 0xb6, 0x56, 0xd9, 0xb4, 0x43, 0x5a, 0x99, - 0xcf, 0xaa, 0x31, 0x37, 0x0c, 0x6f, 0x3a, 0xa0, - 0xf8, 0x53, 0xc4, 0x74, 0xd1, 0x91, 0x0a, 0x46, - 0xf5, 0x38, 0x3b, 0x5c, 0x09, 0xd8, 0x97, 0xdc, - 0x4b, 0xaa, 0x70, 0x26, 0x48, 0xf2, 0xd6, 0x0b, - 0x31, 0xc9, 0xf8, 0xd4, 0x98, 0x43, 0xe1, 0x6c, - 0xd5, 0xc7, 0xb2, 0x8e, 0x0b, 0x01, 0xe6, 0xb6, - 0x00, 0x28, 0x80, 0x7b, 0xfc, 0x96, 0x8f, 0x0d, - 0xa2, 0x4f, 0xb0, 0x79, 0xaf, 0xdc, 0x61, 0x28, - 0x63, 0x33, 0x78, 0xf6, 0x31, 0x39, 0xfd, 0x8a, - 0xf4, 0x15, 0x18, 0x11, 0xfe, 0xdb, 0xd5, 0x07, - 0xda, 0x2c, 0xed, 0x49, 0xa0, 0x23, 0xbf, 0xd0, - 0x3a, 0x38, 0x1d, 0x54, 0xae, 0x1c, 0x7b, 0xea, - 0x29, 0xee, 0xd0, 0x38, 0xc1, 0x76, 0xa7, 0x7f, - 0x2a, 0xf4, 0xce, 0x1e, 0xac, 0xcc, 0x94, 0x79, - 0x90, 0x33, 0x04, 0x01, 0x00, 0x80, 0x0d, 0x8e, - 0x79, 0xe6, 0x86, 0xf6, 0xb6, 0xfb, 0x6b, 0x6a, - 0xcc, 0x55, 0xe4, 0x80, 0x4d, 0xc5, 0x0c, 0xc6, - 0xa3, 0x9f, 0x1d, 0x39, 0xd2, 0x98, 0x57, 0x31, - 0xa2, 0x90, 0x73, 0xe8, 0xd2, 0xcd, 0xb0, 0x93, - 0x1a, 0x60, 0x0f, 0x38, 0x02, 0x3b, 0x1b, 0x25, - 0x56, 0xec, 0x44, 0xab, 0xbe, 0x2e, 0x0c, 0xc0, - 0x6e, 0x54, 0x91, 0x50, 0xd6, 0xb1, 0xa2, 0x98, - 0x14, 0xa8, 0x35, 0x62, 0x9d, 0xca, 0xfb, 0x0f, - 0x64, 0x2b, 0x05, 0xa0, 0xa0, 0x57, 0xef, 0xcd, - 0x95, 0x45, 0x13, 0x5a, 0x9b, 0x3d, 0xdb, 0x42, - 0x54, 0x7f, 0xb9, 0x17, 0x08, 0x7f, 0xb2, 0xf0, - 0xb1, 0xc3, 0xdf, 0x67, 0x95, 0xe2, 0x73, 0xf2, - 0x76, 0xa3, 0x97, 0xfd, 0x9c, 0x92, 0x4a, 0xdb, - 0x95, 0x1e, 0x91, 0x95, 0xae, 0x3d, 0xae, 0x58, - 0xb5, 0x03, 0x6f, 0x5c, 0x3a, 0x19, 0xab, 0x92, - 0xa5, 0x09, 0x6b, 0x40, 0x61, 0xb0, 0x16, 0x03, - 0x03, 0x00, 0x04, 0x0e, 0x00, 0x00, 0x00, +func bigFromString(s string) *big.Int { + ret := new(big.Int) + ret.SetString(s, 10) + return ret +} + +func fromHex(s string) []byte { + b, _ := hex.DecodeString(s) + return b +} + +var testRSACertificate = fromHex("308202b030820219a00302010202090085b0bba48a7fb8ca300d06092a864886f70d01010505003045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3130303432343039303933385a170d3131303432343039303933385a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819f300d06092a864886f70d010101050003818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a381a73081a4301d0603551d0e04160414b1ade2855acfcb28db69ce2369ded3268e18883930750603551d23046e306c8014b1ade2855acfcb28db69ce2369ded3268e188839a149a4473045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746482090085b0bba48a7fb8ca300c0603551d13040530030101ff300d06092a864886f70d010105050003818100086c4524c76bb159ab0c52ccf2b014d7879d7a6475b55a9566e4c52b8eae12661feb4f38b36e60d392fdf74108b52513b1187a24fb301dbaed98b917ece7d73159db95d31d78ea50565cd5825a2d5a5f33c4b6d8c97590968c0f5298b5cd981f89205ff2a01ca31b9694dda9fd57e970e8266d71999b266e3850296c90a7bdd9") + +var testECDSACertificate = fromHex("3082020030820162020900b8bf2d47a0d2ebf4300906072a8648ce3d04013045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3132313132323135303633325a170d3232313132303135303633325a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819b301006072a8648ce3d020106052b81040023038186000400c4a1edbe98f90b4873367ec316561122f23d53c33b4d213dcd6b75e6f6b0dc9adf26c1bcb287f072327cb3642f1c90bcea6823107efee325c0483a69e0286dd33700ef0462dd0da09c706283d881d36431aa9e9731bd96b068c09b23de76643f1a5c7fe9120e5858b65f70dd9bd8ead5d7f5d5ccb9b69f30665b669a20e227e5bffe3b300906072a8648ce3d040103818c0030818802420188a24febe245c5487d1bacf5ed989dae4770c05e1bb62fbdf1b64db76140d311a2ceee0b7e927eff769dc33b7ea53fcefa10e259ec472d7cacda4e970e15a06fd00242014dfcbe67139c2d050ebd3fa38c25c13313830d9406bbd4377af6ec7ac9862eddd711697f857c56defb31782be4c7780daecbbe9e4e3624317b6a0f399512078f2a") + +var testSNICertificate = fromHex("308201f23082015da003020102020100300b06092a864886f70d01010530283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d301e170d3132303431313137343033355a170d3133303431313137343533355a30283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d30819d300b06092a864886f70d01010103818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a3323030300e0603551d0f0101ff0404030200a0300d0603551d0e0406040401020304300f0603551d2304083006800401020304300b06092a864886f70d0101050381810089c6455f1c1f5ef8eb1ab174ee2439059f5c4259bb1a8d86cdb1d056f56a717da40e95ab90f59e8deaf627c157995094db0802266eb34fc6842dea8a4b68d9c1389103ab84fb9e1f85d9b5d23ff2312c8670fbb540148245a4ebafe264d90c8a4cf4f85b0fac12ac2fc4a3154bad52462868af96c62c6525d652b6e31845bdcc") + +var testRSAPrivateKey = &rsa.PrivateKey{ + PublicKey: rsa.PublicKey{ + N: bigFromString("131650079503776001033793877885499001334664249354723305978524647182322416328664556247316495448366990052837680518067798333412266673813370895702118944398081598789828837447552603077848001020611640547221687072142537202428102790818451901395596882588063427854225330436740647715202971973145151161964464812406232198521"), + E: 65537, }, - { - 0x16, 0x03, 0x03, 0x00, 0x8a, 0x10, 0x00, 0x00, - 0x86, 0x85, 0x04, 0x01, 0xba, 0xb8, 0xad, 0x69, - 0x20, 0x5e, 0xc1, 0x61, 0xc3, 0x0f, 0xb4, 0x30, - 0x64, 0x66, 0x70, 0x96, 0x33, 0x3c, 0x8e, 0x12, - 0x56, 0xbf, 0x6d, 0xb8, 0x6d, 0xc6, 0xba, 0xea, - 0xfc, 0x38, 0xc0, 0x8b, 0x87, 0xa8, 0xf3, 0x87, - 0xa1, 0xd5, 0xb6, 0xb0, 0x72, 0xc7, 0xd4, 0x19, - 0x56, 0xa0, 0x91, 0xe1, 0x45, 0xc7, 0xf1, 0x7d, - 0xb0, 0x1d, 0x78, 0x18, 0xf6, 0x3d, 0xbf, 0x1a, - 0x23, 0x93, 0x0b, 0x19, 0xb1, 0x00, 0x56, 0xc9, - 0x5e, 0x89, 0xd4, 0x9d, 0xd9, 0x5b, 0xe0, 0xb8, - 0xff, 0x2f, 0x7d, 0x93, 0xae, 0x5b, 0xa5, 0x1f, - 0x1f, 0x2b, 0x09, 0xe5, 0xf6, 0x07, 0x26, 0xa3, - 0xed, 0xcb, 0x6a, 0x1a, 0xd6, 0x14, 0x83, 0x9b, - 0xd3, 0x9d, 0x47, 0x1b, 0xf3, 0x72, 0x5f, 0x69, - 0x21, 0x8f, 0xfa, 0x09, 0x38, 0x1a, 0x6b, 0x91, - 0xcf, 0x19, 0x32, 0x54, 0x58, 0x8e, 0xee, 0xaf, - 0xeb, 0x06, 0x9b, 0x3a, 0x34, 0x16, 0x66, 0x14, - 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03, 0x03, - 0x00, 0x28, 0xc6, 0x96, 0x67, 0x62, 0xcc, 0x47, - 0x01, 0xb5, 0xbd, 0xb7, 0x24, 0xd3, 0xb6, 0xfd, - 0xb8, 0x46, 0xce, 0x82, 0x6d, 0x31, 0x1f, 0x15, - 0x11, 0x8f, 0xed, 0x62, 0x71, 0x5f, 0xae, 0xb6, - 0xa9, 0x0c, 0x24, 0x1d, 0xe8, 0x26, 0x51, 0xca, - 0x7c, 0x42, + D: bigFromString("29354450337804273969007277378287027274721892607543397931919078829901848876371746653677097639302788129485893852488285045793268732234230875671682624082413996177431586734171663258657462237320300610850244186316880055243099640544518318093544057213190320837094958164973959123058337475052510833916491060913053867729"), + Primes: []*big.Int{ + bigFromString("11969277782311800166562047708379380720136961987713178380670422671426759650127150688426177829077494755200794297055316163155755835813760102405344560929062149"), + bigFromString("10998999429884441391899182616418192492905073053684657075974935218461686523870125521822756579792315215543092255516093840728890783887287417039645833477273829"), }, - { - 0x16, 0x03, 0x03, 0x00, 0x72, 0x04, 0x00, 0x00, - 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, - 0xea, 0x8b, 0xfb, 0xef, 0xba, 0xc8, 0x88, 0x94, - 0x44, 0x99, 0x5f, 0x02, 0x68, 0x3a, 0x12, 0x67, - 0x7f, 0xb9, 0x39, 0x71, 0x84, 0xe0, 0x30, 0xe6, - 0x90, 0x6c, 0xcf, 0x32, 0x29, 0x29, 0x5c, 0x5a, - 0x8b, 0x7d, 0xaa, 0x11, 0x28, 0x26, 0xb5, 0xce, - 0xd2, 0x88, 0xd5, 0xb0, 0x5f, 0x94, 0x37, 0xa2, - 0x48, 0xd9, 0x53, 0xb2, 0xab, 0x59, 0x23, 0x3d, - 0x81, 0x6e, 0x64, 0x89, 0xca, 0x1a, 0x84, 0x16, - 0xdf, 0x31, 0x10, 0xde, 0x52, 0x7f, 0x50, 0xf3, - 0xd9, 0x27, 0xa0, 0xe8, 0x34, 0x15, 0x9e, 0x11, - 0xdd, 0xba, 0xce, 0x40, 0x17, 0xf3, 0x67, 0x14, - 0x03, 0x03, 0x00, 0x01, 0x01, 0x16, 0x03, 0x03, - 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x35, 0xcb, 0x17, 0x66, 0xee, 0xfd, - 0x27, 0xdb, 0xb8, 0xa8, 0x8a, 0xf1, 0x56, 0x67, - 0x89, 0x0d, 0x13, 0xac, 0xe2, 0x31, 0xb9, 0xa2, - 0x26, 0xbb, 0x1c, 0xcf, 0xd1, 0xb2, 0x48, 0x1d, - 0x0d, 0xb1, 0x17, 0x03, 0x03, 0x00, 0x25, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, - 0x89, 0x7c, 0x58, 0x6a, 0x9b, 0x00, 0x05, 0x8c, - 0x7f, 0x28, 0x54, 0x61, 0x44, 0x10, 0xee, 0x85, - 0x26, 0xa8, 0x04, 0xcd, 0xca, 0x85, 0x60, 0xf2, - 0xeb, 0x22, 0xbd, 0x9e, 0x15, 0x03, 0x03, 0x00, - 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x10, 0xe4, 0xe5, 0xf9, 0x85, 0xe3, 0xb0, - 0xec, 0x84, 0x29, 0x91, 0x05, 0x7d, 0x86, 0xe3, - 0x97, 0xeb, 0xb2, +} + +var testECDSAPrivateKey = &ecdsa.PrivateKey{ + PublicKey: ecdsa.PublicKey{ + Curve: elliptic.P521(), + X: bigFromString("2636411247892461147287360222306590634450676461695221912739908880441342231985950069527906976759812296359387337367668045707086543273113073382714101597903639351"), + Y: bigFromString("3204695818431246682253994090650952614555094516658732116404513121125038617915183037601737180082382202488628239201196033284060130040574800684774115478859677243"), }, + D: bigFromString("5477294338614160138026852784385529180817726002953041720191098180813046231640184669647735805135001309477695746518160084669446643325196003346204701381388769751"), } diff --git a/libgo/go/crypto/tls/handshake_test.go b/libgo/go/crypto/tls/handshake_test.go new file mode 100644 index 0000000000..f95f274ab4 --- /dev/null +++ b/libgo/go/crypto/tls/handshake_test.go @@ -0,0 +1,167 @@ +// 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 tls + +import ( + "bufio" + "encoding/hex" + "errors" + "flag" + "fmt" + "io" + "io/ioutil" + "net" + "strconv" + "strings" + "sync" +) + +// TLS reference tests run a connection against a reference implementation +// (OpenSSL) of TLS and record the bytes of the resulting connection. The Go +// code, during a test, is configured with deterministic randomness and so the +// reference test can be reproduced exactly in the future. +// +// In order to save everyone who wishes to run the tests from needing the +// reference implementation installed, the reference connections are saved in +// files in the testdata directory. Thus running the tests involves nothing +// external, but creating and updating them requires the reference +// implementation. +// +// Tests can be updated by running them with the -update flag. This will cause +// the test files. Generally one should combine the -update flag with -test.run +// to updated a specific test. Since the reference implementation will always +// generate fresh random numbers, large parts of the reference connection will +// always change. + +var update = flag.Bool("update", false, "update golden files on disk") + +// recordingConn is a net.Conn that records the traffic that passes through it. +// WriteTo can be used to produce output that can be later be loaded with +// ParseTestData. +type recordingConn struct { + net.Conn + sync.Mutex + flows [][]byte + reading bool +} + +func (r *recordingConn) Read(b []byte) (n int, err error) { + if n, err = r.Conn.Read(b); n == 0 { + return + } + b = b[:n] + + r.Lock() + defer r.Unlock() + + if l := len(r.flows); l == 0 || !r.reading { + buf := make([]byte, len(b)) + copy(buf, b) + r.flows = append(r.flows, buf) + } else { + r.flows[l-1] = append(r.flows[l-1], b[:n]...) + } + r.reading = true + return +} + +func (r *recordingConn) Write(b []byte) (n int, err error) { + if n, err = r.Conn.Write(b); n == 0 { + return + } + b = b[:n] + + r.Lock() + defer r.Unlock() + + if l := len(r.flows); l == 0 || r.reading { + buf := make([]byte, len(b)) + copy(buf, b) + r.flows = append(r.flows, buf) + } else { + r.flows[l-1] = append(r.flows[l-1], b[:n]...) + } + r.reading = false + return +} + +// WriteTo writes Go source code to w that contains the recorded traffic. +func (r *recordingConn) WriteTo(w io.Writer) { + // TLS always starts with a client to server flow. + clientToServer := true + + for i, flow := range r.flows { + source, dest := "client", "server" + if !clientToServer { + source, dest = dest, source + } + fmt.Fprintf(w, ">>> Flow %d (%s to %s)\n", i+1, source, dest) + dumper := hex.Dumper(w) + dumper.Write(flow) + dumper.Close() + clientToServer = !clientToServer + } +} + +func parseTestData(r io.Reader) (flows [][]byte, err error) { + var currentFlow []byte + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + line := scanner.Text() + // If the line starts with ">>> " then it marks the beginning + // of a new flow. + if strings.HasPrefix(line, ">>> ") { + if len(currentFlow) > 0 || len(flows) > 0 { + flows = append(flows, currentFlow) + currentFlow = nil + } + continue + } + + // Otherwise the line is a line of hex dump that looks like: + // 00000170 fc f5 06 bf (...) |.....X{&?......!| + // (Some bytes have been omitted from the middle section.) + + if i := strings.IndexByte(line, ' '); i >= 0 { + line = line[i:] + } else { + return nil, errors.New("invalid test data") + } + + if i := strings.IndexByte(line, '|'); i >= 0 { + line = line[:i] + } else { + return nil, errors.New("invalid test data") + } + + hexBytes := strings.Fields(line) + for _, hexByte := range hexBytes { + val, err := strconv.ParseUint(hexByte, 16, 8) + if err != nil { + return nil, errors.New("invalid hex byte in test data: " + err.Error()) + } + currentFlow = append(currentFlow, byte(val)) + } + } + + if len(currentFlow) > 0 { + flows = append(flows, currentFlow) + } + + return flows, nil +} + +// tempFile creates a temp file containing contents and returns its path. +func tempFile(contents string) string { + file, err := ioutil.TempFile("", "go-tls-test") + if err != nil { + panic("failed to create temp file: " + err.Error()) + } + path := file.Name() + file.WriteString(contents) + file.Close() + return path +} diff --git a/libgo/go/crypto/tls/key_agreement.go b/libgo/go/crypto/tls/key_agreement.go index 7e820c1e7e..0974fc6e0f 100644 --- a/libgo/go/crypto/tls/key_agreement.go +++ b/libgo/go/crypto/tls/key_agreement.go @@ -19,6 +19,9 @@ import ( "math/big" ) +var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message") +var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message") + // rsaKeyAgreement implements the standard TLS key agreement where the client // encrypts the pre-master secret to the server's public key. type rsaKeyAgreement struct{} @@ -35,14 +38,14 @@ func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certifi } if len(ckx.ciphertext) < 2 { - return nil, errors.New("bad ClientKeyExchange") + return nil, errClientKeyExchange } ciphertext := ckx.ciphertext if version != VersionSSL30 { ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1]) if ciphertextLen != len(ckx.ciphertext)-2 { - return nil, errors.New("bad ClientKeyExchange") + return nil, errClientKeyExchange } ciphertext = ckx.ciphertext[2:] } @@ -61,7 +64,7 @@ func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certifi } func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { - return errors.New("unexpected ServerKeyExchange") + return errors.New("tls: unexpected ServerKeyExchange") } func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { @@ -138,7 +141,7 @@ func hashForServerKeyExchange(sigType, hashFunc uint8, version uint16, slices .. // pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a // ServerKeyExchange given the signature type being used and the client's -// advertized list of supported signature and hash combinations. +// advertised list of supported signature and hash combinations. func pickTLS12HashForSignature(sigType uint8, clientSignatureAndHashes []signatureAndHash) (uint8, error) { if len(clientSignatureAndHashes) == 0 { // If the client didn't specify any signature_algorithms @@ -160,6 +163,20 @@ func pickTLS12HashForSignature(sigType uint8, clientSignatureAndHashes []signatu return 0, errors.New("tls: client doesn't support any common hash functions") } +func curveForCurveID(id CurveID) (elliptic.Curve, bool) { + switch id { + case CurveP256: + return elliptic.P256(), true + case CurveP384: + return elliptic.P384(), true + case CurveP521: + return elliptic.P521(), true + default: + return nil, false + } + +} + // ecdheRSAKeyAgreement implements a TLS key agreement where the server // generates a ephemeral EC public/private key pair and signs it. The // pre-master secret is then calculated using ECDH. The signature may @@ -173,23 +190,16 @@ type ecdheKeyAgreement struct { } func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { - var curveid uint16 - -Curve: - for _, c := range clientHello.supportedCurves { - switch c { - case curveP256: - ka.curve = elliptic.P256() - curveid = c - break Curve - case curveP384: - ka.curve = elliptic.P384() - curveid = c - break Curve - case curveP521: - ka.curve = elliptic.P521() - curveid = c - break Curve + var curveid CurveID + preferredCurves := config.curvePreferences() + +NextCandidate: + for _, candidate := range preferredCurves { + for _, c := range clientHello.supportedCurves { + if candidate == c { + curveid = c + break NextCandidate + } } } @@ -197,6 +207,11 @@ Curve: return nil, errors.New("tls: no supported elliptic curves offered") } + var ok bool + if ka.curve, ok = curveForCurveID(curveid); !ok { + return nil, errors.New("tls: preferredCurves includes unsupported curve") + } + var x, y *big.Int var err error ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand()) @@ -271,11 +286,14 @@ Curve: func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { - return nil, errors.New("bad ClientKeyExchange") + return nil, errClientKeyExchange } x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:]) if x == nil { - return nil, errors.New("bad ClientKeyExchange") + return nil, errClientKeyExchange + } + if !ka.curve.IsOnCurve(x, y) { + return nil, errClientKeyExchange } x, _ = ka.curve.ScalarMult(x, y, ka.privateKey) preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3) @@ -285,26 +303,18 @@ func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Cert return preMasterSecret, nil } -var errServerKeyExchange = errors.New("invalid ServerKeyExchange") - func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { if len(skx.key) < 4 { return errServerKeyExchange } if skx.key[0] != 3 { // named curve - return errors.New("server selected unsupported curve") + return errors.New("tls: server selected unsupported curve") } - curveid := uint16(skx.key[1])<<8 | uint16(skx.key[2]) + curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2]) - switch curveid { - case curveP256: - ka.curve = elliptic.P256() - case curveP384: - ka.curve = elliptic.P384() - case curveP521: - ka.curve = elliptic.P521() - default: - return errors.New("server selected unsupported curve") + var ok bool + if ka.curve, ok = curveForCurveID(curveid); !ok { + return errors.New("tls: server selected unsupported curve") } publicLen := int(skx.key[3]) @@ -315,6 +325,9 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell if ka.x == nil { return errServerKeyExchange } + if !ka.curve.IsOnCurve(ka.x, ka.y) { + return errServerKeyExchange + } serverECDHParams := skx.key[:4+publicLen] sig := skx.key[4+publicLen:] diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA new file mode 100644 index 0000000000..00722cba94 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA @@ -0,0 +1,129 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 53 04 f1 03 46 |....Y...U..S...F| +00000010 0f 84 c4 cb 55 ef 85 f6 4f d7 0e e1 4b 10 d4 bb |....U...O...K...| +00000020 35 87 2d f3 d7 18 ec 4e 95 4b f4 20 28 82 94 d9 |5.-....N.K. (...| +00000030 df c4 fc ee 21 23 c1 e2 76 3e 7b 09 af 2c 39 23 |....!#..v>{..,9#| +00000040 f8 46 6c 31 88 42 f0 79 de 37 2b 00 c0 09 00 00 |.Fl1.B.y.7+.....| +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....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +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 d5 0c 00 00 d1 03 00 17 41 04 4f |*............A.O| +00000280 47 16 72 98 9e 9f 2e 8e 78 e9 0f fe 95 83 7b aa |G.r.....x.....{.| +00000290 e5 3d c0 7d cf 83 bd 22 0b fd 48 f1 a7 49 a5 7d |.=.}..."..H..I.}| +000002a0 8e 0c 83 7f e1 2d 71 03 cc 90 09 ab f7 35 81 48 |.....-q......5.H| +000002b0 a4 1e 7d 87 21 23 12 58 2c 47 f3 af c7 6c 71 00 |..}.!#.X,G...lq.| +000002c0 8a 30 81 87 02 42 00 b4 03 38 60 43 d9 32 ef 64 |.0...B...8`C.2.d| +000002d0 5a 9c 91 95 0d 10 21 53 c7 78 f8 bf 50 ed 13 5d |Z.....!S.x..P..]| +000002e0 c3 e7 71 d6 11 04 f1 e4 9d ce 17 99 8d 1a 87 1f |..q.............| +000002f0 cb dd f8 1b ae cd bc 4a 77 ab 7c 50 bf 73 c3 ea |.......Jw.|P.s..| +00000300 d6 df 88 56 f6 b1 03 83 02 41 66 3d fb 4e 7e af |...V.....Af=.N~.| +00000310 4e c1 60 fe 09 fa 7e 74 99 66 7f de b4 b2 74 89 |N.`...~t.f....t.| +00000320 1c a4 cf 74 1a 55 a5 be 74 f9 36 21 3d ae c8 c3 |...t.U..t.6!=...| +00000330 24 8e ad db a3 26 67 8f 98 27 e3 93 ee d9 5c fb |$....&g..'....\.| +00000340 85 82 e2 13 c3 50 ab e9 f6 39 2b 16 03 01 00 0e |.....P...9+.....| +00000350 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |.......@......| +>>> Flow 3 (client to server) +00000000 16 03 01 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0| +00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5| +00000020 d9 17 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 |..0...*.H.=..0E1| +00000030 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 |.0...U....AU1.0.| +00000040 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 |..U....Some-Stat| +00000050 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 |e1!0...U....Inte| +00000060 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 |rnet Widgits Pty| +00000070 20 4c 74 64 30 1e 17 0d 31 32 31 31 31 34 31 33 | Ltd0...12111413| +00000080 32 35 35 33 5a 17 0d 32 32 31 31 31 32 31 33 32 |2553Z..221112132| +00000090 35 35 33 5a 30 41 31 0b 30 09 06 03 55 04 06 13 |553Z0A1.0...U...| +000000a0 02 41 55 31 0c 30 0a 06 03 55 04 08 13 03 4e 53 |.AU1.0...U....NS| +000000b0 57 31 10 30 0e 06 03 55 04 07 13 07 50 79 72 6d |W1.0...U....Pyrm| +000000c0 6f 6e 74 31 12 30 10 06 03 55 04 03 13 09 4a 6f |ont1.0...U....Jo| +000000d0 65 6c 20 53 69 6e 67 30 81 9b 30 10 06 07 2a 86 |el Sing0..0...*.| +000000e0 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| +000000f0 04 00 95 8c 91 75 14 c0 5e c4 57 b4 d4 c3 6f 8d |.....u..^.W...o.| +00000100 ae 68 1e dd 6f ce 86 e1 7e 6e b2 48 3e 81 e5 4e |.h..o...~n.H>..N| +00000110 e2 c6 88 4b 64 dc f5 30 bb d3 ff 65 cc 5b f4 dd |...Kd..0...e.[..| +00000120 b5 6a 3e 3e d0 1d de 47 c3 76 ad 19 f6 45 2c 8c |.j>>...G.v...E,.| +00000130 bc d8 1d 01 4c 1f 70 90 46 76 48 8b 8f 83 cc 4a |....L.p.FvH....J| +00000140 5c 8f 40 76 da e0 89 ec 1d 2b c4 4e 30 76 28 41 |\.@v.....+.N0v(A| +00000150 b2 62 a8 fb 5b f1 f9 4e 7a 8d bd 09 b8 ae ea 8b |.b..[..Nz.......| +00000160 18 27 4f 2e 70 fe 13 96 ba c3 d3 40 16 cd 65 4e |.'O.p......@..eN| +00000170 ac 11 1e e6 f1 30 09 06 07 2a 86 48 ce 3d 04 01 |.....0...*.H.=..| +00000180 03 81 8c 00 30 81 88 02 42 00 e0 14 c4 60 60 0b |....0...B....``.| +00000190 72 68 b0 32 5d 61 4a 02 74 5c c2 81 b9 16 a8 3f |rh.2]aJ.t\.....?| +000001a0 29 c8 36 c7 81 ff 6c b6 5b d9 70 f1 38 3b 50 48 |).6...l.[.p.8;PH| +000001b0 28 94 cb 09 1a 52 f1 5d ee 8d f2 b9 f0 f0 da d9 |(....R.]........| +000001c0 15 3a f9 bd 03 7a 87 a2 23 35 ec 02 42 01 a3 d4 |.:...z..#5..B...| +000001d0 8a 78 35 1c 4a 9a 23 d2 0a be 2b 10 31 9d 9c 5f |.x5.J.#...+.1.._| +000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.| +000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W| +00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| +00000210 03 01 00 46 10 00 00 42 41 04 1e 18 37 ef 0d 19 |...F...BA...7...| +00000220 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..| +00000230 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..| +00000240 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.| +00000250 b5 68 1a 41 03 56 6b dc 5a 89 16 03 01 00 90 0f |.h.A.Vk.Z.......| +00000260 00 00 8c 00 8a 30 81 87 02 42 00 c6 85 8e 06 b7 |.....0...B......| +00000270 04 04 e9 cd 9e 3e cb 66 23 95 b4 42 9c 64 81 39 |.....>.f#..B.d.9| +00000280 05 3f b5 21 f8 28 af 60 6b 4d 3d ba a1 4b 5e 77 |.?.!.(.`kM=..K^w| +00000290 ef e7 59 28 fe 1d c1 27 a2 ff a8 de 33 48 b3 c1 |..Y(...'....3H..| +000002a0 85 6a 42 9b f9 7e 7e 31 c2 e5 bd 66 02 41 4b 49 |.jB..~~1...f.AKI| +000002b0 c6 cd 02 e3 83 f7 03 50 18 6d b4 c9 51 02 c0 ab |.......P.m..Q...| +000002c0 87 bc e0 3e 4b 89 53 3a e2 65 89 97 02 c1 87 f1 |...>K.S:.e......| +000002d0 67 d0 f2 06 28 4e 51 4e fd f0 01 be 41 3c 52 42 |g...(NQN....AD$..w.wo...| +000002f0 03 01 00 01 01 16 03 01 00 30 a3 da 45 22 96 83 |.........0..E"..| +00000300 59 90 e9 6b ec 3b 77 50 05 89 e6 0c 61 d1 1d 2b |Y..k.;wP....a..+| +00000310 da d4 49 bf b9 c6 dd ad c3 9c 82 bd 53 62 e8 57 |..I.........Sb.W| +00000320 a4 6a e7 9f b1 d5 39 77 88 6d |.j....9w.m| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 a4 45 dd 99 df |..........0.E...| +00000010 66 ae f5 c7 bd 1a eb 6a ff ac a6 38 14 81 b5 07 |f......j...8....| +00000020 86 24 80 f1 09 59 ad 33 3d 43 ed 9e 43 b1 1e 9f |.$...Y.3=C..C...| +00000030 bd 8c b3 e0 41 83 a1 34 91 c5 a1 |....A..4...| +>>> Flow 5 (client to server) +00000000 17 03 01 00 20 ae e3 ae 7f 2d e3 a2 f7 1b 4e 69 |.... ....-....Ni| +00000010 cb 18 c6 68 42 f8 de 61 92 4c fa d6 19 7c 8c 09 |...hB..a.L...|..| +00000020 82 e2 f2 32 19 17 03 01 00 20 2a 77 65 1f c1 fd |...2..... *we...| +00000030 5e 37 b7 15 f6 1f 4c 7f 5f 89 52 b4 32 27 4d 17 |^7....L._.R.2'M.| +00000040 33 c6 e8 50 ac 70 c8 b9 2d 0a 15 03 01 00 20 e0 |3..P.p..-..... .| +00000050 cb ce 07 80 55 a0 46 ca a7 25 4c 5f 9d 7c 73 37 |....U.F..%L_.|s7| +00000060 de 72 6d 36 a8 e4 be fd 2a e7 f8 8d 14 80 b7 |.rm6....*......| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA new file mode 100644 index 0000000000..c0be82491e --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA @@ -0,0 +1,125 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 51 02 00 00 4d 03 01 53 04 f1 02 ed |....Q...M..S....| +00000010 86 9c 56 84 5a d3 7d d7 f3 4e 6f 2c 69 0d f0 59 |..V.Z.}..No,i..Y| +00000020 a5 d1 de 2d 03 2f dd 63 c3 ab fa 20 30 d6 5a 24 |...-./.c... 0.Z$| +00000030 5c 31 67 36 8d 4c 43 e1 64 c4 8a 2c a5 fd 39 92 |\1g6.LC.d..,..9.| +00000040 c5 6f 58 47 a3 fe 63 14 98 92 11 90 00 05 00 00 |.oXG..c.........| +00000050 05 ff 01 00 01 00 16 03 01 02 be 0b 00 02 ba 00 |................| +00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 01 00 0e 0d 00 |n8P)l...........| +00000320 00 06 03 01 02 40 00 00 0e 00 00 00 |.....@......| +>>> Flow 3 (client to server) +00000000 16 03 01 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0| +00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5| +00000020 d9 17 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 |..0...*.H.=..0E1| +00000030 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 |.0...U....AU1.0.| +00000040 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 |..U....Some-Stat| +00000050 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 |e1!0...U....Inte| +00000060 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 |rnet Widgits Pty| +00000070 20 4c 74 64 30 1e 17 0d 31 32 31 31 31 34 31 33 | Ltd0...12111413| +00000080 32 35 35 33 5a 17 0d 32 32 31 31 31 32 31 33 32 |2553Z..221112132| +00000090 35 35 33 5a 30 41 31 0b 30 09 06 03 55 04 06 13 |553Z0A1.0...U...| +000000a0 02 41 55 31 0c 30 0a 06 03 55 04 08 13 03 4e 53 |.AU1.0...U....NS| +000000b0 57 31 10 30 0e 06 03 55 04 07 13 07 50 79 72 6d |W1.0...U....Pyrm| +000000c0 6f 6e 74 31 12 30 10 06 03 55 04 03 13 09 4a 6f |ont1.0...U....Jo| +000000d0 65 6c 20 53 69 6e 67 30 81 9b 30 10 06 07 2a 86 |el Sing0..0...*.| +000000e0 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| +000000f0 04 00 95 8c 91 75 14 c0 5e c4 57 b4 d4 c3 6f 8d |.....u..^.W...o.| +00000100 ae 68 1e dd 6f ce 86 e1 7e 6e b2 48 3e 81 e5 4e |.h..o...~n.H>..N| +00000110 e2 c6 88 4b 64 dc f5 30 bb d3 ff 65 cc 5b f4 dd |...Kd..0...e.[..| +00000120 b5 6a 3e 3e d0 1d de 47 c3 76 ad 19 f6 45 2c 8c |.j>>...G.v...E,.| +00000130 bc d8 1d 01 4c 1f 70 90 46 76 48 8b 8f 83 cc 4a |....L.p.FvH....J| +00000140 5c 8f 40 76 da e0 89 ec 1d 2b c4 4e 30 76 28 41 |\.@v.....+.N0v(A| +00000150 b2 62 a8 fb 5b f1 f9 4e 7a 8d bd 09 b8 ae ea 8b |.b..[..Nz.......| +00000160 18 27 4f 2e 70 fe 13 96 ba c3 d3 40 16 cd 65 4e |.'O.p......@..eN| +00000170 ac 11 1e e6 f1 30 09 06 07 2a 86 48 ce 3d 04 01 |.....0...*.H.=..| +00000180 03 81 8c 00 30 81 88 02 42 00 e0 14 c4 60 60 0b |....0...B....``.| +00000190 72 68 b0 32 5d 61 4a 02 74 5c c2 81 b9 16 a8 3f |rh.2]aJ.t\.....?| +000001a0 29 c8 36 c7 81 ff 6c b6 5b d9 70 f1 38 3b 50 48 |).6...l.[.p.8;PH| +000001b0 28 94 cb 09 1a 52 f1 5d ee 8d f2 b9 f0 f0 da d9 |(....R.]........| +000001c0 15 3a f9 bd 03 7a 87 a2 23 35 ec 02 42 01 a3 d4 |.:...z..#5..B...| +000001d0 8a 78 35 1c 4a 9a 23 d2 0a be 2b 10 31 9d 9c 5f |.x5.J.#...+.1.._| +000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.| +000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W| +00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| +00000210 03 01 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 3e |..........mQ...>| +00000220 fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c 8e |.u.A6..j.*.%.gL.| +00000230 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 1d |b/0......+.#....| +00000240 f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 0d |.;...'..$...[.f.| +00000250 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be c8 |j.....C.........| +00000260 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce e6 |.9L.....K.../...| +00000270 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 f1 |.w.o#......:..V.| +00000280 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 35 |.T^F..;3..(....5| +00000290 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 01 00 90 0f |..C.0oUN.p......| +000002a0 00 00 8c 00 8a 30 81 87 02 42 00 c6 85 8e 06 b7 |.....0...B......| +000002b0 04 04 e9 cd 9e 3e cb 66 23 95 b4 42 9c 64 81 39 |.....>.f#..B.d.9| +000002c0 05 3f b5 21 f8 28 af 60 6b 4d 3d ba a1 4b 5e 77 |.?.!.(.`kM=..K^w| +000002d0 ef e7 59 28 fe 1d c1 27 a2 ff a8 de 33 48 b3 c1 |..Y(...'....3H..| +000002e0 85 6a 42 9b f9 7e 7e 31 c2 e5 bd 66 02 41 4b 49 |.jB..~~1...f.AKI| +000002f0 c6 cd 02 e3 83 f7 03 50 18 6d b4 c9 51 02 c0 ab |.......P.m..Q...| +00000300 87 bc e0 3e 4b 89 53 3a e2 65 89 97 02 c1 87 f1 |...>K.S:.e......| +00000310 67 d0 f2 06 28 4e 51 4e fd f0 01 47 e7 c9 d9 23 |g...(NQN...G...#| +00000320 21 6b 87 d2 55 e3 c9 f7 eb 86 d5 1e 50 df d5 14 |!k..U.......P...| +00000330 03 01 00 01 01 16 03 01 00 24 95 62 42 be 90 39 |.........$.bB..9| +00000340 68 ae f5 77 47 21 14 b9 ac ee 81 2d e3 9e c7 34 |h..wG!.....-...4| +00000350 3a 00 5c c9 12 1d c0 5a 7c e7 ef e0 cd fd |:.\....Z|.....| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 24 ea 98 c0 fb 86 |..........$.....| +00000010 87 7a 2e e1 c7 68 61 3e 5b cc da 1f d6 7b ab 5a |.z...ha>[....{.Z| +00000020 a0 ae a2 cf d0 54 44 19 12 db 75 2b 8c 73 8c |.....TD...u+.s.| +>>> Flow 5 (client to server) +00000000 17 03 01 00 1a f3 28 77 31 33 4c b3 7c 4b 75 61 |......(w13L.|Kua| +00000010 38 69 6b ae c9 36 ab 2e 56 16 29 6a 9a 00 2f 15 |8ik..6..V.)j../.| +00000020 03 01 00 16 6b ed 68 18 ed ff 44 39 9b 4a e4 a2 |....k.h...D9.J..| +00000030 cd 79 ef 2a 3e 5a 4d b1 5d 56 |.y.*>ZM.]V| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA new file mode 100644 index 0000000000..3e6dbc271a --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA @@ -0,0 +1,128 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 53 04 f1 02 4f |....Y...U..S...O| +00000010 73 06 2d 72 41 36 a1 b2 d3 50 97 55 8c c5 f1 43 |s.-rA6...P.U...C| +00000020 37 1f 1a 2a fe 51 70 0b 2f 25 9e 20 50 61 86 80 |7..*.Qp./%. Pa..| +00000030 9a 9c 6d 6f c9 ea 5c ce 0c b7 7c ce e3 be d0 e5 |..mo..\...|.....| +00000040 be d0 c4 80 78 c3 c7 17 0c 2d 8e c8 c0 09 00 00 |....x....-......| +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....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +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 d6 0c 00 00 d2 03 00 17 41 04 b1 |*............A..| +00000280 0f 0f 4a 18 ed 25 32 b3 a3 19 ed 4b 61 b6 eb e4 |..J..%2....Ka...| +00000290 d3 f7 77 13 ac 9f 60 c7 8d 6d cb f1 ee 99 1a 71 |..w...`..m.....q| +000002a0 68 aa d3 a7 70 7f 38 d0 f6 23 ab 9a f6 dd 19 4f |h...p.8..#.....O| +000002b0 ce 10 ef d5 cf 64 85 2f 75 f6 20 06 4b f0 b9 00 |.....d./u. .K...| +000002c0 8b 30 81 88 02 42 01 00 b9 6b 80 91 59 0a 48 3f |.0...B...k..Y.H?| +000002d0 72 16 96 8f 21 2c 28 e4 6d 03 74 66 35 16 7d ec |r...!,(.m.tf5.}.| +000002e0 c7 08 9b 52 b5 05 d9 38 d8 b7 51 42 a7 4a 9f 9b |...R...8..QB.J..| +000002f0 1a 37 14 de c5 f5 16 96 83 81 58 d3 a6 1e ce 8a |.7........X.....| +00000300 bc 19 47 30 fe c5 85 55 02 42 01 4f 61 59 68 85 |..G0...U.B.OaYh.| +00000310 c7 64 23 22 f6 83 53 cc 58 38 25 b5 ce 74 c1 68 |.d#"..S.X8%..t.h| +00000320 9f 32 72 33 ea c9 62 e0 26 63 92 e3 5f 34 10 0b |.2r3..b.&c.._4..| +00000330 3c d5 83 fe 9f 67 69 ef 33 6b 19 c1 ec d6 6c 35 |<....gi.3k....l5| +00000340 89 33 17 d3 9d 93 e2 e5 6e 89 9a a1 16 03 01 00 |.3......n.......| +00000350 0e 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |........@......| +>>> Flow 3 (client to server) +00000000 16 03 01 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0| +00000010 82 01 ed 30 82 01 58 a0 03 02 01 02 02 01 00 30 |...0..X........0| +00000020 0b 06 09 2a 86 48 86 f7 0d 01 01 05 30 26 31 10 |...*.H......0&1.| +00000030 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 6f |0...U....Acme Co| +00000040 31 12 30 10 06 03 55 04 03 13 09 31 32 37 2e 30 |1.0...U....127.0| +00000050 2e 30 2e 31 30 1e 17 0d 31 31 31 32 30 38 30 37 |.0.10...11120807| +00000060 35 35 31 32 5a 17 0d 31 32 31 32 30 37 30 38 30 |5512Z..121207080| +00000070 30 31 32 5a 30 26 31 10 30 0e 06 03 55 04 0a 13 |012Z0&1.0...U...| +00000080 07 41 63 6d 65 20 43 6f 31 12 30 10 06 03 55 04 |.Acme Co1.0...U.| +00000090 03 13 09 31 32 37 2e 30 2e 30 2e 31 30 81 9c 30 |...127.0.0.10..0| +000000a0 0b 06 09 2a 86 48 86 f7 0d 01 01 01 03 81 8c 00 |...*.H..........| +000000b0 30 81 88 02 81 80 4e d0 7b 31 e3 82 64 d9 59 c0 |0.....N.{1..d.Y.| +000000c0 c2 87 a4 5e 1e 8b 73 33 c7 63 53 df 66 92 06 84 |...^..s3.cS.f...| +000000d0 f6 64 d5 8f e4 36 a7 1d 2b e8 b3 20 36 45 23 b5 |.d...6..+.. 6E#.| +000000e0 e3 95 ae ed e0 f5 20 9c 8d 95 df 7f 5a 12 ef 87 |...... .....Z...| +000000f0 e4 5b 68 e4 e9 0e 74 ec 04 8a 7f de 93 27 c4 01 |.[h...t......'..| +00000100 19 7a bd f2 dc 3d 14 ab d0 54 ca 21 0c d0 4d 6e |.z...=...T.!..Mn| +00000110 87 2e 5c c5 d2 bb 4d 4b 4f ce b6 2c f7 7e 88 ec |..\...MKO..,.~..| +00000120 7c d7 02 91 74 a6 1e 0c 1a da e3 4a 5a 2e de 13 ||...t......JZ...| +00000130 9c 4c 40 88 59 93 02 03 01 00 01 a3 32 30 30 30 |.L@.Y.......2000| +00000140 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 00 a0 30 |...U...........0| +00000150 0d 06 03 55 1d 0e 04 06 04 04 01 02 03 04 30 0f |...U..........0.| +00000160 06 03 55 1d 23 04 08 30 06 80 04 01 02 03 04 30 |..U.#..0.......0| +00000170 0b 06 09 2a 86 48 86 f7 0d 01 01 05 03 81 81 00 |...*.H..........| +00000180 36 1f b3 7a 0c 75 c9 6e 37 46 61 2b d5 bd c0 a7 |6..z.u.n7Fa+....| +00000190 4b cc 46 9a 81 58 7c 85 79 29 c8 c8 c6 67 dd 32 |K.F..X|.y)...g.2| +000001a0 56 45 2b 75 b6 e9 24 a9 50 9a be 1f 5a fa 1a 15 |VE+u..$.P...Z...| +000001b0 d9 cc 55 95 72 16 83 b9 c2 b6 8f fd 88 8c 38 84 |..U.r.........8.| +000001c0 1d ab 5d 92 31 13 4f fd 83 3b c6 9d f1 11 62 b6 |..].1.O..;....b.| +000001d0 8b ec ab 67 be c8 64 b0 11 50 46 58 17 6b 99 1c |...g..d..PFX.k..| +000001e0 d3 1d fc 06 f1 0e e5 96 a8 0c f9 78 20 b7 44 18 |...........x .D.| +000001f0 51 8d 10 7e 4f 94 67 df a3 4e 70 73 8e 90 91 85 |Q..~O.g..Nps....| +00000200 16 03 01 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| +00000210 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +00000220 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.| +00000230 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I| +00000240 a6 b5 68 1a 41 03 56 6b dc 5a 89 16 03 01 00 86 |..h.A.Vk.Z......| +00000250 0f 00 00 82 00 80 20 2c 5a 08 3a 00 33 50 19 b2 |...... ,Z.:.3P..| +00000260 0f ba 6c 76 7f 5c 92 e2 78 55 3e 32 32 bb 33 bc |..lv.\..xU>22.3.| +00000270 ab a9 34 e0 83 cf 82 cd 9e 6b 3f 9d e6 49 61 29 |..4......k?..Ia)| +00000280 8b b4 ed e8 12 cd a9 52 86 11 48 64 08 61 72 8d |.......R..Hd.ar.| +00000290 d6 6a ac 42 cc e4 07 5f 08 56 9f 2f c5 35 d3 9b |.j.B..._.V./.5..| +000002a0 e9 0d 91 82 c0 e9 bb 9f a9 8f df 96 85 08 9a 69 |...............i| +000002b0 a4 93 b3 72 37 ba f9 b1 a4 0b b0 9f 43 6a 15 ec |...r7.......Cj..| +000002c0 79 b8 fd 9c 1f 5f 0d 2c 56 33 c7 15 d5 4a b7 82 |y...._.,V3...J..| +000002d0 ea 44 80 20 c5 80 14 03 01 00 01 01 16 03 01 00 |.D. ............| +000002e0 30 c9 c0 7c d7 57 d3 00 ab 87 eb 78 56 6b a1 69 |0..|.W.....xVk.i| +000002f0 1d fa ec ae 38 f3 ef 5d 49 19 0d 4b f0 73 63 af |....8..]I..K.sc.| +00000300 89 b6 cb 76 cf fb b9 c1 99 98 06 0a 54 67 a0 6e |...v........Tg.n| +00000310 e7 |.| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 20 db fd ed ed |..........0 ....| +00000010 7c d5 bf 8f 06 3b 86 1b c1 60 7d a4 74 e9 a6 c9 ||....;...`}.t...| +00000020 f5 7c c7 f4 65 91 06 d5 53 88 d7 57 a4 22 b6 1f |.|..e...S..W."..| +00000030 f1 02 e9 79 36 e6 a1 22 51 3a 4c |...y6.."Q:L| +>>> Flow 5 (client to server) +00000000 17 03 01 00 20 00 66 51 6a 14 ca ea e2 21 48 74 |.... .fQj....!Ht| +00000010 c4 c1 6e b9 8b 23 af 7c 33 c9 00 f8 0b ec ab 35 |..n..#.|3......5| +00000020 e7 42 0a d1 ae 17 03 01 00 20 00 1c 6d 60 75 5d |.B....... ..m`u]| +00000030 b3 fb 40 2e e0 b7 0d 48 f4 87 ac d4 bf ea 01 0d |..@....H........| +00000040 fe 10 0d 05 04 43 6b 19 ed f2 15 03 01 00 20 f8 |.....Ck....... .| +00000050 03 ac 62 4b 1f db 2e d2 4e 00 c3 a4 57 3c 0a 62 |..bK....N...W<.b| +00000060 05 a0 ef bd 2b 9b 9a 63 27 72 d7 d8 f1 8d 84 |....+..c'r.....| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA new file mode 100644 index 0000000000..94e686004f --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA @@ -0,0 +1,124 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 51 02 00 00 4d 03 01 53 04 f1 02 73 |....Q...M..S...s| +00000010 ee 5f 70 a4 aa 0d be d7 46 a3 25 3f e3 5d ef 7b |._p.....F.%?.].{| +00000020 73 49 7c b6 82 4d 99 2f 31 fc 8b 20 2d a3 33 7c |sI|..M./1.. -.3|| +00000030 a5 c3 85 86 ba 61 4d 05 b0 5e d3 5e 88 6e c3 4b |.....aM..^.^.n.K| +00000040 95 d3 e9 67 f1 96 24 58 7a 6f e6 c5 00 05 00 00 |...g..$Xzo......| +00000050 05 ff 01 00 01 00 16 03 01 02 be 0b 00 02 ba 00 |................| +00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 01 00 0e 0d 00 |n8P)l...........| +00000320 00 06 03 01 02 40 00 00 0e 00 00 00 |.....@......| +>>> Flow 3 (client to server) +00000000 16 03 01 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0| +00000010 82 01 ed 30 82 01 58 a0 03 02 01 02 02 01 00 30 |...0..X........0| +00000020 0b 06 09 2a 86 48 86 f7 0d 01 01 05 30 26 31 10 |...*.H......0&1.| +00000030 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 6f |0...U....Acme Co| +00000040 31 12 30 10 06 03 55 04 03 13 09 31 32 37 2e 30 |1.0...U....127.0| +00000050 2e 30 2e 31 30 1e 17 0d 31 31 31 32 30 38 30 37 |.0.10...11120807| +00000060 35 35 31 32 5a 17 0d 31 32 31 32 30 37 30 38 30 |5512Z..121207080| +00000070 30 31 32 5a 30 26 31 10 30 0e 06 03 55 04 0a 13 |012Z0&1.0...U...| +00000080 07 41 63 6d 65 20 43 6f 31 12 30 10 06 03 55 04 |.Acme Co1.0...U.| +00000090 03 13 09 31 32 37 2e 30 2e 30 2e 31 30 81 9c 30 |...127.0.0.10..0| +000000a0 0b 06 09 2a 86 48 86 f7 0d 01 01 01 03 81 8c 00 |...*.H..........| +000000b0 30 81 88 02 81 80 4e d0 7b 31 e3 82 64 d9 59 c0 |0.....N.{1..d.Y.| +000000c0 c2 87 a4 5e 1e 8b 73 33 c7 63 53 df 66 92 06 84 |...^..s3.cS.f...| +000000d0 f6 64 d5 8f e4 36 a7 1d 2b e8 b3 20 36 45 23 b5 |.d...6..+.. 6E#.| +000000e0 e3 95 ae ed e0 f5 20 9c 8d 95 df 7f 5a 12 ef 87 |...... .....Z...| +000000f0 e4 5b 68 e4 e9 0e 74 ec 04 8a 7f de 93 27 c4 01 |.[h...t......'..| +00000100 19 7a bd f2 dc 3d 14 ab d0 54 ca 21 0c d0 4d 6e |.z...=...T.!..Mn| +00000110 87 2e 5c c5 d2 bb 4d 4b 4f ce b6 2c f7 7e 88 ec |..\...MKO..,.~..| +00000120 7c d7 02 91 74 a6 1e 0c 1a da e3 4a 5a 2e de 13 ||...t......JZ...| +00000130 9c 4c 40 88 59 93 02 03 01 00 01 a3 32 30 30 30 |.L@.Y.......2000| +00000140 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 00 a0 30 |...U...........0| +00000150 0d 06 03 55 1d 0e 04 06 04 04 01 02 03 04 30 0f |...U..........0.| +00000160 06 03 55 1d 23 04 08 30 06 80 04 01 02 03 04 30 |..U.#..0.......0| +00000170 0b 06 09 2a 86 48 86 f7 0d 01 01 05 03 81 81 00 |...*.H..........| +00000180 36 1f b3 7a 0c 75 c9 6e 37 46 61 2b d5 bd c0 a7 |6..z.u.n7Fa+....| +00000190 4b cc 46 9a 81 58 7c 85 79 29 c8 c8 c6 67 dd 32 |K.F..X|.y)...g.2| +000001a0 56 45 2b 75 b6 e9 24 a9 50 9a be 1f 5a fa 1a 15 |VE+u..$.P...Z...| +000001b0 d9 cc 55 95 72 16 83 b9 c2 b6 8f fd 88 8c 38 84 |..U.r.........8.| +000001c0 1d ab 5d 92 31 13 4f fd 83 3b c6 9d f1 11 62 b6 |..].1.O..;....b.| +000001d0 8b ec ab 67 be c8 64 b0 11 50 46 58 17 6b 99 1c |...g..d..PFX.k..| +000001e0 d3 1d fc 06 f1 0e e5 96 a8 0c f9 78 20 b7 44 18 |...........x .D.| +000001f0 51 8d 10 7e 4f 94 67 df a3 4e 70 73 8e 90 91 85 |Q..~O.g..Nps....| +00000200 16 03 01 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 |...........mQ...| +00000210 3e fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c |>.u.A6..j.*.%.gL| +00000220 8e 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 |.b/0......+.#...| +00000230 1d f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 |..;...'..$...[.f| +00000240 0d 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be |.j.....C........| +00000250 c8 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce |..9L.....K.../..| +00000260 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V| +00000270 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....| +00000280 35 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 01 00 86 |5..C.0oUN.p.....| +00000290 0f 00 00 82 00 80 0f 4c d2 b2 f0 94 6d 61 d1 2c |.......L....ma.,| +000002a0 db 6f 79 03 bd 40 b2 d2 1d 61 ef 83 1b 4a 0c 7b |.oy..@...a...J.{| +000002b0 c5 73 1e 1a 81 e7 67 0a d6 aa 2d 04 04 cc 0e 4b |.s....g...-....K| +000002c0 2e da 96 7f 15 6c 05 ee c4 53 7e 33 89 28 7d db |.....l...S~3.(}.| +000002d0 a1 77 43 ba a3 51 a9 1c b9 f5 ec 9a 8d eb 2c 46 |.wC..Q........,F| +000002e0 5c 33 59 6b 16 af de f4 9b 80 76 a3 22 30 5d bb |\3Yk......v."0].| +000002f0 02 b9 77 96 8a db 36 9f 54 95 00 d8 58 e1 aa 04 |..w...6.T...X...| +00000300 98 c9 0c 32 ae 62 81 12 0c f6 1b 76 c6 58 a7 8c |...2.b.....v.X..| +00000310 0e d8 b7 8e ed 0f 14 03 01 00 01 01 16 03 01 00 |................| +00000320 24 1d c0 20 02 2d da 69 54 29 8c ff af 5c 56 a8 |$.. .-.iT)...\V.| +00000330 eb d0 09 95 29 8f 52 8c e2 7b 9f 36 3e 47 a0 33 |....).R..{.6>G.3| +00000340 2e 63 a2 24 93 |.c.$.| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 24 99 e8 fb 65 f4 |..........$...e.| +00000010 95 ae 8b 71 cc 5d a4 95 a7 27 98 fd 16 3f 7a 1a |...q.]...'...?z.| +00000020 b6 bd bf 0a 58 72 77 97 1f 8e b1 dd 4b 12 12 |....Xrw.....K..| +>>> Flow 5 (client to server) +00000000 17 03 01 00 1a 42 70 c0 89 78 12 5c 91 7e 88 2d |.....Bp..x.\.~.-| +00000010 2f 8f be f2 f2 12 9d 81 ae 78 08 38 5e 6d 1b 15 |/........x.8^m..| +00000020 03 01 00 16 1a 64 b1 6f 8a ff d3 63 6a c7 b8 95 |.....d.o...cj...| +00000030 3d b0 87 bc 62 e9 88 5b 26 bd |=...b..[&.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES new file mode 100644 index 0000000000..30c4c6b831 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES @@ -0,0 +1,87 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 53 04 f1 02 b2 |....Y...U..S....| +00000010 e0 f6 f6 b5 c9 5b 28 d0 5d 58 1b 6f 4e 2b 9d 05 |.....[(.]X.oN+..| +00000020 2a b9 b4 da 45 cf f3 10 b2 23 44 20 f8 4d 59 05 |*...E....#D .MY.| +00000030 ad 27 f2 a0 ee 7f ec cc 20 dc e7 a2 1b 07 b3 a5 |.'...... .......| +00000040 37 7e 61 3d d6 5c 03 cf cc f5 9b ca c0 09 00 00 |7~a=.\..........| +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....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +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 d5 0c 00 00 d1 03 00 17 41 04 da |*............A..| +00000280 5a fd 09 e5 d6 c0 70 41 5e 3a 87 eb df 0c ad 90 |Z.....pA^:......| +00000290 22 8a 2f 90 81 0c 24 00 68 92 f3 d5 95 2f 93 43 |"./...$.h..../.C| +000002a0 e9 58 2d 18 28 62 ee 33 5b 21 2e 49 87 21 4d 32 |.X-.(b.3[!.I.!M2| +000002b0 32 19 b3 ba fe 2d 9a 85 12 0e a1 77 08 06 75 00 |2....-.....w..u.| +000002c0 8a 30 81 87 02 42 01 91 14 fc 68 74 95 10 4b d4 |.0...B....ht..K.| +000002d0 67 60 12 46 bb b0 f6 98 77 a3 41 b8 01 5c 49 54 |g`.F....w.A..\IT| +000002e0 9e 3e 81 e7 97 a3 b9 73 6e 15 74 67 be e5 d9 eb |.>.....sn.tg....| +000002f0 8b 87 c5 22 ab ab 58 28 4f d1 b6 80 94 1b f5 f7 |..."..X(O.......| +00000300 12 43 ef 0a c7 3e 1a 76 02 41 7a 00 49 cb 9f 3b |.C...>.v.Az.I..;| +00000310 91 6e 38 58 0a d3 d0 d1 ee 67 f0 b6 5d cd fa 23 |.n8X.....g..]..#| +00000320 b6 98 43 af 9c 71 90 1e 1d 50 a2 6e 61 5b f2 92 |..C..q...P.na[..| +00000330 b4 69 73 f2 3b 54 bf 1c 9d 05 19 97 e4 4e 41 9e |.is.;T.......NA.| +00000340 f2 9a 76 77 9a 86 43 1f 1f 30 a2 16 03 01 00 04 |..vw..C..0......| +00000350 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 01 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +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 01 00 01 |..h.A.Vk.Z......| +00000050 01 16 03 01 00 30 88 60 65 b2 d7 51 1f ad 96 56 |.....0.`e..Q...V| +00000060 4e 0a 20 eb b5 b0 1a dd 4c f6 1a cf d4 5c 47 c4 |N. .....L....\G.| +00000070 9c 7c a0 36 dd d1 1b 96 91 99 c0 a7 2d 9a 7c 42 |.|.6........-.|B| +00000080 51 d1 de 87 2b a4 |Q...+.| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 86 6c b5 94 69 |..........0.l..i| +00000010 2e e0 55 a2 4d a8 63 f2 5b 1f ae 34 21 c8 21 6a |..U.M.c.[..4!.!j| +00000020 00 b6 56 ed 4e 2a b0 ff 01 2f da ce a1 c0 41 03 |..V.N*.../....A.| +00000030 a9 1b 6e 2e e1 88 50 ba 62 14 88 |..n...P.b..| +>>> Flow 5 (client to server) +00000000 17 03 01 00 20 a6 63 0a 2f a5 dc e1 fb cb 7b 1f |.... .c./.....{.| +00000010 f2 da 74 c3 ff e9 f5 8b 9c 5f 0c d3 f7 1f 44 e6 |..t......_....D.| +00000020 90 13 5c 48 50 17 03 01 00 20 c7 75 b5 ff bc 09 |..\HP.... .u....| +00000030 34 f2 45 db 0d 22 08 8e f1 35 cd b6 0f b0 eb 2a |4.E.."...5.....*| +00000040 b7 1a d0 8e 14 a4 54 84 f9 dc 15 03 01 00 20 e0 |......T....... .| +00000050 36 3d aa b3 a9 b4 20 23 ca 9e 8c 5d fc a8 c8 b7 |6=.... #...]....| +00000060 f5 c2 b6 d0 5a e2 ce a5 7b 68 a0 48 86 95 6a |....Z...{h.H..j| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES new file mode 100644 index 0000000000..868f0ceb0e --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES @@ -0,0 +1,97 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 53 04 f1 02 21 |....Y...U..S...!| +00000010 67 b5 2b 34 fb 62 d7 36 4f cf 68 2e 29 39 d0 28 |g.+4.b.6O.h.)9.(| +00000020 3a 02 32 82 8f 95 de 62 d6 03 77 20 e6 98 56 cd |:.2....b..w ..V.| +00000030 96 24 d1 b9 4d eb 51 19 bb b7 71 f4 9c 29 32 d4 |.$..M.Q...q..)2.| +00000040 e5 c6 0a 54 e0 4a 20 29 3e bd 06 0d c0 13 00 00 |...T.J )>.......| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 01 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..| +00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............| +00000080 a4 8a 7f b8 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....| +00000090 01 05 05 00 30 45 31 0b 30 09 06 03 55 04 06 13 |....0E1.0...U...| +000000a0 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f |.AU1.0...U....So| +000000b0 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 |me-State1!0...U.| +000000c0 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 |...Internet Widg| +000000d0 69 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 |its Pty Ltd0...1| +000000e0 30 30 34 32 34 30 39 30 39 33 38 5a 17 0d 31 31 |00424090938Z..11| +000000f0 30 34 32 34 30 39 30 39 33 38 5a 30 45 31 0b 30 |0424090938Z0E1.0| +00000100 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +00000110 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +00000120 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +00000130 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +00000140 74 64 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 |td0..0...*.H....| +00000150 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 bb |........0.......| +00000160 79 d6 f5 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 |y......F...i..+.| +00000170 43 5a d0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c |CZ..-.zC...R..eL| +00000180 2c 78 b8 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 |,x.#........;~b.| +00000190 2c a5 33 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b |,.3...\zV.....X{| +000001a0 26 3f b5 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a |&?......!.J..T.Z| +000001b0 bf ef 42 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 |..Bq......~.}}..| +000001c0 39 c4 a2 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 cf |9....Q.|..L;2f..| +000001d0 af b1 1d b8 71 9a 1d db db 89 6b ae da 2d 79 02 |....q.....k..-y.| +000001e0 03 01 00 01 a3 81 a7 30 81 a4 30 1d 06 03 55 1d |.......0..0...U.| +000001f0 0e 04 16 04 14 b1 ad e2 85 5a cf cb 28 db 69 ce |.........Z..(.i.| +00000200 23 69 de d3 26 8e 18 88 39 30 75 06 03 55 1d 23 |#i..&...90u..U.#| +00000210 04 6e 30 6c 80 14 b1 ad e2 85 5a cf cb 28 db 69 |.n0l......Z..(.i| +00000220 ce 23 69 de d3 26 8e 18 88 39 a1 49 a4 47 30 45 |.#i..&...9.I.G0E| +00000230 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 |1.0...U....AU1.0| +00000240 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 |...U....Some-Sta| +00000250 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 |te1!0...U....Int| +00000260 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 |ernet Widgits Pt| +00000270 79 20 4c 74 64 82 09 00 85 b0 bb a4 8a 7f b8 ca |y Ltd...........| +00000280 30 0c 06 03 55 1d 13 04 05 30 03 01 01 ff 30 0d |0...U....0....0.| +00000290 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 03 81 81 |..*.H...........| +000002a0 00 08 6c 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 |..lE$.k.Y..R....| +000002b0 d7 87 9d 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 |...zdu.Z.f..+...| +000002c0 66 1f eb 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 |f..O8.n`....A..%| +000002d0 13 b1 18 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 |...z$.0.........| +000002e0 31 59 db 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a |1Y....x.PV\..Z-Z| +000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....| +00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.| +00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...| +00000320 d9 16 03 01 00 cb 0c 00 00 c7 03 00 17 41 04 05 |.............A..| +00000330 45 33 f8 4b e9 96 0e 4a fd ec 54 76 21 9b 24 8a |E3.K...J..Tv!.$.| +00000340 75 0b 80 84 c7 30 2b 22 f0 85 57 a4 a9 79 d6 f6 |u....0+"..W..y..| +00000350 6d 80 b0 71 d9 66 c9 6c dd 76 fc 32 d0 c6 bc 52 |m..q.f.l.v.2...R| +00000360 2f f1 c9 62 17 53 76 ec be a6 1c 93 f2 b4 5d 00 |/..b.Sv.......].| +00000370 80 72 d9 20 52 70 7c 03 b1 33 fa 51 23 cd 05 97 |.r. Rp|..3.Q#...| +00000380 6f d6 89 2f 8d 2e 3a 17 32 eb f2 ff 6b 39 70 5e |o../..:.2...k9p^| +00000390 21 41 8d 69 02 c8 9a 17 19 e4 48 9b 51 c3 7f 9b |!A.i......H.Q...| +000003a0 8d 4a 83 97 07 0e 30 f1 8b 6b e9 92 12 01 d6 96 |.J....0..k......| +000003b0 f2 1a a2 10 7f 59 87 16 1a fb 55 67 68 fc 78 c6 |.....Y....Ugh.x.| +000003c0 57 ac 05 dd f3 6f 77 84 eb ae b0 33 2d 19 2c ba |W....ow....3-.,.| +000003d0 b8 ae 9f 95 69 85 95 45 5e 37 f4 17 17 9b 03 c1 |....i..E^7......| +000003e0 50 b1 36 42 bd 60 5c 8b d8 b6 f3 c8 34 c8 9d 9d |P.6B.`\.....4...| +000003f0 75 16 03 01 00 04 0e 00 00 00 |u.........| +>>> Flow 3 (client to server) +00000000 16 03 01 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +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 01 00 01 |..h.A.Vk.Z......| +00000050 01 16 03 01 00 30 ca d1 1b 08 27 9b 44 e7 e9 b4 |.....0....'.D...| +00000060 90 16 4d 30 4e 65 5c 0d 47 ba 46 86 cf c9 80 e7 |..M0Ne\.G.F.....| +00000070 64 31 f5 a1 9e dc 39 15 d3 be 16 4f c7 90 b6 62 |d1....9....O...b| +00000080 5d 6d 7f 41 4e 3e |]m.AN>| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 98 81 24 8e cd |..........0..$..| +00000010 b6 48 2f 80 de 8e 24 3c cd 02 67 80 34 97 d7 92 |.H/...$<..g.4...| +00000020 78 c2 44 3d 5d 05 eb 88 76 79 46 7a c3 fa ca 73 |x.D=]...vyFz...s| +00000030 45 82 ad c1 81 00 ca 40 c1 2f 13 |E......@./.| +>>> Flow 5 (client to server) +00000000 17 03 01 00 20 ee 19 59 67 67 a9 8b db 99 87 50 |.... ..Ygg.....P| +00000010 01 e2 02 c1 d5 6d 36 79 af aa ec 1b 80 0e b6 5e |.....m6y.......^| +00000020 5f fa 03 01 cc 17 03 01 00 20 ec e2 04 b7 3b a5 |_........ ....;.| +00000030 f2 e0 13 1f 17 48 e7 6e d3 eb f0 fa 36 ef 6e 2e |.....H.n....6.n.| +00000040 fb ea c8 39 c4 5f 4b 28 d4 50 15 03 01 00 20 c7 |...9._K(.P.... .| +00000050 45 ff fb c7 07 0c d8 0e 35 a3 c5 31 47 b7 03 0e |E.......5..1G...| +00000060 14 c8 29 fd 53 70 5f 15 ac d2 1c 4c 69 fb d6 |..).Sp_....Li..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4 b/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4 new file mode 100644 index 0000000000..395d53bbab --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4 @@ -0,0 +1,83 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 51 02 00 00 4d 03 01 53 04 f1 02 76 |....Q...M..S...v| +00000010 e8 45 7f 57 f3 42 4b 33 0b 06 fa a6 fa c4 3d 84 |.E.W.BK3......=.| +00000020 5a 45 dc 93 41 a5 8d 79 6e 8f 11 20 e7 c6 29 2b |ZE..A..yn.. ..)+| +00000030 ff 4a 6e 63 67 a6 10 cb 49 19 46 1e 5e 0a d5 70 |.Jncg...I.F.^..p| +00000040 96 88 9a 32 48 ef c3 4a 45 4c 6d e0 00 05 00 00 |...2H..JELm.....| +00000050 05 ff 01 00 01 00 16 03 01 02 be 0b 00 02 ba 00 |................| +00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 01 00 04 0e 00 |n8P)l...........| +00000320 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 01 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 |...........mQ...| +00000010 3e fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c |>.u.A6..j.*.%.gL| +00000020 8e 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 |.b/0......+.#...| +00000030 1d f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 |..;...'..$...[.f| +00000040 0d 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be |.j.....C........| +00000050 c8 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce |..9L.....K.../..| +00000060 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V| +00000070 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....| +00000080 35 d4 1c 43 d1 30 6f 55 4e 0a 70 14 03 01 00 01 |5..C.0oUN.p.....| +00000090 01 16 03 01 00 24 cd c0 68 dc 2e 69 cc c7 5b c5 |.....$..h..i..[.| +000000a0 3f bd 40 cf a0 0f 41 34 ce 16 37 10 26 c8 3f d1 |?.@...A4..7.&.?.| +000000b0 46 3b ad 7b b0 31 f3 c5 36 e7 |F;.{.1..6.| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 24 ea 77 6f 3c 42 |..........$.wo....]| +>>> Flow 5 (client to server) +00000000 17 03 01 00 1a 9e ae ca 55 df c4 d9 47 04 55 dd |........U...G.U.| +00000010 3b 33 e1 a6 16 6f a1 94 b1 9b 4d 0d cb 6c 3b 15 |;3...o....M..l;.| +00000020 03 01 00 16 92 5d 76 07 e9 b7 31 29 09 c5 b1 09 |.....]v...1)....| +00000030 2d 64 3d 85 8d f1 d1 40 54 b8 |-d=....@T.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES new file mode 100644 index 0000000000..9f941f8ef1 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES @@ -0,0 +1,89 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 02 00 59 02 00 00 55 03 02 53 04 f1 02 1c |....Y...U..S....| +00000010 d1 1c 6a 5f 7a 5c 26 69 92 cd ee c3 57 ed 96 90 |..j_z\&i....W...| +00000020 e3 c5 f1 ee 8b ee 99 5f 46 2c e6 20 c8 50 6a a4 |......._F,. .Pj.| +00000030 4b 93 e6 da ba 6d d4 87 f6 75 a8 9d 44 db b5 43 |K....m...u..D..C| +00000040 df 12 57 de a4 f1 bc fb b8 7a 3f 6a c0 09 00 00 |..W......z?j....| +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....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +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 d4 0c 00 00 d0 03 00 17 41 04 7b |*............A.{| +00000280 c4 00 37 35 51 de c3 f2 a4 95 2c 19 21 3e a6 94 |..75Q.....,.!>..| +00000290 7b fd 04 d7 b7 1c 56 e6 af 3c ee 36 cb 55 e6 f0 |{.....V..<.6.U..| +000002a0 e6 24 34 6b 8a 02 66 71 f9 e2 f5 a6 c9 d7 6c dc |.$4k..fq......l.| +000002b0 65 59 ff 1c c9 ec a9 8b 07 d6 52 2c 01 3c c3 00 |eY........R,.<..| +000002c0 89 30 81 86 02 41 74 89 1a 31 72 e6 8b c0 4a ce |.0...At..1r...J.| +000002d0 8f 5a 49 a7 52 2d 6d b9 8b 50 17 62 2a 99 d6 3b |.ZI.R-m..P.b*..;| +000002e0 02 85 41 4d 34 53 b5 09 bd e3 ac 16 c1 9b e9 83 |..AM4S..........| +000002f0 cc 83 e3 9c 23 34 67 71 72 d4 05 a2 34 f7 08 29 |....#4gqr...4..)| +00000300 62 43 2e cc bc 08 01 02 41 59 de 5a d0 dd d7 6b |bC......AY.Z...k| +00000310 db 9c 35 29 79 f8 96 91 56 74 1f 18 7b ee 25 83 |..5)y...Vt..{.%.| +00000320 f2 37 0e 77 ab 38 fb 5e 04 0b 09 d9 b4 1f 3f be |.7.w.8.^......?.| +00000330 2e e3 60 e3 96 f3 29 c1 6d 8f 56 1b fd 62 14 48 |..`...).m.V..b.H| +00000340 e3 d9 2a ea 2f be 93 d0 8b 31 16 03 02 00 04 0e |..*./....1......| +00000350 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 02 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +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 02 00 01 |..h.A.Vk.Z......| +00000050 01 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........| +00000060 00 00 00 00 00 00 b6 98 a2 a9 48 34 12 6b 0a 94 |..........H4.k..| +00000070 89 fc 38 04 63 5a 6f 63 36 3e d9 35 12 64 8c 28 |..8.cZoc6>.5.d.(| +00000080 99 a6 cf 2e 57 e3 14 6d 0a 8a ab f0 a6 58 37 7c |....W..m.....X7|| +00000090 96 04 d3 71 bc d4 |...q..| +>>> Flow 4 (server to client) +00000000 14 03 02 00 01 01 16 03 02 00 40 c5 01 c9 0a b0 |..........@.....| +00000010 d8 ca 5e c1 19 dc 37 6c 2e a0 b3 11 a8 87 65 5a |..^...7l......eZ| +00000020 09 41 b9 fe 53 c4 c9 76 97 6d 7f ac c0 be d2 07 |.A..S..v.m......| +00000030 84 e5 5b 78 37 34 ee da 3b cb 3e 82 52 79 91 44 |..[x74..;.>.Ry.D| +00000040 b4 e4 1c ec 3a c0 c0 9d cd ff 13 |....:......| +>>> 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 46 60 13 39 2b 2f 72 95 ed 0e aa |.....F`.9+/r....| +00000020 69 6e b4 64 3e 83 43 d0 f9 7f 37 7c 1d b9 ce 11 |in.d>.C...7|....| +00000030 d9 41 66 60 6d 15 03 02 00 30 00 00 00 00 00 00 |.Af`m....0......| +00000040 00 00 00 00 00 00 00 00 00 00 b1 26 d0 5d 08 98 |...........&.]..| +00000050 eb 28 42 74 31 58 42 95 c5 ad 1a 92 0a f5 5f ed |.(Bt1XB......._.| +00000060 45 98 e0 90 e5 a3 b6 8b 8d 18 |E.........| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES new file mode 100644 index 0000000000..fc723396a4 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES @@ -0,0 +1,99 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 02 00 59 02 00 00 55 03 02 53 04 f1 02 fe |....Y...U..S....| +00000010 17 8b 79 ad 93 2e d3 89 66 9b 5d 9b b4 03 3e ba |..y.....f.]...>.| +00000020 65 2a f1 55 f9 3c 33 de 2c a7 47 20 fa 4f 82 11 |e*.U.<3.,.G .O..| +00000030 96 81 d0 70 2e 65 b3 68 2e 3a 6d d7 6c 74 22 33 |...p.e.h.:m.lt"3| +00000040 d4 ae 6c aa c8 f0 c7 20 8b 10 21 e7 c0 13 00 00 |..l.... ..!.....| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 02 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..| +00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............| +00000080 a4 8a 7f b8 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....| +00000090 01 05 05 00 30 45 31 0b 30 09 06 03 55 04 06 13 |....0E1.0...U...| +000000a0 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f |.AU1.0...U....So| +000000b0 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 |me-State1!0...U.| +000000c0 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 |...Internet Widg| +000000d0 69 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 |its Pty Ltd0...1| +000000e0 30 30 34 32 34 30 39 30 39 33 38 5a 17 0d 31 31 |00424090938Z..11| +000000f0 30 34 32 34 30 39 30 39 33 38 5a 30 45 31 0b 30 |0424090938Z0E1.0| +00000100 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +00000110 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +00000120 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +00000130 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +00000140 74 64 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 |td0..0...*.H....| +00000150 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 bb |........0.......| +00000160 79 d6 f5 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 |y......F...i..+.| +00000170 43 5a d0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c |CZ..-.zC...R..eL| +00000180 2c 78 b8 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 |,x.#........;~b.| +00000190 2c a5 33 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b |,.3...\zV.....X{| +000001a0 26 3f b5 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a |&?......!.J..T.Z| +000001b0 bf ef 42 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 |..Bq......~.}}..| +000001c0 39 c4 a2 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 cf |9....Q.|..L;2f..| +000001d0 af b1 1d b8 71 9a 1d db db 89 6b ae da 2d 79 02 |....q.....k..-y.| +000001e0 03 01 00 01 a3 81 a7 30 81 a4 30 1d 06 03 55 1d |.......0..0...U.| +000001f0 0e 04 16 04 14 b1 ad e2 85 5a cf cb 28 db 69 ce |.........Z..(.i.| +00000200 23 69 de d3 26 8e 18 88 39 30 75 06 03 55 1d 23 |#i..&...90u..U.#| +00000210 04 6e 30 6c 80 14 b1 ad e2 85 5a cf cb 28 db 69 |.n0l......Z..(.i| +00000220 ce 23 69 de d3 26 8e 18 88 39 a1 49 a4 47 30 45 |.#i..&...9.I.G0E| +00000230 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 |1.0...U....AU1.0| +00000240 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 |...U....Some-Sta| +00000250 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 |te1!0...U....Int| +00000260 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 |ernet Widgits Pt| +00000270 79 20 4c 74 64 82 09 00 85 b0 bb a4 8a 7f b8 ca |y Ltd...........| +00000280 30 0c 06 03 55 1d 13 04 05 30 03 01 01 ff 30 0d |0...U....0....0.| +00000290 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 03 81 81 |..*.H...........| +000002a0 00 08 6c 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 |..lE$.k.Y..R....| +000002b0 d7 87 9d 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 |...zdu.Z.f..+...| +000002c0 66 1f eb 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 |f..O8.n`....A..%| +000002d0 13 b1 18 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 |...z$.0.........| +000002e0 31 59 db 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a |1Y....x.PV\..Z-Z| +000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....| +00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.| +00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...| +00000320 d9 16 03 02 00 cb 0c 00 00 c7 03 00 17 41 04 26 |.............A.&| +00000330 56 18 02 e5 66 d4 aa 24 7e ae 39 e5 ca 78 6c c1 |V...f..$~.9..xl.| +00000340 90 02 c3 c4 ad 79 2c 47 a8 bf 54 e2 8a 22 b6 ef |.....y,G..T.."..| +00000350 99 d4 7a 7f 8f 78 6a 78 4e 14 2a 16 0d bb 54 38 |..z..xjxN.*...T8| +00000360 59 1f 7a 53 1b c7 73 10 89 4b de c3 66 39 7a 00 |Y.zS..s..K..f9z.| +00000370 80 3a 88 38 c8 15 07 ab 2f 0f 0d cb 19 07 84 ac |.:.8..../.......| +00000380 24 fd 8b d2 9d 05 45 c6 11 c3 d6 84 58 95 5a 08 |$.....E.....X.Z.| +00000390 b9 a4 2c c0 41 4e 34 e0 b2 24 98 94 b7 67 27 50 |..,.AN4..$...g'P| +000003a0 ba 82 35 28 a9 bf 16 ee e3 7b 49 9c 4c 81 80 69 |..5(.....{I.L..i| +000003b0 d7 aa ed 46 ea 9a 68 c4 97 b7 11 d4 35 91 74 5e |...F..h.....5.t^| +000003c0 54 10 34 83 cd c4 06 18 49 7d 7a 28 c9 53 06 73 |T.4.....I}z(.S.s| +000003d0 00 7b 04 b6 d8 36 a7 4b 67 7f 81 30 94 de 40 4d |.{...6.Kg..0..@M| +000003e0 18 f8 c4 b7 02 00 44 8e bc 72 06 24 53 15 74 72 |......D..r.$S.tr| +000003f0 8d 16 03 02 00 04 0e 00 00 00 |..........| +>>> Flow 3 (client to server) +00000000 16 03 02 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +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 02 00 01 |..h.A.Vk.Z......| +00000050 01 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 |.....@..........| +00000060 00 00 00 00 00 00 8a 87 81 38 35 c0 4c bb f8 12 |.........85.L...| +00000070 fa 75 04 cd 1e 3a 61 96 93 c8 fb 07 d1 6d b4 55 |.u...:a......m.U| +00000080 0f b5 0f 07 35 0a 96 ce 5c 6f 24 62 d3 68 e4 b0 |....5...\o$b.h..| +00000090 5d be 81 37 c2 9c |]..7..| +>>> Flow 4 (server to client) +00000000 14 03 02 00 01 01 16 03 02 00 40 66 36 8d f8 8c |..........@f6...| +00000010 7f db 38 e8 39 df f8 2f cb 88 9c 14 d9 89 10 b4 |..8.9../........| +00000020 be 59 88 d7 f3 73 62 af a3 42 66 6e 74 38 64 9f |.Y...sb..Bfnt8d.| +00000030 16 79 09 d7 14 7e 91 8a 70 73 63 28 30 58 fe cc |.y...~..psc(0X..| +00000040 42 45 d6 37 fb 9e 8c c1 01 af 34 |BE.7......4| +>>> 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 31 0b e3 9d 2a 05 83 19 7d 10 36 |.....1...*...}.6| +00000020 23 dc da fe 00 ab d3 aa 8f ce 28 5f 08 fd b7 59 |#.........(_...Y| +00000030 1e 00 2e 25 5a 15 03 02 00 30 00 00 00 00 00 00 |...%Z....0......| +00000040 00 00 00 00 00 00 00 00 00 00 10 91 fd fa 59 07 |..............Y.| +00000050 df 2c 92 25 15 7b 7c 83 44 89 0d 4f 65 43 99 2e |.,.%.{|.D..OeC..| +00000060 41 5d 51 c9 09 89 ed 02 08 bc |A]Q.......| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4 b/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4 new file mode 100644 index 0000000000..f7be3f7e93 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4 @@ -0,0 +1,83 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 02 00 51 02 00 00 4d 03 02 53 04 f1 02 d4 |....Q...M..S....| +00000010 69 65 aa 96 3d 42 96 eb 9e 7d 8a 18 af 4c 7c 5d |ie..=B...}...L|]| +00000020 fb 97 5f da 94 62 13 69 1f 66 06 20 aa 52 e3 08 |.._..b.i.f. .R..| +00000030 35 0a 87 d5 ef 93 49 ab 1a 74 dd 90 bd 69 70 d1 |5.....I..t...ip.| +00000040 e9 f1 44 17 3a dc 33 98 f5 e5 ab 93 00 05 00 00 |..D.:.3.........| +00000050 05 ff 01 00 01 00 16 03 02 02 be 0b 00 02 ba 00 |................| +00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 02 00 04 0e 00 |n8P)l...........| +00000320 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 02 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 |...........mQ...| +00000010 3e fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c |>.u.A6..j.*.%.gL| +00000020 8e 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 |.b/0......+.#...| +00000030 1d f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 |..;...'..$...[.f| +00000040 0d 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be |.j.....C........| +00000050 c8 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce |..9L.....K.../..| +00000060 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V| +00000070 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....| +00000080 35 d4 1c 43 d1 30 6f 55 4e 0a 70 14 03 02 00 01 |5..C.0oUN.p.....| +00000090 01 16 03 02 00 24 07 9f dc df 2d c3 a6 88 06 28 |.....$....-....(| +000000a0 21 e0 e0 d3 31 99 fc 89 b8 82 6e 95 f4 4b 9e e2 |!...1.....n..K..| +000000b0 d9 36 5c 14 ce d7 db e2 78 4e |.6\.....xN| +>>> Flow 4 (server to client) +00000000 14 03 02 00 01 01 16 03 02 00 24 81 72 75 80 d4 |..........$.ru..| +00000010 1b 1a 32 00 89 bf 9e 79 30 b9 6b 67 e0 8e c7 eb |..2....y0.kg....| +00000020 73 f2 e4 93 51 65 9b 5f 91 b1 b4 b1 f7 44 76 |s...Qe._.....Dv| +>>> Flow 5 (client to server) +00000000 17 03 02 00 1a b2 91 39 63 c0 38 3c 4d 25 fd 14 |.......9c.8>> Flow 1 (client to server) +00000000 16 03 01 00 8d 01 00 00 89 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 46 33 74 00 00 |./.5.......F3t..| +00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................| +00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................| +00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 00 10 |................| +00000080 00 10 00 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 |.....proto2.prot| +00000090 6f 31 |o1| +>>> Flow 2 (server to client) +00000000 16 03 03 00 66 02 00 00 62 03 03 77 a9 7d 9c 4b |....f...b..w.}.K| +00000010 69 65 aa dc 95 cb 78 08 3d d2 1a 0a 45 69 23 73 |ie....x.=...Ei#s| +00000020 4f 41 4f 24 12 2e 57 47 b7 53 64 20 82 9a f8 e7 |OAO$..WG.Sd ....| +00000030 79 f8 13 2c 9d cd b5 cb cb 9a 95 56 0e e9 cb a8 |y..,.......V....| +00000040 e4 a2 8a d6 bc dc fa 25 b3 57 cc cf c0 2f 00 00 |.......%.W.../..| +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 be |.....proto1.....| +00000070 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 b0 30 82 |..........0...0.| +00000080 02 19 a0 03 02 01 02 02 09 00 85 b0 bb a4 8a 7f |................| +00000090 b8 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 |..0...*.H.......| +000000a0 00 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 55 |.0E1.0...U....AU| +000000b0 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d |1.0...U....Some-| +000000c0 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 18 |State1!0...U....| +000000d0 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 73 |Internet Widgits| +000000e0 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 30 30 34 | Pty Ltd0...1004| +000000f0 32 34 30 39 30 39 33 38 5a 17 0d 31 31 30 34 32 |24090938Z..11042| +00000100 34 30 39 30 39 33 38 5a 30 45 31 0b 30 09 06 03 |4090938Z0E1.0...| +00000110 55 04 06 13 02 41 55 31 13 30 11 06 03 55 04 08 |U....AU1.0...U..| +00000120 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f |..Some-State1!0.| +00000130 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 |..U....Internet | +00000140 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 30 |Widgits Pty Ltd0| +00000150 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 |..0...*.H.......| +00000160 00 03 81 8d 00 30 81 89 02 81 81 00 bb 79 d6 f5 |.....0.......y..| +00000170 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 43 5a d0 |....F...i..+.CZ.| +00000180 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c 2c 78 b8 |.-.zC...R..eL,x.| +00000190 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 2c a5 33 |#........;~b.,.3| +000001a0 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b 26 3f b5 |...\zV.....X{&?.| +000001b0 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a bf ef 42 |.....!.J..T.Z..B| +000001c0 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 39 c4 a2 |q......~.}}..9..| +000001d0 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 cf af b1 1d |..Q.|..L;2f.....| +000001e0 b8 71 9a 1d db db 89 6b ae da 2d 79 02 03 01 00 |.q.....k..-y....| +000001f0 01 a3 81 a7 30 81 a4 30 1d 06 03 55 1d 0e 04 16 |....0..0...U....| +00000200 04 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 de |......Z..(.i.#i.| +00000210 d3 26 8e 18 88 39 30 75 06 03 55 1d 23 04 6e 30 |.&...90u..U.#.n0| +00000220 6c 80 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 |l......Z..(.i.#i| +00000230 de d3 26 8e 18 88 39 a1 49 a4 47 30 45 31 0b 30 |..&...9.I.G0E1.0| +00000240 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +00000250 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +00000260 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +00000270 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +00000280 74 64 82 09 00 85 b0 bb a4 8a 7f b8 ca 30 0c 06 |td...........0..| +00000290 03 55 1d 13 04 05 30 03 01 01 ff 30 0d 06 09 2a |.U....0....0...*| +000002a0 86 48 86 f7 0d 01 01 05 05 00 03 81 81 00 08 6c |.H.............l| +000002b0 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 d7 87 9d |E$.k.Y..R.......| +000002c0 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 66 1f eb |zdu.Z.f..+...f..| +000002d0 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 13 b1 18 |O8.n`....A..%...| +000002e0 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 31 59 db |z$.0.........1Y.| +000002f0 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a 5f 33 c4 |...x.PV\..Z-Z_3.| +00000300 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 1f 89 20 |...u....R...... | +00000310 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 70 e8 26 |_..........W.p.&| +00000320 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd d9 16 03 |mq..&n8P)l......| +00000330 03 00 cd 0c 00 00 c9 03 00 17 41 04 1b 42 c3 ae |..........A..B..| +00000340 44 19 d3 84 7c 6c 98 cb b9 22 a2 67 63 95 aa cc |D...|l...".gc...| +00000350 bd e4 1e f8 08 e6 60 f3 bc 83 9f 81 da 9c 1c 8c |......`.........| +00000360 ff 6f f4 3e 1e e5 3b f6 49 61 f9 70 43 7f c1 69 |.o.>..;.Ia.pC..i| +00000370 de 73 98 4b bd 5c c3 78 24 18 a8 ec 04 01 00 80 |.s.K.\.x$.......| +00000380 70 d2 5b e1 39 cf 4d 54 de d2 74 4e 5e a8 b3 ca |p.[.9.MT..tN^...| +00000390 e1 f2 4e 76 3c 77 8b ef f7 d1 df b9 ad c1 70 39 |..Nv>> 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..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +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 35 9d |.....(........5.| +00000060 92 e8 bf df 7f a7 77 1b cf 03 2a bf e2 6c 62 2b |......w...*..lb+| +00000070 26 f0 fb 93 d3 df fd 55 84 d3 ed 88 31 cb |&......U....1.| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 c8 c0 78 09 73 |..........(..x.s| +00000010 58 41 73 66 88 cf db f3 fe c6 57 ab 45 be 2e d8 |XAsf......W.E...| +00000020 4e e5 ff 42 57 13 74 d2 cc c2 62 07 39 8b 06 46 |N..BW.t...b.9..F| +00000030 1d 8f 88 |...| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 10 c3 5f |..............._| +00000010 3f c8 92 6c 7a a7 23 05 f3 d8 31 20 01 52 f1 99 |?..lz.#...1 .R..| +00000020 33 c1 2a 15 03 03 00 1a 00 00 00 00 00 00 00 02 |3.*.............| +00000030 cc ef eb 78 e4 e1 9d 90 05 6d 95 ac f2 49 ba 8e |...x.....m...I..| +00000040 6b 8d |k.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch b/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch new file mode 100644 index 0000000000..f24a70cc82 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch @@ -0,0 +1,95 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 86 01 00 00 82 03 03 00 00 00 00 00 |................| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 3f 33 74 00 00 |./.5.......?3t..| +00000050 00 05 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 |................| +00000060 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0a 00 |................| +00000070 08 04 01 04 03 02 01 02 03 ff 01 00 01 00 00 10 |................| +00000080 00 09 00 07 06 70 72 6f 74 6f 33 |.....proto3| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 69 84 d1 d3 44 |....Y...U..i...D| +00000010 e9 66 08 48 bc 70 d8 ae 40 0b 17 69 e7 27 f6 7a |.f.H.p..@..i.'.z| +00000020 d5 ee 86 74 54 9e a8 bb 79 76 89 20 57 53 1b 02 |...tT...yv. WS..| +00000030 5b 70 81 a6 f1 53 bc 9d b7 42 5e ac 92 93 b5 20 |[p...S...B^.... | +00000040 8a bb 36 cc 8f cb 7e a0 61 a2 e8 ef c0 2f 00 00 |..6...~.a..../..| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..| +00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............| +00000080 a4 8a 7f b8 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....| +00000090 01 05 05 00 30 45 31 0b 30 09 06 03 55 04 06 13 |....0E1.0...U...| +000000a0 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f |.AU1.0...U....So| +000000b0 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 |me-State1!0...U.| +000000c0 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 |...Internet Widg| +000000d0 69 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 |its Pty Ltd0...1| +000000e0 30 30 34 32 34 30 39 30 39 33 38 5a 17 0d 31 31 |00424090938Z..11| +000000f0 30 34 32 34 30 39 30 39 33 38 5a 30 45 31 0b 30 |0424090938Z0E1.0| +00000100 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +00000110 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +00000120 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +00000130 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +00000140 74 64 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 |td0..0...*.H....| +00000150 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 bb |........0.......| +00000160 79 d6 f5 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 |y......F...i..+.| +00000170 43 5a d0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c |CZ..-.zC...R..eL| +00000180 2c 78 b8 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 |,x.#........;~b.| +00000190 2c a5 33 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b |,.3...\zV.....X{| +000001a0 26 3f b5 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a |&?......!.J..T.Z| +000001b0 bf ef 42 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 |..Bq......~.}}..| +000001c0 39 c4 a2 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 cf |9....Q.|..L;2f..| +000001d0 af b1 1d b8 71 9a 1d db db 89 6b ae da 2d 79 02 |....q.....k..-y.| +000001e0 03 01 00 01 a3 81 a7 30 81 a4 30 1d 06 03 55 1d |.......0..0...U.| +000001f0 0e 04 16 04 14 b1 ad e2 85 5a cf cb 28 db 69 ce |.........Z..(.i.| +00000200 23 69 de d3 26 8e 18 88 39 30 75 06 03 55 1d 23 |#i..&...90u..U.#| +00000210 04 6e 30 6c 80 14 b1 ad e2 85 5a cf cb 28 db 69 |.n0l......Z..(.i| +00000220 ce 23 69 de d3 26 8e 18 88 39 a1 49 a4 47 30 45 |.#i..&...9.I.G0E| +00000230 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 |1.0...U....AU1.0| +00000240 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 |...U....Some-Sta| +00000250 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 |te1!0...U....Int| +00000260 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 |ernet Widgits Pt| +00000270 79 20 4c 74 64 82 09 00 85 b0 bb a4 8a 7f b8 ca |y Ltd...........| +00000280 30 0c 06 03 55 1d 13 04 05 30 03 01 01 ff 30 0d |0...U....0....0.| +00000290 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 03 81 81 |..*.H...........| +000002a0 00 08 6c 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 |..lE$.k.Y..R....| +000002b0 d7 87 9d 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 |...zdu.Z.f..+...| +000002c0 66 1f eb 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 |f..O8.n`....A..%| +000002d0 13 b1 18 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 |...z$.0.........| +000002e0 31 59 db 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a |1Y....x.PV\..Z-Z| +000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....| +00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.| +00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...| +00000320 d9 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 04 |.............A..| +00000330 be 27 08 6f 12 83 1b 04 76 fa 5f 16 d6 e3 64 76 |.'.o....v._...dv| +00000340 ad 0a 77 37 71 64 44 4c 3f 1a be dc 85 ce 46 c8 |..w7qdDL?.....F.| +00000350 29 a1 e2 24 78 66 1f 35 90 05 46 c0 91 d1 fd dd |)..$xf.5..F.....| +00000360 b5 5b 87 d7 6d 9d 77 a7 f7 b3 df 68 27 fd 6d 04 |.[..m.w....h'.m.| +00000370 01 00 80 7b 9b fd 0d 62 57 07 ef 97 f5 ff a9 00 |...{...bW.......| +00000380 a0 89 35 5a 8a e6 e7 ae 7b 55 c5 dc 21 64 87 6e |..5Z....{U..!d.n| +00000390 0f ab 85 6d 82 e8 83 fd 7d 3b 49 a7 ae 92 5f 6d |...m....};I..._m| +000003a0 a3 42 ce ff ef a6 00 6a 33 32 1f 7b eb b7 c2 5c |.B.....j32.{...\| +000003b0 2d 38 cf 10 4b 59 69 4d 15 e0 68 49 39 ba cb 2a |-8..KYiM..hI9..*| +000003c0 d9 b9 f3 fe 33 01 4f 7e ac 69 02 35 a5 e0 33 8d |....3.O~.i.5..3.| +000003d0 b3 74 34 14 45 9c 89 ad 41 2d d0 27 22 90 58 c6 |.t4.E...A-.'".X.| +000003e0 e0 2c b4 6e 19 04 e4 46 26 ec 13 35 48 a6 3f 64 |.,.n...F&..5H.?d| +000003f0 dc 85 2b 16 03 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..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +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 88 0d |.....(..........| +00000060 04 8b 8e 93 55 58 d6 75 ca 16 26 42 a3 60 20 67 |....UX.u..&B.` g| +00000070 84 cf d7 b3 10 fe 63 6c 2f 40 64 0c d6 78 |......cl/@d..x| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 bd 6c 2f 70 b9 |..........(.l/p.| +00000010 2f 9c 29 70 af 34 49 4c 5b 25 c3 14 b6 6d 28 81 |/.)p.4IL[%...m(.| +00000020 ff 54 d9 71 8d 2c c7 38 dd 44 27 6b 54 1e 53 7b |.T.q.,.8.D'kT.S{| +00000030 22 cb 65 |".e| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 7f 0d d7 |................| +00000010 d9 4b 87 7b 36 fb 24 92 69 22 43 50 1e 46 fb c4 |.K.{6.$.i"CP.F..| +00000020 86 64 6f 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.do.............| +00000030 37 d5 2d 0a be c5 a8 ae d4 bd 2b 09 34 18 a0 87 |7.-.......+.4...| +00000040 08 a6 |..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA new file mode 100644 index 0000000000..2073270364 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA @@ -0,0 +1,134 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 53 04 f1 03 6f |....Y...U..S...o| +00000010 c6 4b 55 27 fe e8 fe 4d 7c 0e d4 20 98 b8 7c 81 |.KU'...M|.. ..|.| +00000020 3d 31 f8 35 66 2f 0a 0b f1 2c e3 20 86 4d 12 32 |=1.5f/...,. .M.2| +00000030 73 e3 ba be 25 50 a4 a2 a1 7b f1 9a 76 7a 75 fb |s...%P...{..vzu.| +00000040 e2 64 a2 12 ec f3 e7 9d 9a 24 6e 94 c0 09 00 00 |.d.......$n.....| +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....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +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 d7 0c 00 00 d3 03 00 17 41 04 a3 |*............A..| +00000280 03 8c de d2 b0 68 c8 25 0e 85 ea d7 ae 13 0d 79 |.....h.%.......y| +00000290 ec 59 0d b5 4d 51 96 d9 7f 64 36 fb 4c d5 6a 26 |.Y..MQ...d6.L.j&| +000002a0 ae 0e 48 61 df 5c 2b d4 ff 09 41 15 c4 14 8e 1b |..Ha.\+...A.....| +000002b0 84 a8 c8 cd ef 10 97 95 66 67 85 dd fd dc 2a 04 |........fg....*.| +000002c0 03 00 8a 30 81 87 02 41 11 75 5d bc bd 08 28 d4 |...0...A.u]...(.| +000002d0 5b 1b 45 7f 9c d3 8d 0b 91 fa f6 82 ba 59 bd 3e |[.E..........Y.>| +000002e0 96 01 c6 1d 38 db fe 08 e7 56 89 fc 10 b0 37 6a |....8....V....7j| +000002f0 3d d6 c9 50 16 53 f7 c2 a2 60 67 82 1f 74 b8 d5 |=..P.S...`g..t..| +00000300 bc 02 ec 96 db 82 18 8c 87 02 42 01 0d df f7 b7 |..........B.....| +00000310 05 3c 8c 56 f0 1d 33 18 cf c5 4c 80 7e 0b d9 f9 |.<.V..3...L.~...| +00000320 f0 51 69 fe 5d b8 0b 64 c0 c7 0d f4 75 65 ae 07 |.Qi.]..d....ue..| +00000330 9d cf f4 4b ad 52 f6 b8 10 26 18 bd d6 e2 0d a8 |...K.R...&......| +00000340 80 10 50 34 15 cd 72 0b 7d a9 94 de 4c 16 03 03 |..P4..r.}...L...| +00000350 00 30 0d 00 00 28 03 01 02 40 00 20 06 01 06 02 |.0...(...@. ....| +00000360 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................| +00000370 03 02 03 03 02 01 02 02 02 03 01 01 00 00 0e 00 |................| +00000380 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 03 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0| +00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5| +00000020 d9 17 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 |..0...*.H.=..0E1| +00000030 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 |.0...U....AU1.0.| +00000040 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 |..U....Some-Stat| +00000050 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 |e1!0...U....Inte| +00000060 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 |rnet Widgits Pty| +00000070 20 4c 74 64 30 1e 17 0d 31 32 31 31 31 34 31 33 | Ltd0...12111413| +00000080 32 35 35 33 5a 17 0d 32 32 31 31 31 32 31 33 32 |2553Z..221112132| +00000090 35 35 33 5a 30 41 31 0b 30 09 06 03 55 04 06 13 |553Z0A1.0...U...| +000000a0 02 41 55 31 0c 30 0a 06 03 55 04 08 13 03 4e 53 |.AU1.0...U....NS| +000000b0 57 31 10 30 0e 06 03 55 04 07 13 07 50 79 72 6d |W1.0...U....Pyrm| +000000c0 6f 6e 74 31 12 30 10 06 03 55 04 03 13 09 4a 6f |ont1.0...U....Jo| +000000d0 65 6c 20 53 69 6e 67 30 81 9b 30 10 06 07 2a 86 |el Sing0..0...*.| +000000e0 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| +000000f0 04 00 95 8c 91 75 14 c0 5e c4 57 b4 d4 c3 6f 8d |.....u..^.W...o.| +00000100 ae 68 1e dd 6f ce 86 e1 7e 6e b2 48 3e 81 e5 4e |.h..o...~n.H>..N| +00000110 e2 c6 88 4b 64 dc f5 30 bb d3 ff 65 cc 5b f4 dd |...Kd..0...e.[..| +00000120 b5 6a 3e 3e d0 1d de 47 c3 76 ad 19 f6 45 2c 8c |.j>>...G.v...E,.| +00000130 bc d8 1d 01 4c 1f 70 90 46 76 48 8b 8f 83 cc 4a |....L.p.FvH....J| +00000140 5c 8f 40 76 da e0 89 ec 1d 2b c4 4e 30 76 28 41 |\.@v.....+.N0v(A| +00000150 b2 62 a8 fb 5b f1 f9 4e 7a 8d bd 09 b8 ae ea 8b |.b..[..Nz.......| +00000160 18 27 4f 2e 70 fe 13 96 ba c3 d3 40 16 cd 65 4e |.'O.p......@..eN| +00000170 ac 11 1e e6 f1 30 09 06 07 2a 86 48 ce 3d 04 01 |.....0...*.H.=..| +00000180 03 81 8c 00 30 81 88 02 42 00 e0 14 c4 60 60 0b |....0...B....``.| +00000190 72 68 b0 32 5d 61 4a 02 74 5c c2 81 b9 16 a8 3f |rh.2]aJ.t\.....?| +000001a0 29 c8 36 c7 81 ff 6c b6 5b d9 70 f1 38 3b 50 48 |).6...l.[.p.8;PH| +000001b0 28 94 cb 09 1a 52 f1 5d ee 8d f2 b9 f0 f0 da d9 |(....R.]........| +000001c0 15 3a f9 bd 03 7a 87 a2 23 35 ec 02 42 01 a3 d4 |.:...z..#5..B...| +000001d0 8a 78 35 1c 4a 9a 23 d2 0a be 2b 10 31 9d 9c 5f |.x5.J.#...+.1.._| +000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.| +000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W| +00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| +00000210 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d 19 |...F...BA...7...| +00000220 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..| +00000230 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..| +00000240 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.| +00000250 b5 68 1a 41 03 56 6b dc 5a 89 16 03 03 00 92 0f |.h.A.Vk.Z.......| +00000260 00 00 8e 04 03 00 8a 30 81 87 02 42 00 c6 85 8e |.......0...B....| +00000270 06 b7 04 04 e9 cd 9e 3e cb 66 23 95 b4 42 9c 64 |.......>.f#..B.d| +00000280 81 39 05 3f b5 21 f8 28 af 60 6b 4d 3d ba a1 4b |.9.?.!.(.`kM=..K| +00000290 5e 77 ef e7 59 28 fe 1d c1 27 a2 ff a8 de 33 48 |^w..Y(...'....3H| +000002a0 b3 c1 85 6a 42 9b f9 7e 7e 31 c2 e5 bd 66 02 41 |...jB..~~1...f.A| +000002b0 4b 49 c6 cd 02 e3 83 f7 03 50 18 6d b4 c9 51 02 |KI.......P.m..Q.| +000002c0 c0 ab 87 bc e0 3e 4b 89 53 3a e2 65 89 97 02 c1 |.....>K.S:.e....| +000002d0 88 0d 64 db 8e 4f 73 4e ea 29 0b ed a0 f5 ce 3d |..d..OsN.).....=| +000002e0 5f cc 20 ef 0a 22 02 82 f2 14 2a b7 42 68 bd c7 |_. .."....*.Bh..| +000002f0 4d 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 |M..........@....| +00000300 00 00 00 00 00 00 00 00 00 00 00 00 f0 cc 4f c7 |..............O.| +00000310 b6 0f c9 38 4d 4b 97 2c 4f be 53 08 4c d6 5b 4e |...8MK.,O.S.L.[N| +00000320 24 70 30 81 82 3a 7f 62 95 03 4d fc 54 78 ec 13 |$p0..:.b..M.Tx..| +00000330 b2 a1 00 85 2b 04 e4 1d 7b 6e 87 60 |....+...{n.`| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 d5 2a 76 79 1c |..........@.*vy.| +00000010 e7 d5 b1 5c 65 6b d1 45 73 53 4c 05 3a 6c 5d 81 |...\ek.EsSL.:l].| +00000020 dd 2f f0 74 62 e4 8e f8 ed 21 99 c7 4f d6 28 40 |./.tb....!..O.(@| +00000030 63 d9 6d e5 b0 04 73 27 7a 1d 08 19 31 10 da ef |c.m...s'z...1...| +00000040 79 26 33 fb 45 23 be a4 7c 03 66 |y&3.E#..|.f| +>>> 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 e2 53 bd c0 ef 9e e6 44 94 ea 5d |......S.....D..]| +00000020 f5 c5 a9 4b ed eb 1c 49 9f 79 44 f9 cd d7 de 02 |...K...I.yD.....| +00000030 51 10 ae 87 7d 15 03 03 00 30 00 00 00 00 00 00 |Q...}....0......| +00000040 00 00 00 00 00 00 00 00 00 00 d3 95 13 7f 5f 58 |.............._X| +00000050 ab d6 17 ea 01 2c 2a ea 5d 7c 44 61 4a 27 97 52 |.....,*.]|DaJ'.R| +00000060 cc 9b 86 f6 37 42 2b 94 01 49 |....7B+..I| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA new file mode 100644 index 0000000000..c3b753a7b4 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA @@ -0,0 +1,127 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 51 02 00 00 4d 03 03 53 04 f1 03 b0 |....Q...M..S....| +00000010 43 00 97 24 a7 a8 ea b2 24 fe 96 24 a1 49 64 fd |C..$....$..$.Id.| +00000020 1c a3 30 35 2d 85 a7 40 42 86 6b 20 af 27 7f ac |..05-..@B.k .'..| +00000030 8b 16 89 6c 78 b7 f5 29 02 58 a6 8b 61 43 c2 b0 |...lx..).X..aC..| +00000040 e0 a8 96 c8 fa 2b 26 ad 9a 5f 2d d6 00 05 00 00 |.....+&.._-.....| +00000050 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................| +00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 30 0d 00 |n8P)l........0..| +00000320 00 28 03 01 02 40 00 20 06 01 06 02 06 03 05 01 |.(...@. ........| +00000330 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................| +00000340 02 01 02 02 02 03 01 01 00 00 0e 00 00 00 |..............| +>>> Flow 3 (client to server) +00000000 16 03 03 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0| +00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5| +00000020 d9 17 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 |..0...*.H.=..0E1| +00000030 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 |.0...U....AU1.0.| +00000040 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 |..U....Some-Stat| +00000050 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 |e1!0...U....Inte| +00000060 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 |rnet Widgits Pty| +00000070 20 4c 74 64 30 1e 17 0d 31 32 31 31 31 34 31 33 | Ltd0...12111413| +00000080 32 35 35 33 5a 17 0d 32 32 31 31 31 32 31 33 32 |2553Z..221112132| +00000090 35 35 33 5a 30 41 31 0b 30 09 06 03 55 04 06 13 |553Z0A1.0...U...| +000000a0 02 41 55 31 0c 30 0a 06 03 55 04 08 13 03 4e 53 |.AU1.0...U....NS| +000000b0 57 31 10 30 0e 06 03 55 04 07 13 07 50 79 72 6d |W1.0...U....Pyrm| +000000c0 6f 6e 74 31 12 30 10 06 03 55 04 03 13 09 4a 6f |ont1.0...U....Jo| +000000d0 65 6c 20 53 69 6e 67 30 81 9b 30 10 06 07 2a 86 |el Sing0..0...*.| +000000e0 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| +000000f0 04 00 95 8c 91 75 14 c0 5e c4 57 b4 d4 c3 6f 8d |.....u..^.W...o.| +00000100 ae 68 1e dd 6f ce 86 e1 7e 6e b2 48 3e 81 e5 4e |.h..o...~n.H>..N| +00000110 e2 c6 88 4b 64 dc f5 30 bb d3 ff 65 cc 5b f4 dd |...Kd..0...e.[..| +00000120 b5 6a 3e 3e d0 1d de 47 c3 76 ad 19 f6 45 2c 8c |.j>>...G.v...E,.| +00000130 bc d8 1d 01 4c 1f 70 90 46 76 48 8b 8f 83 cc 4a |....L.p.FvH....J| +00000140 5c 8f 40 76 da e0 89 ec 1d 2b c4 4e 30 76 28 41 |\.@v.....+.N0v(A| +00000150 b2 62 a8 fb 5b f1 f9 4e 7a 8d bd 09 b8 ae ea 8b |.b..[..Nz.......| +00000160 18 27 4f 2e 70 fe 13 96 ba c3 d3 40 16 cd 65 4e |.'O.p......@..eN| +00000170 ac 11 1e e6 f1 30 09 06 07 2a 86 48 ce 3d 04 01 |.....0...*.H.=..| +00000180 03 81 8c 00 30 81 88 02 42 00 e0 14 c4 60 60 0b |....0...B....``.| +00000190 72 68 b0 32 5d 61 4a 02 74 5c c2 81 b9 16 a8 3f |rh.2]aJ.t\.....?| +000001a0 29 c8 36 c7 81 ff 6c b6 5b d9 70 f1 38 3b 50 48 |).6...l.[.p.8;PH| +000001b0 28 94 cb 09 1a 52 f1 5d ee 8d f2 b9 f0 f0 da d9 |(....R.]........| +000001c0 15 3a f9 bd 03 7a 87 a2 23 35 ec 02 42 01 a3 d4 |.:...z..#5..B...| +000001d0 8a 78 35 1c 4a 9a 23 d2 0a be 2b 10 31 9d 9c 5f |.x5.J.#...+.1.._| +000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.| +000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W| +00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| +00000210 03 03 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 3e |..........mQ...>| +00000220 fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c 8e |.u.A6..j.*.%.gL.| +00000230 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 1d |b/0......+.#....| +00000240 f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 0d |.;...'..$...[.f.| +00000250 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be c8 |j.....C.........| +00000260 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce e6 |.9L.....K.../...| +00000270 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 f1 |.w.o#......:..V.| +00000280 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 35 |.T^F..;3..(....5| +00000290 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 03 00 92 0f |..C.0oUN.p......| +000002a0 00 00 8e 04 03 00 8a 30 81 87 02 42 00 c6 85 8e |.......0...B....| +000002b0 06 b7 04 04 e9 cd 9e 3e cb 66 23 95 b4 42 9c 64 |.......>.f#..B.d| +000002c0 81 39 05 3f b5 21 f8 28 af 60 6b 4d 3d ba a1 4b |.9.?.!.(.`kM=..K| +000002d0 5e 77 ef e7 59 28 fe 1d c1 27 a2 ff a8 de 33 48 |^w..Y(...'....3H| +000002e0 b3 c1 85 6a 42 9b f9 7e 7e 31 c2 e5 bd 66 02 41 |...jB..~~1...f.A| +000002f0 4b 49 c6 cd 02 e3 83 f7 03 50 18 6d b4 c9 51 02 |KI.......P.m..Q.| +00000300 c0 ab 87 bc e0 3e 4b 89 53 3a e2 65 89 97 02 c1 |.....>K.S:.e....| +00000310 88 5a 97 82 3e 55 6b 7c d8 db b8 cc 1b 30 84 0a |.Z..>Uk|.....0..| +00000320 7a 97 71 e4 10 bb a4 39 8c 2a cf f5 88 c7 d1 95 |z.q....9.*......| +00000330 73 14 03 03 00 01 01 16 03 03 00 24 9f 1e f0 72 |s..........$...r| +00000340 92 ea dc f7 56 96 37 e4 69 db db 66 1d f6 94 c4 |....V.7.i..f....| +00000350 18 31 4f d0 5d c5 f4 53 21 aa 98 b1 dc 08 94 94 |.1O.]..S!.......| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 24 ee 68 c1 87 9f |..........$.h...| +00000010 d7 90 94 f1 3b 6d 26 0b 3d 89 7a 45 3b 52 5d 3c |....;m&.=.zE;R]<| +00000020 dd 7c c1 4e 57 3e a9 ee 91 be cf 2b a3 98 9d |.|.NW>.....+...| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1a 88 33 3e 2b 22 6b 92 d0 bb 8a 1e |......3>+"k.....| +00000010 9b f4 9e aa 91 8b 2b 95 ea 53 c8 03 0a 93 58 15 |......+..S....X.| +00000020 03 03 00 16 c4 67 79 ba ec cf 90 b1 f9 ac ec 64 |.....gy........d| +00000030 72 01 08 8f 3a 98 aa 66 25 00 |r...:..f%.| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA new file mode 100644 index 0000000000..0037af61a0 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA @@ -0,0 +1,133 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 53 04 f1 02 fd |....Y...U..S....| +00000010 41 bd ef ee f3 da fc 1a 31 8c 77 f2 e9 66 54 a0 |A.......1.w..fT.| +00000020 f4 15 b1 1c 84 0d 6d 74 87 ac 7d 20 78 17 8b 08 |......mt..} x...| +00000030 10 20 c9 44 e4 8a 43 af 4a c7 b8 3d 99 f2 f7 af |. .D..C.J..=....| +00000040 bb a3 21 2f 40 cc ed b6 da a8 a1 d5 c0 09 00 00 |..!/@...........| +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....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +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 d8 0c 00 00 d4 03 00 17 41 04 a9 |*............A..| +00000280 19 8b d9 9b 5c 7c 6a 7d 85 d2 70 4e 89 7e 0b 5b |....\|j}..pN.~.[| +00000290 dd 5e a1 63 8d 15 bc 0b 0c 47 3d 4d e8 a7 56 88 |.^.c.....G=M..V.| +000002a0 2e f6 7f e2 4d fc ed cc 03 ed a1 2d ac ae 81 a5 |....M......-....| +000002b0 e2 6d 7f 9f a3 93 e9 10 c1 0e 48 1b f3 f4 38 04 |.m........H...8.| +000002c0 03 00 8b 30 81 88 02 42 00 87 fe 7e 63 82 14 57 |...0...B...~c..W| +000002d0 dc 7d e2 0f cc 97 2d ba 3c a7 56 4a 17 a8 09 6a |.}....-.<.VJ...j| +000002e0 28 2e f2 66 1a 3f 2d 48 2b 6f 79 a1 60 cd 5e 10 |(..f.?-H+oy.`.^.| +000002f0 0b 0a 28 f2 5f e4 3f 4f f9 c9 91 34 d9 dc bc fc |..(._.?O...4....| +00000300 98 ea 77 0b 99 f8 a2 11 c4 bd 02 42 01 a0 b0 dc |..w........B....| +00000310 db 5b c2 09 99 bd ee a0 b9 aa 31 b9 10 84 22 be |.[........1...".| +00000320 5a 63 12 5a 43 00 8e c1 33 cc 91 bb c2 70 7a 63 |Zc.ZC...3....pzc| +00000330 19 82 c0 74 48 a1 c7 3d 1f f1 6f 4a 6f 6a 8c 3f |...tH..=..oJoj.?| +00000340 28 31 a8 0c 65 19 26 62 4b 7a 7c 4b ea 1a 16 03 |(1..e.&bKz|K....| +00000350 03 00 30 0d 00 00 28 03 01 02 40 00 20 06 01 06 |..0...(...@. ...| +00000360 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................| +00000370 01 03 02 03 03 02 01 02 02 02 03 01 01 00 00 0e |................| +00000380 00 00 00 |...| +>>> Flow 3 (client to server) +00000000 16 03 03 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0| +00000010 82 01 ed 30 82 01 58 a0 03 02 01 02 02 01 00 30 |...0..X........0| +00000020 0b 06 09 2a 86 48 86 f7 0d 01 01 05 30 26 31 10 |...*.H......0&1.| +00000030 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 6f |0...U....Acme Co| +00000040 31 12 30 10 06 03 55 04 03 13 09 31 32 37 2e 30 |1.0...U....127.0| +00000050 2e 30 2e 31 30 1e 17 0d 31 31 31 32 30 38 30 37 |.0.10...11120807| +00000060 35 35 31 32 5a 17 0d 31 32 31 32 30 37 30 38 30 |5512Z..121207080| +00000070 30 31 32 5a 30 26 31 10 30 0e 06 03 55 04 0a 13 |012Z0&1.0...U...| +00000080 07 41 63 6d 65 20 43 6f 31 12 30 10 06 03 55 04 |.Acme Co1.0...U.| +00000090 03 13 09 31 32 37 2e 30 2e 30 2e 31 30 81 9c 30 |...127.0.0.10..0| +000000a0 0b 06 09 2a 86 48 86 f7 0d 01 01 01 03 81 8c 00 |...*.H..........| +000000b0 30 81 88 02 81 80 4e d0 7b 31 e3 82 64 d9 59 c0 |0.....N.{1..d.Y.| +000000c0 c2 87 a4 5e 1e 8b 73 33 c7 63 53 df 66 92 06 84 |...^..s3.cS.f...| +000000d0 f6 64 d5 8f e4 36 a7 1d 2b e8 b3 20 36 45 23 b5 |.d...6..+.. 6E#.| +000000e0 e3 95 ae ed e0 f5 20 9c 8d 95 df 7f 5a 12 ef 87 |...... .....Z...| +000000f0 e4 5b 68 e4 e9 0e 74 ec 04 8a 7f de 93 27 c4 01 |.[h...t......'..| +00000100 19 7a bd f2 dc 3d 14 ab d0 54 ca 21 0c d0 4d 6e |.z...=...T.!..Mn| +00000110 87 2e 5c c5 d2 bb 4d 4b 4f ce b6 2c f7 7e 88 ec |..\...MKO..,.~..| +00000120 7c d7 02 91 74 a6 1e 0c 1a da e3 4a 5a 2e de 13 ||...t......JZ...| +00000130 9c 4c 40 88 59 93 02 03 01 00 01 a3 32 30 30 30 |.L@.Y.......2000| +00000140 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 00 a0 30 |...U...........0| +00000150 0d 06 03 55 1d 0e 04 06 04 04 01 02 03 04 30 0f |...U..........0.| +00000160 06 03 55 1d 23 04 08 30 06 80 04 01 02 03 04 30 |..U.#..0.......0| +00000170 0b 06 09 2a 86 48 86 f7 0d 01 01 05 03 81 81 00 |...*.H..........| +00000180 36 1f b3 7a 0c 75 c9 6e 37 46 61 2b d5 bd c0 a7 |6..z.u.n7Fa+....| +00000190 4b cc 46 9a 81 58 7c 85 79 29 c8 c8 c6 67 dd 32 |K.F..X|.y)...g.2| +000001a0 56 45 2b 75 b6 e9 24 a9 50 9a be 1f 5a fa 1a 15 |VE+u..$.P...Z...| +000001b0 d9 cc 55 95 72 16 83 b9 c2 b6 8f fd 88 8c 38 84 |..U.r.........8.| +000001c0 1d ab 5d 92 31 13 4f fd 83 3b c6 9d f1 11 62 b6 |..].1.O..;....b.| +000001d0 8b ec ab 67 be c8 64 b0 11 50 46 58 17 6b 99 1c |...g..d..PFX.k..| +000001e0 d3 1d fc 06 f1 0e e5 96 a8 0c f9 78 20 b7 44 18 |...........x .D.| +000001f0 51 8d 10 7e 4f 94 67 df a3 4e 70 73 8e 90 91 85 |Q..~O.g..Nps....| +00000200 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..| +00000210 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +00000220 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.| +00000230 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I| +00000240 a6 b5 68 1a 41 03 56 6b dc 5a 89 16 03 03 00 88 |..h.A.Vk.Z......| +00000250 0f 00 00 84 04 01 00 80 38 f2 16 e5 b5 86 16 62 |........8......b| +00000260 86 e1 7d 01 f1 a8 e1 f7 e7 85 b1 a0 17 ee 84 25 |..}............%| +00000270 cb 3c 46 61 1a 78 7b 1e ee 32 bc d9 6c fa 6b 76 |.>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 ee a8 82 bc 3f |..........@....?| +00000010 bf ab a6 e4 30 e0 3d f1 2f 19 a2 ac 7a 81 57 f1 |....0.=./...z.W.| +00000020 ee 67 3f 55 2b 30 fa 72 b5 10 03 ec 8d 0a 8f bb |.g?U+0.r........| +00000030 24 f5 45 f5 4e 53 4b 93 a5 0d 42 6c 46 69 98 fb |$.E.NSK...BlFi..| +00000040 63 c5 9f 95 65 d1 b6 f0 a4 15 bd |c...e......| +>>> 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 cb 4e bc d1 a9 58 ef c8 39 a9 36 |......N...X..9.6| +00000020 f4 35 05 96 8e a4 50 bc f4 15 06 f9 fd 41 6d 1e |.5....P......Am.| +00000030 5e 7c 82 63 94 15 03 03 00 30 00 00 00 00 00 00 |^|.c.....0......| +00000040 00 00 00 00 00 00 00 00 00 00 bd 77 87 a5 5a d4 |...........w..Z.| +00000050 b8 59 e6 6b 0f dd ea f9 ed 18 b2 9f a9 61 b4 3a |.Y.k.........a.:| +00000060 47 15 15 3b 83 ef e1 6d db a8 |G..;...m..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA new file mode 100644 index 0000000000..df3eaa4406 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA @@ -0,0 +1,126 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 51 02 00 00 4d 03 03 53 04 f1 02 1d |....Q...M..S....| +00000010 0e dc 86 e5 a9 07 71 46 15 34 af 47 15 3f 03 9c |......qF.4.G.?..| +00000020 fc d6 fd 44 7c f4 f1 c7 8d 6f f8 20 28 ea 3c dc |...D|....o. (.<.| +00000030 b2 4c b7 ba 20 88 c4 db a5 73 ea 93 ab 3a 85 a6 |.L.. ....s...:..| +00000040 8f 59 49 d9 a9 31 14 d5 a6 2b 4f d1 00 05 00 00 |.YI..1...+O.....| +00000050 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................| +00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 30 0d 00 |n8P)l........0..| +00000320 00 28 03 01 02 40 00 20 06 01 06 02 06 03 05 01 |.(...@. ........| +00000330 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................| +00000340 02 01 02 02 02 03 01 01 00 00 0e 00 00 00 |..............| +>>> Flow 3 (client to server) +00000000 16 03 03 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0| +00000010 82 01 ed 30 82 01 58 a0 03 02 01 02 02 01 00 30 |...0..X........0| +00000020 0b 06 09 2a 86 48 86 f7 0d 01 01 05 30 26 31 10 |...*.H......0&1.| +00000030 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 6f |0...U....Acme Co| +00000040 31 12 30 10 06 03 55 04 03 13 09 31 32 37 2e 30 |1.0...U....127.0| +00000050 2e 30 2e 31 30 1e 17 0d 31 31 31 32 30 38 30 37 |.0.10...11120807| +00000060 35 35 31 32 5a 17 0d 31 32 31 32 30 37 30 38 30 |5512Z..121207080| +00000070 30 31 32 5a 30 26 31 10 30 0e 06 03 55 04 0a 13 |012Z0&1.0...U...| +00000080 07 41 63 6d 65 20 43 6f 31 12 30 10 06 03 55 04 |.Acme Co1.0...U.| +00000090 03 13 09 31 32 37 2e 30 2e 30 2e 31 30 81 9c 30 |...127.0.0.10..0| +000000a0 0b 06 09 2a 86 48 86 f7 0d 01 01 01 03 81 8c 00 |...*.H..........| +000000b0 30 81 88 02 81 80 4e d0 7b 31 e3 82 64 d9 59 c0 |0.....N.{1..d.Y.| +000000c0 c2 87 a4 5e 1e 8b 73 33 c7 63 53 df 66 92 06 84 |...^..s3.cS.f...| +000000d0 f6 64 d5 8f e4 36 a7 1d 2b e8 b3 20 36 45 23 b5 |.d...6..+.. 6E#.| +000000e0 e3 95 ae ed e0 f5 20 9c 8d 95 df 7f 5a 12 ef 87 |...... .....Z...| +000000f0 e4 5b 68 e4 e9 0e 74 ec 04 8a 7f de 93 27 c4 01 |.[h...t......'..| +00000100 19 7a bd f2 dc 3d 14 ab d0 54 ca 21 0c d0 4d 6e |.z...=...T.!..Mn| +00000110 87 2e 5c c5 d2 bb 4d 4b 4f ce b6 2c f7 7e 88 ec |..\...MKO..,.~..| +00000120 7c d7 02 91 74 a6 1e 0c 1a da e3 4a 5a 2e de 13 ||...t......JZ...| +00000130 9c 4c 40 88 59 93 02 03 01 00 01 a3 32 30 30 30 |.L@.Y.......2000| +00000140 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 00 a0 30 |...U...........0| +00000150 0d 06 03 55 1d 0e 04 06 04 04 01 02 03 04 30 0f |...U..........0.| +00000160 06 03 55 1d 23 04 08 30 06 80 04 01 02 03 04 30 |..U.#..0.......0| +00000170 0b 06 09 2a 86 48 86 f7 0d 01 01 05 03 81 81 00 |...*.H..........| +00000180 36 1f b3 7a 0c 75 c9 6e 37 46 61 2b d5 bd c0 a7 |6..z.u.n7Fa+....| +00000190 4b cc 46 9a 81 58 7c 85 79 29 c8 c8 c6 67 dd 32 |K.F..X|.y)...g.2| +000001a0 56 45 2b 75 b6 e9 24 a9 50 9a be 1f 5a fa 1a 15 |VE+u..$.P...Z...| +000001b0 d9 cc 55 95 72 16 83 b9 c2 b6 8f fd 88 8c 38 84 |..U.r.........8.| +000001c0 1d ab 5d 92 31 13 4f fd 83 3b c6 9d f1 11 62 b6 |..].1.O..;....b.| +000001d0 8b ec ab 67 be c8 64 b0 11 50 46 58 17 6b 99 1c |...g..d..PFX.k..| +000001e0 d3 1d fc 06 f1 0e e5 96 a8 0c f9 78 20 b7 44 18 |...........x .D.| +000001f0 51 8d 10 7e 4f 94 67 df a3 4e 70 73 8e 90 91 85 |Q..~O.g..Nps....| +00000200 16 03 03 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 |...........mQ...| +00000210 3e fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c |>.u.A6..j.*.%.gL| +00000220 8e 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 |.b/0......+.#...| +00000230 1d f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 |..;...'..$...[.f| +00000240 0d 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be |.j.....C........| +00000250 c8 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce |..9L.....K.../..| +00000260 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V| +00000270 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....| +00000280 35 d4 1c 43 d1 30 6f 55 4e 0a 70 16 03 03 00 88 |5..C.0oUN.p.....| +00000290 0f 00 00 84 04 01 00 80 2a 1f ae 48 9f 86 16 dc |........*..H....| +000002a0 c2 55 1f 5f 95 81 ed 56 00 5d 35 46 e5 b6 57 d5 |.U._...V.]5F..W.| +000002b0 a6 3e 32 38 8b e2 c6 1c b9 b1 38 b2 da 66 45 ed |.>28......8..fE.| +000002c0 58 6a 7f 43 41 93 a5 09 da b9 04 ce 3f 13 8a 19 |Xj.CA.......?...| +000002d0 13 e9 2c 1f c5 e7 35 b4 2d ea 7c 81 90 33 c0 66 |..,...5.-.|..3.f| +000002e0 dc 41 8b 23 08 8f 69 d4 d6 a2 5f c1 bd 26 e6 2e |.A.#..i..._..&..| +000002f0 7f c8 7c a8 2d d4 08 95 ce 6e 58 54 04 a2 a6 63 |..|.-....nXT...c| +00000300 54 72 67 f2 7f 61 0a 6b 58 46 d4 88 95 38 37 f2 |Trg..a.kXF...87.| +00000310 93 95 48 56 14 a7 b9 7c 14 03 03 00 01 01 16 03 |..HV...|........| +00000320 03 00 24 64 bb 41 3a cb a2 2f 95 53 5c 2f f7 83 |..$d.A:../.S\/..| +00000330 a2 35 18 f6 d0 8d 6f e2 54 ed 2f 07 10 f4 36 e2 |.5....o.T./...6.| +00000340 3d e5 30 1d e3 63 01 |=.0..c.| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 24 0a 22 b6 bc da |..........$."...| +00000010 34 38 53 8e 80 e2 25 7b 31 2f 70 8e 3a db e8 a3 |48S...%{1/p.:...| +00000020 70 0e 88 22 b4 a8 be d4 a3 e3 cc 13 94 ef 47 |p.."..........G| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1a b4 9c b1 57 ea 01 03 fe 01 e7 1e |........W.......| +00000010 c4 a7 0f 25 14 99 00 4f 88 51 c1 98 6e 99 01 15 |...%...O.Q..n...| +00000020 03 03 00 16 2e c4 11 8b 1a fc 37 81 18 33 e4 9f |..........7..3..| +00000030 48 a3 29 e3 ad 9b 9b ec 9f 99 |H.).......| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES new file mode 100644 index 0000000000..76445903ba --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES @@ -0,0 +1,89 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 53 04 f1 02 a0 |....Y...U..S....| +00000010 5f bd a4 8d 98 93 b8 da 08 86 9f b2 be 9a a4 91 |_...............| +00000020 2b 3c 1f 18 f0 75 7c a9 a8 a0 f7 20 4a 89 9a d2 |+<...u|.... J...| +00000030 34 3b d9 b1 c2 fd 61 bd 97 19 22 ce b9 d1 5b a7 |4;....a..."...[.| +00000040 83 80 9c 19 d0 f5 a0 aa 4c ac 06 20 c0 09 00 00 |........L.. ....| +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....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +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 d7 0c 00 00 d3 03 00 17 41 04 3c |*............A.<| +00000280 8f 35 1e 47 5d 7b ad 13 0c e9 5c c0 97 c7 83 06 |.5.G]{....\.....| +00000290 49 0f 6c cf e5 4d 3b ed f7 1b c6 96 8d ba 54 35 |I.l..M;.......T5| +000002a0 7f df 35 e3 6e 28 e9 71 f2 24 b5 ab 17 2b 4b 2b |..5.n(.q.$...+K+| +000002b0 0c 8f 9f 48 89 73 8f 09 69 84 af 7f ec 43 7a 04 |...H.s..i....Cz.| +000002c0 03 00 8a 30 81 87 02 41 79 84 43 0c 78 fa 7e e2 |...0...Ay.C.x.~.| +000002d0 c5 51 c1 60 88 c4 4a 59 7d 02 fa dc 19 68 33 ed |.Q.`..JY}....h3.| +000002e0 19 ef a1 df ef 6b 21 a6 98 aa ba a9 13 70 91 0f |.....k!......p..| +000002f0 cc 6c 5c 1e 99 53 1b 42 51 6c 06 a7 3c c4 04 22 |.l\..S.BQl..<.."| +00000300 5d 0d c1 30 ab e3 ec b4 54 02 42 01 15 15 1a 6e |]..0....T.B....n| +00000310 6f f1 c6 b1 10 84 2c c8 04 de 2b 52 d5 b4 f7 c9 |o.....,...+R....| +00000320 4f 6d 0e 0e 26 45 1d 7a 28 59 2b 8b f6 92 3a 23 |Om..&E.z(Y+...:#| +00000330 7a 39 9c d5 4e cc 5d c5 45 92 9c d0 5f 33 12 e3 |z9..N.].E..._3..| +00000340 2b 29 39 52 bb 16 aa e1 72 9e b5 fe 99 16 03 03 |+)9R....r.......| +00000350 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..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +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 40 00 00 00 00 00 00 00 00 00 00 |.....@..........| +00000060 00 00 00 00 00 00 20 a3 f8 5a e2 ea f3 09 19 3e |...... ..Z.....>| +00000070 4a 54 69 70 06 5b 17 35 0f ed e7 30 3b 6f eb a1 |JTip.[.5...0;o..| +00000080 cb 9c 35 81 10 2e 34 f7 12 a5 e4 63 20 b2 65 31 |..5...4....c .e1| +00000090 19 da 30 43 39 59 |..0C9Y| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 8d 4d 31 07 df |..........@.M1..| +00000010 ab 41 f5 19 9c 1a 57 fc 33 ab 5f e6 bd 45 b9 fa |.A....W.3._..E..| +00000020 7f db c0 df 72 f2 3b ef aa d4 5e 34 e6 3d 44 7c |....r.;...^4.=D|| +00000030 12 05 c7 57 da 54 b1 e3 66 f0 0a ab cd 15 a5 bf |...W.T..f.......| +00000040 c5 c2 07 a9 d9 a7 2e 5e 29 da da |.......^)..| +>>> 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 dc 03 7b 29 2c 49 64 58 2d dc f7 |.......{),IdX-..| +00000020 26 a1 3b ec 2d e8 30 c4 6c a3 ff e2 bc b5 a4 a6 |&.;.-.0.l.......| +00000030 93 ce 14 bd da 15 03 03 00 30 00 00 00 00 00 00 |.........0......| +00000040 00 00 00 00 00 00 00 00 00 00 a6 77 10 30 15 eb |...........w.0..| +00000050 ed cf 73 5b 74 5d 09 52 4a 5b e2 f0 e4 67 f8 7a |..s[t].RJ[...g.z| +00000060 5e 5e fc ba 7f 80 0a d2 f4 fb |^^........| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM new file mode 100644 index 0000000000..fb5af17f0c --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM @@ -0,0 +1,84 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 53 04 f1 02 48 |....Y...U..S...H| +00000010 03 36 01 05 56 6f f0 54 d2 c3 d3 41 c2 e2 69 7b |.6..Vo.T...A..i{| +00000020 50 f8 03 ef 3f 5d 7c e6 9c cb fe 20 82 a0 81 fd |P...?]|.... ....| +00000030 72 4b b8 e6 29 76 3b 0f 1d 0a b7 82 9d 0b cf a0 |rK..)v;.........| +00000040 65 b1 56 53 c9 d5 58 7b f0 b6 2d cf c0 2b 00 00 |e.VS..X{..-..+..| +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....| +00000080 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b 30 |0...*.H.=..0E1.0| +00000090 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +000000a0 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +000000b0 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +000000c0 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +000000d0 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 36 |td0...1211221506| +000000e0 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 33 |32Z..22112015063| +000000f0 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 |2Z0E1.0...U....A| +00000100 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 |U1.0...U....Some| +00000110 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 |-State1!0...U...| +00000120 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 |.Internet Widgit| +00000130 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 07 |s Pty Ltd0..0...| +00000140 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 |*.H.=....+...#..| +00000150 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e c3 |...........Hs6~.| +00000160 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 e6 |.V.".=S.;M!=.ku.| +00000170 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 64 |.....&.....r2|.d| +00000180 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a 69 |/....h#.~..%.H:i| +00000190 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 83 |.(m.7...b....pb.| +000001a0 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b 23 |...d1...1...h..#| +000001b0 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 dd |.vd?.\....XX._p.| +000001c0 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 9a |...........0f[f.| +000001d0 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce 3d | .'...;0...*.H.=| +000001e0 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f eb |......0...B...O.| +000001f0 e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 5e |.E.H}.......Gp.^| +00000200 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee 0b |../...M.a@......| +00000210 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 59 |~.~.v..;~.?....Y| +00000220 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 01 |.G-|..N....o..B.| +00000230 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 33 |M..g..-...?..%.3| +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 d7 0c 00 00 d3 03 00 17 41 04 86 |*............A..| +00000280 36 b4 78 76 87 70 ed ae 0d 34 70 3d 16 e5 a4 db |6.xv.p...4p=....| +00000290 ae 28 58 4c 01 5a 56 73 a7 0d 34 59 a7 04 75 69 |.(XL.ZVs..4Y..ui| +000002a0 f2 55 24 40 b0 33 c6 93 ff ae e0 14 f5 4b ce a8 |.U$@.3.......K..| +000002b0 e2 e6 9a 67 1d 66 fb 8f fd 56 59 e7 73 f2 2c 04 |...g.f...VY.s.,.| +000002c0 03 00 8a 30 81 87 02 41 73 ab a8 3c 64 17 69 9f |...0...As..>> 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..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +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 87 7a |.....(.........z| +00000060 82 d7 46 25 1d a6 bb c2 a8 a8 4e a5 d1 f8 02 db |..F%......N.....| +00000070 33 33 ca 78 b6 d3 bd 77 8a 33 23 a7 95 fb |33.x...w.3#...| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 ce a1 9d 01 c0 |..........(.....| +00000010 31 e5 d5 57 16 e1 a6 b3 8b 25 58 0f fa 2a de 3e |1..W.....%X..*.>| +00000020 0c d9 06 11 a6 b0 d7 b0 33 ad 31 73 5b 26 b4 d2 |........3.1s[&..| +00000030 12 56 c8 |.V.| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 d5 04 4c |...............L| +00000010 7b 35 b4 d7 90 ae fe 00 d2 f2 4b 76 f1 36 5e 24 |{5........Kv.6^$| +00000020 4a aa 94 15 03 03 00 1a 00 00 00 00 00 00 00 02 |J...............| +00000030 d3 1c 41 37 ab f6 17 79 f0 01 a4 19 a5 75 7a 8e |..A7...y.....uz.| +00000040 a3 b2 |..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES new file mode 100644 index 0000000000..5336bbbad8 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES @@ -0,0 +1,99 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 53 04 f1 02 41 |....Y...U..S...A| +00000010 95 cc 56 30 65 46 24 75 d5 9e 3c a7 5b 6c 99 fe |..V0eF$u..<.[l..| +00000020 86 35 23 42 3a 8f 4d 4c b9 98 7d 20 a7 46 43 72 |.5#B:.ML..} .FCr| +00000030 66 bb b6 ad ff ad cf 63 37 fe 6b b4 78 94 08 49 |f......c7.k.x..I| +00000040 54 06 ed f4 85 73 38 4a c6 fe b6 98 c0 13 00 00 |T....s8J........| +00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................| +00000060 03 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 02 |.............0..| +00000070 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 bb |.0..............| +00000080 a4 8a 7f b8 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....| +00000090 01 05 05 00 30 45 31 0b 30 09 06 03 55 04 06 13 |....0E1.0...U...| +000000a0 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f |.AU1.0...U....So| +000000b0 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 |me-State1!0...U.| +000000c0 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 |...Internet Widg| +000000d0 69 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 |its Pty Ltd0...1| +000000e0 30 30 34 32 34 30 39 30 39 33 38 5a 17 0d 31 31 |00424090938Z..11| +000000f0 30 34 32 34 30 39 30 39 33 38 5a 30 45 31 0b 30 |0424090938Z0E1.0| +00000100 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 |...U....AU1.0...| +00000110 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 |U....Some-State1| +00000120 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e |!0...U....Intern| +00000130 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c |et Widgits Pty L| +00000140 74 64 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 |td0..0...*.H....| +00000150 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 bb |........0.......| +00000160 79 d6 f5 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 |y......F...i..+.| +00000170 43 5a d0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c |CZ..-.zC...R..eL| +00000180 2c 78 b8 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 |,x.#........;~b.| +00000190 2c a5 33 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b |,.3...\zV.....X{| +000001a0 26 3f b5 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a |&?......!.J..T.Z| +000001b0 bf ef 42 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 |..Bq......~.}}..| +000001c0 39 c4 a2 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 cf |9....Q.|..L;2f..| +000001d0 af b1 1d b8 71 9a 1d db db 89 6b ae da 2d 79 02 |....q.....k..-y.| +000001e0 03 01 00 01 a3 81 a7 30 81 a4 30 1d 06 03 55 1d |.......0..0...U.| +000001f0 0e 04 16 04 14 b1 ad e2 85 5a cf cb 28 db 69 ce |.........Z..(.i.| +00000200 23 69 de d3 26 8e 18 88 39 30 75 06 03 55 1d 23 |#i..&...90u..U.#| +00000210 04 6e 30 6c 80 14 b1 ad e2 85 5a cf cb 28 db 69 |.n0l......Z..(.i| +00000220 ce 23 69 de d3 26 8e 18 88 39 a1 49 a4 47 30 45 |.#i..&...9.I.G0E| +00000230 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 |1.0...U....AU1.0| +00000240 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 |...U....Some-Sta| +00000250 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 |te1!0...U....Int| +00000260 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 |ernet Widgits Pt| +00000270 79 20 4c 74 64 82 09 00 85 b0 bb a4 8a 7f b8 ca |y Ltd...........| +00000280 30 0c 06 03 55 1d 13 04 05 30 03 01 01 ff 30 0d |0...U....0....0.| +00000290 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 03 81 81 |..*.H...........| +000002a0 00 08 6c 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 |..lE$.k.Y..R....| +000002b0 d7 87 9d 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 |...zdu.Z.f..+...| +000002c0 66 1f eb 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 |f..O8.n`....A..%| +000002d0 13 b1 18 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 |...z$.0.........| +000002e0 31 59 db 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a |1Y....x.PV\..Z-Z| +000002f0 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 |_3....u....R....| +00000300 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 |.. _..........W.| +00000310 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 bd |p.&mq..&n8P)l...| +00000320 d9 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 48 |.............A.H| +00000330 68 d8 8a 10 b4 bf eb 8d d1 98 b0 a6 f4 47 5d 91 |h............G].| +00000340 61 da 50 d9 85 7b 5d 90 02 2c 38 c9 af 81 d3 55 |a.P..{]..,8....U| +00000350 07 62 b1 62 58 7f 39 94 d7 91 96 a8 1f 47 60 a5 |.b.bX.9......G`.| +00000360 c0 04 f2 fb cb 15 75 a6 16 3f 94 53 7c ff dd 04 |......u..?.S|...| +00000370 01 00 80 b9 82 fa 0b f8 8c 94 2c 6e 05 81 7d 80 |..........,n..}.| +00000380 5d 9a 77 78 af c8 33 5d 89 7e 2e 3c e5 72 66 a8 |].wx..3].~.<.rf.| +00000390 f1 5c 02 04 02 70 76 7b 45 ff 0d 29 a0 cb 0d db |.\...pv{E..)....| +000003a0 7a 4c c4 13 19 cd 47 b2 f1 c9 43 4f 95 d2 f1 c6 |zL....G...CO....| +000003b0 bc ae 31 4a 9d de 80 b2 a4 b7 b6 dd 8c 03 3e 2a |..1J..........>*| +000003c0 46 5e d1 e7 5b c5 9e 06 58 f3 55 b2 77 09 f3 98 |F^..[...X.U.w...| +000003d0 d5 7f 5a 74 64 7e 48 22 8f 7d a8 68 b6 1d 90 df |..Ztd~H".}.h....| +000003e0 2c 91 d7 c5 07 3d d1 6f e9 c1 91 03 3c 23 5a 56 |,....=.o....<#ZV| +000003f0 3b b2 c2 16 03 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..| +00000010 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +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 40 00 00 00 00 00 00 00 00 00 00 |.....@..........| +00000060 00 00 00 00 00 00 59 e6 92 05 27 ec 09 2c b0 a5 |......Y...'..,..| +00000070 2a fb 7e f1 03 53 16 63 68 a1 86 13 bb da 98 27 |*.~..S.ch......'| +00000080 6d 42 08 35 6a ec 58 61 2a 4d 44 ec ae c5 b9 d2 |mB.5j.Xa*MD.....| +00000090 76 57 1f 75 9f 8d |vW.u..| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 40 6e 03 d0 e6 98 |..........@n....| +00000010 1f f5 39 7b 06 9f 95 f0 7a 88 35 7c 55 db c3 2f |..9{....z.5|U../| +00000020 00 ef 5b d3 62 87 a2 94 da 2f f6 4a 89 c9 a8 3d |..[.b..../.J...=| +00000030 3a 92 db 77 35 92 01 4b f5 c5 6b 95 09 9f cd 79 |:..w5..K..k....y| +00000040 3c af 37 5b 27 bf 93 3e 04 55 71 |<.7['..>.Uq| +>>> 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 bc c9 d0 8e 80 14 de 32 18 49 e8 |............2.I.| +00000020 20 dc 5e 6c e4 6d 14 00 df 51 71 fb 86 95 16 4c | .^l.m...Qq....L| +00000030 04 8e 71 e1 48 15 03 03 00 30 00 00 00 00 00 00 |..q.H....0......| +00000040 00 00 00 00 00 00 00 00 00 00 b7 6d 30 72 61 53 |...........m0raS| +00000050 d8 0a d4 1d ae e5 d4 22 46 c9 d5 4e 4a 86 f5 ac |......."F..NJ...| +00000060 72 98 c6 db 38 29 97 2c 84 0b |r...8).,..| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4 b/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4 new file mode 100644 index 0000000000..0377f052ae --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4 @@ -0,0 +1,83 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 75 01 00 00 71 03 03 00 00 00 00 00 |....u...q.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 1a c0 2f |.............../| +00000030 c0 2b c0 11 c0 07 c0 13 c0 09 c0 14 c0 0a 00 05 |.+..............| +00000040 00 2f 00 35 c0 12 00 0a 01 00 00 2e 00 05 00 05 |./.5............| +00000050 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 18 00 |................| +00000060 19 00 0b 00 02 01 00 00 0d 00 0a 00 08 04 01 04 |................| +00000070 03 02 01 02 03 ff 01 00 01 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 51 02 00 00 4d 03 03 53 04 f1 02 9d |....Q...M..S....| +00000010 2e 4e d9 17 4a 35 fa 9d 94 f6 45 0a f6 6b 5d 1c |.N..J5....E..k].| +00000020 1e 15 19 8d 6d 94 cc 90 d9 39 94 20 8b 4b de 76 |....m....9. .K.v| +00000030 d5 64 5d b7 19 df e7 eb 7e a0 22 c4 09 38 a0 12 |.d].....~."..8..| +00000040 d5 59 10 c8 31 06 dc fc e4 9d d1 80 00 05 00 00 |.Y..1...........| +00000050 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................| +00000060 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000070 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000080 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000090 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +000000a0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +000000b0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000c0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000d0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000e0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000f0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +00000100 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +00000110 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000120 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000130 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000140 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000150 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000160 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000170 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000180 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000190 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +000001a0 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +000001b0 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001c0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001d0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001e0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001f0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +00000200 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +00000210 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000220 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000230 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000240 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000250 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000260 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000270 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000280 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000290 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +000002a0 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +000002b0 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002c0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002d0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002e0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002f0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +00000300 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +00000310 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 04 0e 00 |n8P)l...........| +00000320 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 6d 51 f3 7f f9 |...........mQ...| +00000010 3e fb 75 82 41 36 83 e8 6a ee 2a 2e 25 90 67 4c |>.u.A6..j.*.%.gL| +00000020 8e 62 2f 30 81 17 e0 85 09 0c 2b b7 23 d7 b0 e2 |.b/0......+.#...| +00000030 1d f7 3b d7 f5 a1 27 b6 ee 24 b6 1b cc 5b ea 66 |..;...'..$...[.f| +00000040 0d 6a f4 e5 85 f9 da 43 b4 0e 86 85 e1 f5 aa be |.j.....C........| +00000050 c8 ce 39 4c 9c 86 00 08 c2 4b e2 c6 ec 2f f7 ce |..9L.....K.../..| +00000060 e6 bd 77 82 6f 23 b6 e0 bd a2 92 b7 3a ac e8 56 |..w.o#......:..V| +00000070 f1 af 54 5e 46 87 e9 3b 33 e7 b8 28 b7 d6 c8 90 |..T^F..;3..(....| +00000080 35 d4 1c 43 d1 30 6f 55 4e 0a 70 14 03 03 00 01 |5..C.0oUN.p.....| +00000090 01 16 03 03 00 24 37 14 b2 97 7b b5 f0 9a 38 05 |.....$7...{...8.| +000000a0 22 35 69 9c 95 2f 86 4b 37 98 22 db 4e 9a 46 9c |"5i../.K7.".N.F.| +000000b0 b9 81 74 72 58 18 53 0c 5c 3c |..trX.S.\<| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 24 3c b3 e7 77 5a |..........$<..wZ| +00000010 7c 36 5a 74 74 26 8d 5b 5a 09 96 60 e8 24 45 2f ||6Ztt&.[Z..`.$E/| +00000020 c2 39 14 5e db 58 12 49 ad a8 b6 ea ef 58 16 |.9.^.X.I.....X.| +>>> Flow 5 (client to server) +00000000 17 03 03 00 1a 6d 29 d7 ba 2f 85 02 b6 f0 82 64 |.....m)../.....d| +00000010 6c 55 ae ab f6 fd 14 ff b8 38 f0 f8 a6 ea cc 15 |lU.......8......| +00000020 03 03 00 16 10 c5 d9 41 7b e2 89 67 dc 29 8e f8 |.......A{..g.)..| +00000030 b5 ab 32 91 44 2c 27 84 49 f7 |..2.D,'.I.| diff --git a/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES b/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES new file mode 100644 index 0000000000..a6c7a4196c --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES @@ -0,0 +1,83 @@ +>>> Flow 1 (client to server) +00000000 16 03 00 00 2f 01 00 00 2b 03 00 52 cc 57 59 d8 |..../...+..R.WY.| +00000010 86 d6 07 ae e0 8d 63 b7 1e cb aa c6 67 32 c8 dd |......c.....g2..| +00000020 68 03 d8 3d 37 18 72 c3 c0 f1 9d 00 00 04 00 0a |h..=7.r.........| +00000030 00 ff 01 00 |....| +>>> Flow 2 (server to client) +00000000 16 03 00 00 31 02 00 00 2d 03 00 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 0a 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 00 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 00 00 04 0e 00 |n8P)l...........| +00000300 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 00 00 84 10 00 00 80 75 e0 c9 76 d6 e9 34 |.........u..v..4| +00000010 1d e3 31 9e db 3b 03 41 93 e8 db 73 7c e9 3f 6a |..1..;.A...s|.?j| +00000020 d8 2a 7b 25 83 4f 45 de 3f 78 3f b6 53 a7 b4 6c |.*{%.OE.?x?.S..l| +00000030 e3 87 c4 c3 70 55 71 79 55 dc 74 98 84 21 19 13 |....pUqyU.t..!..| +00000040 be d5 8e 0a ff 2f 9f 7a 6b d4 6c ef 78 d1 cb 65 |...../.zk.l.x..e| +00000050 32 4c 0c c5 29 b9 60 94 c6 79 56 a2 aa 2d d9 ad |2L..).`..yV..-..| +00000060 51 2c 54 1b 28 23 33 54 cd 48 cb 80 13 45 3d 4a |Q,T.(#3T.H...E=J| +00000070 8e 2f f2 da bd 68 3e 1b eb 73 f9 2d 35 6b b1 40 |./...h>..s.-5k.@| +00000080 2e 6d 9d 1c e9 c1 02 80 37 14 03 00 00 01 01 16 |.m......7.......| +00000090 03 00 00 40 f7 c3 dd a4 64 3d 81 24 de a2 81 7d |...@....d=.$...}| +000000a0 e4 df 78 46 e7 ba 93 6c 36 43 05 96 fc 75 ef ec |..xF...l6C...u..| +000000b0 a5 46 6d 47 a5 be 74 ad 15 93 d9 87 4f 1d e2 b3 |.FmG..t.....O...| +000000c0 03 ff 2e 89 6e 50 f4 d6 a6 e2 b3 54 cb 74 07 f7 |....nP.....T.t..| +000000d0 ca 1b 8c 0a |....| +>>> Flow 4 (server to client) +00000000 14 03 00 00 01 01 16 03 00 00 40 6d 3d d8 d5 cf |..........@m=...| +00000010 05 7d 98 8c 28 28 e2 43 ab ad 4a fa ae bf ec c3 |.}..((.C..J.....| +00000020 9c 0a 13 4d 28 a4 45 c4 b9 f2 bc c5 12 a2 68 91 |...M(.E.......h.| +00000030 77 fa 72 f8 9e 4e b7 1f b4 02 02 e3 5d 57 b0 8b |w.r..N......]W..| +00000040 d8 90 0c 9d e6 df 5b 90 92 a1 0d 17 03 00 00 18 |......[.........| +00000050 91 48 8a e1 d6 bf 79 1c d5 0a 70 d5 94 20 25 78 |.H....y...p.. %x| +00000060 d8 84 c8 6e 54 f0 99 01 17 03 00 00 28 74 19 90 |...nT.......(t..| +00000070 41 44 53 27 bb fb 1f fd 71 34 20 61 a0 eb a4 7c |ADS'....q4 a...|| +00000080 fe 36 f8 4b d7 b0 27 d3 b9 36 e1 67 af 2d 0e 23 |.6.K..'..6.g.-.#| +00000090 2b 76 a7 2f c3 15 03 00 00 18 db fc e9 fd 87 5f |+v./..........._| +000000a0 92 a8 3d 4b 35 f5 c6 48 2c b4 42 50 c3 81 28 f0 |..=K5..H,.BP..(.| +000000b0 2b 41 |+A| diff --git a/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES b/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES new file mode 100644 index 0000000000..4885b267da --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES @@ -0,0 +1,84 @@ +>>> Flow 1 (client to server) +00000000 16 03 00 00 2f 01 00 00 2b 03 00 52 cc 57 59 30 |..../...+..R.WY0| +00000010 e1 ee 8c 60 5b 40 dd 95 bd b4 84 87 2f 01 15 e7 |...`[@....../...| +00000020 50 88 4c 82 6b 6d 93 8a 57 d0 27 00 00 04 00 2f |P.L.km..W.'..../| +00000030 00 ff 01 00 |....| +>>> Flow 2 (server to client) +00000000 16 03 00 00 31 02 00 00 2d 03 00 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2f 00 00 |............./..| +00000030 05 ff 01 00 01 00 16 03 00 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 00 00 04 0e 00 |n8P)l...........| +00000300 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 00 00 84 10 00 00 80 74 50 05 6f f5 83 c9 |.........tP.o...| +00000010 f5 0c 5a 65 c7 4e c6 f3 87 96 d7 5d 3e 88 27 32 |..Ze.N.....]>.'2| +00000020 89 12 ba ec db ef c0 85 70 84 ed b6 83 03 8f 44 |........p......D| +00000030 f5 6f fa fa d0 1f 95 30 d1 ae a7 71 cf ee e9 b1 |.o.....0...q....| +00000040 80 7b 34 a9 ea 1b 5e e5 71 40 3f e8 7d 30 d1 8b |.{4...^.q@?.}0..| +00000050 11 f1 68 1f c8 25 f0 77 c5 af b3 92 6e d9 81 cc |..h..%.w....n...| +00000060 f8 fd 82 95 cc 1f 4a b1 05 15 7a b3 a1 22 33 09 |......J...z.."3.| +00000070 e7 a5 c2 89 7f 03 e0 91 b6 61 a3 a0 4e 17 0d 7a |.........a..N..z| +00000080 13 01 c4 b6 50 c7 d9 81 15 14 03 00 00 01 01 16 |....P...........| +00000090 03 00 00 40 56 da 56 ab e6 26 98 58 53 1f 36 b5 |...@V.V..&.XS.6.| +000000a0 03 14 bd 42 29 ee 9c 7c e4 48 26 82 68 ae fd fe |...B)..|.H&.h...| +000000b0 5e a4 43 22 75 95 7b c8 77 88 fd d6 d4 9b c9 b5 |^.C"u.{.w.......| +000000c0 ee 3e a6 e8 c5 04 90 63 3f ac be 56 67 da 30 d4 |.>.....c?..Vg.0.| +000000d0 64 fb a8 a0 |d...| +>>> Flow 4 (server to client) +00000000 14 03 00 00 01 01 16 03 00 00 40 96 af fb 79 96 |..........@...y.| +00000010 92 97 2d d0 67 46 1e 08 b5 35 65 ef dc bc 8e 57 |..-.gF...5e....W| +00000020 53 b7 36 58 74 d7 88 b1 55 fc eb fa 2e f3 17 b7 |S.6Xt...U.......| +00000030 62 58 a0 9d 99 e1 85 d4 33 e0 b4 1f 1d 94 f2 88 |bX......3.......| +00000040 d5 9a 34 5b 74 cd d2 ff 87 bd 52 17 03 00 00 20 |..4[t.....R.... | +00000050 c6 61 c2 28 ac d2 0c 08 7f f1 c2 62 af 37 7e 78 |.a.(.......b.7~x| +00000060 e8 e2 a1 54 f2 3a 80 97 f8 47 64 f2 cd 94 dd 0b |...T.:...Gd.....| +00000070 17 03 00 00 30 b8 40 8f a3 18 ff 03 84 d4 1c 28 |....0.@........(| +00000080 82 ce d8 9a 81 3a dd 23 7c 65 d8 ca f7 f1 46 1b |.....:.#|e....F.| +00000090 70 f0 d7 d9 54 a7 71 e6 4d d4 25 61 5a e4 30 d3 |p...T.q.M.%aZ.0.| +000000a0 4a 42 ae 26 a5 15 03 00 00 20 c4 e8 ed 40 57 00 |JB.&..... ...@W.| +000000b0 dc a5 0e 82 90 47 92 08 dd 7e 50 6b 30 66 5e 90 |.....G...~Pk0f^.| +000000c0 73 7c 81 93 8d 24 b1 06 e7 39 |s|...$...9| diff --git a/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4 b/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4 new file mode 100644 index 0000000000..1314b659bf --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4 @@ -0,0 +1,79 @@ +>>> Flow 1 (client to server) +00000000 16 03 00 00 2f 01 00 00 2b 03 00 52 cc 57 59 79 |..../...+..R.WYy| +00000010 b9 3b ef df 53 fb 09 f6 01 e5 18 0a fc 3d 65 bb |.;..S........=e.| +00000020 cf 9c 4c 77 b1 e8 6b 4f 5f c7 94 00 00 04 00 05 |..Lw..kO_.......| +00000030 00 ff 01 00 |....| +>>> Flow 2 (server to client) +00000000 16 03 00 00 31 02 00 00 2d 03 00 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 00 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 00 00 04 0e 00 |n8P)l...........| +00000300 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 00 00 84 10 00 00 80 4d 66 7a f3 f8 ab 86 |.........Mfz....| +00000010 43 4c 5f 7c 52 ca e7 3f ba 62 b3 82 88 16 7d ca |CL_|R..?.b....}.| +00000020 3a 66 15 c0 36 55 2c ab bf 30 6b cd 9c d8 b9 48 |:f..6U,..0k....H| +00000030 03 c9 d0 98 ab 0b a6 5b 39 c8 fe 82 8e bb f0 16 |.......[9.......| +00000040 6f 96 62 81 f2 dc 52 02 c9 de e4 47 73 21 6e 1e |o.b...R....Gs!n.| +00000050 3a 11 89 7a e2 6b 9e 04 64 72 15 ba 2d 10 a2 69 |:..z.k..dr..-..i| +00000060 07 e6 ba 17 cf 54 d6 4e 5f 99 e8 59 8b 54 ce 8e |.....T.N_..Y.T..| +00000070 6b 58 ba 83 68 46 4a 5f 43 3e 9b e1 32 a2 19 42 |kX..hFJ_C>..2..B| +00000080 46 0f e4 47 1a 3b 16 5f e1 14 03 00 00 01 01 16 |F..G.;._........| +00000090 03 00 00 3c 78 7e ee da 0d 38 0b 1a d6 d4 8e d5 |...>> Flow 4 (server to client) +00000000 14 03 00 00 01 01 16 03 00 00 3c 23 29 64 62 23 |..........<#)db#| +00000010 19 20 f8 2e 15 07 ee c8 f4 ab f0 3e 66 c3 ed 7b |. .........>f..{| +00000020 7c a7 c2 7e c3 25 3c 8f f3 04 dc 37 e8 fc 0a 1d ||..~.%<....7....| +00000030 fa 7a 09 d4 21 11 e3 24 21 4b 37 d1 85 cc 40 bf |.z..!..$!K7...@.| +00000040 bd bd f8 59 6b cd 73 17 03 00 00 21 47 1d ac 54 |...Yk.s....!G..T| +00000050 bd 58 a6 c0 04 e2 0c 6b 66 64 5a 85 09 0e 47 fc |.X.....kfdZ...G.| +00000060 0b 57 ee f1 24 b6 89 57 46 be 6b 0d f2 15 03 00 |.W..$..WF.k.....| +00000070 00 16 b4 f7 34 99 19 43 b6 b3 5a 8b c3 d2 67 2f |....4..C..Z...g/| +00000080 3b 19 1c 31 d4 f9 bd 96 |;..1....| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES new file mode 100644 index 0000000000..9b8cb4d9b6 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES @@ -0,0 +1,84 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 76 01 00 00 72 03 01 53 04 f0 f9 4b |....v...r..S...K| +00000010 30 a8 68 d0 79 13 14 69 ee 3b 5d 05 cb 71 63 43 |0.h.y..i.;]..qcC| +00000020 4a 55 6b 05 25 53 19 ba e0 2f b1 00 00 04 c0 0a |JUk.%S.../......| +00000030 00 ff 01 00 00 45 00 0b 00 04 03 00 01 02 00 0a |.....E..........| +00000040 00 34 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 |.4.2............| +00000050 00 09 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 |................| +00000060 00 15 00 04 00 05 00 12 00 13 00 01 00 02 00 03 |................| +00000070 00 0f 00 10 00 11 00 0f 00 01 01 |...........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 31 02 00 00 2d 03 01 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 0a 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 01 02 0e 0b 00 02 0a 00 |................| +00000040 02 07 00 02 04 30 82 02 00 30 82 01 62 02 09 00 |.....0...0..b...| +00000050 b8 bf 2d 47 a0 d2 eb f4 30 09 06 07 2a 86 48 ce |..-G....0...*.H.| +00000060 3d 04 01 30 45 31 0b 30 09 06 03 55 04 06 13 02 |=..0E1.0...U....| +00000070 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +00000080 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000090 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +000000a0 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 32 |ts Pty Ltd0...12| +000000b0 31 31 32 32 31 35 30 36 33 32 5a 17 0d 32 32 31 |1122150632Z..221| +000000c0 31 32 30 31 35 30 36 33 32 5a 30 45 31 0b 30 09 |120150632Z0E1.0.| +000000d0 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 55 |..U....AU1.0...U| +000000e0 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 |....Some-State1!| +000000f0 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 |0...U....Interne| +00000100 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 |t Widgits Pty Lt| +00000110 64 30 81 9b 30 10 06 07 2a 86 48 ce 3d 02 01 06 |d0..0...*.H.=...| +00000120 05 2b 81 04 00 23 03 81 86 00 04 00 c4 a1 ed be |.+...#..........| +00000130 98 f9 0b 48 73 36 7e c3 16 56 11 22 f2 3d 53 c3 |...Hs6~..V.".=S.| +00000140 3b 4d 21 3d cd 6b 75 e6 f6 b0 dc 9a df 26 c1 bc |;M!=.ku......&..| +00000150 b2 87 f0 72 32 7c b3 64 2f 1c 90 bc ea 68 23 10 |...r2|.d/....h#.| +00000160 7e fe e3 25 c0 48 3a 69 e0 28 6d d3 37 00 ef 04 |~..%.H:i.(m.7...| +00000170 62 dd 0d a0 9c 70 62 83 d8 81 d3 64 31 aa 9e 97 |b....pb....d1...| +00000180 31 bd 96 b0 68 c0 9b 23 de 76 64 3f 1a 5c 7f e9 |1...h..#.vd?.\..| +00000190 12 0e 58 58 b6 5f 70 dd 9b d8 ea d5 d7 f5 d5 cc |..XX._p.........| +000001a0 b9 b6 9f 30 66 5b 66 9a 20 e2 27 e5 bf fe 3b 30 |...0f[f. .'...;0| +000001b0 09 06 07 2a 86 48 ce 3d 04 01 03 81 8c 00 30 81 |...*.H.=......0.| +000001c0 88 02 42 01 88 a2 4f eb e2 45 c5 48 7d 1b ac f5 |..B...O..E.H}...| +000001d0 ed 98 9d ae 47 70 c0 5e 1b b6 2f bd f1 b6 4d b7 |....Gp.^../...M.| +000001e0 61 40 d3 11 a2 ce ee 0b 7e 92 7e ff 76 9d c3 3b |a@......~.~.v..;| +000001f0 7e a5 3f ce fa 10 e2 59 ec 47 2d 7c ac da 4e 97 |~.?....Y.G-|..N.| +00000200 0e 15 a0 6f d0 02 42 01 4d fc be 67 13 9c 2d 05 |...o..B.M..g..-.| +00000210 0e bd 3f a3 8c 25 c1 33 13 83 0d 94 06 bb d4 37 |..?..%.3.......7| +00000220 7a f6 ec 7a c9 86 2e dd d7 11 69 7f 85 7c 56 de |z..z......i..|V.| +00000230 fb 31 78 2b e4 c7 78 0d ae cb be 9e 4e 36 24 31 |.1x+..x.....N6$1| +00000240 7b 6a 0f 39 95 12 07 8f 2a 16 03 01 00 d6 0c 00 |{j.9....*.......| +00000250 00 d2 03 00 17 41 04 1e 18 37 ef 0d 19 51 88 35 |.....A...7...Q.5| +00000260 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 3e |uq..T[....g..$ >| +00000270 b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f 6c |.V...(^.+-O....l| +00000280 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 1a |K[.V.2B.X..I..h.| +00000290 41 03 56 6b dc 5a 89 00 8b 30 81 88 02 42 00 c6 |A.Vk.Z...0...B..| +000002a0 85 8e 06 b7 04 04 e9 cd 9e 3e cb 66 23 95 b4 42 |.........>.f#..B| +000002b0 9c 64 81 39 05 3f b5 21 f8 28 af 60 6b 4d 3d ba |.d.9.?.!.(.`kM=.| +000002c0 a1 4b 5e 77 ef e7 59 28 fe 1d c1 27 a2 ff a8 de |.K^w..Y(...'....| +000002d0 33 48 b3 c1 85 6a 42 9b f9 7e 7e 31 c2 e5 bd 66 |3H...jB..~~1...f| +000002e0 02 42 00 ad 7d 06 35 ab ec 8d ac d4 ba 1b 49 5e |.B..}.5.......I^| +000002f0 05 5f f0 97 93 82 b8 2b 8d 91 98 63 8e b4 14 62 |._.....+...c...b| +00000300 db 1e c9 2b 30 f8 41 9b a6 e6 bc de 0e 68 30 21 |...+0.A......h0!| +00000310 d8 ef 2f 05 42 da f2 e0 2c 06 33 1d 0d 9a 1a 75 |../.B...,.3....u| +00000320 59 a7 3a bc 16 03 01 00 04 0e 00 00 00 |Y.:..........| +>>> Flow 3 (client to server) +00000000 16 03 01 00 46 10 00 00 42 41 04 08 28 cf bd 3c |....F...BA..(..<| +00000010 3c cc 98 9e 73 3f 92 a7 cb 22 83 3b c7 61 46 0e |<...s?...".;.aF.| +00000020 4d 7c 30 b5 06 85 2f 01 be b5 40 e2 64 1e 45 c1 |M|0.../...@.d.E.| +00000030 9d 73 95 d5 65 92 0b 9b e7 6f c6 91 ab b6 fa be |.s..e....o......| +00000040 61 83 a7 f2 eb f5 65 31 fe 24 7b 14 03 01 00 01 |a.....e1.${.....| +00000050 01 16 03 01 00 30 15 d1 c4 ca 0b 01 84 13 5a ba |.....0........Z.| +00000060 89 04 87 73 7c bb d8 89 7e 10 27 ba 6f 5d dc d3 |...s|...~.'.o]..| +00000070 b5 ef 32 86 58 cc fb eb 5c 32 9e 95 ef 01 1c ac |..2.X...\2......| +00000080 dc 8e df 7f fe 0a |......| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 e8 48 86 81 3c |..........0.H..<| +00000010 f5 25 5c 94 a9 06 c4 5c 71 62 b1 43 76 ec 2c 44 |.%\....\qb.Cv.,D| +00000020 95 b5 8c 95 d2 ff 82 92 b6 fc 52 75 03 c6 a1 f0 |..........Ru....| +00000030 99 6d b1 ed ec 68 6c d7 9f 18 50 17 03 01 00 20 |.m...hl...P.... | +00000040 32 d9 26 8a 81 b8 9d a5 7b fd d5 4e 7a db 2e 29 |2.&.....{..Nz..)| +00000050 58 9a 4f 6a 27 18 bc dc c2 49 b8 65 cb 8e 16 5a |X.Oj'....I.e...Z| +00000060 17 03 01 00 30 c4 56 0a ad 9a 82 cb 3e 32 f1 7c |....0.V.....>2.|| +00000070 95 6e dd cd e9 4d f0 e5 2d c9 a3 f7 de bb d7 fd |.n...M..-.......| +00000080 84 bb df 34 8c 64 1f 03 58 64 19 4a 5b 7a a8 81 |...4.d..Xd.J[z..| +00000090 52 bb 51 0a 43 15 03 01 00 20 89 18 7a 40 ec 49 |R.Q.C.... ..z@.I| +000000a0 52 d5 d3 20 ac 07 eb e9 4a 78 23 cf e7 21 32 74 |R.. ....Jx#..!2t| +000000b0 ec 40 8d a8 f4 33 1c ae 93 cf |.@...3....| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-3DES b/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-3DES new file mode 100644 index 0000000000..c0e6241c07 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-3DES @@ -0,0 +1,79 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 36 01 00 00 32 03 01 52 cc 57 59 13 |....6...2..R.WY.| +00000010 8b e6 5b a3 1d cb 94 ef 48 e4 59 7e 20 6d 07 67 |..[.....H.Y~ m.g| +00000020 1e 28 6d 31 a2 e7 96 b3 7d 32 cc 00 00 04 00 0a |.(m1....}2......| +00000030 00 ff 01 00 00 05 00 0f 00 01 01 |...........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 31 02 00 00 2d 03 01 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 0a 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 01 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 01 00 04 0e 00 |n8P)l...........| +00000300 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 01 00 86 10 00 00 82 00 80 2e af d2 61 f6 |..............a.| +00000010 e2 b8 24 da 28 17 55 99 fd 11 bd 7a ab 98 dd f2 |..$.(.U....z....| +00000020 f6 5f e0 11 6b 12 61 6f 86 48 b2 6e db f0 dd d5 |._..k.ao.H.n....| +00000030 07 88 e5 95 f4 2d 6b 0c d0 09 1a 5e 5f 50 1f dc |.....-k....^_P..| +00000040 f2 e7 02 7d 5e a0 70 29 80 ef 87 aa cc 95 3f 2e |...}^.p)......?.| +00000050 24 d1 40 b6 62 53 1d 25 31 87 1e 2f 77 d3 e1 1c |$.@.bS.%1../w...| +00000060 c4 99 89 bc 99 09 e9 ad 1f ce 09 e6 36 1c 3e 97 |............6.>.| +00000070 be 62 69 a0 4e 14 20 9c 82 2a 3e fc 7e 9b c4 7a |.bi.N. ..*>.~..z| +00000080 5a f7 ad 1a 03 17 2a f8 7a 5f 44 14 03 01 00 01 |Z.....*.z_D.....| +00000090 01 16 03 01 00 28 49 6b da 73 07 ad 85 9a 0e fb |.....(Ik.s......| +000000a0 dd e0 69 ef c9 22 2d 86 91 51 26 63 d0 24 7d 16 |..i.."-..Q&c.$}.| +000000b0 3c db 9b 00 c9 7e 64 e2 69 02 85 7d f7 47 |<....~d.i..}.G| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 28 dc 60 83 43 6c |..........(.`.Cl| +00000010 37 79 ab 6e 92 1f 66 d0 b1 12 ce c1 64 9d 2b 68 |7y.n..f.....d.+h| +00000020 c7 1a e5 1f 8c 80 08 d2 86 3e a1 2c e3 7e f4 64 |.........>.,.~.d| +00000030 e7 96 b2 17 03 01 00 18 8d b5 7c 03 78 cf dc 09 |..........|.x...| +00000040 95 06 4b a6 82 f9 30 d2 6b 26 cb 0a 9a 9d 47 9f |..K...0.k&....G.| +00000050 17 03 01 00 28 30 a9 55 dd b9 4d 6a 76 00 39 96 |....(0.U..Mjv.9.| +00000060 a3 94 6a df e5 af 1e a2 eb bb e4 ac 95 2c f7 93 |..j..........,..| +00000070 ef d1 b5 13 d8 e2 06 1a ad 5c 00 dd 0c 15 03 01 |.........\......| +00000080 00 18 a5 62 e4 8b 51 1d 28 46 bc 8a c8 50 a3 32 |...b..Q.(F...P.2| +00000090 6b 7b f1 b6 19 43 63 1f 7d 38 |k{...Cc.}8| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES b/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES new file mode 100644 index 0000000000..1670997b0d --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES @@ -0,0 +1,82 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 36 01 00 00 32 03 01 52 cc 57 59 5d |....6...2..R.WY]| +00000010 0d 77 24 3e b3 32 3d ba 0f b0 aa 1d e3 13 06 f6 |.w$>.2=.........| +00000020 0f be 3c 92 ba 93 bd a6 6d 69 53 00 00 04 00 2f |..<.....miS..../| +00000030 00 ff 01 00 00 05 00 0f 00 01 01 |...........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 31 02 00 00 2d 03 01 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2f 00 00 |............./..| +00000030 05 ff 01 00 01 00 16 03 01 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 01 00 04 0e 00 |n8P)l...........| +00000300 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 01 00 86 10 00 00 82 00 80 20 e6 80 f7 48 |........... ...H| +00000010 7e 7d 08 08 54 e1 b4 e3 98 27 5f 90 9d 3b e3 c2 |~}..T....'_..;..| +00000020 c8 8b dc 9e ff 75 fa fc 60 e1 9e 67 7c c4 08 27 |.....u..`..g|..'| +00000030 cc 6f 15 6c bc 7c 96 de 83 8f 98 6d 4a c7 b7 20 |.o.l.|.....mJ.. | +00000040 8c 19 47 5a ff 76 92 0a df df 66 d2 b6 9d 2d 06 |..GZ.v....f...-.| +00000050 fb ac 07 cf 38 08 f1 fd 0d fe 07 d7 69 3e 8a 79 |....8.......i>.y| +00000060 dc 2d ab bb f7 18 3c 51 14 6e c6 70 95 a2 59 b1 |.-........0| +000000c0 ed c6 bc c2 38 b6 |....8.| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 5d 0c a2 18 13 |..........0]....| +00000010 40 a1 84 ce c5 d8 4e fc a4 8a 14 b5 94 18 b1 86 |@.....N.........| +00000020 da 6a 7d 26 08 d6 a0 f8 78 5b 42 7e f8 83 54 56 |.j}&....x[B~..TV| +00000030 36 a4 91 37 67 5a d7 68 37 c4 4f 17 03 01 00 20 |6..7gZ.h7.O.... | +00000040 fd aa 5e cf 4b 12 c5 be a4 a2 65 5d 6e 65 46 5f |..^.K.....e]neF_| +00000050 d2 fe 46 e7 77 2d 9c 1e 0b 39 40 48 c2 2f be 21 |..F.w-...9@H./.!| +00000060 17 03 01 00 30 03 af 9e 6b d6 76 ed 9e 1d 8b 8b |....0...k.v.....| +00000070 2e 2a 5d da c4 73 95 ac 0e 6f 69 cb 63 df 50 27 |.*]..s...oi.c.P'| +00000080 30 de 2e 55 86 85 ad 3e 33 22 49 72 f2 e2 9f 8f |0..U...>3"Ir....| +00000090 ba cf 4e 30 34 15 03 01 00 20 4c 4c 97 61 70 ea |..N04.... LL.ap.| +000000a0 ae fc a2 e9 c6 c2 b6 2e 4d 85 f6 ae 2b 56 46 82 |........M...+VF.| +000000b0 9d d8 a5 82 17 fa 3e 62 67 7e |......>bg~| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4 b/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4 new file mode 100644 index 0000000000..d653561f9d --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4 @@ -0,0 +1,76 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 36 01 00 00 32 03 01 52 cc 57 59 cf |....6...2..R.WY.| +00000010 00 a1 49 a4 37 69 74 d8 a7 93 ea 8d e7 50 b7 b3 |..I.7it......P..| +00000020 8c ec e5 56 fb dc 5f 1a 2e ab 18 00 00 04 00 05 |...V.._.........| +00000030 00 ff 01 00 00 05 00 0f 00 01 01 |...........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 31 02 00 00 2d 03 01 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 01 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 01 00 04 0e 00 |n8P)l...........| +00000300 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 01 00 86 10 00 00 82 00 80 b1 96 7b 6f f5 |.............{o.| +00000010 a0 cb 0d 60 9b 64 d3 f5 17 76 47 7b bc a5 0e 96 |...`.d...vG{....| +00000020 53 af 68 0c 96 22 f7 28 0c 24 37 9c 51 69 ed b2 |S.h..".(.$7.Qi..| +00000030 47 14 ba 33 c5 79 6b 96 f2 ab 3c 02 5c 37 a4 97 |G..3.yk...<.\7..| +00000040 23 fc 7f d3 95 2d 85 99 1a 10 1b 38 e5 f1 83 55 |#....-.....8...U| +00000050 4a ab 60 f8 89 0a 6a c4 eb 45 f5 b0 f4 f8 09 31 |J.`...j..E.....1| +00000060 6e f0 25 30 fd 5e 68 61 bc cb 0d 9e 05 73 0a f4 |n.%0.^ha.....s..| +00000070 a5 2e d9 d5 4e 08 f6 3b 8d 2d 21 f5 79 b6 97 55 |....N..;.-!.y..U| +00000080 b9 99 03 49 ea 96 36 49 21 56 bf 14 03 01 00 01 |...I..6I!V......| +00000090 01 16 03 01 00 24 f0 4f 30 06 c3 25 01 93 34 ab |.....$.O0..%..4.| +000000a0 93 8f 59 26 83 6e 8a fd 5a a6 cf af ad b1 a2 83 |..Y&.n..Z.......| +000000b0 28 ff c2 66 5f ac e5 a5 a5 03 |(..f_.....| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 24 9d b4 ea d8 be |..........$.....| +00000010 b5 9f 00 fd b5 99 04 12 6b 7a 3f b8 52 d7 52 a9 |........kz?.R.R.| +00000020 e9 bd 5b 63 ad b0 53 ac 46 80 be 48 6e dd ee 17 |..[c..S.F..Hn...| +00000030 03 01 00 21 07 ac c4 fb 21 e4 b8 6b 64 3b b5 27 |...!....!..kd;.'| +00000040 29 67 a1 10 2e d2 71 d5 59 5e fc 1d 84 31 15 6e |)g....q.Y^...1.n| +00000050 4d 4b dc a9 3a 15 03 01 00 16 25 22 a5 78 23 5a |MK..:.....%".x#Z| +00000060 69 6f 99 a1 b3 1c 8d bf f3 bd 1b c8 1c 57 15 75 |io...........W.u| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv11-FallbackSCSV b/libgo/go/crypto/tls/testdata/Server-TLSv11-FallbackSCSV new file mode 100644 index 0000000000..2d8dfbc3b4 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv11-FallbackSCSV @@ -0,0 +1,17 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 d4 01 00 00 d0 03 02 74 2d da 6d 98 |...........t-.m.| +00000010 ad 3e a5 ec 90 ea d1 5b f0 e0 a7 45 33 d9 5e 8d |.>.....[...E3.^.| +00000020 0f 1d 01 16 6d 00 31 65 ed 50 88 00 00 5e c0 14 |....m.1e.P...^..| +00000030 c0 0a 00 39 00 38 00 88 00 87 c0 0f c0 05 00 35 |...9.8.........5| +00000040 00 84 c0 13 c0 09 00 33 00 32 00 9a 00 99 00 45 |.......3.2.....E| +00000050 00 44 c0 0e c0 04 00 2f 00 96 00 41 00 07 c0 11 |.D...../...A....| +00000060 c0 07 c0 0c c0 02 00 05 00 04 c0 12 c0 08 00 16 |................| +00000070 00 13 c0 0d c0 03 00 0a 00 15 00 12 00 09 00 14 |................| +00000080 00 11 00 08 00 06 00 03 00 ff 56 00 01 00 00 49 |..........V....I| +00000090 00 0b 00 04 03 00 01 02 00 0a 00 34 00 32 00 0e |...........4.2..| +000000a0 00 0d 00 19 00 0b 00 0c 00 18 00 09 00 0a 00 16 |................| +000000b0 00 17 00 08 00 06 00 07 00 14 00 15 00 04 00 05 |................| +000000c0 00 12 00 13 00 01 00 02 00 03 00 0f 00 10 00 11 |................| +000000d0 00 23 00 00 00 0f 00 01 01 |.#.......| +>>> Flow 2 (server to client) +00000000 15 03 02 00 02 02 56 |......V| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv11-RSA-RC4 b/libgo/go/crypto/tls/testdata/Server-TLSv11-RSA-RC4 new file mode 100644 index 0000000000..9237db0786 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv11-RSA-RC4 @@ -0,0 +1,76 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 36 01 00 00 32 03 02 52 cc 57 59 bd |....6...2..R.WY.| +00000010 cd 9d 1e 17 38 43 a5 e3 e7 30 e4 2b 2a ef f7 5b |....8C...0.+*..[| +00000020 81 91 0c 0b 52 f8 2d 2c 61 d3 13 00 00 04 00 05 |....R.-,a.......| +00000030 00 ff 01 00 00 05 00 0f 00 01 01 |...........| +>>> Flow 2 (server to client) +00000000 16 03 02 00 31 02 00 00 2d 03 02 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 02 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 02 00 04 0e 00 |n8P)l...........| +00000300 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 02 00 86 10 00 00 82 00 80 71 2b 19 25 86 |...........q+.%.| +00000010 a0 ff ba d5 1c a6 0c 8b 6b 0a b8 e9 42 93 2f 55 |........k...B./U| +00000020 a8 ee 62 fa ed bc 6d e2 9d e3 76 a6 73 d7 99 58 |..b...m...v.s..X| +00000030 cc 0b 14 42 96 7c b6 c7 8f 21 16 cf 71 9b 2b b9 |...B.|...!..q.+.| +00000040 e0 34 57 76 22 d5 87 8a ce 1f ea 26 6e 1e e6 ca |.4Wv"......&n...| +00000050 55 3b 20 cd cf 42 26 b1 51 3e 8c 1d a2 ae c4 63 |U; ..B&.Q>.....c| +00000060 f5 ce 27 3c 1e c3 e0 e3 b1 16 c1 8a 62 bd 21 7f |..'<........b.!.| +00000070 38 b5 b7 3a 3c bb 03 37 e1 a5 ff f1 29 e2 21 0a |8..:<..7....).!.| +00000080 8c 20 02 e0 c0 82 97 9d 18 6d f8 14 03 02 00 01 |. .......m......| +00000090 01 16 03 02 00 24 bc 19 16 6e fd 0b db 9e d5 1d |.....$...n......| +000000a0 65 b6 57 1c 58 b5 6a ac f7 4f f0 cd a1 a9 0c c0 |e.W.X.j..O......| +000000b0 df e6 eb d5 00 f7 fd 43 bb 27 |.......C.'| +>>> Flow 4 (server to client) +00000000 14 03 02 00 01 01 16 03 02 00 24 cf 4f e4 27 b0 |..........$.O.'.| +00000010 3d 17 34 b1 3c 37 6e c5 2b 3d 4a c3 46 50 44 b4 |=.4.<7n.+=J.FPD.| +00000020 de 77 18 10 4f 60 b3 4e dc 06 fd 25 ec 05 15 17 |.w..O`.N...%....| +00000030 03 02 00 21 a5 c9 32 f2 21 fb 94 7e 0d 15 65 fd |...!..2.!..~..e.| +00000040 3e fe e4 c1 a5 e9 88 72 b2 f1 26 39 a6 48 59 97 |>......r..&9.HY.| +00000050 65 e3 f0 cb 46 15 03 02 00 16 4b 02 ec cd ca 30 |e...F.....K....0| +00000060 42 cf 3d a0 4a fa 8e 79 bb ed b0 59 40 9b 2c 1a |B.=.J..y...Y@.,.| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN new file mode 100644 index 0000000000..106244d5a2 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN @@ -0,0 +1,122 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 01 8a 01 00 01 86 03 03 34 54 69 f3 d7 |...........4Ti..| +00000010 20 9d 1d 74 db 72 e9 2f 51 7c c2 82 0a 9b cb 6d | ..t.r./Q|.....m| +00000020 90 b4 8e a2 1f 2f c7 66 74 8f 33 00 00 d6 c0 30 |...../.ft.3....0| +00000030 c0 2c c0 28 c0 24 c0 14 c0 0a c0 22 c0 21 c0 20 |.,.(.$.....".!. | +00000040 00 a5 00 a3 00 a1 00 9f 00 6b 00 6a 00 69 00 68 |.........k.j.i.h| +00000050 00 39 00 38 00 37 00 36 00 88 00 87 00 86 00 85 |.9.8.7.6........| +00000060 c0 32 c0 2e c0 2a c0 26 c0 0f c0 05 00 9d 00 3d |.2...*.&.......=| +00000070 00 35 00 84 c0 2f c0 2b c0 27 c0 23 c0 13 c0 09 |.5.../.+.'.#....| +00000080 c0 1f c0 1e c0 1d 00 a4 00 a2 00 a0 00 9e 00 67 |...............g| +00000090 00 40 00 3f 00 3e 00 33 00 32 00 31 00 30 00 9a |.@.?.>.3.2.1.0..| +000000a0 00 99 00 98 00 97 00 45 00 44 00 43 00 42 c0 31 |.......E.D.C.B.1| +000000b0 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c 00 3c 00 2f |.-.).%.......<./| +000000c0 00 96 00 41 00 07 c0 11 c0 07 c0 0c c0 02 00 05 |...A............| +000000d0 00 04 c0 12 c0 08 c0 1c c0 1b c0 1a 00 16 00 13 |................| +000000e0 00 10 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f |................| +000000f0 00 0c 00 09 00 14 00 11 00 0e 00 0b 00 08 00 06 |................| +00000100 00 03 00 ff 01 00 00 87 00 0b 00 04 03 00 01 02 |................| +00000110 00 0a 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b |...:.8..........| +00000120 00 0c 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 |................| +00000130 00 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 |................| +00000140 00 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 23 |...............#| +00000150 00 00 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 |..... ..........| +00000160 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................| +00000170 02 01 02 02 02 03 00 0f 00 01 01 00 10 00 10 00 |................| +00000180 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 6f 31 |..proto2.proto1| +>>> Flow 2 (server to client) +00000000 16 03 03 00 42 02 00 00 3e 03 03 00 00 00 00 00 |....B...>.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 14 00 00 |................| +00000030 16 00 23 00 00 ff 01 00 01 00 00 10 00 09 00 07 |..#.............| +00000040 06 70 72 6f 74 6f 31 16 03 03 02 be 0b 00 02 ba |.proto1.........| +00000050 00 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 |......0...0.....| +00000060 02 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d |..............0.| +00000070 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 |..*.H........0E1| +00000080 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 |.0...U....AU1.0.| +00000090 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 |..U....Some-Stat| +000000a0 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 |e1!0...U....Inte| +000000b0 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 |rnet Widgits Pty| +000000c0 20 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 | Ltd0...10042409| +000000d0 30 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 |0938Z..110424090| +000000e0 39 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 |938Z0E1.0...U...| +000000f0 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f |.AU1.0...U....So| +00000100 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 |me-State1!0...U.| +00000110 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 |...Internet Widg| +00000120 69 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d |its Pty Ltd0..0.| +00000130 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d |..*.H...........| +00000140 00 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf |.0.......y......| +00000150 46 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a |F...i..+.CZ..-.z| +00000160 43 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 |C...R..eL,x.#...| +00000170 82 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c |.....;~b.,.3...\| +00000180 7a 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 |zV.....X{&?.....| +00000190 c9 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 |.!.J..T.Z..Bq...| +000001a0 99 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 |...~.}}..9....Q.| +000001b0 7c e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d ||..L;2f......q..| +000001c0 db db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 |...k..-y........| +000001d0 30 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad |0..0...U........| +000001e0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +000001f0 88 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 |.90u..U.#.n0l...| +00000200 ad e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e |...Z..(.i.#i..&.| +00000210 18 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 |..9.I.G0E1.0...U| +00000220 04 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 |....AU1.0...U...| +00000230 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 |.Some-State1!0..| +00000240 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 |.U....Internet W| +00000250 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 |idgits Pty Ltd..| +00000260 00 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 |.........0...U..| +00000270 04 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 |..0....0...*.H..| +00000280 0d 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b |...........lE$.k| +00000290 b1 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 |.Y..R.......zdu.| +000002a0 5a 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e |Z.f..+...f..O8.n| +000002b0 60 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 |`....A..%...z$.0| +000002c0 1d ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 |.........1Y....x| +000002d0 ea 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 |.PV\..Z-Z_3....u| +000002e0 90 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c |....R...... _...| +000002f0 a3 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b |.......W.p.&mq..| +00000300 26 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 cd 0c |&n8P)l..........| +00000310 00 00 c9 03 00 17 41 04 1e 18 37 ef 0d 19 51 88 |......A...7...Q.| +00000320 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 |5uq..T[....g..$ | +00000330 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f |>.V...(^.+-O....| +00000340 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 |lK[.V.2B.X..I..h| +00000350 1a 41 03 56 6b dc 5a 89 04 01 00 80 2d a0 6e 47 |.A.Vk.Z.....-.nG| +00000360 93 a2 19 17 32 f5 42 58 93 f6 4f d4 e9 4d a4 0f |....2.BX..O..M..| +00000370 fe 4e d7 2c 62 b6 fb 83 37 a3 09 60 4b 69 e2 4c |.N.,b...7..`Ki.L| +00000380 fc b8 4c d1 a6 9a 89 a0 c5 76 f5 62 b7 e8 eb c2 |..L......v.b....| +00000390 fa 0f 0e 61 86 bc 70 da 13 72 8d 87 94 16 9a 8d |...a..p..r......| +000003a0 5f 80 82 92 77 37 4f 9e 55 5d dc 35 42 a3 75 5c |_...w7O.U].5B.u\| +000003b0 ec a4 58 78 66 97 97 da 49 67 2e b6 7e 11 de fb |..Xxf...Ig..~...| +000003c0 e3 8f e8 bf 1d 91 1e 91 20 1b 2a df c6 58 e4 82 |........ .*..X..| +000003d0 ce 37 dd 6f a5 ac 51 3d 65 db 3f f5 16 03 03 00 |.7.o..Q=e.?.....| +000003e0 04 0e 00 00 00 |.....| +>>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 f3 fc ea d8 50 |....F...BA.....P| +00000010 e6 15 b0 e7 11 c7 6d ee 09 ad 80 d5 54 eb 4f 62 |......m.....T.Ob| +00000020 7d bb a7 2d 28 0c 66 33 42 09 cf 2b 58 f8 58 41 |}..-(.f3B..+X.XA| +00000030 bd 46 51 0a f0 7d 8c 0c 98 9e 26 77 20 fd 5e c1 |.FQ..}....&w .^.| +00000040 a9 b3 e5 c3 6c 05 97 e3 81 fd db 14 03 03 00 01 |....l...........| +00000050 01 16 03 03 00 40 02 2a 28 41 e3 9c 5d 45 d4 45 |.....@.*(A..]E.E| +00000060 51 8c 7a c0 ba b1 8e a4 84 2c f3 83 cd c4 55 5c |Q.z......,....U\| +00000070 d6 5c 6f 72 ab 89 7a c6 d7 9c 2a 54 f0 c4 20 ee |.\or..z...*T.. .| +00000080 37 74 9b b6 8c f7 e4 37 2c eb d4 9f 5c 5e 55 a0 |7t.....7,...\^U.| +00000090 e2 5a fe 1e c8 67 |.Z...g| +>>> Flow 4 (server to client) +00000000 16 03 03 00 72 04 00 00 6e 00 00 00 00 00 68 00 |....r...n.....h.| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 |...............e| +00000020 ea 8b c0 ef ba 59 31 75 33 96 f1 f8 c9 e1 ef 30 |.....Y1u3......0| +00000030 00 a3 a9 1d ab c8 4b 29 94 f2 c8 c8 8d 03 57 ab |......K)......W.| +00000040 56 df 0f 4e 0d 30 13 09 c9 e4 fa 51 4e b3 26 ad |V..N.0.....QN.&.| +00000050 43 9f ae 62 d5 59 23 05 9b 69 8f 5b a8 ba 39 f1 |C..b.Y#..i.[..9.| +00000060 90 84 35 bf 8f 8d d5 39 93 98 ee b9 75 03 3f 91 |..5....9....u.?.| +00000070 e8 56 0b cb 44 a6 7a 14 03 03 00 01 01 16 03 03 |.V..D.z.........| +00000080 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.@..............| +00000090 00 00 f9 a0 8e 23 34 f1 61 15 a8 4e ae c4 f3 2a |.....#4.a..N...*| +000000a0 a6 f8 ee 1b 65 c4 c0 ff 93 14 74 ed 82 ae 48 a8 |....e.....t...H.| +000000b0 42 fb a9 24 5d dd fd 98 b8 65 73 03 88 99 e1 ed |B..$]....es.....| +000000c0 02 95 17 03 03 00 40 00 00 00 00 00 00 00 00 00 |......@.........| +000000d0 00 00 00 00 00 00 00 b9 b3 f5 41 84 3b 2a a9 c3 |..........A.;*..| +000000e0 9c e3 d4 38 90 76 c1 8c f0 4f 10 1b 04 b5 07 fe |...8.v...O......| +000000f0 79 3d 7b 77 a4 17 0f 4e df 64 70 70 9e 34 8e b6 |y={w...N.dpp.4..| +00000100 db b2 b6 fd 41 fe b3 15 03 03 00 30 00 00 00 00 |....A......0....| +00000110 00 00 00 00 00 00 00 00 00 00 00 00 02 73 de fe |.............s..| +00000120 fa 4b 69 6d 30 69 79 96 7e 4f 2f 04 67 36 96 27 |.Kim0iy.~O/.g6.'| +00000130 67 23 2b dc 7a c4 6c 34 ea fc 79 fd |g#+.z.l4..y.| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch new file mode 100644 index 0000000000..db5881b768 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch @@ -0,0 +1,121 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 01 8a 01 00 01 86 03 03 0a a8 82 53 61 |..............Sa| +00000010 68 e0 83 91 71 36 f9 c1 19 ff e8 09 fc 21 9f 03 |h...q6.......!..| +00000020 31 f3 87 4a 04 8c 3d c2 6e 00 32 00 00 d6 c0 30 |1..J..=.n.2....0| +00000030 c0 2c c0 28 c0 24 c0 14 c0 0a c0 22 c0 21 c0 20 |.,.(.$.....".!. | +00000040 00 a5 00 a3 00 a1 00 9f 00 6b 00 6a 00 69 00 68 |.........k.j.i.h| +00000050 00 39 00 38 00 37 00 36 00 88 00 87 00 86 00 85 |.9.8.7.6........| +00000060 c0 32 c0 2e c0 2a c0 26 c0 0f c0 05 00 9d 00 3d |.2...*.&.......=| +00000070 00 35 00 84 c0 2f c0 2b c0 27 c0 23 c0 13 c0 09 |.5.../.+.'.#....| +00000080 c0 1f c0 1e c0 1d 00 a4 00 a2 00 a0 00 9e 00 67 |...............g| +00000090 00 40 00 3f 00 3e 00 33 00 32 00 31 00 30 00 9a |.@.?.>.3.2.1.0..| +000000a0 00 99 00 98 00 97 00 45 00 44 00 43 00 42 c0 31 |.......E.D.C.B.1| +000000b0 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c 00 3c 00 2f |.-.).%.......<./| +000000c0 00 96 00 41 00 07 c0 11 c0 07 c0 0c c0 02 00 05 |...A............| +000000d0 00 04 c0 12 c0 08 c0 1c c0 1b c0 1a 00 16 00 13 |................| +000000e0 00 10 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f |................| +000000f0 00 0c 00 09 00 14 00 11 00 0e 00 0b 00 08 00 06 |................| +00000100 00 03 00 ff 01 00 00 87 00 0b 00 04 03 00 01 02 |................| +00000110 00 0a 00 3a 00 38 00 0e 00 0d 00 19 00 1c 00 0b |...:.8..........| +00000120 00 0c 00 1b 00 18 00 09 00 0a 00 1a 00 16 00 17 |................| +00000130 00 08 00 06 00 07 00 14 00 15 00 04 00 05 00 12 |................| +00000140 00 13 00 01 00 02 00 03 00 0f 00 10 00 11 00 23 |...............#| +00000150 00 00 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 |..... ..........| +00000160 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................| +00000170 02 01 02 02 02 03 00 0f 00 01 01 00 10 00 10 00 |................| +00000180 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 6f 31 |..proto2.proto1| +>>> Flow 2 (server to client) +00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 14 00 00 |................| +00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 be 0b |..#.............| +00000040 00 02 ba 00 02 b7 00 02 b4 30 82 02 b0 30 82 02 |.........0...0..| +00000050 19 a0 03 02 01 02 02 09 00 85 b0 bb a4 8a 7f b8 |................| +00000060 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 |.0...*.H........| +00000070 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 |0E1.0...U....AU1| +00000080 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 |.0...U....Some-S| +00000090 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 |tate1!0...U....I| +000000a0 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 |nternet Widgits | +000000b0 50 74 79 20 4c 74 64 30 1e 17 0d 31 30 30 34 32 |Pty Ltd0...10042| +000000c0 34 30 39 30 39 33 38 5a 17 0d 31 31 30 34 32 34 |4090938Z..110424| +000000d0 30 39 30 39 33 38 5a 30 45 31 0b 30 09 06 03 55 |090938Z0E1.0...U| +000000e0 04 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 |....AU1.0...U...| +000000f0 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 |.Some-State1!0..| +00000100 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 |.U....Internet W| +00000110 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 30 81 |idgits Pty Ltd0.| +00000120 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 |.0...*.H........| +00000130 03 81 8d 00 30 81 89 02 81 81 00 bb 79 d6 f5 17 |....0.......y...| +00000140 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 43 5a d0 03 |...F...i..+.CZ..| +00000150 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 |-.zC...R..eL,x.#| +00000160 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 |........;~b.,.3.| +00000170 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b 26 3f b5 cd |..\zV.....X{&?..| +00000180 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a bf ef 42 71 |....!.J..T.Z..Bq| +00000190 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e |......~.}}..9...| +000001a0 db 51 c9 7c e3 c0 4c 3b 32 66 01 cf af b1 1d b8 |.Q.|..L;2f......| +000001b0 71 9a 1d db db 89 6b ae da 2d 79 02 03 01 00 01 |q.....k..-y.....| +000001c0 a3 81 a7 30 81 a4 30 1d 06 03 55 1d 0e 04 16 04 |...0..0...U.....| +000001d0 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 de d3 |.....Z..(.i.#i..| +000001e0 26 8e 18 88 39 30 75 06 03 55 1d 23 04 6e 30 6c |&...90u..U.#.n0l| +000001f0 80 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 de |......Z..(.i.#i.| +00000200 d3 26 8e 18 88 39 a1 49 a4 47 30 45 31 0b 30 09 |.&...9.I.G0E1.0.| +00000210 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 55 |..U....AU1.0...U| +00000220 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 |....Some-State1!| +00000230 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 |0...U....Interne| +00000240 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 |t Widgits Pty Lt| +00000250 64 82 09 00 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 |d...........0...| +00000260 55 1d 13 04 05 30 03 01 01 ff 30 0d 06 09 2a 86 |U....0....0...*.| +00000270 48 86 f7 0d 01 01 05 05 00 03 81 81 00 08 6c 45 |H.............lE| +00000280 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a |$.k.Y..R.......z| +00000290 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f |du.Z.f..+...f..O| +000002a0 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 13 b1 18 7a |8.n`....A..%...z| +000002b0 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 31 59 db 95 |$.0.........1Y..| +000002c0 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 |..x.PV\..Z-Z_3..| +000002d0 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f |..u....R...... _| +000002e0 f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d |..........W.p.&m| +000002f0 71 99 9b 26 6e 38 50 29 6c 90 a7 bd d9 16 03 03 |q..&n8P)l.......| +00000300 00 cd 0c 00 00 c9 03 00 17 41 04 1e 18 37 ef 0d |.........A...7..| +00000310 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.| +00000320 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.| +00000330 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I| +00000340 a6 b5 68 1a 41 03 56 6b dc 5a 89 04 01 00 80 b9 |..h.A.Vk.Z......| +00000350 0f 79 8a 16 f4 da 8f 27 b4 16 fc c0 51 db ae d1 |.y.....'....Q...| +00000360 af 79 77 d5 d5 a2 13 05 45 20 cc eb ac ed cb 30 |.yw.....E .....0| +00000370 32 2e 2c bd fa 1c 4d b5 32 a6 37 43 c8 5c 2d f8 |2.,...M.2.7C.\-.| +00000380 6e 85 f5 cd 54 92 29 ad 13 7d d5 9e 8c 1d b7 d0 |n...T.)..}......| +00000390 c1 c7 3d e8 ba 4a 0f 9a a6 3e 25 5f 27 62 b1 00 |..=..J...>%_'b..| +000003a0 91 d9 23 48 3f 10 fe c5 e3 07 9a 58 57 6d cc 10 |..#H?......XWm..| +000003b0 3b f8 1a d5 6e 8b 1f 03 6f 82 84 98 b5 f7 71 5d |;...n...o.....q]| +000003c0 c2 ad 60 14 c1 88 07 5a 3d 99 fd a8 c9 9a 03 16 |..`....Z=.......| +000003d0 03 03 00 04 0e 00 00 00 |........| +>>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 76 aa 4e b9 f9 |....F...BA.v.N..| +00000010 68 85 81 74 7c d9 f9 64 7f bd 09 83 08 5b 4f 76 |h..t|..d.....[Ov| +00000020 6e be 79 b6 4e 97 17 63 e4 b5 1c 77 e5 85 76 8a |n.y.N..c...w..v.| +00000030 5d 9f f1 21 88 ec f9 a7 7c 41 af f9 c5 fe 11 81 |]..!....|A......| +00000040 11 51 8e a7 20 33 5f cf e7 90 90 14 03 03 00 01 |.Q.. 3_.........| +00000050 01 16 03 03 00 40 44 3e 32 01 71 ac 5a b5 1f 2c |.....@D>2.q.Z..,| +00000060 37 d9 4b 70 72 91 89 d4 d7 c2 c3 e7 ff dc 72 2a |7.Kpr.........r*| +00000070 ba f5 30 b0 e9 dd 48 10 3d cd 98 48 a3 e3 ca de |..0...H.=..H....| +00000080 15 0e 90 8e e5 04 14 74 42 b8 b0 12 cc 68 7b 7d |.......tB....h{}| +00000090 6c 43 72 60 05 0d |lCr`..| +>>> Flow 4 (server to client) +00000000 16 03 03 00 72 04 00 00 6e 00 00 00 00 00 68 00 |....r...n.....h.| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 |...............e| +00000020 ea 8b c0 ef ba 12 45 17 61 24 cd d2 4c 22 bb 3b |......E.a$..L".;| +00000030 e3 0e d0 ff 83 e9 7c b7 8f 10 3c 16 1c fc c2 44 |......|...<....D| +00000040 ef 45 f8 27 30 56 db ea eb ae f5 b6 17 b2 ef f9 |.E.'0V..........| +00000050 96 0d 2d db e4 59 23 0a fc fa e3 13 48 57 e5 b3 |..-..Y#.....HW..| +00000060 3a d1 f5 5e ca ef d7 3f 7b b5 f4 69 85 c3 bd da |:..^...?{..i....| +00000070 fd 9c 50 05 2f 86 ce 14 03 03 00 01 01 16 03 03 |..P./...........| +00000080 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.@..............| +00000090 00 00 60 25 1c ed 6f c6 a5 bd b2 29 39 4e 09 d1 |..`%..o....)9N..| +000000a0 64 cc 75 cd df 91 a8 90 9d 03 aa 92 07 f2 d0 8a |d.u.............| +000000b0 60 bb 3e 85 21 22 fe f8 dc 52 3c 4e 82 77 14 14 |`.>.!"...R.>}t| +000000e0 0d ac c4 a9 df 67 1c 5a ad 3e 01 34 03 88 2f 39 |.....g.Z.>.4../9| +000000f0 f7 3c 06 e4 f6 81 43 66 b1 1b ed a5 e5 b6 a8 43 |.<....Cf.......C| +00000100 7f 36 2f b2 da 45 9a 15 03 03 00 30 00 00 00 00 |.6/..E.....0....| +00000110 00 00 00 00 00 00 00 00 00 00 00 00 fa 63 4e c5 |.............cN.| +00000120 77 89 71 56 e3 0a cf 98 da 2f 89 8f 74 8e 76 24 |w.qV...../..t.v$| +00000130 e2 40 a5 9f 29 1b b2 11 ef 7a 55 7f |.@..)....zU.| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA b/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA new file mode 100644 index 0000000000..0ab8b8d74c --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA @@ -0,0 +1,91 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 ca 01 00 00 c6 03 03 53 04 f1 3f 5f |...........S..?_| +00000010 f4 ef 1f b3 41 0b 54 e4 4d 56 0a 31 22 b8 5c 73 |....A.T.MV.1".\s| +00000020 a3 cb b5 b2 9d 43 f1 83 bc d3 bd 00 00 32 c0 30 |.....C.......2.0| +00000030 c0 2c c0 28 c0 24 c0 14 c0 0a c0 22 c0 21 00 a3 |.,.(.$.....".!..| +00000040 00 9f 00 6b 00 6a 00 39 00 38 00 88 00 87 c0 32 |...k.j.9.8.....2| +00000050 c0 2e c0 2a c0 26 c0 0f c0 05 00 9d 00 3d 00 35 |...*.&.......=.5| +00000060 01 00 00 6b 00 0b 00 04 03 00 01 02 00 0a 00 34 |...k...........4| +00000070 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 00 09 |.2..............| +00000080 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 00 15 |................| +00000090 00 04 00 05 00 12 00 13 00 01 00 02 00 03 00 0f |................| +000000a0 00 10 00 11 00 0d 00 22 00 20 06 01 06 02 06 03 |.......". ......| +000000b0 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 |................| +000000c0 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 01 |...............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 2a 02 00 00 26 03 03 00 00 00 00 00 |....*...&.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 0a 00 16 |................| +00000030 03 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 |..............0.| +00000040 02 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb |..0..b.....-G...| +00000050 f4 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 0b |.0...*.H.=..0E1.| +00000060 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000070 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000080 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +00000090 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000a0 4c 74 64 30 1e 17 0d 31 32 31 31 32 32 31 35 30 |Ltd0...121122150| +000000b0 36 33 32 5a 17 0d 32 32 31 31 32 30 31 35 30 36 |632Z..2211201506| +000000c0 33 32 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |32Z0E1.0...U....| +000000d0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000e0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +000000f0 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000100 74 73 20 50 74 79 20 4c 74 64 30 81 9b 30 10 06 |ts Pty Ltd0..0..| +00000110 07 2a 86 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 |.*.H.=....+...#.| +00000120 81 86 00 04 00 c4 a1 ed be 98 f9 0b 48 73 36 7e |............Hs6~| +00000130 c3 16 56 11 22 f2 3d 53 c3 3b 4d 21 3d cd 6b 75 |..V.".=S.;M!=.ku| +00000140 e6 f6 b0 dc 9a df 26 c1 bc b2 87 f0 72 32 7c b3 |......&.....r2|.| +00000150 64 2f 1c 90 bc ea 68 23 10 7e fe e3 25 c0 48 3a |d/....h#.~..%.H:| +00000160 69 e0 28 6d d3 37 00 ef 04 62 dd 0d a0 9c 70 62 |i.(m.7...b....pb| +00000170 83 d8 81 d3 64 31 aa 9e 97 31 bd 96 b0 68 c0 9b |....d1...1...h..| +00000180 23 de 76 64 3f 1a 5c 7f e9 12 0e 58 58 b6 5f 70 |#.vd?.\....XX._p| +00000190 dd 9b d8 ea d5 d7 f5 d5 cc b9 b6 9f 30 66 5b 66 |............0f[f| +000001a0 9a 20 e2 27 e5 bf fe 3b 30 09 06 07 2a 86 48 ce |. .'...;0...*.H.| +000001b0 3d 04 01 03 81 8c 00 30 81 88 02 42 01 88 a2 4f |=......0...B...O| +000001c0 eb e2 45 c5 48 7d 1b ac f5 ed 98 9d ae 47 70 c0 |..E.H}.......Gp.| +000001d0 5e 1b b6 2f bd f1 b6 4d b7 61 40 d3 11 a2 ce ee |^../...M.a@.....| +000001e0 0b 7e 92 7e ff 76 9d c3 3b 7e a5 3f ce fa 10 e2 |.~.~.v..;~.?....| +000001f0 59 ec 47 2d 7c ac da 4e 97 0e 15 a0 6f d0 02 42 |Y.G-|..N....o..B| +00000200 01 4d fc be 67 13 9c 2d 05 0e bd 3f a3 8c 25 c1 |.M..g..-...?..%.| +00000210 33 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e |3.......7z..z...| +00000220 dd d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 |...i..|V..1x+..x| +00000230 0d ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 |.....N6$1{j.9...| +00000240 8f 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 |.*............A.| +00000250 1e 18 37 ef 0d 19 51 88 35 75 71 b5 e5 54 5b 12 |..7...Q.5uq..T[.| +00000260 2e 8f 09 67 fd a7 24 20 3e b2 56 1c ce 97 28 5e |...g..$ >.V...(^| +00000270 f8 2b 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 32 42 |.+-O....lK[.V.2B| +00000280 e9 58 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc 5a 89 |.X..I..h.A.Vk.Z.| +00000290 04 03 00 8b 30 81 88 02 42 00 c6 85 8e 06 b7 04 |....0...B.......| +000002a0 04 e9 cd 9e 3e cb 66 23 95 b4 42 9c 64 81 39 05 |....>.f#..B.d.9.| +000002b0 3f b5 21 f8 28 af 60 6b 4d 3d ba a1 4b 5e 77 ef |?.!.(.`kM=..K^w.| +000002c0 e7 59 28 fe 1d c1 27 a2 ff a8 de 33 48 b3 c1 85 |.Y(...'....3H...| +000002d0 6a 42 9b f9 7e 7e 31 c2 e5 bd 66 02 42 00 ad 7d |jB..~~1...f.B..}| +000002e0 06 35 ab ec 8d ac d4 ba 1b 49 5e 05 5f f0 97 93 |.5.......I^._...| +000002f0 82 b8 2b 8d 91 98 63 8e b4 14 62 db 1e c9 2b 64 |..+...c...b...+d| +00000300 e9 e6 bf 15 5b 67 c2 40 90 c6 1f b7 92 db 4b f6 |....[g.@......K.| +00000310 f4 db ae 82 f1 4f 02 75 52 40 38 10 ff 35 f0 16 |.....O.uR@8..5..| +00000320 03 03 00 04 0e 00 00 00 |........| +>>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 d8 94 c4 05 26 |....F...BA.....&| +00000010 76 29 2d 0e ec 47 b6 50 d5 a3 da 2a ba 02 11 37 |v)-..G.P...*...7| +00000020 3d ef e6 2a db d0 47 47 a7 9a 5f 43 2d 98 78 26 |=..*..GG.._C-.x&| +00000030 81 e2 f1 ba fe f7 66 c6 61 cb c1 b7 60 62 34 a5 |......f.a...`b4.| +00000040 78 67 50 3d 9a 0e 4a 8c 8f d7 10 14 03 03 00 01 |xgP=..J.........| +00000050 01 16 03 03 00 40 5e 46 b0 5d 30 f6 da 8f 9e 67 |.....@^F.]0....g| +00000060 f5 3e bd fe c9 b8 53 b2 10 d5 7c 0e 34 e3 93 6d |.>....S...|.4..m| +00000070 0e 8e 8a 2b df fb 9a 0f a5 23 55 e7 0a 4b e2 d3 |...+.....#U..K..| +00000080 db 15 e8 52 74 26 78 b3 b0 56 65 63 ac ae 1e c0 |...Rt&x..Vec....| +00000090 0b f4 92 56 a9 04 |...V..| +>>> 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 16 a9 63 0a 99 |.............c..| +00000020 21 8a fc 5c b3 ee 05 71 4e 75 c0 d9 40 54 0d 3e |!..\...qNu..@T.>| +00000030 4e 5d 44 b7 4b 5d a9 e7 5a 30 ed b6 d5 08 50 b1 |N]D.K]..Z0....P.| +00000040 e8 8c 54 eb 1b 39 7a f9 3b ac 2e 17 03 03 00 40 |..T..9z.;......@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 96 03 20 2b 20 c4 c1 9a 76 7b f3 96 bd 33 ed e6 |.. + ...v{...3..| +00000070 38 48 ea 53 d5 e0 62 b5 7e 1a 36 a8 dd 9f 2d 4b |8H.S..b.~.6...-K| +00000080 06 0d ae f6 bc 99 14 b3 93 14 27 63 e2 a0 c8 76 |..........'c...v| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 48 af e1 e4 11 e1 b7 03 19 b0 e3 |.....H..........| +000000b0 e6 a9 66 d8 ac af aa 03 f6 0d 51 df 9a 27 78 3a |..f.......Q..'x:| +000000c0 56 5a 03 1a 4c |VZ..L| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA b/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA new file mode 100644 index 0000000000..88abb15a7e --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA @@ -0,0 +1,101 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 ca 01 00 00 c6 03 03 53 04 f1 3f cc |...........S..?.| +00000010 41 74 00 07 cb ae 3b 30 79 48 51 60 41 a3 8c ab |At....;0yHQ`A...| +00000020 dc 76 f9 74 52 1e c5 fb a9 69 c2 00 00 32 c0 30 |.v.tR....i...2.0| +00000030 c0 2c c0 28 c0 24 c0 14 c0 0a c0 22 c0 21 00 a3 |.,.(.$.....".!..| +00000040 00 9f 00 6b 00 6a 00 39 00 38 00 88 00 87 c0 32 |...k.j.9.8.....2| +00000050 c0 2e c0 2a c0 26 c0 0f c0 05 00 9d 00 3d 00 35 |...*.&.......=.5| +00000060 01 00 00 6b 00 0b 00 04 03 00 01 02 00 0a 00 34 |...k...........4| +00000070 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 00 09 |.2..............| +00000080 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 00 15 |................| +00000090 00 04 00 05 00 12 00 13 00 01 00 02 00 03 00 0f |................| +000000a0 00 10 00 11 00 0d 00 22 00 20 06 01 06 02 06 03 |.......". ......| +000000b0 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 |................| +000000c0 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 01 |...............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 2a 02 00 00 26 03 03 00 00 00 00 00 |....*...&.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 14 00 16 |................| +00000030 03 03 02 be 0b 00 02 ba 00 02 b7 00 02 b4 30 82 |..............0.| +00000040 02 b0 30 82 02 19 a0 03 02 01 02 02 09 00 85 b0 |..0.............| +00000050 bb a4 8a 7f b8 ca 30 0d 06 09 2a 86 48 86 f7 0d |......0...*.H...| +00000060 01 01 05 05 00 30 45 31 0b 30 09 06 03 55 04 06 |.....0E1.0...U..| +00000070 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 |..AU1.0...U....S| +00000080 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 |ome-State1!0...U| +00000090 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 |....Internet Wid| +000000a0 67 69 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d |gits Pty Ltd0...| +000000b0 31 30 30 34 32 34 30 39 30 39 33 38 5a 17 0d 31 |100424090938Z..1| +000000c0 31 30 34 32 34 30 39 30 39 33 38 5a 30 45 31 0b |10424090938Z0E1.| +000000d0 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +000000e0 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +000000f0 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +00000100 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +00000110 4c 74 64 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d |Ltd0..0...*.H...| +00000120 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 |.........0......| +00000130 bb 79 d6 f5 17 b5 e5 bf 46 10 d0 dc 69 be e6 2b |.y......F...i..+| +00000140 07 43 5a d0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 65 |.CZ..-.zC...R..e| +00000150 4c 2c 78 b8 23 8c b5 b4 82 e5 de 1f 95 3b 7e 62 |L,x.#........;~b| +00000160 a5 2c a5 33 d6 fe 12 5c 7a 56 fc f5 06 bf fa 58 |.,.3...\zV.....X| +00000170 7b 26 3f b5 cd 04 d3 d0 c9 21 96 4a c7 f4 54 9f |{&?......!.J..T.| +00000180 5a bf ef 42 71 00 fe 18 99 07 7f 7e 88 7d 7d f1 |Z..Bq......~.}}.| +00000190 04 39 c4 a2 2e db 51 c9 7c e3 c0 4c 3b 32 66 01 |.9....Q.|..L;2f.| +000001a0 cf af b1 1d b8 71 9a 1d db db 89 6b ae da 2d 79 |.....q.....k..-y| +000001b0 02 03 01 00 01 a3 81 a7 30 81 a4 30 1d 06 03 55 |........0..0...U| +000001c0 1d 0e 04 16 04 14 b1 ad e2 85 5a cf cb 28 db 69 |..........Z..(.i| +000001d0 ce 23 69 de d3 26 8e 18 88 39 30 75 06 03 55 1d |.#i..&...90u..U.| +000001e0 23 04 6e 30 6c 80 14 b1 ad e2 85 5a cf cb 28 db |#.n0l......Z..(.| +000001f0 69 ce 23 69 de d3 26 8e 18 88 39 a1 49 a4 47 30 |i.#i..&...9.I.G0| +00000200 45 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 |E1.0...U....AU1.| +00000210 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 |0...U....Some-St| +00000220 61 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e |ate1!0...U....In| +00000230 74 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 |ternet Widgits P| +00000240 74 79 20 4c 74 64 82 09 00 85 b0 bb a4 8a 7f b8 |ty Ltd..........| +00000250 ca 30 0c 06 03 55 1d 13 04 05 30 03 01 01 ff 30 |.0...U....0....0| +00000260 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 03 81 |...*.H..........| +00000270 81 00 08 6c 45 24 c7 6b b1 59 ab 0c 52 cc f2 b0 |...lE$.k.Y..R...| +00000280 14 d7 87 9d 7a 64 75 b5 5a 95 66 e4 c5 2b 8e ae |....zdu.Z.f..+..| +00000290 12 66 1f eb 4f 38 b3 6e 60 d3 92 fd f7 41 08 b5 |.f..O8.n`....A..| +000002a0 25 13 b1 18 7a 24 fb 30 1d ba ed 98 b9 17 ec e7 |%...z$.0........| +000002b0 d7 31 59 db 95 d3 1d 78 ea 50 56 5c d5 82 5a 2d |.1Y....x.PV\..Z-| +000002c0 5a 5f 33 c4 b6 d8 c9 75 90 96 8c 0f 52 98 b5 cd |Z_3....u....R...| +000002d0 98 1f 89 20 5f f2 a0 1c a3 1b 96 94 dd a9 fd 57 |... _..........W| +000002e0 e9 70 e8 26 6d 71 99 9b 26 6e 38 50 29 6c 90 a7 |.p.&mq..&n8P)l..| +000002f0 bd d9 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 |..............A.| +00000300 1e 18 37 ef 0d 19 51 88 35 75 71 b5 e5 54 5b 12 |..7...Q.5uq..T[.| +00000310 2e 8f 09 67 fd a7 24 20 3e b2 56 1c ce 97 28 5e |...g..$ >.V...(^| +00000320 f8 2b 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 32 42 |.+-O....lK[.V.2B| +00000330 e9 58 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc 5a 89 |.X..I..h.A.Vk.Z.| +00000340 04 01 00 80 9d 84 09 35 73 fb f6 ea 94 7b 49 fb |.......5s....{I.| +00000350 c2 70 b1 11 64 5b 93 9f d9 8c f5 56 98 f6 d3 66 |.p..d[.....V...f| +00000360 a6 1d 18 56 88 87 71 3f b0 38 9d 44 1f ad 2c 0d |...V..q?.8.D..,.| +00000370 3a a7 e8 d4 3e 33 3c 41 20 f3 3f 5c e5 fb e3 23 |:...>36as.d...mP| +000003b0 33 55 c7 e1 c5 a5 4c 32 5c 95 dc 07 43 60 49 11 |3U....L2\...C`I.| +000003c0 e9 98 cc ba 16 03 03 00 04 0e 00 00 00 |.............| +>>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 28 02 84 d5 b4 |....F...BA.(....| +00000010 58 07 47 d5 a0 d6 0b 1d 37 91 e6 34 a4 ad 0b ad |X.G.....7..4....| +00000020 22 01 82 77 a7 32 86 78 83 3a da 75 2f e5 68 7a |"..w.2.x.:.u/.hz| +00000030 de e4 05 e0 02 47 40 4e 38 d2 2c c3 7b da 53 73 |.....G@N8.,.{.Ss| +00000040 19 cb 8b 73 34 72 4d 33 71 39 c8 14 03 03 00 01 |...s4rM3q9......| +00000050 01 16 03 03 00 40 10 63 43 76 83 bd 36 e4 1e 4d |.....@.cCv..6..M| +00000060 7e 13 b0 ac aa c8 ec 90 31 df 84 46 49 68 39 5a |~.......1..FIh9Z| +00000070 05 8b 73 32 86 15 3a 18 57 d8 e2 2c 2d 05 89 93 |..s2..:.W..,-...| +00000080 37 b8 dd 73 33 92 ff a7 b2 53 27 94 b7 25 56 64 |7..s3....S'..%Vd| +00000090 a1 d3 2c f7 6b 71 |..,.kq| +>>> 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 21 5c 31 b1 4b |...........!\1.K| +00000020 96 96 30 8f 79 35 3a 3a 2d 26 67 d0 70 48 be 30 |..0.y5::-&g.pH.0| +00000030 f8 3e e8 c1 cb 1d d5 89 f6 9c 72 bb 1c f9 4d 90 |.>........r...M.| +00000040 9c d7 c6 fa 40 76 a5 61 46 61 24 17 03 03 00 40 |....@v.aFa$....@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 94 8a 14 04 06 b9 30 a0 67 fd b2 4c 84 f4 10 93 |......0.g..L....| +00000070 7d d4 2b 23 f0 e9 62 93 c2 20 a2 f2 7c 07 21 4b |}.+#..b.. ..|.!K| +00000080 94 ba 7b 7d cb 77 da 85 93 bd 53 ee ca db 9b 3e |..{}.w....S....>| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 17 3f 53 8d b3 35 b4 84 ed bb 12 |......?S..5.....| +000000b0 cf 73 25 25 7c c3 d3 bb 1f 5a 6b 73 9a 8a b1 a2 |.s%%|....Zks....| +000000c0 ba 99 f8 0e 43 |....C| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven b/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven new file mode 100644 index 0000000000..547f79834d --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven @@ -0,0 +1,122 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 5c 01 00 00 58 03 03 52 cc 57 59 65 |....\...X..R.WYe| +00000010 ae b3 ec a4 7a 05 f7 ec 39 22 7d 8c 91 96 6b e0 |....z...9"}...k.| +00000020 69 81 ff 88 28 17 60 ac 94 19 ff 00 00 04 00 05 |i...(.`.........| +00000030 00 ff 01 00 00 2b 00 0d 00 22 00 20 06 01 06 02 |.....+...". ....| +00000040 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................| +00000050 03 02 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 |................| +00000060 01 |.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 0f 0d 00 |n8P)l...........| +00000300 00 0b 02 01 40 00 04 04 01 04 03 00 00 16 03 03 |....@...........| +00000310 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 02 0a 0b 00 02 06 00 02 03 00 02 00 30 |...............0| +00000010 82 01 fc 30 82 01 5e 02 09 00 9a 30 84 6c 26 35 |...0..^....0.l&5| +00000020 d9 17 30 09 06 07 2a 86 48 ce 3d 04 01 30 45 31 |..0...*.H.=..0E1| +00000030 0b 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 |.0...U....AU1.0.| +00000040 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 |..U....Some-Stat| +00000050 65 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 |e1!0...U....Inte| +00000060 72 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 |rnet Widgits Pty| +00000070 20 4c 74 64 30 1e 17 0d 31 32 31 31 31 34 31 33 | Ltd0...12111413| +00000080 32 35 35 33 5a 17 0d 32 32 31 31 31 32 31 33 32 |2553Z..221112132| +00000090 35 35 33 5a 30 41 31 0b 30 09 06 03 55 04 06 13 |553Z0A1.0...U...| +000000a0 02 41 55 31 0c 30 0a 06 03 55 04 08 13 03 4e 53 |.AU1.0...U....NS| +000000b0 57 31 10 30 0e 06 03 55 04 07 13 07 50 79 72 6d |W1.0...U....Pyrm| +000000c0 6f 6e 74 31 12 30 10 06 03 55 04 03 13 09 4a 6f |ont1.0...U....Jo| +000000d0 65 6c 20 53 69 6e 67 30 81 9b 30 10 06 07 2a 86 |el Sing0..0...*.| +000000e0 48 ce 3d 02 01 06 05 2b 81 04 00 23 03 81 86 00 |H.=....+...#....| +000000f0 04 00 95 8c 91 75 14 c0 5e c4 57 b4 d4 c3 6f 8d |.....u..^.W...o.| +00000100 ae 68 1e dd 6f ce 86 e1 7e 6e b2 48 3e 81 e5 4e |.h..o...~n.H>..N| +00000110 e2 c6 88 4b 64 dc f5 30 bb d3 ff 65 cc 5b f4 dd |...Kd..0...e.[..| +00000120 b5 6a 3e 3e d0 1d de 47 c3 76 ad 19 f6 45 2c 8c |.j>>...G.v...E,.| +00000130 bc d8 1d 01 4c 1f 70 90 46 76 48 8b 8f 83 cc 4a |....L.p.FvH....J| +00000140 5c 8f 40 76 da e0 89 ec 1d 2b c4 4e 30 76 28 41 |\.@v.....+.N0v(A| +00000150 b2 62 a8 fb 5b f1 f9 4e 7a 8d bd 09 b8 ae ea 8b |.b..[..Nz.......| +00000160 18 27 4f 2e 70 fe 13 96 ba c3 d3 40 16 cd 65 4e |.'O.p......@..eN| +00000170 ac 11 1e e6 f1 30 09 06 07 2a 86 48 ce 3d 04 01 |.....0...*.H.=..| +00000180 03 81 8c 00 30 81 88 02 42 00 e0 14 c4 60 60 0b |....0...B....``.| +00000190 72 68 b0 32 5d 61 4a 02 74 5c c2 81 b9 16 a8 3f |rh.2]aJ.t\.....?| +000001a0 29 c8 36 c7 81 ff 6c b6 5b d9 70 f1 38 3b 50 48 |).6...l.[.p.8;PH| +000001b0 28 94 cb 09 1a 52 f1 5d ee 8d f2 b9 f0 f0 da d9 |(....R.]........| +000001c0 15 3a f9 bd 03 7a 87 a2 23 35 ec 02 42 01 a3 d4 |.:...z..#5..B...| +000001d0 8a 78 35 1c 4a 9a 23 d2 0a be 2b 10 31 9d 9c 5f |.x5.J.#...+.1.._| +000001e0 be e8 91 b3 da 1a f5 5d a3 23 f5 26 8b 45 70 8d |.......].#.&.Ep.| +000001f0 65 62 9b 7e 01 99 3d 18 f6 10 9a 38 61 9b 2e 57 |eb.~..=....8a..W| +00000200 e4 fa cc b1 8a ce e2 23 a0 87 f0 e1 67 51 eb 16 |.......#....gQ..| +00000210 03 03 00 86 10 00 00 82 00 80 47 5a 2f b8 78 46 |..........GZ/.xF| +00000220 9f 3c fc ab 8b 35 c9 77 da c3 96 78 31 7c 2b 4f |.<...5.w...x1|+O| +00000230 56 be 0f 33 bd 17 bc 1c 86 5a ae b3 0f 8b 18 2f |V..3.....Z...../| +00000240 48 0d e0 0a 20 d3 53 96 88 d2 8a 7d b6 58 13 44 |H... .S....}.X.D| +00000250 a5 e8 19 6d 02 df a6 1b 79 c5 54 c2 ef 4d 41 4f |...m....y.T..MAO| +00000260 04 1c eb 37 55 b7 2b f4 7c 6d 37 9c f1 89 a0 2c |...7U.+.|m7....,| +00000270 0f ba 10 09 e4 a1 ee 0a 7e 9a fd 2c 32 63 1c 55 |........~..,2c.U| +00000280 85 38 de d0 7b 5f 46 03 1f cc 4d 69 51 97 d8 d7 |.8..{_F...MiQ...| +00000290 88 6f ba 43 04 b0 42 09 61 5e 16 03 03 00 92 0f |.o.C..B.a^......| +000002a0 00 00 8e 04 03 00 8a 30 81 87 02 41 14 3d 4c 71 |.......0...A.=Lq| +000002b0 c2 32 4a 20 ee b7 69 17 55 e8 99 55 11 76 51 7a |.2J ..i.U..U.vQz| +000002c0 74 55 e7 e8 c3 3b b3 70 db 1c 8e f6 8a d4 99 40 |tU...;.p.......@| +000002d0 6e da 04 fd 7a 47 41 d6 ae c0 63 ad fd 91 a8 58 |n...zGA...c....X| +000002e0 24 b9 ac 2f 7a 4c bf 5b 24 12 cb 3a f3 02 42 00 |$../zL.[$..:..B.| +000002f0 90 f9 48 97 0e d4 33 99 09 9f 1d a8 97 16 60 82 |..H...3.......`.| +00000300 85 cc 5a 5d 79 f7 2f 03 2a c0 b8 12 61 ac 9f 88 |..Z]y./.*...a...| +00000310 1d 0d 9e 0a ee 28 a8 5a e2 42 b7 94 e2 e6 0e 13 |.....(.Z.B......| +00000320 c8 64 dc 4e d3 6b 10 d6 83 41 9c dc d4 53 c3 08 |.d.N.k...A...S..| +00000330 19 14 03 03 00 01 01 16 03 03 00 24 ef bd e3 23 |...........$...#| +00000340 10 23 ae 6e b5 12 eb 9c 21 78 db 36 fd bf 7f ee |.#.n....!x.6....| +00000350 6f c8 00 2d b6 35 cc 2f 38 73 ae a4 34 cf 0d df |o..-.5./8s..4...| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 24 a7 50 0f 50 b4 |..........$.P.P.| +00000010 1c c3 4d f3 7a 64 df 65 ac 35 22 13 46 cc ec 36 |..M.zd.e.5".F..6| +00000020 e6 d2 f3 67 94 6a 18 85 9f 4a 3c 44 a3 58 b0 17 |...g.j...J>> Flow 1 (client to server) +00000000 16 03 01 00 5c 01 00 00 58 03 03 52 cc 57 59 6b |....\...X..R.WYk| +00000010 11 07 04 39 77 20 c2 b4 3f cb 0a c9 53 fe 5b 3e |...9w ..?...S.[>| +00000020 5f 58 2c 7e 30 69 e1 8e 6c 9d c8 00 00 04 00 05 |_X,~0i..l.......| +00000030 00 ff 01 00 00 2b 00 0d 00 22 00 20 06 01 06 02 |.....+...". ....| +00000040 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................| +00000050 03 02 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 |................| +00000060 01 |.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 0f 0d 00 |n8P)l...........| +00000300 00 0b 02 01 40 00 04 04 01 04 03 00 00 16 03 03 |....@...........| +00000310 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 01 fb 0b 00 01 f7 00 01 f4 00 01 f1 30 |...............0| +00000010 82 01 ed 30 82 01 58 a0 03 02 01 02 02 01 00 30 |...0..X........0| +00000020 0b 06 09 2a 86 48 86 f7 0d 01 01 05 30 26 31 10 |...*.H......0&1.| +00000030 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 6f |0...U....Acme Co| +00000040 31 12 30 10 06 03 55 04 03 13 09 31 32 37 2e 30 |1.0...U....127.0| +00000050 2e 30 2e 31 30 1e 17 0d 31 31 31 32 30 38 30 37 |.0.10...11120807| +00000060 35 35 31 32 5a 17 0d 31 32 31 32 30 37 30 38 30 |5512Z..121207080| +00000070 30 31 32 5a 30 26 31 10 30 0e 06 03 55 04 0a 13 |012Z0&1.0...U...| +00000080 07 41 63 6d 65 20 43 6f 31 12 30 10 06 03 55 04 |.Acme Co1.0...U.| +00000090 03 13 09 31 32 37 2e 30 2e 30 2e 31 30 81 9c 30 |...127.0.0.10..0| +000000a0 0b 06 09 2a 86 48 86 f7 0d 01 01 01 03 81 8c 00 |...*.H..........| +000000b0 30 81 88 02 81 80 4e d0 7b 31 e3 82 64 d9 59 c0 |0.....N.{1..d.Y.| +000000c0 c2 87 a4 5e 1e 8b 73 33 c7 63 53 df 66 92 06 84 |...^..s3.cS.f...| +000000d0 f6 64 d5 8f e4 36 a7 1d 2b e8 b3 20 36 45 23 b5 |.d...6..+.. 6E#.| +000000e0 e3 95 ae ed e0 f5 20 9c 8d 95 df 7f 5a 12 ef 87 |...... .....Z...| +000000f0 e4 5b 68 e4 e9 0e 74 ec 04 8a 7f de 93 27 c4 01 |.[h...t......'..| +00000100 19 7a bd f2 dc 3d 14 ab d0 54 ca 21 0c d0 4d 6e |.z...=...T.!..Mn| +00000110 87 2e 5c c5 d2 bb 4d 4b 4f ce b6 2c f7 7e 88 ec |..\...MKO..,.~..| +00000120 7c d7 02 91 74 a6 1e 0c 1a da e3 4a 5a 2e de 13 ||...t......JZ...| +00000130 9c 4c 40 88 59 93 02 03 01 00 01 a3 32 30 30 30 |.L@.Y.......2000| +00000140 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 00 a0 30 |...U...........0| +00000150 0d 06 03 55 1d 0e 04 06 04 04 01 02 03 04 30 0f |...U..........0.| +00000160 06 03 55 1d 23 04 08 30 06 80 04 01 02 03 04 30 |..U.#..0.......0| +00000170 0b 06 09 2a 86 48 86 f7 0d 01 01 05 03 81 81 00 |...*.H..........| +00000180 36 1f b3 7a 0c 75 c9 6e 37 46 61 2b d5 bd c0 a7 |6..z.u.n7Fa+....| +00000190 4b cc 46 9a 81 58 7c 85 79 29 c8 c8 c6 67 dd 32 |K.F..X|.y)...g.2| +000001a0 56 45 2b 75 b6 e9 24 a9 50 9a be 1f 5a fa 1a 15 |VE+u..$.P...Z...| +000001b0 d9 cc 55 95 72 16 83 b9 c2 b6 8f fd 88 8c 38 84 |..U.r.........8.| +000001c0 1d ab 5d 92 31 13 4f fd 83 3b c6 9d f1 11 62 b6 |..].1.O..;....b.| +000001d0 8b ec ab 67 be c8 64 b0 11 50 46 58 17 6b 99 1c |...g..d..PFX.k..| +000001e0 d3 1d fc 06 f1 0e e5 96 a8 0c f9 78 20 b7 44 18 |...........x .D.| +000001f0 51 8d 10 7e 4f 94 67 df a3 4e 70 73 8e 90 91 85 |Q..~O.g..Nps....| +00000200 16 03 03 00 86 10 00 00 82 00 80 44 89 7d aa 26 |...........D.}.&| +00000210 30 ce 6b db 25 70 b0 1e 16 fa 5b 3a dd 4a 4b bd |0.k.%p....[:.JK.| +00000220 ec ee 50 9d 21 ba 52 b5 51 4f a8 65 d8 2e 41 e2 |..P.!.R.QO.e..A.| +00000230 e1 dc f3 1a df 58 4f 87 7a d3 e1 e1 1c 13 b2 0b |.....XO.z.......| +00000240 b7 43 b7 92 f2 df 19 bb 79 71 e0 71 44 ab 19 2f |.C......yq.qD../| +00000250 37 11 ac 62 50 b6 f1 53 fe aa b4 bc 29 8e 0b 4c |7..bP..S....)..L| +00000260 0b 12 8d d5 84 a9 fa a9 ea 16 aa c3 0d da 32 c8 |..............2.| +00000270 e0 4c 9f 99 f8 69 cd a8 c3 b1 76 42 67 f3 ff 15 |.L...i....vBg...| +00000280 52 95 43 66 da 49 43 25 9d e5 eb 16 03 03 00 88 |R.Cf.IC%........| +00000290 0f 00 00 84 04 01 00 80 01 d5 0e 1c 75 97 89 52 |............u..R| +000002a0 1a f0 cc ef 93 6e 71 b2 b1 38 8c 50 11 f7 a3 02 |.....nq..8.P....| +000002b0 71 c4 d5 6f 8d 01 83 06 2e ea 5a 10 8a 0d d0 fc |q..o......Z.....| +000002c0 b6 a2 63 af 4f 99 b5 eb ab fd 01 c2 fb 26 fc fd |..c.O........&..| +000002d0 ad 2c b3 63 b3 87 a6 f5 14 ea 7d e7 fe a8 e7 7e |.,.c......}....~| +000002e0 20 ab b9 f6 c3 58 bd c0 f3 96 eb 83 dc 42 6c 0d | ....X.......Bl.| +000002f0 5e e8 09 55 c7 b8 24 05 dd e1 7c af 9f 2c 22 6c |^..U..$...|..,"l| +00000300 fa b8 94 13 3b f1 09 e1 38 59 fc a1 8c cb aa ca |....;...8Y......| +00000310 f8 e0 2a 9c 36 f9 c3 2b 14 03 03 00 01 01 16 03 |..*.6..+........| +00000320 03 00 24 d0 12 7c cc d2 3e 37 1f f4 7d b4 c0 fc |..$..|..>7..}...| +00000330 19 f6 c8 ea 62 12 e0 0d af 62 d4 69 f7 96 5a c0 |....b....b.i..Z.| +00000340 97 d3 bb b0 a3 f7 3f |......?| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 24 cd 20 85 1e 74 |..........$. ..t| +00000010 18 b2 71 48 d5 10 61 c6 b0 18 26 83 c2 7f f1 b1 |..qH..a...&.....| +00000020 2f b5 35 d0 47 a8 99 9a 9a a5 62 64 fb f9 29 17 |/.5.G.....bd..).| +00000030 03 03 00 21 22 7b ed 61 e3 9b 6d 98 b9 23 98 e3 |...!"{.a..m..#..| +00000040 55 11 b8 0f 7e 2b e1 c1 d4 f1 83 79 c3 f8 03 f0 |U...~+.....y....| +00000050 02 5c 61 24 d7 15 03 03 00 16 14 2b a3 5a 56 f0 |.\a$.......+.ZV.| +00000060 92 da d0 e6 32 91 d8 30 7a b4 d0 a2 93 f5 01 ea |....2..0z.......| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven b/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven new file mode 100644 index 0000000000..562fe1aaa0 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven @@ -0,0 +1,81 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 5c 01 00 00 58 03 03 52 cc 57 59 1b |....\...X..R.WY.| +00000010 08 fe f7 8a bf 07 84 2b 60 a6 13 2d 15 13 f8 b6 |.......+`..-....| +00000020 d4 b6 3b f2 7a 98 ff 32 a0 68 7c 00 00 04 00 05 |..;.z..2.h|.....| +00000030 00 ff 01 00 00 2b 00 0d 00 22 00 20 06 01 06 02 |.....+...". ....| +00000040 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................| +00000050 03 02 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 |................| +00000060 01 |.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 0f 0d 00 |n8P)l...........| +00000300 00 0b 02 01 40 00 04 04 01 04 03 00 00 16 03 03 |....@...........| +00000310 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 07 0b 00 00 03 00 00 00 16 03 03 00 |................| +00000010 86 10 00 00 82 00 80 6b 51 48 d3 18 7d 30 e0 0c |.......kQH..}0..| +00000020 20 8d f3 e4 39 47 30 0e a5 85 79 f9 8b 11 50 9e | ...9G0...y...P.| +00000030 81 71 5c 26 c6 bb cb aa d5 00 d1 89 79 b1 77 2d |.q\&........y.w-| +00000040 eb 9b 86 7c 52 c6 f7 b7 10 b0 b6 94 22 51 b8 12 |...|R......."Q..| +00000050 3c 09 35 8e 1b cc f4 3b b7 b8 78 ab 89 59 41 49 |<.5....;..x..YAI| +00000060 21 31 eb f0 f8 94 63 3d e6 96 8f b6 63 95 05 dd |!1....c=....c...| +00000070 46 b3 00 8a d6 83 75 99 1b 5a 48 0a 23 b5 10 c1 |F.....u..ZH.#...| +00000080 95 b5 bc 15 72 b5 f5 a0 62 e2 1d c0 ff d2 87 a5 |....r...b.......| +00000090 97 5c 33 49 a7 26 35 14 03 03 00 01 01 16 03 03 |.\3I.&5.........| +000000a0 00 24 61 38 1f 9d fb d9 65 2e 02 07 fb be f9 85 |.$a8....e.......| +000000b0 8d 15 34 c0 d1 0e 4e 10 3c 25 60 2f ac 04 21 66 |..4...N.<%`/..!f| +000000c0 04 9d 9a 60 31 72 |...`1r| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 24 fe 0e 3e 84 af |..........$..>..| +00000010 e5 6b 10 ed 41 9c 2b e0 ba e0 2b 53 61 36 1b 40 |.k..A.+...+Sa6.@| +00000020 35 de 3a c7 c3 5c df 74 67 f7 05 74 84 f5 e1 17 |5.:..\.tg..t....| +00000030 03 03 00 21 d3 8d 81 85 b7 1f 30 bd 89 33 f9 81 |...!......0..3..| +00000040 89 f7 af d1 be b0 c1 46 e3 df 32 f6 dc 2f 4d 82 |.......F..2../M.| +00000050 0a 84 9f 5b 03 15 03 03 00 16 13 af 37 91 82 67 |...[........7..g| +00000060 b0 7c 5e 0e ec 8e cc 31 a0 ea a5 72 a4 2b 0b 73 |.|^....1...r.+.s| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES new file mode 100644 index 0000000000..aacbb86705 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES @@ -0,0 +1,89 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 9c 01 00 00 98 03 03 53 04 f0 f9 09 |...........S....| +00000010 13 56 01 37 84 b1 32 59 4c 73 b1 8e bb 02 1a 32 |.V.7..2YLs.....2| +00000020 db ab 8c e6 ed ad 7f 52 9a 59 39 00 00 04 c0 0a |.......R.Y9.....| +00000030 00 ff 01 00 00 6b 00 0b 00 04 03 00 01 02 00 0a |.....k..........| +00000040 00 34 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 |.4.2............| +00000050 00 09 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 |................| +00000060 00 15 00 04 00 05 00 12 00 13 00 01 00 02 00 03 |................| +00000070 00 0f 00 10 00 11 00 0d 00 22 00 20 06 01 06 02 |.........". ....| +00000080 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................| +00000090 03 02 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 |................| +000000a0 01 |.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 0a 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 03 02 0e 0b 00 02 0a 00 |................| +00000040 02 07 00 02 04 30 82 02 00 30 82 01 62 02 09 00 |.....0...0..b...| +00000050 b8 bf 2d 47 a0 d2 eb f4 30 09 06 07 2a 86 48 ce |..-G....0...*.H.| +00000060 3d 04 01 30 45 31 0b 30 09 06 03 55 04 06 13 02 |=..0E1.0...U....| +00000070 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +00000080 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000090 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +000000a0 74 73 20 50 74 79 20 4c 74 64 30 1e 17 0d 31 32 |ts Pty Ltd0...12| +000000b0 31 31 32 32 31 35 30 36 33 32 5a 17 0d 32 32 31 |1122150632Z..221| +000000c0 31 32 30 31 35 30 36 33 32 5a 30 45 31 0b 30 09 |120150632Z0E1.0.| +000000d0 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 55 |..U....AU1.0...U| +000000e0 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 |....Some-State1!| +000000f0 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 |0...U....Interne| +00000100 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 |t Widgits Pty Lt| +00000110 64 30 81 9b 30 10 06 07 2a 86 48 ce 3d 02 01 06 |d0..0...*.H.=...| +00000120 05 2b 81 04 00 23 03 81 86 00 04 00 c4 a1 ed be |.+...#..........| +00000130 98 f9 0b 48 73 36 7e c3 16 56 11 22 f2 3d 53 c3 |...Hs6~..V.".=S.| +00000140 3b 4d 21 3d cd 6b 75 e6 f6 b0 dc 9a df 26 c1 bc |;M!=.ku......&..| +00000150 b2 87 f0 72 32 7c b3 64 2f 1c 90 bc ea 68 23 10 |...r2|.d/....h#.| +00000160 7e fe e3 25 c0 48 3a 69 e0 28 6d d3 37 00 ef 04 |~..%.H:i.(m.7...| +00000170 62 dd 0d a0 9c 70 62 83 d8 81 d3 64 31 aa 9e 97 |b....pb....d1...| +00000180 31 bd 96 b0 68 c0 9b 23 de 76 64 3f 1a 5c 7f e9 |1...h..#.vd?.\..| +00000190 12 0e 58 58 b6 5f 70 dd 9b d8 ea d5 d7 f5 d5 cc |..XX._p.........| +000001a0 b9 b6 9f 30 66 5b 66 9a 20 e2 27 e5 bf fe 3b 30 |...0f[f. .'...;0| +000001b0 09 06 07 2a 86 48 ce 3d 04 01 03 81 8c 00 30 81 |...*.H.=......0.| +000001c0 88 02 42 01 88 a2 4f eb e2 45 c5 48 7d 1b ac f5 |..B...O..E.H}...| +000001d0 ed 98 9d ae 47 70 c0 5e 1b b6 2f bd f1 b6 4d b7 |....Gp.^../...M.| +000001e0 61 40 d3 11 a2 ce ee 0b 7e 92 7e ff 76 9d c3 3b |a@......~.~.v..;| +000001f0 7e a5 3f ce fa 10 e2 59 ec 47 2d 7c ac da 4e 97 |~.?....Y.G-|..N.| +00000200 0e 15 a0 6f d0 02 42 01 4d fc be 67 13 9c 2d 05 |...o..B.M..g..-.| +00000210 0e bd 3f a3 8c 25 c1 33 13 83 0d 94 06 bb d4 37 |..?..%.3.......7| +00000220 7a f6 ec 7a c9 86 2e dd d7 11 69 7f 85 7c 56 de |z..z......i..|V.| +00000230 fb 31 78 2b e4 c7 78 0d ae cb be 9e 4e 36 24 31 |.1x+..x.....N6$1| +00000240 7b 6a 0f 39 95 12 07 8f 2a 16 03 03 00 d8 0c 00 |{j.9....*.......| +00000250 00 d4 03 00 17 41 04 1e 18 37 ef 0d 19 51 88 35 |.....A...7...Q.5| +00000260 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 3e |uq..T[....g..$ >| +00000270 b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f 6c |.V...(^.+-O....l| +00000280 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 1a |K[.V.2B.X..I..h.| +00000290 41 03 56 6b dc 5a 89 04 03 00 8b 30 81 88 02 42 |A.Vk.Z.....0...B| +000002a0 00 c6 85 8e 06 b7 04 04 e9 cd 9e 3e cb 66 23 95 |...........>.f#.| +000002b0 b4 42 9c 64 81 39 05 3f b5 21 f8 28 af 60 6b 4d |.B.d.9.?.!.(.`kM| +000002c0 3d ba a1 4b 5e 77 ef e7 59 28 fe 1d c1 27 a2 ff |=..K^w..Y(...'..| +000002d0 a8 de 33 48 b3 c1 85 6a 42 9b f9 7e 7e 31 c2 e5 |..3H...jB..~~1..| +000002e0 bd 66 02 42 00 ad 7d 06 35 ab ec 8d ac d4 ba 1b |.f.B..}.5.......| +000002f0 49 5e 05 5f f0 97 93 82 b8 2b 8d 91 98 63 8e b4 |I^._.....+...c..| +00000300 14 62 db 1e c9 2c 13 ae b7 d3 17 38 23 2f f6 7f |.b...,.....8#/..| +00000310 0c 4d d3 33 d2 79 d1 77 ee cb b1 c2 fc 34 b8 69 |.M.3.y.w.....4.i| +00000320 f9 10 8b 61 89 85 16 03 03 00 04 0e 00 00 00 |...a...........| +>>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 dd 22 68 a1 4e |....F...BA.."h.N| +00000010 04 1b 47 f9 c5 7d 04 1d d8 fe 84 fa be 31 2e a7 |..G..}.......1..| +00000020 f8 e5 b8 14 92 44 99 11 0e 34 97 fc e5 b1 91 cf |.....D...4......| +00000030 a4 d1 3f b4 71 94 c6 06 16 f0 98 c0 3e 05 f9 2f |..?.q.......>../| +00000040 0a 97 78 3d ef dc fa a2 d7 ee 7d 14 03 03 00 01 |..x=......}.....| +00000050 01 16 03 03 00 40 90 bf 7f e9 c9 6e d1 80 f5 12 |.....@.....n....| +00000060 6d c5 b7 c5 15 4b 18 a5 d3 18 1e f8 8c 4d 7e 6d |m....K.......M~m| +00000070 03 60 29 7c 45 7c b2 ca 8c 07 71 70 aa 23 fa 6e |.`)|E|....qp.#.n| +00000080 d9 0b 0a 32 4c 9e e5 00 f9 19 9b b6 8d dc d3 67 |...2L..........g| +00000090 3d 0f bb b8 4b 9e |=...K.| +>>> 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 a1 6e e5 d1 ca |............n...| +00000020 03 f4 77 dc ec ee 5d f0 22 5e 7f 55 1a 8d ad 45 |..w...]."^.U...E| +00000030 09 f1 3b b2 61 36 dc 3d 2a 1e 1f e5 a7 84 76 a9 |..;.a6.=*.....v.| +00000040 41 5b 86 03 ac 22 18 20 9b a9 29 17 03 03 00 40 |A[...". ..)....@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 f5 cb 28 1e b5 bc 82 7f 82 38 54 14 e8 b9 6d 3b |..(......8T...m;| +00000070 bc 99 d6 0e f9 00 96 99 a8 92 2e 86 9d 62 4e 90 |.............bN.| +00000080 27 52 58 45 20 93 90 a1 f3 a8 89 2b e7 21 24 16 |'RXE ......+.!$.| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 a8 2a ab 8f b0 ce 49 8b fd a5 c9 |......*....I....| +000000b0 11 b2 04 83 18 f3 1d 6c 82 34 1d df dd 2f 45 3b |.......l.4.../E;| +000000c0 27 8a 0f 16 69 |'...i| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicket b/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicket new file mode 100644 index 0000000000..e3e62f2242 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicket @@ -0,0 +1,87 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 60 01 00 00 5c 03 03 52 cc 57 59 7e |....`...\..R.WY~| +00000010 43 5c 3b fd 50 ab 61 3f 64 a4 f9 bd ba 8c 28 e1 |C\;.P.a?d.....(.| +00000020 f9 a1 45 7e 48 9e 62 af 25 de 0e 00 00 04 00 05 |..E~H.b.%.......| +00000030 00 ff 01 00 00 2f 00 23 00 00 00 0d 00 22 00 20 |...../.#.....". | +00000040 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 02 |................| +00000050 04 03 03 01 03 02 03 03 02 01 02 02 02 03 01 01 |................| +00000060 00 0f 00 01 01 |.....| +>>> Flow 2 (server to client) +00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 |................| +00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 be 0b |..#.............| +00000040 00 02 ba 00 02 b7 00 02 b4 30 82 02 b0 30 82 02 |.........0...0..| +00000050 19 a0 03 02 01 02 02 09 00 85 b0 bb a4 8a 7f b8 |................| +00000060 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 |.0...*.H........| +00000070 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 |0E1.0...U....AU1| +00000080 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 |.0...U....Some-S| +00000090 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 |tate1!0...U....I| +000000a0 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 |nternet Widgits | +000000b0 50 74 79 20 4c 74 64 30 1e 17 0d 31 30 30 34 32 |Pty Ltd0...10042| +000000c0 34 30 39 30 39 33 38 5a 17 0d 31 31 30 34 32 34 |4090938Z..110424| +000000d0 30 39 30 39 33 38 5a 30 45 31 0b 30 09 06 03 55 |090938Z0E1.0...U| +000000e0 04 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 |....AU1.0...U...| +000000f0 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 |.Some-State1!0..| +00000100 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 |.U....Internet W| +00000110 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 30 81 |idgits Pty Ltd0.| +00000120 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 |.0...*.H........| +00000130 03 81 8d 00 30 81 89 02 81 81 00 bb 79 d6 f5 17 |....0.......y...| +00000140 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 43 5a d0 03 |...F...i..+.CZ..| +00000150 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 |-.zC...R..eL,x.#| +00000160 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 |........;~b.,.3.| +00000170 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b 26 3f b5 cd |..\zV.....X{&?..| +00000180 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a bf ef 42 71 |....!.J..T.Z..Bq| +00000190 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e |......~.}}..9...| +000001a0 db 51 c9 7c e3 c0 4c 3b 32 66 01 cf af b1 1d b8 |.Q.|..L;2f......| +000001b0 71 9a 1d db db 89 6b ae da 2d 79 02 03 01 00 01 |q.....k..-y.....| +000001c0 a3 81 a7 30 81 a4 30 1d 06 03 55 1d 0e 04 16 04 |...0..0...U.....| +000001d0 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 de d3 |.....Z..(.i.#i..| +000001e0 26 8e 18 88 39 30 75 06 03 55 1d 23 04 6e 30 6c |&...90u..U.#.n0l| +000001f0 80 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 de |......Z..(.i.#i.| +00000200 d3 26 8e 18 88 39 a1 49 a4 47 30 45 31 0b 30 09 |.&...9.I.G0E1.0.| +00000210 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 55 |..U....AU1.0...U| +00000220 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 |....Some-State1!| +00000230 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 |0...U....Interne| +00000240 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 |t Widgits Pty Lt| +00000250 64 82 09 00 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 |d...........0...| +00000260 55 1d 13 04 05 30 03 01 01 ff 30 0d 06 09 2a 86 |U....0....0...*.| +00000270 48 86 f7 0d 01 01 05 05 00 03 81 81 00 08 6c 45 |H.............lE| +00000280 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a |$.k.Y..R.......z| +00000290 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f |du.Z.f..+...f..O| +000002a0 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 13 b1 18 7a |8.n`....A..%...z| +000002b0 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 31 59 db 95 |$.0.........1Y..| +000002c0 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 |..x.PV\..Z-Z_3..| +000002d0 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f |..u....R...... _| +000002e0 f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d |..........W.p.&m| +000002f0 71 99 9b 26 6e 38 50 29 6c 90 a7 bd d9 16 03 03 |q..&n8P)l.......| +00000300 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 6e 2e 79 82 3a |...........n.y.:| +00000010 c4 68 72 f5 a2 42 3d 71 f9 ec 22 8c 0b fa f0 82 |.hr..B=q..".....| +00000020 82 c0 cb fc 52 0a 51 03 04 8c eb 4a 4e 4f b6 49 |....R.Q....JNO.I| +00000030 ef 94 65 21 3c f7 9d 46 85 6e 35 d5 17 6b ff a3 |..e!<..F.n5..k..| +00000040 5e 4d c1 36 1a 2f 68 f5 06 d4 2d 73 4f 1c 3b 7b |^M.6./h...-sO.;{| +00000050 c1 fa 4e 7e 7c f9 6c 13 a6 f4 3a 43 e9 aa be 22 |..N~|.l...:C..."| +00000060 85 6f 2f 7c 5b b0 08 e2 86 b2 ae cb a9 12 d8 32 |.o/|[..........2| +00000070 80 1d e4 2e 5d c3 66 d1 19 e5 89 33 2a 88 24 40 |....].f....3*.$@| +00000080 2a 6d 6b b5 f1 92 4b 66 06 b8 49 14 03 03 00 01 |*mk...Kf..I.....| +00000090 01 16 03 03 00 24 16 49 e2 a0 67 31 cf 0d 72 cb |.....$.I..g1..r.| +000000a0 ac 16 2c 80 37 71 69 f7 5f c4 d3 00 19 b7 4b fb |..,.7qi._.....K.| +000000b0 e5 e9 74 8e 30 b3 1c c5 ae e6 |..t.0.....| +>>> Flow 4 (server to client) +00000000 16 03 03 00 72 04 00 00 6e 00 00 00 00 00 68 00 |....r...n.....h.| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 |...............e| +00000020 ea 4b d1 ef ba 06 38 1e e1 88 82 3a cd 03 ac 3b |.K....8....:...;| +00000030 39 0a e0 19 fd af 6c 57 30 df 31 6e f7 92 38 4b |9.....lW0.1n..8K| +00000040 5d 77 90 39 ff 32 51 f5 ed 12 d7 b0 7c 4d 6c c5 |]w.9.2Q.....|Ml.| +00000050 76 e4 72 48 3e 59 23 fe 0d 15 df f4 ba ea b9 67 |v.rH>Y#........g| +00000060 16 23 8f 7d 15 b6 11 f1 ab d7 d4 cd a3 21 82 92 |.#.}.........!..| +00000070 2a 12 cf 95 f3 60 b2 14 03 03 00 01 01 16 03 03 |*....`..........| +00000080 00 24 89 ad 87 04 4f 08 dc 2a 71 37 fb f1 95 d1 |.$....O..*q7....| +00000090 2e 3c c2 6e 0f 38 5d e4 0e c3 f7 27 d0 46 a3 c1 |.<.n.8]....'.F..| +000000a0 a8 3b 06 ed 96 ec 17 03 03 00 21 30 d4 9f 0b 49 |.;........!0...I| +000000b0 9f a2 a8 a1 2c 0a 79 93 56 2d 8a ee 85 ed 62 42 |....,.y.V-....bB| +000000c0 8c 18 fe 7a 09 3a 24 c4 5e ed 7d 2a 15 03 03 00 |...z.:$.^.}*....| +000000d0 16 a0 24 0a 8b 90 4c fc 99 ba 67 bb 04 1e 59 69 |..$...L...g...Yi| +000000e0 c2 98 49 b5 00 0b e0 |..I....| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable b/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable new file mode 100644 index 0000000000..30f0026815 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable @@ -0,0 +1,87 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 60 01 00 00 5c 03 03 54 23 54 02 17 |....`...\..T#T..| +00000010 f3 53 13 3d 48 88 c3 19 b9 d1 3d 33 7f f5 99 56 |.S.=H.....=3...V| +00000020 04 71 1b d9 d5 64 8a 0d 4a 54 00 00 00 04 00 05 |.q...d..JT......| +00000030 00 ff 01 00 00 2f 00 23 00 00 00 0d 00 22 00 20 |...../.#.....". | +00000040 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 02 |................| +00000050 04 03 03 01 03 02 03 03 02 01 02 02 02 03 01 01 |................| +00000060 00 0f 00 01 01 |.....| +>>> Flow 2 (server to client) +00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 |................| +00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 be 0b |..#.............| +00000040 00 02 ba 00 02 b7 00 02 b4 30 82 02 b0 30 82 02 |.........0...0..| +00000050 19 a0 03 02 01 02 02 09 00 85 b0 bb a4 8a 7f b8 |................| +00000060 ca 30 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 |.0...*.H........| +00000070 30 45 31 0b 30 09 06 03 55 04 06 13 02 41 55 31 |0E1.0...U....AU1| +00000080 13 30 11 06 03 55 04 08 13 0a 53 6f 6d 65 2d 53 |.0...U....Some-S| +00000090 74 61 74 65 31 21 30 1f 06 03 55 04 0a 13 18 49 |tate1!0...U....I| +000000a0 6e 74 65 72 6e 65 74 20 57 69 64 67 69 74 73 20 |nternet Widgits | +000000b0 50 74 79 20 4c 74 64 30 1e 17 0d 31 30 30 34 32 |Pty Ltd0...10042| +000000c0 34 30 39 30 39 33 38 5a 17 0d 31 31 30 34 32 34 |4090938Z..110424| +000000d0 30 39 30 39 33 38 5a 30 45 31 0b 30 09 06 03 55 |090938Z0E1.0...U| +000000e0 04 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 |....AU1.0...U...| +000000f0 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 |.Some-State1!0..| +00000100 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 |.U....Internet W| +00000110 69 64 67 69 74 73 20 50 74 79 20 4c 74 64 30 81 |idgits Pty Ltd0.| +00000120 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 |.0...*.H........| +00000130 03 81 8d 00 30 81 89 02 81 81 00 bb 79 d6 f5 17 |....0.......y...| +00000140 b5 e5 bf 46 10 d0 dc 69 be e6 2b 07 43 5a d0 03 |...F...i..+.CZ..| +00000150 2d 8a 7a 43 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 |-.zC...R..eL,x.#| +00000160 8c b5 b4 82 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 |........;~b.,.3.| +00000170 fe 12 5c 7a 56 fc f5 06 bf fa 58 7b 26 3f b5 cd |..\zV.....X{&?..| +00000180 04 d3 d0 c9 21 96 4a c7 f4 54 9f 5a bf ef 42 71 |....!.J..T.Z..Bq| +00000190 00 fe 18 99 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e |......~.}}..9...| +000001a0 db 51 c9 7c e3 c0 4c 3b 32 66 01 cf af b1 1d b8 |.Q.|..L;2f......| +000001b0 71 9a 1d db db 89 6b ae da 2d 79 02 03 01 00 01 |q.....k..-y.....| +000001c0 a3 81 a7 30 81 a4 30 1d 06 03 55 1d 0e 04 16 04 |...0..0...U.....| +000001d0 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 de d3 |.....Z..(.i.#i..| +000001e0 26 8e 18 88 39 30 75 06 03 55 1d 23 04 6e 30 6c |&...90u..U.#.n0l| +000001f0 80 14 b1 ad e2 85 5a cf cb 28 db 69 ce 23 69 de |......Z..(.i.#i.| +00000200 d3 26 8e 18 88 39 a1 49 a4 47 30 45 31 0b 30 09 |.&...9.I.G0E1.0.| +00000210 06 03 55 04 06 13 02 41 55 31 13 30 11 06 03 55 |..U....AU1.0...U| +00000220 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 31 21 |....Some-State1!| +00000230 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 6e 65 |0...U....Interne| +00000240 74 20 57 69 64 67 69 74 73 20 50 74 79 20 4c 74 |t Widgits Pty Lt| +00000250 64 82 09 00 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 |d...........0...| +00000260 55 1d 13 04 05 30 03 01 01 ff 30 0d 06 09 2a 86 |U....0....0...*.| +00000270 48 86 f7 0d 01 01 05 05 00 03 81 81 00 08 6c 45 |H.............lE| +00000280 24 c7 6b b1 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a |$.k.Y..R.......z| +00000290 64 75 b5 5a 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f |du.Z.f..+...f..O| +000002a0 38 b3 6e 60 d3 92 fd f7 41 08 b5 25 13 b1 18 7a |8.n`....A..%...z| +000002b0 24 fb 30 1d ba ed 98 b9 17 ec e7 d7 31 59 db 95 |$.0.........1Y..| +000002c0 d3 1d 78 ea 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 |..x.PV\..Z-Z_3..| +000002d0 d8 c9 75 90 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f |..u....R...... _| +000002e0 f2 a0 1c a3 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d |..........W.p.&m| +000002f0 71 99 9b 26 6e 38 50 29 6c 90 a7 bd d9 16 03 03 |q..&n8P)l.......| +00000300 00 04 0e 00 00 00 |......| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 27 e9 a4 f7 e7 |...........'....| +00000010 df 25 de 84 8c 1f d6 e6 c3 11 28 55 9a c1 91 37 |.%........(U...7| +00000020 84 f5 ba f8 80 0d ca 50 cb 1e 72 f7 97 6f c2 b2 |.......P..r..o..| +00000030 04 4d 13 7c e0 6e a0 1f 91 e1 38 1b a2 c0 55 16 |.M.|.n....8...U.| +00000040 7f 29 fc ed 1c 1a cf 72 14 c3 00 c1 dd 36 36 af |.).....r.....66.| +00000050 a6 e4 a8 be ba ec 13 d0 1e d0 1d fd e1 5b 27 fd |.............['.| +00000060 9a da 2e 12 c8 b0 b9 c2 b9 76 ec 7f 3c 98 b6 63 |.........v..<..c| +00000070 bc da f0 07 7a 3d e7 61 f4 2f 12 80 3b f9 3b cc |....z=.a./..;.;.| +00000080 05 c8 2f 7e 28 b2 73 bf 97 61 29 14 03 03 00 01 |../~(.s..a).....| +00000090 01 16 03 03 00 24 17 59 a9 45 53 46 33 96 50 dd |.....$.Y.ESF3.P.| +000000a0 3e 23 aa 91 38 f8 56 4a 2f 1a f2 b1 44 9b ce 17 |>#..8.VJ/...D...| +000000b0 6b 8a 89 76 bc 67 b8 8b ba 90 |k..v.g....| +>>> Flow 4 (server to client) +00000000 16 03 03 00 72 04 00 00 6e 00 00 00 00 00 68 00 |....r...n.....h.| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 |...............e| +00000020 ea 4b d1 ef ba 2d db 0c ba 9a d4 20 76 57 c8 ec |.K...-..... vW..| +00000030 dc 2d 77 fb fb 3b 93 5f 53 e0 14 4f 90 fb d6 55 |.-w..;._S..O...U| +00000040 57 8c 8d 0d 25 ea 5d 0d f2 91 e5 12 22 12 ec 7b |W...%.]....."..{| +00000050 5f b6 6e fd 07 59 23 24 fc b1 97 ca ea 56 a5 c2 |_.n..Y#$.....V..| +00000060 a0 e4 9e 99 64 f2 64 d0 75 7a 46 63 e3 dc 21 ed |....d.d.uzFc..!.| +00000070 78 56 e9 e1 ab 66 80 14 03 03 00 01 01 16 03 03 |xV...f..........| +00000080 00 24 fc 14 68 07 17 1f df b7 84 cb fd c1 e0 e4 |.$..h...........| +00000090 f2 1a ea 34 b5 00 7f 70 be c8 1c 0a d6 55 e3 57 |...4...p.....U.W| +000000a0 50 4e 6d 7d 8a 5d 17 03 03 00 21 24 27 50 40 c1 |PNm}.]....!$'P@.| +000000b0 c5 bd c7 9f 95 d9 ba 2e 7b 0e db ea a7 31 81 05 |........{....1..| +000000c0 75 43 b1 63 cf b8 55 92 ef 76 98 a9 15 03 03 00 |uC.c..U..v......| +000000d0 16 d7 ea 3c 79 e7 a6 2f 61 39 ec 4e 95 86 48 5e |...>> Flow 1 (client to server) +00000000 16 03 01 00 5c 01 00 00 58 03 03 52 cc 57 59 68 |....\...X..R.WYh| +00000010 11 72 a6 ec 6b 0a 47 1d 10 06 ec 75 af 07 38 a0 |.r..k.G....u..8.| +00000020 30 9e 91 12 e1 9b 19 46 0d d4 45 00 00 04 00 0a |0......F..E.....| +00000030 00 ff 01 00 00 2b 00 0d 00 22 00 20 06 01 06 02 |.....+...". ....| +00000040 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................| +00000050 03 02 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 |................| +00000060 01 |.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 0a 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 04 0e 00 |n8P)l...........| +00000300 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 7a c0 73 ec cb |...........z.s..| +00000010 cf c2 a8 86 c0 7e 03 63 57 a1 ce 42 37 6d 78 54 |.....~.cW..B7mxT| +00000020 29 f5 3e cc 57 c7 0d d9 69 e1 52 5c 3b 6b c4 c7 |).>.W...i.R\;k..| +00000030 20 6d 59 ee c0 07 81 74 74 9f 62 41 64 f0 4d c8 | mY....tt.bAd.M.| +00000040 9b aa 1a b9 da 56 07 f5 6c 1c 59 8c d3 f9 08 d9 |.....V..l.Y.....| +00000050 08 f4 16 93 5d 9a e5 6f fb 9f ba 3d 3c d6 81 ad |....]..o...=<...| +00000060 02 12 a7 28 b6 81 6a 77 c3 e9 d7 c7 54 d6 77 83 |...(..jw....T.w.| +00000070 77 de 71 fb b3 f3 2d c4 a5 b1 e5 de aa 0e 21 bd |w.q...-.......!.| +00000080 91 a2 dc 7f f7 6f 90 82 54 b1 e7 14 03 03 00 01 |.....o..T.......| +00000090 01 16 03 03 00 30 8f ee bf fb c8 5c 54 f5 29 23 |.....0.....\T.)#| +000000a0 d4 55 f6 98 a1 6e d5 43 e7 81 b2 36 f2 98 d8 1b |.U...n.C...6....| +000000b0 0d 76 cb 14 ba 32 d7 36 30 e6 ab 42 80 95 f6 8a |.v...2.60..B....| +000000c0 60 64 a0 6b 90 81 |`d.k..| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 30 00 00 00 00 00 |..........0.....| +00000010 00 00 00 2c 21 52 34 63 ac e3 a3 66 45 00 41 0c |...,!R4c...fE.A.| +00000020 93 5d 6a 74 5a 25 dc 69 1d 76 73 0c f4 42 6a 18 |.]jtZ%.i.vs..Bj.| +00000030 5b 62 23 e7 fe 41 cf d4 9b 86 35 17 03 03 00 30 |[b#..A....5....0| +00000040 00 00 00 00 00 00 00 00 7d 5d ce 43 85 5c 6b 89 |........}].C.\k.| +00000050 c9 a5 0e 22 69 8e b9 4a 77 4c c0 4e cc 79 d9 7e |..."i..JwL.N.y.~| +00000060 a3 c8 d3 db 5c 53 f8 92 4d c4 5a 88 72 58 05 11 |....\S..M.Z.rX..| +00000070 15 03 03 00 20 00 00 00 00 00 00 00 00 1d 63 8b |.... .........c.| +00000080 a7 74 fb 76 1d 47 31 93 1f ec 8c e2 18 8e 21 dd |.t.v.G1.......!.| +00000090 87 97 9f 1c ca |.....| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES new file mode 100644 index 0000000000..a152a96a84 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES @@ -0,0 +1,87 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 5c 01 00 00 58 03 03 52 cc 57 59 d0 |....\...X..R.WY.| +00000010 38 05 36 7e e3 1e 93 2a 5a bf dc c2 f8 0a 03 6f |8.6~...*Z......o| +00000020 1a fc 21 74 e5 8b 2a c3 9e 2c 26 00 00 04 00 2f |..!t..*..,&..../| +00000030 00 ff 01 00 00 2b 00 0d 00 22 00 20 06 01 06 02 |.....+...". ....| +00000040 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................| +00000050 03 02 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 |................| +00000060 01 |.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2f 00 00 |............./..| +00000030 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 04 0e 00 |n8P)l...........| +00000300 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 4b b4 28 bc 78 |...........K.(.x| +00000010 41 34 f3 49 e8 74 07 74 42 ae 2e 55 9e 9a ce e5 |A4.I.t.tB..U....| +00000020 4a 1b e7 55 c7 64 c4 9c b3 dd 20 d6 f8 8e 67 b3 |J..U.d.... ...g.| +00000030 7a 5c 3b 34 e4 1a f6 bd 65 fc 21 cd 9a de 64 77 |z\;4....e.!...dw| +00000040 09 a5 92 e5 a4 f5 18 7b 23 5b 8b c1 95 23 97 6f |.......{#[...#.o| +00000050 76 55 04 34 22 7d 43 71 db cd eb f8 36 36 44 4b |vU.4"}Cq....66DK| +00000060 ae e3 cc ec 64 88 7b e1 ea d6 ab 49 35 94 a5 04 |....d.{....I5...| +00000070 1e 83 c5 cf 21 bb ca 33 5f d4 bf 1d d3 4d 07 59 |....!..3_....M.Y| +00000080 b4 39 b2 4b 7b 05 43 70 0d ba 7a 14 03 03 00 01 |.9.K{.Cp..z.....| +00000090 01 16 03 03 00 40 74 4b 7d b2 53 49 ea 86 90 c3 |.....@tK}.SI....| +000000a0 64 6b 64 31 1a 2a 3f 1a 37 1e 56 b8 dd 12 6d 56 |dkd1.*?.7.V...mV| +000000b0 2a 61 92 5b 39 e7 e1 be 71 70 4b 9b b3 f0 71 e7 |*a.[9...qpK...q.| +000000c0 47 2e 2e 17 c3 0a 66 9f 69 74 30 2d f0 a0 7f 84 |G.....f.it0-....| +000000d0 25 db c1 81 ee cf |%.....| +>>> 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 f3 4d 5a fc 21 |............MZ.!| +00000020 30 b5 a1 86 9d e2 ea 38 ac 54 57 fa 5a 54 97 b8 |0......8.TW.ZT..| +00000030 bb 4d 64 09 ef ce a1 75 0c 50 8d ff 5c c2 e9 47 |.Md....u.P..\..G| +00000040 95 93 53 c0 bd dc c5 9c e0 59 17 17 03 03 00 40 |..S......Y.....@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 69 c5 48 6e 45 cf 98 1b 2c 23 40 d1 ab a3 c2 e2 |i.HnE...,#@.....| +00000070 10 7b b1 c8 21 3c f0 eb 96 bd 4f 78 b2 4a 7b 18 |.{..!<....Ox.J{.| +00000080 4c b1 a6 67 bf 06 40 01 d0 8d 91 be 17 d8 0c 71 |L..g..@........q| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 20 84 80 3d 70 fe ae ee d7 2f e9 |..... ..=p..../.| +000000b0 bf 65 30 bf 0b dd 98 ea bb ba 12 14 98 53 7f d5 |.e0..........S..| +000000c0 56 ce 06 3c d0 |V..<.| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM new file mode 100644 index 0000000000..0ddfe022f2 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM @@ -0,0 +1,93 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 9c 01 00 00 98 03 03 53 04 f1 30 73 |...........S..0s| +00000010 a1 ea 8c d2 90 1c c6 d6 0d 3c af 58 21 65 90 25 |.........<.X!e.%| +00000020 5e fa f4 27 22 65 c9 68 90 b9 04 00 00 04 c0 2f |^..'"e.h......./| +00000030 00 ff 01 00 00 6b 00 0b 00 04 03 00 01 02 00 0a |.....k..........| +00000040 00 34 00 32 00 0e 00 0d 00 19 00 0b 00 0c 00 18 |.4.2............| +00000050 00 09 00 0a 00 16 00 17 00 08 00 06 00 07 00 14 |................| +00000060 00 15 00 04 00 05 00 12 00 13 00 01 00 02 00 03 |................| +00000070 00 0f 00 10 00 11 00 0d 00 22 00 20 06 01 06 02 |.........". ....| +00000080 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................| +00000090 03 02 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 |................| +000000a0 01 |.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 2f 00 00 |............./..| +00000030 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 cd 0c 00 |n8P)l...........| +00000300 00 c9 03 00 17 41 04 1e 18 37 ef 0d 19 51 88 35 |.....A...7...Q.5| +00000310 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 24 20 3e |uq..T[....g..$ >| +00000320 b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 07 9f 6c |.V...(^.+-O....l| +00000330 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 b5 68 1a |K[.V.2B.X..I..h.| +00000340 41 03 56 6b dc 5a 89 04 01 00 80 a2 54 61 84 29 |A.Vk.Z......Ta.)| +00000350 3e 97 4b 97 9a 9f 5c c0 49 6d 86 d2 79 8e 95 a1 |>.K...\.Im..y...| +00000360 0a 5a 36 73 34 bb 05 73 35 47 e1 2b 5d f3 ef 36 |.Z6s4..s5G.+]..6| +00000370 a8 32 e2 7e ef aa 3f 1f b3 64 60 d4 06 2e 98 e3 |.2.~..?..d`.....| +00000380 11 e2 60 3c d6 20 17 63 b2 6f a0 cd 21 01 2b 4e |..`<. .c.o..!.+N| +00000390 b2 a8 55 04 39 37 5c 6c 71 66 4d a3 eb 1b 83 67 |..U.97\lqfM....g| +000003a0 6b 15 a0 56 9a f1 a2 79 92 29 ce 58 3c 10 4d 65 |k..V...y.).X<.Me| +000003b0 1f 22 e3 ea d8 74 aa 01 7e ca f3 89 23 41 4d bd |."...t..~...#AM.| +000003c0 df 77 4e 59 54 97 74 ad 07 ea c0 16 03 03 00 04 |.wNYT.t.........| +000003d0 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 03 00 46 10 00 00 42 41 04 45 65 ce f7 b9 |....F...BA.Ee...| +00000010 52 e3 fb 13 db 91 f2 65 43 84 57 f5 1a 19 a0 e6 |R......eC.W.....| +00000020 89 2d bb 2c 83 6b 62 f6 6f 1f 26 ae 59 67 bd dc |.-.,.kb.o.&.Yg..| +00000030 c4 9e 0b dc 7d 6e f8 6b 95 8c 61 47 3d cd d1 df |....}n.k..aG=...| +00000040 82 45 30 81 c3 a3 49 5d 85 59 70 14 03 03 00 01 |.E0...I].Yp.....| +00000050 01 16 03 03 00 28 3f aa 85 33 f9 c6 95 a0 56 ff |.....(?..3....V.| +00000060 1c f1 5a ba 6e 41 50 0c ab 92 e1 e2 8e 89 1c f1 |..Z.nAP.........| +00000070 fa 54 1b f1 f5 00 01 12 6d c4 96 78 b6 87 |.T......m..x..| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 |..........(.....| +00000010 00 00 00 94 5c be 46 05 d6 d0 b0 3a 56 dc 2c 10 |....\.F....:V.,.| +00000020 0f 6f 5d 33 33 7f a5 4e 74 84 bf 63 87 c4 f4 49 |.o]33..Nt..c...I| +00000030 bc 6b ab 17 03 03 00 25 00 00 00 00 00 00 00 01 |.k.....%........| +00000040 7e 4f f9 ae ae fe 6b a0 4a f8 0f 0b b4 b6 65 b6 |~O....k.J.....e.| +00000050 be 24 5f 94 6d d1 db 54 11 07 b9 ce 01 15 03 03 |.$_.m..T........| +00000060 00 1a 00 00 00 00 00 00 00 02 a8 1c d6 62 ac fd |.............b..| +00000070 77 ba 23 92 5d 34 f1 17 c7 e1 1c 99 |w.#.]4......| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4 b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4 new file mode 100644 index 0000000000..b703a8f766 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4 @@ -0,0 +1,79 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 5c 01 00 00 58 03 03 52 cc 57 59 c9 |....\...X..R.WY.| +00000010 c3 13 fc 18 8a ee c2 0e 88 ff fb 4a 16 f2 eb eb |...........J....| +00000020 d4 f8 b3 5b cd bb 25 0e 0b cb 48 00 00 04 00 05 |...[..%...H.....| +00000030 00 ff 01 00 00 2b 00 0d 00 22 00 20 06 01 06 02 |.....+...". ....| +00000040 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................| +00000050 03 02 03 03 02 01 02 02 02 03 01 01 00 0f 00 01 |................| +00000060 01 |.| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 04 0e 00 |n8P)l...........| +00000300 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 35 b3 60 ba 14 |...........5.`..| +00000010 5f 19 24 a0 24 de 4e 85 a9 64 78 3a 51 24 64 70 |_.$.$.N..dx:Q$dp| +00000020 88 55 6d c3 11 b8 d3 9f bc 7a 33 f8 3c 48 93 2f |.Um......z3..|.| +00000070 44 82 f4 24 03 22 40 00 64 27 53 15 41 8c 01 e9 |D..$."@.d'S.A...| +00000080 39 32 fa 8e 2d f9 b4 89 34 15 d6 14 03 03 00 01 |92..-...4.......| +00000090 01 16 03 03 00 24 f5 61 8b 24 bf b4 82 3a cf 49 |.....$.a.$...:.I| +000000a0 99 a0 b1 1b a7 a7 a3 92 7c 84 85 e0 64 a3 3d bd |........|...d.=.| +000000b0 38 98 7d 97 a8 b9 2a 35 a9 09 |8.}...*5..| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 24 c9 0b 84 e6 39 |..........$....9| +00000010 f2 e0 f3 ac 9f 0f 17 92 5f 6d de 94 18 c4 60 d9 |........_m....`.| +00000020 66 c3 0d 1a ae c2 8f 46 8f 7f f0 58 0e 4a 9b 17 |f......F...X.J..| +00000030 03 03 00 21 8b 73 a1 6a 7e d9 7e 4f 1d cc b2 7d |...!.s.j~.~O...}| +00000040 3c 83 3f 52 f8 08 77 01 4c 65 11 6d 50 25 9a cc |<.?R..w.Le.mP%..| +00000050 e3 54 27 72 59 15 03 03 00 16 3d c8 ab 14 51 fa |.T'rY.....=...Q.| +00000060 97 f1 ef 5f b4 4f 44 58 d4 93 3b ae e5 61 1f a3 |..._.ODX..;..a..| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-Resume b/libgo/go/crypto/tls/testdata/Server-TLSv12-Resume new file mode 100644 index 0000000000..c495d4adc6 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-Resume @@ -0,0 +1,36 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 e8 01 00 00 e4 03 03 52 cc 57 59 c3 |...........R.WY.| +00000010 8b df 97 05 d8 5f 16 22 b4 b1 e7 cb 7d 2f 9b 58 |....._."....}/.X| +00000020 a3 f4 d7 2c a4 c1 9d 49 ed 4b ba 20 90 da 90 3e |...,...I.K. ...>| +00000030 36 19 7a db 56 43 26 f7 dc 42 57 33 22 ed 9d a4 |6.z.VC&..BW3"...| +00000040 9d 53 da f8 9d 4e 60 66 71 a0 2e 2e 00 04 00 05 |.S...N`fq.......| +00000050 00 ff 01 00 00 97 00 23 00 68 00 00 00 00 00 00 |.......#.h......| +00000060 00 00 00 00 00 00 00 00 00 00 65 ea 4b d1 ef ba |..........e.K...| +00000070 06 38 1e e1 88 82 3a cd 03 ac 3b 39 0a e0 19 fd |.8....:...;9....| +00000080 af 6c 57 30 df 31 6e f7 92 38 4b 5d 77 90 39 ff |.lW0.1n..8K]w.9.| +00000090 32 51 f5 ed 12 d7 b0 7c 4d 6c c5 76 e4 72 48 3e |2Q.....|Ml.v.rH>| +000000a0 59 23 fe 0d 15 df f4 ba ea b9 67 16 23 8f 7d 15 |Y#........g.#.}.| +000000b0 b6 11 f1 ab d7 d4 cd a3 21 82 92 2a 12 cf 95 f3 |........!..*....| +000000c0 60 b2 00 0d 00 22 00 20 06 01 06 02 06 03 05 01 |`....". ........| +000000d0 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................| +000000e0 02 01 02 02 02 03 01 01 00 0f 00 01 01 |.............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 51 02 00 00 4d 03 03 00 00 00 00 00 |....Q...M.......| +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 90 da 90 3e |........... ...>| +00000030 36 19 7a db 56 43 26 f7 dc 42 57 33 22 ed 9d a4 |6.z.VC&..BW3"...| +00000040 9d 53 da f8 9d 4e 60 66 71 a0 2e 2e 00 05 00 00 |.S...N`fq.......| +00000050 05 ff 01 00 01 00 14 03 03 00 01 01 16 03 03 00 |................| +00000060 24 11 12 ff 28 10 14 4c e5 0e ad a7 fa f3 92 fb |$...(..L........| +00000070 13 7d ae f2 b2 4a 6b a1 9e 67 cf a8 f7 8c 6f a0 |.}...Jk..g....o.| +00000080 6c 30 0e 18 55 |l0..U| +>>> Flow 3 (client to server) +00000000 14 03 03 00 01 01 16 03 03 00 24 0d 46 41 8b 24 |..........$.FA.$| +00000010 36 01 a9 fd 8b ec fc e6 b1 83 96 df 0d 3e 53 54 |6............>ST| +00000020 58 b8 43 f2 a6 25 5e 1a ae 19 9e d2 28 44 92 |X.C..%^.....(D.| +>>> Flow 4 (server to client) +00000000 17 03 03 00 21 c4 fb f6 53 bb 3e 04 cc 0b a0 03 |....!...S.>.....| +00000010 fa 49 96 da b5 8d b2 f2 e5 d8 f3 5c 27 57 4f 9c |.I.........\'WO.| +00000020 30 00 34 fc 52 92 15 03 03 00 16 a3 02 7a 50 d2 |0.4.R........zP.| +00000030 c6 b3 fc 69 8f e4 94 ae ab 22 ad 05 1d 15 69 b9 |...i....."....i.| +00000040 a5 |.| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ResumeDisabled b/libgo/go/crypto/tls/testdata/Server-TLSv12-ResumeDisabled new file mode 100644 index 0000000000..db833f6555 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ResumeDisabled @@ -0,0 +1,87 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 e8 01 00 00 e4 03 03 54 23 54 02 a5 |...........T#T..| +00000010 10 11 0f 6d e5 2d 2f e8 bb 52 b1 38 3f 65 01 43 |...m.-/..R.8?e.C| +00000020 36 cc 48 f6 09 22 a1 85 20 28 3c 20 35 8b fe 7a |6.H..".. (< 5..z| +00000030 41 3b 59 3a 5d b9 b3 21 f0 62 e9 0d 7b af f5 5d |A;Y:]..!.b..{..]| +00000040 fa 65 1a 40 c8 ca cd 74 8c ef d2 fb 00 04 00 05 |.e.@...t........| +00000050 00 ff 01 00 00 97 00 23 00 68 00 00 00 00 00 00 |.......#.h......| +00000060 00 00 00 00 00 00 00 00 00 00 65 ea 4b d1 ef ba |..........e.K...| +00000070 2d db 0c ba 9a d4 20 76 57 c8 ec dc 2d 77 fb fb |-..... vW...-w..| +00000080 3b 93 5f 53 e0 14 4f 90 fb d6 55 57 8c 8d 0d 25 |;._S..O...UW...%| +00000090 ea 5d 0d f2 91 e5 12 22 12 ec 7b 5f b6 6e fd 07 |.]....."..{_.n..| +000000a0 59 23 24 fc b1 97 ca ea 56 a5 c2 a0 e4 9e 99 64 |Y#$.....V......d| +000000b0 f2 64 d0 75 7a 46 63 e3 dc 21 ed 78 56 e9 e1 ab |.d.uzFc..!.xV...| +000000c0 66 80 00 0d 00 22 00 20 06 01 06 02 06 03 05 01 |f....". ........| +000000d0 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................| +000000e0 02 01 02 02 02 03 01 01 00 0f 00 01 01 |.............| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 05 00 00 |................| +00000030 05 ff 01 00 01 00 16 03 03 02 be 0b 00 02 ba 00 |................| +00000040 02 b7 00 02 b4 30 82 02 b0 30 82 02 19 a0 03 02 |.....0...0......| +00000050 01 02 02 09 00 85 b0 bb a4 8a 7f b8 ca 30 0d 06 |.............0..| +00000060 09 2a 86 48 86 f7 0d 01 01 05 05 00 30 45 31 0b |.*.H........0E1.| +00000070 30 09 06 03 55 04 06 13 02 41 55 31 13 30 11 06 |0...U....AU1.0..| +00000080 03 55 04 08 13 0a 53 6f 6d 65 2d 53 74 61 74 65 |.U....Some-State| +00000090 31 21 30 1f 06 03 55 04 0a 13 18 49 6e 74 65 72 |1!0...U....Inter| +000000a0 6e 65 74 20 57 69 64 67 69 74 73 20 50 74 79 20 |net Widgits Pty | +000000b0 4c 74 64 30 1e 17 0d 31 30 30 34 32 34 30 39 30 |Ltd0...100424090| +000000c0 39 33 38 5a 17 0d 31 31 30 34 32 34 30 39 30 39 |938Z..1104240909| +000000d0 33 38 5a 30 45 31 0b 30 09 06 03 55 04 06 13 02 |38Z0E1.0...U....| +000000e0 41 55 31 13 30 11 06 03 55 04 08 13 0a 53 6f 6d |AU1.0...U....Som| +000000f0 65 2d 53 74 61 74 65 31 21 30 1f 06 03 55 04 0a |e-State1!0...U..| +00000100 13 18 49 6e 74 65 72 6e 65 74 20 57 69 64 67 69 |..Internet Widgi| +00000110 74 73 20 50 74 79 20 4c 74 64 30 81 9f 30 0d 06 |ts Pty Ltd0..0..| +00000120 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............| +00000130 30 81 89 02 81 81 00 bb 79 d6 f5 17 b5 e5 bf 46 |0.......y......F| +00000140 10 d0 dc 69 be e6 2b 07 43 5a d0 03 2d 8a 7a 43 |...i..+.CZ..-.zC| +00000150 85 b7 14 52 e7 a5 65 4c 2c 78 b8 23 8c b5 b4 82 |...R..eL,x.#....| +00000160 e5 de 1f 95 3b 7e 62 a5 2c a5 33 d6 fe 12 5c 7a |....;~b.,.3...\z| +00000170 56 fc f5 06 bf fa 58 7b 26 3f b5 cd 04 d3 d0 c9 |V.....X{&?......| +00000180 21 96 4a c7 f4 54 9f 5a bf ef 42 71 00 fe 18 99 |!.J..T.Z..Bq....| +00000190 07 7f 7e 88 7d 7d f1 04 39 c4 a2 2e db 51 c9 7c |..~.}}..9....Q.|| +000001a0 e3 c0 4c 3b 32 66 01 cf af b1 1d b8 71 9a 1d db |..L;2f......q...| +000001b0 db 89 6b ae da 2d 79 02 03 01 00 01 a3 81 a7 30 |..k..-y........0| +000001c0 81 a4 30 1d 06 03 55 1d 0e 04 16 04 14 b1 ad e2 |..0...U.........| +000001d0 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 88 |.Z..(.i.#i..&...| +000001e0 39 30 75 06 03 55 1d 23 04 6e 30 6c 80 14 b1 ad |90u..U.#.n0l....| +000001f0 e2 85 5a cf cb 28 db 69 ce 23 69 de d3 26 8e 18 |..Z..(.i.#i..&..| +00000200 88 39 a1 49 a4 47 30 45 31 0b 30 09 06 03 55 04 |.9.I.G0E1.0...U.| +00000210 06 13 02 41 55 31 13 30 11 06 03 55 04 08 13 0a |...AU1.0...U....| +00000220 53 6f 6d 65 2d 53 74 61 74 65 31 21 30 1f 06 03 |Some-State1!0...| +00000230 55 04 0a 13 18 49 6e 74 65 72 6e 65 74 20 57 69 |U....Internet Wi| +00000240 64 67 69 74 73 20 50 74 79 20 4c 74 64 82 09 00 |dgits Pty Ltd...| +00000250 85 b0 bb a4 8a 7f b8 ca 30 0c 06 03 55 1d 13 04 |........0...U...| +00000260 05 30 03 01 01 ff 30 0d 06 09 2a 86 48 86 f7 0d |.0....0...*.H...| +00000270 01 01 05 05 00 03 81 81 00 08 6c 45 24 c7 6b b1 |..........lE$.k.| +00000280 59 ab 0c 52 cc f2 b0 14 d7 87 9d 7a 64 75 b5 5a |Y..R.......zdu.Z| +00000290 95 66 e4 c5 2b 8e ae 12 66 1f eb 4f 38 b3 6e 60 |.f..+...f..O8.n`| +000002a0 d3 92 fd f7 41 08 b5 25 13 b1 18 7a 24 fb 30 1d |....A..%...z$.0.| +000002b0 ba ed 98 b9 17 ec e7 d7 31 59 db 95 d3 1d 78 ea |........1Y....x.| +000002c0 50 56 5c d5 82 5a 2d 5a 5f 33 c4 b6 d8 c9 75 90 |PV\..Z-Z_3....u.| +000002d0 96 8c 0f 52 98 b5 cd 98 1f 89 20 5f f2 a0 1c a3 |...R...... _....| +000002e0 1b 96 94 dd a9 fd 57 e9 70 e8 26 6d 71 99 9b 26 |......W.p.&mq..&| +000002f0 6e 38 50 29 6c 90 a7 bd d9 16 03 03 00 04 0e 00 |n8P)l...........| +00000300 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 ae 02 dd 1f 1a |................| +00000010 86 83 f5 2f 82 46 4b 29 58 aa a1 b3 56 8b 4e 40 |.../.FK)X...V.N@| +00000020 ef 23 65 67 ad 48 e5 e1 fd ae dd bf 68 fd bd a6 |.#eg.H......h...| +00000030 13 a0 7e 05 ab f7 20 e1 6a 4e d1 37 93 08 1d c9 |..~... .jN.7....| +00000040 37 e0 b5 34 28 bf 20 45 45 da 0f 7e 51 a7 c6 ae |7..4(. EE..~Q...| +00000050 61 6c 07 1b 73 ef da 6e 25 c4 ed be e3 3f da ae |al..s..n%....?..| +00000060 cd 3c 17 9c 2e ee fb 47 9d b3 a1 b2 c3 5d e0 83 |.<.....G.....]..| +00000070 74 20 37 2d 72 d6 d0 4d 58 0e 26 1c 50 22 95 08 |t 7-r..MX.&.P"..| +00000080 7d e0 5f 86 99 9e 2c 2e a7 a0 7f 14 03 03 00 01 |}._...,.........| +00000090 01 16 03 03 00 24 a2 ab 41 25 a5 cf 04 18 1d 98 |.....$..A%......| +000000a0 88 6c 59 21 86 33 54 f4 35 b4 21 6e a5 29 d5 6e |.lY!.3T.5.!n.).n| +000000b0 3d 08 72 b0 af 46 b5 8f 6b 86 |=.r..F..k.| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 24 59 20 4d c2 17 |..........$Y M..| +00000010 8b 3c 9b 33 d9 f9 ef fb 80 18 1f 67 a7 58 12 89 |.<.3.......g.X..| +00000020 4e 73 0f 2d 7b e6 c4 a6 79 73 01 da 22 e8 54 17 |Ns.-{...ys..".T.| +00000030 03 03 00 21 36 ca 64 0f 4a 12 a5 50 3d 97 bb 39 |...!6.d.J..P=..9| +00000040 02 fc ed d1 82 6a 9a 2e 21 79 f6 e1 b3 cc 32 db |.....j..!y....2.| +00000050 0f 5d b3 fb a5 15 03 03 00 16 51 f4 be 57 7a df |.]........Q..Wz.| +00000060 f1 f2 bd b5 51 5e 45 80 be 0b 9a 0c d1 19 3c 79 |....Q^E.......>> Flow 1 (client to server) +00000000 16 03 01 00 70 01 00 00 6c 03 03 52 cc 57 59 2d |....p...l..R.WY-| +00000010 77 aa 75 35 fa ff 2a a2 bf 91 5e e3 7f 38 7d 7a |w.u5..*...^..8}z| +00000020 e3 93 d3 e8 8b 09 bb 06 c8 6d 91 00 00 04 00 2f |.........m...../| +00000030 00 ff 01 00 00 3f 00 00 00 10 00 0e 00 00 0b 73 |.....?.........s| +00000040 6e 69 74 65 73 74 2e 63 6f 6d 00 0d 00 22 00 20 |nitest.com...". | +00000050 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 02 |................| +00000060 04 03 03 01 03 02 03 03 02 01 02 02 02 03 01 01 |................| +00000070 00 0f 00 01 01 |.....| +>>> Flow 2 (server to client) +00000000 16 03 03 00 31 02 00 00 2d 03 03 00 00 00 00 00 |....1...-.......| +00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2f 00 00 |............./..| +00000030 05 ff 01 00 01 00 16 03 03 02 00 0b 00 01 fc 00 |................| +00000040 01 f9 00 01 f6 30 82 01 f2 30 82 01 5d a0 03 02 |.....0...0..]...| +00000050 01 02 02 01 00 30 0b 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....| +00000060 01 05 30 28 31 10 30 0e 06 03 55 04 0a 13 07 41 |..0(1.0...U....A| +00000070 63 6d 65 20 43 6f 31 14 30 12 06 03 55 04 03 13 |cme Co1.0...U...| +00000080 0b 73 6e 69 74 65 73 74 2e 63 6f 6d 30 1e 17 0d |.snitest.com0...| +00000090 31 32 30 34 31 31 31 37 34 30 33 35 5a 17 0d 31 |120411174035Z..1| +000000a0 33 30 34 31 31 31 37 34 35 33 35 5a 30 28 31 10 |30411174535Z0(1.| +000000b0 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 6f |0...U....Acme Co| +000000c0 31 14 30 12 06 03 55 04 03 13 0b 73 6e 69 74 65 |1.0...U....snite| +000000d0 73 74 2e 63 6f 6d 30 81 9d 30 0b 06 09 2a 86 48 |st.com0..0...*.H| +000000e0 86 f7 0d 01 01 01 03 81 8d 00 30 81 89 02 81 81 |..........0.....| +000000f0 00 bb 79 d6 f5 17 b5 e5 bf 46 10 d0 dc 69 be e6 |..y......F...i..| +00000100 2b 07 43 5a d0 03 2d 8a 7a 43 85 b7 14 52 e7 a5 |+.CZ..-.zC...R..| +00000110 65 4c 2c 78 b8 23 8c b5 b4 82 e5 de 1f 95 3b 7e |eL,x.#........;~| +00000120 62 a5 2c a5 33 d6 fe 12 5c 7a 56 fc f5 06 bf fa |b.,.3...\zV.....| +00000130 58 7b 26 3f b5 cd 04 d3 d0 c9 21 96 4a c7 f4 54 |X{&?......!.J..T| +00000140 9f 5a bf ef 42 71 00 fe 18 99 07 7f 7e 88 7d 7d |.Z..Bq......~.}}| +00000150 f1 04 39 c4 a2 2e db 51 c9 7c e3 c0 4c 3b 32 66 |..9....Q.|..L;2f| +00000160 01 cf af b1 1d b8 71 9a 1d db db 89 6b ae da 2d |......q.....k..-| +00000170 79 02 03 01 00 01 a3 32 30 30 30 0e 06 03 55 1d |y......2000...U.| +00000180 0f 01 01 ff 04 04 03 02 00 a0 30 0d 06 03 55 1d |..........0...U.| +00000190 0e 04 06 04 04 01 02 03 04 30 0f 06 03 55 1d 23 |.........0...U.#| +000001a0 04 08 30 06 80 04 01 02 03 04 30 0b 06 09 2a 86 |..0.......0...*.| +000001b0 48 86 f7 0d 01 01 05 03 81 81 00 89 c6 45 5f 1c |H............E_.| +000001c0 1f 5e f8 eb 1a b1 74 ee 24 39 05 9f 5c 42 59 bb |.^....t.$9..\BY.| +000001d0 1a 8d 86 cd b1 d0 56 f5 6a 71 7d a4 0e 95 ab 90 |......V.jq}.....| +000001e0 f5 9e 8d ea f6 27 c1 57 99 50 94 db 08 02 26 6e |.....'.W.P....&n| +000001f0 b3 4f c6 84 2d ea 8a 4b 68 d9 c1 38 91 03 ab 84 |.O..-..Kh..8....| +00000200 fb 9e 1f 85 d9 b5 d2 3f f2 31 2c 86 70 fb b5 40 |.......?.1,.p..@| +00000210 14 82 45 a4 eb af e2 64 d9 0c 8a 4c f4 f8 5b 0f |..E....d...L..[.| +00000220 ac 12 ac 2f c4 a3 15 4b ad 52 46 28 68 af 96 c6 |.../...K.RF(h...| +00000230 2c 65 25 d6 52 b6 e3 18 45 bd cc 16 03 03 00 04 |,e%.R...E.......| +00000240 0e 00 00 00 |....| +>>> Flow 3 (client to server) +00000000 16 03 03 00 86 10 00 00 82 00 80 0d f2 bf 75 a9 |..............u.| +00000010 aa db f3 25 55 d4 20 59 63 54 d1 70 82 f9 61 c5 |...%U. YcT.p..a.| +00000020 b7 ae 3f 75 71 75 9d c5 01 a1 ed b1 07 66 9f 3f |..?uqu.......f.?| +00000030 cf c6 e6 ad 44 03 fd 18 6f 53 24 ce 76 01 bd fe |....D...oS$.v...| +00000040 e2 51 f7 df 8a 23 3a 21 c4 00 15 ff d0 e0 ff c8 |.Q...#:!........| +00000050 8b 89 33 c6 8e e0 ce 97 ef b4 c6 f9 b0 ea 38 89 |..3...........8.| +00000060 79 98 34 9e f7 bc c6 fd d2 5d 56 84 5c d2 9a ce |y.4......]V.\...| +00000070 ae de 09 bc 24 25 fc 09 0c bc 0e 91 0d 6b 36 ae |....$%.......k6.| +00000080 ce 6b cd 14 ec b6 3c fa d6 df fc 14 03 03 00 01 |.k....<.........| +00000090 01 16 03 03 00 40 ad 21 13 2b 33 7a 4a 0d fb 0f |.....@.!.+3zJ...| +000000a0 eb d2 b6 85 29 1f 59 79 ba 86 53 5c 68 b4 c7 e3 |....).Yy..S\h...| +000000b0 8a 6c 5c 18 04 4d e4 76 19 30 ba 92 b4 79 8c 64 |.l\..M.v.0...y.d| +000000c0 00 a0 2e 13 96 45 9f e7 a9 e4 23 9e 9f 89 23 26 |.....E....#...#&| +000000d0 36 20 82 fc 75 fe |6 ..u.| +>>> 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 b7 87 61 10 03 |.............a..| +00000020 b8 a4 42 d4 8b 49 bc 40 80 70 92 c8 25 b0 c6 7f |..B..I.@.p..%...| +00000030 b3 87 76 50 5a 59 b3 3c d8 3e 23 24 aa 1a f3 36 |..vPZY.<.>#$...6| +00000040 c9 2c 87 c1 22 d2 94 f8 2c fd ef 17 03 03 00 40 |.,.."...,......@| +00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| +00000060 e5 7f bd 3e ff 9f d4 1b 91 02 f8 69 6f 70 9d 51 |...>.......iop.Q| +00000070 a5 ec ef 5b 10 3f 4e 3f 44 e5 9a 39 68 7c 3a b9 |...[.?N?D..9h|:.| +00000080 69 38 31 ec 9c 45 bf 19 d1 5c 5e 2e 06 00 ca 19 |i81..E...\^.....| +00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........| +000000a0 00 00 00 00 00 63 5e 79 2c f2 05 dc 2b d7 5b ac |.....c^y,...+.[.| +000000b0 9d fc 75 94 03 16 ca 1f b2 75 58 2d f1 2f f1 1e |..u......uX-./..| +000000c0 d2 f6 84 8f 2e |.....| diff --git a/libgo/go/crypto/tls/ticket.go b/libgo/go/crypto/tls/ticket.go index 4cfc5a53ff..0923027c70 100644 --- a/libgo/go/crypto/tls/ticket.go +++ b/libgo/go/crypto/tls/ticket.go @@ -153,7 +153,8 @@ func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) { } func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) { - if len(encrypted) < aes.BlockSize+sha256.Size { + if c.config.SessionTicketsDisabled || + len(encrypted) < aes.BlockSize+sha256.Size { return nil, false } diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go index 6c67506fc3..d50e120292 100644 --- a/libgo/go/crypto/tls/tls.go +++ b/libgo/go/crypto/tls/tls.go @@ -15,6 +15,7 @@ import ( "io/ioutil" "net" "strings" + "time" ) // Server returns a new TLS server side connection @@ -27,9 +28,8 @@ func Server(conn net.Conn, config *Config) *Conn { // Client returns a new TLS client side connection // using conn as the underlying transport. -// Client interprets a nil configuration as equivalent to -// the zero configuration; see the documentation of Config -// for the defaults. +// The config cannot be nil: users must set either ServerName or +// InsecureSkipVerify in the config. func Client(conn net.Conn, config *Config) *Conn { return &Conn{conn: conn, config: config, isClient: true} } @@ -77,24 +77,51 @@ func Listen(network, laddr string, config *Config) (net.Listener, error) { return NewListener(l, config), nil } -// Dial connects to the given network address using net.Dial -// and then initiates a TLS handshake, returning the resulting -// TLS connection. -// Dial interprets a nil configuration as equivalent to -// the zero configuration; see the documentation of Config -// for the defaults. -func Dial(network, addr string, config *Config) (*Conn, error) { - raddr := addr - c, err := net.Dial(network, raddr) +type timeoutError struct{} + +func (timeoutError) Error() string { return "tls: DialWithDialer timed out" } +func (timeoutError) Timeout() bool { return true } +func (timeoutError) Temporary() bool { return true } + +// DialWithDialer connects to the given network address using dialer.Dial and +// then initiates a TLS handshake, returning the resulting TLS connection. Any +// timeout or deadline given in the dialer apply to connection and TLS +// handshake as a whole. +// +// DialWithDialer interprets a nil configuration as equivalent to the zero +// configuration; see the documentation of Config for the defaults. +func DialWithDialer(dialer *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 := dialer.Timeout + + if !dialer.Deadline.IsZero() { + deadlineTimeout := dialer.Deadline.Sub(time.Now()) + if timeout == 0 || deadlineTimeout < timeout { + timeout = deadlineTimeout + } + } + + var errChannel chan error + + if timeout != 0 { + errChannel = make(chan error, 2) + time.AfterFunc(timeout, func() { + errChannel <- timeoutError{} + }) + } + + rawConn, err := dialer.Dial(network, addr) if err != nil { return nil, err } - colonPos := strings.LastIndex(raddr, ":") + colonPos := strings.LastIndex(addr, ":") if colonPos == -1 { - colonPos = len(raddr) + colonPos = len(addr) } - hostname := raddr[:colonPos] + hostname := addr[:colonPos] if config == nil { config = defaultConfig() @@ -107,14 +134,37 @@ func Dial(network, addr string, config *Config) (*Conn, error) { c.ServerName = hostname config = &c } - conn := Client(c, config) - if err = conn.Handshake(); err != nil { - c.Close() + + conn := Client(rawConn, config) + + if timeout == 0 { + err = conn.Handshake() + } else { + go func() { + errChannel <- conn.Handshake() + }() + + err = <-errChannel + } + + if err != nil { + rawConn.Close() return nil, err } + return conn, nil } +// Dial connects to the given network address using net.Dial +// and then initiates a TLS handshake, returning the resulting +// TLS connection. +// Dial interprets a nil configuration as equivalent to +// the zero configuration; see the documentation of Config +// for the defaults. +func Dial(network, addr string, config *Config) (*Conn, error) { + return DialWithDialer(new(net.Dialer), network, addr, config) +} + // LoadX509KeyPair reads and parses a public/private key pair from a pair of // files. The files must contain PEM encoded data. func LoadX509KeyPair(certFile, keyFile string) (cert Certificate, err error) { diff --git a/libgo/go/crypto/tls/tls_test.go b/libgo/go/crypto/tls/tls_test.go index 38229014cd..e82579eee9 100644 --- a/libgo/go/crypto/tls/tls_test.go +++ b/libgo/go/crypto/tls/tls_test.go @@ -5,7 +5,13 @@ package tls import ( + "bytes" + "fmt" + "io" + "net" + "strings" "testing" + "time" ) var rsaCertPEM = `-----BEGIN CERTIFICATE----- @@ -105,3 +111,172 @@ func TestX509MixedKeyPair(t *testing.T) { t.Error("Load of ECDSA certificate succeeded with RSA private key") } } + +func newLocalListener(t *testing.T) net.Listener { + ln, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + ln, err = net.Listen("tcp6", "[::1]:0") + } + if err != nil { + t.Fatal(err) + } + return ln +} + +func TestDialTimeout(t *testing.T) { + if testing.Short() { + t.Skip("skipping in short mode") + } + listener := newLocalListener(t) + + addr := listener.Addr().String() + defer listener.Close() + + complete := make(chan bool) + defer close(complete) + + go func() { + conn, err := listener.Accept() + if err != nil { + t.Error(err) + return + } + <-complete + conn.Close() + }() + + dialer := &net.Dialer{ + Timeout: 10 * time.Millisecond, + } + + var err error + if _, err = DialWithDialer(dialer, "tcp", addr, nil); err == nil { + t.Fatal("DialWithTimeout completed successfully") + } + + if !strings.Contains(err.Error(), "timed out") { + t.Errorf("resulting error not a timeout: %s", err) + } +} + +// tests that Conn.Read returns (non-zero, io.EOF) instead of +// (non-zero, nil) when a Close (alertCloseNotify) is sitting right +// behind the application data in the buffer. +func TestConnReadNonzeroAndEOF(t *testing.T) { + // This test is racy: it assumes that after a write to a + // localhost TCP connection, the peer TCP connection can + // immediately read it. Because it's racy, we skip this test + // in short mode, and then retry it several times with an + // increasing sleep in between our final write (via srv.Close + // below) and the following read. + if testing.Short() { + t.Skip("skipping in short mode") + } + var err error + for delay := time.Millisecond; delay <= 64*time.Millisecond; delay *= 2 { + if err = testConnReadNonzeroAndEOF(t, delay); err == nil { + return + } + } + t.Error(err) +} + +func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error { + ln := newLocalListener(t) + defer ln.Close() + + srvCh := make(chan *Conn, 1) + var serr error + go func() { + sconn, err := ln.Accept() + if err != nil { + serr = err + srvCh <- nil + return + } + serverConfig := *testConfig + srv := Server(sconn, &serverConfig) + if err := srv.Handshake(); err != nil { + serr = fmt.Errorf("handshake: %v", err) + srvCh <- nil + return + } + srvCh <- srv + }() + + clientConfig := *testConfig + conn, err := Dial("tcp", ln.Addr().String(), &clientConfig) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + + srv := <-srvCh + if srv == nil { + return serr + } + + buf := make([]byte, 6) + + srv.Write([]byte("foobar")) + n, err := conn.Read(buf) + if n != 6 || err != nil || string(buf) != "foobar" { + return fmt.Errorf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf) + } + + srv.Write([]byte("abcdef")) + srv.Close() + time.Sleep(delay) + n, err = conn.Read(buf) + if n != 6 || string(buf) != "abcdef" { + return fmt.Errorf("Read = %d, buf= %q; want 6, abcdef", n, buf) + } + if err != io.EOF { + return fmt.Errorf("Second Read error = %v; want io.EOF", err) + } + return nil +} + +func TestTLSUniqueMatches(t *testing.T) { + ln := newLocalListener(t) + defer ln.Close() + + serverTLSUniques := make(chan []byte) + go func() { + for i := 0; i < 2; i++ { + sconn, err := ln.Accept() + if err != nil { + t.Fatal(err) + } + serverConfig := *testConfig + srv := Server(sconn, &serverConfig) + if err := srv.Handshake(); err != nil { + t.Fatal(err) + } + serverTLSUniques <- srv.ConnectionState().TLSUnique + } + }() + + clientConfig := *testConfig + clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) + conn, err := Dial("tcp", ln.Addr().String(), &clientConfig) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(conn.ConnectionState().TLSUnique, <-serverTLSUniques) { + t.Error("client and server channel bindings differ") + } + conn.Close() + + conn, err = Dial("tcp", ln.Addr().String(), &clientConfig) + if err != nil { + t.Fatal(err) + } + defer conn.Close() + if !conn.ConnectionState().DidResume { + t.Error("second session did not use resumption") + } + if !bytes.Equal(conn.ConnectionState().TLSUnique, <-serverTLSUniques) { + t.Error("client and server channel bindings differ when session resumption is used") + } +} diff --git a/libgo/go/crypto/x509/pem_decrypt_test.go b/libgo/go/crypto/x509/pem_decrypt_test.go index 59ba6f9001..13e4700bdd 100644 --- a/libgo/go/crypto/x509/pem_decrypt_test.go +++ b/libgo/go/crypto/x509/pem_decrypt_test.go @@ -14,7 +14,7 @@ import ( func TestDecrypt(t *testing.T) { for i, data := range testData { - t.Logf("test %d. %s", i, data.kind) + t.Logf("test %v. %v", i, data.kind) block, rest := pem.Decode(data.pemData) if len(rest) > 0 { t.Error("extra data") @@ -39,7 +39,7 @@ func TestDecrypt(t *testing.T) { func TestEncrypt(t *testing.T) { for i, data := range testData { - t.Logf("test %d. %s", i, data.kind) + t.Logf("test %v. %v", i, data.kind) plainDER, err := base64.StdEncoding.DecodeString(data.plainDER) if err != nil { t.Fatal("cannot decode test DER data: ", err) diff --git a/libgo/go/crypto/x509/pkix/pkix.go b/libgo/go/crypto/x509/pkix/pkix.go index 5034946f71..8768b78590 100644 --- a/libgo/go/crypto/x509/pkix/pkix.go +++ b/libgo/go/crypto/x509/pkix/pkix.go @@ -30,6 +30,13 @@ type AttributeTypeAndValue struct { Value interface{} } +// AttributeTypeAndValueSET represents a set of ASN.1 sequences of +// AttributeTypeAndValue sequences from RFC 2986 (PKCS #10). +type AttributeTypeAndValueSET struct { + Type asn1.ObjectIdentifier + Value [][]AttributeTypeAndValue `asn1:"set"` +} + // Extension represents the ASN.1 structure of the same name. See RFC // 5280, section 4.2. type Extension struct { @@ -157,7 +164,7 @@ type TBSCertificateList struct { Signature AlgorithmIdentifier Issuer RDNSequence ThisUpdate time.Time - NextUpdate time.Time + NextUpdate time.Time `asn1:"optional"` RevokedCertificates []RevokedCertificate `asn1:"optional"` Extensions []Extension `asn1:"tag:0,optional,explicit"` } diff --git a/libgo/go/crypto/x509/root_cgo_darwin.go b/libgo/go/crypto/x509/root_cgo_darwin.go new file mode 100644 index 0000000000..bdcc2c1708 --- /dev/null +++ b/libgo/go/crypto/x509/root_cgo_darwin.go @@ -0,0 +1,79 @@ +// 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. + +// +build cgo + +package x509 + +/* +#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1060 +#cgo LDFLAGS: -framework CoreFoundation -framework Security + +#include +#include + +// FetchPEMRoots fetches the system's list of trusted X.509 root certificates. +// +// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root +// certificates of the system. On failure, the function returns -1. +// +// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after +// we've consumed its content. +int FetchPEMRoots(CFDataRef *pemRoots) { + if (pemRoots == NULL) { + return -1; + } + + CFArrayRef certs = NULL; + OSStatus err = SecTrustCopyAnchorCertificates(&certs); + if (err != noErr) { + return -1; + } + + CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0); + int i, ncerts = CFArrayGetCount(certs); + for (i = 0; i < ncerts; i++) { + CFDataRef data = NULL; + SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i); + if (cert == NULL) { + continue; + } + + // Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport. + // Once we support weak imports via cgo we should prefer that, and fall back to this + // for older systems. + err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data); + if (err != noErr) { + continue; + } + + if (data != NULL) { + CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data)); + CFRelease(data); + } + } + + CFRelease(certs); + + *pemRoots = combinedData; + return 0; +} +*/ +import "C" +import "unsafe" + +func initSystemRoots() { + roots := NewCertPool() + + var data C.CFDataRef = nil + err := C.FetchPEMRoots(&data) + if err == -1 { + return + } + + defer C.CFRelease(C.CFTypeRef(data)) + buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data))) + roots.AppendCertsFromPEM(buf) + systemRoots = roots +} diff --git a/libgo/go/crypto/x509/root_darwin.go b/libgo/go/crypto/x509/root_darwin.go index ad3bfb4b43..2a61d36eae 100644 --- a/libgo/go/crypto/x509/root_darwin.go +++ b/libgo/go/crypto/x509/root_darwin.go @@ -1,81 +1,23 @@ -// Copyright 2011 The Go Authors. All rights reserved. +// Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package x509 -/* -#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1060 -#cgo LDFLAGS: -framework CoreFoundation -framework Security - -#include -#include - -// FetchPEMRoots fetches the system's list of trusted X.509 root certificates. -// -// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root -// certificates of the system. On failure, the function returns -1. -// -// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after -// we've consumed its content. -int FetchPEMRoots(CFDataRef *pemRoots) { - if (pemRoots == NULL) { - return -1; - } - - CFArrayRef certs = NULL; - OSStatus err = SecTrustCopyAnchorCertificates(&certs); - if (err != noErr) { - return -1; - } - - CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0); - int i, ncerts = CFArrayGetCount(certs); - for (i = 0; i < ncerts; i++) { - CFDataRef data = NULL; - SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i); - if (cert == NULL) { - continue; - } - - // Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport. - // Once we support weak imports via cgo we should prefer that, and fall back to this - // for older systems. - err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data); - if (err != noErr) { - continue; - } - - if (data != NULL) { - CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data)); - CFRelease(data); - } - } - - CFRelease(certs); - - *pemRoots = combinedData; - return 0; -} -*/ -import "C" -import "unsafe" +import "os/exec" func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { return nil, nil } -func initSystemRoots() { - roots := NewCertPool() - - var data C.CFDataRef = nil - err := C.FetchPEMRoots(&data) - if err == -1 { - return +func execSecurityRoots() (*CertPool, error) { + cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain") + data, err := cmd.Output() + if err != nil { + return nil, err } - defer C.CFRelease(C.CFTypeRef(data)) - buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data))) - roots.AppendCertsFromPEM(buf) - systemRoots = roots + roots := NewCertPool() + roots.AppendCertsFromPEM(data) + return roots, nil } diff --git a/libgo/go/crypto/x509/root_nocgo_darwin.go b/libgo/go/crypto/x509/root_nocgo_darwin.go new file mode 100644 index 0000000000..d00e257662 --- /dev/null +++ b/libgo/go/crypto/x509/root_nocgo_darwin.go @@ -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. + +// +build !cgo + +package x509 + +func initSystemRoots() { + systemRoots, _ = execSecurityRoots() +} diff --git a/libgo/go/crypto/x509/root_stub.go b/libgo/go/crypto/x509/root_stub.go deleted file mode 100644 index 4c742ccc37..0000000000 --- a/libgo/go/crypto/x509/root_stub.go +++ /dev/null @@ -1,14 +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. - -// +build darwin,!cgo - -package x509 - -func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { - return nil, nil -} - -func initSystemRoots() { -} diff --git a/libgo/go/crypto/x509/root_unix.go b/libgo/go/crypto/x509/root_unix.go index 324f855b13..f77d6c0c57 100644 --- a/libgo/go/crypto/x509/root_unix.go +++ b/libgo/go/crypto/x509/root_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build dragonfly freebsd linux openbsd netbsd +// +build dragonfly freebsd linux nacl netbsd openbsd solaris package x509 @@ -15,6 +15,15 @@ var certFiles = []string{ "/etc/ssl/ca-bundle.pem", // OpenSUSE "/etc/ssl/cert.pem", // OpenBSD "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly + "/etc/pki/tls/cacert.pem", // OpenELEC + "/etc/certs/ca-certificates.crt", // Solaris 11.2+ +} + +// Possible directories with certificate files; stop after successfully +// reading at least one file from a directory. +var certDirectories = []string{ + "/system/etc/security/cacerts", // Android + } func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { @@ -32,6 +41,24 @@ func initSystemRoots() { } } + for _, directory := range certDirectories { + fis, err := ioutil.ReadDir(directory) + if err != nil { + continue + } + rootsAdded := false + for _, fi := range fis { + data, err := ioutil.ReadFile(directory + "/" + fi.Name()) + if err == nil && roots.AppendCertsFromPEM(data) { + rootsAdded = true + } + } + if rootsAdded { + systemRoots = roots + return + } + } + // All of the files failed to load. systemRoots will be nil which will // trigger a specific error at verification time. } diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go index 8327463ca8..ec1981423d 100644 --- a/libgo/go/crypto/x509/verify.go +++ b/libgo/go/crypto/x509/verify.go @@ -116,10 +116,9 @@ func (e UnknownAuthorityError) Error() string { } // SystemRootsError results when we fail to load the system root certificates. -type SystemRootsError struct { -} +type SystemRootsError struct{} -func (e SystemRootsError) Error() string { +func (SystemRootsError) Error() string { return "x509: failed to load system roots and no roots provided" } @@ -206,6 +205,9 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V // needed. If successful, it returns one or more chains where the first // element of the chain is c and the last element is from opts.Roots. // +// If opts.Roots is nil and system roots are unavailable the returned error +// will be of type SystemRootsError. +// // WARNING: this doesn't do any revocation checking. func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) { // Use Windows's own verification and chain building. @@ -425,6 +427,7 @@ func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool { // by each certificate. If we cross out all the usages, then the chain // is unacceptable. +NextCert: for i := len(chain) - 1; i >= 0; i-- { cert := chain[i] if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 { @@ -435,7 +438,7 @@ func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool { for _, usage := range cert.ExtKeyUsage { if usage == ExtKeyUsageAny { // The certificate is explicitly good for any usage. - continue + continue NextCert } } diff --git a/libgo/go/crypto/x509/verify_test.go b/libgo/go/crypto/x509/verify_test.go index ba6c13d451..96b9d9b420 100644 --- a/libgo/go/crypto/x509/verify_test.go +++ b/libgo/go/crypto/x509/verify_test.go @@ -31,8 +31,8 @@ type verifyTest struct { var verifyTests = []verifyTest{ { leaf: googleLeaf, - intermediates: []string{thawteIntermediate}, - currentTime: 1302726541, + intermediates: []string{giag2Intermediate}, + currentTime: 1395785200, dnsName: "www.google.com", testSystemRootsError: true, @@ -42,39 +42,39 @@ var verifyTests = []verifyTest{ }, { leaf: googleLeaf, - intermediates: []string{thawteIntermediate}, - roots: []string{verisignRoot}, - currentTime: 1302726541, + intermediates: []string{giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, dnsName: "www.google.com", expectedChains: [][]string{ - {"Google", "Thawte", "VeriSign"}, + {"Google", "Google Internet Authority", "GeoTrust"}, }, }, { leaf: googleLeaf, - intermediates: []string{thawteIntermediate}, - roots: []string{verisignRoot}, - currentTime: 1302726541, + intermediates: []string{giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, dnsName: "WwW.GooGLE.coM", expectedChains: [][]string{ - {"Google", "Thawte", "VeriSign"}, + {"Google", "Google Internet Authority", "GeoTrust"}, }, }, { leaf: googleLeaf, - intermediates: []string{thawteIntermediate}, - roots: []string{verisignRoot}, - currentTime: 1302726541, + intermediates: []string{giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, dnsName: "www.example.com", errorCallback: expectHostnameError, }, { leaf: googleLeaf, - intermediates: []string{thawteIntermediate}, - roots: []string{verisignRoot}, + intermediates: []string{giag2Intermediate}, + roots: []string{geoTrustRoot}, currentTime: 1, dnsName: "www.example.com", @@ -82,8 +82,8 @@ var verifyTests = []verifyTest{ }, { leaf: googleLeaf, - roots: []string{verisignRoot}, - currentTime: 1302726541, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, dnsName: "www.google.com", // Skip when using systemVerify, since Windows @@ -93,14 +93,22 @@ var verifyTests = []verifyTest{ }, { leaf: googleLeaf, - intermediates: []string{verisignRoot, thawteIntermediate}, - roots: []string{verisignRoot}, - currentTime: 1302726541, + intermediates: []string{geoTrustRoot, giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, dnsName: "www.google.com", expectedChains: [][]string{ - {"Google", "Thawte", "VeriSign"}, + {"Google", "Google Internet Authority", "GeoTrust"}, + // TODO(agl): this is ok, but it would be nice if the + // chain building didn't visit the same SPKI + // twice. + {"Google", "Google Internet Authority", "GeoTrust", "GeoTrust"}, }, + // CAPI doesn't build the chain with the duplicated GeoTrust + // entry so the results don't match. Thus we skip this test + // until that's fixed. + systemSkip: true, }, { leaf: dnssecExpLeaf, @@ -128,9 +136,9 @@ var verifyTests = []verifyTest{ }, { leaf: googleLeafWithInvalidHash, - intermediates: []string{thawteIntermediate}, - roots: []string{verisignRoot}, - currentTime: 1302726541, + intermediates: []string{giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, dnsName: "www.google.com", // The specific error message may not occur when using system @@ -201,6 +209,24 @@ var verifyTests = []verifyTest{ }, }, }, + { + // Check that SHA-384 intermediates (which are popping up) + // work. + leaf: moipLeafCert, + intermediates: []string{comodoIntermediateSHA384, comodoRSAAuthority}, + roots: []string{addTrustRoot}, + currentTime: 1397502195, + dnsName: "api.moip.com.br", + + expectedChains: [][]string{ + { + "api.moip.com.br", + "COMODO RSA Extended Validation Secure Server CA", + "COMODO RSA Certification Authority", + "AddTrust External CA Root", + }, + }, + }, } func expectHostnameError(t *testing.T, i int, err error) (ok bool) { @@ -385,84 +411,111 @@ func nameToKey(name *pkix.Name) string { return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName } -const verisignRoot = `-----BEGIN CERTIFICATE----- -MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG -A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz -cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 -MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV -BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt -YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE -BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is -I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G -CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do -lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc -AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k +const geoTrustRoot = `-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== -----END CERTIFICATE----- ` -const thawteIntermediate = `-----BEGIN CERTIFICATE----- -MIIDIzCCAoygAwIBAgIEMAAAAjANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJV -UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVi -bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNTEzMDAw -MDAwWhcNMTQwNTEyMjM1OTU5WjBMMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh -d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBD -QTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1NNn0I0Vf67NMf59HZGhPwtx -PKzMyGT7Y/wySweUvW+Aui/hBJPAM/wJMyPpC3QrccQDxtLN4i/1CWPN/0ilAL/g -5/OIty0y3pg25gqtAHvEZEo7hHUD8nCSfQ5i9SGraTaEMXWQ+L/HbIgbBpV8yeWo -3nWhLHpo39XKHIdYYBkCAwEAAaOB/jCB+zASBgNVHRMBAf8ECDAGAQH/AgEAMAsG -A1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAX -BgNVBAMTEFByaXZhdGVMYWJlbDMtMTUwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDov -L2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwMgYIKwYBBQUHAQEEJjAkMCIGCCsG -AQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMDQGA1UdJQQtMCsGCCsGAQUF -BwMBBggrBgEFBQcDAgYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEB -BQUAA4GBAFWsY+reod3SkF+fC852vhNRj5PZBSvIG3dLrWlQoe7e3P3bB+noOZTc -q3J5Lwa/q4FwxKjt6lM07e8eU9kGx1Yr0Vz00YqOtCuxN5BICEIlxT6Ky3/rbwTR -bcV0oveifHtgPHfNDs5IAn8BL7abN+AqKjbc1YXWrOU/VG+WHgWv +const giag2Intermediate = `-----BEGIN CERTIFICATE----- +MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG +EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy +bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP +VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv +h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE +ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ +EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC +DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7 +qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD +VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g +K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI +KwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n +ZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB +BQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY +/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/ +zG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza +HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto +WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6 +yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx -----END CERTIFICATE----- ` const googleLeaf = `-----BEGIN CERTIFICATE----- -MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BAQUFADBM -MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg -THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x -MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh -MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw -FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC -gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN -gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L -05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM -BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl -LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF -BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw -Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0 -ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAQUF -AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5 -u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6 -z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw== ------END CERTIFICATE-----` +MIIEdjCCA16gAwIBAgIIcR5k4dkoe04wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE +BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl +cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwMzEyMDkzODMwWhcNMTQwNjEwMDAwMDAw +WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN +TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOd3d3 +Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4zYCe +m0oUBhwE0EwBr65eBOcgcQO2PaSIAB2dEP/c1EMX2tOy0ov8rk83ePhJ+MWdT1z6 +jge9X4zQQI8ZyA9qIiwrKBZOi8DNUvrqNZC7fJAVRrb9aX/99uYOJCypIbpmWG1q +fhbHjJewhwf8xYPj71eU4rLG80a+DapWmphtfq3h52lDQIBzLVf1yYbyrTaELaz4 +NXF7HXb5YkId/gxIsSzM0aFUVu2o8sJcLYAsJqwfFKBKOMxUcn545nlspf0mTcWZ +0APlbwsKznNs4/xCDwIxxWjjqgHrYAFl6y07i1gzbAOqdNEyR24p+3JWI8WZBlBI +dk2KGj0W1fIfsvyxAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEFBQcDAQYI +KwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYBBQUHAQEE +XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0 +MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G +A1UdDgQWBBTXD5Bx6iqT+dmEhbFL4OUoHyZn8zAMBgNVHRMBAf8EAjAAMB8GA1Ud +IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYKKwYBBAHW +eQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB +RzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCR3RJtHzgDh33b/MI1ugiki+nl8Ikj +5larbJRE/rcA5oite+QJyAr6SU1gJJ/rRrK3ItVEHr9L621BCM7GSdoNMjB9MMcf +tJAW0kYGJ+wqKm53wG/JaOADTnnq2Mt/j6F2uvjgN/ouns1nRHufIvd370N0LeH+ +orKqTuAPzXK7imQk6+OycYABbqCtC/9qmwRd8wwn7sF97DtYfK8WuNHtFalCAwyi +8LxJJYJCLWoMhZ+V8GZm+FOex5qkQAjnZrtNlbQJ8ro4r+rpKXtmMFFhfa+7L+PA +Kom08eUK8skxAzfDDijZPh10VtJ66uBoiDPdT+uCBehcBIcmSTrKjFGX +-----END CERTIFICATE----- +` // googleLeafWithInvalidHash is the same as googleLeaf, but the signature // algorithm in the certificate contains a nonsense OID. const googleLeafWithInvalidHash = `-----BEGIN CERTIFICATE----- -MIIDITCCAoqgAwIBAgIQL9+89q6RUm0PmqPfQDQ+mjANBgkqhkiG9w0BATIFADBM -MQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkg -THRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBDQTAeFw0wOTEyMTgwMDAwMDBaFw0x -MTEyMTgyMzU5NTlaMGgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh -MRYwFAYDVQQHFA1Nb3VudGFpbiBWaWV3MRMwEQYDVQQKFApHb29nbGUgSW5jMRcw -FQYDVQQDFA53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC -gYEA6PmGD5D6htffvXImttdEAoN4c9kCKO+IRTn7EOh8rqk41XXGOOsKFQebg+jN -gtXj9xVoRaELGYW84u+E593y17iYwqG7tcFR39SDAqc9BkJb4SLD3muFXxzW2k6L -05vuuWciKh0R73mkszeK9P4Y/bz5RiNQl/Os/CRGK1w7t0UCAwEAAaOB5zCB5DAM -BgNVHRMBAf8EAjAAMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwudGhhd3Rl -LmNvbS9UaGF3dGVTR0NDQS5jcmwwKAYDVR0lBCEwHwYIKwYBBQUHAwEGCCsGAQUF -BwMCBglghkgBhvhCBAEwcgYIKwYBBQUHAQEEZjBkMCIGCCsGAQUFBzABhhZodHRw -Oi8vb2NzcC50aGF3dGUuY29tMD4GCCsGAQUFBzAChjJodHRwOi8vd3d3LnRoYXd0 -ZS5jb20vcmVwb3NpdG9yeS9UaGF3dGVfU0dDX0NBLmNydDANBgkqhkiG9w0BAVAF -AAOBgQCfQ89bxFApsb/isJr/aiEdLRLDLE5a+RLizrmCUi3nHX4adpaQedEkUjh5 -u2ONgJd8IyAPkU0Wueru9G2Jysa9zCRo1kNbzipYvzwY4OA8Ys+WAi0oR1A04Se6 -z5nRUP8pJcA2NhUzUnC+MY+f6H/nEQyNv4SgQhqAibAxWEEHXw== ------END CERTIFICATE-----` +MIIEdjCCA16gAwIBAgIIcR5k4dkoe04wDQYJKoZIhvcNAWAFBQAwSTELMAkGA1UE +BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl +cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwMzEyMDkzODMwWhcNMTQwNjEwMDAwMDAw +WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN +TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOd3d3 +Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4zYCe +m0oUBhwE0EwBr65eBOcgcQO2PaSIAB2dEP/c1EMX2tOy0ov8rk83ePhJ+MWdT1z6 +jge9X4zQQI8ZyA9qIiwrKBZOi8DNUvrqNZC7fJAVRrb9aX/99uYOJCypIbpmWG1q +fhbHjJewhwf8xYPj71eU4rLG80a+DapWmphtfq3h52lDQIBzLVf1yYbyrTaELaz4 +NXF7HXb5YkId/gxIsSzM0aFUVu2o8sJcLYAsJqwfFKBKOMxUcn545nlspf0mTcWZ +0APlbwsKznNs4/xCDwIxxWjjqgHrYAFl6y07i1gzbAOqdNEyR24p+3JWI8WZBlBI +dk2KGj0W1fIfsvyxAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEFBQcDAQYI +KwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYBBQUHAQEE +XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0 +MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G +A1UdDgQWBBTXD5Bx6iqT+dmEhbFL4OUoHyZn8zAMBgNVHRMBAf8EAjAAMB8GA1Ud +IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYKKwYBBAHW +eQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB +RzIuY3JsMA0GCSqGSIb3DQFgBQUAA4IBAQCR3RJtHzgDh33b/MI1ugiki+nl8Ikj +5larbJRE/rcA5oite+QJyAr6SU1gJJ/rRrK3ItVEHr9L621BCM7GSdoNMjB9MMcf +tJAW0kYGJ+wqKm53wG/JaOADTnnq2Mt/j6F2uvjgN/ouns1nRHufIvd370N0LeH+ +orKqTuAPzXK7imQk6+OycYABbqCtC/9qmwRd8wwn7sF97DtYfK8WuNHtFalCAwyi +8LxJJYJCLWoMhZ+V8GZm+FOex5qkQAjnZrtNlbQJ8ro4r+rpKXtmMFFhfa+7L+PA +Kom08eUK8skxAzfDDijZPh10VtJ66uBoiDPdT+uCBehcBIcmSTrKjFGX +-----END CERTIFICATE----- +` const dnssecExpLeaf = `-----BEGIN CERTIFICATE----- MIIGzTCCBbWgAwIBAgIDAdD6MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ @@ -936,3 +989,135 @@ AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE-----` + +var moipLeafCert = `-----BEGIN CERTIFICATE----- +MIIGQDCCBSigAwIBAgIRAPe/cwh7CUWizo8mYSDavLIwDQYJKoZIhvcNAQELBQAw +gZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYD +VQQDEy9DT01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZl +ciBDQTAeFw0xMzA4MTUwMDAwMDBaFw0xNDA4MTUyMzU5NTlaMIIBQjEXMBUGA1UE +BRMOMDg3MTg0MzEwMDAxMDgxEzARBgsrBgEEAYI3PAIBAxMCQlIxGjAYBgsrBgEE +AYI3PAIBAhMJU2FvIFBhdWxvMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlv +bjELMAkGA1UEBhMCQlIxETAPBgNVBBETCDAxNDUyMDAwMRIwEAYDVQQIEwlTYW8g +UGF1bG8xEjAQBgNVBAcTCVNhbyBQYXVsbzEtMCsGA1UECRMkQXZlbmlkYSBCcmln +YWRlaXJvIEZhcmlhIExpbWEgLCAyOTI3MR0wGwYDVQQKExRNb2lwIFBhZ2FtZW50 +b3MgUy5BLjENMAsGA1UECxMETU9JUDEYMBYGA1UECxMPU1NMIEJsaW5kYWRvIEVW +MRgwFgYDVQQDEw9hcGkubW9pcC5jb20uYnIwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDN0b9x6TrXXA9hPCF8/NjqGJ++2D4LO4ZiMFTjs0VwpXy2Y1Oe +s74/HuiLGnAHxTmAtV7IpZMibiOcTxcnDYp9oEWkf+gR+hZvwFZwyOBC7wyb3SR3 +UvV0N1ZbEVRYpN9kuX/3vjDghjDmzzBwu8a/T+y5JTym5uiJlngVAWyh/RjtIvYi ++NVkQMbyVlPGkoCe6c30pH8DKYuUCZU6DHjUsPTX3jAskqbhDSAnclX9iX0p2bmw +KVBc+5Vh/2geyzDuquF0w+mNIYdU5h7uXvlmJnf3d2Cext5dxdL8/jezD3U0dAqI +pYSKERbyxSkJWxdvRlhdpM9YXMJcpc88xNp1AgMBAAGjggHcMIIB2DAfBgNVHSME +GDAWgBQ52v/KKBSKqHQTCLnkDqnS+n6daTAdBgNVHQ4EFgQU/lXuOa7DMExzZjRj +LQWcMWGZY7swDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYw +FAYIKwYBBQUHAwEGCCsGAQUFBwMCMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQUB +MCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMFYG +A1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET1JT +QUV4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCBhwYIKwYBBQUH +AQEEezB5MFEGCCsGAQUFBzAChkVodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01P +RE9SU0FFeHRlbmRlZFZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5jcnQwJAYIKwYB +BQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAvBgNVHREEKDAmgg9hcGku +bW9pcC5jb20uYnKCE3d3dy5hcGkubW9pcC5jb20uYnIwDQYJKoZIhvcNAQELBQAD +ggEBAFoTmPlaDcf+nudhjXHwud8g7/LRyA8ucb+3/vfmgbn7FUc1eprF5sJS1mA+ +pbiTyXw4IxcJq2KUj0Nw3IPOe9k84mzh+XMmdCKH+QK3NWkE9Udz+VpBOBc0dlqC +1RH5umStYDmuZg/8/r652eeQ5kUDcJyADfpKWBgDPYaGtwzKVT4h3Aok9SLXRHx6 +z/gOaMjEDMarMCMw4VUIG1pvNraZrG5oTaALPaIXXpd8VqbQYPudYJ6fR5eY3FeW +H/ofbYFdRcuD26MfBFWE9VGGral9Fgo8sEHffho+UWhgApuQV4/l5fMzxB5YBXyQ +jhuy8PqqZS9OuLilTeLu4a8z2JI= +-----END CERTIFICATE-----` + +var comodoIntermediateSHA384 = `-----BEGIN CERTIFICATE----- +MIIGDjCCA/agAwIBAgIQBqdDgNTr/tQ1taP34Wq92DANBgkqhkiG9w0BAQwFADCB +hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV +BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTIwMjEy +MDAwMDAwWhcNMjcwMjExMjM1OTU5WjCBkjELMAkGA1UEBhMCR0IxGzAZBgNVBAgT +EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMTL0NPTU9ETyBSU0EgRXh0ZW5kZWQg +VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAlVbeVLTf1QJJe9FbXKKyHo+cK2JMK40SKPMalaPGEP0p3uGf +CzhAk9HvbpUQ/OGQF3cs7nU+e2PsYZJuTzurgElr3wDqAwB/L3XVKC/sVmePgIOj +vdwDmZOLlJFWW6G4ajo/Br0OksxgnP214J9mMF/b5pTwlWqvyIqvgNnmiDkBfBzA +xSr3e5Wg8narbZtyOTDr0VdVAZ1YEZ18bYSPSeidCfw8/QpKdhQhXBZzQCMZdMO6 +WAqmli7eNuWf0MLw4eDBYuPCGEUZUaoXHugjddTI0JYT/8ck0YwLJ66eetw6YWNg +iJctXQUL5Tvrrs46R3N2qPos3cCHF+msMJn4HwIDAQABo4IBaTCCAWUwHwYDVR0j +BBgwFoAUu69+Aj36pvE8hI6t7jiY7NkyMtQwHQYDVR0OBBYEFDna/8ooFIqodBMI +ueQOqdL6fp1pMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMD4G +A1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5j +b21vZG8uY29tL0NQUzBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9k +b2NhLmNvbS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggr +BgEFBQcBAQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29t +L0NPTU9ET1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz +cC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAERCnUFRK0iIXZebeV4R +AUpSGXtBLMeJPNBy3IX6WK/VJeQT+FhlZ58N/1eLqYVeyqZLsKeyLeCMIs37/3mk +jCuN/gI9JN6pXV/kD0fQ22YlPodHDK4ixVAihNftSlka9pOlk7DgG4HyVsTIEFPk +1Hax0VtpS3ey4E/EhOfUoFDuPPpE/NBXueEoU/1Tzdy5H3pAvTA/2GzS8+cHnx8i +teoiccsq8FZ8/qyo0QYPFBRSTP5kKwxpKrgNUG4+BAe/eiCL+O5lCeHHSQgyPQ0o +fkkdt0rvAucNgBfIXOBhYsvss2B5JdoaZXOcOBCgJjqwyBZ9kzEi7nQLiMBciUEA +KKlHMd99SUWa9eanRRrSjhMQ34Ovmw2tfn6dNVA0BM7pINae253UqNpktNEvWS5e +ojZh1CSggjMziqHRbO9haKPl0latxf1eYusVqHQSTC8xjOnB3xBLAer2VBvNfzu9 +XJ/B288ByvK6YBIhMe2pZLiySVgXbVrXzYxtvp5/4gJYp9vDLVj2dAZqmvZh+fYA +tmnYOosxWd2R5nwnI4fdAw+PKowegwFOAWEMUnNt/AiiuSpm5HZNMaBWm9lTjaK2 +jwLI5jqmBNFI+8NKAnb9L9K8E7bobTQk+p0pisehKxTxlgBzuRPpwLk6R1YCcYAn +pLwltum95OmYdBbxN4SBB7SC +-----END CERTIFICATE-----` + +const comodoRSAAuthority = `-----BEGIN CERTIFICATE----- +MIIFdDCCBFygAwIBAgIQJ2buVutJ846r13Ci/ITeIjANBgkqhkiG9w0BAQwFADBv +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk +ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF +eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow +gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD +VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkehUktIKVrGsDSTdxc9EZ3SZKzejfSNw +AHG8U9/E+ioSj0t/EFa9n3Byt2F/yUsPF6c947AEYe7/EZfH9IY+Cvo+XPmT5jR6 +2RRr55yzhaCCenavcZDX7P0N+pxs+t+wgvQUfvm+xKYvT3+Zf7X8Z0NyvQwA1onr +ayzT7Y+YHBSrfuXjbvzYqOSSJNpDa2K4Vf3qwbxstovzDo2a5JtsaZn4eEgwRdWt +4Q08RWD8MpZRJ7xnw8outmvqRsfHIKCxH2XeSAi6pE6p8oNGN4Tr6MyBSENnTnIq +m1y9TBsoilwie7SrmNnu4FGDwwlGTm0+mfqVF9p8M1dBPI1R7Qu2XK8sYxrfV8g/ +vOldxJuvRZnio1oktLqpVj3Pb6r/SVi+8Kj/9Lit6Tf7urj0Czr56ENCHonYhMsT +8dm74YlguIwoVqwUHZwK53Hrzw7dPamWoUi9PPevtQ0iTMARgexWO/bTouJbt7IE +IlKVgJNp6I5MZfGRAy1wdALqi2cVKWlSArvX31BqVUa/oKMoYX9w0MOiqiwhqkfO +KJwGRXa/ghgntNWutMtQ5mv0TIZxMOmm3xaG4Nj/QN370EKIf6MzOi5cHkERgWPO +GHFrK+ymircxXDpqR+DDeVnWIBqv8mqYqnK8V0rSS527EPywTEHl7R09XiidnMy/ +s1Hap0flhFMCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73g +JMtUGjAdBgNVHQ4EFgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQD +AgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9 +MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVy +bmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6 +Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAGS/g/FfmoXQ +zbihKVcN6Fr30ek+8nYEbvFScLsePP9NDXRqzIGCJdPDoCpdTPW6i6FtxFQJdcfj +Jw5dhHk3QBN39bSsHNA7qxcS1u80GH4r6XnTq1dFDK8o+tDb5VCViLvfhVdpfZLY +Uspzgb8c8+a4bmYRBbMelC1/kZWSWfFMzqORcUx8Rww7Cxn2obFshj5cqsQugsv5 +B5a6SE2Q8pTIqXOi6wZ7I53eovNNVZ96YUWYGGjHXkBrI/V5eu+MtWuLt29G9Hvx +PUsE2JOAWVrgQSQdso8VYFhH2+9uRv0V9dlfmrPb2LjkQLPNlzmuhbsdjrzch5vR +pu/xO28QOG8= +-----END CERTIFICATE-----` + +const addTrustRoot = `-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU +MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs +IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 +MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h +bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt +H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 +uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX +mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX +a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN +E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 +WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD +VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 +Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU +cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx +IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN +AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH +YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC +Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX +c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a +mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE-----` diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go index 57f68ba7ed..7a37b98e31 100644 --- a/libgo/go/crypto/x509/x509.go +++ b/libgo/go/crypto/x509/x509.go @@ -13,6 +13,8 @@ import ( "crypto/elliptic" "crypto/rsa" "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" "crypto/x509/pkix" "encoding/asn1" "encoding/pem" @@ -241,32 +243,31 @@ var ( oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} ) +var signatureAlgorithmDetails = []struct { + algo SignatureAlgorithm + oid asn1.ObjectIdentifier + pubKeyAlgo PublicKeyAlgorithm + hash crypto.Hash +}{ + {MD2WithRSA, oidSignatureMD2WithRSA, RSA, crypto.Hash(0) /* no value for MD2 */}, + {MD5WithRSA, oidSignatureMD5WithRSA, RSA, crypto.MD5}, + {SHA1WithRSA, oidSignatureSHA1WithRSA, RSA, crypto.SHA1}, + {SHA256WithRSA, oidSignatureSHA256WithRSA, RSA, crypto.SHA256}, + {SHA384WithRSA, oidSignatureSHA384WithRSA, RSA, crypto.SHA384}, + {SHA512WithRSA, oidSignatureSHA512WithRSA, RSA, crypto.SHA512}, + {DSAWithSHA1, oidSignatureDSAWithSHA1, DSA, crypto.SHA1}, + {DSAWithSHA256, oidSignatureDSAWithSHA256, DSA, crypto.SHA256}, + {ECDSAWithSHA1, oidSignatureECDSAWithSHA1, ECDSA, crypto.SHA1}, + {ECDSAWithSHA256, oidSignatureECDSAWithSHA256, ECDSA, crypto.SHA256}, + {ECDSAWithSHA384, oidSignatureECDSAWithSHA384, ECDSA, crypto.SHA384}, + {ECDSAWithSHA512, oidSignatureECDSAWithSHA512, ECDSA, crypto.SHA512}, +} + func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm { - switch { - case oid.Equal(oidSignatureMD2WithRSA): - return MD2WithRSA - case oid.Equal(oidSignatureMD5WithRSA): - return MD5WithRSA - case oid.Equal(oidSignatureSHA1WithRSA): - return SHA1WithRSA - case oid.Equal(oidSignatureSHA256WithRSA): - return SHA256WithRSA - case oid.Equal(oidSignatureSHA384WithRSA): - return SHA384WithRSA - case oid.Equal(oidSignatureSHA512WithRSA): - return SHA512WithRSA - case oid.Equal(oidSignatureDSAWithSHA1): - return DSAWithSHA1 - case oid.Equal(oidSignatureDSAWithSHA256): - return DSAWithSHA256 - case oid.Equal(oidSignatureECDSAWithSHA1): - return ECDSAWithSHA1 - case oid.Equal(oidSignatureECDSAWithSHA256): - return ECDSAWithSHA256 - case oid.Equal(oidSignatureECDSAWithSHA384): - return ECDSAWithSHA384 - case oid.Equal(oidSignatureECDSAWithSHA512): - return ECDSAWithSHA512 + for _, details := range signatureAlgorithmDetails { + if oid.Equal(details.oid) { + return details.algo + } } return UnknownSignatureAlgorithm } @@ -493,6 +494,11 @@ type Certificate struct { BasicConstraintsValid bool // if true then the next two fields are valid. IsCA bool MaxPathLen int + // MaxPathLenZero indicates that BasicConstraintsValid==true and + // MaxPathLen==0 should be interpreted as an actual maximum path length + // of zero. Otherwise, that combination is interpreted as MaxPathLen + // not being set. + MaxPathLenZero bool SubjectKeyId []byte AuthorityKeyId []byte @@ -790,6 +796,58 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{ } } +func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddresses []net.IP, err 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 + if _, err = asn1.Unmarshal(value, &seq); err != nil { + return + } + if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 { + err = asn1.StructuralError{Msg: "bad SAN sequence"} + return + } + + rest := seq.Bytes + for len(rest) > 0 { + var v asn1.RawValue + rest, err = asn1.Unmarshal(rest, &v) + if err != nil { + return + } + switch v.Tag { + case 1: + emailAddresses = append(emailAddresses, string(v.Bytes)) + case 2: + dnsNames = append(dnsNames, string(v.Bytes)) + case 7: + switch len(v.Bytes) { + case net.IPv4len, net.IPv6len: + ipAddresses = append(ipAddresses, v.Bytes) + default: + err = errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(v.Bytes))) + return + } + } + } + + return +} + func parseCertificate(in *certificate) (*Certificate, error) { out := new(Certificate) out.Raw = in.Raw @@ -860,61 +918,16 @@ func parseCertificate(in *certificate) (*Certificate, error) { out.BasicConstraintsValid = true out.IsCA = constraints.IsCA out.MaxPathLen = constraints.MaxPathLen + out.MaxPathLenZero = out.MaxPathLen == 0 continue } case 17: - // 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 - _, err := asn1.Unmarshal(e.Value, &seq) + out.DNSNames, out.EmailAddresses, out.IPAddresses, err = parseSANExtension(e.Value) if err != nil { return nil, err } - if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 { - return nil, asn1.StructuralError{Msg: "bad SAN sequence"} - } - parsedName := false - - rest := seq.Bytes - for len(rest) > 0 { - var v asn1.RawValue - rest, err = asn1.Unmarshal(rest, &v) - if err != nil { - return nil, err - } - switch v.Tag { - case 1: - out.EmailAddresses = append(out.EmailAddresses, string(v.Bytes)) - parsedName = true - case 2: - out.DNSNames = append(out.DNSNames, string(v.Bytes)) - parsedName = true - case 7: - switch len(v.Bytes) { - case net.IPv4len, net.IPv6len: - out.IPAddresses = append(out.IPAddresses, v.Bytes) - default: - return nil, errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(v.Bytes))) - } - } - } - - if parsedName { + if len(out.DNSNames) > 0 || len(out.EmailAddresses) > 0 || len(out.IPAddresses) > 0 { continue } // If we didn't parse any of the names then we @@ -1151,6 +1164,27 @@ func oidInExtensions(oid asn1.ObjectIdentifier, extensions []pkix.Extension) boo return false } +// marshalSANs marshals a list of addresses into a the contents of an X.509 +// SubjectAlternativeName extension. +func marshalSANs(dnsNames, emailAddresses []string, ipAddresses []net.IP) (derBytes []byte, err error) { + var rawValues []asn1.RawValue + for _, name := range dnsNames { + rawValues = append(rawValues, asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(name)}) + } + for _, email := range emailAddresses { + rawValues = append(rawValues, asn1.RawValue{Tag: 1, Class: 2, Bytes: []byte(email)}) + } + for _, rawIP := range ipAddresses { + // If possible, we always want to encode IPv4 addresses in 4 bytes. + ip := rawIP.To4() + if ip == nil { + ip = rawIP + } + rawValues = append(rawValues, asn1.RawValue{Tag: 7, Class: 2, Bytes: ip}) + } + return asn1.Marshal(rawValues) +} + func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) { ret = make([]pkix.Extension, 10 /* maximum number of elements. */) n := 0 @@ -1199,8 +1233,15 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) { } if template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) { + // Leaving MaxPathLen as zero indicates that no maximum path + // length is desired, unless MaxPathLenZero is set. A value of + // -1 causes encoding/asn1 to omit the value as desired. + maxPathLen := template.MaxPathLen + if maxPathLen == 0 && !template.MaxPathLenZero { + maxPathLen = -1 + } ret[n].Id = oidExtensionBasicConstraints - ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, template.MaxPathLen}) + ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, maxPathLen}) ret[n].Critical = true if err != nil { return @@ -1252,22 +1293,7 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) { if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0) && !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) { ret[n].Id = oidExtensionSubjectAltName - var rawValues []asn1.RawValue - for _, name := range template.DNSNames { - rawValues = append(rawValues, asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(name)}) - } - for _, email := range template.EmailAddresses { - rawValues = append(rawValues, asn1.RawValue{Tag: 1, Class: 2, Bytes: []byte(email)}) - } - for _, rawIP := range template.IPAddresses { - // If possible, we always want to encode IPv4 addresses in 4 bytes. - ip := rawIP.To4() - if ip == nil { - ip = rawIP - } - rawValues = append(rawValues, asn1.RawValue{Tag: 7, Class: 2, Bytes: ip}) - } - ret[n].Value, err = asn1.Marshal(rawValues) + ret[n].Value, err = marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses) if err != nil { return } @@ -1315,7 +1341,7 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) { dp := distributionPoint{ DistributionPoint: distributionPointName{ - FullName: asn1.RawValue{Tag: 0, Class: 2, Bytes: rawFullName}, + FullName: asn1.RawValue{Tag: 0, Class: 2, IsCompound: true, Bytes: rawFullName}, }, } crlDp = append(crlDp, dp) @@ -1342,11 +1368,76 @@ func subjectBytes(cert *Certificate) ([]byte, error) { return asn1.Marshal(cert.Subject.ToRDNSequence()) } +// signingParamsForPrivateKey returns the parameters to use for signing with +// priv. If requestedSigAlgo is not zero then it overrides the default +// signature algorithm. +func signingParamsForPrivateKey(priv interface{}, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { + var pubType PublicKeyAlgorithm + + switch priv := priv.(type) { + case *rsa.PrivateKey: + pubType = RSA + sigAlgo.Algorithm = oidSignatureSHA256WithRSA + hashFunc = crypto.SHA256 + + case *ecdsa.PrivateKey: + pubType = ECDSA + + switch priv.Curve { + case elliptic.P224(), elliptic.P256(): + hashFunc = crypto.SHA256 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 + case elliptic.P384(): + hashFunc = crypto.SHA384 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 + case elliptic.P521(): + hashFunc = crypto.SHA512 + sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 + default: + err = errors.New("x509: unknown elliptic curve") + } + + default: + err = errors.New("x509: only RSA and ECDSA private keys supported") + } + + if err != nil { + return + } + + if requestedSigAlgo == 0 { + return + } + + found := false + for _, details := range signatureAlgorithmDetails { + if details.algo == requestedSigAlgo { + if details.pubKeyAlgo != pubType { + err = errors.New("x509: requested SignatureAlgorithm does not match private key type") + return + } + sigAlgo.Algorithm, hashFunc = details.oid, details.hash + if hashFunc == 0 { + err = errors.New("x509: cannot sign with hash function requested") + return + } + found = true + break + } + } + + if !found { + err = errors.New("x509: unknown SignatureAlgorithm") + } + + return +} + // CreateCertificate creates a new certificate based on a template. The // following members of template are used: SerialNumber, Subject, NotBefore, // NotAfter, KeyUsage, ExtKeyUsage, UnknownExtKeyUsage, BasicConstraintsValid, // IsCA, MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical, -// PermittedDNSDomains. +// PermittedDNSDomains, SignatureAlgorithm. // // 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 @@ -1355,38 +1446,16 @@ func subjectBytes(cert *Certificate) ([]byte, error) { // The returned slice is the certificate in DER encoding. // // The only supported key types are RSA and ECDSA (*rsa.PublicKey or -// *ecdsa.PublicKey for pub, *rsa.PrivateKey or *ecdsa.PublicKey for priv). +// *ecdsa.PublicKey for pub, *rsa.PrivateKey or *ecdsa.PrivateKey for priv). func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interface{}, priv interface{}) (cert []byte, err error) { - var publicKeyBytes []byte - var publicKeyAlgorithm pkix.AlgorithmIdentifier - - if publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(pub); err != nil { + hashFunc, signatureAlgorithm, err := signingParamsForPrivateKey(priv, template.SignatureAlgorithm) + if err != nil { return nil, err } - var signatureAlgorithm pkix.AlgorithmIdentifier - var hashFunc crypto.Hash - - switch priv := priv.(type) { - case *rsa.PrivateKey: - signatureAlgorithm.Algorithm = oidSignatureSHA1WithRSA - hashFunc = crypto.SHA1 - case *ecdsa.PrivateKey: - switch priv.Curve { - case elliptic.P224(), elliptic.P256(): - hashFunc = crypto.SHA256 - signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA256 - case elliptic.P384(): - hashFunc = crypto.SHA384 - signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA384 - case elliptic.P521(): - hashFunc = crypto.SHA512 - signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA512 - default: - return nil, errors.New("x509: unknown elliptic curve") - } - default: - return nil, errors.New("x509: only RSA and ECDSA private keys supported") + publicKeyBytes, publicKeyAlgorithm, err := marshalPublicKey(pub) + if err != nil { + return nil, err } if err != nil { @@ -1535,3 +1604,313 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts [ SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, }) } + +// CertificateRequest represents a PKCS #10, certificate signature request. +type CertificateRequest struct { + Raw []byte // Complete ASN.1 DER content (CSR, signature algorithm and signature). + RawTBSCertificateRequest []byte // Certificate request info part of raw ASN.1 DER content. + RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo. + RawSubject []byte // DER encoded Subject. + + Version int + Signature []byte + SignatureAlgorithm SignatureAlgorithm + + PublicKeyAlgorithm PublicKeyAlgorithm + PublicKey interface{} + + Subject pkix.Name + + // Attributes is a collection of attributes providing + // additional information about the subject of the certificate. + // See RFC 2986 section 4.1. + Attributes []pkix.AttributeTypeAndValueSET + + // Extensions contains raw X.509 extensions. When parsing CSRs, this + // can be used to extract extensions that are not parsed by this + // package. + Extensions []pkix.Extension + + // ExtraExtensions contains extensions to be copied, raw, into any + // marshaled CSR. Values override any extensions that would otherwise + // be produced based on the other fields but are overridden by any + // extensions specified in Attributes. + // + // The ExtraExtensions field is not populated when parsing CSRs, see + // Extensions. + ExtraExtensions []pkix.Extension + + // Subject Alternate Name values. + DNSNames []string + EmailAddresses []string + IPAddresses []net.IP +} + +// These structures reflect the ASN.1 structure of X.509 certificate +// signature requests (see RFC 2986): + +type tbsCertificateRequest struct { + Raw asn1.RawContent + Version int + Subject asn1.RawValue + PublicKey publicKeyInfo + Attributes []pkix.AttributeTypeAndValueSET `asn1:"tag:0"` +} + +type certificateRequest struct { + Raw asn1.RawContent + TBSCSR tbsCertificateRequest + SignatureAlgorithm pkix.AlgorithmIdentifier + SignatureValue asn1.BitString +} + +// oidExtensionRequest is a PKCS#9 OBJECT IDENTIFIER that indicates requested +// extensions in a CSR. +var oidExtensionRequest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 14} + +// CreateCertificateRequest creates a new certificate based on a template. The +// following members of template are used: Subject, Attributes, +// SignatureAlgorithm, Extensions, DNSNames, EmailAddresses, and IPAddresses. +// The private key is the private key of the signer. +// +// The returned slice is the certificate request in DER encoding. +// +// The only supported key types are RSA (*rsa.PrivateKey) and ECDSA +// (*ecdsa.PrivateKey). +func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv interface{}) (csr []byte, err error) { + hashFunc, sigAlgo, err := signingParamsForPrivateKey(priv, template.SignatureAlgorithm) + if err != nil { + return nil, err + } + + var publicKeyBytes []byte + var publicKeyAlgorithm pkix.AlgorithmIdentifier + + switch priv := priv.(type) { + case *rsa.PrivateKey: + publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(&priv.PublicKey) + case *ecdsa.PrivateKey: + publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(&priv.PublicKey) + default: + panic("internal error") + } + + if err != nil { + return nil, err + } + + var extensions []pkix.Extension + + if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0) && + !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) { + sanBytes, err := marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses) + if err != nil { + return nil, err + } + + extensions = append(extensions, pkix.Extension{ + Id: oidExtensionSubjectAltName, + Value: sanBytes, + }) + } + + extensions = append(extensions, template.ExtraExtensions...) + + var attributes []pkix.AttributeTypeAndValueSET + attributes = append(attributes, template.Attributes...) + + if len(extensions) > 0 { + // specifiedExtensions contains all the extensions that we + // found specified via template.Attributes. + specifiedExtensions := make(map[string]bool) + + for _, atvSet := range template.Attributes { + if !atvSet.Type.Equal(oidExtensionRequest) { + continue + } + + for _, atvs := range atvSet.Value { + for _, atv := range atvs { + specifiedExtensions[atv.Type.String()] = true + } + } + } + + atvs := make([]pkix.AttributeTypeAndValue, 0, len(extensions)) + for _, e := range extensions { + if specifiedExtensions[e.Id.String()] { + // Attributes already contained a value for + // this extension and it takes priority. + continue + } + + atvs = append(atvs, pkix.AttributeTypeAndValue{ + // There is no place for the critical flag in a CSR. + Type: e.Id, + Value: e.Value, + }) + } + + // Append the extensions to an existing attribute if possible. + appended := false + for _, atvSet := range attributes { + if !atvSet.Type.Equal(oidExtensionRequest) || len(atvSet.Value) == 0 { + continue + } + + atvSet.Value[0] = append(atvSet.Value[0], atvs...) + appended = true + break + } + + // Otherwise, add a new attribute for the extensions. + if !appended { + attributes = append(attributes, pkix.AttributeTypeAndValueSET{ + Type: oidExtensionRequest, + Value: [][]pkix.AttributeTypeAndValue{ + atvs, + }, + }) + } + } + + asn1Subject := template.RawSubject + if len(asn1Subject) == 0 { + asn1Subject, err = asn1.Marshal(template.Subject.ToRDNSequence()) + if err != nil { + return + } + } + + tbsCSR := tbsCertificateRequest{ + Version: 0, // PKCS #10, RFC 2986 + Subject: asn1.RawValue{FullBytes: asn1Subject}, + PublicKey: publicKeyInfo{ + Algorithm: publicKeyAlgorithm, + PublicKey: asn1.BitString{ + Bytes: publicKeyBytes, + BitLength: len(publicKeyBytes) * 8, + }, + }, + Attributes: attributes, + } + + tbsCSRContents, err := asn1.Marshal(tbsCSR) + if err != nil { + return + } + tbsCSR.Raw = tbsCSRContents + + h := hashFunc.New() + h.Write(tbsCSRContents) + digest := h.Sum(nil) + + var signature []byte + switch priv := priv.(type) { + case *rsa.PrivateKey: + signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest) + case *ecdsa.PrivateKey: + var r, s *big.Int + if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil { + signature, err = asn1.Marshal(ecdsaSignature{r, s}) + } + default: + panic("internal error") + } + + if err != nil { + return + } + + return asn1.Marshal(certificateRequest{ + TBSCSR: tbsCSR, + SignatureAlgorithm: sigAlgo, + SignatureValue: asn1.BitString{ + Bytes: signature, + BitLength: len(signature) * 8, + }, + }) +} + +// ParseCertificateRequest parses a single certificate request from the +// given ASN.1 DER data. +func ParseCertificateRequest(asn1Data []byte) (*CertificateRequest, error) { + var csr certificateRequest + + rest, err := asn1.Unmarshal(asn1Data, &csr) + if err != nil { + return nil, err + } else if len(rest) != 0 { + return nil, asn1.SyntaxError{Msg: "trailing data"} + } + + return parseCertificateRequest(&csr) +} + +func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error) { + out := &CertificateRequest{ + Raw: in.Raw, + RawTBSCertificateRequest: in.TBSCSR.Raw, + RawSubjectPublicKeyInfo: in.TBSCSR.PublicKey.Raw, + RawSubject: in.TBSCSR.Subject.FullBytes, + + Signature: in.SignatureValue.RightAlign(), + SignatureAlgorithm: getSignatureAlgorithmFromOID(in.SignatureAlgorithm.Algorithm), + + PublicKeyAlgorithm: getPublicKeyAlgorithmFromOID(in.TBSCSR.PublicKey.Algorithm.Algorithm), + + Version: in.TBSCSR.Version, + Attributes: in.TBSCSR.Attributes, + } + + var err error + out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCSR.PublicKey) + if err != nil { + return nil, err + } + + var subject pkix.RDNSequence + if _, err := asn1.Unmarshal(in.TBSCSR.Subject.FullBytes, &subject); err != nil { + return nil, err + } + + out.Subject.FillFromRDNSequence(&subject) + + var extensions []pkix.AttributeTypeAndValue + + for _, atvSet := range in.TBSCSR.Attributes { + if !atvSet.Type.Equal(oidExtensionRequest) { + continue + } + + for _, atvs := range atvSet.Value { + extensions = append(extensions, atvs...) + } + } + + out.Extensions = make([]pkix.Extension, 0, len(extensions)) + + for _, e := range extensions { + value, ok := e.Value.([]byte) + if !ok { + return nil, errors.New("x509: extension attribute contained non-OCTET STRING data") + } + + out.Extensions = append(out.Extensions, pkix.Extension{ + Id: e.Type, + Value: value, + }) + + if len(e.Type) == 4 && e.Type[0] == 2 && e.Type[1] == 5 && e.Type[2] == 29 { + switch e.Type[3] { + case 17: + out.DNSNames, out.EmailAddresses, out.IPAddresses, err = parseSANExtension(value) + if err != nil { + return nil, err + } + } + } + } + + return out, nil +} diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go index f1097e992e..4f1f0c2cc6 100644 --- a/libgo/go/crypto/x509/x509_test.go +++ b/libgo/go/crypto/x509/x509_test.go @@ -20,7 +20,9 @@ import ( "encoding/pem" "math/big" "net" + "os/exec" "reflect" + "runtime" "testing" "time" ) @@ -305,11 +307,12 @@ func TestCreateSelfSignedCertificate(t *testing.T) { name string pub, priv interface{} checkSig bool + sigAlgo SignatureAlgorithm }{ - {"RSA/RSA", &rsaPriv.PublicKey, rsaPriv, true}, - {"RSA/ECDSA", &rsaPriv.PublicKey, ecdsaPriv, false}, - {"ECDSA/RSA", &ecdsaPriv.PublicKey, rsaPriv, false}, - {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true}, + {"RSA/RSA", &rsaPriv.PublicKey, rsaPriv, true, SHA1WithRSA}, + {"RSA/ECDSA", &rsaPriv.PublicKey, ecdsaPriv, false, ECDSAWithSHA384}, + {"ECDSA/RSA", &ecdsaPriv.PublicKey, rsaPriv, false, SHA256WithRSA}, + {"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true, ECDSAWithSHA1}, } testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth} @@ -327,6 +330,8 @@ func TestCreateSelfSignedCertificate(t *testing.T) { NotBefore: time.Unix(1000, 0), NotAfter: time.Unix(100000, 0), + SignatureAlgorithm: test.sigAlgo, + SubjectKeyId: []byte{1, 2, 3, 4}, KeyUsage: KeyUsageCertSign, @@ -390,6 +395,10 @@ func TestCreateSelfSignedCertificate(t *testing.T) { t.Errorf("%s: issuer wasn't correctly copied from the template. Got %s, want %s", test.name, cert.Issuer.CommonName, commonName) } + if cert.SignatureAlgorithm != test.sigAlgo { + t.Errorf("%s: SignatureAlgorithm wasn't copied from template. Got %v, want %v", test.name, cert.SignatureAlgorithm, test.sigAlgo) + } + if !reflect.DeepEqual(cert.ExtKeyUsage, testExtKeyUsage) { t.Errorf("%s: extkeyusage wasn't correctly copied from the template. Got %v, want %v", test.name, cert.ExtKeyUsage, testExtKeyUsage) } @@ -671,11 +680,11 @@ func TestCRLCreation(t *testing.T) { func fromBase64(in string) []byte { out := make([]byte, base64.StdEncoding.DecodedLen(len(in))) - _, err := base64.StdEncoding.Decode(out, []byte(in)) + n, err := base64.StdEncoding.Decode(out, []byte(in)) if err != nil { panic("failed to base64 decode") } - return out + return out[:n] } func TestParseDERCRL(t *testing.T) { @@ -698,6 +707,17 @@ func TestParseDERCRL(t *testing.T) { // Can't check the signature here without a package cycle. } +func TestCRLWithoutExpiry(t *testing.T) { + derBytes := fromBase64("MIHYMIGZMAkGByqGSM44BAMwEjEQMA4GA1UEAxMHQ2FybERTUxcNOTkwODI3MDcwMDAwWjBpMBMCAgDIFw05OTA4MjIwNzAwMDBaMBMCAgDJFw05OTA4MjIwNzAwMDBaMBMCAgDTFw05OTA4MjIwNzAwMDBaMBMCAgDSFw05OTA4MjIwNzAwMDBaMBMCAgDUFw05OTA4MjQwNzAwMDBaMAkGByqGSM44BAMDLwAwLAIUfmVSdjP+NHMX0feW+aDU2G1cfT0CFAJ6W7fVWxjBz4fvftok8yqDnDWh") + certList, err := ParseDERCRL(derBytes) + if err != nil { + t.Fatal(err) + } + if !certList.TBSCertList.NextUpdate.IsZero() { + t.Errorf("NextUpdate is not the zero value") + } +} + func TestParsePEMCRL(t *testing.T) { pemBytes := fromBase64(pemCRLBase64) certList, err := ParseCRL(pemBytes) @@ -718,6 +738,291 @@ func TestParsePEMCRL(t *testing.T) { // Can't check the signature here without a package cycle. } +func TestImports(t *testing.T) { + t.Skip("gccgo does not have a go command") + switch runtime.GOOS { + case "android", "nacl": + t.Skipf("skipping on %s", runtime.GOOS) + } + + if err := exec.Command("go", "run", "x509_test_import.go").Run(); err != nil { + t.Errorf("failed to run x509_test_import.go: %s", err) + } +} + const derCRLBase64 = "MIINqzCCDJMCAQEwDQYJKoZIhvcNAQEFBQAwVjEZMBcGA1UEAxMQUEtJIEZJTk1FQ0NBTklDQTEVMBMGA1UEChMMRklOTUVDQ0FOSUNBMRUwEwYDVQQLEwxGSU5NRUNDQU5JQ0ExCzAJBgNVBAYTAklUFw0xMTA1MDQxNjU3NDJaFw0xMTA1MDQyMDU3NDJaMIIMBzAhAg4Ze1od49Lt1qIXBydAzhcNMDkwNzE2MDg0MzIyWjAAMCECDl0HSL9bcZ1Ci/UHJ0DPFw0wOTA3MTYwODQzMTNaMAAwIQIOESB9tVAmX3cY7QcnQNAXDTA5MDcxNjA4NDUyMlowADAhAg4S1tGAQ3mHt8uVBydA1RcNMDkwODA0MTUyNTIyWjAAMCECDlQ249Y7vtC25ScHJ0DWFw0wOTA4MDQxNTI1MzdaMAAwIQIOISMop3NkA4PfYwcnQNkXDTA5MDgwNDExMDAzNFowADAhAg56/BMoS29KEShTBydA2hcNMDkwODA0MTEwMTAzWjAAMCECDnBp/22HPH5CSWoHJ0DbFw0wOTA4MDQxMDU0NDlaMAAwIQIOV9IP+8CD8bK+XAcnQNwXDTA5MDgwNDEwNTcxN1owADAhAg4v5aRz0IxWqYiXBydA3RcNMDkwODA0MTA1NzQ1WjAAMCECDlOU34VzvZAybQwHJ0DeFw0wOTA4MDQxMDU4MjFaMAAwIAINO4CD9lluIxcwBydBAxcNMDkwNzIyMTUzMTU5WjAAMCECDgOllfO8Y1QA7/wHJ0ExFw0wOTA3MjQxMTQxNDNaMAAwIQIOJBX7jbiCdRdyjgcnQUQXDTA5MDkxNjA5MzAwOFowADAhAg5iYSAgmDrlH/RZBydBRRcNMDkwOTE2MDkzMDE3WjAAMCECDmu6k6srP3jcMaQHJ0FRFw0wOTA4MDQxMDU2NDBaMAAwIQIOX8aHlO0V+WVH4QcnQVMXDTA5MDgwNDEwNTcyOVowADAhAg5flK2rg3NnsRgDBydBzhcNMTEwMjAxMTUzMzQ2WjAAMCECDg35yJDL1jOPTgoHJ0HPFw0xMTAyMDExNTM0MjZaMAAwIQIOMyFJ6+e9iiGVBQcnQdAXDTA5MDkxODEzMjAwNVowADAhAg5Emb/Oykucmn8fBydB1xcNMDkwOTIxMTAxMDQ3WjAAMCECDjQKCncV+MnUavMHJ0HaFw0wOTA5MjIwODE1MjZaMAAwIQIOaxiFUt3dpd+tPwcnQfQXDTEwMDYxODA4NDI1MVowADAhAg5G7P8nO0tkrMt7BydB9RcNMTAwNjE4MDg0MjMwWjAAMCECDmTCC3SXhmDRst4HJ0H2Fw0wOTA5MjgxMjA3MjBaMAAwIQIOHoGhUr/pRwzTKgcnQfcXDTA5MDkyODEyMDcyNFowADAhAg50wrcrCiw8mQmPBydCBBcNMTAwMjE2MTMwMTA2WjAAMCECDifWmkvwyhEqwEcHJ0IFFw0xMDAyMTYxMzAxMjBaMAAwIQIOfgPmlW9fg+osNgcnQhwXDTEwMDQxMzA5NTIwMFowADAhAg4YHAGuA6LgCk7tBydCHRcNMTAwNDEzMDk1MTM4WjAAMCECDi1zH1bxkNJhokAHJ0IsFw0xMDA0MTMwOTU5MzBaMAAwIQIOMipNccsb/wo2fwcnQi0XDTEwMDQxMzA5NTkwMFowADAhAg46lCmvPl4GpP6ABydCShcNMTAwMTE5MDk1MjE3WjAAMCECDjaTcaj+wBpcGAsHJ0JLFw0xMDAxMTkwOTUyMzRaMAAwIQIOOMC13EOrBuxIOQcnQloXDTEwMDIwMTA5NDcwNVowADAhAg5KmZl+krz4RsmrBydCWxcNMTAwMjAxMDk0NjQwWjAAMCECDmLG3zQJ/fzdSsUHJ0JiFw0xMDAzMDEwOTUxNDBaMAAwIQIOP39ksgHdojf4owcnQmMXDTEwMDMwMTA5NTExN1owADAhAg4LDQzvWNRlD6v9BydCZBcNMTAwMzAxMDk0NjIyWjAAMCECDkmNfeclaFhIaaUHJ0JlFw0xMDAzMDEwOTQ2MDVaMAAwIQIOT/qWWfpH/m8NTwcnQpQXDTEwMDUxMTA5MTgyMVowADAhAg5m/ksYxvCEgJSvBydClRcNMTAwNTExMDkxODAxWjAAMCECDgvf3Ohq6JOPU9AHJ0KWFw0xMDA1MTEwOTIxMjNaMAAwIQIOKSPas10z4jNVIQcnQpcXDTEwMDUxMTA5MjEwMlowADAhAg4mCWmhoZ3lyKCDBydCohcNMTEwNDI4MTEwMjI1WjAAMCECDkeiyRsBMK0Gvr4HJ0KjFw0xMTA0MjgxMTAyMDdaMAAwIQIOa09b/nH2+55SSwcnQq4XDTExMDQwMTA4Mjk0NlowADAhAg5O7M7iq7gGplr1BydCrxcNMTEwNDAxMDgzMDE3WjAAMCECDjlT6mJxUjTvyogHJ0K1Fw0xMTAxMjcxNTQ4NTJaMAAwIQIODS/l4UUFLe21NAcnQrYXDTExMDEyNzE1NDgyOFowADAhAg5lPRA0XdOUF6lSBydDHhcNMTEwMTI4MTQzNTA1WjAAMCECDixKX4fFGGpENwgHJ0MfFw0xMTAxMjgxNDM1MzBaMAAwIQIORNBkqsPnpKTtbAcnQ08XDTEwMDkwOTA4NDg0MlowADAhAg5QL+EMM3lohedEBydDUBcNMTAwOTA5MDg0ODE5WjAAMCECDlhDnHK+HiTRAXcHJ0NUFw0xMDEwMTkxNjIxNDBaMAAwIQIOdBFqAzq/INz53gcnQ1UXDTEwMTAxOTE2MjA0NFowADAhAg4OjR7s8MgKles1BydDWhcNMTEwMTI3MTY1MzM2WjAAMCECDmfR/elHee+d0SoHJ0NbFw0xMTAxMjcxNjUzNTZaMAAwIQIOBTKv2ui+KFMI+wcnQ5YXDTEwMDkxNTEwMjE1N1owADAhAg49F3c/GSah+oRUBydDmxcNMTEwMTI3MTczMjMzWjAAMCECDggv4I61WwpKFMMHJ0OcFw0xMTAxMjcxNzMyNTVaMAAwIQIOXx/Y8sEvwS10LAcnQ6UXDTExMDEyODExMjkzN1owADAhAg5LSLbnVrSKaw/9BydDphcNMTEwMTI4MTEyOTIwWjAAMCECDmFFoCuhKUeACQQHJ0PfFw0xMTAxMTExMDE3MzdaMAAwIQIOQTDdFh2fSPF6AAcnQ+AXDTExMDExMTEwMTcxMFowADAhAg5B8AOXX61FpvbbBydD5RcNMTAxMDA2MTAxNDM2WjAAMCECDh41P2Gmi7PkwI4HJ0PmFw0xMDEwMDYxMDE2MjVaMAAwIQIOWUHGLQCd+Ale9gcnQ/0XDTExMDUwMjA3NTYxMFowADAhAg5Z2c9AYkikmgWOBydD/hcNMTEwNTAyMDc1NjM0WjAAMCECDmf/UD+/h8nf+74HJ0QVFw0xMTA0MTUwNzI4MzNaMAAwIQIOICvj4epy3MrqfwcnRBYXDTExMDQxNTA3Mjg1NlowADAhAg4bouRMfOYqgv4xBydEHxcNMTEwMzA4MTYyNDI1WjAAMCECDhebWHGoKiTp7pEHJ0QgFw0xMTAzMDgxNjI0NDhaMAAwIQIOX+qnxxAqJ8LtawcnRDcXDTExMDEzMTE1MTIyOFowADAhAg4j0fICqZ+wkOdqBydEOBcNMTEwMTMxMTUxMTQxWjAAMCECDhmXjsV4SUpWtAMHJ0RLFw0xMTAxMjgxMTI0MTJaMAAwIQIODno/w+zG43kkTwcnREwXDTExMDEyODExMjM1MlowADAhAg4b1gc88767Fr+LBydETxcNMTEwMTI4MTEwMjA4WjAAMCECDn+M3Pa1w2nyFeUHJ0RQFw0xMTAxMjgxMDU4NDVaMAAwIQIOaduoyIH61tqybAcnRJUXDTEwMTIxNTA5NDMyMlowADAhAg4nLqQPkyi3ESAKBydElhcNMTAxMjE1MDk0MzM2WjAAMCECDi504NIMH8578gQHJ0SbFw0xMTAyMTQxNDA1NDFaMAAwIQIOGuaM8PDaC5u1egcnRJwXDTExMDIxNDE0MDYwNFowADAhAg4ehYq/BXGnB5PWBydEnxcNMTEwMjA0MDgwOTUxWjAAMCECDkSD4eS4FxW5H20HJ0SgFw0xMTAyMDQwODA5MjVaMAAwIQIOOCcb6ilYObt1egcnRKEXDTExMDEyNjEwNDEyOVowADAhAg58tISWCCwFnKGnBydEohcNMTEwMjA0MDgxMzQyWjAAMCECDn5rjtabY/L/WL0HJ0TJFw0xMTAyMDQxMTAzNDFaMAAwDQYJKoZIhvcNAQEFBQADggEBAGnF2Gs0+LNiYCW1Ipm83OXQYP/bd5tFFRzyz3iepFqNfYs4D68/QihjFoRHQoXEB0OEe1tvaVnnPGnEOpi6krwekquMxo4H88B5SlyiFIqemCOIss0SxlCFs69LmfRYvPPvPEhoXtQ3ZThe0UvKG83GOklhvGl6OaiRf4Mt+m8zOT4Wox/j6aOBK6cw6qKCdmD+Yj1rrNqFGg1CnSWMoD6S6mwNgkzwdBUJZ22BwrzAAo4RHa2Uy3ef1FjwD0XtU5N3uDSxGGBEDvOe5z82rps3E22FpAA8eYl8kaXtmWqyvYU0epp4brGuTxCuBMCAsxt/OjIjeNNQbBGkwxgfYA0=" const pemCRLBase64 = "LS0tLS1CRUdJTiBYNTA5IENSTC0tLS0tDQpNSUlCOWpDQ0FWOENBUUV3RFFZSktvWklodmNOQVFFRkJRQXdiREVhTUJnR0ExVUVDaE1SVWxOQklGTmxZM1Z5DQphWFI1SUVsdVl5NHhIakFjQmdOVkJBTVRGVkpUUVNCUWRXSnNhV01nVW05dmRDQkRRU0IyTVRFdU1Dd0dDU3FHDQpTSWIzRFFFSkFSWWZjbk5oYTJWdmJuSnZiM1J6YVdkdVFISnpZWE5sWTNWeWFYUjVMbU52YlJjTk1URXdNakl6DQpNVGt5T0RNd1doY05NVEV3T0RJeU1Ua3lPRE13V2pDQmpEQktBaEVBckRxb2g5RkhKSFhUN09QZ3V1bjQrQmNODQpNRGt4TVRBeU1UUXlOekE1V2pBbU1Bb0dBMVVkRlFRRENnRUpNQmdHQTFVZEdBUVJHQTh5TURBNU1URXdNakUwDQpNalExTlZvd1BnSVJBTEd6blowOTVQQjVhQU9MUGc1N2ZNTVhEVEF5TVRBeU16RTBOVEF4TkZvd0dqQVlCZ05WDQpIUmdFRVJnUE1qQXdNakV3TWpNeE5EVXdNVFJhb0RBd0xqQWZCZ05WSFNNRUdEQVdnQlQxVERGNlVRTS9MTmVMDQpsNWx2cUhHUXEzZzltekFMQmdOVkhSUUVCQUlDQUlRd0RRWUpLb1pJaHZjTkFRRUZCUUFEZ1lFQUZVNUFzNk16DQpxNVBSc2lmYW9iUVBHaDFhSkx5QytNczVBZ2MwYld5QTNHQWR4dXI1U3BQWmVSV0NCamlQL01FSEJXSkNsQkhQDQpHUmNxNXlJZDNFakRrYUV5eFJhK2k2N0x6dmhJNmMyOUVlNks5cFNZd2ppLzdSVWhtbW5Qclh0VHhsTDBsckxyDQptUVFKNnhoRFJhNUczUUE0Q21VZHNITnZicnpnbUNZcHZWRT0NCi0tLS0tRU5EIFg1MDkgQ1JMLS0tLS0NCg0K" + +func TestCreateCertificateRequest(t *testing.T) { + random := rand.Reader + + block, _ := pem.Decode([]byte(pemPrivateKey)) + rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + t.Fatalf("Failed to parse private key: %s", err) + } + + ecdsa256Priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatalf("Failed to generate ECDSA key: %s", err) + } + + ecdsa384Priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + t.Fatalf("Failed to generate ECDSA key: %s", err) + } + + ecdsa521Priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) + if err != nil { + t.Fatalf("Failed to generate ECDSA key: %s", err) + } + + tests := []struct { + name string + priv interface{} + sigAlgo SignatureAlgorithm + }{ + {"RSA", rsaPriv, SHA1WithRSA}, + {"ECDSA-256", ecdsa256Priv, ECDSAWithSHA1}, + {"ECDSA-384", ecdsa384Priv, ECDSAWithSHA1}, + {"ECDSA-521", ecdsa521Priv, ECDSAWithSHA1}, + } + + for _, test := range tests { + template := CertificateRequest{ + Subject: pkix.Name{ + CommonName: "test.example.com", + Organization: []string{"Σ Acme Co"}, + }, + SignatureAlgorithm: test.sigAlgo, + DNSNames: []string{"test.example.com"}, + EmailAddresses: []string{"gopher@golang.org"}, + IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")}, + } + + derBytes, err := CreateCertificateRequest(random, &template, test.priv) + if err != nil { + t.Errorf("%s: failed to create certificate request: %s", test.name, err) + continue + } + + out, err := ParseCertificateRequest(derBytes) + if err != nil { + t.Errorf("%s: failed to create certificate request: %s", test.name, err) + continue + } + + if out.Subject.CommonName != template.Subject.CommonName { + t.Errorf("%s: output subject common name and template subject common name don't match", test.name) + } else if len(out.Subject.Organization) != len(template.Subject.Organization) { + t.Errorf("%s: output subject organisation and template subject organisation don't match", test.name) + } else if len(out.DNSNames) != len(template.DNSNames) { + t.Errorf("%s: output DNS names and template DNS names don't match", test.name) + } else if len(out.EmailAddresses) != len(template.EmailAddresses) { + t.Errorf("%s: output email addresses and template email addresses don't match", test.name) + } else if len(out.IPAddresses) != len(template.IPAddresses) { + t.Errorf("%s: output IP addresses and template IP addresses names don't match", test.name) + } + } +} + +func marshalAndParseCSR(t *testing.T, template *CertificateRequest) *CertificateRequest { + block, _ := pem.Decode([]byte(pemPrivateKey)) + rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + t.Fatal(err) + } + + derBytes, err := CreateCertificateRequest(rand.Reader, template, rsaPriv) + if err != nil { + t.Fatal(err) + } + + csr, err := ParseCertificateRequest(derBytes) + if err != nil { + t.Fatal(err) + } + + return csr +} + +func TestCertificateRequestOverrides(t *testing.T) { + sanContents, err := marshalSANs([]string{"foo.example.com"}, nil, nil) + if err != nil { + t.Fatal(err) + } + + template := CertificateRequest{ + Subject: pkix.Name{ + CommonName: "test.example.com", + Organization: []string{"Σ Acme Co"}, + }, + DNSNames: []string{"test.example.com"}, + + // An explicit extension should override the DNSNames from the + // template. + ExtraExtensions: []pkix.Extension{ + { + Id: oidExtensionSubjectAltName, + Value: sanContents, + }, + }, + } + + csr := marshalAndParseCSR(t, &template) + + if len(csr.DNSNames) != 1 || csr.DNSNames[0] != "foo.example.com" { + t.Errorf("Extension did not override template. Got %v\n", csr.DNSNames) + } + + // If there is already an attribute with X.509 extensions then the + // extra extensions should be added to it rather than creating a CSR + // with two extension attributes. + + template.Attributes = []pkix.AttributeTypeAndValueSET{ + { + Type: oidExtensionRequest, + Value: [][]pkix.AttributeTypeAndValue{ + { + { + Type: oidExtensionAuthorityInfoAccess, + Value: []byte("foo"), + }, + }, + }, + }, + } + + csr = marshalAndParseCSR(t, &template) + if l := len(csr.Attributes); l != 1 { + t.Errorf("incorrect number of attributes: %d\n", l) + } + + if !csr.Attributes[0].Type.Equal(oidExtensionRequest) || + len(csr.Attributes[0].Value) != 1 || + len(csr.Attributes[0].Value[0]) != 2 { + t.Errorf("bad attributes: %#v\n", csr.Attributes) + } + + sanContents2, err := marshalSANs([]string{"foo2.example.com"}, nil, nil) + if err != nil { + t.Fatal(err) + } + + // Extensions in Attributes should override those in ExtraExtensions. + template.Attributes[0].Value[0] = append(template.Attributes[0].Value[0], pkix.AttributeTypeAndValue{ + Type: oidExtensionSubjectAltName, + Value: sanContents2, + }) + + csr = marshalAndParseCSR(t, &template) + + if len(csr.DNSNames) != 1 || csr.DNSNames[0] != "foo2.example.com" { + t.Errorf("Attributes did not override ExtraExtensions. Got %v\n", csr.DNSNames) + } +} + +func TestParseCertificateRequest(t *testing.T) { + csrBytes := fromBase64(csrBase64) + csr, err := ParseCertificateRequest(csrBytes) + if err != nil { + t.Fatalf("failed to parse CSR: %s", err) + } + + if len(csr.EmailAddresses) != 1 || csr.EmailAddresses[0] != "gopher@golang.org" { + t.Errorf("incorrect email addresses found: %v", csr.EmailAddresses) + } + + if len(csr.DNSNames) != 1 || csr.DNSNames[0] != "test.example.com" { + t.Errorf("incorrect DNS names found: %v", csr.DNSNames) + } + + if len(csr.Subject.Country) != 1 || csr.Subject.Country[0] != "AU" { + t.Errorf("incorrect Subject name: %v", csr.Subject) + } + + found := false + for _, e := range csr.Extensions { + if e.Id.Equal(oidExtensionBasicConstraints) { + found = true + break + } + } + if !found { + t.Errorf("basic constraints extension not found in CSR") + } +} + +func TestMaxPathLen(t *testing.T) { + block, _ := pem.Decode([]byte(pemPrivateKey)) + rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + t.Fatalf("Failed to parse private key: %s", err) + } + + template := &Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "Σ Acme Co", + }, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(100000, 0), + + BasicConstraintsValid: true, + IsCA: true, + } + + serialiseAndParse := func(template *Certificate) *Certificate { + derBytes, err := CreateCertificate(rand.Reader, template, template, &rsaPriv.PublicKey, rsaPriv) + if err != nil { + t.Fatalf("failed to create certificate: %s", err) + return nil + } + + cert, err := ParseCertificate(derBytes) + if err != nil { + t.Fatalf("failed to parse certificate: %s", err) + return nil + } + + return cert + } + + cert1 := serialiseAndParse(template) + if m := cert1.MaxPathLen; m != -1 { + t.Errorf("Omitting MaxPathLen didn't turn into -1, got %d", m) + } + if cert1.MaxPathLenZero { + t.Errorf("Omitting MaxPathLen resulted in MaxPathLenZero") + } + + template.MaxPathLen = 1 + cert2 := serialiseAndParse(template) + if m := cert2.MaxPathLen; m != 1 { + t.Errorf("Setting MaxPathLen didn't work. Got %d but set 1", m) + } + if cert2.MaxPathLenZero { + t.Errorf("Setting MaxPathLen resulted in MaxPathLenZero") + } + + template.MaxPathLen = 0 + template.MaxPathLenZero = true + cert3 := serialiseAndParse(template) + if m := cert3.MaxPathLen; m != 0 { + t.Errorf("Setting MaxPathLenZero didn't work, got %d", m) + } + if !cert3.MaxPathLenZero { + t.Errorf("Setting MaxPathLen to zero didn't result in MaxPathLenZero") + } +} + +// This CSR was generated with OpenSSL: +// openssl req -out CSR.csr -new -newkey rsa:2048 -nodes -keyout privateKey.key -config openssl.cnf +// +// The openssl.cnf needs to include this section: +// [ v3_req ] +// basicConstraints = CA:FALSE +// keyUsage = nonRepudiation, digitalSignature, keyEncipherment +// subjectAltName = email:gopher@golang.org,DNS:test.example.com +const csrBase64 = "MIIC4zCCAcsCAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOY+MVedRg2JEnyeLcSzcsMv2VcsTfkB5+Etd6hihAh6MrGezNyASMMKuQN6YhCX1icQDiQtGsDLTtheNnSXK06tAhHjAP/hGlszRJp+5+rP2M58fDBAkUBEhskbCUWwpY14jFtVuGNJ8vF8h8IeczdolvQhX9lVai9G0EUXJMliMKdjA899H0mRs9PzHyidyrXFNiZlQXfD8Kg7gETn2Ny965iyI6ujAIYSCvam6TnxRHYH2MBKyVGvsYGbPYUQJCsgdgyajEg6ekihvQY3SzO1HSAlZAd7d1QYO4VeWJ2mY6Wu3Jpmh+AmG19S9CcHqGjd0bhuAX9cpPOKgnEmqn0CAwEAAaBZMFcGCSqGSIb3DQEJDjFKMEgwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwLgYDVR0RBCcwJYERZ29waGVyQGdvbGFuZy5vcmeCEHRlc3QuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQEFBQADggEBAC9+QpKfdabxwCWwf4IEe1cKjdXLS1ScSuw27a3kZzQiPV78WJMa6dB8dqhdH5BRwGZ/qsgLrO6ZHlNeIv2Ib41Ccq71ecHW/nXc94A1BzJ/bVdI9LZcmTUvR1/m1jCpN7UqQ0ml1u9VihK7Pe762hEYxuWDQzYEU0l15S/bXmqeq3eF1A59XT/2jwe5+NV0Wwf4UQlkTXsAQMsJ+KzrQafd8Qv2A49o048uRvmjeJDrXLawGVianZ7D5A6Fpd1rZh6XcjqBpmgLw41DRQWENOdzhy+HyphKRv1MlY8OLkNqpGMhu8DdgJVGoT16DGiickoEa7Z3UCPVNgdTkT9jq7U=" diff --git a/libgo/go/crypto/x509/x509_test_import.go b/libgo/go/crypto/x509/x509_test_import.go new file mode 100644 index 0000000000..3fda7da188 --- /dev/null +++ b/libgo/go/crypto/x509/x509_test_import.go @@ -0,0 +1,53 @@ +// 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. + +// +build ignore + +// This file is run by the x509 tests to ensure that a program with minimal +// imports can sign certificates without errors resulting from missing hash +// functions. +package main + +import ( + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "math/big" + "time" +) + +func main() { + block, _ := pem.Decode([]byte(pemPrivateKey)) + rsaPriv, err := x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + panic("Failed to parse private key: " + err.Error()) + } + + template := x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "test", + Organization: []string{"Σ Acme Co"}, + }, + NotBefore: time.Unix(1000, 0), + NotAfter: time.Unix(100000, 0), + KeyUsage: x509.KeyUsageCertSign, + } + + if _, err = x509.CreateCertificate(rand.Reader, &template, &template, &rsaPriv.PublicKey, rsaPriv); err != nil { + panic("failed to create certificate with basic imports: " + err.Error()) + } +} + +var pemPrivateKey = `-----BEGIN RSA PRIVATE KEY----- +MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 +fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu +/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu +RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/ +EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A +IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS +tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V +-----END RSA PRIVATE KEY----- +` diff --git a/libgo/go/database/sql/convert.go b/libgo/go/database/sql/convert.go index c04adde1fc..c0b38a2494 100644 --- a/libgo/go/database/sql/convert.go +++ b/libgo/go/database/sql/convert.go @@ -160,27 +160,19 @@ func convertAssign(dest, src interface{}) error { reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64: - *d = fmt.Sprintf("%v", src) + *d = asString(src) return nil } case *[]byte: sv = reflect.ValueOf(src) - switch sv.Kind() { - case reflect.Bool, - reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, - reflect.Float32, reflect.Float64: - *d = []byte(fmt.Sprintf("%v", src)) + if b, ok := asBytes(nil, sv); ok { + *d = b return nil } case *RawBytes: sv = reflect.ValueOf(src) - switch sv.Kind() { - case reflect.Bool, - reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, - reflect.Float32, reflect.Float64: - *d = RawBytes(fmt.Sprintf("%v", src)) + if b, ok := asBytes([]byte(*d)[:0], sv); ok { + *d = RawBytes(b) return nil } case *bool: @@ -271,5 +263,37 @@ func asString(src interface{}) string { case []byte: return string(v) } + rv := reflect.ValueOf(src) + switch rv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return strconv.FormatInt(rv.Int(), 10) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return strconv.FormatUint(rv.Uint(), 10) + case reflect.Float64: + return strconv.FormatFloat(rv.Float(), 'g', -1, 64) + case reflect.Float32: + return strconv.FormatFloat(rv.Float(), 'g', -1, 32) + case reflect.Bool: + return strconv.FormatBool(rv.Bool()) + } return fmt.Sprintf("%v", src) } + +func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) { + switch rv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return strconv.AppendInt(buf, rv.Int(), 10), true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return strconv.AppendUint(buf, rv.Uint(), 10), true + case reflect.Float32: + return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true + case reflect.Float64: + return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true + case reflect.Bool: + return strconv.AppendBool(buf, rv.Bool()), true + case reflect.String: + s := rv.String() + return append(buf, s...), true + } + return +} diff --git a/libgo/go/database/sql/convert_test.go b/libgo/go/database/sql/convert_test.go index a39c2c54fb..98af9fb64c 100644 --- a/libgo/go/database/sql/convert_test.go +++ b/libgo/go/database/sql/convert_test.go @@ -8,6 +8,7 @@ import ( "database/sql/driver" "fmt" "reflect" + "runtime" "testing" "time" ) @@ -279,3 +280,69 @@ func TestValueConverters(t *testing.T) { } } } + +// Tests that assigning to RawBytes doesn't allocate (and also works). +func TestRawBytesAllocs(t *testing.T) { + var tests = []struct { + name string + in interface{} + want string + }{ + {"uint64", uint64(12345678), "12345678"}, + {"uint32", uint32(1234), "1234"}, + {"uint16", uint16(12), "12"}, + {"uint8", uint8(1), "1"}, + {"uint", uint(123), "123"}, + {"int", int(123), "123"}, + {"int8", int8(1), "1"}, + {"int16", int16(12), "12"}, + {"int32", int32(1234), "1234"}, + {"int64", int64(12345678), "12345678"}, + {"float32", float32(1.5), "1.5"}, + {"float64", float64(64), "64"}, + {"bool", false, "false"}, + } + + buf := make(RawBytes, 10) + test := func(name string, in interface{}, want string) { + if err := convertAssign(&buf, in); err != nil { + t.Fatalf("%s: convertAssign = %v", name, err) + } + match := len(buf) == len(want) + if match { + for i, b := range buf { + if want[i] != b { + match = false + break + } + } + } + if !match { + t.Fatalf("%s: got %q (len %d); want %q (len %d)", name, buf, len(buf), want, len(want)) + } + } + + n := testing.AllocsPerRun(100, func() { + for _, tt := range tests { + test(tt.name, tt.in, tt.want) + } + }) + + // The numbers below are only valid for 64-bit interface word sizes, + // and gc. With 32-bit words there are more convT2E allocs, and + // with gccgo, only pointers currently go in interface data. + // So only care on amd64 gc for now. + measureAllocs := runtime.GOARCH == "amd64" && runtime.Compiler == "gc" + + if n > 0.5 && measureAllocs { + t.Fatalf("allocs = %v; want 0", n) + } + + // This one involves a convT2E allocation, string -> interface{} + n = testing.AllocsPerRun(100, func() { + test("string", "foo", "foo") + }) + if n > 1.5 && measureAllocs { + t.Fatalf("allocs = %v; want max 1", n) + } +} diff --git a/libgo/go/database/sql/driver/driver.go b/libgo/go/database/sql/driver/driver.go index 0828e63c65..eca25f29a0 100644 --- a/libgo/go/database/sql/driver/driver.go +++ b/libgo/go/database/sql/driver/driver.go @@ -134,7 +134,7 @@ type Stmt interface { // as an INSERT or UPDATE. Exec(args []Value) (Result, error) - // Exec executes a query that may return rows, such as a + // Query executes a query that may return rows, such as a // SELECT. Query(args []Value) (Rows, error) } diff --git a/libgo/go/database/sql/fakedb_test.go b/libgo/go/database/sql/fakedb_test.go index a8adfdd942..a993fd46ed 100644 --- a/libgo/go/database/sql/fakedb_test.go +++ b/libgo/go/database/sql/fakedb_test.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "log" + "sort" "strconv" "strings" "sync" @@ -23,7 +24,7 @@ var _ = log.Printf // interface, just for testing. // // It speaks a query language that's semantically similar to but -// syntantically different and simpler than SQL. The syntax is as +// syntactically different and simpler than SQL. The syntax is as // follows: // // WIPE @@ -126,6 +127,29 @@ func init() { Register("test", fdriver) } +func contains(list []string, y string) bool { + for _, x := range list { + if x == y { + return true + } + } + return false +} + +type Dummy struct { + driver.Driver +} + +func TestDrivers(t *testing.T) { + unregisterAllDrivers() + Register("test", fdriver) + Register("invalid", Dummy{}) + all := Drivers() + if len(all) < 2 || !sort.StringsAreSorted(all) || !contains(all, "test") || !contains(all, "invalid") { + t.Fatalf("Drivers = %v, want sorted list with at least [invalid, test]", all) + } +} + // Supports dsn forms: // // ; (only currently supported option is `badConn`, @@ -433,11 +457,19 @@ func (c *fakeConn) prepareInsert(stmt *fakeStmt, parts []string) (driver.Stmt, e return stmt, nil } +// hook to simulate broken connections +var hookPrepareBadConn func() bool + func (c *fakeConn) Prepare(query string) (driver.Stmt, error) { c.numPrepare++ if c.db == nil { panic("nil c.db; conn = " + fmt.Sprintf("%#v", c)) } + + if hookPrepareBadConn != nil && hookPrepareBadConn() { + return nil, driver.ErrBadConn + } + parts := strings.Split(query, "|") if len(parts) < 1 { return nil, errf("empty query") @@ -489,10 +521,18 @@ func (s *fakeStmt) Close() error { var errClosed = errors.New("fakedb: statement has been closed") +// hook to simulate broken connections +var hookExecBadConn func() bool + func (s *fakeStmt) Exec(args []driver.Value) (driver.Result, error) { if s.closed { return nil, errClosed } + + if hookExecBadConn != nil && hookExecBadConn() { + return nil, driver.ErrBadConn + } + err := checkSubsetTypes(args) if err != nil { return nil, err @@ -565,10 +605,18 @@ func (s *fakeStmt) execInsert(args []driver.Value, doInsert bool) (driver.Result return driver.RowsAffected(1), nil } +// hook to simulate broken connections +var hookQueryBadConn func() bool + func (s *fakeStmt) Query(args []driver.Value) (driver.Rows, error) { if s.closed { return nil, errClosed } + + if hookQueryBadConn != nil && hookQueryBadConn() { + return nil, driver.ErrBadConn + } + err := checkSubsetTypes(args) if err != nil { return nil, err @@ -686,7 +734,13 @@ func (rc *rowsCursor) Columns() []string { return rc.cols } +var rowsCursorNextHook func(dest []driver.Value) error + func (rc *rowsCursor) Next(dest []driver.Value) error { + if rowsCursorNextHook != nil { + return rowsCursorNextHook(dest) + } + if rc.closed { return errors.New("fakedb: cursor is closed") } diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go index 84a0965132..6e6f246aee 100644 --- a/libgo/go/database/sql/sql.go +++ b/libgo/go/database/sql/sql.go @@ -13,12 +13,12 @@ package sql import ( - "container/list" "database/sql/driver" "errors" "fmt" "io" "runtime" + "sort" "sync" ) @@ -37,6 +37,21 @@ func Register(name string, driver driver.Driver) { drivers[name] = driver } +func unregisterAllDrivers() { + // For tests. + drivers = make(map[string]driver.Driver) +} + +// Drivers returns a sorted list of the names of the registered drivers. +func Drivers() []string { + var list []string + for name := range drivers { + list = append(list, name) + } + sort.Strings(list) + return list +} + // RawBytes is a byte slice that holds a reference to memory owned by // the database itself. After a Scan into a RawBytes, the slice is only // valid until the next call to Next, Scan, or Close. @@ -181,7 +196,8 @@ type Scanner interface { // defers this error until a Scan. var ErrNoRows = errors.New("sql: no rows in result set") -// DB is a database handle. It's safe for concurrent use by multiple +// DB is a database handle representing a pool of zero or more +// underlying connections. It's safe for concurrent use by multiple // goroutines. // // The sql package creates and frees connections automatically; it @@ -197,8 +213,8 @@ type DB struct { dsn string mu sync.Mutex // protects following fields - freeConn *list.List // of *driverConn - connRequests *list.List // of connRequest + freeConn []*driverConn + connRequests []chan connRequest numOpen int pendingOpens int // Used to signal the need for new connections @@ -231,9 +247,6 @@ type driverConn struct { inUse bool onPut []func() // code (with db.mu held) run when conn is next returned dbmuClosed bool // same as closed, but guarded by db.mu, for connIfFree - // This is the Element returned by db.freeConn.PushFront(conn). - // It's used by connIfFree to remove the conn from the freeConn list. - listElem *list.Element } func (dc *driverConn) releaseConn(err error) { @@ -256,7 +269,7 @@ func (dc *driverConn) prepareLocked(query string) (driver.Stmt, error) { // stmt closes if the conn is about to close anyway? For now // do the safe thing, in case stmts need to be closed. // - // TODO(bradfitz): after Go 1.1, closing driver.Stmts + // TODO(bradfitz): after Go 1.2, closing driver.Stmts // should be moved to driverStmt, using unique // *driverStmts everywhere (including from // *Stmt.connStmt, instead of returning a @@ -405,7 +418,7 @@ func (db *DB) removeDepLocked(x finalCloser, dep interface{}) func() error { // This value should be larger than the maximum typical value // used for db.maxOpen. If maxOpen is significantly larger than // connectionRequestQueueSize then it is possible for ALL calls into the *DB -// to block until the connectionOpener can satify the backlog of requests. +// to block until the connectionOpener can satisfy the backlog of requests. var connectionRequestQueueSize = 1000000 // Open opens a database specified by its database driver name and a @@ -420,6 +433,11 @@ var connectionRequestQueueSize = 1000000 // Open may just validate its arguments without creating a connection // to the database. To verify that the data source name is valid, call // Ping. +// +// The returned DB is safe for concurrent use by multiple goroutines +// and maintains its own pool of idle connections. Thus, the Open +// function should be called just once. It is rarely necessary to +// close a DB. func Open(driverName, dataSourceName string) (*DB, error) { driveri, ok := drivers[driverName] if !ok { @@ -431,8 +449,6 @@ func Open(driverName, dataSourceName string) (*DB, error) { openerCh: make(chan struct{}, connectionRequestQueueSize), lastPut: make(map[*driverConn]string), } - db.freeConn = list.New() - db.connRequests = list.New() go db.connectionOpener() return db, nil } @@ -452,6 +468,9 @@ func (db *DB) Ping() error { } // Close closes the database, releasing any open resources. +// +// It is rare to Close a DB, as the DB handle is meant to be +// long-lived and shared between many goroutines. func (db *DB) Close() error { db.mu.Lock() if db.closed { // Make DB.Close idempotent @@ -460,17 +479,13 @@ func (db *DB) Close() error { } close(db.openerCh) var err error - fns := make([]func() error, 0, db.freeConn.Len()) - for db.freeConn.Front() != nil { - dc := db.freeConn.Front().Value.(*driverConn) - dc.listElem = nil + fns := make([]func() error, 0, len(db.freeConn)) + for _, dc := range db.freeConn { fns = append(fns, dc.closeDBLocked()) - db.freeConn.Remove(db.freeConn.Front()) } + db.freeConn = nil db.closed = true - for db.connRequests.Front() != nil { - req := db.connRequests.Front().Value.(connRequest) - db.connRequests.Remove(db.connRequests.Front()) + for _, req := range db.connRequests { close(req) } db.mu.Unlock() @@ -518,11 +533,11 @@ func (db *DB) SetMaxIdleConns(n int) { db.maxIdle = db.maxOpen } var closing []*driverConn - for db.freeConn.Len() > db.maxIdleConnsLocked() { - dc := db.freeConn.Back().Value.(*driverConn) - dc.listElem = nil - db.freeConn.Remove(db.freeConn.Back()) - closing = append(closing, dc) + idleCount := len(db.freeConn) + maxIdle := db.maxIdleConnsLocked() + if idleCount > maxIdle { + closing = db.freeConn[maxIdle:] + db.freeConn = db.freeConn[:maxIdle] } db.mu.Unlock() for _, c := range closing { @@ -555,7 +570,7 @@ func (db *DB) SetMaxOpenConns(n int) { // If there are connRequests and the connection limit hasn't been reached, // then tell the connectionOpener to open new connections. func (db *DB) maybeOpenNewConnections() { - numRequests := db.connRequests.Len() - db.pendingOpens + numRequests := len(db.connRequests) - db.pendingOpens if db.maxOpen > 0 { numCanOpen := db.maxOpen - (db.numOpen + db.pendingOpens) if numRequests > numCanOpen { @@ -569,9 +584,9 @@ func (db *DB) maybeOpenNewConnections() { } } -// Runs in a seperate goroutine, opens new connections when requested. +// Runs in a separate goroutine, opens new connections when requested. func (db *DB) connectionOpener() { - for _ = range db.openerCh { + for range db.openerCh { db.openNewConnection() } } @@ -607,7 +622,10 @@ func (db *DB) openNewConnection() { // connRequest represents one request for a new connection // When there are no idle connections available, DB.conn will create // a new connRequest and put it on the db.connRequests list. -type connRequest chan<- interface{} // takes either a *driverConn or an error +type connRequest struct { + conn *driverConn + err error +} var errDBClosed = errors.New("sql: database is closed") @@ -621,44 +639,36 @@ func (db *DB) conn() (*driverConn, error) { // If db.maxOpen > 0 and the number of open connections is over the limit // and there are no free connection, make a request and wait. - if db.maxOpen > 0 && db.numOpen >= db.maxOpen && db.freeConn.Len() == 0 { + if db.maxOpen > 0 && db.numOpen >= db.maxOpen && len(db.freeConn) == 0 { // Make the connRequest channel. It's buffered so that the // connectionOpener doesn't block while waiting for the req to be read. - ch := make(chan interface{}, 1) - req := connRequest(ch) - db.connRequests.PushBack(req) + req := make(chan connRequest, 1) + db.connRequests = append(db.connRequests, req) db.maybeOpenNewConnections() db.mu.Unlock() - ret, ok := <-ch - if !ok { - return nil, errDBClosed - } - switch ret.(type) { - case *driverConn: - return ret.(*driverConn), nil - case error: - return nil, ret.(error) - default: - panic("sql: Unexpected type passed through connRequest.ch") - } + ret := <-req + return ret.conn, ret.err } - if f := db.freeConn.Front(); f != nil { - conn := f.Value.(*driverConn) - conn.listElem = nil - db.freeConn.Remove(f) + if c := len(db.freeConn); c > 0 { + conn := db.freeConn[0] + copy(db.freeConn, db.freeConn[1:]) + db.freeConn = db.freeConn[:c-1] conn.inUse = true db.mu.Unlock() return conn, nil } + db.numOpen++ // optimistically db.mu.Unlock() ci, err := db.driver.Open(db.dsn) if err != nil { + db.mu.Lock() + db.numOpen-- // correct for earlier optimism + db.mu.Unlock() return nil, err } db.mu.Lock() - db.numOpen++ dc := &driverConn{ db: db, ci: ci, @@ -690,9 +700,15 @@ func (db *DB) connIfFree(wanted *driverConn) (*driverConn, error) { if wanted.inUse { return nil, errConnBusy } - if wanted.listElem != nil { - db.freeConn.Remove(wanted.listElem) - wanted.listElem = nil + idx := -1 + for ii, v := range db.freeConn { + if v == wanted { + idx = ii + break + } + } + if idx >= 0 { + db.freeConn = append(db.freeConn[:idx], db.freeConn[idx+1:]...) wanted.inUse = true return wanted, nil } @@ -774,37 +790,46 @@ func (db *DB) putConn(dc *driverConn, err error) { // Satisfy a connRequest or put the driverConn in the idle pool and return true // or return false. // putConnDBLocked will satisfy a connRequest if there is one, or it will -// return the *driverConn to the freeConn list if err != nil and the idle -// connection limit would not be reached. +// return the *driverConn to the freeConn list if err == nil and the idle +// connection limit will not be exceeded. // If err != nil, the value of dc is ignored. // If err == nil, then dc must not equal nil. -// If a connRequest was fullfilled or the *driverConn was placed in the +// If a connRequest was fulfilled or the *driverConn was placed in the // freeConn list, then true is returned, otherwise false is returned. func (db *DB) putConnDBLocked(dc *driverConn, err error) bool { - if db.connRequests.Len() > 0 { - req := db.connRequests.Front().Value.(connRequest) - db.connRequests.Remove(db.connRequests.Front()) - if err != nil { - req <- err - } else { + if c := len(db.connRequests); c > 0 { + req := db.connRequests[0] + // This copy is O(n) but in practice faster than a linked list. + // TODO: consider compacting it down less often and + // moving the base instead? + copy(db.connRequests, db.connRequests[1:]) + db.connRequests = db.connRequests[:c-1] + if err == nil { dc.inUse = true - req <- dc + } + req <- connRequest{ + conn: dc, + err: err, } return true - } else if err == nil && !db.closed && db.maxIdleConnsLocked() > 0 && db.maxIdleConnsLocked() > db.freeConn.Len() { - dc.listElem = db.freeConn.PushFront(dc) + } else if err == nil && !db.closed && db.maxIdleConnsLocked() > len(db.freeConn) { + db.freeConn = append(db.freeConn, dc) return true } return false } +// maxBadConnRetries is the number of maximum retries if the driver returns +// driver.ErrBadConn to signal a broken connection. +const maxBadConnRetries = 10 + // Prepare creates a prepared statement for later queries or executions. // Multiple queries or executions may be run concurrently from the // returned statement. func (db *DB) Prepare(query string) (*Stmt, error) { var stmt *Stmt var err error - for i := 0; i < 10; i++ { + for i := 0; i < maxBadConnRetries; i++ { stmt, err = db.prepare(query) if err != driver.ErrBadConn { break @@ -846,7 +871,7 @@ func (db *DB) prepare(query string) (*Stmt, error) { func (db *DB) Exec(query string, args ...interface{}) (Result, error) { var res Result var err error - for i := 0; i < 10; i++ { + for i := 0; i < maxBadConnRetries; i++ { res, err = db.exec(query, args) if err != driver.ErrBadConn { break @@ -895,7 +920,7 @@ func (db *DB) exec(query string, args []interface{}) (res Result, err error) { func (db *DB) Query(query string, args ...interface{}) (*Rows, error) { var rows *Rows var err error - for i := 0; i < 10; i++ { + for i := 0; i < maxBadConnRetries; i++ { rows, err = db.query(query, args) if err != driver.ErrBadConn { break @@ -983,7 +1008,7 @@ func (db *DB) QueryRow(query string, args ...interface{}) *Row { func (db *DB) Begin() (*Tx, error) { var tx *Tx var err error - for i := 0; i < 10; i++ { + for i := 0; i < maxBadConnRetries; i++ { tx, err = db.begin() if err != driver.ErrBadConn { break @@ -1034,6 +1059,13 @@ type Tx struct { // or Rollback. once done, all operations fail with // ErrTxDone. done bool + + // All Stmts prepared for this transaction. These will be closed after the + // transaction has been committed or rolled back. + stmts struct { + sync.Mutex + v []*Stmt + } } var ErrTxDone = errors.New("sql: Transaction has already been committed or rolled back") @@ -1055,6 +1087,15 @@ func (tx *Tx) grabConn() (*driverConn, error) { return tx.dc, nil } +// Closes all Stmts prepared for this transaction. +func (tx *Tx) closePrepared() { + tx.stmts.Lock() + for _, stmt := range tx.stmts.v { + stmt.Close() + } + tx.stmts.Unlock() +} + // Commit commits the transaction. func (tx *Tx) Commit() error { if tx.done { @@ -1062,8 +1103,12 @@ func (tx *Tx) Commit() error { } defer tx.close() tx.dc.Lock() - defer tx.dc.Unlock() - return tx.txi.Commit() + err := tx.txi.Commit() + tx.dc.Unlock() + if err != driver.ErrBadConn { + tx.closePrepared() + } + return err } // Rollback aborts the transaction. @@ -1073,8 +1118,12 @@ func (tx *Tx) Rollback() error { } defer tx.close() tx.dc.Lock() - defer tx.dc.Unlock() - return tx.txi.Rollback() + err := tx.txi.Rollback() + tx.dc.Unlock() + if err != driver.ErrBadConn { + tx.closePrepared() + } + return err } // Prepare creates a prepared statement for use within a transaction. @@ -1118,6 +1167,9 @@ func (tx *Tx) Prepare(query string) (*Stmt, error) { }, query: query, } + tx.stmts.Lock() + tx.stmts.v = append(tx.stmts.v, stmt) + tx.stmts.Unlock() return stmt, nil } @@ -1146,7 +1198,7 @@ func (tx *Tx) Stmt(stmt *Stmt) *Stmt { dc.Lock() si, err := dc.ci.Prepare(stmt.query) dc.Unlock() - return &Stmt{ + txs := &Stmt{ db: tx.db, tx: tx, txsi: &driverStmt{ @@ -1156,6 +1208,10 @@ func (tx *Tx) Stmt(stmt *Stmt) *Stmt { query: stmt.query, stickyErr: err, } + tx.stmts.Lock() + tx.stmts.v = append(tx.stmts.v, txs) + tx.stmts.Unlock() + return txs } // Exec executes a query that doesn't return rows. @@ -1245,13 +1301,24 @@ type Stmt struct { func (s *Stmt) Exec(args ...interface{}) (Result, error) { s.closemu.RLock() defer s.closemu.RUnlock() - dc, releaseConn, si, err := s.connStmt() - if err != nil { - return nil, err - } - defer releaseConn(nil) - return resultFromStatement(driverStmt{dc, si}, args...) + var res Result + for i := 0; i < maxBadConnRetries; i++ { + dc, releaseConn, si, err := s.connStmt() + if err != nil { + if err == driver.ErrBadConn { + continue + } + return nil, err + } + + res, err = resultFromStatement(driverStmt{dc, si}, args...) + releaseConn(err) + if err != driver.ErrBadConn { + return res, err + } + } + return nil, driver.ErrBadConn } func resultFromStatement(ds driverStmt, args ...interface{}) (Result, error) { @@ -1306,15 +1373,12 @@ func (s *Stmt) connStmt() (ci *driverConn, releaseConn func(error), si driver.St return ci, releaseConn, s.txsi.si, nil } - var cs connStmt - match := false for i := 0; i < len(s.css); i++ { v := s.css[i] _, err := s.db.connIfFree(v.dc) if err == nil { - match = true - cs = v - break + s.mu.Unlock() + return v.dc, v.dc.releaseConn, v.si, nil } if err == errConnClosed { // Lazily remove dead conn from our freelist. @@ -1326,33 +1390,41 @@ func (s *Stmt) connStmt() (ci *driverConn, releaseConn func(error), si driver.St } s.mu.Unlock() - // Make a new conn if all are busy. - // TODO(bradfitz): or wait for one? make configurable later? - if !match { - for i := 0; ; i++ { - dc, err := s.db.conn() - if err != nil { - return nil, nil, nil, err - } - dc.Lock() - si, err := dc.prepareLocked(s.query) - dc.Unlock() - if err == driver.ErrBadConn && i < 10 { - continue - } - if err != nil { - return nil, nil, nil, err - } - s.mu.Lock() - cs = connStmt{dc, si} - s.css = append(s.css, cs) + // If all connections are busy, either wait for one to become available (if + // we've already hit the maximum number of open connections) or create a + // new one. + // + // TODO(bradfitz): or always wait for one? make configurable later? + dc, err := s.db.conn() + if err != nil { + return nil, nil, nil, err + } + + // Do another pass over the list to see whether this statement has + // already been prepared on the connection assigned to us. + s.mu.Lock() + for _, v := range s.css { + if v.dc == dc { s.mu.Unlock() - break + return dc, dc.releaseConn, v.si, nil } } + s.mu.Unlock() - conn := cs.dc - return conn, conn.releaseConn, cs.si, nil + // No luck; we need to prepare the statement on this connection + dc.Lock() + si, err = dc.prepareLocked(s.query) + dc.Unlock() + if err != nil { + s.db.putConn(dc, err) + return nil, nil, nil, err + } + s.mu.Lock() + cs := connStmt{dc, si} + s.css = append(s.css, cs) + s.mu.Unlock() + + return dc, dc.releaseConn, si, nil } // Query executes a prepared query statement with the given arguments @@ -1361,31 +1433,39 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) { s.closemu.RLock() defer s.closemu.RUnlock() - dc, releaseConn, si, err := s.connStmt() - if err != nil { - return nil, err - } + var rowsi driver.Rows + for i := 0; i < maxBadConnRetries; i++ { + dc, releaseConn, si, err := s.connStmt() + if err != nil { + if err == driver.ErrBadConn { + continue + } + return nil, err + } - ds := driverStmt{dc, si} - rowsi, err := rowsiFromStatement(ds, args...) - if err != nil { - releaseConn(err) - return nil, err - } + rowsi, err = rowsiFromStatement(driverStmt{dc, si}, args...) + if err == nil { + // Note: ownership of ci passes to the *Rows, to be freed + // with releaseConn. + rows := &Rows{ + dc: dc, + rowsi: rowsi, + // releaseConn set below + } + s.db.addDep(s, rows) + rows.releaseConn = func(err error) { + releaseConn(err) + s.db.removeDep(s, rows) + } + return rows, nil + } - // Note: ownership of ci passes to the *Rows, to be freed - // with releaseConn. - rows := &Rows{ - dc: dc, - rowsi: rowsi, - // releaseConn set below - } - s.db.addDep(s, rows) - rows.releaseConn = func(err error) { releaseConn(err) - s.db.removeDep(s, rows) + if err != driver.ErrBadConn { + return nil, err + } } - return rows, nil + return nil, driver.ErrBadConn } func rowsiFromStatement(ds driverStmt, args ...interface{}) (driver.Rows, error) { @@ -1476,6 +1556,7 @@ func (s *Stmt) finalClose() error { // // rows, err := db.Query("SELECT ...") // ... +// defer rows.Close() // for rows.Next() { // var id int // var name string @@ -1495,10 +1576,12 @@ type Rows struct { closeStmt driver.Stmt // if non-nil, statement to Close on close } -// Next prepares the next result row for reading with the Scan method. -// It returns true on success, false if there is no next result row. -// Every call to Scan, even the first one, must be preceded by a call -// to Next. +// Next prepares the next result row for reading with the Scan method. It +// returns true on success, or false if there is no next result row or an error +// happened while preparing it. Err should be consulted to distinguish between +// the two cases. +// +// Every call to Scan, even the first one, must be preceded by a call to Next. func (rs *Rows) Next() bool { if rs.closed { return false @@ -1625,12 +1708,19 @@ func (r *Row) Scan(dest ...interface{}) error { } if !r.rows.Next() { + if err := r.rows.Err(); err != nil { + return err + } return ErrNoRows } err := r.rows.Scan(dest...) if err != nil { return err } + // Make sure the query can be processed to completion with no errors. + if err := r.rows.Close(); err != nil { + return err + } return nil } diff --git a/libgo/go/database/sql/sql_test.go b/libgo/go/database/sql/sql_test.go index 787a5c9f74..34efdf254c 100644 --- a/libgo/go/database/sql/sql_test.go +++ b/libgo/go/database/sql/sql_test.go @@ -24,7 +24,14 @@ func init() { } freedFrom := make(map[dbConn]string) putConnHook = func(db *DB, c *driverConn) { - if c.listElem != nil { + idx := -1 + for i, v := range db.freeConn { + if v == c { + idx = i + break + } + } + if idx >= 0 { // print before panic, as panic may get lost due to conflicting panic // (all goroutines asleep) elsewhere, since we might not unlock // the mutex in freeConn here. @@ -79,15 +86,14 @@ func closeDB(t testing.TB, db *DB) { t.Errorf("Error closing fakeConn: %v", err) } }) - for node, i := db.freeConn.Front(), 0; node != nil; node, i = node.Next(), i+1 { - dc := node.Value.(*driverConn) + for i, dc := range db.freeConn { if n := len(dc.openStmt); n > 0 { // Just a sanity check. This is legal in // general, but if we make the tests clean up // their statements first, then we can safely // verify this is always zero here, and any // other value is a leak. - t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, db.freeConn.Len(), n) + t.Errorf("while closing db, freeConn %d/%d had %d open stmts; want 0", i, len(db.freeConn), n) } } err := db.Close() @@ -105,10 +111,10 @@ func closeDB(t testing.TB, db *DB) { // numPrepares assumes that db has exactly 1 idle conn and returns // its count of calls to Prepare func numPrepares(t *testing.T, db *DB) int { - if n := db.freeConn.Len(); n != 1 { + if n := len(db.freeConn); n != 1 { t.Fatalf("free conns = %d; want 1", n) } - return (db.freeConn.Front().Value.(*driverConn)).ci.(*fakeConn).numPrepare + return db.freeConn[0].ci.(*fakeConn).numPrepare } func (db *DB) numDeps() int { @@ -133,7 +139,7 @@ func (db *DB) numDepsPollUntil(want int, d time.Duration) int { func (db *DB) numFreeConns() int { db.mu.Lock() defer db.mu.Unlock() - return db.freeConn.Len() + return len(db.freeConn) } func (db *DB) dumpDeps(t *testing.T) { @@ -348,7 +354,6 @@ func TestStatementQueryRow(t *testing.T) { t.Errorf("%d: age=%d, want %d", n, age, tt.want) } } - } // golang.org/issue/3734 @@ -436,6 +441,33 @@ func TestExec(t *testing.T) { } } +func TestTxPrepare(t *testing.T) { + db := newTestDB(t, "") + defer closeDB(t, db) + exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") + tx, err := db.Begin() + if err != nil { + t.Fatalf("Begin = %v", err) + } + stmt, err := tx.Prepare("INSERT|t1|name=?,age=?") + if err != nil { + t.Fatalf("Stmt, err = %v, %v", stmt, err) + } + defer stmt.Close() + _, err = stmt.Exec("Bobby", 7) + if err != nil { + t.Fatalf("Exec = %v", err) + } + err = tx.Commit() + if err != nil { + t.Fatalf("Commit = %v", err) + } + // Commit() should have closed the statement + if !stmt.closed { + t.Fatal("Stmt not closed after Commit") + } +} + func TestTxStmt(t *testing.T) { db := newTestDB(t, "") defer closeDB(t, db) @@ -459,10 +491,14 @@ func TestTxStmt(t *testing.T) { if err != nil { t.Fatalf("Commit = %v", err) } + // Commit() should have closed the statement + if !txs.closed { + t.Fatal("Stmt not closed after Commit") + } } // Issue: http://golang.org/issue/2784 -// This test didn't fail before because we got luckly with the fakedb driver. +// This test didn't fail before because we got lucky with the fakedb driver. // It was failing, and now not, in github.com/bradfitz/go-sql-test func TestTxQuery(t *testing.T) { db := newTestDB(t, "") @@ -651,15 +687,44 @@ func TestQueryRowClosingStmt(t *testing.T) { if err != nil { t.Fatal(err) } - if db.freeConn.Len() != 1 { + if len(db.freeConn) != 1 { t.Fatalf("expected 1 free conn") } - fakeConn := (db.freeConn.Front().Value.(*driverConn)).ci.(*fakeConn) + fakeConn := db.freeConn[0].ci.(*fakeConn) if made, closed := fakeConn.stmtsMade, fakeConn.stmtsClosed; made != closed { t.Errorf("statement close mismatch: made %d, closed %d", made, closed) } } +// Test issue 6651 +func TestIssue6651(t *testing.T) { + db := newTestDB(t, "people") + defer closeDB(t, db) + + var v string + + want := "error in rows.Next" + rowsCursorNextHook = func(dest []driver.Value) error { + return fmt.Errorf(want) + } + defer func() { rowsCursorNextHook = nil }() + err := db.QueryRow("SELECT|people|name|").Scan(&v) + if err == nil || err.Error() != want { + t.Errorf("error = %q; want %q", err, want) + } + rowsCursorNextHook = nil + + want = "error in rows.Close" + rowsCloseHook = func(rows *Rows, err *error) { + *err = fmt.Errorf(want) + } + defer func() { rowsCloseHook = nil }() + err = db.QueryRow("SELECT|people|name|").Scan(&v) + if err == nil || err.Error() != want { + t.Errorf("error = %q; want %q", err, want) + } +} + type nullTestRow struct { nullParam interface{} notNullParam interface{} @@ -850,13 +915,13 @@ func TestMaxIdleConns(t *testing.T) { t.Fatal(err) } tx.Commit() - if got := db.freeConn.Len(); got != 1 { + if got := len(db.freeConn); got != 1 { t.Errorf("freeConns = %d; want 1", got) } db.SetMaxIdleConns(0) - if got := db.freeConn.Len(); got != 0 { + if got := len(db.freeConn); got != 0 { t.Errorf("freeConns after set to zero = %d; want 0", got) } @@ -865,7 +930,7 @@ func TestMaxIdleConns(t *testing.T) { t.Fatal(err) } tx.Commit() - if got := db.freeConn.Len(); got != 0 { + if got := len(db.freeConn); got != 0 { t.Errorf("freeConns = %d; want 0", got) } } @@ -1152,10 +1217,10 @@ func TestCloseConnBeforeStmts(t *testing.T) { t.Fatal(err) } - if db.freeConn.Len() != 1 { - t.Fatalf("expected 1 freeConn; got %d", db.freeConn.Len()) + if len(db.freeConn) != 1 { + t.Fatalf("expected 1 freeConn; got %d", len(db.freeConn)) } - dc := db.freeConn.Front().Value.(*driverConn) + dc := db.freeConn[0] if dc.closed { t.Errorf("conn shouldn't be closed") } @@ -1249,6 +1314,112 @@ func TestStmtCloseOrder(t *testing.T) { } } +// golang.org/issue/5781 +func TestErrBadConnReconnect(t *testing.T) { + db := newTestDB(t, "foo") + defer closeDB(t, db) + exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool") + + simulateBadConn := func(name string, hook *func() bool, op func() error) { + broken, retried := false, false + numOpen := db.numOpen + + // simulate a broken connection on the first try + *hook = func() bool { + if !broken { + broken = true + return true + } + retried = true + return false + } + + if err := op(); err != nil { + t.Errorf(name+": %v", err) + return + } + + if !broken || !retried { + t.Error(name + ": Failed to simulate broken connection") + } + *hook = nil + + if numOpen != db.numOpen { + t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen) + numOpen = db.numOpen + } + } + + // db.Exec + dbExec := func() error { + _, err := db.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true) + return err + } + simulateBadConn("db.Exec prepare", &hookPrepareBadConn, dbExec) + simulateBadConn("db.Exec exec", &hookExecBadConn, dbExec) + + // db.Query + dbQuery := func() error { + rows, err := db.Query("SELECT|t1|age,name|") + if err == nil { + err = rows.Close() + } + return err + } + simulateBadConn("db.Query prepare", &hookPrepareBadConn, dbQuery) + simulateBadConn("db.Query query", &hookQueryBadConn, dbQuery) + + // db.Prepare + simulateBadConn("db.Prepare", &hookPrepareBadConn, func() error { + stmt, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?") + if err != nil { + return err + } + stmt.Close() + return nil + }) + + // Provide a way to force a re-prepare of a statement on next execution + forcePrepare := func(stmt *Stmt) { + stmt.css = nil + } + + // stmt.Exec + stmt1, err := db.Prepare("INSERT|t1|name=?,age=?,dead=?") + if err != nil { + t.Fatalf("prepare: %v", err) + } + defer stmt1.Close() + // make sure we must prepare the stmt first + forcePrepare(stmt1) + + stmtExec := func() error { + _, err := stmt1.Exec("Gopher", 3, false) + return err + } + simulateBadConn("stmt.Exec prepare", &hookPrepareBadConn, stmtExec) + simulateBadConn("stmt.Exec exec", &hookExecBadConn, stmtExec) + + // stmt.Query + stmt2, err := db.Prepare("SELECT|t1|age,name|") + if err != nil { + t.Fatalf("prepare: %v", err) + } + defer stmt2.Close() + // make sure we must prepare the stmt first + forcePrepare(stmt2) + + stmtQuery := func() error { + rows, err := stmt2.Query() + if err == nil { + err = rows.Close() + } + return err + } + simulateBadConn("stmt.Query prepare", &hookPrepareBadConn, stmtQuery) + simulateBadConn("stmt.Query exec", &hookQueryBadConn, stmtQuery) +} + type concurrentTest interface { init(t testing.TB, db *DB) finish(t testing.TB) @@ -1575,7 +1746,7 @@ func doConcurrentTest(t testing.TB, ct concurrentTest) { for i := 0; i < maxProcs*2; i++ { go func() { - for _ = range reqs { + for range reqs { err := ct.test(t) if err != nil { wg.Done() @@ -1617,7 +1788,7 @@ func manyConcurrentQueries(t testing.TB) { for i := 0; i < maxProcs*2; i++ { go func() { - for _ = range reqs { + for range reqs { rows, err := stmt.Query() if err != nil { t.Errorf("error on query: %v", err) diff --git a/libgo/go/debug/dwarf/const.go b/libgo/go/debug/dwarf/const.go index 68503c742f..6cc6bc937a 100644 --- a/libgo/go/debug/dwarf/const.go +++ b/libgo/go/debug/dwarf/const.go @@ -207,10 +207,15 @@ const ( formRef8 format = 0x14 formRefUdata format = 0x15 formIndirect format = 0x16 + // The following are new in DWARF 4. formSecOffset format = 0x17 formExprloc format = 0x18 formFlagPresent format = 0x19 formRefSig8 format = 0x20 + // Extensions for multi-file compression (.dwz) + // http://www.dwarfstd.org/ShowIssue.php?issue=120604.1 + formGnuRefAlt format = 0x1f20 + formGnuStrpAlt format = 0x1f21 ) // A Tag is the classification (the type) of an Entry. @@ -264,15 +269,22 @@ const ( TagVariantPart Tag = 0x33 TagVariable Tag = 0x34 TagVolatileType Tag = 0x35 - TagDwarfProcedure Tag = 0x36 - TagRestrictType Tag = 0x37 - TagInterfaceType Tag = 0x38 - TagNamespace Tag = 0x39 - TagImportedModule Tag = 0x3A - TagUnspecifiedType Tag = 0x3B - TagPartialUnit Tag = 0x3C - TagImportedUnit Tag = 0x3D - TagMutableType Tag = 0x3E + // The following are new in DWARF 3. + TagDwarfProcedure Tag = 0x36 + TagRestrictType Tag = 0x37 + TagInterfaceType Tag = 0x38 + TagNamespace Tag = 0x39 + TagImportedModule Tag = 0x3A + TagUnspecifiedType Tag = 0x3B + TagPartialUnit Tag = 0x3C + TagImportedUnit Tag = 0x3D + TagMutableType Tag = 0x3E // Later removed from DWARF. + TagCondition Tag = 0x3F + TagSharedType Tag = 0x40 + // The following are new in DWARF 4. + TagTypeUnit Tag = 0x41 + TagRvalueReferenceType Tag = 0x42 + TagTemplateAlias Tag = 0x43 ) var tagNames = [...]string{ @@ -332,6 +344,11 @@ var tagNames = [...]string{ TagPartialUnit: "PartialUnit", TagImportedUnit: "ImportedUnit", TagMutableType: "MutableType", + TagCondition: "Condition", + TagSharedType: "SharedType", + TagTypeUnit: "TypeUnit", + TagRvalueReferenceType: "RvalueReferenceType", + TagTemplateAlias: "TemplateAlias", } func (t Tag) String() string { diff --git a/libgo/go/debug/dwarf/entry.go b/libgo/go/debug/dwarf/entry.go index e0d3229fb4..b6ba8c0d1c 100644 --- a/libgo/go/debug/dwarf/entry.go +++ b/libgo/go/debug/dwarf/entry.go @@ -241,10 +241,10 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { // lineptr, loclistptr, macptr, rangelistptr // New in DWARF 4, but clang can generate them with -gdwarf-2. // Section reference, replacing use of formData4 and formData8. - case formSecOffset: + case formSecOffset, formGnuRefAlt, formGnuStrpAlt: is64, known := b.format.dwarf64() if !known { - b.error("unknown size for DW_FORM_sec_offset") + b.error("unknown size for form 0x" + strconv.FormatInt(int64(fmt), 16)) } else if is64 { val = int64(b.uint64()) } else { @@ -396,3 +396,15 @@ func (r *Reader) SkipChildren() { } } } + +// clone returns a copy of the reader. This is used by the typeReader +// interface. +func (r *Reader) clone() typeReader { + return r.d.Reader() +} + +// offset returns the current buffer offset. This is used by the +// typeReader interface. +func (r *Reader) offset() Offset { + return r.b.off +} diff --git a/libgo/go/debug/dwarf/open.go b/libgo/go/debug/dwarf/open.go index 7579892529..c1b3f37aca 100644 --- a/libgo/go/debug/dwarf/open.go +++ b/libgo/go/debug/dwarf/open.go @@ -26,6 +26,7 @@ type Data struct { abbrevCache map[uint32]abbrevTable order binary.ByteOrder typeCache map[Offset]Type + typeSigs map[uint64]*typeUnit unit []unit } @@ -49,6 +50,7 @@ func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Dat str: str, abbrevCache: make(map[uint32]abbrevTable), typeCache: make(map[Offset]Type), + typeSigs: make(map[uint64]*typeUnit), } // Sniff .debug_info to figure out byte order. @@ -75,3 +77,11 @@ func New(abbrev, aranges, frame, info, line, pubnames, ranges, str []byte) (*Dat d.unit = u return d, nil } + +// AddTypes will add one .debug_types section to the DWARF data. A +// typical object with DWARF version 4 debug info will have multiple +// .debug_types sections. The name is used for error reporting only, +// and serves to distinguish one .debug_types section from another. +func (d *Data) AddTypes(name string, types []byte) error { + return d.parseTypes(name, types) +} diff --git a/libgo/go/debug/dwarf/testdata/typedef.elf4 b/libgo/go/debug/dwarf/testdata/typedef.elf4 new file mode 100644 index 0000000000..3d5a5a1b16 Binary files /dev/null and b/libgo/go/debug/dwarf/testdata/typedef.elf4 differ diff --git a/libgo/go/debug/dwarf/type.go b/libgo/go/debug/dwarf/type.go index 1fbae6c144..6986b19e72 100644 --- a/libgo/go/debug/dwarf/type.go +++ b/libgo/go/debug/dwarf/type.go @@ -88,6 +88,11 @@ type AddrType struct { BasicType } +// An UnspecifiedType represents an implicit, unknown, ambiguous or nonexistent type. +type UnspecifiedType struct { + BasicType +} + // qualifiers // A QualType represents a type that has the C/C++ "const", "restrict", or "volatile" qualifier. @@ -113,7 +118,12 @@ func (t *ArrayType) String() string { return "[" + strconv.FormatInt(t.Count, 10) + "]" + t.Type.String() } -func (t *ArrayType) Size() int64 { return t.Count * t.Type.Size() } +func (t *ArrayType) Size() int64 { + if t.Count == -1 { + return 0 + } + return t.Count * t.Type.Size() +} // A VoidType represents the C void type. type VoidType struct { @@ -251,23 +261,37 @@ func (t *TypedefType) String() string { return t.Name } func (t *TypedefType) Size() int64 { return t.Type.Size() } +// typeReader is used to read from either the info section or the +// types section. +type typeReader interface { + Seek(Offset) + Next() (*Entry, error) + clone() typeReader + offset() Offset +} + +// Type reads the type at off in the DWARF ``info'' section. func (d *Data) Type(off Offset) (Type, error) { - if t, ok := d.typeCache[off]; ok { + return d.readType("info", d.Reader(), off, d.typeCache) +} + +// readType reads a type from r at off of name using and updating a +// type cache. +func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type) (Type, error) { + if t, ok := typeCache[off]; ok { return t, nil } - - r := d.Reader() r.Seek(off) e, err := r.Next() if err != nil { return nil, err } if e == nil || e.Offset != off { - return nil, DecodeError{"info", off, "no type at offset"} + return nil, DecodeError{name, off, "no type at offset"} } // Parse type from Entry. - // Must always set d.typeCache[off] before calling + // Must always set typeCache[off] before calling // d.Type recursively, to handle circular types correctly. var typ Type @@ -290,7 +314,7 @@ func (d *Data) Type(off Offset) (Type, error) { return nil } if kid == nil { - err = DecodeError{"info", r.b.off, "unexpected end of DWARF entries"} + err = DecodeError{name, r.offset(), "unexpected end of DWARF entries"} return nil } if kid.Tag == 0 { @@ -313,15 +337,21 @@ func (d *Data) Type(off Offset) (Type, error) { // Get Type referred to by Entry's AttrType field. // Set err if error happens. Not having a type is an error. typeOf := func(e *Entry) Type { - toff, ok := e.Val(AttrType).(Offset) - if !ok { + tval := e.Val(AttrType) + var t Type + switch toff := tval.(type) { + case Offset: + if t, err = d.readType(name, r.clone(), toff, typeCache); err != nil { + return nil + } + case uint64: + if t, err = d.sigToType(toff); err != nil { + return nil + } + default: // It appears that no Type means "void". return new(VoidType) } - var t Type - if t, err = d.Type(toff); err != nil { - return nil - } return t } @@ -337,39 +367,43 @@ func (d *Data) Type(off Offset) (Type, error) { // dimensions are in left to right order. t := new(ArrayType) typ = t - d.typeCache[off] = t + typeCache[off] = t if t.Type = typeOf(e); err != nil { goto Error } t.StrideBitSize, _ = e.Val(AttrStrideSize).(int64) // Accumulate dimensions, - ndim := 0 + var dims []int64 for kid := next(); kid != nil; kid = next() { // TODO(rsc): Can also be TagEnumerationType // but haven't seen that in the wild yet. switch kid.Tag { case TagSubrangeType: - max, ok := kid.Val(AttrUpperBound).(int64) + count, ok := kid.Val(AttrCount).(int64) if !ok { - max = -2 // Count == -1, as in x[]. - } - if ndim == 0 { - t.Count = max + 1 - } else { - // Multidimensional array. - // Create new array type underneath this one. - t.Type = &ArrayType{Type: t.Type, Count: max + 1} + // Old binaries may have an upper bound instead. + count, ok = kid.Val(AttrUpperBound).(int64) + if ok { + count++ // Length is one more than upper bound. + } else if len(dims) == 0 { + count = -1 // As in x[]. + } } - ndim++ + dims = append(dims, count) case TagEnumerationType: - err = DecodeError{"info", kid.Offset, "cannot handle enumeration type as array bound"} + err = DecodeError{name, kid.Offset, "cannot handle enumeration type as array bound"} goto Error } } - if ndim == 0 { + if len(dims) == 0 { // LLVM generates this for x[]. - t.Count = -1 + dims = []int64{-1} + } + + t.Count = dims[0] + for i := len(dims) - 1; i >= 1; i-- { + t.Type = &ArrayType{Type: t.Type, Count: dims[i]} } case TagBaseType: @@ -383,12 +417,12 @@ func (d *Data) Type(off Offset) (Type, error) { name, _ := e.Val(AttrName).(string) enc, ok := e.Val(AttrEncoding).(int64) if !ok { - err = DecodeError{"info", e.Offset, "missing encoding attribute for " + name} + err = DecodeError{name, e.Offset, "missing encoding attribute for " + name} goto Error } switch enc { default: - err = DecodeError{"info", e.Offset, "unrecognized encoding attribute value"} + err = DecodeError{name, e.Offset, "unrecognized encoding attribute value"} goto Error case encAddress: @@ -397,6 +431,17 @@ func (d *Data) Type(off Offset) (Type, error) { typ = new(BoolType) case encComplexFloat: typ = new(ComplexType) + if name == "complex" { + // clang writes out 'complex' instead of 'complex float' or 'complex double'. + // clang also writes out a byte size that we can use to distinguish. + // See issue 8694. + switch byteSize, _ := e.Val(AttrByteSize).(int64); byteSize { + case 8: + name = "complex float" + case 16: + name = "complex double" + } + } case encFloat: typ = new(FloatType) case encSigned: @@ -408,7 +453,7 @@ func (d *Data) Type(off Offset) (Type, error) { case encUnsignedChar: typ = new(UcharType) } - d.typeCache[off] = typ + typeCache[off] = typ t := typ.(interface { Basic() *BasicType }).Basic() @@ -433,7 +478,7 @@ func (d *Data) Type(off Offset) (Type, error) { // There is much more to handle C++, all ignored for now. t := new(StructType) typ = t - d.typeCache[off] = t + typeCache[off] = t switch e.Tag { case TagClassType: t.Kind = "class" @@ -445,7 +490,7 @@ func (d *Data) Type(off Offset) (Type, error) { t.StructName, _ = e.Val(AttrName).(string) t.Incomplete = e.Val(AttrDeclaration) != nil t.Field = make([]*StructField, 0, 8) - var lastFieldType Type + var lastFieldType *Type var lastFieldBitOffset int64 for kid := next(); kid != nil; kid = next() { if kid.Tag == TagMember { @@ -453,12 +498,13 @@ func (d *Data) Type(off Offset) (Type, error) { if f.Type = typeOf(kid); err != nil { goto Error } - if loc, ok := kid.Val(AttrDataMemberLoc).([]byte); ok { + switch loc := kid.Val(AttrDataMemberLoc).(type) { + case []byte: // TODO: Should have original compilation // unit here, not unknownFormat. b := makeBuf(d, unknownFormat{}, "location", 0, loc) if b.uint8() != opPlusUconst { - err = DecodeError{"info", kid.Offset, "unexpected opcode"} + err = DecodeError{name, kid.Offset, "unexpected opcode"} goto Error } f.ByteOffset = int64(b.uint()) @@ -466,6 +512,8 @@ func (d *Data) Type(off Offset) (Type, error) { err = b.err goto Error } + case int64: + f.ByteOffset = loc } haveBitOffset := false @@ -484,7 +532,7 @@ func (d *Data) Type(off Offset) (Type, error) { // (DWARF writes out 0-length arrays as if they were 1-length arrays.) zeroArray(lastFieldType) } - lastFieldType = f.Type + lastFieldType = &f.Type lastFieldBitOffset = bito } } @@ -502,7 +550,7 @@ func (d *Data) Type(off Offset) (Type, error) { // AttrType: subtype t := new(QualType) typ = t - d.typeCache[off] = t + typeCache[off] = t if t.Type = typeOf(e); err != nil { goto Error } @@ -526,7 +574,7 @@ func (d *Data) Type(off Offset) (Type, error) { // AttrConstValue: value of constant t := new(EnumType) typ = t - d.typeCache[off] = t + typeCache[off] = t t.EnumName, _ = e.Val(AttrName).(string) t.Val = make([]*EnumValue, 0, 8) for kid := next(); kid != nil; kid = next() { @@ -552,7 +600,7 @@ func (d *Data) Type(off Offset) (Type, error) { // AttrAddrClass: address class [ignored] t := new(PtrType) typ = t - d.typeCache[off] = t + typeCache[off] = t if e.Val(AttrType) == nil { t.Type = &VoidType{} break @@ -571,7 +619,7 @@ func (d *Data) Type(off Offset) (Type, error) { // TagUnspecifiedParameter: final ... t := new(FuncType) typ = t - d.typeCache[off] = t + typeCache[off] = t if t.ReturnType = typeOf(e); err != nil { goto Error } @@ -598,9 +646,18 @@ func (d *Data) Type(off Offset) (Type, error) { // AttrType: type definition [required] t := new(TypedefType) typ = t - d.typeCache[off] = t + typeCache[off] = t t.Name, _ = e.Val(AttrName).(string) t.Type = typeOf(e) + + case TagUnspecifiedType: + // Unspecified type (DWARF v3 §5.2) + // Attributes: + // AttrName: name + t := new(UnspecifiedType) + typ = t + typeCache[off] = t + t.Name, _ = e.Val(AttrName).(string) } if err != nil { @@ -620,17 +677,20 @@ Error: // If the parse fails, take the type out of the cache // so that the next call with this offset doesn't hit // the cache and return success. - delete(d.typeCache, off) + delete(typeCache, off) return nil, err } -func zeroArray(t Type) { - for { - at, ok := t.(*ArrayType) - if !ok { - break - } - at.Count = 0 - t = at.Type +func zeroArray(t *Type) { + if t == nil { + return + } + at, ok := (*t).(*ArrayType) + if !ok || at.Type.Size() == 0 { + return } + // Make a copy to avoid invalidating typeCache. + tt := *at + tt.Count = 0 + *t = &tt } diff --git a/libgo/go/debug/dwarf/type_test.go b/libgo/go/debug/dwarf/type_test.go index b5b255f6f4..2cb85e74bb 100644 --- a/libgo/go/debug/dwarf/type_test.go +++ b/libgo/go/debug/dwarf/type_test.go @@ -73,6 +73,8 @@ func TestTypedefsMachO(t *testing.T) { testTypedefs(t, machoData(t, "testdata/typedef.macho"), "macho") } +func TestTypedefsELFDwarf4(t *testing.T) { testTypedefs(t, elfData(t, "testdata/typedef.elf4"), "elf") } + func testTypedefs(t *testing.T, d *Data, kind string) { r := d.Reader() seen := make(map[string]bool) diff --git a/libgo/go/debug/dwarf/typeunit.go b/libgo/go/debug/dwarf/typeunit.go new file mode 100644 index 0000000000..3fd1c9973e --- /dev/null +++ b/libgo/go/debug/dwarf/typeunit.go @@ -0,0 +1,166 @@ +// 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 dwarf + +import ( + "fmt" + "strconv" +) + +// Parse the type units stored in a DWARF4 .debug_types section. Each +// type unit defines a single primary type and an 8-byte signature. +// Other sections may then use formRefSig8 to refer to the type. + +// The typeUnit format is a single type with a signature. It holds +// the same data as a compilation unit. +type typeUnit struct { + unit + toff Offset // Offset to signature type within data. + name string // Name of .debug_type section. + cache Type // Cache the type, nil to start. +} + +// Parse a .debug_types section. +func (d *Data) parseTypes(name string, types []byte) error { + b := makeBuf(d, unknownFormat{}, name, 0, types) + for len(b.data) > 0 { + base := b.off + dwarf64 := false + n := b.uint32() + if n == 0xffffffff { + n64 := b.uint64() + if n64 != uint64(uint32(n64)) { + b.error("type unit length overflow") + return b.err + } + n = uint32(n64) + dwarf64 = true + } + hdroff := b.off + vers := b.uint16() + if vers != 4 { + b.error("unsupported DWARF version " + strconv.Itoa(int(vers))) + return b.err + } + var ao uint32 + if !dwarf64 { + ao = b.uint32() + } else { + ao64 := b.uint64() + if ao64 != uint64(uint32(ao64)) { + b.error("type unit abbrev offset overflow") + return b.err + } + ao = uint32(ao64) + } + atable, err := d.parseAbbrev(ao) + if err != nil { + return err + } + asize := b.uint8() + sig := b.uint64() + + var toff uint32 + if !dwarf64 { + toff = b.uint32() + } else { + to64 := b.uint64() + if to64 != uint64(uint32(to64)) { + b.error("type unit type offset overflow") + return b.err + } + toff = uint32(to64) + } + + boff := b.off + d.typeSigs[sig] = &typeUnit{ + unit: unit{ + base: base, + off: boff, + data: b.bytes(int(Offset(n) - (b.off - hdroff))), + atable: atable, + asize: int(asize), + vers: int(vers), + is64: dwarf64, + }, + toff: Offset(toff), + name: name, + } + if b.err != nil { + return b.err + } + } + return nil +} + +// Return the type for a type signature. +func (d *Data) sigToType(sig uint64) (Type, error) { + tu := d.typeSigs[sig] + if tu == nil { + return nil, fmt.Errorf("no type unit with signature %v", sig) + } + if tu.cache != nil { + return tu.cache, nil + } + + b := makeBuf(d, tu, tu.name, tu.off, tu.data) + r := &typeUnitReader{d: d, tu: tu, b: b} + t, err := d.readType(tu.name, r, Offset(tu.toff), make(map[Offset]Type)) + if err != nil { + return nil, err + } + + tu.cache = t + return t, nil +} + +// typeUnitReader is a typeReader for a tagTypeUnit. +type typeUnitReader struct { + d *Data + tu *typeUnit + b buf + err error +} + +// Seek to a new position in the type unit. +func (tur *typeUnitReader) Seek(off Offset) { + tur.err = nil + doff := off - tur.tu.off + if doff < 0 || doff >= Offset(len(tur.tu.data)) { + tur.err = fmt.Errorf("%s: offset %d out of range; max %d", tur.tu.name, doff, len(tur.tu.data)) + return + } + tur.b = makeBuf(tur.d, tur.tu, tur.tu.name, off, tur.tu.data[doff:]) +} + +// Next reads the next Entry from the type unit. +func (tur *typeUnitReader) Next() (*Entry, error) { + if tur.err != nil { + return nil, tur.err + } + if len(tur.tu.data) == 0 { + return nil, nil + } + e := tur.b.entry(tur.tu.atable, tur.tu.base) + if tur.b.err != nil { + tur.err = tur.b.err + return nil, tur.err + } + return e, nil +} + +// clone returns a new reader for the type unit. +func (tur *typeUnitReader) clone() typeReader { + return &typeUnitReader{ + d: tur.d, + tu: tur.tu, + b: makeBuf(tur.d, tur.tu, tur.tu.name, tur.tu.off, tur.tu.data), + } +} + +// offset returns the current offset. +func (tur *typeUnitReader) offset() Offset { + return tur.b.off +} diff --git a/libgo/go/debug/dwarf/unit.go b/libgo/go/debug/dwarf/unit.go index 8e09298a8b..be6093519d 100644 --- a/libgo/go/debug/dwarf/unit.go +++ b/libgo/go/debug/dwarf/unit.go @@ -76,7 +76,7 @@ func (d *Data) parseUnits() ([]unit, error) { n = uint32(b.uint64()) } vers := b.uint16() - if vers < 2 || vers > 4 { + if vers != 2 && vers != 3 && vers != 4 { b.error("unsupported DWARF version " + strconv.Itoa(int(vers))) break } diff --git a/libgo/go/debug/elf/elf.go b/libgo/go/debug/elf/elf.go index 6d6433d1ca..a9466bbdcd 100644 --- a/libgo/go/debug/elf/elf.go +++ b/libgo/go/debug/elf/elf.go @@ -519,7 +519,7 @@ const ( DT_INIT_ARRAY DynTag = 25 /* Address of the array of pointers to initialization functions */ DT_FINI_ARRAY DynTag = 26 /* Address of the array of pointers to termination functions */ DT_INIT_ARRAYSZ DynTag = 27 /* Size in bytes of the array of initialization functions. */ - DT_FINI_ARRAYSZ DynTag = 28 /* Size in bytes of the array of terminationfunctions. */ + DT_FINI_ARRAYSZ DynTag = 28 /* Size in bytes of the array of termination functions. */ DT_RUNPATH DynTag = 29 /* String table offset of a null-terminated library search path string. */ DT_FLAGS DynTag = 30 /* Object specific flag values. */ DT_ENCODING DynTag = 32 /* Values greater than or equal to DT_ENCODING @@ -1414,6 +1414,250 @@ var rppcStrings = []intName{ func (i R_PPC) String() string { return stringName(uint32(i), rppcStrings, false) } func (i R_PPC) GoString() string { return stringName(uint32(i), rppcStrings, true) } +// Relocation types for PowerPC 64. +type R_PPC64 int + +const ( + R_PPC64_NONE R_PPC64 = 0 + R_PPC64_ADDR32 R_PPC64 = 1 + R_PPC64_ADDR24 R_PPC64 = 2 + R_PPC64_ADDR16 R_PPC64 = 3 + R_PPC64_ADDR16_LO R_PPC64 = 4 + R_PPC64_ADDR16_HI R_PPC64 = 5 + R_PPC64_ADDR16_HA R_PPC64 = 6 + R_PPC64_ADDR14 R_PPC64 = 7 + R_PPC64_ADDR14_BRTAKEN R_PPC64 = 8 + R_PPC64_ADDR14_BRNTAKEN R_PPC64 = 9 + R_PPC64_REL24 R_PPC64 = 10 + R_PPC64_REL14 R_PPC64 = 11 + R_PPC64_REL14_BRTAKEN R_PPC64 = 12 + R_PPC64_REL14_BRNTAKEN R_PPC64 = 13 + R_PPC64_GOT16 R_PPC64 = 14 + R_PPC64_GOT16_LO R_PPC64 = 15 + R_PPC64_GOT16_HI R_PPC64 = 16 + R_PPC64_GOT16_HA R_PPC64 = 17 + R_PPC64_JMP_SLOT R_PPC64 = 21 + R_PPC64_REL32 R_PPC64 = 26 + R_PPC64_ADDR64 R_PPC64 = 38 + R_PPC64_ADDR16_HIGHER R_PPC64 = 39 + R_PPC64_ADDR16_HIGHERA R_PPC64 = 40 + R_PPC64_ADDR16_HIGHEST R_PPC64 = 41 + R_PPC64_ADDR16_HIGHESTA R_PPC64 = 42 + R_PPC64_REL64 R_PPC64 = 44 + R_PPC64_TOC16 R_PPC64 = 47 + R_PPC64_TOC16_LO R_PPC64 = 48 + R_PPC64_TOC16_HI R_PPC64 = 49 + R_PPC64_TOC16_HA R_PPC64 = 50 + R_PPC64_TOC R_PPC64 = 51 + R_PPC64_ADDR16_DS R_PPC64 = 56 + R_PPC64_ADDR16_LO_DS R_PPC64 = 57 + R_PPC64_GOT16_DS R_PPC64 = 58 + R_PPC64_GOT16_LO_DS R_PPC64 = 59 + R_PPC64_TOC16_DS R_PPC64 = 63 + R_PPC64_TOC16_LO_DS R_PPC64 = 64 + R_PPC64_TLS R_PPC64 = 67 + R_PPC64_DTPMOD64 R_PPC64 = 68 + R_PPC64_TPREL16 R_PPC64 = 69 + R_PPC64_TPREL16_LO R_PPC64 = 70 + R_PPC64_TPREL16_HI R_PPC64 = 71 + R_PPC64_TPREL16_HA R_PPC64 = 72 + R_PPC64_TPREL64 R_PPC64 = 73 + R_PPC64_DTPREL16 R_PPC64 = 74 + R_PPC64_DTPREL16_LO R_PPC64 = 75 + R_PPC64_DTPREL16_HI R_PPC64 = 76 + R_PPC64_DTPREL16_HA R_PPC64 = 77 + R_PPC64_DTPREL64 R_PPC64 = 78 + R_PPC64_GOT_TLSGD16 R_PPC64 = 79 + R_PPC64_GOT_TLSGD16_LO R_PPC64 = 80 + R_PPC64_GOT_TLSGD16_HI R_PPC64 = 81 + R_PPC64_GOT_TLSGD16_HA R_PPC64 = 82 + R_PPC64_GOT_TLSLD16 R_PPC64 = 83 + R_PPC64_GOT_TLSLD16_LO R_PPC64 = 84 + R_PPC64_GOT_TLSLD16_HI R_PPC64 = 85 + R_PPC64_GOT_TLSLD16_HA R_PPC64 = 86 + R_PPC64_GOT_TPREL16_DS R_PPC64 = 87 + R_PPC64_GOT_TPREL16_LO_DS R_PPC64 = 88 + R_PPC64_GOT_TPREL16_HI R_PPC64 = 89 + R_PPC64_GOT_TPREL16_HA R_PPC64 = 90 + R_PPC64_GOT_DTPREL16_DS R_PPC64 = 91 + R_PPC64_GOT_DTPREL16_LO_DS R_PPC64 = 92 + R_PPC64_GOT_DTPREL16_HI R_PPC64 = 93 + R_PPC64_GOT_DTPREL16_HA R_PPC64 = 94 + R_PPC64_TPREL16_DS R_PPC64 = 95 + R_PPC64_TPREL16_LO_DS R_PPC64 = 96 + R_PPC64_TPREL16_HIGHER R_PPC64 = 97 + R_PPC64_TPREL16_HIGHERA R_PPC64 = 98 + R_PPC64_TPREL16_HIGHEST R_PPC64 = 99 + R_PPC64_TPREL16_HIGHESTA R_PPC64 = 100 + R_PPC64_DTPREL16_DS R_PPC64 = 101 + R_PPC64_DTPREL16_LO_DS R_PPC64 = 102 + R_PPC64_DTPREL16_HIGHER R_PPC64 = 103 + R_PPC64_DTPREL16_HIGHERA R_PPC64 = 104 + R_PPC64_DTPREL16_HIGHEST R_PPC64 = 105 + R_PPC64_DTPREL16_HIGHESTA R_PPC64 = 106 + R_PPC64_TLSGD R_PPC64 = 107 + R_PPC64_TLSLD R_PPC64 = 108 + R_PPC64_REL16 R_PPC64 = 249 + R_PPC64_REL16_LO R_PPC64 = 250 + R_PPC64_REL16_HI R_PPC64 = 251 + R_PPC64_REL16_HA R_PPC64 = 252 +) + +var rppc64Strings = []intName{ + {0, "R_PPC64_NONE"}, + {1, "R_PPC64_ADDR32"}, + {2, "R_PPC64_ADDR24"}, + {3, "R_PPC64_ADDR16"}, + {4, "R_PPC64_ADDR16_LO"}, + {5, "R_PPC64_ADDR16_HI"}, + {6, "R_PPC64_ADDR16_HA"}, + {7, "R_PPC64_ADDR14"}, + {8, "R_PPC64_ADDR14_BRTAKEN"}, + {9, "R_PPC64_ADDR14_BRNTAKEN"}, + {10, "R_PPC64_REL24"}, + {11, "R_PPC64_REL14"}, + {12, "R_PPC64_REL14_BRTAKEN"}, + {13, "R_PPC64_REL14_BRNTAKEN"}, + {14, "R_PPC64_GOT16"}, + {15, "R_PPC64_GOT16_LO"}, + {16, "R_PPC64_GOT16_HI"}, + {17, "R_PPC64_GOT16_HA"}, + {21, "R_PPC64_JMP_SLOT"}, + {26, "R_PPC64_REL32"}, + {38, "R_PPC64_ADDR64"}, + {39, "R_PPC64_ADDR16_HIGHER"}, + {40, "R_PPC64_ADDR16_HIGHERA"}, + {41, "R_PPC64_ADDR16_HIGHEST"}, + {42, "R_PPC64_ADDR16_HIGHESTA"}, + {44, "R_PPC64_REL64"}, + {47, "R_PPC64_TOC16"}, + {48, "R_PPC64_TOC16_LO"}, + {49, "R_PPC64_TOC16_HI"}, + {50, "R_PPC64_TOC16_HA"}, + {51, "R_PPC64_TOC"}, + {56, "R_PPC64_ADDR16_DS"}, + {57, "R_PPC64_ADDR16_LO_DS"}, + {58, "R_PPC64_GOT16_DS"}, + {59, "R_PPC64_GOT16_LO_DS"}, + {63, "R_PPC64_TOC16_DS"}, + {64, "R_PPC64_TOC16_LO_DS"}, + {67, "R_PPC64_TLS"}, + {68, "R_PPC64_DTPMOD64"}, + {69, "R_PPC64_TPREL16"}, + {70, "R_PPC64_TPREL16_LO"}, + {71, "R_PPC64_TPREL16_HI"}, + {72, "R_PPC64_TPREL16_HA"}, + {73, "R_PPC64_TPREL64"}, + {74, "R_PPC64_DTPREL16"}, + {75, "R_PPC64_DTPREL16_LO"}, + {76, "R_PPC64_DTPREL16_HI"}, + {77, "R_PPC64_DTPREL16_HA"}, + {78, "R_PPC64_DTPREL64"}, + {79, "R_PPC64_GOT_TLSGD16"}, + {80, "R_PPC64_GOT_TLSGD16_LO"}, + {81, "R_PPC64_GOT_TLSGD16_HI"}, + {82, "R_PPC64_GOT_TLSGD16_HA"}, + {83, "R_PPC64_GOT_TLSLD16"}, + {84, "R_PPC64_GOT_TLSLD16_LO"}, + {85, "R_PPC64_GOT_TLSLD16_HI"}, + {86, "R_PPC64_GOT_TLSLD16_HA"}, + {87, "R_PPC64_GOT_TPREL16_DS"}, + {88, "R_PPC64_GOT_TPREL16_LO_DS"}, + {89, "R_PPC64_GOT_TPREL16_HI"}, + {90, "R_PPC64_GOT_TPREL16_HA"}, + {91, "R_PPC64_GOT_DTPREL16_DS"}, + {92, "R_PPC64_GOT_DTPREL16_LO_DS"}, + {93, "R_PPC64_GOT_DTPREL16_HI"}, + {94, "R_PPC64_GOT_DTPREL16_HA"}, + {95, "R_PPC64_TPREL16_DS"}, + {96, "R_PPC64_TPREL16_LO_DS"}, + {97, "R_PPC64_TPREL16_HIGHER"}, + {98, "R_PPC64_TPREL16_HIGHERA"}, + {99, "R_PPC64_TPREL16_HIGHEST"}, + {100, "R_PPC64_TPREL16_HIGHESTA"}, + {101, "R_PPC64_DTPREL16_DS"}, + {102, "R_PPC64_DTPREL16_LO_DS"}, + {103, "R_PPC64_DTPREL16_HIGHER"}, + {104, "R_PPC64_DTPREL16_HIGHERA"}, + {105, "R_PPC64_DTPREL16_HIGHEST"}, + {106, "R_PPC64_DTPREL16_HIGHESTA"}, + {107, "R_PPC64_TLSGD"}, + {108, "R_PPC64_TLSLD"}, + {249, "R_PPC64_REL16"}, + {250, "R_PPC64_REL16_LO"}, + {251, "R_PPC64_REL16_HI"}, + {252, "R_PPC64_REL16_HA"}, +} + +func (i R_PPC64) String() string { return stringName(uint32(i), rppc64Strings, false) } +func (i R_PPC64) GoString() string { return stringName(uint32(i), rppc64Strings, true) } + +// Relocation types for s390 +type R_390 int + +const ( + R_390_NONE R_390 = 0 + R_390_8 R_390 = 1 + R_390_12 R_390 = 2 + R_390_16 R_390 = 3 + R_390_32 R_390 = 4 + R_390_PC32 R_390 = 5 + R_390_GOT12 R_390 = 6 + R_390_GOT32 R_390 = 7 + R_390_PLT32 R_390 = 8 + R_390_COPY R_390 = 9 + R_390_GLOB_DAT R_390 = 10 + R_390_JMP_SLOT R_390 = 11 + R_390_RELATIVE R_390 = 12 + R_390_GOTOFF R_390 = 13 + R_390_GOTPC R_390 = 14 + R_390_GOT16 R_390 = 15 + R_390_PC16 R_390 = 16 + R_390_PC16DBL R_390 = 17 + R_390_PLT16DBL R_390 = 18 + R_390_PC32DBL R_390 = 19 + R_390_PLT32DBL R_390 = 20 + R_390_GOTPCDBL R_390 = 21 + R_390_64 R_390 = 22 + R_390_PC64 R_390 = 23 + R_390_GOT64 R_390 = 24 + R_390_PLT64 R_390 = 25 + R_390_GOTENT R_390 = 26 +) + +var r390Strings = []intName{ + {0, "R_390_NONE"}, + {1, "R_390_8"}, + {2, "R_390_12"}, + {3, "R_390_16"}, + {4, "R_390_32"}, + {5, "R_390_PC32"}, + {6, "R_390_GOT12"}, + {7, "R_390_GOT32"}, + {8, "R_390_PLT32"}, + {9, "R_390_COPY"}, + {10, "R_390_GLOB_DAT"}, + {11, "R_390_JMP_SLOT"}, + {12, "R_390_RELATIVE"}, + {13, "R_390_GOTOFF"}, + {14, "R_390_GOTPC"}, + {15, "R_390_GOT16"}, + {16, "R_390_PC16"}, + {17, "R_390_PC16DBL"}, + {18, "R_390_PLT16DBL"}, + {19, "R_390_PC32DBL"}, + {20, "R_390_PLT32DBL"}, + {21, "R_390_GOTPCDBL"}, + {22, "R_390_64"}, + {23, "R_390_PC64"}, + {24, "R_390_GOT64"}, + {25, "R_390_PLT64"}, + {26, "R_390_GOTENT"}, +} + +func (i R_390) String() string { return stringName(uint32(i), r390Strings, false) } +func (i R_390) GoString() string { return stringName(uint32(i), r390Strings, true) } + // Relocation types for SPARC. type R_SPARC int diff --git a/libgo/go/debug/elf/elf_test.go b/libgo/go/debug/elf/elf_test.go index 67b961b5c6..e3c51bb717 100644 --- a/libgo/go/debug/elf/elf_test.go +++ b/libgo/go/debug/elf/elf_test.go @@ -43,7 +43,7 @@ func TestNames(t *testing.T) { for i, tt := range nameTests { s := fmt.Sprint(tt.val) if s != tt.str { - t.Errorf("#%d: want %q have %q", i, s, tt.str) + t.Errorf("#%d: Sprint(%d) = %q, want %q", i, tt.val, s, tt.str) } } } diff --git a/libgo/go/debug/elf/file.go b/libgo/go/debug/elf/file.go index f6e7e31a8e..0135f7f8db 100644 --- a/libgo/go/debug/elf/file.go +++ b/libgo/go/debug/elf/file.go @@ -76,6 +76,9 @@ type Section struct { func (s *Section) Data() ([]byte, error) { dat := make([]byte, s.sr.Size()) n, err := s.sr.ReadAt(dat, 0) + if n == len(dat) { + err = nil + } return dat[0:n], err } @@ -402,17 +405,21 @@ func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, error) { return nil, nil, errors.New("not implemented") } +// ErrNoSymbols is returned by File.Symbols and File.DynamicSymbols +// if there is no such section in the File. +var ErrNoSymbols = errors.New("no symbol section") + func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) { symtabSection := f.SectionByType(typ) if symtabSection == nil { - return nil, nil, errors.New("no symbol section") + return nil, nil, ErrNoSymbols } data, err := symtabSection.Data() if err != nil { return nil, nil, errors.New("cannot load symbol section") } - symtab := bytes.NewBuffer(data) + symtab := bytes.NewReader(data) if symtab.Len()%Sym32Size != 0 { return nil, nil, errors.New("length of symbol section is not a multiple of SymSize") } @@ -448,14 +455,14 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) { func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) { symtabSection := f.SectionByType(typ) if symtabSection == nil { - return nil, nil, errors.New("no symbol section") + return nil, nil, ErrNoSymbols } data, err := symtabSection.Data() if err != nil { return nil, nil, errors.New("cannot load symbol section") } - symtab := bytes.NewBuffer(data) + symtab := bytes.NewReader(data) if symtab.Len()%Sym64Size != 0 { return nil, nil, errors.New("length of symbol section is not a multiple of Sym64Size") } @@ -519,16 +526,29 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error { if f.Class == ELFCLASS64 && f.Machine == EM_X86_64 { return f.applyRelocationsAMD64(dst, rels) } + if f.Class == ELFCLASS32 && f.Machine == EM_386 { + return f.applyRelocations386(dst, rels) + } if f.Class == ELFCLASS64 && f.Machine == EM_AARCH64 { return f.applyRelocationsARM64(dst, rels) } + if f.Class == ELFCLASS32 && f.Machine == EM_PPC { + return f.applyRelocationsPPC(dst, rels) + } + if f.Class == ELFCLASS64 && f.Machine == EM_PPC64 { + return f.applyRelocationsPPC64(dst, rels) + } + if f.Class == ELFCLASS64 && f.Machine == EM_S390 { + return f.applyRelocationsS390x(dst, rels) + } return errors.New("not implemented") } func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error { - if len(rels)%Sym64Size != 0 { - return errors.New("length of relocation section is not a multiple of Sym64Size") + // 24 is the size of Rela64. + if len(rels)%24 != 0 { + return errors.New("length of relocation section is not a multiple of 24") } symbols, _, err := f.getSymbols(SHT_SYMTAB) @@ -536,7 +556,7 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error { return err } - b := bytes.NewBuffer(rels) + b := bytes.NewReader(rels) var rela Rela64 for b.Len() > 0 { @@ -553,6 +573,10 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error { continue } + // There are relocations, so this must be a normal + // object file, and we only look at section symbols, + // so we assume that the symbol value is 0. + switch t { case R_X86_64_64: if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { @@ -570,6 +594,43 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error { return nil } +func (f *File) applyRelocations386(dst []byte, rels []byte) error { + // 8 is the size of Rel32. + if len(rels)%8 != 0 { + return errors.New("length of relocation section is not a multiple of 8") + } + + symbols, _, err := f.getSymbols(SHT_SYMTAB) + if err != nil { + return err + } + + b := bytes.NewReader(rels) + var rel Rel32 + + for b.Len() > 0 { + binary.Read(b, f.ByteOrder, &rel) + symNo := rel.Info >> 8 + t := R_386(rel.Info & 0xff) + + if symNo == 0 || symNo > uint32(len(symbols)) { + continue + } + sym := &symbols[symNo-1] + + if t == R_386_32 { + if rel.Off+4 >= uint32(len(dst)) { + continue + } + val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4]) + val += uint32(sym.Value) + f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val) + } + } + + return nil +} + func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error { // 24 is the size of Rela64. if len(rels)%24 != 0 { @@ -598,6 +659,10 @@ func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error { continue } + // There are relocations, so this must be a normal + // object file, and we only look at section symbols, + // so we assume that the symbol value is 0. + switch t { case R_AARCH64_ABS64: if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { @@ -615,6 +680,132 @@ func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error { return nil } +func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error { + // 12 is the size of Rela32. + if len(rels)%12 != 0 { + return errors.New("length of relocation section is not a multiple of 12") + } + + symbols, _, err := f.getSymbols(SHT_SYMTAB) + if err != nil { + return err + } + + b := bytes.NewReader(rels) + var rela Rela32 + + for b.Len() > 0 { + binary.Read(b, f.ByteOrder, &rela) + symNo := rela.Info >> 8 + t := R_PPC(rela.Info & 0xff) + + if symNo == 0 || symNo > uint32(len(symbols)) { + continue + } + sym := &symbols[symNo-1] + if SymType(sym.Info&0xf) != STT_SECTION { + // We don't handle non-section relocations for now. + continue + } + + switch t { + case R_PPC_ADDR32: + if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 { + continue + } + f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) + } + } + + return nil +} + +func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error { + // 24 is the size of Rela64. + if len(rels)%24 != 0 { + return errors.New("length of relocation section is not a multiple of 24") + } + + symbols, _, err := f.getSymbols(SHT_SYMTAB) + if err != nil { + return err + } + + b := bytes.NewReader(rels) + var rela Rela64 + + for b.Len() > 0 { + binary.Read(b, f.ByteOrder, &rela) + symNo := rela.Info >> 32 + t := R_PPC64(rela.Info & 0xffff) + + if symNo == 0 || symNo > uint64(len(symbols)) { + continue + } + sym := &symbols[symNo-1] + if SymType(sym.Info&0xf) != STT_SECTION { + // We don't handle non-section relocations for now. + continue + } + + switch t { + case R_PPC64_ADDR64: + if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { + continue + } + f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)) + case R_PPC64_ADDR32: + if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { + continue + } + f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) + } + } + + return nil +} + +func (f *File) applyRelocationsS390x(dst []byte, rels []byte) error { + // 24 is the size of Rela64. + if len(rels)%24 != 0 { + return errors.New("length of relocation section is not a multiple of 24") + } + + symbols, _, err := f.getSymbols(SHT_SYMTAB) + if err != nil { + return err + } + + b := bytes.NewBuffer(rels) + var rela Rela64 + + for b.Len() > 0 { + binary.Read(b, f.ByteOrder, &rela) + symNo := rela.Info >> 32 + t := R_390(rela.Info & 0xffff) + + if symNo == 0 || symNo > uint64(len(symbols)) { + continue + } + sym := &symbols[symNo-1] + + switch t { + case R_390_64: + if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { + continue + } + f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)+uint64(sym.Value)) + case R_390_32: + if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { + continue + } + f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)+uint32(sym.Value)) + } + } + + return nil +} + func (f *File) DWARF() (*dwarf.Data, error) { // There are many other DWARF sections, but these // are the required ones, and the debug/dwarf package @@ -637,7 +828,7 @@ func (f *File) DWARF() (*dwarf.Data, error) { // If there's a relocation table for .debug_info, we have to process it // now otherwise the data in .debug_info is invalid for x86-64 objects. rela := f.Section(".rela.debug_info") - if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_AARCH64) { + if rela != nil && rela.Type == SHT_RELA && (f.Machine == EM_X86_64 || f.Machine == EM_AARCH64 || f.Machine == EM_PPC || f.Machine == EM_PPC64 || f.Machine == EM_S390) { data, err := rela.Data() if err != nil { return nil, err @@ -648,11 +839,62 @@ func (f *File) DWARF() (*dwarf.Data, error) { } } + // When using clang we need to process relocations even for 386. + rel := f.Section(".rel.debug_info") + if rel != nil && rel.Type == SHT_REL && f.Machine == EM_386 { + data, err := rel.Data() + if err != nil { + return nil, err + } + err = f.applyRelocations(dat[1], data) + if err != nil { + return nil, err + } + } + abbrev, info, line, ranges, str := dat[0], dat[1], dat[2], dat[3], dat[4] - return dwarf.New(abbrev, nil, nil, info, line, nil, ranges, str) + d, err := dwarf.New(abbrev, nil, nil, info, line, nil, ranges, str) + if err != nil { + return nil, err + } + + // Look for DWARF4 .debug_types sections. + for i, s := range f.Sections { + if s.Name == ".debug_types" { + b, err := s.Data() + if err != nil && uint64(len(b)) < s.Size { + return nil, err + } + + for _, r := range f.Sections { + if r.Type != SHT_RELA && r.Type != SHT_REL { + continue + } + if int(r.Info) != i { + continue + } + rd, err := r.Data() + if err != nil { + return nil, err + } + err = f.applyRelocations(b, rd) + if err != nil { + return nil, err + } + } + + err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + if err != nil { + return nil, err + } + } + } + + return d, nil } -// Symbols returns the symbol table for f. +// Symbols returns the symbol table for f. The symbols will be listed in the order +// they appear in f. // // For compatibility with Go 1.0, Symbols omits the null symbol at index 0. // After retrieving the symbols as symtab, an externally supplied index x @@ -662,6 +904,17 @@ func (f *File) Symbols() ([]Symbol, error) { return sym, err } +// DynamicSymbols returns the dynamic symbol table for f. The symbols +// will be listed in the order they appear in f. +// +// For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0. +// After retrieving the symbols as symtab, an externally supplied index x +// corresponds to symtab[x-1], not symtab[x]. +func (f *File) DynamicSymbols() ([]Symbol, error) { + sym, _, err := f.getSymbols(SHT_DYNSYM) + return sym, err +} + type ImportedSymbol struct { Name string Version string diff --git a/libgo/go/debug/elf/file_test.go b/libgo/go/debug/elf/file_test.go index 38b5f9e707..56e2604d9d 100644 --- a/libgo/go/debug/elf/file_test.go +++ b/libgo/go/debug/elf/file_test.go @@ -166,11 +166,11 @@ func TestOpen(t *testing.T) { } else { f, err = Open(tt.file) } - defer f.Close() if err != nil { t.Errorf("cannot open file %s: %v", tt.file, err) continue } + defer f.Close() if !reflect.DeepEqual(f.FileHeader, tt.hdr) { t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr) continue @@ -260,6 +260,30 @@ var relocationTests = []relocationTest{ {0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: uint64(0x6)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}}, }, }, + { + "testdata/go-relocation-test-gcc5-ppc.obj", + []relocationTestEntry{ + {0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{dwarf.Field{Attr: dwarf.AttrProducer, Val: "GNU C11 5.0.0 20150116 (experimental) -Asystem=linux -Asystem=unix -Asystem=posix -g"}, dwarf.Field{Attr: dwarf.AttrLanguage, Val: int64(12)}, dwarf.Field{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc5-ppc.c"}, dwarf.Field{Attr: dwarf.AttrCompDir, Val: "/tmp"}, dwarf.Field{Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, dwarf.Field{Attr: dwarf.AttrHighpc, Val: int64(0x44)}, dwarf.Field{Attr: dwarf.AttrStmtList, Val: int64(0)}}}}, + }, + }, + { + "testdata/go-relocation-test-gcc482-ppc64le.obj", + []relocationTestEntry{ + {0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{dwarf.Field{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -mtune=power8 -mcpu=power7 -gdwarf-2 -fstack-protector"}, dwarf.Field{Attr: dwarf.AttrLanguage, Val: int64(1)}, dwarf.Field{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c"}, dwarf.Field{Attr: dwarf.AttrCompDir, Val: "/tmp"}, dwarf.Field{Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, dwarf.Field{Attr: dwarf.AttrHighpc, Val: uint64(0x24)}, dwarf.Field{Attr: dwarf.AttrStmtList, Val: int64(0)}}}}, + }, + }, + { + "testdata/go-relocation-test-gcc482-aarch64.obj", + []relocationTestEntry{ + {0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector"}, {Attr: dwarf.AttrLanguage, Val: int64(1)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c"}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0)}, {Attr: dwarf.AttrHighpc, Val: int64(0x24)}, {Attr: dwarf.AttrStmtList, Val: int64(0)}}}}, + }, + }, + { + "testdata/go-relocation-test-clang-x86.obj", + []relocationTestEntry{ + {0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)"}, {Attr: dwarf.AttrLanguage, Val: int64(12)}, {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c"}, {Attr: dwarf.AttrStmtList, Val: int64(0)}, {Attr: dwarf.AttrCompDir, Val: "/tmp"}}}}, + }, + }, { "testdata/gcc-amd64-openbsd-debug-with-rela.obj", []relocationTestEntry{ diff --git a/libgo/go/debug/elf/symbols_test.go b/libgo/go/debug/elf/symbols_test.go new file mode 100644 index 0000000000..1b79520e3c --- /dev/null +++ b/libgo/go/debug/elf/symbols_test.go @@ -0,0 +1,834 @@ +// 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 elf + +import ( + "io" + "path" + "reflect" + "testing" +) + +// TODO: remove duplicate code +func TestSymbols(t *testing.T) { + do := func(file string, ts []Symbol, getfunc func(*File) ([]Symbol, error)) { + var f *File + var err error + if path.Ext(file) == ".gz" { + var r io.ReaderAt + if r, err = decompress(file); err == nil { + f, err = NewFile(r) + } + } else { + f, err = Open(file) + } + if err != nil { + t.Errorf("TestSymbols: cannot open file %s: %v", file, err) + return + } + defer f.Close() + fs, err := getfunc(f) + if err != nil && err != ErrNoSymbols { + t.Error(err) + return + } else if err == ErrNoSymbols { + fs = []Symbol{} + } + if !reflect.DeepEqual(ts, fs) { + t.Errorf("%s: Symbols = %v, want %v", file, ts, fs) + } + } + for file, ts := range symbolsGolden { + do(file, ts, (*File).Symbols) + } + for file, ts := range dynamicSymbolsGolden { + do(file, ts, (*File).DynamicSymbols) + } +} + +// golden symbol table data generated by testdata/getgoldsym.c + +var symbolsGolden = map[string][]Symbol{ + "testdata/gcc-amd64-linux-exec": { + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x1, + Value: 0x400200, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x2, + Value: 0x40021C, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x3, + Value: 0x400240, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x4, + Value: 0x400268, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x5, + Value: 0x400288, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x6, + Value: 0x4002E8, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x7, + Value: 0x400326, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x8, + Value: 0x400330, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x9, + Value: 0x400350, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0xA, + Value: 0x400368, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0xB, + Value: 0x400398, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0xC, + Value: 0x4003B0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0xD, + Value: 0x4003E0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0xE, + Value: 0x400594, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0xF, + Value: 0x4005A4, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x10, + Value: 0x4005B8, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x11, + Value: 0x4005E0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x12, + Value: 0x600688, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x13, + Value: 0x600698, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x14, + Value: 0x6006A8, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x15, + Value: 0x6006B0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x16, + Value: 0x600850, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x17, + Value: 0x600858, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x18, + Value: 0x600880, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x19, + Value: 0x600898, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x1A, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x1B, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x1C, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x1D, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x1E, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x1F, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x20, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x21, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "init.c", + Info: 0x4, + Other: 0x0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "initfini.c", + Info: 0x4, + Other: 0x0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "call_gmon_start", + Info: 0x2, + Other: 0x0, + Section: 0xD, + Value: 0x40040C, + Size: 0x0, + }, + Symbol{ + Name: "crtstuff.c", + Info: 0x4, + Other: 0x0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "__CTOR_LIST__", + Info: 0x1, + Other: 0x0, + Section: 0x12, + Value: 0x600688, + Size: 0x0, + }, + Symbol{ + Name: "__DTOR_LIST__", + Info: 0x1, + Other: 0x0, + Section: 0x13, + Value: 0x600698, + Size: 0x0, + }, + Symbol{ + Name: "__JCR_LIST__", + Info: 0x1, + Other: 0x0, + Section: 0x14, + Value: 0x6006A8, + Size: 0x0, + }, + Symbol{ + Name: "__do_global_dtors_aux", + Info: 0x2, + Other: 0x0, + Section: 0xD, + Value: 0x400430, + Size: 0x0, + }, + Symbol{ + Name: "completed.6183", + Info: 0x1, + Other: 0x0, + Section: 0x19, + Value: 0x600898, + Size: 0x1, + }, + Symbol{ + Name: "p.6181", + Info: 0x1, + Other: 0x0, + Section: 0x18, + Value: 0x600890, + Size: 0x0, + }, + Symbol{ + Name: "frame_dummy", + Info: 0x2, + Other: 0x0, + Section: 0xD, + Value: 0x400470, + Size: 0x0, + }, + Symbol{ + Name: "crtstuff.c", + Info: 0x4, + Other: 0x0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "__CTOR_END__", + Info: 0x1, + Other: 0x0, + Section: 0x12, + Value: 0x600690, + Size: 0x0, + }, + Symbol{ + Name: "__DTOR_END__", + Info: 0x1, + Other: 0x0, + Section: 0x13, + Value: 0x6006A0, + Size: 0x0, + }, + Symbol{ + Name: "__FRAME_END__", + Info: 0x1, + Other: 0x0, + Section: 0x11, + Value: 0x400680, + Size: 0x0, + }, + Symbol{ + Name: "__JCR_END__", + Info: 0x1, + Other: 0x0, + Section: 0x14, + Value: 0x6006A8, + Size: 0x0, + }, + Symbol{ + Name: "__do_global_ctors_aux", + Info: 0x2, + Other: 0x0, + Section: 0xD, + Value: 0x400560, + Size: 0x0, + }, + Symbol{ + Name: "initfini.c", + Info: 0x4, + Other: 0x0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "hello.c", + Info: 0x4, + Other: 0x0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "_GLOBAL_OFFSET_TABLE_", + Info: 0x1, + Other: 0x2, + Section: 0x17, + Value: 0x600858, + Size: 0x0, + }, + Symbol{ + Name: "__init_array_end", + Info: 0x0, + Other: 0x2, + Section: 0x12, + Value: 0x600684, + Size: 0x0, + }, + Symbol{ + Name: "__init_array_start", + Info: 0x0, + Other: 0x2, + Section: 0x12, + Value: 0x600684, + Size: 0x0, + }, + Symbol{ + Name: "_DYNAMIC", + Info: 0x1, + Other: 0x2, + Section: 0x15, + Value: 0x6006B0, + Size: 0x0, + }, + Symbol{ + Name: "data_start", + Info: 0x20, + Other: 0x0, + Section: 0x18, + Value: 0x600880, + Size: 0x0, + }, + Symbol{ + Name: "__libc_csu_fini", + Info: 0x12, + Other: 0x0, + Section: 0xD, + Value: 0x4004C0, + Size: 0x2, + }, + Symbol{ + Name: "_start", + Info: 0x12, + Other: 0x0, + Section: 0xD, + Value: 0x4003E0, + Size: 0x0, + }, + Symbol{ + Name: "__gmon_start__", + Info: 0x20, + Other: 0x0, + Section: 0x0, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "_Jv_RegisterClasses", + Info: 0x20, + Other: 0x0, + Section: 0x0, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "puts@@GLIBC_2.2.5", + Info: 0x12, + Other: 0x0, + Section: 0x0, + Value: 0x0, + Size: 0x18C, + }, + Symbol{ + Name: "_fini", + Info: 0x12, + Other: 0x0, + Section: 0xE, + Value: 0x400594, + Size: 0x0, + }, + Symbol{ + Name: "__libc_start_main@@GLIBC_2.2.5", + Info: 0x12, + Other: 0x0, + Section: 0x0, + Value: 0x0, + Size: 0x1C2, + }, + Symbol{ + Name: "_IO_stdin_used", + Info: 0x11, + Other: 0x0, + Section: 0xF, + Value: 0x4005A4, + Size: 0x4, + }, + Symbol{ + Name: "__data_start", + Info: 0x10, + Other: 0x0, + Section: 0x18, + Value: 0x600880, + Size: 0x0, + }, + Symbol{ + Name: "__dso_handle", + Info: 0x11, + Other: 0x2, + Section: 0x18, + Value: 0x600888, + Size: 0x0, + }, + Symbol{ + Name: "__libc_csu_init", + Info: 0x12, + Other: 0x0, + Section: 0xD, + Value: 0x4004D0, + Size: 0x89, + }, + Symbol{ + Name: "__bss_start", + Info: 0x10, + Other: 0x0, + Section: 0xFFF1, + Value: 0x600898, + Size: 0x0, + }, + Symbol{ + Name: "_end", + Info: 0x10, + Other: 0x0, + Section: 0xFFF1, + Value: 0x6008A0, + Size: 0x0, + }, + Symbol{ + Name: "_edata", + Info: 0x10, + Other: 0x0, + Section: 0xFFF1, + Value: 0x600898, + Size: 0x0, + }, + Symbol{ + Name: "main", + Info: 0x12, + Other: 0x0, + Section: 0xD, + Value: 0x400498, + Size: 0x1B, + }, + Symbol{ + Name: "_init", + Info: 0x12, + Other: 0x0, + Section: 0xB, + Value: 0x400398, + Size: 0x0, + }, + }, + "testdata/go-relocation-test-clang-x86.obj": { + Symbol{ + Name: "go-relocation-test-clang.c", + Info: 0x4, + Other: 0x0, + Section: 0xFFF1, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: ".Linfo_string0", + Info: 0x0, + Other: 0x0, + Section: 0xC, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: ".Linfo_string1", + Info: 0x0, + Other: 0x0, + Section: 0xC, + Value: 0x2C, + Size: 0x0, + }, + Symbol{ + Name: ".Linfo_string2", + Info: 0x0, + Other: 0x0, + Section: 0xC, + Value: 0x47, + Size: 0x0, + }, + Symbol{ + Name: ".Linfo_string3", + Info: 0x0, + Other: 0x0, + Section: 0xC, + Value: 0x4C, + Size: 0x0, + }, + Symbol{ + Name: ".Linfo_string4", + Info: 0x0, + Other: 0x0, + Section: 0xC, + Value: 0x4E, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x1, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x2, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x3, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x4, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x6, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x7, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x8, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0xA, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0xC, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0xD, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0xE, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0xF, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "", + Info: 0x3, + Other: 0x0, + Section: 0x10, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "v", + Info: 0x11, + Other: 0x0, + Section: 0xFFF2, + Value: 0x4, + Size: 0x4, + }, + }, + "testdata/hello-world-core.gz": {}, +} + +var dynamicSymbolsGolden = map[string][]Symbol{ + "testdata/gcc-amd64-linux-exec": { + Symbol{ + Name: "__gmon_start__", + Info: 0x20, + Other: 0x0, + Section: 0x0, + Value: 0x0, + Size: 0x0, + }, + Symbol{ + Name: "puts", + Info: 0x12, + Other: 0x0, + Section: 0x0, + Value: 0x0, + Size: 0x18C, + }, + Symbol{ + Name: "__libc_start_main", + Info: 0x12, + Other: 0x0, + Section: 0x0, + Value: 0x0, + Size: 0x1C2, + }, + }, + "testdata/go-relocation-test-clang-x86.obj": {}, + "testdata/hello-world-core.gz": {}, +} diff --git a/libgo/go/debug/elf/testdata/go-relocation-test-clang-x86.obj b/libgo/go/debug/elf/testdata/go-relocation-test-clang-x86.obj new file mode 100644 index 0000000000..e909cf4e6e Binary files /dev/null and b/libgo/go/debug/elf/testdata/go-relocation-test-clang-x86.obj differ diff --git a/libgo/go/debug/elf/testdata/go-relocation-test-gcc482-aarch64.obj b/libgo/go/debug/elf/testdata/go-relocation-test-gcc482-aarch64.obj new file mode 100644 index 0000000000..849e2644ec Binary files /dev/null and b/libgo/go/debug/elf/testdata/go-relocation-test-gcc482-aarch64.obj differ diff --git a/libgo/go/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj b/libgo/go/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj new file mode 100644 index 0000000000..dad7445486 Binary files /dev/null and b/libgo/go/debug/elf/testdata/go-relocation-test-gcc482-ppc64le.obj differ diff --git a/libgo/go/debug/elf/testdata/go-relocation-test-gcc5-ppc.obj b/libgo/go/debug/elf/testdata/go-relocation-test-gcc5-ppc.obj new file mode 100644 index 0000000000..f4165af098 Binary files /dev/null and b/libgo/go/debug/elf/testdata/go-relocation-test-gcc5-ppc.obj differ diff --git a/libgo/go/debug/elf/testdata/hello.c b/libgo/go/debug/elf/testdata/hello.c new file mode 100644 index 0000000000..34d9ee7923 --- /dev/null +++ b/libgo/go/debug/elf/testdata/hello.c @@ -0,0 +1,7 @@ +#include + +void +main(int argc, char *argv[]) +{ + printf("hello, world\n"); +} diff --git a/libgo/go/debug/gosym/pclntab.go b/libgo/go/debug/gosym/pclntab.go index 3e6a8046b3..6620aefb05 100644 --- a/libgo/go/debug/gosym/pclntab.go +++ b/libgo/go/debug/gosym/pclntab.go @@ -196,6 +196,33 @@ func (t *LineTable) go12Init() { t.go12 = 1 // so far so good } +// go12Funcs returns a slice of Funcs derived from the Go 1.2 pcln table. +func (t *LineTable) go12Funcs() []Func { + // Assume it is malformed and return nil on error. + defer func() { + recover() + }() + + n := len(t.functab) / int(t.ptrsize) / 2 + funcs := make([]Func, n) + for i := range funcs { + f := &funcs[i] + f.Entry = uint64(t.uintptr(t.functab[2*i*int(t.ptrsize):])) + f.End = uint64(t.uintptr(t.functab[(2*i+2)*int(t.ptrsize):])) + info := t.Data[t.uintptr(t.functab[(2*i+1)*int(t.ptrsize):]):] + f.LineTable = t + f.FrameSize = int(t.binary.Uint32(info[t.ptrsize+2*4:])) + f.Sym = &Sym{ + Value: f.Entry, + Type: 'T', + Name: t.string(t.binary.Uint32(info[t.ptrsize:])), + GoType: 0, + Func: f, + } + } + return funcs +} + // findFunc returns the func corresponding to the given program counter. func (t *LineTable) findFunc(pc uint64) []byte { if pc < t.uintptr(t.functab) || pc >= t.uintptr(t.functab[len(t.functab)-int(t.ptrsize):]) { diff --git a/libgo/go/debug/gosym/symtab.go b/libgo/go/debug/gosym/symtab.go index 9ab05bac2f..ee18499d11 100644 --- a/libgo/go/debug/gosym/symtab.go +++ b/libgo/go/debug/gosym/symtab.go @@ -129,6 +129,9 @@ var ( ) func walksymtab(data []byte, fn func(sym) error) error { + if len(data) == 0 { // missing symtab is okay + return nil + } var order binary.ByteOrder = binary.BigEndian newTable := false switch { @@ -399,7 +402,7 @@ func NewTable(symtab []byte, pcln *LineTable) (*Table, error) { if n := len(t.Funcs); n > 0 { t.Funcs[n-1].End = sym.Value } - if sym.Name == "etext" { + if sym.Name == "runtime.etext" || sym.Name == "etext" { continue } @@ -455,6 +458,10 @@ func NewTable(symtab []byte, pcln *LineTable) (*Table, error) { i = end - 1 // loop will i++ } } + + if t.go12line != nil && nf == 0 { + t.Funcs = t.go12line.go12Funcs() + } if obj != nil { obj.Funcs = t.Funcs[lastf:] } diff --git a/libgo/go/debug/macho/fat.go b/libgo/go/debug/macho/fat.go new file mode 100644 index 0000000000..93b8315263 --- /dev/null +++ b/libgo/go/debug/macho/fat.go @@ -0,0 +1,146 @@ +// 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 macho + +import ( + "encoding/binary" + "fmt" + "io" + "os" +) + +// A FatFile is a Mach-O universal binary that contains at least one architecture. +type FatFile struct { + Magic uint32 + Arches []FatArch + closer io.Closer +} + +// A FatArchHeader represents a fat header for a specific image architecture. +type FatArchHeader struct { + Cpu Cpu + SubCpu uint32 + Offset uint32 + Size uint32 + Align uint32 +} + +const fatArchHeaderSize = 5 * 4 + +// A FatArch is a Mach-O File inside a FatFile. +type FatArch struct { + FatArchHeader + *File +} + +// ErrNotFat is returned from NewFatFile or OpenFat when the file is not a +// universal binary but may be a thin binary, based on its magic number. +var ErrNotFat = &FormatError{0, "not a fat Mach-O file", nil} + +// NewFatFile creates a new FatFile for accessing all the Mach-O images in a +// universal binary. The Mach-O binary is expected to start at position 0 in +// the ReaderAt. +func NewFatFile(r io.ReaderAt) (*FatFile, error) { + var ff FatFile + sr := io.NewSectionReader(r, 0, 1<<63-1) + + // Read the fat_header struct, which is always in big endian. + // Start with the magic number. + err := binary.Read(sr, binary.BigEndian, &ff.Magic) + if err != nil { + return nil, &FormatError{0, "error reading magic number", nil} + } else if ff.Magic != MagicFat { + // See if this is a Mach-O file via its magic number. The magic + // must be converted to little endian first though. + var buf [4]byte + binary.BigEndian.PutUint32(buf[:], ff.Magic) + leMagic := binary.LittleEndian.Uint32(buf[:]) + if leMagic == Magic32 || leMagic == Magic64 { + return nil, ErrNotFat + } else { + return nil, &FormatError{0, "invalid magic number", nil} + } + } + offset := int64(4) + + // Read the number of FatArchHeaders that come after the fat_header. + var narch uint32 + err = binary.Read(sr, binary.BigEndian, &narch) + if err != nil { + return nil, &FormatError{offset, "invalid fat_header", nil} + } + offset += 4 + + if narch < 1 { + return nil, &FormatError{offset, "file contains no images", nil} + } + + // Combine the Cpu and SubCpu (both uint32) into a uint64 to make sure + // there are not duplicate architectures. + seenArches := make(map[uint64]bool, narch) + // Make sure that all images are for the same MH_ type. + var machoType Type + + // Following the fat_header comes narch fat_arch structs that index + // Mach-O images further in the file. + ff.Arches = make([]FatArch, narch) + for i := uint32(0); i < narch; i++ { + fa := &ff.Arches[i] + err = binary.Read(sr, binary.BigEndian, &fa.FatArchHeader) + if err != nil { + return nil, &FormatError{offset, "invalid fat_arch header", nil} + } + offset += fatArchHeaderSize + + fr := io.NewSectionReader(r, int64(fa.Offset), int64(fa.Size)) + fa.File, err = NewFile(fr) + if err != nil { + return nil, err + } + + // Make sure the architecture for this image is not duplicate. + seenArch := (uint64(fa.Cpu) << 32) | uint64(fa.SubCpu) + if o, k := seenArches[seenArch]; o || k { + return nil, &FormatError{offset, fmt.Sprintf("duplicate architecture cpu=%v, subcpu=%#x", fa.Cpu, fa.SubCpu), nil} + } + seenArches[seenArch] = true + + // Make sure the Mach-O type matches that of the first image. + if i == 0 { + machoType = fa.Type + } else { + if fa.Type != machoType { + return nil, &FormatError{offset, fmt.Sprintf("Mach-O type for architecture #%d (type=%#x) does not match first (type=%#x)", i, fa.Type, machoType), nil} + } + } + } + + return &ff, nil +} + +// OpenFat opens the named file using os.Open and prepares it for use as a Mach-O +// universal binary. +func OpenFat(name string) (ff *FatFile, err error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + ff, err = NewFatFile(f) + if err != nil { + f.Close() + return nil, err + } + ff.closer = f + return +} + +func (ff *FatFile) Close() error { + var err error + if ff.closer != nil { + err = ff.closer.Close() + ff.closer = nil + } + return err +} diff --git a/libgo/go/debug/macho/file.go b/libgo/go/debug/macho/file.go index 9d912e7a08..da13c51006 100644 --- a/libgo/go/debug/macho/file.go +++ b/libgo/go/debug/macho/file.go @@ -11,7 +11,6 @@ import ( "bytes" "debug/dwarf" "encoding/binary" - "errors" "fmt" "io" "os" @@ -74,6 +73,9 @@ type Segment struct { func (s *Segment) Data() ([]byte, error) { dat := make([]byte, s.sr.Size()) n, err := s.sr.ReadAt(dat, 0) + if n == len(dat) { + err = nil + } return dat[0:n], err } @@ -109,6 +111,9 @@ type Section struct { func (s *Section) Data() ([]byte, error) { dat := make([]byte, s.sr.Size()) n, err := s.sr.ReadAt(dat, 0) + if n == len(dat) { + err = nil + } return dat[0:n], err } @@ -246,7 +251,7 @@ func NewFile(r io.ReaderAt) (*File, error) { case LoadCmdDylib: var hdr DylibCmd - b := bytes.NewBuffer(cmddat) + b := bytes.NewReader(cmddat) if err := binary.Read(b, bo, &hdr); err != nil { return nil, err } @@ -263,7 +268,7 @@ func NewFile(r io.ReaderAt) (*File, error) { case LoadCmdSymtab: var hdr SymtabCmd - b := bytes.NewBuffer(cmddat) + b := bytes.NewReader(cmddat) if err := binary.Read(b, bo, &hdr); err != nil { return nil, err } @@ -290,7 +295,7 @@ func NewFile(r io.ReaderAt) (*File, error) { case LoadCmdDysymtab: var hdr DysymtabCmd - b := bytes.NewBuffer(cmddat) + b := bytes.NewReader(cmddat) if err := binary.Read(b, bo, &hdr); err != nil { return nil, err } @@ -299,7 +304,7 @@ func NewFile(r io.ReaderAt) (*File, error) { return nil, err } x := make([]uint32, hdr.Nindirectsyms) - if err := binary.Read(bytes.NewBuffer(dat), bo, x); err != nil { + if err := binary.Read(bytes.NewReader(dat), bo, x); err != nil { return nil, err } st := new(Dysymtab) @@ -311,7 +316,7 @@ func NewFile(r io.ReaderAt) (*File, error) { case LoadCmdSegment: var seg32 Segment32 - b := bytes.NewBuffer(cmddat) + b := bytes.NewReader(cmddat) if err := binary.Read(b, bo, &seg32); err != nil { return nil, err } @@ -349,7 +354,7 @@ func NewFile(r io.ReaderAt) (*File, error) { case LoadCmdSegment64: var seg64 Segment64 - b := bytes.NewBuffer(cmddat) + b := bytes.NewReader(cmddat) if err := binary.Read(b, bo, &seg64); err != nil { return nil, err } @@ -396,7 +401,7 @@ func NewFile(r io.ReaderAt) (*File, error) { func (f *File) parseSymtab(symdat, strtab, cmddat []byte, hdr *SymtabCmd, offset int64) (*Symtab, error) { bo := f.ByteOrder symtab := make([]Symbol, hdr.Nsyms) - b := bytes.NewBuffer(symdat) + b := bytes.NewReader(symdat) for i := range symtab { var n Nlist64 if f.Magic == Magic64 { @@ -475,7 +480,7 @@ func (f *File) DWARF() (*dwarf.Data, error) { name = "__debug_" + name s := f.Section(name) if s == nil { - return nil, errors.New("missing Mach-O section " + name) + continue } b, err := s.Data() if err != nil && uint64(len(b)) < s.Size { diff --git a/libgo/go/debug/macho/file_test.go b/libgo/go/debug/macho/file_test.go index 640225b329..4797780ce7 100644 --- a/libgo/go/debug/macho/file_test.go +++ b/libgo/go/debug/macho/file_test.go @@ -165,3 +165,46 @@ func TestOpenFailure(t *testing.T) { t.Errorf("open %s: succeeded unexpectedly", filename) } } + +func TestOpenFat(t *testing.T) { + ff, err := OpenFat("testdata/fat-gcc-386-amd64-darwin-exec") + if err != nil { + t.Fatal(err) + } + + if ff.Magic != MagicFat { + t.Errorf("OpenFat: got magic number %#x, want %#x", ff.Magic, MagicFat) + } + if len(ff.Arches) != 2 { + t.Errorf("OpenFat: got %d architectures, want 2", len(ff.Arches)) + } + + for i := range ff.Arches { + arch := &ff.Arches[i] + ftArch := &fileTests[i] + + if arch.Cpu != ftArch.hdr.Cpu || arch.SubCpu != ftArch.hdr.SubCpu { + t.Errorf("OpenFat: architecture #%d got cpu=%#x subtype=%#x, expected cpu=%#x, subtype=%#x", i, arch.Cpu, arch.SubCpu, ftArch.hdr.Cpu, ftArch.hdr.SubCpu) + } + + if !reflect.DeepEqual(arch.FileHeader, ftArch.hdr) { + t.Errorf("OpenFat header:\n\tgot %#v\n\twant %#v\n", arch.FileHeader, ftArch.hdr) + } + } +} + +func TestOpenFatFailure(t *testing.T) { + filename := "file.go" // not a Mach-O file + if _, err := OpenFat(filename); err == nil { + t.Errorf("OpenFat %s: succeeded unexpectedly", filename) + } + + filename = "testdata/gcc-386-darwin-exec" // not a fat Mach-O + ff, err := OpenFat(filename) + if err != ErrNotFat { + t.Errorf("OpenFat %s: got %v, want ErrNotFat", filename, err) + } + if ff != nil { + t.Errorf("OpenFat %s: got %v, want nil", filename, ff) + } +} diff --git a/libgo/go/debug/macho/macho.go b/libgo/go/debug/macho/macho.go index bc14226c56..d9678c8eda 100644 --- a/libgo/go/debug/macho/macho.go +++ b/libgo/go/debug/macho/macho.go @@ -26,29 +26,40 @@ const ( ) const ( - Magic32 uint32 = 0xfeedface - Magic64 uint32 = 0xfeedfacf + Magic32 uint32 = 0xfeedface + Magic64 uint32 = 0xfeedfacf + MagicFat uint32 = 0xcafebabe ) -// A Type is a Mach-O file type, either an object or an executable. +// A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library. type Type uint32 const ( - TypeObj Type = 1 - TypeExec Type = 2 + TypeObj Type = 1 + TypeExec Type = 2 + TypeDylib Type = 6 + TypeBundle Type = 8 ) // A Cpu is a Mach-O cpu type. type Cpu uint32 +const cpuArch64 = 0x01000000 + const ( Cpu386 Cpu = 7 - CpuAmd64 Cpu = Cpu386 + 1<<24 + CpuAmd64 Cpu = Cpu386 | cpuArch64 + CpuArm Cpu = 12 + CpuPpc Cpu = 18 + CpuPpc64 Cpu = CpuPpc | cpuArch64 ) var cpuStrings = []intName{ {uint32(Cpu386), "Cpu386"}, {uint32(CpuAmd64), "CpuAmd64"}, + {uint32(CpuArm), "CpuArm"}, + {uint32(CpuPpc), "CpuPpc"}, + {uint32(CpuPpc64), "CpuPpc64"}, } func (i Cpu) String() string { return stringName(uint32(i), cpuStrings, false) } diff --git a/libgo/go/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec b/libgo/go/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec new file mode 100644 index 0000000000..7efd19300b Binary files /dev/null and b/libgo/go/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec differ diff --git a/libgo/go/debug/pe/file.go b/libgo/go/debug/pe/file.go index f521566efa..759e5674fd 100644 --- a/libgo/go/debug/pe/file.go +++ b/libgo/go/debug/pe/file.go @@ -18,8 +18,9 @@ import ( // A File represents an open PE file. type File struct { FileHeader - Sections []*Section - Symbols []*Symbol + OptionalHeader interface{} // of type *OptionalHeader32 or *OptionalHeader64 + Sections []*Section + Symbols []*Symbol closer io.Closer } @@ -72,6 +73,9 @@ type ImportDirectory struct { func (s *Section) Data() ([]byte, error) { dat := make([]byte, s.sr.Size()) n, err := s.sr.ReadAt(dat, 0) + if n == len(dat) { + err = nil + } return dat[0:n], err } @@ -120,6 +124,11 @@ func (f *File) Close() error { return err } +var ( + sizeofOptionalHeader32 = uint16(binary.Size(OptionalHeader32{})) + sizeofOptionalHeader64 = uint16(binary.Size(OptionalHeader64{})) +) + // NewFile creates a new File for accessing a PE binary in an underlying reader. func NewFile(r io.ReaderAt) (*File, error) { f := new(File) @@ -193,10 +202,33 @@ func NewFile(r io.ReaderAt) (*File, error) { } } - // Process sections. + // Read optional header. sr.Seek(base, os.SEEK_SET) - binary.Read(sr, binary.LittleEndian, &f.FileHeader) - sr.Seek(int64(f.FileHeader.SizeOfOptionalHeader), os.SEEK_CUR) //Skip OptionalHeader + if err := binary.Read(sr, binary.LittleEndian, &f.FileHeader); err != nil { + return nil, err + } + var oh32 OptionalHeader32 + var oh64 OptionalHeader64 + switch f.FileHeader.SizeOfOptionalHeader { + case sizeofOptionalHeader32: + if err := binary.Read(sr, binary.LittleEndian, &oh32); err != nil { + return nil, err + } + if oh32.Magic != 0x10b { // PE32 + return nil, fmt.Errorf("pe32 optional header has unexpected Magic of 0x%x", oh32.Magic) + } + f.OptionalHeader = &oh32 + case sizeofOptionalHeader64: + if err := binary.Read(sr, binary.LittleEndian, &oh64); err != nil { + return nil, err + } + if oh64.Magic != 0x20b { // PE32+ + return nil, fmt.Errorf("pe32+ optional header has unexpected Magic of 0x%x", oh64.Magic) + } + f.OptionalHeader = &oh64 + } + + // Process sections. f.Sections = make([]*Section, f.FileHeader.NumberOfSections) for i := 0; i < int(f.FileHeader.NumberOfSections); i++ { sh := new(SectionHeader32) @@ -213,15 +245,15 @@ func NewFile(r io.ReaderAt) (*File, error) { s := new(Section) s.SectionHeader = SectionHeader{ Name: name, - VirtualSize: uint32(sh.VirtualSize), - VirtualAddress: uint32(sh.VirtualAddress), - Size: uint32(sh.SizeOfRawData), - Offset: uint32(sh.PointerToRawData), - PointerToRelocations: uint32(sh.PointerToRelocations), - PointerToLineNumbers: uint32(sh.PointerToLineNumbers), - NumberOfRelocations: uint16(sh.NumberOfRelocations), - NumberOfLineNumbers: uint16(sh.NumberOfLineNumbers), - Characteristics: uint32(sh.Characteristics), + VirtualSize: sh.VirtualSize, + VirtualAddress: sh.VirtualAddress, + Size: sh.SizeOfRawData, + Offset: sh.PointerToRawData, + PointerToRelocations: sh.PointerToRelocations, + PointerToLineNumbers: sh.PointerToLineNumbers, + NumberOfRelocations: sh.NumberOfRelocations, + NumberOfLineNumbers: sh.NumberOfLineNumbers, + Characteristics: sh.Characteristics, } s.sr = io.NewSectionReader(r, int64(s.SectionHeader.Offset), int64(s.SectionHeader.Size)) s.ReaderAt = s.sr diff --git a/libgo/go/debug/pe/file_test.go b/libgo/go/debug/pe/file_test.go index c0f9fcb95d..0d73969bca 100644 --- a/libgo/go/debug/pe/file_test.go +++ b/libgo/go/debug/pe/file_test.go @@ -12,6 +12,7 @@ import ( type fileTest struct { file string hdr FileHeader + opthdr interface{} sections []*SectionHeader symbols []*Symbol } @@ -20,6 +21,7 @@ var fileTests = []fileTest{ { "testdata/gcc-386-mingw-obj", FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104}, + nil, []*SectionHeader{ {".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020}, {".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264}, @@ -56,27 +58,137 @@ var fileTests = []fileTest{ { "testdata/gcc-386-mingw-exec", FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107}, + &OptionalHeader32{ + 0x10b, 0x2, 0x38, 0xe00, 0x1a00, 0x200, 0x1160, 0x1000, 0x2000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x1, 0x0, 0x4, 0x0, 0x0, 0x10000, 0x400, 0x14abb, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10, + [16]DataDirectory{ + {0x0, 0x0}, + {0x5000, 0x3c8}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x7000, 0x18}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + }, + }, []*SectionHeader{ - {Name: ".text", VirtualSize: 0xcd8, VirtualAddress: 0x1000, Size: 0xe00, Offset: 0x400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x60500060}, - {Name: ".data", VirtualSize: 0x10, VirtualAddress: 0x2000, Size: 0x200, Offset: 0x1200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040}, - {Name: ".rdata", VirtualSize: 0x120, VirtualAddress: 0x3000, Size: 0x200, Offset: 0x1400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x40300040}, - {Name: ".bss", VirtualSize: 0xdc, VirtualAddress: 0x4000, Size: 0x0, Offset: 0x0, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0400080}, - {Name: ".idata", VirtualSize: 0x3c8, VirtualAddress: 0x5000, Size: 0x400, Offset: 0x1600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040}, - {Name: ".CRT", VirtualSize: 0x18, VirtualAddress: 0x6000, Size: 0x200, Offset: 0x1a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040}, - {Name: ".tls", VirtualSize: 0x20, VirtualAddress: 0x7000, Size: 0x200, Offset: 0x1c00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0xc0300040}, - {Name: ".debug_aranges", VirtualSize: 0x20, VirtualAddress: 0x8000, Size: 0x200, Offset: 0x1e00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, - {Name: ".debug_pubnames", VirtualSize: 0x51, VirtualAddress: 0x9000, Size: 0x200, Offset: 0x2000, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, - {Name: ".debug_pubtypes", VirtualSize: 0x91, VirtualAddress: 0xa000, Size: 0x200, Offset: 0x2200, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, - {Name: ".debug_info", VirtualSize: 0xe22, VirtualAddress: 0xb000, Size: 0x1000, Offset: 0x2400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, - {Name: ".debug_abbrev", VirtualSize: 0x157, VirtualAddress: 0xc000, Size: 0x200, Offset: 0x3400, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, - {Name: ".debug_line", VirtualSize: 0x144, VirtualAddress: 0xd000, Size: 0x200, Offset: 0x3600, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, - {Name: ".debug_frame", VirtualSize: 0x34, VirtualAddress: 0xe000, Size: 0x200, Offset: 0x3800, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42300000}, - {Name: ".debug_loc", VirtualSize: 0x38, VirtualAddress: 0xf000, Size: 0x200, Offset: 0x3a00, PointerToRelocations: 0x0, PointerToLineNumbers: 0x0, NumberOfRelocations: 0x0, NumberOfLineNumbers: 0x0, Characteristics: 0x42100000}, + {".text", 0xcd8, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060}, + {".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040}, + {".rdata", 0x120, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040}, + {".bss", 0xdc, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0400080}, + {".idata", 0x3c8, 0x5000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0xc0300040}, + {".CRT", 0x18, 0x6000, 0x200, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040}, + {".tls", 0x20, 0x7000, 0x200, 0x1c00, 0x0, 0x0, 0x0, 0x0, 0xc0300040}, + {".debug_aranges", 0x20, 0x8000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0x42100000}, + {".debug_pubnames", 0x51, 0x9000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x42100000}, + {".debug_pubtypes", 0x91, 0xa000, 0x200, 0x2200, 0x0, 0x0, 0x0, 0x0, 0x42100000}, + {".debug_info", 0xe22, 0xb000, 0x1000, 0x2400, 0x0, 0x0, 0x0, 0x0, 0x42100000}, + {".debug_abbrev", 0x157, 0xc000, 0x200, 0x3400, 0x0, 0x0, 0x0, 0x0, 0x42100000}, + {".debug_line", 0x144, 0xd000, 0x200, 0x3600, 0x0, 0x0, 0x0, 0x0, 0x42100000}, + {".debug_frame", 0x34, 0xe000, 0x200, 0x3800, 0x0, 0x0, 0x0, 0x0, 0x42300000}, + {".debug_loc", 0x38, 0xf000, 0x200, 0x3a00, 0x0, 0x0, 0x0, 0x0, 0x42100000}, + }, + []*Symbol{}, + }, + { + "testdata/gcc-amd64-mingw-obj", + FileHeader{0x8664, 0x6, 0x0, 0x198, 0x12, 0x0, 0x4}, + nil, + []*SectionHeader{ + {".text", 0x0, 0x0, 0x30, 0x104, 0x15c, 0x0, 0x3, 0x0, 0x60500020}, + {".data", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500040}, + {".bss", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500080}, + {".rdata", 0x0, 0x0, 0x10, 0x134, 0x0, 0x0, 0x0, 0x0, 0x40500040}, + {".xdata", 0x0, 0x0, 0xc, 0x144, 0x0, 0x0, 0x0, 0x0, 0x40300040}, + {".pdata", 0x0, 0x0, 0xc, 0x150, 0x17a, 0x0, 0x3, 0x0, 0x40300040}, + }, + []*Symbol{ + {".file", 0x0, -2, 0x0, 0x67}, + {"main", 0x0, 1, 0x20, 0x2}, + {".text", 0x0, 1, 0x0, 0x3}, + {".data", 0x0, 2, 0x0, 0x3}, + {".bss", 0x0, 3, 0x0, 0x3}, + {".rdata", 0x0, 4, 0x0, 0x3}, + {".xdata", 0x0, 5, 0x0, 0x3}, + {".pdata", 0x0, 6, 0x0, 0x3}, + {"__main", 0x0, 0, 0x20, 0x2}, + {"puts", 0x0, 0, 0x20, 0x2}, + }, + }, + { + "testdata/gcc-amd64-mingw-exec", + FileHeader{0x8664, 0x11, 0x53e4364f, 0x39600, 0x6fc, 0xf0, 0x27}, + &OptionalHeader64{ + 0x20b, 0x2, 0x16, 0x6a00, 0x2400, 0x1600, 0x14e0, 0x1000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x0, 0x0, 0x5, 0x2, 0x0, 0x45000, 0x600, 0x46f19, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10, + [16]DataDirectory{ + {0x0, 0x0}, + {0xe000, 0x990}, + {0x0, 0x0}, + {0xa000, 0x498}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x10000, 0x28}, + {0x0, 0x0}, + {0x0, 0x0}, + {0xe254, 0x218}, + {0x0, 0x0}, + {0x0, 0x0}, + {0x0, 0x0}, + }}, + []*SectionHeader{ + {".text", 0x6860, 0x1000, 0x6a00, 0x600, 0x0, 0x0, 0x0, 0x0, 0x60500020}, + {".data", 0xe0, 0x8000, 0x200, 0x7000, 0x0, 0x0, 0x0, 0x0, 0xc0500040}, + {".rdata", 0x6b0, 0x9000, 0x800, 0x7200, 0x0, 0x0, 0x0, 0x0, 0x40600040}, + {".pdata", 0x498, 0xa000, 0x600, 0x7a00, 0x0, 0x0, 0x0, 0x0, 0x40300040}, + {".xdata", 0x488, 0xb000, 0x600, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x40300040}, + {".bss", 0x1410, 0xc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0600080}, + {".idata", 0x990, 0xe000, 0xa00, 0x8600, 0x0, 0x0, 0x0, 0x0, 0xc0300040}, + {".CRT", 0x68, 0xf000, 0x200, 0x9000, 0x0, 0x0, 0x0, 0x0, 0xc0400040}, + {".tls", 0x48, 0x10000, 0x200, 0x9200, 0x0, 0x0, 0x0, 0x0, 0xc0600040}, + {".debug_aranges", 0x600, 0x11000, 0x600, 0x9400, 0x0, 0x0, 0x0, 0x0, 0x42500040}, + {".debug_info", 0x1316e, 0x12000, 0x13200, 0x9a00, 0x0, 0x0, 0x0, 0x0, 0x42100040}, + {".debug_abbrev", 0x2ccb, 0x26000, 0x2e00, 0x1cc00, 0x0, 0x0, 0x0, 0x0, 0x42100040}, + {".debug_line", 0x3c4d, 0x29000, 0x3e00, 0x1fa00, 0x0, 0x0, 0x0, 0x0, 0x42100040}, + {".debug_frame", 0x18b8, 0x2d000, 0x1a00, 0x23800, 0x0, 0x0, 0x0, 0x0, 0x42400040}, + {".debug_str", 0x396, 0x2f000, 0x400, 0x25200, 0x0, 0x0, 0x0, 0x0, 0x42100040}, + {".debug_loc", 0x13240, 0x30000, 0x13400, 0x25600, 0x0, 0x0, 0x0, 0x0, 0x42100040}, + {".debug_ranges", 0xa70, 0x44000, 0xc00, 0x38a00, 0x0, 0x0, 0x0, 0x0, 0x42100040}, }, []*Symbol{}, }, } +func isOptHdrEq(a, b interface{}) bool { + switch va := a.(type) { + case *OptionalHeader32: + vb, ok := b.(*OptionalHeader32) + if !ok { + return false + } + return *vb == *va + case *OptionalHeader64: + vb, ok := b.(*OptionalHeader64) + if !ok { + return false + } + return *vb == *va + case nil: + return b == nil + } + return false +} + func TestOpen(t *testing.T) { for i := range fileTests { tt := &fileTests[i] @@ -90,6 +202,10 @@ func TestOpen(t *testing.T) { t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr) continue } + if !isOptHdrEq(tt.opthdr, f.OptionalHeader) { + t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.OptionalHeader, tt.opthdr) + continue + } for i, sh := range f.Sections { if i >= len(tt.sections) { diff --git a/libgo/go/debug/pe/pe.go b/libgo/go/debug/pe/pe.go index 0606217b3b..8e90b1b513 100644 --- a/libgo/go/debug/pe/pe.go +++ b/libgo/go/debug/pe/pe.go @@ -14,6 +14,78 @@ type FileHeader struct { Characteristics uint16 } +type DataDirectory struct { + VirtualAddress uint32 + Size uint32 +} + +type OptionalHeader32 struct { + Magic uint16 + MajorLinkerVersion uint8 + MinorLinkerVersion uint8 + SizeOfCode uint32 + SizeOfInitializedData uint32 + SizeOfUninitializedData uint32 + AddressOfEntryPoint uint32 + BaseOfCode uint32 + BaseOfData uint32 + ImageBase uint32 + SectionAlignment uint32 + FileAlignment uint32 + MajorOperatingSystemVersion uint16 + MinorOperatingSystemVersion uint16 + MajorImageVersion uint16 + MinorImageVersion uint16 + MajorSubsystemVersion uint16 + MinorSubsystemVersion uint16 + Win32VersionValue uint32 + SizeOfImage uint32 + SizeOfHeaders uint32 + CheckSum uint32 + Subsystem uint16 + DllCharacteristics uint16 + SizeOfStackReserve uint32 + SizeOfStackCommit uint32 + SizeOfHeapReserve uint32 + SizeOfHeapCommit uint32 + LoaderFlags uint32 + NumberOfRvaAndSizes uint32 + DataDirectory [16]DataDirectory +} + +type OptionalHeader64 struct { + Magic uint16 + MajorLinkerVersion uint8 + MinorLinkerVersion uint8 + SizeOfCode uint32 + SizeOfInitializedData uint32 + SizeOfUninitializedData uint32 + AddressOfEntryPoint uint32 + BaseOfCode uint32 + ImageBase uint64 + SectionAlignment uint32 + FileAlignment uint32 + MajorOperatingSystemVersion uint16 + MinorOperatingSystemVersion uint16 + MajorImageVersion uint16 + MinorImageVersion uint16 + MajorSubsystemVersion uint16 + MinorSubsystemVersion uint16 + Win32VersionValue uint32 + SizeOfImage uint32 + SizeOfHeaders uint32 + CheckSum uint32 + Subsystem uint16 + DllCharacteristics uint16 + SizeOfStackReserve uint64 + SizeOfStackCommit uint64 + SizeOfHeapReserve uint64 + SizeOfHeapCommit uint64 + LoaderFlags uint32 + NumberOfRvaAndSizes uint32 + DataDirectory [16]DataDirectory +} + type SectionHeader32 struct { Name [8]uint8 VirtualSize uint32 diff --git a/libgo/go/debug/pe/testdata/gcc-amd64-mingw-exec b/libgo/go/debug/pe/testdata/gcc-amd64-mingw-exec new file mode 100644 index 0000000000..ce6feb6b7b Binary files /dev/null and b/libgo/go/debug/pe/testdata/gcc-amd64-mingw-exec differ diff --git a/libgo/go/debug/pe/testdata/gcc-amd64-mingw-obj b/libgo/go/debug/pe/testdata/gcc-amd64-mingw-obj new file mode 100644 index 0000000000..48ae7921f3 Binary files /dev/null and b/libgo/go/debug/pe/testdata/gcc-amd64-mingw-obj differ diff --git a/libgo/go/debug/plan9obj/file.go b/libgo/go/debug/plan9obj/file.go new file mode 100644 index 0000000000..b11ed86f18 --- /dev/null +++ b/libgo/go/debug/plan9obj/file.go @@ -0,0 +1,328 @@ +// 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 plan9obj implements access to Plan 9 a.out object files. +package plan9obj + +import ( + "encoding/binary" + "errors" + "fmt" + "io" + "os" +) + +// A FileHeader represents a Plan 9 a.out file header. +type FileHeader struct { + Magic uint32 + Bss uint32 + Entry uint64 + PtrSize int + LoadAddress uint64 + HdrSize uint64 +} + +// A File represents an open Plan 9 a.out file. +type File struct { + FileHeader + Sections []*Section + closer io.Closer +} + +// A SectionHeader represents a single Plan 9 a.out section header. +// This structure doesn't exist on-disk, but eases navigation +// through the object file. +type SectionHeader struct { + Name string + Size uint32 + Offset uint32 +} + +// A Section represents a single section in a Plan 9 a.out file. +type Section struct { + SectionHeader + + // Embed ReaderAt for ReadAt method. + // Do not embed SectionReader directly + // to avoid having Read and Seek. + // If a client wants Read and Seek it must use + // Open() to avoid fighting over the seek offset + // with other clients. + io.ReaderAt + sr *io.SectionReader +} + +// Data reads and returns the contents of the Plan 9 a.out section. +func (s *Section) Data() ([]byte, error) { + dat := make([]byte, s.sr.Size()) + n, err := s.sr.ReadAt(dat, 0) + if n == len(dat) { + err = nil + } + return dat[0:n], err +} + +// Open returns a new ReadSeeker reading the Plan 9 a.out section. +func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) } + +// A Symbol represents an entry in a Plan 9 a.out symbol table section. +type Sym struct { + Value uint64 + Type rune + Name string +} + +/* + * Plan 9 a.out reader + */ + +// formatError is returned by some operations if the data does +// not have the correct format for an object file. +type formatError struct { + off int + msg string + val interface{} +} + +func (e *formatError) Error() string { + msg := e.msg + if e.val != nil { + msg += fmt.Sprintf(" '%v'", e.val) + } + msg += fmt.Sprintf(" in record at byte %#x", e.off) + return msg +} + +// Open opens the named file using os.Open and prepares it for use as a Plan 9 a.out binary. +func Open(name string) (*File, error) { + f, err := os.Open(name) + if err != nil { + return nil, err + } + ff, err := NewFile(f) + if err != nil { + f.Close() + return nil, err + } + ff.closer = f + return ff, nil +} + +// Close closes the File. +// If the File was created using NewFile directly instead of Open, +// Close has no effect. +func (f *File) Close() error { + var err error + if f.closer != nil { + err = f.closer.Close() + f.closer = nil + } + return err +} + +func parseMagic(magic []byte) (uint32, error) { + m := binary.BigEndian.Uint32(magic) + switch m { + case Magic386, MagicAMD64, MagicARM: + return m, nil + } + return 0, &formatError{0, "bad magic number", magic} +} + +// NewFile creates a new File for accessing a Plan 9 binary in an underlying reader. +// The Plan 9 binary is expected to start at position 0 in the ReaderAt. +func NewFile(r io.ReaderAt) (*File, error) { + sr := io.NewSectionReader(r, 0, 1<<63-1) + // Read and decode Plan 9 magic + var magic [4]byte + if _, err := r.ReadAt(magic[:], 0); err != nil { + return nil, err + } + _, err := parseMagic(magic[:]) + if err != nil { + return nil, err + } + + ph := new(prog) + if err := binary.Read(sr, binary.BigEndian, ph); err != nil { + return nil, err + } + + f := &File{FileHeader: FileHeader{ + Magic: ph.Magic, + Bss: ph.Bss, + Entry: uint64(ph.Entry), + PtrSize: 4, + LoadAddress: 0x1000, + HdrSize: 4 * 8, + }} + + if ph.Magic&Magic64 != 0 { + if err := binary.Read(sr, binary.BigEndian, &f.Entry); err != nil { + return nil, err + } + f.PtrSize = 8 + f.LoadAddress = 0x200000 + f.HdrSize += 8 + } + + var sects = []struct { + name string + size uint32 + }{ + {"text", ph.Text}, + {"data", ph.Data}, + {"syms", ph.Syms}, + {"spsz", ph.Spsz}, + {"pcsz", ph.Pcsz}, + } + + f.Sections = make([]*Section, 5) + + off := uint32(f.HdrSize) + + for i, sect := range sects { + s := new(Section) + s.SectionHeader = SectionHeader{ + Name: sect.name, + Size: sect.size, + Offset: off, + } + off += sect.size + s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Size)) + s.ReaderAt = s.sr + f.Sections[i] = s + } + + return f, nil +} + +func walksymtab(data []byte, ptrsz int, fn func(sym) error) error { + var order binary.ByteOrder = binary.BigEndian + var s sym + p := data + for len(p) >= 4 { + // Symbol type, value. + if len(p) < ptrsz { + return &formatError{len(data), "unexpected EOF", nil} + } + // fixed-width value + if ptrsz == 8 { + s.value = order.Uint64(p[0:8]) + p = p[8:] + } else { + s.value = uint64(order.Uint32(p[0:4])) + p = p[4:] + } + + var typ byte + typ = p[0] & 0x7F + s.typ = typ + p = p[1:] + + // Name. + var i int + var nnul int + for i = 0; i < len(p); i++ { + if p[i] == 0 { + nnul = 1 + break + } + } + switch typ { + case 'z', 'Z': + p = p[i+nnul:] + for i = 0; i+2 <= len(p); i += 2 { + if p[i] == 0 && p[i+1] == 0 { + nnul = 2 + break + } + } + } + if len(p) < i+nnul { + return &formatError{len(data), "unexpected EOF", nil} + } + s.name = p[0:i] + i += nnul + p = p[i:] + + fn(s) + } + return nil +} + +// NewTable decodes the Go symbol table in data, +// returning an in-memory representation. +func newTable(symtab []byte, ptrsz int) ([]Sym, error) { + var n int + err := walksymtab(symtab, ptrsz, func(s sym) error { + n++ + return nil + }) + if err != nil { + return nil, err + } + + fname := make(map[uint16]string) + syms := make([]Sym, 0, n) + err = walksymtab(symtab, ptrsz, func(s sym) error { + n := len(syms) + syms = syms[0 : n+1] + ts := &syms[n] + ts.Type = rune(s.typ) + ts.Value = s.value + switch s.typ { + default: + ts.Name = string(s.name[:]) + case 'z', 'Z': + for i := 0; i < len(s.name); i += 2 { + eltIdx := binary.BigEndian.Uint16(s.name[i : i+2]) + elt, ok := fname[eltIdx] + if !ok { + return &formatError{-1, "bad filename code", eltIdx} + } + if n := len(ts.Name); n > 0 && ts.Name[n-1] != '/' { + ts.Name += "/" + } + ts.Name += elt + } + } + switch s.typ { + case 'f': + fname[uint16(s.value)] = ts.Name + } + return nil + }) + if err != nil { + return nil, err + } + + return syms, nil +} + +// Symbols returns the symbol table for f. +func (f *File) Symbols() ([]Sym, error) { + symtabSection := f.Section("syms") + if symtabSection == nil { + return nil, errors.New("no symbol section") + } + + symtab, err := symtabSection.Data() + if err != nil { + return nil, errors.New("cannot load symbol section") + } + + return newTable(symtab, f.PtrSize) +} + +// Section returns a section with the given name, or nil if no such +// section exists. +func (f *File) Section(name string) *Section { + for _, s := range f.Sections { + if s.Name == name { + return s + } + } + return nil +} diff --git a/libgo/go/debug/plan9obj/file_test.go b/libgo/go/debug/plan9obj/file_test.go new file mode 100644 index 0000000000..cfd7a61d1c --- /dev/null +++ b/libgo/go/debug/plan9obj/file_test.go @@ -0,0 +1,81 @@ +// 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 plan9obj + +import ( + "reflect" + "testing" +) + +type fileTest struct { + file string + hdr FileHeader + sections []*SectionHeader +} + +var fileTests = []fileTest{ + { + "testdata/386-plan9-exec", + FileHeader{Magic386, 0x324, 0x14, 4, 0x1000, 32}, + []*SectionHeader{ + {"text", 0x4c5f, 0x20}, + {"data", 0x94c, 0x4c7f}, + {"syms", 0x2c2b, 0x55cb}, + {"spsz", 0x0, 0x81f6}, + {"pcsz", 0xf7a, 0x81f6}, + }, + }, + { + "testdata/amd64-plan9-exec", + FileHeader{MagicAMD64, 0x618, 0x13, 8, 0x200000, 40}, + []*SectionHeader{ + {"text", 0x4213, 0x28}, + {"data", 0xa80, 0x423b}, + {"syms", 0x2c8c, 0x4cbb}, + {"spsz", 0x0, 0x7947}, + {"pcsz", 0xca0, 0x7947}, + }, + }, +} + +func TestOpen(t *testing.T) { + for i := range fileTests { + tt := &fileTests[i] + + f, err := Open(tt.file) + if err != nil { + t.Error(err) + continue + } + if !reflect.DeepEqual(f.FileHeader, tt.hdr) { + t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr) + continue + } + + for i, sh := range f.Sections { + if i >= len(tt.sections) { + break + } + have := &sh.SectionHeader + want := tt.sections[i] + if !reflect.DeepEqual(have, want) { + t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want) + } + } + tn := len(tt.sections) + fn := len(f.Sections) + if tn != fn { + t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn) + } + } +} + +func TestOpenFailure(t *testing.T) { + filename := "file.go" // not a Plan 9 a.out file + _, err := Open(filename) // don't crash + if err == nil { + t.Errorf("open %s: succeeded unexpectedly", filename) + } +} diff --git a/libgo/go/debug/plan9obj/plan9obj.go b/libgo/go/debug/plan9obj/plan9obj.go new file mode 100644 index 0000000000..af9858562f --- /dev/null +++ b/libgo/go/debug/plan9obj/plan9obj.go @@ -0,0 +1,36 @@ +// 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. + +/* + * Plan 9 a.out constants and data structures + */ + +package plan9obj + +// Plan 9 Program header. +type prog struct { + Magic uint32 /* magic number */ + Text uint32 /* size of text segment */ + Data uint32 /* size of initialized data */ + Bss uint32 /* size of uninitialized data */ + Syms uint32 /* size of symbol table */ + Entry uint32 /* entry point */ + Spsz uint32 /* size of pc/sp offset table */ + Pcsz uint32 /* size of pc/line number table */ +} + +// Plan 9 symbol table entries. +type sym struct { + value uint64 + typ byte + name []byte +} + +const ( + Magic64 = 0x8000 // 64-bit expanded header + + Magic386 = (4*11+0)*11 + 7 + MagicAMD64 = (4*26+0)*26 + 7 + Magic64 + MagicARM = (4*20+0)*20 + 7 +) diff --git a/libgo/go/debug/plan9obj/testdata/386-plan9-exec b/libgo/go/debug/plan9obj/testdata/386-plan9-exec new file mode 100644 index 0000000000..748e83f8e6 Binary files /dev/null and b/libgo/go/debug/plan9obj/testdata/386-plan9-exec differ diff --git a/libgo/go/debug/plan9obj/testdata/amd64-plan9-exec b/libgo/go/debug/plan9obj/testdata/amd64-plan9-exec new file mode 100644 index 0000000000..3e257dd8ff Binary files /dev/null and b/libgo/go/debug/plan9obj/testdata/amd64-plan9-exec differ diff --git a/libgo/go/debug/plan9obj/testdata/hello.c b/libgo/go/debug/plan9obj/testdata/hello.c new file mode 100644 index 0000000000..c0d633e29f --- /dev/null +++ b/libgo/go/debug/plan9obj/testdata/hello.c @@ -0,0 +1,8 @@ +#include +#include + +void +main(void) +{ + print("hello, world\n"); +} diff --git a/libgo/go/encoding/ascii85/ascii85.go b/libgo/go/encoding/ascii85/ascii85.go index e2afc58714..4d7193873a 100644 --- a/libgo/go/encoding/ascii85/ascii85.go +++ b/libgo/go/encoding/ascii85/ascii85.go @@ -249,7 +249,6 @@ type decoder struct { err error readErr error r io.Reader - end bool // saw end of message buf [1024]byte // leftover input nbuf int out []byte // leftover decoded output @@ -281,6 +280,18 @@ func (d *decoder) Read(p []byte) (n int, err error) { d.nbuf = copy(d.buf[0:], d.buf[nsrc:d.nbuf]) continue // copy out and return } + if ndst == 0 && d.err == nil { + // Special case: input buffer is mostly filled with non-data bytes. + // Filter out such bytes to make room for more input. + off := 0 + for i := 0; i < d.nbuf; i++ { + if d.buf[i] > ' ' { + d.buf[off] = d.buf[i] + off++ + } + } + d.nbuf = off + } } // Out of input, out of decoded output. Check errors. diff --git a/libgo/go/encoding/ascii85/ascii85_test.go b/libgo/go/encoding/ascii85/ascii85_test.go index 42cf7e80e1..aad199b4fa 100644 --- a/libgo/go/encoding/ascii85/ascii85_test.go +++ b/libgo/go/encoding/ascii85/ascii85_test.go @@ -8,6 +8,7 @@ import ( "bytes" "io" "io/ioutil" + "strings" "testing" ) @@ -16,6 +17,11 @@ type testpair struct { } var pairs = []testpair{ + // Encode returns 0 when len(src) is 0 + { + "", + "", + }, // Wikipedia example { "Man is distinguished, not only by his reason, but by this singular passion from " + @@ -110,7 +116,7 @@ func TestDecode(t *testing.T) { func TestDecoder(t *testing.T) { for _, p := range pairs { - decoder := NewDecoder(bytes.NewBufferString(p.encoded)) + decoder := NewDecoder(strings.NewReader(p.encoded)) dbuf, err := ioutil.ReadAll(decoder) if err != nil { t.Fatal("Read failed", err) @@ -125,7 +131,7 @@ func TestDecoder(t *testing.T) { func TestDecoderBuffering(t *testing.T) { for bs := 1; bs <= 12; bs++ { - decoder := NewDecoder(bytes.NewBufferString(bigtest.encoded)) + decoder := NewDecoder(strings.NewReader(bigtest.encoded)) buf := make([]byte, len(bigtest.decoded)+12) var total int for total = 0; total < len(bigtest.decoded); { @@ -191,3 +197,14 @@ func TestBig(t *testing.T) { t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i) } } + +func TestDecoderInternalWhitespace(t *testing.T) { + s := strings.Repeat(" ", 2048) + "z" + decoded, err := ioutil.ReadAll(NewDecoder(strings.NewReader(s))) + if err != nil { + t.Errorf("Decode gave error %v", err) + } + if want := []byte("\000\000\000\000"); !bytes.Equal(want, decoded) { + t.Errorf("Decode failed: got %v, want %v", decoded, want) + } +} diff --git a/libgo/go/encoding/asn1/asn1.go b/libgo/go/encoding/asn1/asn1.go index 992356c263..8b3d1b3412 100644 --- a/libgo/go/encoding/asn1/asn1.go +++ b/libgo/go/encoding/asn1/asn1.go @@ -23,6 +23,7 @@ import ( "fmt" "math/big" "reflect" + "strconv" "time" ) @@ -197,6 +198,19 @@ func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool { return true } +func (oi ObjectIdentifier) String() string { + var s string + + for i, v := range oi { + if i > 0 { + s += "." + } + s += strconv.Itoa(v) + } + + return s +} + // parseObjectIdentifier parses an OBJECT IDENTIFIER from the given bytes and // returns it. An object identifier is a sequence of variable length integers // that are assigned in a hierarchy. @@ -451,11 +465,17 @@ func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type if err != nil { return } - // We pretend that GENERAL STRINGs are PRINTABLE STRINGs so - // that a sequence of them can be parsed into a []string. - if t.tag == tagGeneralString { + switch t.tag { + case tagIA5String, tagGeneralString, tagT61String, tagUTF8String: + // We pretend that various other string types are + // PRINTABLE STRINGs so that a sequence of them can be + // parsed into a []string. t.tag = tagPrintableString + case tagGeneralizedTime, tagUTCTime: + // Likewise, both time types are treated the same. + t.tag = tagUTCTime } + if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag { err = StructuralError{"sequence tag mismatch"} return @@ -620,18 +640,26 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam // when it sees a string, so if we see a different string type on the // wire, we change the universal type to match. if universalTag == tagPrintableString { - switch t.tag { - case tagIA5String, tagGeneralString, tagT61String, tagUTF8String: - universalTag = t.tag + if t.class == classUniversal { + switch t.tag { + case tagIA5String, tagGeneralString, tagT61String, tagUTF8String: + universalTag = t.tag + } + } else if params.stringType != 0 { + universalTag = params.stringType } } // Special case for time: UTCTime and GeneralizedTime both map to the // Go type time.Time. - if universalTag == tagUTCTime && t.tag == tagGeneralizedTime { + if universalTag == tagUTCTime && t.tag == tagGeneralizedTime && t.class == classUniversal { universalTag = tagGeneralizedTime } + if params.set { + universalTag = tagSet + } + expectedClass := classUniversal expectedTag := universalTag @@ -798,8 +826,19 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam return } +// canHaveDefaultValue reports whether k is a Kind that we will set a default +// value for. (A signed integer, essentially.) +func canHaveDefaultValue(k reflect.Kind) bool { + switch k { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return true + } + + return false +} + // setDefaultValue is used to install a default value, from a tag string, into -// a Value. It is successful is the field was optional, even if a default value +// a Value. It is successful if the field was optional, even if a default value // wasn't provided or it failed to install it into the Value. func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { if !params.optional { @@ -809,9 +848,8 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { if params.defaultValue == nil { return } - switch val := v; val.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - val.SetInt(*params.defaultValue) + if canHaveDefaultValue(v.Kind()) { + v.SetInt(*params.defaultValue) } return } @@ -852,13 +890,20 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { // // The following tags on struct fields have special meaning to Unmarshal: // -// optional marks the field as ASN.1 OPTIONAL -// [explicit] tag:x specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC -// default:x sets the default value for optional integer fields +// application specifies that a APPLICATION tag is used +// default:x sets the default value for optional integer fields +// explicit specifies that an additional, explicit tag wraps the implicit one +// optional marks the field as ASN.1 OPTIONAL +// set causes a SET, rather than a SEQUENCE type to be expected +// tag:x specifies the ASN.1 tag number; implies ASN.1 CONTEXT SPECIFIC // // If the type of the first field of a structure is RawContent then the raw // ASN1 contents of the struct will be stored in it. // +// If the type name of a slice element ends with "SET" then it's treated as if +// the "set" tag was set on it. This can be used with nested slices where a +// struct tag cannot be given. +// // Other ASN.1 types are not supported; if it encounters them, // Unmarshal returns a parse error. func Unmarshal(b []byte, val interface{}) (rest []byte, err error) { diff --git a/libgo/go/encoding/asn1/asn1_test.go b/libgo/go/encoding/asn1/asn1_test.go index f68804ebff..4e864d08ac 100644 --- a/libgo/go/encoding/asn1/asn1_test.go +++ b/libgo/go/encoding/asn1/asn1_test.go @@ -6,6 +6,7 @@ package asn1 import ( "bytes" + "fmt" "math/big" "reflect" "testing" @@ -171,6 +172,12 @@ func TestBitStringAt(t *testing.T) { if bs.At(9) != 1 { t.Error("#4: Failed") } + if bs.At(-1) != 0 { + t.Error("#5: Failed") + } + if bs.At(17) != 0 { + t.Error("#6: Failed") + } } type bitStringRightAlignTest struct { @@ -225,6 +232,10 @@ func TestObjectIdentifier(t *testing.T) { } } } + + if s := ObjectIdentifier([]int{1, 2, 3, 4}).String(); s != "1.2.3.4" { + t.Errorf("bad ObjectIdentifier.String(). Got %s, want 1.2.3.4", s) + } } type timeTest struct { @@ -238,6 +249,7 @@ var utcTestData = []timeTest{ {"910506164540+0730", true, time.Date(1991, 05, 06, 16, 45, 40, 0, time.FixedZone("", 7*60*60+30*60))}, {"910506234540Z", true, time.Date(1991, 05, 06, 23, 45, 40, 0, time.UTC)}, {"9105062345Z", true, time.Date(1991, 05, 06, 23, 45, 0, 0, time.UTC)}, + {"5105062345Z", true, time.Date(1951, 05, 06, 23, 45, 0, 0, time.UTC)}, {"a10506234540Z", false, time.Time{}}, {"91a506234540Z", false, time.Time{}}, {"9105a6234540Z", false, time.Time{}}, @@ -380,6 +392,10 @@ type TestContextSpecificTags2 struct { B int } +type TestContextSpecificTags3 struct { + S string `asn1:"tag:1,utf8"` +} + type TestElementsAfterString struct { S string A, B int @@ -389,6 +405,10 @@ type TestBigInt struct { X *big.Int } +type TestSet struct { + Ints []int `asn1:"set"` +} + var unmarshalTestData = []struct { in []byte out interface{} @@ -404,10 +424,12 @@ var unmarshalTestData = []struct { {[]byte{0x04, 0x04, 1, 2, 3, 4}, &RawValue{0, 4, false, []byte{1, 2, 3, 4}, []byte{4, 4, 1, 2, 3, 4}}}, {[]byte{0x30, 0x03, 0x81, 0x01, 0x01}, &TestContextSpecificTags{1}}, {[]byte{0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02}, &TestContextSpecificTags2{1, 2}}, + {[]byte{0x30, 0x03, 0x81, 0x01, '@'}, &TestContextSpecificTags3{"@"}}, {[]byte{0x01, 0x01, 0x00}, newBool(false)}, {[]byte{0x01, 0x01, 0xff}, newBool(true)}, {[]byte{0x30, 0x0b, 0x13, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x01, 0x22, 0x02, 0x01, 0x33}, &TestElementsAfterString{"foo", 0x22, 0x33}}, {[]byte{0x30, 0x05, 0x02, 0x03, 0x12, 0x34, 0x56}, &TestBigInt{big.NewInt(0x123456)}}, + {[]byte{0x30, 0x0b, 0x31, 0x09, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03}, &TestSet{Ints: []int{1, 2, 3}}}, } func TestUnmarshal(t *testing.T) { @@ -509,6 +531,38 @@ func TestRawStructs(t *testing.T) { } } +type oiEqualTest struct { + first ObjectIdentifier + second ObjectIdentifier + same bool +} + +var oiEqualTests = []oiEqualTest{ + { + ObjectIdentifier{1, 2, 3}, + ObjectIdentifier{1, 2, 3}, + true, + }, + { + ObjectIdentifier{1}, + ObjectIdentifier{1, 2, 3}, + false, + }, + { + ObjectIdentifier{1, 2, 3}, + ObjectIdentifier{10, 11, 12}, + false, + }, +} + +func TestObjectIdentifierEqual(t *testing.T) { + for _, o := range oiEqualTests { + if s := o.first.Equal(o.second); s != o.same { + t.Errorf("ObjectIdentifier.Equal: got: %t want: %t", s, o.same) + } + } +} + var derEncodedSelfSignedCert = Certificate{ TBSCertificate: TBSCertificate{ Version: 0, @@ -737,3 +791,77 @@ var derEncodedPaypalNULCertBytes = []byte{ 0xc8, 0x64, 0x8c, 0xb5, 0x50, 0x23, 0x82, 0x6f, 0xdb, 0xb8, 0x22, 0x1c, 0x43, 0x96, 0x07, 0xa8, 0xbb, } + +var stringSliceTestData = [][]string{ + {"foo", "bar"}, + {"foo", "\\bar"}, + {"foo", "\"bar\""}, + {"foo", "åäö"}, +} + +func TestStringSlice(t *testing.T) { + for _, test := range stringSliceTestData { + bs, err := Marshal(test) + if err != nil { + t.Error(err) + } + + var res []string + _, err = Unmarshal(bs, &res) + if err != nil { + t.Error(err) + } + + if fmt.Sprintf("%v", res) != fmt.Sprintf("%v", test) { + t.Errorf("incorrect marshal/unmarshal; %v != %v", res, test) + } + } +} + +type explicitTaggedTimeTest struct { + Time time.Time `asn1:"explicit,tag:0"` +} + +var explicitTaggedTimeTestData = []struct { + in []byte + out explicitTaggedTimeTest +}{ + {[]byte{0x30, 0x11, 0xa0, 0xf, 0x17, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'}, + explicitTaggedTimeTest{time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC)}}, + {[]byte{0x30, 0x17, 0xa0, 0xf, 0x18, 0x13, '2', '0', '1', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '+', '0', '6', '0', '7'}, + explicitTaggedTimeTest{time.Date(2010, 01, 02, 03, 04, 05, 0, time.FixedZone("", 6*60*60+7*60))}}, +} + +func TestExplicitTaggedTime(t *testing.T) { + // Test that a time.Time will match either tagUTCTime or + // tagGeneralizedTime. + for i, test := range explicitTaggedTimeTestData { + var got explicitTaggedTimeTest + _, err := Unmarshal(test.in, &got) + if err != nil { + t.Errorf("Unmarshal failed at index %d %v", i, err) + } + if !got.Time.Equal(test.out.Time) { + t.Errorf("#%d: got %v, want %v", i, got.Time, test.out.Time) + } + } +} + +type implicitTaggedTimeTest struct { + Time time.Time `asn1:"tag:24"` +} + +func TestImplicitTaggedTime(t *testing.T) { + // An implicitly tagged time value, that happens to have an implicit + // tag equal to a GENERALIZEDTIME, should still be parsed as a UTCTime. + // (There's no "timeType" in fieldParameters to determine what type of + // time should be expected when implicitly tagged.) + der := []byte{0x30, 0x0f, 0x80 | 24, 0xd, '9', '1', '0', '5', '0', '6', '1', '6', '4', '5', '4', '0', 'Z'} + var result implicitTaggedTimeTest + if _, err := Unmarshal(der, &result); err != nil { + t.Fatalf("Error while parsing: %s", err) + } + if expected := time.Date(1991, 05, 06, 16, 45, 40, 0, time.UTC); !result.Time.Equal(expected) { + t.Errorf("Wrong result. Got %v, want %v", result.Time, expected) + } +} diff --git a/libgo/go/encoding/asn1/marshal.go b/libgo/go/encoding/asn1/marshal.go index ed17e41a55..b2f104b4cb 100644 --- a/libgo/go/encoding/asn1/marshal.go +++ b/libgo/go/encoding/asn1/marshal.go @@ -295,8 +295,23 @@ func marshalTwoDigits(out *forkableWriter, v int) (err error) { return out.WriteByte(byte('0' + v%10)) } +func marshalFourDigits(out *forkableWriter, v int) (err error) { + var bytes [4]byte + for i := range bytes { + bytes[3-i] = '0' + byte(v%10) + v /= 10 + } + _, err = out.Write(bytes[:]) + return +} + +func outsideUTCRange(t time.Time) bool { + year := t.Year() + return year < 1950 || year >= 2050 +} + func marshalUTCTime(out *forkableWriter, t time.Time) (err error) { - year, month, day := t.Date() + year := t.Year() switch { case 1950 <= year && year < 2000: @@ -310,6 +325,24 @@ func marshalUTCTime(out *forkableWriter, t time.Time) (err error) { return } + return marshalTimeCommon(out, t) +} + +func marshalGeneralizedTime(out *forkableWriter, t time.Time) (err error) { + year := t.Year() + if year < 0 || year > 9999 { + return StructuralError{"cannot represent time as GeneralizedTime"} + } + if err = marshalFourDigits(out, year); err != nil { + return + } + + return marshalTimeCommon(out, t) +} + +func marshalTimeCommon(out *forkableWriter, t time.Time) (err error) { + _, month, day := t.Date() + err = marshalTwoDigits(out, int(month)) if err != nil { return @@ -378,7 +411,12 @@ func stripTagAndLength(in []byte) []byte { func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) { switch value.Type() { case timeType: - return marshalUTCTime(out, value.Interface().(time.Time)) + t := value.Interface().(time.Time) + if outsideUTCRange(t) { + return marshalGeneralizedTime(out, t) + } else { + return marshalUTCTime(out, t) + } case bitStringType: return marshalBitString(out, value.Interface().(BitString)) case objectIdentifierType: @@ -475,8 +513,22 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) return } - if params.optional && reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) { - return + if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) { + defaultValue := reflect.New(v.Type()).Elem() + defaultValue.SetInt(*params.defaultValue) + + if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) { + return + } + } + + // If no default value is given then the zero value for the type is + // assumed to be the default value. This isn't obviously the correct + // behaviour, but it's what Go has traditionally done. + if params.optional && params.defaultValue == nil { + if reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface()) { + return + } } if v.Type() == rawValueType { @@ -504,7 +556,8 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) return StructuralError{"explicit string type given to non-string member"} } - if tag == tagPrintableString { + switch tag { + case tagPrintableString: if params.stringType == 0 { // This is a string without an explicit string type. We'll use // a PrintableString if the character set in the string is @@ -521,6 +574,10 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) } else { tag = params.stringType } + case tagUTCTime: + if outsideUTCRange(v.Interface().(time.Time)) { + tag = tagGeneralizedTime + } } if params.set { @@ -568,6 +625,14 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) } // Marshal returns the ASN.1 encoding of val. +// +// In addition to the struct tags recognised by Unmarshal, the following can be +// used: +// +// ia5: causes strings to be marshaled as ASN.1, IA5 strings +// omitempty: causes empty slices to be skipped +// printable: causes strings to be marshaled as ASN.1, PrintableString strings. +// utf8: causes strings to be marshaled as ASN.1, UTF8 strings func Marshal(val interface{}) ([]byte, error) { var out bytes.Buffer v := reflect.ValueOf(val) diff --git a/libgo/go/encoding/asn1/marshal_test.go b/libgo/go/encoding/asn1/marshal_test.go index 763c86da23..5b0115f28c 100644 --- a/libgo/go/encoding/asn1/marshal_test.go +++ b/libgo/go/encoding/asn1/marshal_test.go @@ -58,6 +58,10 @@ type omitEmptyTest struct { A []string `asn1:"omitempty"` } +type defaultTest struct { + A int `asn1:"optional,default:1"` +} + type testSET []int var PST = time.FixedZone("PST", -8*60*60) @@ -67,6 +71,14 @@ type marshalTest struct { out string // hex encoded } +func farFuture() time.Time { + t, err := time.Parse(time.RFC3339, "2100-04-05T12:01:01Z") + if err != nil { + panic(err) + } + return t +} + var marshalTests = []marshalTest{ {10, "02010a"}, {127, "02017f"}, @@ -83,6 +95,7 @@ var marshalTests = []marshalTest{ {time.Unix(0, 0).UTC(), "170d3730303130313030303030305a"}, {time.Unix(1258325776, 0).UTC(), "170d3039313131353232353631365a"}, {time.Unix(1258325776, 0).In(PST), "17113039313131353134353631362d30383030"}, + {farFuture(), "180f32313030303430353132303130315a"}, {BitString{[]byte{0x80}, 1}, "03020780"}, {BitString{[]byte{0x81, 0xf0}, 12}, "03030481f0"}, {ObjectIdentifier([]int{1, 2, 3, 4}), "06032a0304"}, @@ -124,6 +137,9 @@ var marshalTests = []marshalTest{ {omitEmptyTest{[]string{}}, "3000"}, {omitEmptyTest{[]string{"1"}}, "30053003130131"}, {"Σ", "0c02cea3"}, + {defaultTest{0}, "3003020100"}, + {defaultTest{1}, "3000"}, + {defaultTest{2}, "3003020102"}, } func TestMarshal(t *testing.T) { diff --git a/libgo/go/encoding/base32/base32.go b/libgo/go/encoding/base32/base32.go index fe17b73220..5a9e86919d 100644 --- a/libgo/go/encoding/base32/base32.go +++ b/libgo/go/encoding/base32/base32.go @@ -73,45 +73,43 @@ func (enc *Encoding) Encode(dst, src []byte) { } for len(src) > 0 { - dst[0] = 0 - dst[1] = 0 - dst[2] = 0 - dst[3] = 0 - dst[4] = 0 - dst[5] = 0 - dst[6] = 0 - dst[7] = 0 + var b0, b1, b2, b3, b4, b5, b6, b7 byte // Unpack 8x 5-bit source blocks into a 5 byte // destination quantum switch len(src) { default: - dst[7] |= src[4] & 0x1F - dst[6] |= src[4] >> 5 + b7 = src[4] & 0x1F + b6 = src[4] >> 5 fallthrough case 4: - dst[6] |= (src[3] << 3) & 0x1F - dst[5] |= (src[3] >> 2) & 0x1F - dst[4] |= src[3] >> 7 + b6 |= (src[3] << 3) & 0x1F + b5 = (src[3] >> 2) & 0x1F + b4 = src[3] >> 7 fallthrough case 3: - dst[4] |= (src[2] << 1) & 0x1F - dst[3] |= (src[2] >> 4) & 0x1F + b4 |= (src[2] << 1) & 0x1F + b3 = (src[2] >> 4) & 0x1F fallthrough case 2: - dst[3] |= (src[1] << 4) & 0x1F - dst[2] |= (src[1] >> 1) & 0x1F - dst[1] |= (src[1] >> 6) & 0x1F + b3 |= (src[1] << 4) & 0x1F + b2 = (src[1] >> 1) & 0x1F + b1 = (src[1] >> 6) & 0x1F fallthrough case 1: - dst[1] |= (src[0] << 2) & 0x1F - dst[0] |= src[0] >> 3 + b1 |= (src[0] << 2) & 0x1F + b0 = src[0] >> 3 } // Encode 5-bit blocks using the base32 alphabet - for j := 0; j < 8; j++ { - dst[j] = enc.encode[dst[j]] - } + dst[0] = enc.encode[b0] + dst[1] = enc.encode[b1] + dst[2] = enc.encode[b2] + dst[3] = enc.encode[b3] + dst[4] = enc.encode[b4] + dst[5] = enc.encode[b5] + dst[6] = enc.encode[b6] + dst[7] = enc.encode[b7] // Pad the final quantum if len(src) < 5 { @@ -179,13 +177,11 @@ func (e *encoder) Write(p []byte) (n int, err error) { nn := len(e.out) / 8 * 5 if nn > len(p) { nn = len(p) + nn -= nn % 5 } - nn -= nn % 5 - if nn > 0 { - e.enc.Encode(e.out[0:], p[0:nn]) - if _, e.err = e.w.Write(e.out[0 : nn/5*8]); e.err != nil { - return n, e.err - } + e.enc.Encode(e.out[0:], p[0:nn]) + if _, e.err = e.w.Write(e.out[0 : nn/5*8]); e.err != nil { + return n, e.err } n += nn p = p[nn:] @@ -268,7 +264,7 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) { // 7, 5 and 2 are not valid padding lengths, and so 1, 3 and 6 are not // valid dlen values. See RFC 4648 Section 6 "Base 32 Encoding" listing // the five valid padding lengths, and Section 9 "Illustrations and - // Examples" for an illustration for how the the 1st, 3rd and 6th base32 + // Examples" for an illustration for how the 1st, 3rd and 6th base32 // src bytes do not yield enough information to decode a dst byte. if dlen == 1 || dlen == 3 || dlen == 6 { return n, false, CorruptInputError(olen - len(src) - 1) @@ -332,7 +328,7 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err error) { func (enc *Encoding) DecodeString(s string) ([]byte, error) { s = strings.Map(removeNewlinesMapper, s) dbuf := make([]byte, enc.DecodedLen(len(s))) - n, err := enc.Decode(dbuf, []byte(s)) + n, _, err := enc.decode(dbuf, []byte(s)) return dbuf[:n], err } diff --git a/libgo/go/encoding/base32/base32_test.go b/libgo/go/encoding/base32/base32_test.go index 63298d1c94..5a68f06e1c 100644 --- a/libgo/go/encoding/base32/base32_test.go +++ b/libgo/go/encoding/base32/base32_test.go @@ -108,7 +108,7 @@ func TestDecode(t *testing.T) { func TestDecoder(t *testing.T) { for _, p := range pairs { - decoder := NewDecoder(StdEncoding, bytes.NewBufferString(p.encoded)) + decoder := NewDecoder(StdEncoding, strings.NewReader(p.encoded)) dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded))) count, err := decoder.Read(dbuf) if err != nil && err != io.EOF { @@ -125,7 +125,7 @@ func TestDecoder(t *testing.T) { func TestDecoderBuffering(t *testing.T) { for bs := 1; bs <= 12; bs++ { - decoder := NewDecoder(StdEncoding, bytes.NewBufferString(bigtest.encoded)) + decoder := NewDecoder(StdEncoding, strings.NewReader(bigtest.encoded)) buf := make([]byte, len(bigtest.decoded)+12) var total int for total = 0; total < len(bigtest.decoded); { @@ -267,13 +267,13 @@ LNEBUWIIDFON2CA3DBMJXXE5LNFY== ====` encodedShort := strings.Replace(encoded, "\n", "", -1) - dec := NewDecoder(StdEncoding, bytes.NewBufferString(encoded)) + dec := NewDecoder(StdEncoding, strings.NewReader(encoded)) res1, err := ioutil.ReadAll(dec) if err != nil { t.Errorf("ReadAll failed: %v", err) } - dec = NewDecoder(StdEncoding, bytes.NewBufferString(encodedShort)) + dec = NewDecoder(StdEncoding, strings.NewReader(encodedShort)) var res2 []byte res2, err = ioutil.ReadAll(dec) if err != nil { @@ -284,3 +284,19 @@ LNEBUWIIDFON2CA3DBMJXXE5LNFY== t.Error("Decoded results not equal") } } + +func BenchmarkEncodeToString(b *testing.B) { + data := make([]byte, 8192) + b.SetBytes(int64(len(data))) + for i := 0; i < b.N; i++ { + StdEncoding.EncodeToString(data) + } +} + +func BenchmarkDecodeString(b *testing.B) { + data := StdEncoding.EncodeToString(make([]byte, 8192)) + b.SetBytes(int64(len(data))) + for i := 0; i < b.N; i++ { + StdEncoding.DecodeString(data) + } +} diff --git a/libgo/go/encoding/base64/base64.go b/libgo/go/encoding/base64/base64.go index 85e398fd0b..ad3abe6623 100644 --- a/libgo/go/encoding/base64/base64.go +++ b/libgo/go/encoding/base64/base64.go @@ -74,31 +74,29 @@ func (enc *Encoding) Encode(dst, src []byte) { } for len(src) > 0 { - dst[0] = 0 - dst[1] = 0 - dst[2] = 0 - dst[3] = 0 + var b0, b1, b2, b3 byte // Unpack 4x 6-bit source blocks into a 4 byte // destination quantum switch len(src) { default: - dst[3] |= src[2] & 0x3F - dst[2] |= src[2] >> 6 + b3 = src[2] & 0x3F + b2 = src[2] >> 6 fallthrough case 2: - dst[2] |= (src[1] << 2) & 0x3F - dst[1] |= src[1] >> 4 + b2 |= (src[1] << 2) & 0x3F + b1 = src[1] >> 4 fallthrough case 1: - dst[1] |= (src[0] << 4) & 0x3F - dst[0] |= src[0] >> 2 + b1 |= (src[0] << 4) & 0x3F + b0 = src[0] >> 2 } // Encode 6-bit blocks using the base64 alphabet - for j := 0; j < 4; j++ { - dst[j] = enc.encode[dst[j]] - } + dst[0] = enc.encode[b0] + dst[1] = enc.encode[b1] + dst[2] = enc.encode[b2] + dst[3] = enc.encode[b3] // Pad the final quantum if len(src) < 3 { @@ -159,13 +157,11 @@ func (e *encoder) Write(p []byte) (n int, err error) { nn := len(e.out) / 4 * 3 if nn > len(p) { nn = len(p) + nn -= nn % 3 } - nn -= nn % 3 - if nn > 0 { - e.enc.Encode(e.out[0:], p[0:nn]) - if _, e.err = e.w.Write(e.out[0 : nn/3*4]); e.err != nil { - return n, e.err - } + e.enc.Encode(e.out[0:], p[0:nn]) + if _, e.err = e.w.Write(e.out[0 : nn/3*4]); e.err != nil { + return n, e.err } n += nn p = p[nn:] @@ -226,21 +222,33 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) { var dbuf [4]byte dlen := 4 - for j := 0; j < 4; { + for j := range dbuf { if len(src) == 0 { return n, false, CorruptInputError(olen - len(src) - j) } in := src[0] src = src[1:] - if in == '=' && j >= 2 && len(src) < 4 { + if in == '=' { // We've reached the end and there's padding - if len(src)+j < 4-1 { - // not enough padding - return n, false, CorruptInputError(olen) - } - if len(src) > 0 && src[0] != '=' { + switch j { + case 0, 1: // incorrect padding return n, false, CorruptInputError(olen - len(src) - 1) + case 2: + // "==" is expected, the first "=" is already consumed. + if len(src) == 0 { + // not enough padding + return n, false, CorruptInputError(olen) + } + if src[0] != '=' { + // incorrect padding + return n, false, CorruptInputError(olen - len(src) - 1) + } + src = src[1:] + } + if len(src) > 0 { + // trailing garbage + err = CorruptInputError(olen - len(src)) } dlen, end = j, true break @@ -249,7 +257,6 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) { if dbuf[j] == 0xFF { return n, false, CorruptInputError(olen - len(src) - 1) } - j++ } // Pack 4x 6-bit source blocks into 3 byte destination @@ -268,7 +275,7 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) { n += dlen - 1 } - return n, end, nil + return n, end, err } // Decode decodes src using the encoding enc. It writes at most @@ -286,7 +293,7 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err error) { func (enc *Encoding) DecodeString(s string) ([]byte, error) { s = strings.Map(removeNewlinesMapper, s) dbuf := make([]byte, enc.DecodedLen(len(s))) - n, err := enc.Decode(dbuf, []byte(s)) + n, _, err := enc.decode(dbuf, []byte(s)) return dbuf[:n], err } diff --git a/libgo/go/encoding/base64/base64_test.go b/libgo/go/encoding/base64/base64_test.go index 579591a88d..7d199bfa08 100644 --- a/libgo/go/encoding/base64/base64_test.go +++ b/libgo/go/encoding/base64/base64_test.go @@ -9,6 +9,7 @@ import ( "errors" "io" "io/ioutil" + "reflect" "strings" "testing" "time" @@ -113,7 +114,7 @@ func TestDecode(t *testing.T) { func TestDecoder(t *testing.T) { for _, p := range pairs { - decoder := NewDecoder(StdEncoding, bytes.NewBufferString(p.encoded)) + decoder := NewDecoder(StdEncoding, strings.NewReader(p.encoded)) dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded))) count, err := decoder.Read(dbuf) if err != nil && err != io.EOF { @@ -130,7 +131,7 @@ func TestDecoder(t *testing.T) { func TestDecoderBuffering(t *testing.T) { for bs := 1; bs <= 12; bs++ { - decoder := NewDecoder(StdEncoding, bytes.NewBufferString(bigtest.encoded)) + decoder := NewDecoder(StdEncoding, strings.NewReader(bigtest.encoded)) buf := make([]byte, len(bigtest.decoded)+12) var total int for total = 0; total < len(bigtest.decoded); { @@ -149,9 +150,13 @@ func TestDecodeCorrupt(t *testing.T) { }{ {"", -1}, {"!!!!", 0}, + {"====", 0}, {"x===", 1}, + {"=AAA", 0}, + {"A=AA", 1}, {"AA=A", 2}, - {"AAA=AAAA", 3}, + {"AA==A", 4}, + {"AAA=AAAA", 4}, {"AAAAA", 4}, {"AAAAAA", 4}, {"A=", 1}, @@ -161,6 +166,7 @@ func TestDecodeCorrupt(t *testing.T) { {"AAA=", -1}, {"AAAA", -1}, {"AAAAAA=", 7}, + {"YWJjZA=====", 8}, } for _, tc := range testCases { dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input))) @@ -308,13 +314,13 @@ bqbPb06551Y4 ` encodedShort := strings.Replace(encoded, "\n", "", -1) - dec := NewDecoder(StdEncoding, bytes.NewBufferString(encoded)) + dec := NewDecoder(StdEncoding, strings.NewReader(encoded)) res1, err := ioutil.ReadAll(dec) if err != nil { t.Errorf("ReadAll failed: %v", err) } - dec = NewDecoder(StdEncoding, bytes.NewBufferString(encodedShort)) + dec = NewDecoder(StdEncoding, strings.NewReader(encodedShort)) var res2 []byte res2, err = ioutil.ReadAll(dec) if err != nil { @@ -325,3 +331,30 @@ bqbPb06551Y4 t.Error("Decoded results not equal") } } + +func TestDecoderIssue7733(t *testing.T) { + s, err := StdEncoding.DecodeString("YWJjZA=====") + want := CorruptInputError(8) + if !reflect.DeepEqual(want, err) { + t.Errorf("Error = %v; want CorruptInputError(8)", err) + } + if string(s) != "abcd" { + t.Errorf("DecodeString = %q; want abcd", s) + } +} + +func BenchmarkEncodeToString(b *testing.B) { + data := make([]byte, 8192) + b.SetBytes(int64(len(data))) + for i := 0; i < b.N; i++ { + StdEncoding.EncodeToString(data) + } +} + +func BenchmarkDecodeString(b *testing.B) { + data := StdEncoding.EncodeToString(make([]byte, 8192)) + b.SetBytes(int64(len(data))) + for i := 0; i < b.N; i++ { + StdEncoding.DecodeString(data) + } +} diff --git a/libgo/go/encoding/binary/binary.go b/libgo/go/encoding/binary/binary.go index f3466b9af0..466bf97c97 100644 --- a/libgo/go/encoding/binary/binary.go +++ b/libgo/go/encoding/binary/binary.go @@ -10,9 +10,10 @@ // type (int8, uint8, int16, float32, complex64, ...) // or an array or struct containing only fixed-size values. // -// Varints are a method of encoding integers using one or more bytes; -// numbers with smaller absolute value take a smaller number of bytes. -// For a specification, see http://code.google.com/apis/protocolbuffers/docs/encoding.html. +// The varint functions encode and decode single integer values using +// a variable-length encoding; smaller values require fewer bytes. +// For a specification, see +// http://code.google.com/apis/protocolbuffers/docs/encoding.html. // // This package favors simplicity over efficiency. Clients that require // high-performance serialization, especially for large data structures, @@ -133,6 +134,7 @@ func (bigEndian) GoString() string { return "binary.BigEndian" } // When reading into structs, the field data for fields with // blank (_) field names is skipped; i.e., blank field names // may be used for padding. +// When reading into a struct, all non-blank fields must be exported. func Read(r io.Reader, order ByteOrder, data interface{}) error { // Fast path for basic types and slices. if n := intDataSize(data); n != 0 { @@ -198,18 +200,17 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error { } // Fallback to reflect-based decoding. - var v reflect.Value - switch d := reflect.ValueOf(data); d.Kind() { + v := reflect.ValueOf(data) + size := -1 + switch v.Kind() { case reflect.Ptr: - v = d.Elem() + v = v.Elem() + size = dataSize(v) case reflect.Slice: - v = d - default: - return errors.New("binary.Read: invalid type " + d.Type().String()) + size = dataSize(v) } - size, err := dataSize(v) - if err != nil { - return errors.New("binary.Read: " + err.Error()) + if size < 0 { + return errors.New("binary.Read: invalid type " + reflect.TypeOf(data).String()) } d := &decoder{order: order, buf: make([]byte, size)} if _, err := io.ReadFull(r, d.buf); err != nil { @@ -322,68 +323,64 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error { // Fallback to reflect-based encoding. v := reflect.Indirect(reflect.ValueOf(data)) - size, err := dataSize(v) - if err != nil { - return errors.New("binary.Write: " + err.Error()) + size := dataSize(v) + if size < 0 { + return errors.New("binary.Write: invalid type " + reflect.TypeOf(data).String()) } buf := make([]byte, size) e := &encoder{order: order, buf: buf} e.value(v) - _, err = w.Write(buf) + _, err := w.Write(buf) return err } // Size returns how many bytes Write would generate to encode the value v, which // must be a fixed-size value or a slice of fixed-size values, or a pointer to such data. +// If v is neither of these, Size returns -1. func Size(v interface{}) int { - n, err := dataSize(reflect.Indirect(reflect.ValueOf(v))) - if err != nil { - return -1 - } - return n + return dataSize(reflect.Indirect(reflect.ValueOf(v))) } // dataSize returns the number of bytes the actual data represented by v occupies in memory. // For compound structures, it sums the sizes of the elements. Thus, for instance, for a slice // it returns the length of the slice times the element size and does not count the memory -// occupied by the header. -func dataSize(v reflect.Value) (int, error) { +// occupied by the header. If the type of v is not acceptable, dataSize returns -1. +func dataSize(v reflect.Value) int { if v.Kind() == reflect.Slice { - elem, err := sizeof(v.Type().Elem()) - if err != nil { - return 0, err + if s := sizeof(v.Type().Elem()); s >= 0 { + return s * v.Len() } - return v.Len() * elem, nil + return -1 } return sizeof(v.Type()) } -func sizeof(t reflect.Type) (int, error) { +// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable. +func sizeof(t reflect.Type) int { switch t.Kind() { case reflect.Array: - n, err := sizeof(t.Elem()) - if err != nil { - return 0, err + if s := sizeof(t.Elem()); s >= 0 { + return s * t.Len() } - return t.Len() * n, nil case reflect.Struct: sum := 0 for i, n := 0, t.NumField(); i < n; i++ { - s, err := sizeof(t.Field(i).Type) - if err != nil { - return 0, err + s := sizeof(t.Field(i).Type) + if s < 0 { + return -1 } sum += s } - return sum, nil + return sum case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: - return int(t.Size()), nil + return int(t.Size()) } - return 0, errors.New("invalid type " + t.String()) + + return -1 } type coder struct { @@ -593,12 +590,11 @@ func (e *encoder) value(v reflect.Value) { } func (d *decoder) skip(v reflect.Value) { - n, _ := dataSize(v) - d.buf = d.buf[n:] + d.buf = d.buf[dataSize(v):] } func (e *encoder) skip(v reflect.Value) { - n, _ := dataSize(v) + n := dataSize(v) for i := range e.buf[0:n] { e.buf[i] = 0 } diff --git a/libgo/go/encoding/binary/binary_test.go b/libgo/go/encoding/binary/binary_test.go index fdfee7d871..8ee595fa47 100644 --- a/libgo/go/encoding/binary/binary_test.go +++ b/libgo/go/encoding/binary/binary_test.go @@ -111,7 +111,7 @@ func checkResult(t *testing.T, dir string, order ByteOrder, err error, have, wan func testRead(t *testing.T, order ByteOrder, b []byte, s1 interface{}) { var s2 Struct - err := Read(bytes.NewBuffer(b), order, &s2) + err := Read(bytes.NewReader(b), order, &s2) checkResult(t, "Read", order, err, s2, s1) } @@ -131,7 +131,7 @@ func TestBigEndianPtrWrite(t *testing.T) { testWrite(t, BigEndian, big, &s) } func TestReadSlice(t *testing.T) { slice := make([]int32, 2) - err := Read(bytes.NewBuffer(src), BigEndian, slice) + err := Read(bytes.NewReader(src), BigEndian, slice) checkResult(t, "ReadSlice", BigEndian, err, slice, res) } @@ -265,6 +265,50 @@ func TestBlankFields(t *testing.T) { } } +// An attempt to read into a struct with an unexported field will +// panic. This is probably not the best choice, but at this point +// anything else would be an API change. + +type Unexported struct { + a int32 +} + +func TestUnexportedRead(t *testing.T) { + var buf bytes.Buffer + u1 := Unexported{a: 1} + if err := Write(&buf, LittleEndian, &u1); err != nil { + t.Fatal(err) + } + + defer func() { + if recover() == nil { + t.Fatal("did not panic") + } + }() + var u2 Unexported + Read(&buf, LittleEndian, &u2) +} + +func TestReadErrorMsg(t *testing.T) { + var buf bytes.Buffer + read := func(data interface{}) { + err := Read(&buf, LittleEndian, data) + want := "binary.Read: invalid type " + reflect.TypeOf(data).String() + if err == nil { + t.Errorf("%T: got no error; want %q", data, want) + return + } + if got := err.Error(); got != want { + t.Errorf("%T: got %q; want %q", data, got, want) + } + } + read(0) + s := new(struct{}) + read(&s) + p := &s + read(&p) +} + type byteSliceReader struct { remain []byte } @@ -291,8 +335,7 @@ func BenchmarkReadStruct(b *testing.B) { bsr := &byteSliceReader{} var buf bytes.Buffer Write(&buf, BigEndian, &s) - n, _ := dataSize(reflect.ValueOf(s)) - b.SetBytes(int64(n)) + b.SetBytes(int64(dataSize(reflect.ValueOf(s)))) t := s b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/libgo/go/encoding/binary/varint_test.go b/libgo/go/encoding/binary/varint_test.go index 9476bd5fb7..ca411ecbd6 100644 --- a/libgo/go/encoding/binary/varint_test.go +++ b/libgo/go/encoding/binary/varint_test.go @@ -35,7 +35,7 @@ func testVarint(t *testing.T, x int64) { t.Errorf("Varint(%d): got n = %d; want %d", x, m, n) } - y, err := ReadVarint(bytes.NewBuffer(buf)) + y, err := ReadVarint(bytes.NewReader(buf)) if err != nil { t.Errorf("ReadVarint(%d): %s", x, err) } @@ -55,7 +55,7 @@ func testUvarint(t *testing.T, x uint64) { t.Errorf("Uvarint(%d): got n = %d; want %d", x, m, n) } - y, err := ReadUvarint(bytes.NewBuffer(buf)) + y, err := ReadUvarint(bytes.NewReader(buf)) if err != nil { t.Errorf("ReadUvarint(%d): %s", x, err) } @@ -114,7 +114,7 @@ func TestBufferTooSmall(t *testing.T) { t.Errorf("Uvarint(%v): got x = %d, n = %d", buf, x, n) } - x, err := ReadUvarint(bytes.NewBuffer(buf)) + x, err := ReadUvarint(bytes.NewReader(buf)) if x != 0 || err != io.EOF { t.Errorf("ReadUvarint(%v): got x = %d, err = %s", buf, x, err) } @@ -127,7 +127,7 @@ func testOverflow(t *testing.T, buf []byte, n0 int, err0 error) { t.Errorf("Uvarint(%v): got x = %d, n = %d; want 0, %d", buf, x, n, n0) } - x, err := ReadUvarint(bytes.NewBuffer(buf)) + x, err := ReadUvarint(bytes.NewReader(buf)) if x != 0 || err != err0 { t.Errorf("ReadUvarint(%v): got x = %d, err = %s; want 0, %s", buf, x, err, err0) } diff --git a/libgo/go/encoding/csv/reader.go b/libgo/go/encoding/csv/reader.go index b328dcc375..d9432954ac 100644 --- a/libgo/go/encoding/csv/reader.go +++ b/libgo/go/encoding/csv/reader.go @@ -193,12 +193,6 @@ func (r *Reader) readRune() (rune, error) { return r1, err } -// unreadRune puts the last rune read from r back. -func (r *Reader) unreadRune() { - r.r.UnreadRune() - r.column-- -} - // skip reads runes up to and including the rune delim or until error. func (r *Reader) skip(delim rune) error { for { diff --git a/libgo/go/encoding/csv/writer.go b/libgo/go/encoding/csv/writer.go index 1faecb6648..17e7bb7f5c 100644 --- a/libgo/go/encoding/csv/writer.go +++ b/libgo/go/encoding/csv/writer.go @@ -115,10 +115,22 @@ func (w *Writer) WriteAll(records [][]string) (err error) { } // fieldNeedsQuotes returns true if our field must be enclosed in quotes. -// Empty fields, files with a Comma, fields with a quote or newline, and +// Fields with a Comma, fields with a quote or newline, and // fields which start with a space must be enclosed in quotes. +// We used to quote empty strings, but we do not anymore (as of Go 1.4). +// The two representations should be equivalent, but Postgres distinguishes +// quoted vs non-quoted empty string during database imports, and it has +// an option to force the quoted behavior for non-quoted CSV but it has +// no option to force the non-quoted behavior for quoted CSV, making +// CSV with quoted empty strings strictly less useful. +// Not quoting the empty string also makes this package match the behavior +// of Microsoft Excel and Google Drive. +// For Postgres, quote the data termating string `\.`. func (w *Writer) fieldNeedsQuotes(field string) bool { - if len(field) == 0 || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 { + if field == "" { + return false + } + if field == `\.` || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 { return true } diff --git a/libgo/go/encoding/csv/writer_test.go b/libgo/go/encoding/csv/writer_test.go index 03ca6b093c..8ddca0abe0 100644 --- a/libgo/go/encoding/csv/writer_test.go +++ b/libgo/go/encoding/csv/writer_test.go @@ -26,6 +26,19 @@ var writeTests = []struct { {Input: [][]string{{"abc"}, {"def"}}, Output: "abc\ndef\n"}, {Input: [][]string{{"abc\ndef"}}, Output: "\"abc\ndef\"\n"}, {Input: [][]string{{"abc\ndef"}}, Output: "\"abc\r\ndef\"\r\n", UseCRLF: true}, + {Input: [][]string{{"abc\rdef"}}, Output: "\"abcdef\"\r\n", UseCRLF: true}, + {Input: [][]string{{"abc\rdef"}}, Output: "\"abc\rdef\"\n", UseCRLF: false}, + {Input: [][]string{{""}}, Output: "\n"}, + {Input: [][]string{{"", ""}}, Output: ",\n"}, + {Input: [][]string{{"", "", ""}}, Output: ",,\n"}, + {Input: [][]string{{"", "", "a"}}, Output: ",,a\n"}, + {Input: [][]string{{"", "a", ""}}, Output: ",a,\n"}, + {Input: [][]string{{"", "a", "a"}}, Output: ",a,a\n"}, + {Input: [][]string{{"a", "", ""}}, Output: "a,,\n"}, + {Input: [][]string{{"a", "", "a"}}, Output: "a,,a\n"}, + {Input: [][]string{{"a", "a", ""}}, Output: "a,a,\n"}, + {Input: [][]string{{"a", "a", "a"}}, Output: "a,a,a\n"}, + {Input: [][]string{{`\.`}}, Output: "\"\\.\"\n"}, } func TestWrite(t *testing.T) { diff --git a/libgo/go/encoding/gob/codec_test.go b/libgo/go/encoding/gob/codec_test.go index b40f78360c..56a7298fa5 100644 --- a/libgo/go/encoding/gob/codec_test.go +++ b/libgo/go/encoding/gob/codec_test.go @@ -14,7 +14,6 @@ import ( "strings" "testing" "time" - "unsafe" ) var doFuzzTests = flag.Bool("gob.fuzz", false, "run the fuzz tests, which are large and very slow") @@ -51,10 +50,16 @@ func testError(t *testing.T) { return } +func newDecBuffer(data []byte) *decBuffer { + return &decBuffer{ + data: data, + } +} + // Test basic encode/decode routines for unsigned integers func TestUintCodec(t *testing.T) { defer testError(t) - b := new(bytes.Buffer) + b := new(encBuffer) encState := newEncoderState(b) for _, tt := range encodeT { b.Reset() @@ -63,10 +68,10 @@ func TestUintCodec(t *testing.T) { t.Errorf("encodeUint: %#x encode: expected % x got % x", tt.x, tt.b, b.Bytes()) } } - decState := newDecodeState(b) for u := uint64(0); ; u = (u + 1) * 7 { b.Reset() encState.encodeUint(u) + decState := newDecodeState(newDecBuffer(b.Bytes())) v := decState.decodeUint() if u != v { t.Errorf("Encode/Decode: sent %#x received %#x", u, v) @@ -79,10 +84,10 @@ func TestUintCodec(t *testing.T) { func verifyInt(i int64, t *testing.T) { defer testError(t) - var b = new(bytes.Buffer) + var b = new(encBuffer) encState := newEncoderState(b) encState.encodeInt(i) - decState := newDecodeState(b) + decState := newDecodeState(newDecBuffer(b.Bytes())) decState.buf = make([]byte, 8) j := decState.decodeInt() if i != j { @@ -119,14 +124,14 @@ var complexResult = []byte{0x07, 0xFE, 0x31, 0x40, 0xFE, 0x33, 0x40} // The result of encoding "hello" with field number 7 var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'} -func newDecodeState(buf *bytes.Buffer) *decoderState { +func newDecodeState(buf *decBuffer) *decoderState { d := new(decoderState) d.b = buf d.buf = make([]byte, uint64Size) return d } -func newEncoderState(b *bytes.Buffer) *encoderState { +func newEncoderState(b *encBuffer) *encoderState { b.Reset() state := &encoderState{enc: nil, b: b} state.fieldnum = -1 @@ -136,14 +141,14 @@ func newEncoderState(b *bytes.Buffer) *encoderState { // Test instruction execution for encoding. // Do not run the machine yet; instead do individual instructions crafted by hand. func TestScalarEncInstructions(t *testing.T) { - var b = new(bytes.Buffer) + var b = new(encBuffer) // bool { - data := struct{ a bool }{true} - instr := &encInstr{encBool, 6, 0, 0} + var data bool = true + instr := &encInstr{encBool, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(boolResult, b.Bytes()) { t.Errorf("bool enc instructions: expected % x got % x", boolResult, b.Bytes()) } @@ -152,10 +157,10 @@ func TestScalarEncInstructions(t *testing.T) { // int { b.Reset() - data := struct{ a int }{17} - instr := &encInstr{encInt, 6, 0, 0} + var data int = 17 + instr := &encInstr{encInt, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(signedResult, b.Bytes()) { t.Errorf("int enc instructions: expected % x got % x", signedResult, b.Bytes()) } @@ -164,10 +169,10 @@ func TestScalarEncInstructions(t *testing.T) { // uint { b.Reset() - data := struct{ a uint }{17} - instr := &encInstr{encUint, 6, 0, 0} + var data uint = 17 + instr := &encInstr{encUint, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(unsignedResult, b.Bytes()) { t.Errorf("uint enc instructions: expected % x got % x", unsignedResult, b.Bytes()) } @@ -176,10 +181,10 @@ func TestScalarEncInstructions(t *testing.T) { // int8 { b.Reset() - data := struct{ a int8 }{17} - instr := &encInstr{encInt8, 6, 0, 0} + var data int8 = 17 + instr := &encInstr{encInt, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(signedResult, b.Bytes()) { t.Errorf("int8 enc instructions: expected % x got % x", signedResult, b.Bytes()) } @@ -188,10 +193,10 @@ func TestScalarEncInstructions(t *testing.T) { // uint8 { b.Reset() - data := struct{ a uint8 }{17} - instr := &encInstr{encUint8, 6, 0, 0} + var data uint8 = 17 + instr := &encInstr{encUint, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(unsignedResult, b.Bytes()) { t.Errorf("uint8 enc instructions: expected % x got % x", unsignedResult, b.Bytes()) } @@ -200,10 +205,10 @@ func TestScalarEncInstructions(t *testing.T) { // int16 { b.Reset() - data := struct{ a int16 }{17} - instr := &encInstr{encInt16, 6, 0, 0} + var data int16 = 17 + instr := &encInstr{encInt, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(signedResult, b.Bytes()) { t.Errorf("int16 enc instructions: expected % x got % x", signedResult, b.Bytes()) } @@ -212,10 +217,10 @@ func TestScalarEncInstructions(t *testing.T) { // uint16 { b.Reset() - data := struct{ a uint16 }{17} - instr := &encInstr{encUint16, 6, 0, 0} + var data uint16 = 17 + instr := &encInstr{encUint, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(unsignedResult, b.Bytes()) { t.Errorf("uint16 enc instructions: expected % x got % x", unsignedResult, b.Bytes()) } @@ -224,10 +229,10 @@ func TestScalarEncInstructions(t *testing.T) { // int32 { b.Reset() - data := struct{ a int32 }{17} - instr := &encInstr{encInt32, 6, 0, 0} + var data int32 = 17 + instr := &encInstr{encInt, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(signedResult, b.Bytes()) { t.Errorf("int32 enc instructions: expected % x got % x", signedResult, b.Bytes()) } @@ -236,10 +241,10 @@ func TestScalarEncInstructions(t *testing.T) { // uint32 { b.Reset() - data := struct{ a uint32 }{17} - instr := &encInstr{encUint32, 6, 0, 0} + var data uint32 = 17 + instr := &encInstr{encUint, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(unsignedResult, b.Bytes()) { t.Errorf("uint32 enc instructions: expected % x got % x", unsignedResult, b.Bytes()) } @@ -248,10 +253,10 @@ func TestScalarEncInstructions(t *testing.T) { // int64 { b.Reset() - data := struct{ a int64 }{17} - instr := &encInstr{encInt64, 6, 0, 0} + var data int64 = 17 + instr := &encInstr{encInt, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(signedResult, b.Bytes()) { t.Errorf("int64 enc instructions: expected % x got % x", signedResult, b.Bytes()) } @@ -260,10 +265,10 @@ func TestScalarEncInstructions(t *testing.T) { // uint64 { b.Reset() - data := struct{ a uint64 }{17} - instr := &encInstr{encUint64, 6, 0, 0} + var data uint64 = 17 + instr := &encInstr{encUint, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(unsignedResult, b.Bytes()) { t.Errorf("uint64 enc instructions: expected % x got % x", unsignedResult, b.Bytes()) } @@ -272,10 +277,10 @@ func TestScalarEncInstructions(t *testing.T) { // float32 { b.Reset() - data := struct{ a float32 }{17} - instr := &encInstr{encFloat32, 6, 0, 0} + var data float32 = 17 + instr := &encInstr{encFloat, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(floatResult, b.Bytes()) { t.Errorf("float32 enc instructions: expected % x got % x", floatResult, b.Bytes()) } @@ -284,10 +289,10 @@ func TestScalarEncInstructions(t *testing.T) { // float64 { b.Reset() - data := struct{ a float64 }{17} - instr := &encInstr{encFloat64, 6, 0, 0} + var data float64 = 17 + instr := &encInstr{encFloat, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(floatResult, b.Bytes()) { t.Errorf("float64 enc instructions: expected % x got % x", floatResult, b.Bytes()) } @@ -296,10 +301,10 @@ func TestScalarEncInstructions(t *testing.T) { // bytes == []uint8 { b.Reset() - data := struct{ a []byte }{[]byte("hello")} - instr := &encInstr{encUint8Array, 6, 0, 0} + data := []byte("hello") + instr := &encInstr{encUint8Array, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(bytesResult, b.Bytes()) { t.Errorf("bytes enc instructions: expected % x got % x", bytesResult, b.Bytes()) } @@ -308,28 +313,28 @@ func TestScalarEncInstructions(t *testing.T) { // string { b.Reset() - data := struct{ a string }{"hello"} - instr := &encInstr{encString, 6, 0, 0} + var data string = "hello" + instr := &encInstr{encString, 6, nil, 0} state := newEncoderState(b) - instr.op(instr, state, unsafe.Pointer(&data)) + instr.op(instr, state, reflect.ValueOf(data)) if !bytes.Equal(bytesResult, b.Bytes()) { t.Errorf("string enc instructions: expected % x got % x", bytesResult, b.Bytes()) } } } -func execDec(typ string, instr *decInstr, state *decoderState, t *testing.T, p unsafe.Pointer) { +func execDec(typ string, instr *decInstr, state *decoderState, t *testing.T, value reflect.Value) { defer testError(t) v := int(state.decodeUint()) if v+state.fieldnum != 6 { t.Fatalf("decoding field number %d, got %d", 6, v+state.fieldnum) } - instr.op(instr, state, decIndirect(p, instr.indir)) + instr.op(instr, state, value.Elem()) state.fieldnum = 6 } func newDecodeStateFromData(data []byte) *decoderState { - b := bytes.NewBuffer(data) + b := newDecBuffer(data) state := newDecodeState(b) state.fieldnum = -1 return state @@ -342,234 +347,198 @@ func TestScalarDecInstructions(t *testing.T) { // bool { - var data struct { - a bool - } - instr := &decInstr{decBool, 6, 0, 0, ovfl} + var data bool + instr := &decInstr{decBool, 6, nil, ovfl} state := newDecodeStateFromData(boolResult) - execDec("bool", instr, state, t, unsafe.Pointer(&data)) - if data.a != true { - t.Errorf("bool a = %v not true", data.a) + execDec("bool", instr, state, t, reflect.ValueOf(&data)) + if data != true { + t.Errorf("bool a = %v not true", data) } } // int { - var data struct { - a int - } - instr := &decInstr{decOpTable[reflect.Int], 6, 0, 0, ovfl} + var data int + instr := &decInstr{decOpTable[reflect.Int], 6, nil, ovfl} state := newDecodeStateFromData(signedResult) - execDec("int", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("int a = %v not 17", data.a) + execDec("int", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("int a = %v not 17", data) } } // uint { - var data struct { - a uint - } - instr := &decInstr{decOpTable[reflect.Uint], 6, 0, 0, ovfl} + var data uint + instr := &decInstr{decOpTable[reflect.Uint], 6, nil, ovfl} state := newDecodeStateFromData(unsignedResult) - execDec("uint", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("uint a = %v not 17", data.a) + execDec("uint", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("uint a = %v not 17", data) } } // int8 { - var data struct { - a int8 - } - instr := &decInstr{decInt8, 6, 0, 0, ovfl} + var data int8 + instr := &decInstr{decInt8, 6, nil, ovfl} state := newDecodeStateFromData(signedResult) - execDec("int8", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("int8 a = %v not 17", data.a) + execDec("int8", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("int8 a = %v not 17", data) } } // uint8 { - var data struct { - a uint8 - } - instr := &decInstr{decUint8, 6, 0, 0, ovfl} + var data uint8 + instr := &decInstr{decUint8, 6, nil, ovfl} state := newDecodeStateFromData(unsignedResult) - execDec("uint8", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("uint8 a = %v not 17", data.a) + execDec("uint8", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("uint8 a = %v not 17", data) } } // int16 { - var data struct { - a int16 - } - instr := &decInstr{decInt16, 6, 0, 0, ovfl} + var data int16 + instr := &decInstr{decInt16, 6, nil, ovfl} state := newDecodeStateFromData(signedResult) - execDec("int16", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("int16 a = %v not 17", data.a) + execDec("int16", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("int16 a = %v not 17", data) } } // uint16 { - var data struct { - a uint16 - } - instr := &decInstr{decUint16, 6, 0, 0, ovfl} + var data uint16 + instr := &decInstr{decUint16, 6, nil, ovfl} state := newDecodeStateFromData(unsignedResult) - execDec("uint16", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("uint16 a = %v not 17", data.a) + execDec("uint16", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("uint16 a = %v not 17", data) } } // int32 { - var data struct { - a int32 - } - instr := &decInstr{decInt32, 6, 0, 0, ovfl} + var data int32 + instr := &decInstr{decInt32, 6, nil, ovfl} state := newDecodeStateFromData(signedResult) - execDec("int32", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("int32 a = %v not 17", data.a) + execDec("int32", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("int32 a = %v not 17", data) } } // uint32 { - var data struct { - a uint32 - } - instr := &decInstr{decUint32, 6, 0, 0, ovfl} + var data uint32 + instr := &decInstr{decUint32, 6, nil, ovfl} state := newDecodeStateFromData(unsignedResult) - execDec("uint32", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("uint32 a = %v not 17", data.a) + execDec("uint32", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("uint32 a = %v not 17", data) } } // uintptr { - var data struct { - a uintptr - } - instr := &decInstr{decOpTable[reflect.Uintptr], 6, 0, 0, ovfl} + var data uintptr + instr := &decInstr{decOpTable[reflect.Uintptr], 6, nil, ovfl} state := newDecodeStateFromData(unsignedResult) - execDec("uintptr", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("uintptr a = %v not 17", data.a) + execDec("uintptr", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("uintptr a = %v not 17", data) } } // int64 { - var data struct { - a int64 - } - instr := &decInstr{decInt64, 6, 0, 0, ovfl} + var data int64 + instr := &decInstr{decInt64, 6, nil, ovfl} state := newDecodeStateFromData(signedResult) - execDec("int64", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("int64 a = %v not 17", data.a) + execDec("int64", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("int64 a = %v not 17", data) } } // uint64 { - var data struct { - a uint64 - } - instr := &decInstr{decUint64, 6, 0, 0, ovfl} + var data uint64 + instr := &decInstr{decUint64, 6, nil, ovfl} state := newDecodeStateFromData(unsignedResult) - execDec("uint64", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("uint64 a = %v not 17", data.a) + execDec("uint64", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("uint64 a = %v not 17", data) } } // float32 { - var data struct { - a float32 - } - instr := &decInstr{decFloat32, 6, 0, 0, ovfl} + var data float32 + instr := &decInstr{decFloat32, 6, nil, ovfl} state := newDecodeStateFromData(floatResult) - execDec("float32", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("float32 a = %v not 17", data.a) + execDec("float32", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("float32 a = %v not 17", data) } } // float64 { - var data struct { - a float64 - } - instr := &decInstr{decFloat64, 6, 0, 0, ovfl} + var data float64 + instr := &decInstr{decFloat64, 6, nil, ovfl} state := newDecodeStateFromData(floatResult) - execDec("float64", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17 { - t.Errorf("float64 a = %v not 17", data.a) + execDec("float64", instr, state, t, reflect.ValueOf(&data)) + if data != 17 { + t.Errorf("float64 a = %v not 17", data) } } // complex64 { - var data struct { - a complex64 - } - instr := &decInstr{decOpTable[reflect.Complex64], 6, 0, 0, ovfl} + var data complex64 + instr := &decInstr{decOpTable[reflect.Complex64], 6, nil, ovfl} state := newDecodeStateFromData(complexResult) - execDec("complex", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17+19i { - t.Errorf("complex a = %v not 17+19i", data.a) + execDec("complex", instr, state, t, reflect.ValueOf(&data)) + if data != 17+19i { + t.Errorf("complex a = %v not 17+19i", data) } } // complex128 { - var data struct { - a complex128 - } - instr := &decInstr{decOpTable[reflect.Complex128], 6, 0, 0, ovfl} + var data complex128 + instr := &decInstr{decOpTable[reflect.Complex128], 6, nil, ovfl} state := newDecodeStateFromData(complexResult) - execDec("complex", instr, state, t, unsafe.Pointer(&data)) - if data.a != 17+19i { - t.Errorf("complex a = %v not 17+19i", data.a) + execDec("complex", instr, state, t, reflect.ValueOf(&data)) + if data != 17+19i { + t.Errorf("complex a = %v not 17+19i", data) } } // bytes == []uint8 { - var data struct { - a []byte - } - instr := &decInstr{decUint8Slice, 6, 0, 0, ovfl} + var data []byte + instr := &decInstr{decUint8Slice, 6, nil, ovfl} state := newDecodeStateFromData(bytesResult) - execDec("bytes", instr, state, t, unsafe.Pointer(&data)) - if string(data.a) != "hello" { - t.Errorf(`bytes a = %q not "hello"`, string(data.a)) + execDec("bytes", instr, state, t, reflect.ValueOf(&data)) + if string(data) != "hello" { + t.Errorf(`bytes a = %q not "hello"`, string(data)) } } // string { - var data struct { - a string - } - instr := &decInstr{decString, 6, 0, 0, ovfl} + var data string + instr := &decInstr{decString, 6, nil, ovfl} state := newDecodeStateFromData(bytesResult) - execDec("bytes", instr, state, t, unsafe.Pointer(&data)) - if data.a != "hello" { - t.Errorf(`bytes a = %q not "hello"`, data.a) + execDec("bytes", instr, state, t, reflect.ValueOf(&data)) + if data != "hello" { + t.Errorf(`bytes a = %q not "hello"`, data) } } } @@ -1364,11 +1333,7 @@ type DT struct { S []string } -func TestDebugStruct(t *testing.T) { - if debugFunc == nil { - return - } - Register(OnTheFly{}) +func newDT() DT { var dt DT dt.A = 17 dt.B = "hello" @@ -1379,6 +1344,15 @@ func TestDebugStruct(t *testing.T) { dt.M = map[string]int{"one": 1, "two": 2} dt.T = [3]int{11, 22, 33} dt.S = []string{"hi", "joe"} + return dt +} + +func TestDebugStruct(t *testing.T) { + if debugFunc == nil { + return + } + Register(OnTheFly{}) + dt := newDT() b := new(bytes.Buffer) err := NewEncoder(b).Encode(dt) if err != nil { @@ -1458,3 +1432,44 @@ func testFuzz(t *testing.T, seed int64, n int, input ...interface{}) { } } } + +// TestFuzzOneByte tries to decode corrupted input sequences +// and checks that no panic occurs. +func TestFuzzOneByte(t *testing.T) { + buf := new(bytes.Buffer) + Register(OnTheFly{}) + dt := newDT() + if err := NewEncoder(buf).Encode(dt); err != nil { + t.Fatal(err) + } + s := buf.String() + + indices := make([]int, 0, len(s)) + for i := 0; i < len(s); i++ { + switch i { + case 14, 167, 231, 265: // a slice length, corruptions are not handled yet. + continue + } + indices = append(indices, i) + } + if testing.Short() { + indices = []int{1, 111, 178} // known fixed panics + } + for _, i := range indices { + for j := 0; j < 256; j += 3 { + b := []byte(s) + b[i] ^= byte(j) + var e DT + func() { + defer func() { + if p := recover(); p != nil { + t.Errorf("crash for b[%d] ^= 0x%x", i, j) + panic(p) + } + }() + err := NewDecoder(bytes.NewReader(b)).Decode(&e) + _ = err + }() + } + } +} diff --git a/libgo/go/encoding/gob/debug.go b/libgo/go/encoding/gob/debug.go index 6117eb0837..536bbdb5ac 100644 --- a/libgo/go/encoding/gob/debug.go +++ b/libgo/go/encoding/gob/debug.go @@ -306,7 +306,7 @@ func (deb *debugger) common() CommonType { // Id typeId id = deb.typeId() default: - errorf("corrupted CommonType") + errorf("corrupted CommonType, delta is %d fieldNum is %d", delta, fieldNum) } } return CommonType{name, id} @@ -598,11 +598,11 @@ func (deb *debugger) printBuiltin(indent tab, id typeId) { fmt.Fprintf(os.Stderr, "%s%d\n", indent, x) case tFloat: x := deb.uint64() - fmt.Fprintf(os.Stderr, "%s%g\n", indent, floatFromBits(x)) + fmt.Fprintf(os.Stderr, "%s%g\n", indent, float64FromBits(x)) case tComplex: r := deb.uint64() i := deb.uint64() - fmt.Fprintf(os.Stderr, "%s%g+%gi\n", indent, floatFromBits(r), floatFromBits(i)) + fmt.Fprintf(os.Stderr, "%s%g+%gi\n", indent, float64FromBits(r), float64FromBits(i)) case tBytes: x := int(deb.uint64()) b := make([]byte, x) diff --git a/libgo/go/encoding/gob/dec_helpers.go b/libgo/go/encoding/gob/dec_helpers.go new file mode 100644 index 0000000000..a1b67661d8 --- /dev/null +++ b/libgo/go/encoding/gob/dec_helpers.go @@ -0,0 +1,468 @@ +// Created by decgen --output dec_helpers.go; DO NOT EDIT + +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gob + +import ( + "math" + "reflect" +) + +var decArrayHelper = map[reflect.Kind]decHelper{ + reflect.Bool: decBoolArray, + reflect.Complex64: decComplex64Array, + reflect.Complex128: decComplex128Array, + reflect.Float32: decFloat32Array, + reflect.Float64: decFloat64Array, + reflect.Int: decIntArray, + reflect.Int16: decInt16Array, + reflect.Int32: decInt32Array, + reflect.Int64: decInt64Array, + reflect.Int8: decInt8Array, + reflect.String: decStringArray, + reflect.Uint: decUintArray, + reflect.Uint16: decUint16Array, + reflect.Uint32: decUint32Array, + reflect.Uint64: decUint64Array, + reflect.Uintptr: decUintptrArray, +} + +var decSliceHelper = map[reflect.Kind]decHelper{ + reflect.Bool: decBoolSlice, + reflect.Complex64: decComplex64Slice, + reflect.Complex128: decComplex128Slice, + reflect.Float32: decFloat32Slice, + reflect.Float64: decFloat64Slice, + reflect.Int: decIntSlice, + reflect.Int16: decInt16Slice, + reflect.Int32: decInt32Slice, + reflect.Int64: decInt64Slice, + reflect.Int8: decInt8Slice, + reflect.String: decStringSlice, + reflect.Uint: decUintSlice, + reflect.Uint16: decUint16Slice, + reflect.Uint32: decUint32Slice, + reflect.Uint64: decUint64Slice, + reflect.Uintptr: decUintptrSlice, +} + +func decBoolArray(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decBoolSlice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decBoolSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]bool) + if !ok { + // It is kind bool but not type bool. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding bool array or slice: length exceeds input size (%d elements)", length) + } + slice[i] = state.decodeUint() != 0 + } + return true +} + +func decComplex64Array(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decComplex64Slice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decComplex64Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]complex64) + if !ok { + // It is kind complex64 but not type complex64. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding complex64 array or slice: length exceeds input size (%d elements)", length) + } + real := float32FromBits(state.decodeUint(), ovfl) + imag := float32FromBits(state.decodeUint(), ovfl) + slice[i] = complex(float32(real), float32(imag)) + } + return true +} + +func decComplex128Array(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decComplex128Slice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decComplex128Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]complex128) + if !ok { + // It is kind complex128 but not type complex128. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding complex128 array or slice: length exceeds input size (%d elements)", length) + } + real := float64FromBits(state.decodeUint()) + imag := float64FromBits(state.decodeUint()) + slice[i] = complex(real, imag) + } + return true +} + +func decFloat32Array(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decFloat32Slice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decFloat32Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]float32) + if !ok { + // It is kind float32 but not type float32. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding float32 array or slice: length exceeds input size (%d elements)", length) + } + slice[i] = float32(float32FromBits(state.decodeUint(), ovfl)) + } + return true +} + +func decFloat64Array(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decFloat64Slice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decFloat64Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]float64) + if !ok { + // It is kind float64 but not type float64. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding float64 array or slice: length exceeds input size (%d elements)", length) + } + slice[i] = float64FromBits(state.decodeUint()) + } + return true +} + +func decIntArray(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decIntSlice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decIntSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]int) + if !ok { + // It is kind int but not type int. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding int array or slice: length exceeds input size (%d elements)", length) + } + x := state.decodeInt() + // MinInt and MaxInt + if x < ^int64(^uint(0)>>1) || int64(^uint(0)>>1) < x { + error_(ovfl) + } + slice[i] = int(x) + } + return true +} + +func decInt16Array(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decInt16Slice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decInt16Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]int16) + if !ok { + // It is kind int16 but not type int16. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding int16 array or slice: length exceeds input size (%d elements)", length) + } + x := state.decodeInt() + if x < math.MinInt16 || math.MaxInt16 < x { + error_(ovfl) + } + slice[i] = int16(x) + } + return true +} + +func decInt32Array(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decInt32Slice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decInt32Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]int32) + if !ok { + // It is kind int32 but not type int32. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding int32 array or slice: length exceeds input size (%d elements)", length) + } + x := state.decodeInt() + if x < math.MinInt32 || math.MaxInt32 < x { + error_(ovfl) + } + slice[i] = int32(x) + } + return true +} + +func decInt64Array(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decInt64Slice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decInt64Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]int64) + if !ok { + // It is kind int64 but not type int64. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding int64 array or slice: length exceeds input size (%d elements)", length) + } + slice[i] = state.decodeInt() + } + return true +} + +func decInt8Array(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decInt8Slice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decInt8Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]int8) + if !ok { + // It is kind int8 but not type int8. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding int8 array or slice: length exceeds input size (%d elements)", length) + } + x := state.decodeInt() + if x < math.MinInt8 || math.MaxInt8 < x { + error_(ovfl) + } + slice[i] = int8(x) + } + return true +} + +func decStringArray(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decStringSlice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decStringSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]string) + if !ok { + // It is kind string but not type string. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding string array or slice: length exceeds input size (%d elements)", length) + } + u := state.decodeUint() + n := int(u) + if n < 0 || uint64(n) != u || n > state.b.Len() { + errorf("length of string exceeds input size (%d bytes)", u) + } + if n > state.b.Len() { + errorf("string data too long for buffer: %d", n) + } + // Read the data. + data := make([]byte, n) + if _, err := state.b.Read(data); err != nil { + errorf("error decoding string: %s", err) + } + slice[i] = string(data) + } + return true +} + +func decUintArray(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decUintSlice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decUintSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]uint) + if !ok { + // It is kind uint but not type uint. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding uint array or slice: length exceeds input size (%d elements)", length) + } + x := state.decodeUint() + /*TODO if math.MaxUint32 < x { + error_(ovfl) + }*/ + slice[i] = uint(x) + } + return true +} + +func decUint16Array(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decUint16Slice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decUint16Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]uint16) + if !ok { + // It is kind uint16 but not type uint16. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding uint16 array or slice: length exceeds input size (%d elements)", length) + } + x := state.decodeUint() + if math.MaxUint16 < x { + error_(ovfl) + } + slice[i] = uint16(x) + } + return true +} + +func decUint32Array(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decUint32Slice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decUint32Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]uint32) + if !ok { + // It is kind uint32 but not type uint32. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding uint32 array or slice: length exceeds input size (%d elements)", length) + } + x := state.decodeUint() + if math.MaxUint32 < x { + error_(ovfl) + } + slice[i] = uint32(x) + } + return true +} + +func decUint64Array(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decUint64Slice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decUint64Slice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]uint64) + if !ok { + // It is kind uint64 but not type uint64. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding uint64 array or slice: length exceeds input size (%d elements)", length) + } + slice[i] = state.decodeUint() + } + return true +} + +func decUintptrArray(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return decUintptrSlice(state, v.Slice(0, v.Len()), length, ovfl) +} + +func decUintptrSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]uintptr) + if !ok { + // It is kind uintptr but not type uintptr. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding uintptr array or slice: length exceeds input size (%d elements)", length) + } + x := state.decodeUint() + if uint64(^uintptr(0)) < x { + error_(ovfl) + } + slice[i] = uintptr(x) + } + return true +} diff --git a/libgo/go/encoding/gob/decgen.go b/libgo/go/encoding/gob/decgen.go new file mode 100644 index 0000000000..da41a899ed --- /dev/null +++ b/libgo/go/encoding/gob/decgen.go @@ -0,0 +1,240 @@ +// 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. + +// +build ignore + +// encgen writes the helper functions for encoding. Intended to be +// used with go generate; see the invocation in encode.go. + +// TODO: We could do more by being unsafe. Add a -unsafe flag? + +package main + +import ( + "bytes" + "flag" + "fmt" + "go/format" + "log" + "os" +) + +var output = flag.String("output", "dec_helpers.go", "file name to write") + +type Type struct { + lower string + upper string + decoder string +} + +var types = []Type{ + { + "bool", + "Bool", + `slice[i] = state.decodeUint() != 0`, + }, + { + "complex64", + "Complex64", + `real := float32FromBits(state.decodeUint(), ovfl) + imag := float32FromBits(state.decodeUint(), ovfl) + slice[i] = complex(float32(real), float32(imag))`, + }, + { + "complex128", + "Complex128", + `real := float64FromBits(state.decodeUint()) + imag := float64FromBits(state.decodeUint()) + slice[i] = complex(real, imag)`, + }, + { + "float32", + "Float32", + `slice[i] = float32(float32FromBits(state.decodeUint(), ovfl))`, + }, + { + "float64", + "Float64", + `slice[i] = float64FromBits(state.decodeUint())`, + }, + { + "int", + "Int", + `x := state.decodeInt() + // MinInt and MaxInt + if x < ^int64(^uint(0)>>1) || int64(^uint(0)>>1) < x { + error_(ovfl) + } + slice[i] = int(x)`, + }, + { + "int16", + "Int16", + `x := state.decodeInt() + if x < math.MinInt16 || math.MaxInt16 < x { + error_(ovfl) + } + slice[i] = int16(x)`, + }, + { + "int32", + "Int32", + `x := state.decodeInt() + if x < math.MinInt32 || math.MaxInt32 < x { + error_(ovfl) + } + slice[i] = int32(x)`, + }, + { + "int64", + "Int64", + `slice[i] = state.decodeInt()`, + }, + { + "int8", + "Int8", + `x := state.decodeInt() + if x < math.MinInt8 || math.MaxInt8 < x { + error_(ovfl) + } + slice[i] = int8(x)`, + }, + { + "string", + "String", + `u := state.decodeUint() + n := int(u) + if n < 0 || uint64(n) != u || n > state.b.Len() { + errorf("length of string exceeds input size (%d bytes)", u) + } + if n > state.b.Len() { + errorf("string data too long for buffer: %d", n) + } + // Read the data. + data := make([]byte, n) + if _, err := state.b.Read(data); err != nil { + errorf("error decoding string: %s", err) + } + slice[i] = string(data)`, + }, + { + "uint", + "Uint", + `x := state.decodeUint() + /*TODO if math.MaxUint32 < x { + error_(ovfl) + }*/ + slice[i] = uint(x)`, + }, + { + "uint16", + "Uint16", + `x := state.decodeUint() + if math.MaxUint16 < x { + error_(ovfl) + } + slice[i] = uint16(x)`, + }, + { + "uint32", + "Uint32", + `x := state.decodeUint() + if math.MaxUint32 < x { + error_(ovfl) + } + slice[i] = uint32(x)`, + }, + { + "uint64", + "Uint64", + `slice[i] = state.decodeUint()`, + }, + { + "uintptr", + "Uintptr", + `x := state.decodeUint() + if uint64(^uintptr(0)) < x { + error_(ovfl) + } + slice[i] = uintptr(x)`, + }, + // uint8 Handled separately. +} + +func main() { + log.SetFlags(0) + log.SetPrefix("decgen: ") + flag.Parse() + if flag.NArg() != 0 { + log.Fatal("usage: decgen [--output filename]") + } + var b bytes.Buffer + fmt.Fprintf(&b, "// Created by decgen --output %s; DO NOT EDIT\n", *output) + fmt.Fprint(&b, header) + printMaps(&b, "Array") + fmt.Fprint(&b, "\n") + printMaps(&b, "Slice") + for _, t := range types { + fmt.Fprintf(&b, arrayHelper, t.lower, t.upper) + fmt.Fprintf(&b, sliceHelper, t.lower, t.upper, t.decoder) + } + source, err := format.Source(b.Bytes()) + if err != nil { + log.Fatal("source format error:", err) + } + fd, err := os.Create(*output) + _, err = fd.Write(source) + if err != nil { + log.Fatal(err) + } +} + +func printMaps(b *bytes.Buffer, upperClass string) { + fmt.Fprintf(b, "var dec%sHelper = map[reflect.Kind]decHelper{\n", upperClass) + for _, t := range types { + fmt.Fprintf(b, "reflect.%s: dec%s%s,\n", t.upper, t.upper, upperClass) + } + fmt.Fprintf(b, "}\n") +} + +const header = ` +// 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 gob + +import ( + "math" + "reflect" +) + +` + +const arrayHelper = ` +func dec%[2]sArray(state *decoderState, v reflect.Value, length int, ovfl error) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return dec%[2]sSlice(state, v.Slice(0, v.Len()), length, ovfl) +} +` + +const sliceHelper = ` +func dec%[2]sSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool { + slice, ok := v.Interface().([]%[1]s) + if !ok { + // It is kind %[1]s but not type %[1]s. TODO: We can handle this unsafely. + return false + } + for i := 0; i < length; i++ { + if state.b.Len() == 0 { + errorf("decoding %[1]s array or slice: length exceeds input size (%%d elements)", length) + } + %[3]s + } + return true +} +` diff --git a/libgo/go/encoding/gob/decode.go b/libgo/go/encoding/gob/decode.go index 3e76f4c906..a5bef93141 100644 --- a/libgo/go/encoding/gob/decode.go +++ b/libgo/go/encoding/gob/decode.go @@ -2,19 +2,16 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package gob +//go:generate go run decgen.go -output dec_helpers.go -// TODO(rsc): When garbage collector changes, revisit -// the allocations in this file that use unsafe.Pointer. +package gob import ( - "bytes" "encoding" "errors" "io" "math" "reflect" - "unsafe" ) var ( @@ -23,21 +20,79 @@ var ( errRange = errors.New("gob: bad data: field numbers out of bounds") ) +type decHelper func(state *decoderState, v reflect.Value, length int, ovfl error) bool + // decoderState is the execution state of an instance of the decoder. A new state // is created for nested objects. type decoderState struct { dec *Decoder // The buffer is stored with an extra indirection because it may be replaced // if we load a type during decode (when reading an interface value). - b *bytes.Buffer + b *decBuffer fieldnum int // the last field number read. buf []byte next *decoderState // for free list } +// decBuffer is an extremely simple, fast implementation of a read-only byte buffer. +// It is initialized by calling Size and then copying the data into the slice returned by Bytes(). +type decBuffer struct { + data []byte + offset int // Read offset. +} + +func (d *decBuffer) Read(p []byte) (int, error) { + n := copy(p, d.data[d.offset:]) + if n == 0 && len(p) != 0 { + return 0, io.EOF + } + d.offset += n + return n, nil +} + +func (d *decBuffer) Drop(n int) { + if n > d.Len() { + panic("drop") + } + d.offset += n +} + +// Size grows the buffer to exactly n bytes, so d.Bytes() will +// return a slice of length n. Existing data is first discarded. +func (d *decBuffer) Size(n int) { + d.Reset() + if cap(d.data) < n { + d.data = make([]byte, n) + } else { + d.data = d.data[0:n] + } +} + +func (d *decBuffer) ReadByte() (byte, error) { + if d.offset >= len(d.data) { + return 0, io.EOF + } + c := d.data[d.offset] + d.offset++ + return c, nil +} + +func (d *decBuffer) Len() int { + return len(d.data) - d.offset +} + +func (d *decBuffer) Bytes() []byte { + return d.data[d.offset:] +} + +func (d *decBuffer) Reset() { + d.data = d.data[0:0] + d.offset = 0 +} + // We pass the bytes.Buffer separately for easier testing of the infrastructure // without requiring a full Decoder. -func (dec *Decoder) newDecoderState(buf *bytes.Buffer) *decoderState { +func (dec *Decoder) newDecoderState(buf *decBuffer) *decoderState { d := dec.freeList if d == nil { d = new(decoderState) @@ -128,175 +183,118 @@ func (state *decoderState) decodeInt() int64 { } // decOp is the signature of a decoding operator for a given type. -type decOp func(i *decInstr, state *decoderState, p unsafe.Pointer) +type decOp func(i *decInstr, state *decoderState, v reflect.Value) // The 'instructions' of the decoding machine type decInstr struct { - op decOp - field int // field number of the wire type - indir int // how many pointer indirections to reach the value in the struct - offset uintptr // offset in the structure of the field to encode - ovfl error // error message for overflow/underflow (for arrays, of the elements) -} - -// Since the encoder writes no zeros, if we arrive at a decoder we have -// a value to extract and store. The field number has already been read -// (it's how we knew to call this decoder). -// Each decoder is responsible for handling any indirections associated -// with the data structure. If any pointer so reached is nil, allocation must -// be done. - -// Walk the pointer hierarchy, allocating if we find a nil. Stop one before the end. -func decIndirect(p unsafe.Pointer, indir int) unsafe.Pointer { - for ; indir > 1; indir-- { - if *(*unsafe.Pointer)(p) == nil { - // Allocation required - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(unsafe.Pointer)) - } - p = *(*unsafe.Pointer)(p) - } - return p + op decOp + field int // field number of the wire type + index []int // field access indices for destination type + ovfl error // error message for overflow/underflow (for arrays, of the elements) } // ignoreUint discards a uint value with no destination. -func ignoreUint(i *decInstr, state *decoderState, p unsafe.Pointer) { +func ignoreUint(i *decInstr, state *decoderState, v reflect.Value) { state.decodeUint() } // ignoreTwoUints discards a uint value with no destination. It's used to skip // complex values. -func ignoreTwoUints(i *decInstr, state *decoderState, p unsafe.Pointer) { +func ignoreTwoUints(i *decInstr, state *decoderState, v reflect.Value) { state.decodeUint() state.decodeUint() } -// decBool decodes a uint and stores it as a boolean through p. -func decBool(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(bool)) +// Since the encoder writes no zeros, if we arrive at a decoder we have +// a value to extract and store. The field number has already been read +// (it's how we knew to call this decoder). +// Each decoder is responsible for handling any indirections associated +// with the data structure. If any pointer so reached is nil, allocation must +// be done. + +// decAlloc takes a value and returns a settable value that can +// be assigned to. If the value is a pointer, decAlloc guarantees it points to storage. +// The callers to the individual decoders are expected to have used decAlloc. +// The individual decoders don't need to it. +func decAlloc(v reflect.Value) reflect.Value { + for v.Kind() == reflect.Ptr { + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) } - p = *(*unsafe.Pointer)(p) + v = v.Elem() } - *(*bool)(p) = state.decodeUint() != 0 + return v } -// decInt8 decodes an integer and stores it as an int8 through p. -func decInt8(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int8)) - } - p = *(*unsafe.Pointer)(p) - } +// decBool decodes a uint and stores it as a boolean in value. +func decBool(i *decInstr, state *decoderState, value reflect.Value) { + value.SetBool(state.decodeUint() != 0) +} + +// decInt8 decodes an integer and stores it as an int8 in value. +func decInt8(i *decInstr, state *decoderState, value reflect.Value) { v := state.decodeInt() if v < math.MinInt8 || math.MaxInt8 < v { error_(i.ovfl) - } else { - *(*int8)(p) = int8(v) } + value.SetInt(v) } -// decUint8 decodes an unsigned integer and stores it as a uint8 through p. -func decUint8(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint8)) - } - p = *(*unsafe.Pointer)(p) - } +// decUint8 decodes an unsigned integer and stores it as a uint8 in value. +func decUint8(i *decInstr, state *decoderState, value reflect.Value) { v := state.decodeUint() if math.MaxUint8 < v { error_(i.ovfl) - } else { - *(*uint8)(p) = uint8(v) } + value.SetUint(v) } -// decInt16 decodes an integer and stores it as an int16 through p. -func decInt16(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int16)) - } - p = *(*unsafe.Pointer)(p) - } +// decInt16 decodes an integer and stores it as an int16 in value. +func decInt16(i *decInstr, state *decoderState, value reflect.Value) { v := state.decodeInt() if v < math.MinInt16 || math.MaxInt16 < v { error_(i.ovfl) - } else { - *(*int16)(p) = int16(v) } + value.SetInt(v) } -// decUint16 decodes an unsigned integer and stores it as a uint16 through p. -func decUint16(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint16)) - } - p = *(*unsafe.Pointer)(p) - } +// decUint16 decodes an unsigned integer and stores it as a uint16 in value. +func decUint16(i *decInstr, state *decoderState, value reflect.Value) { v := state.decodeUint() if math.MaxUint16 < v { error_(i.ovfl) - } else { - *(*uint16)(p) = uint16(v) } + value.SetUint(v) } -// decInt32 decodes an integer and stores it as an int32 through p. -func decInt32(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int32)) - } - p = *(*unsafe.Pointer)(p) - } +// decInt32 decodes an integer and stores it as an int32 in value. +func decInt32(i *decInstr, state *decoderState, value reflect.Value) { v := state.decodeInt() if v < math.MinInt32 || math.MaxInt32 < v { error_(i.ovfl) - } else { - *(*int32)(p) = int32(v) } + value.SetInt(v) } -// decUint32 decodes an unsigned integer and stores it as a uint32 through p. -func decUint32(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint32)) - } - p = *(*unsafe.Pointer)(p) - } +// decUint32 decodes an unsigned integer and stores it as a uint32 in value. +func decUint32(i *decInstr, state *decoderState, value reflect.Value) { v := state.decodeUint() if math.MaxUint32 < v { error_(i.ovfl) - } else { - *(*uint32)(p) = uint32(v) } + value.SetUint(v) } -// decInt64 decodes an integer and stores it as an int64 through p. -func decInt64(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(int64)) - } - p = *(*unsafe.Pointer)(p) - } - *(*int64)(p) = int64(state.decodeInt()) +// decInt64 decodes an integer and stores it as an int64 in value. +func decInt64(i *decInstr, state *decoderState, value reflect.Value) { + v := state.decodeInt() + value.SetInt(v) } -// decUint64 decodes an unsigned integer and stores it as a uint64 through p. -func decUint64(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(uint64)) - } - p = *(*unsafe.Pointer)(p) - } - *(*uint64)(p) = uint64(state.decodeUint()) +// decUint64 decodes an unsigned integer and stores it as a uint64 in value. +func decUint64(i *decInstr, state *decoderState, value reflect.Value) { + v := state.decodeUint() + value.SetUint(v) } // Floating-point numbers are transmitted as uint64s holding the bits @@ -304,7 +302,7 @@ func decUint64(i *decInstr, state *decoderState, p unsafe.Pointer) { // the exponent end coming out first, so integer floating point numbers // (for example) transmit more compactly. This routine does the // unswizzling. -func floatFromBits(u uint64) float64 { +func float64FromBits(u uint64) float64 { var v uint64 for i := 0; i < 8; i++ { v <<= 8 @@ -314,128 +312,100 @@ func floatFromBits(u uint64) float64 { return math.Float64frombits(v) } -// storeFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point -// number, and stores it through p. It's a helper function for float32 and complex64. -func storeFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) { - v := floatFromBits(state.decodeUint()) +// float32FromBits decodes an unsigned integer, treats it as a 32-bit floating-point +// number, and returns it. It's a helper function for float32 and complex64. +// It returns a float64 because that's what reflection needs, but its return +// value is known to be accurately representable in a float32. +func float32FromBits(u uint64, ovfl error) float64 { + v := float64FromBits(u) av := v if av < 0 { av = -av } // +Inf is OK in both 32- and 64-bit floats. Underflow is always OK. if math.MaxFloat32 < av && av <= math.MaxFloat64 { - error_(i.ovfl) - } else { - *(*float32)(p) = float32(v) + error_(ovfl) } + return v } // decFloat32 decodes an unsigned integer, treats it as a 32-bit floating-point -// number, and stores it through p. -func decFloat32(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float32)) - } - p = *(*unsafe.Pointer)(p) - } - storeFloat32(i, state, p) +// number, and stores it in value. +func decFloat32(i *decInstr, state *decoderState, value reflect.Value) { + value.SetFloat(float32FromBits(state.decodeUint(), i.ovfl)) } // decFloat64 decodes an unsigned integer, treats it as a 64-bit floating-point -// number, and stores it through p. -func decFloat64(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(float64)) - } - p = *(*unsafe.Pointer)(p) - } - *(*float64)(p) = floatFromBits(uint64(state.decodeUint())) +// number, and stores it in value. +func decFloat64(i *decInstr, state *decoderState, value reflect.Value) { + value.SetFloat(float64FromBits(state.decodeUint())) } // decComplex64 decodes a pair of unsigned integers, treats them as a -// pair of floating point numbers, and stores them as a complex64 through p. +// pair of floating point numbers, and stores them as a complex64 in value. // The real part comes first. -func decComplex64(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex64)) - } - p = *(*unsafe.Pointer)(p) - } - storeFloat32(i, state, p) - storeFloat32(i, state, unsafe.Pointer(uintptr(p)+unsafe.Sizeof(float32(0)))) +func decComplex64(i *decInstr, state *decoderState, value reflect.Value) { + real := float32FromBits(state.decodeUint(), i.ovfl) + imag := float32FromBits(state.decodeUint(), i.ovfl) + value.SetComplex(complex(real, imag)) } // decComplex128 decodes a pair of unsigned integers, treats them as a -// pair of floating point numbers, and stores them as a complex128 through p. +// pair of floating point numbers, and stores them as a complex128 in value. // The real part comes first. -func decComplex128(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex128)) - } - p = *(*unsafe.Pointer)(p) - } - real := floatFromBits(uint64(state.decodeUint())) - imag := floatFromBits(uint64(state.decodeUint())) - *(*complex128)(p) = complex(real, imag) +func decComplex128(i *decInstr, state *decoderState, value reflect.Value) { + real := float64FromBits(state.decodeUint()) + imag := float64FromBits(state.decodeUint()) + value.SetComplex(complex(real, imag)) } -// decUint8Slice decodes a byte slice and stores through p a slice header +// decUint8Slice decodes a byte slice and stores in value a slice header // describing the data. // uint8 slices are encoded as an unsigned count followed by the raw bytes. -func decUint8Slice(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8)) - } - p = *(*unsafe.Pointer)(p) +func decUint8Slice(i *decInstr, state *decoderState, value reflect.Value) { + u := state.decodeUint() + n := int(u) + if n < 0 || uint64(n) != u { + errorf("length of %s exceeds input size (%d bytes)", value.Type(), u) } - n := state.decodeUint() - if n > uint64(state.b.Len()) { - errorf("length of []byte exceeds input size (%d bytes)", n) + if n > state.b.Len() { + errorf("%s data too long for buffer: %d", value.Type(), n) } - slice := (*[]uint8)(p) - if uint64(cap(*slice)) < n { - *slice = make([]uint8, n) + if n > tooBig { + errorf("byte slice too big: %d", n) + } + if value.Cap() < n { + value.Set(reflect.MakeSlice(value.Type(), n, n)) } else { - *slice = (*slice)[0:n] + value.Set(value.Slice(0, n)) } - if _, err := state.b.Read(*slice); err != nil { + if _, err := state.b.Read(value.Bytes()); err != nil { errorf("error decoding []byte: %s", err) } } -// decString decodes byte array and stores through p a string header +// decString decodes byte array and stores in value a string header // describing the data. // Strings are encoded as an unsigned count followed by the raw bytes. -func decString(i *decInstr, state *decoderState, p unsafe.Pointer) { - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(new(string)) - } - p = *(*unsafe.Pointer)(p) +func decString(i *decInstr, state *decoderState, value reflect.Value) { + u := state.decodeUint() + n := int(u) + if n < 0 || uint64(n) != u || n > state.b.Len() { + errorf("length of %s exceeds input size (%d bytes)", value.Type(), u) } - n := state.decodeUint() - if n > uint64(state.b.Len()) { - errorf("string length exceeds input size (%d bytes)", n) + if n > state.b.Len() { + errorf("%s data too long for buffer: %d", value.Type(), n) } - b := make([]byte, n) - state.b.Read(b) - // It would be a shame to do the obvious thing here, - // *(*string)(p) = string(b) - // because we've already allocated the storage and this would - // allocate again and copy. So we do this ugly hack, which is even - // even more unsafe than it looks as it depends the memory - // representation of a string matching the beginning of the memory - // representation of a byte slice (a byte slice is longer). - *(*string)(p) = *(*string)(unsafe.Pointer(&b)) + // Read the data. + data := make([]byte, n) + if _, err := state.b.Read(data); err != nil { + errorf("error decoding string: %s", err) + } + value.SetString(string(data)) } // ignoreUint8Array skips over the data for a byte slice value with no destination. -func ignoreUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) { +func ignoreUint8Array(i *decInstr, state *decoderState, value reflect.Value) { b := make([]byte, state.decodeUint()) state.b.Read(b) } @@ -449,55 +419,29 @@ type decEngine struct { numInstr int // the number of active instructions } -// allocate makes sure storage is available for an object of underlying type rtyp -// that is indir levels of indirection through p. -func allocate(rtyp reflect.Type, p unsafe.Pointer, indir int) unsafe.Pointer { - if indir == 0 { - return p - } - up := p - if indir > 1 { - up = decIndirect(up, indir) - } - if *(*unsafe.Pointer)(up) == nil { - // Allocate object. - *(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.New(rtyp).Pointer()) - } - return *(*unsafe.Pointer)(up) -} - -// decodeSingle decodes a top-level value that is not a struct and stores it through p. +// decodeSingle decodes a top-level value that is not a struct and stores it in value. // Such values are preceded by a zero, making them have the memory layout of a // struct field (although with an illegal field number). -func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep unsafe.Pointer) { +func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, value reflect.Value) { state := dec.newDecoderState(&dec.buf) + defer dec.freeDecoderState(state) state.fieldnum = singletonField - delta := int(state.decodeUint()) - if delta != 0 { + if state.decodeUint() != 0 { errorf("decode: corrupted data: non-zero delta for singleton") } instr := &engine.instr[singletonField] - if instr.indir != ut.indir { - errorf("internal error: inconsistent indirection instr %d ut %d", instr.indir, ut.indir) - } - ptr := basep // offset will be zero - if instr.indir > 1 { - ptr = decIndirect(ptr, instr.indir) - } - instr.op(instr, state, ptr) - dec.freeDecoderState(state) + instr.op(instr, state, value) } -// decodeStruct decodes a top-level struct and stores it through p. +// decodeStruct decodes a top-level struct and stores it in value. // Indir is for the value, not the type. At the time of the call it may // differ from ut.indir, which was computed when the engine was built. // This state cannot arise for decodeSingle, which is called directly // from the user's value, not from the innards of an engine. -func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p unsafe.Pointer, indir int) { - p = allocate(ut.base, p, indir) +func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, value reflect.Value) { state := dec.newDecoderState(&dec.buf) + defer dec.freeDecoderState(state) state.fieldnum = -1 - basep := p for state.b.Len() > 0 { delta := int(state.decodeUint()) if delta < 0 { @@ -512,19 +456,25 @@ func (dec *Decoder) decodeStruct(engine *decEngine, ut *userTypeInfo, p unsafe.P break } instr := &engine.instr[fieldnum] - p := unsafe.Pointer(uintptr(basep) + instr.offset) - if instr.indir > 1 { - p = decIndirect(p, instr.indir) + var field reflect.Value + if instr.index != nil { + // Otherwise the field is unknown to us and instr.op is an ignore op. + field = value.FieldByIndex(instr.index) + if field.Kind() == reflect.Ptr { + field = decAlloc(field) + } } - instr.op(instr, state, p) + instr.op(instr, state, field) state.fieldnum = fieldnum } - dec.freeDecoderState(state) } +var noValue reflect.Value + // ignoreStruct discards the data for a struct with no destination. func (dec *Decoder) ignoreStruct(engine *decEngine) { state := dec.newDecoderState(&dec.buf) + defer dec.freeDecoderState(state) state.fieldnum = -1 for state.b.Len() > 0 { delta := int(state.decodeUint()) @@ -539,97 +489,89 @@ func (dec *Decoder) ignoreStruct(engine *decEngine) { error_(errRange) } instr := &engine.instr[fieldnum] - instr.op(instr, state, unsafe.Pointer(nil)) + instr.op(instr, state, noValue) state.fieldnum = fieldnum } - dec.freeDecoderState(state) } // ignoreSingle discards the data for a top-level non-struct value with no // destination. It's used when calling Decode with a nil value. func (dec *Decoder) ignoreSingle(engine *decEngine) { state := dec.newDecoderState(&dec.buf) + defer dec.freeDecoderState(state) state.fieldnum = singletonField delta := int(state.decodeUint()) if delta != 0 { errorf("decode: corrupted data: non-zero delta for singleton") } instr := &engine.instr[singletonField] - instr.op(instr, state, unsafe.Pointer(nil)) - dec.freeDecoderState(state) + instr.op(instr, state, noValue) } // decodeArrayHelper does the work for decoding arrays and slices. -func (dec *Decoder) decodeArrayHelper(state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, elemIndir int, ovfl error) { - instr := &decInstr{elemOp, 0, elemIndir, 0, ovfl} +func (dec *Decoder) decodeArrayHelper(state *decoderState, value reflect.Value, elemOp decOp, length int, ovfl error, helper decHelper) { + if helper != nil && helper(state, value, length, ovfl) { + return + } + instr := &decInstr{elemOp, 0, nil, ovfl} + isPtr := value.Type().Elem().Kind() == reflect.Ptr for i := 0; i < length; i++ { if state.b.Len() == 0 { errorf("decoding array or slice: length exceeds input size (%d elements)", length) } - up := p - if elemIndir > 1 { - up = decIndirect(up, elemIndir) + v := value.Index(i) + if isPtr { + v = decAlloc(v) } - elemOp(instr, state, up) - p = unsafe.Pointer(uintptr(p) + elemWid) + elemOp(instr, state, v) } } -// decodeArray decodes an array and stores it through p, that is, p points to the zeroth element. +// decodeArray decodes an array and stores it in value. // The length is an unsigned integer preceding the elements. Even though the length is redundant // (it's part of the type), it's a useful check and is included in the encoding. -func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, p unsafe.Pointer, elemOp decOp, elemWid uintptr, length, indir, elemIndir int, ovfl error) { - if indir > 0 { - p = allocate(atyp, p, 1) // All but the last level has been allocated by dec.Indirect - } +func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, value reflect.Value, elemOp decOp, length int, ovfl error, helper decHelper) { if n := state.decodeUint(); n != uint64(length) { errorf("length mismatch in decodeArray") } - dec.decodeArrayHelper(state, p, elemOp, elemWid, length, elemIndir, ovfl) + dec.decodeArrayHelper(state, value, elemOp, length, ovfl, helper) } -// decodeIntoValue is a helper for map decoding. Since maps are decoded using reflection, -// unlike the other items we can't use a pointer directly. -func decodeIntoValue(state *decoderState, op decOp, indir int, v reflect.Value, ovfl error) reflect.Value { - instr := &decInstr{op, 0, indir, 0, ovfl} - up := unsafeAddr(v) - if indir > 1 { - up = decIndirect(up, indir) +// decodeIntoValue is a helper for map decoding. +func decodeIntoValue(state *decoderState, op decOp, isPtr bool, value reflect.Value, ovfl error) reflect.Value { + instr := &decInstr{op, 0, nil, ovfl} + v := value + if isPtr { + v = decAlloc(value) } - op(instr, state, up) - return v + op(instr, state, v) + return value } -// decodeMap decodes a map and stores its header through p. +// decodeMap decodes a map and stores it in value. // Maps are encoded as a length followed by key:value pairs. // Because the internals of maps are not visible to us, we must // use reflection rather than pointer magic. -func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p unsafe.Pointer, keyOp, elemOp decOp, indir, keyIndir, elemIndir int, ovfl error) { - if indir > 0 { - p = allocate(mtyp, p, 1) // All but the last level has been allocated by dec.Indirect - } - up := unsafe.Pointer(p) - if *(*unsafe.Pointer)(up) == nil { // maps are represented as a pointer in the runtime +func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, value reflect.Value, keyOp, elemOp decOp, ovfl error) { + if value.IsNil() { // Allocate map. - *(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.MakeMap(mtyp).Pointer()) + value.Set(reflect.MakeMap(mtyp)) } - // Maps cannot be accessed by moving addresses around the way - // that slices etc. can. We must recover a full reflection value for - // the iteration. - v := reflect.NewAt(mtyp, unsafe.Pointer(p)).Elem() n := int(state.decodeUint()) + keyIsPtr := mtyp.Key().Kind() == reflect.Ptr + elemIsPtr := mtyp.Elem().Kind() == reflect.Ptr for i := 0; i < n; i++ { - key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl) - elem := decodeIntoValue(state, elemOp, elemIndir, allocValue(mtyp.Elem()), ovfl) - v.SetMapIndex(key, elem) + key := decodeIntoValue(state, keyOp, keyIsPtr, allocValue(mtyp.Key()), ovfl) + elem := decodeIntoValue(state, elemOp, elemIsPtr, allocValue(mtyp.Elem()), ovfl) + value.SetMapIndex(key, elem) } } // ignoreArrayHelper does the work for discarding arrays and slices. func (dec *Decoder) ignoreArrayHelper(state *decoderState, elemOp decOp, length int) { - instr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")} + instr := &decInstr{elemOp, 0, nil, errors.New("no error")} for i := 0; i < length; i++ { - elemOp(instr, state, nil) + elemOp(instr, state, noValue) } } @@ -644,37 +586,34 @@ func (dec *Decoder) ignoreArray(state *decoderState, elemOp decOp, length int) { // ignoreMap discards the data for a map value with no destination. func (dec *Decoder) ignoreMap(state *decoderState, keyOp, elemOp decOp) { n := int(state.decodeUint()) - keyInstr := &decInstr{keyOp, 0, 0, 0, errors.New("no error")} - elemInstr := &decInstr{elemOp, 0, 0, 0, errors.New("no error")} + keyInstr := &decInstr{keyOp, 0, nil, errors.New("no error")} + elemInstr := &decInstr{elemOp, 0, nil, errors.New("no error")} for i := 0; i < n; i++ { - keyOp(keyInstr, state, nil) - elemOp(elemInstr, state, nil) + keyOp(keyInstr, state, noValue) + elemOp(elemInstr, state, noValue) } } -// decodeSlice decodes a slice and stores the slice header through p. +// decodeSlice decodes a slice and stores it in value. // Slices are encoded as an unsigned length followed by the elements. -func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintptr, elemOp decOp, elemWid uintptr, indir, elemIndir int, ovfl error) { - nr := state.decodeUint() - n := int(nr) - if indir > 0 { - up := unsafe.Pointer(p) - if *(*unsafe.Pointer)(up) == nil { - // Allocate the slice header. - *(*unsafe.Pointer)(up) = unsafe.Pointer(new([]unsafe.Pointer)) - } - p = *(*uintptr)(up) - } - // Allocate storage for the slice elements, that is, the underlying array, - // if the existing slice does not have the capacity. - // Always write a header at p. - hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p)) - if hdrp.Cap < n { - hdrp.Data = reflect.MakeSlice(atyp, n, n).Pointer() - hdrp.Cap = n +func (dec *Decoder) decodeSlice(state *decoderState, value reflect.Value, elemOp decOp, ovfl error, helper decHelper) { + u := state.decodeUint() + typ := value.Type() + size := uint64(typ.Elem().Size()) + nBytes := u * size + n := int(u) + // Take care with overflow in this calculation. + if n < 0 || uint64(n) != u || nBytes > tooBig || (size > 0 && nBytes/size != u) { + // We don't check n against buffer length here because if it's a slice + // of interfaces, there will be buffer reloads. + errorf("%s slice too big: %d elements of %d bytes", typ.Elem(), u, size) + } + if value.Cap() < n { + value.Set(reflect.MakeSlice(typ, n, n)) + } else { + value.Set(value.Slice(0, n)) } - hdrp.Len = n - dec.decodeArrayHelper(state, unsafe.Pointer(hdrp.Data), elemOp, elemWid, n, elemIndir, ovfl) + dec.decodeArrayHelper(state, value, elemOp, n, ovfl, helper) } // ignoreSlice skips over the data for a slice value with no destination. @@ -682,36 +621,25 @@ func (dec *Decoder) ignoreSlice(state *decoderState, elemOp decOp) { dec.ignoreArrayHelper(state, elemOp, int(state.decodeUint())) } -// setInterfaceValue sets an interface value to a concrete value, -// but first it checks that the assignment will succeed. -func setInterfaceValue(ivalue reflect.Value, value reflect.Value) { - if !value.Type().AssignableTo(ivalue.Type()) { - errorf("cannot assign value of type %s to %s", value.Type(), ivalue.Type()) - } - ivalue.Set(value) -} - -// decodeInterface decodes an interface value and stores it through p. +// decodeInterface decodes an interface value and stores it in value. // Interfaces are encoded as the name of a concrete type followed by a value. // If the name is empty, the value is nil and no value is sent. -func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p unsafe.Pointer, indir int) { - // Create a writable interface reflect.Value. We need one even for the nil case. - ivalue := allocValue(ityp) +func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, value reflect.Value) { // Read the name of the concrete type. nr := state.decodeUint() if nr < 0 || nr > 1<<31 { // zero is permissible for anonymous types errorf("invalid type name length %d", nr) } + if nr > uint64(state.b.Len()) { + errorf("invalid type name length %d: exceeds input size", nr) + } b := make([]byte, nr) state.b.Read(b) name := string(b) + // Allocate the destination interface value. if name == "" { - // Copy the representation of the nil interface value to the target. - // This is horribly unsafe and special. - if indir > 0 { - p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect - } - *(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData() + // Copy the nil interface value to the target. + value.Set(reflect.Zero(value.Type())) return } if len(name) > 1024 { @@ -733,21 +661,18 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p un // in case we want to ignore the value by skipping it completely). state.decodeUint() // Read the concrete value. - value := allocValue(typ) - dec.decodeValue(concreteId, value) + v := allocValue(typ) + dec.decodeValue(concreteId, v) if dec.err != nil { error_(dec.err) } - // Allocate the destination interface value. - if indir > 0 { - p = allocate(ityp, p, 1) // All but the last level has been allocated by dec.Indirect - } // Assign the concrete value to the interface. // Tread carefully; it might not satisfy the interface. - setInterfaceValue(ivalue, value) - // Copy the representation of the interface value to the target. - // This is horribly unsafe and special. - *(*[2]uintptr)(unsafe.Pointer(p)) = ivalue.InterfaceData() + if !typ.AssignableTo(ityp) { + errorf("%s is not assignable to type %s", typ, ityp) + } + // Copy the interface value to the target. + value.Set(v) } // ignoreInterface discards the data for an interface value with no destination. @@ -763,12 +688,12 @@ func (dec *Decoder) ignoreInterface(state *decoderState) { error_(dec.err) } // At this point, the decoder buffer contains a delimited value. Just toss it. - state.b.Next(int(state.decodeUint())) + state.b.Drop(int(state.decodeUint())) } // decodeGobDecoder decodes something implementing the GobDecoder interface. // The data is encoded as a byte slice. -func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, v reflect.Value) { +func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, value reflect.Value) { // Read the bytes for the value. b := make([]byte, state.decodeUint()) _, err := state.b.Read(b) @@ -778,11 +703,11 @@ func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, v re // We know it's one of these. switch ut.externalDec { case xGob: - err = v.Interface().(GobDecoder).GobDecode(b) + err = value.Interface().(GobDecoder).GobDecode(b) case xBinary: - err = v.Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary(b) + err = value.Interface().(encoding.BinaryUnmarshaler).UnmarshalBinary(b) case xText: - err = v.Interface().(encoding.TextUnmarshaler).UnmarshalText(b) + err = value.Interface().(encoding.TextUnmarshaler).UnmarshalText(b) } if err != nil { error_(err) @@ -830,7 +755,7 @@ var decIgnoreOpMap = map[typeId]decOp{ // decOpFor returns the decoding op for the base type under rt and // the indirection count to reach it. -func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) (*decOp, int) { +func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProgress map[reflect.Type]*decOp) *decOp { ut := userType(rt) // If the type implements GobEncoder, we handle it without further processing. if ut.externalDec != 0 { @@ -840,10 +765,9 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg // If this type is already in progress, it's a recursive type (e.g. map[string]*T). // Return the pointer to the op we're already building. if opPtr := inProgress[rt]; opPtr != nil { - return opPtr, ut.indir + return opPtr } typ := ut.base - indir := ut.indir var op decOp k := typ.Kind() if int(k) < len(decOpTable) { @@ -856,20 +780,21 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg case reflect.Array: name = "element of " + name elemId := dec.wireType[wireId].ArrayT.Elem - elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress) + elemOp := dec.decOpFor(elemId, t.Elem(), name, inProgress) ovfl := overflow(name) - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - state.dec.decodeArray(t, state, p, *elemOp, t.Elem().Size(), t.Len(), i.indir, elemIndir, ovfl) + helper := decArrayHelper[t.Elem().Kind()] + op = func(i *decInstr, state *decoderState, value reflect.Value) { + state.dec.decodeArray(t, state, value, *elemOp, t.Len(), ovfl, helper) } case reflect.Map: keyId := dec.wireType[wireId].MapT.Key elemId := dec.wireType[wireId].MapT.Elem - keyOp, keyIndir := dec.decOpFor(keyId, t.Key(), "key of "+name, inProgress) - elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress) + keyOp := dec.decOpFor(keyId, t.Key(), "key of "+name, inProgress) + elemOp := dec.decOpFor(elemId, t.Elem(), "element of "+name, inProgress) ovfl := overflow(name) - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - state.dec.decodeMap(t, state, p, *keyOp, *elemOp, i.indir, keyIndir, elemIndir, ovfl) + op = func(i *decInstr, state *decoderState, value reflect.Value) { + state.dec.decodeMap(t, state, value, *keyOp, *elemOp, ovfl) } case reflect.Slice: @@ -884,32 +809,34 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg } else { elemId = dec.wireType[wireId].SliceT.Elem } - elemOp, elemIndir := dec.decOpFor(elemId, t.Elem(), name, inProgress) + elemOp := dec.decOpFor(elemId, t.Elem(), name, inProgress) ovfl := overflow(name) - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - state.dec.decodeSlice(t, state, uintptr(p), *elemOp, t.Elem().Size(), i.indir, elemIndir, ovfl) + helper := decSliceHelper[t.Elem().Kind()] + op = func(i *decInstr, state *decoderState, value reflect.Value) { + state.dec.decodeSlice(state, value, *elemOp, ovfl, helper) } case reflect.Struct: // Generate a closure that calls out to the engine for the nested type. - enginePtr, err := dec.getDecEnginePtr(wireId, userType(typ)) + ut := userType(typ) + enginePtr, err := dec.getDecEnginePtr(wireId, ut) if err != nil { error_(err) } - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + op = func(i *decInstr, state *decoderState, value reflect.Value) { // indirect through enginePtr to delay evaluation for recursive structs. - dec.decodeStruct(*enginePtr, userType(typ), p, i.indir) + dec.decodeStruct(*enginePtr, ut, value) } case reflect.Interface: - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - state.dec.decodeInterface(t, state, p, i.indir) + op = func(i *decInstr, state *decoderState, value reflect.Value) { + state.dec.decodeInterface(t, state, value) } } } if op == nil { errorf("decode can't handle type %s", rt) } - return &op, indir + return &op } // decIgnoreOpFor returns the decoding op for a field that has no destination. @@ -919,7 +846,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp { if wireId == tInterface { // Special case because it's a method: the ignored item might // define types and we need to record their state in the decoder. - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + op = func(i *decInstr, state *decoderState, value reflect.Value) { state.dec.ignoreInterface(state) } return op @@ -932,7 +859,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp { case wire.ArrayT != nil: elemId := wire.ArrayT.Elem elemOp := dec.decIgnoreOpFor(elemId) - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + op = func(i *decInstr, state *decoderState, value reflect.Value) { state.dec.ignoreArray(state, elemOp, wire.ArrayT.Len) } @@ -941,14 +868,14 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp { elemId := dec.wireType[wireId].MapT.Elem keyOp := dec.decIgnoreOpFor(keyId) elemOp := dec.decIgnoreOpFor(elemId) - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + op = func(i *decInstr, state *decoderState, value reflect.Value) { state.dec.ignoreMap(state, keyOp, elemOp) } case wire.SliceT != nil: elemId := wire.SliceT.Elem elemOp := dec.decIgnoreOpFor(elemId) - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + op = func(i *decInstr, state *decoderState, value reflect.Value) { state.dec.ignoreSlice(state, elemOp) } @@ -958,13 +885,13 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp { if err != nil { error_(err) } - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + op = func(i *decInstr, state *decoderState, value reflect.Value) { // indirect through enginePtr to delay evaluation for recursive structs state.dec.ignoreStruct(*enginePtr) } case wire.GobEncoderT != nil, wire.BinaryMarshalerT != nil, wire.TextMarshalerT != nil: - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { + op = func(i *decInstr, state *decoderState, value reflect.Value) { state.dec.ignoreGobDecoder(state) } } @@ -977,7 +904,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) decOp { // gobDecodeOpFor returns the op for a type that is known to implement // GobDecoder. -func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) { +func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) *decOp { rcvrType := ut.user if ut.decIndir == -1 { rcvrType = reflect.PtrTo(rcvrType) @@ -987,25 +914,14 @@ func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) { } } var op decOp - op = func(i *decInstr, state *decoderState, p unsafe.Pointer) { - // Caller has gotten us to within one indirection of our value. - if i.indir > 0 { - if *(*unsafe.Pointer)(p) == nil { - *(*unsafe.Pointer)(p) = unsafe.Pointer(reflect.New(ut.base).Pointer()) - } + op = func(i *decInstr, state *decoderState, value reflect.Value) { + // We now have the base type. We need its address if the receiver is a pointer. + if value.Kind() != reflect.Ptr && rcvrType.Kind() == reflect.Ptr { + value = value.Addr() } - // Now p is a pointer to the base type. Do we need to climb out to - // get to the receiver type? - var v reflect.Value - if ut.decIndir == -1 { - v = reflect.NewAt(rcvrType, unsafe.Pointer(&p)).Elem() - } else { - v = reflect.NewAt(rcvrType, p).Elem() - } - state.dec.decodeGobDecoder(ut, state, v) + state.dec.decodeGobDecoder(ut, state, value) } - return &op, int(ut.indir) - + return &op } // compatibleType asks: Are these two gob Types compatible? @@ -1106,9 +1022,9 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de } return nil, errors.New("gob: decoding into local type " + name + ", received remote type " + remoteType) } - op, indir := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp)) + op := dec.decOpFor(remoteId, rt, name, make(map[reflect.Type]*decOp)) ovfl := errors.New(`value for "` + name + `" out of range`) - engine.instr[singletonField] = decInstr{*op, singletonField, indir, 0, ovfl} + engine.instr[singletonField] = decInstr{*op, singletonField, nil, ovfl} engine.numInstr = 1 return } @@ -1119,7 +1035,7 @@ func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err engine.instr = make([]decInstr, 1) // one item op := dec.decIgnoreOpFor(remoteId) ovfl := overflow(dec.typeString(remoteId)) - engine.instr[0] = decInstr{op, 0, 0, 0, ovfl} + engine.instr[0] = decInstr{op, 0, nil, ovfl} engine.numInstr = 1 return } @@ -1162,14 +1078,14 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn // TODO(r): anonymous names if !present || !isExported(wireField.Name) { op := dec.decIgnoreOpFor(wireField.Id) - engine.instr[fieldnum] = decInstr{op, fieldnum, 0, 0, ovfl} + engine.instr[fieldnum] = decInstr{op, fieldnum, nil, ovfl} continue } if !dec.compatibleType(localField.Type, wireField.Id, make(map[reflect.Type]typeId)) { errorf("wrong type (%s) for received field %s.%s", localField.Type, wireStruct.Name, wireField.Name) } - op, indir := dec.decOpFor(wireField.Id, localField.Type, localField.Name, seen) - engine.instr[fieldnum] = decInstr{*op, fieldnum, indir, uintptr(localField.Offset), ovfl} + op := dec.decOpFor(wireField.Id, localField.Type, localField.Name, seen) + engine.instr[fieldnum] = decInstr{*op, fieldnum, localField.Index, ovfl} engine.numInstr++ } return @@ -1220,31 +1136,33 @@ func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, er return } -// decodeValue decodes the data stream representing a value and stores it in val. -func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) { +// decodeValue decodes the data stream representing a value and stores it in value. +func (dec *Decoder) decodeValue(wireId typeId, value reflect.Value) { defer catchError(&dec.err) // If the value is nil, it means we should just ignore this item. - if !val.IsValid() { + if !value.IsValid() { dec.decodeIgnoredValue(wireId) return } // Dereference down to the underlying type. - ut := userType(val.Type()) + ut := userType(value.Type()) base := ut.base var enginePtr **decEngine enginePtr, dec.err = dec.getDecEnginePtr(wireId, ut) if dec.err != nil { return } + value = decAlloc(value) engine := *enginePtr if st := base; st.Kind() == reflect.Struct && ut.externalDec == 0 { - if engine.numInstr == 0 && st.NumField() > 0 && len(dec.wireType[wireId].StructT.Field) > 0 { + if engine.numInstr == 0 && st.NumField() > 0 && + dec.wireType[wireId] != nil && len(dec.wireType[wireId].StructT.Field) > 0 { name := base.Name() errorf("type mismatch: no fields matched compiling decoder for %s", name) } - dec.decodeStruct(engine, ut, unsafeAddr(val), ut.indir) + dec.decodeStruct(engine, ut, value) } else { - dec.decodeSingle(engine, ut, unsafeAddr(val)) + dec.decodeSingle(engine, ut, value) } } @@ -1290,21 +1208,6 @@ func init() { decOpTable[reflect.Uintptr] = uop } -// Gob assumes it can call UnsafeAddr on any Value -// in order to get a pointer it can copy data from. -// Values that have just been created and do not point -// into existing structs or slices cannot be addressed, -// so simulate it by returning a pointer to a copy. -// Each call allocates once. -func unsafeAddr(v reflect.Value) unsafe.Pointer { - if v.CanAddr() { - return unsafe.Pointer(v.UnsafeAddr()) - } - x := reflect.New(v.Type()).Elem() - x.Set(v) - return unsafe.Pointer(x.UnsafeAddr()) -} - // Gob depends on being able to take the address // of zeroed Values it creates, so use this wrapper instead // of the standard reflect.Zero. diff --git a/libgo/go/encoding/gob/decoder.go b/libgo/go/encoding/gob/decoder.go index 04f706ca54..c453e9ba39 100644 --- a/libgo/go/encoding/gob/decoder.go +++ b/libgo/go/encoding/gob/decoder.go @@ -6,25 +6,28 @@ package gob import ( "bufio" - "bytes" "errors" "io" "reflect" "sync" ) +// tooBig provides a sanity check for sizes; used in several places. +// Upper limit of 1GB, allowing room to grow a little without overflow. +// TODO: make this adjustable? +const tooBig = 1 << 30 + // A Decoder manages the receipt of type and data information read from the // remote side of a connection. type Decoder struct { mutex sync.Mutex // each item must be received atomically r io.Reader // source of the data - buf bytes.Buffer // buffer for more efficient i/o from r + buf decBuffer // buffer for more efficient i/o from r wireType map[typeId]*wireType // map from remote ID to local description decoderCache map[reflect.Type]map[typeId]**decEngine // cache of compiled engines ignorerCache map[typeId]**decEngine // ditto for ignored objects freeList *decoderState // list of free decoderStates; avoids reallocation countBuf []byte // used for decoding integers while parsing messages - tmp []byte // temporary storage for i/o; saves reallocating err error } @@ -75,9 +78,7 @@ func (dec *Decoder) recvMessage() bool { dec.err = err return false } - // Upper limit of 1GB, allowing room to grow a little without overflow. - // TODO: We might want more control over this limit. - if nbytes >= 1<<30 { + if nbytes >= tooBig { dec.err = errBadCount return false } @@ -87,37 +88,17 @@ func (dec *Decoder) recvMessage() bool { // readMessage reads the next nbytes bytes from the input. func (dec *Decoder) readMessage(nbytes int) { - // Allocate the dec.tmp buffer, up to 10KB. - const maxBuf = 10 * 1024 - nTmp := nbytes - if nTmp > maxBuf { - nTmp = maxBuf - } - if cap(dec.tmp) < nTmp { - nAlloc := nTmp + 100 // A little extra for growth. - if nAlloc > maxBuf { - nAlloc = maxBuf - } - dec.tmp = make([]byte, nAlloc) + if dec.buf.Len() != 0 { + // The buffer should always be empty now. + panic("non-empty decoder buffer") } - dec.tmp = dec.tmp[:nTmp] - // Read the data - dec.buf.Grow(nbytes) - for nbytes > 0 { - if nbytes < nTmp { - dec.tmp = dec.tmp[:nbytes] - } - var nRead int - nRead, dec.err = io.ReadFull(dec.r, dec.tmp) - if dec.err != nil { - if dec.err == io.EOF { - dec.err = io.ErrUnexpectedEOF - } - return + dec.buf.Size(nbytes) + _, dec.err = io.ReadFull(dec.r, dec.buf.Bytes()) + if dec.err != nil { + if dec.err == io.EOF { + dec.err = io.ErrUnexpectedEOF } - dec.buf.Write(dec.tmp) - nbytes -= nRead } } @@ -183,11 +164,13 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId { return -1 } -// Decode reads the next value from the connection and stores +// Decode reads the next value from the input stream and stores // it in the data represented by the empty interface value. // If e is nil, the value will be discarded. Otherwise, // the value underlying e must be a pointer to the // correct type for the next data item received. +// If the input is at EOF, Decode returns io.EOF and +// does not modify e. func (dec *Decoder) Decode(e interface{}) error { if e == nil { return dec.DecodeValue(reflect.Value{}) @@ -202,10 +185,12 @@ func (dec *Decoder) Decode(e interface{}) error { return dec.DecodeValue(value) } -// DecodeValue reads the next value from the connection. +// DecodeValue reads the next value from the input stream. // If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value. // Otherwise, it stores the value into v. In that case, v must represent // a non-nil pointer to data or be an assignable reflect.Value (v.CanSet()) +// If the input is at EOF, DecodeValue returns io.EOF and +// does not modify v. func (dec *Decoder) DecodeValue(v reflect.Value) error { if v.IsValid() { if v.Kind() == reflect.Ptr && !v.IsNil() { diff --git a/libgo/go/encoding/gob/enc_helpers.go b/libgo/go/encoding/gob/enc_helpers.go new file mode 100644 index 0000000000..804e539d84 --- /dev/null +++ b/libgo/go/encoding/gob/enc_helpers.go @@ -0,0 +1,414 @@ +// Created by encgen --output enc_helpers.go; DO NOT EDIT + +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gob + +import ( + "reflect" +) + +var encArrayHelper = map[reflect.Kind]encHelper{ + reflect.Bool: encBoolArray, + reflect.Complex64: encComplex64Array, + reflect.Complex128: encComplex128Array, + reflect.Float32: encFloat32Array, + reflect.Float64: encFloat64Array, + reflect.Int: encIntArray, + reflect.Int16: encInt16Array, + reflect.Int32: encInt32Array, + reflect.Int64: encInt64Array, + reflect.Int8: encInt8Array, + reflect.String: encStringArray, + reflect.Uint: encUintArray, + reflect.Uint16: encUint16Array, + reflect.Uint32: encUint32Array, + reflect.Uint64: encUint64Array, + reflect.Uintptr: encUintptrArray, +} + +var encSliceHelper = map[reflect.Kind]encHelper{ + reflect.Bool: encBoolSlice, + reflect.Complex64: encComplex64Slice, + reflect.Complex128: encComplex128Slice, + reflect.Float32: encFloat32Slice, + reflect.Float64: encFloat64Slice, + reflect.Int: encIntSlice, + reflect.Int16: encInt16Slice, + reflect.Int32: encInt32Slice, + reflect.Int64: encInt64Slice, + reflect.Int8: encInt8Slice, + reflect.String: encStringSlice, + reflect.Uint: encUintSlice, + reflect.Uint16: encUint16Slice, + reflect.Uint32: encUint32Slice, + reflect.Uint64: encUint64Slice, + reflect.Uintptr: encUintptrSlice, +} + +func encBoolArray(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encBoolSlice(state, v.Slice(0, v.Len())) +} + +func encBoolSlice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]bool) + if !ok { + // It is kind bool but not type bool. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != false || state.sendZero { + if x { + state.encodeUint(1) + } else { + state.encodeUint(0) + } + } + } + return true +} + +func encComplex64Array(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encComplex64Slice(state, v.Slice(0, v.Len())) +} + +func encComplex64Slice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]complex64) + if !ok { + // It is kind complex64 but not type complex64. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0+0i || state.sendZero { + rpart := floatBits(float64(real(x))) + ipart := floatBits(float64(imag(x))) + state.encodeUint(rpart) + state.encodeUint(ipart) + } + } + return true +} + +func encComplex128Array(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encComplex128Slice(state, v.Slice(0, v.Len())) +} + +func encComplex128Slice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]complex128) + if !ok { + // It is kind complex128 but not type complex128. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0+0i || state.sendZero { + rpart := floatBits(real(x)) + ipart := floatBits(imag(x)) + state.encodeUint(rpart) + state.encodeUint(ipart) + } + } + return true +} + +func encFloat32Array(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encFloat32Slice(state, v.Slice(0, v.Len())) +} + +func encFloat32Slice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]float32) + if !ok { + // It is kind float32 but not type float32. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0 || state.sendZero { + bits := floatBits(float64(x)) + state.encodeUint(bits) + } + } + return true +} + +func encFloat64Array(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encFloat64Slice(state, v.Slice(0, v.Len())) +} + +func encFloat64Slice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]float64) + if !ok { + // It is kind float64 but not type float64. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0 || state.sendZero { + bits := floatBits(x) + state.encodeUint(bits) + } + } + return true +} + +func encIntArray(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encIntSlice(state, v.Slice(0, v.Len())) +} + +func encIntSlice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]int) + if !ok { + // It is kind int but not type int. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0 || state.sendZero { + state.encodeInt(int64(x)) + } + } + return true +} + +func encInt16Array(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encInt16Slice(state, v.Slice(0, v.Len())) +} + +func encInt16Slice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]int16) + if !ok { + // It is kind int16 but not type int16. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0 || state.sendZero { + state.encodeInt(int64(x)) + } + } + return true +} + +func encInt32Array(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encInt32Slice(state, v.Slice(0, v.Len())) +} + +func encInt32Slice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]int32) + if !ok { + // It is kind int32 but not type int32. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0 || state.sendZero { + state.encodeInt(int64(x)) + } + } + return true +} + +func encInt64Array(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encInt64Slice(state, v.Slice(0, v.Len())) +} + +func encInt64Slice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]int64) + if !ok { + // It is kind int64 but not type int64. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0 || state.sendZero { + state.encodeInt(x) + } + } + return true +} + +func encInt8Array(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encInt8Slice(state, v.Slice(0, v.Len())) +} + +func encInt8Slice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]int8) + if !ok { + // It is kind int8 but not type int8. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0 || state.sendZero { + state.encodeInt(int64(x)) + } + } + return true +} + +func encStringArray(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encStringSlice(state, v.Slice(0, v.Len())) +} + +func encStringSlice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]string) + if !ok { + // It is kind string but not type string. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != "" || state.sendZero { + state.encodeUint(uint64(len(x))) + state.b.WriteString(x) + } + } + return true +} + +func encUintArray(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encUintSlice(state, v.Slice(0, v.Len())) +} + +func encUintSlice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]uint) + if !ok { + // It is kind uint but not type uint. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0 || state.sendZero { + state.encodeUint(uint64(x)) + } + } + return true +} + +func encUint16Array(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encUint16Slice(state, v.Slice(0, v.Len())) +} + +func encUint16Slice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]uint16) + if !ok { + // It is kind uint16 but not type uint16. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0 || state.sendZero { + state.encodeUint(uint64(x)) + } + } + return true +} + +func encUint32Array(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encUint32Slice(state, v.Slice(0, v.Len())) +} + +func encUint32Slice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]uint32) + if !ok { + // It is kind uint32 but not type uint32. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0 || state.sendZero { + state.encodeUint(uint64(x)) + } + } + return true +} + +func encUint64Array(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encUint64Slice(state, v.Slice(0, v.Len())) +} + +func encUint64Slice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]uint64) + if !ok { + // It is kind uint64 but not type uint64. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0 || state.sendZero { + state.encodeUint(x) + } + } + return true +} + +func encUintptrArray(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return encUintptrSlice(state, v.Slice(0, v.Len())) +} + +func encUintptrSlice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]uintptr) + if !ok { + // It is kind uintptr but not type uintptr. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != 0 || state.sendZero { + state.encodeUint(uint64(x)) + } + } + return true +} diff --git a/libgo/go/encoding/gob/encgen.go b/libgo/go/encoding/gob/encgen.go new file mode 100644 index 0000000000..efdd928292 --- /dev/null +++ b/libgo/go/encoding/gob/encgen.go @@ -0,0 +1,218 @@ +// 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. + +// +build ignore + +// encgen writes the helper functions for encoding. Intended to be +// used with go generate; see the invocation in encode.go. + +// TODO: We could do more by being unsafe. Add a -unsafe flag? + +package main + +import ( + "bytes" + "flag" + "fmt" + "go/format" + "log" + "os" +) + +var output = flag.String("output", "enc_helpers.go", "file name to write") + +type Type struct { + lower string + upper string + zero string + encoder string +} + +var types = []Type{ + { + "bool", + "Bool", + "false", + `if x { + state.encodeUint(1) + } else { + state.encodeUint(0) + }`, + }, + { + "complex64", + "Complex64", + "0+0i", + `rpart := floatBits(float64(real(x))) + ipart := floatBits(float64(imag(x))) + state.encodeUint(rpart) + state.encodeUint(ipart)`, + }, + { + "complex128", + "Complex128", + "0+0i", + `rpart := floatBits(real(x)) + ipart := floatBits(imag(x)) + state.encodeUint(rpart) + state.encodeUint(ipart)`, + }, + { + "float32", + "Float32", + "0", + `bits := floatBits(float64(x)) + state.encodeUint(bits)`, + }, + { + "float64", + "Float64", + "0", + `bits := floatBits(x) + state.encodeUint(bits)`, + }, + { + "int", + "Int", + "0", + `state.encodeInt(int64(x))`, + }, + { + "int16", + "Int16", + "0", + `state.encodeInt(int64(x))`, + }, + { + "int32", + "Int32", + "0", + `state.encodeInt(int64(x))`, + }, + { + "int64", + "Int64", + "0", + `state.encodeInt(x)`, + }, + { + "int8", + "Int8", + "0", + `state.encodeInt(int64(x))`, + }, + { + "string", + "String", + `""`, + `state.encodeUint(uint64(len(x))) + state.b.WriteString(x)`, + }, + { + "uint", + "Uint", + "0", + `state.encodeUint(uint64(x))`, + }, + { + "uint16", + "Uint16", + "0", + `state.encodeUint(uint64(x))`, + }, + { + "uint32", + "Uint32", + "0", + `state.encodeUint(uint64(x))`, + }, + { + "uint64", + "Uint64", + "0", + `state.encodeUint(x)`, + }, + { + "uintptr", + "Uintptr", + "0", + `state.encodeUint(uint64(x))`, + }, + // uint8 Handled separately. +} + +func main() { + log.SetFlags(0) + log.SetPrefix("encgen: ") + flag.Parse() + if flag.NArg() != 0 { + log.Fatal("usage: encgen [--output filename]") + } + var b bytes.Buffer + fmt.Fprintf(&b, "// Created by encgen --output %s; DO NOT EDIT\n", *output) + fmt.Fprint(&b, header) + printMaps(&b, "Array") + fmt.Fprint(&b, "\n") + printMaps(&b, "Slice") + for _, t := range types { + fmt.Fprintf(&b, arrayHelper, t.lower, t.upper) + fmt.Fprintf(&b, sliceHelper, t.lower, t.upper, t.zero, t.encoder) + } + source, err := format.Source(b.Bytes()) + if err != nil { + log.Fatal("source format error:", err) + } + fd, err := os.Create(*output) + _, err = fd.Write(source) + if err != nil { + log.Fatal(err) + } +} + +func printMaps(b *bytes.Buffer, upperClass string) { + fmt.Fprintf(b, "var enc%sHelper = map[reflect.Kind]encHelper{\n", upperClass) + for _, t := range types { + fmt.Fprintf(b, "reflect.%s: enc%s%s,\n", t.upper, t.upper, upperClass) + } + fmt.Fprintf(b, "}\n") +} + +const header = ` +// 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 gob + +import ( + "reflect" +) + +` + +const arrayHelper = ` +func enc%[2]sArray(state *encoderState, v reflect.Value) bool { + // Can only slice if it is addressable. + if !v.CanAddr() { + return false + } + return enc%[2]sSlice(state, v.Slice(0, v.Len())) +} +` + +const sliceHelper = ` +func enc%[2]sSlice(state *encoderState, v reflect.Value) bool { + slice, ok := v.Interface().([]%[1]s) + if !ok { + // It is kind %[1]s but not type %[1]s. TODO: We can handle this unsafely. + return false + } + for _, x := range slice { + if x != %[3]s || state.sendZero { + %[4]s + } + } + return true +} +` diff --git a/libgo/go/encoding/gob/encode.go b/libgo/go/encoding/gob/encode.go index d158b6442a..f66279f141 100644 --- a/libgo/go/encoding/gob/encode.go +++ b/libgo/go/encoding/gob/encode.go @@ -2,17 +2,19 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:generate go run encgen.go -output enc_helpers.go + package gob import ( - "bytes" "encoding" "math" "reflect" - "unsafe" ) -const uint64Size = int(unsafe.Sizeof(uint64(0))) +const uint64Size = 8 + +type encHelper func(state *encoderState, v reflect.Value) bool // encoderState is the global execution state of an instance of the encoder. // Field numbers are delta encoded and always increase. The field @@ -20,14 +22,46 @@ const uint64Size = int(unsafe.Sizeof(uint64(0))) // 0 terminates the structure. type encoderState struct { enc *Encoder - b *bytes.Buffer + b *encBuffer sendZero bool // encoding an array element or map key/value pair; send zero values fieldnum int // the last field number written. buf [1 + uint64Size]byte // buffer used by the encoder; here to avoid allocation. next *encoderState // for free list } -func (enc *Encoder) newEncoderState(b *bytes.Buffer) *encoderState { +// encBuffer is an extremely simple, fast implementation of a write-only byte buffer. +// It never returns a non-nil error, but Write returns an error value so it matches io.Writer. +type encBuffer struct { + data []byte + scratch [64]byte +} + +func (e *encBuffer) WriteByte(c byte) { + e.data = append(e.data, c) +} + +func (e *encBuffer) Write(p []byte) (int, error) { + e.data = append(e.data, p...) + return len(p), nil +} + +func (e *encBuffer) WriteString(s string) { + e.data = append(e.data, s...) +} + +func (e *encBuffer) Len() int { + return len(e.data) +} + +func (e *encBuffer) Bytes() []byte { + return e.data +} + +func (e *encBuffer) Reset() { + e.data = e.data[0:0] +} + +func (enc *Encoder) newEncoderState(b *encBuffer) *encoderState { e := enc.freeList if e == nil { e = new(encoderState) @@ -38,6 +72,9 @@ func (enc *Encoder) newEncoderState(b *bytes.Buffer) *encoderState { e.sendZero = false e.fieldnum = 0 e.b = b + if len(b.data) == 0 { + b.data = b.scratch[0:0] + } return e } @@ -54,10 +91,7 @@ func (enc *Encoder) freeEncoderState(e *encoderState) { // encodeUint writes an encoded unsigned integer to state.b. func (state *encoderState) encodeUint(x uint64) { if x <= 0x7F { - err := state.b.WriteByte(uint8(x)) - if err != nil { - error_(err) - } + state.b.WriteByte(uint8(x)) return } i := uint64Size @@ -67,10 +101,7 @@ func (state *encoderState) encodeUint(x uint64) { i-- } state.buf[i] = uint8(i - uint64Size) // = loop count, negated - _, err := state.b.Write(state.buf[i : uint64Size+1]) - if err != nil { - error_(err) - } + state.b.Write(state.buf[i : uint64Size+1]) } // encodeInt writes an encoded signed integer to state.w. @@ -87,14 +118,14 @@ func (state *encoderState) encodeInt(i int64) { } // encOp is the signature of an encoding operator for a given type. -type encOp func(i *encInstr, state *encoderState, p unsafe.Pointer) +type encOp func(i *encInstr, state *encoderState, v reflect.Value) // The 'instructions' of the encoding machine type encInstr struct { - op encOp - field int // field number - indir int // how many pointer indirections to reach the value in the struct - offset uintptr // offset in the structure of the field to encode + op encOp + field int // field number in input + index []int // struct index + indir int // how many pointer indirections to reach the value in the struct } // update emits a field number and updates the state to record its value for delta encoding. @@ -115,20 +146,20 @@ func (state *encoderState) update(instr *encInstr) { // encoded integer, followed by the field data in its appropriate // format. -// encIndirect dereferences p indir times and returns the result. -func encIndirect(p unsafe.Pointer, indir int) unsafe.Pointer { +// encIndirect dereferences pv indir times and returns the result. +func encIndirect(pv reflect.Value, indir int) reflect.Value { for ; indir > 0; indir-- { - p = *(*unsafe.Pointer)(p) - if p == nil { - return unsafe.Pointer(nil) + if pv.IsNil() { + break } + pv = pv.Elem() } - return p + return pv } -// encBool encodes the bool with address p as an unsigned 0 or 1. -func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) { - b := *(*bool)(p) +// encBool encodes the bool referenced by v as an unsigned 0 or 1. +func encBool(i *encInstr, state *encoderState, v reflect.Value) { + b := v.Bool() if b || state.sendZero { state.update(i) if b { @@ -139,102 +170,21 @@ func encBool(i *encInstr, state *encoderState, p unsafe.Pointer) { } } -// encInt encodes the int with address p. -func encInt(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := int64(*(*int)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeInt(v) - } -} - -// encUint encodes the uint with address p. -func encUint(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := uint64(*(*uint)(p)) - if v != 0 || state.sendZero { +// encInt encodes the signed integer (int int8 int16 int32 int64) referenced by v. +func encInt(i *encInstr, state *encoderState, v reflect.Value) { + value := v.Int() + if value != 0 || state.sendZero { state.update(i) - state.encodeUint(v) + state.encodeInt(value) } } -// encInt8 encodes the int8 with address p. -func encInt8(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := int64(*(*int8)(p)) - if v != 0 || state.sendZero { +// encUint encodes the unsigned integer (uint uint8 uint16 uint32 uint64 uintptr) referenced by v. +func encUint(i *encInstr, state *encoderState, v reflect.Value) { + value := v.Uint() + if value != 0 || state.sendZero { state.update(i) - state.encodeInt(v) - } -} - -// encUint8 encodes the uint8 with address p. -func encUint8(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := uint64(*(*uint8)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeUint(v) - } -} - -// encInt16 encodes the int16 with address p. -func encInt16(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := int64(*(*int16)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeInt(v) - } -} - -// encUint16 encodes the uint16 with address p. -func encUint16(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := uint64(*(*uint16)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeUint(v) - } -} - -// encInt32 encodes the int32 with address p. -func encInt32(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := int64(*(*int32)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeInt(v) - } -} - -// encUint encodes the uint32 with address p. -func encUint32(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := uint64(*(*uint32)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeUint(v) - } -} - -// encInt64 encodes the int64 with address p. -func encInt64(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := *(*int64)(p) - if v != 0 || state.sendZero { - state.update(i) - state.encodeInt(v) - } -} - -// encInt64 encodes the uint64 with address p. -func encUint64(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := *(*uint64)(p) - if v != 0 || state.sendZero { - state.update(i) - state.encodeUint(v) - } -} - -// encUintptr encodes the uintptr with address p. -func encUintptr(i *encInstr, state *encoderState, p unsafe.Pointer) { - v := uint64(*(*uintptr)(p)) - if v != 0 || state.sendZero { - state.update(i) - state.encodeUint(v) + state.encodeUint(value) } } @@ -255,42 +205,20 @@ func floatBits(f float64) uint64 { return v } -// encFloat32 encodes the float32 with address p. -func encFloat32(i *encInstr, state *encoderState, p unsafe.Pointer) { - f := *(*float32)(p) +// encFloat encodes the floating point value (float32 float64) referenced by v. +func encFloat(i *encInstr, state *encoderState, v reflect.Value) { + f := v.Float() if f != 0 || state.sendZero { - v := floatBits(float64(f)) + bits := floatBits(f) state.update(i) - state.encodeUint(v) + state.encodeUint(bits) } } -// encFloat64 encodes the float64 with address p. -func encFloat64(i *encInstr, state *encoderState, p unsafe.Pointer) { - f := *(*float64)(p) - if f != 0 || state.sendZero { - state.update(i) - v := floatBits(f) - state.encodeUint(v) - } -} - -// encComplex64 encodes the complex64 with address p. +// encComplex encodes the complex value (complex64 complex128) referenced by v. // Complex numbers are just a pair of floating-point numbers, real part first. -func encComplex64(i *encInstr, state *encoderState, p unsafe.Pointer) { - c := *(*complex64)(p) - if c != 0+0i || state.sendZero { - rpart := floatBits(float64(real(c))) - ipart := floatBits(float64(imag(c))) - state.update(i) - state.encodeUint(rpart) - state.encodeUint(ipart) - } -} - -// encComplex128 encodes the complex128 with address p. -func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) { - c := *(*complex128)(p) +func encComplex(i *encInstr, state *encoderState, v reflect.Value) { + c := v.Complex() if c != 0+0i || state.sendZero { rpart := floatBits(real(c)) ipart := floatBits(imag(c)) @@ -300,10 +228,10 @@ func encComplex128(i *encInstr, state *encoderState, p unsafe.Pointer) { } } -// encUint8Array encodes the byte slice whose header has address p. +// encUint8Array encodes the byte array referenced by v. // Byte arrays are encoded as an unsigned count followed by the raw bytes. -func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) { - b := *(*[]byte)(p) +func encUint8Array(i *encInstr, state *encoderState, v reflect.Value) { + b := v.Bytes() if len(b) > 0 || state.sendZero { state.update(i) state.encodeUint(uint64(len(b))) @@ -311,10 +239,10 @@ func encUint8Array(i *encInstr, state *encoderState, p unsafe.Pointer) { } } -// encString encodes the string whose header has address p. +// encString encodes the string referenced by v. // Strings are encoded as an unsigned count followed by the raw bytes. -func encString(i *encInstr, state *encoderState, p unsafe.Pointer) { - s := *(*string)(p) +func encString(i *encInstr, state *encoderState, v reflect.Value) { + s := v.String() if len(s) > 0 || state.sendZero { state.update(i) state.encodeUint(uint64(len(s))) @@ -324,7 +252,7 @@ func encString(i *encInstr, state *encoderState, p unsafe.Pointer) { // encStructTerminator encodes the end of an encoded struct // as delta field number of 0. -func encStructTerminator(i *encInstr, state *encoderState, p unsafe.Pointer) { +func encStructTerminator(i *encInstr, state *encoderState, v reflect.Value) { state.encodeUint(0) } @@ -338,60 +266,83 @@ type encEngine struct { const singletonField = 0 +// valid reports whether the value is valid and a non-nil pointer. +// (Slices, maps, and chans take care of themselves.) +func valid(v reflect.Value) bool { + switch v.Kind() { + case reflect.Invalid: + return false + case reflect.Ptr: + return !v.IsNil() + } + return true +} + // encodeSingle encodes a single top-level non-struct value. -func (enc *Encoder) encodeSingle(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) { +func (enc *Encoder) encodeSingle(b *encBuffer, engine *encEngine, value reflect.Value) { state := enc.newEncoderState(b) + defer enc.freeEncoderState(state) state.fieldnum = singletonField // There is no surrounding struct to frame the transmission, so we must // generate data even if the item is zero. To do this, set sendZero. state.sendZero = true instr := &engine.instr[singletonField] - p := basep // offset will be zero if instr.indir > 0 { - if p = encIndirect(p, instr.indir); p == nil { - return - } + value = encIndirect(value, instr.indir) + } + if valid(value) { + instr.op(instr, state, value) } - instr.op(instr, state, p) - enc.freeEncoderState(state) } // encodeStruct encodes a single struct value. -func (enc *Encoder) encodeStruct(b *bytes.Buffer, engine *encEngine, basep unsafe.Pointer) { +func (enc *Encoder) encodeStruct(b *encBuffer, engine *encEngine, value reflect.Value) { + if !valid(value) { + return + } state := enc.newEncoderState(b) + defer enc.freeEncoderState(state) state.fieldnum = -1 for i := 0; i < len(engine.instr); i++ { instr := &engine.instr[i] - p := unsafe.Pointer(uintptr(basep) + instr.offset) + if i >= value.NumField() { + // encStructTerminator + instr.op(instr, state, reflect.Value{}) + break + } + field := value.FieldByIndex(instr.index) if instr.indir > 0 { - if p = encIndirect(p, instr.indir); p == nil { + field = encIndirect(field, instr.indir) + // TODO: Is field guaranteed valid? If so we could avoid this check. + if !valid(field) { continue } } - instr.op(instr, state, p) + instr.op(instr, state, field) } - enc.freeEncoderState(state) } -// encodeArray encodes the array whose 0th element is at p. -func (enc *Encoder) encodeArray(b *bytes.Buffer, p unsafe.Pointer, op encOp, elemWid uintptr, elemIndir int, length int) { +// encodeArray encodes an array. +func (enc *Encoder) encodeArray(b *encBuffer, value reflect.Value, op encOp, elemIndir int, length int, helper encHelper) { state := enc.newEncoderState(b) + defer enc.freeEncoderState(state) state.fieldnum = -1 state.sendZero = true state.encodeUint(uint64(length)) + if helper != nil && helper(state, value) { + return + } for i := 0; i < length; i++ { - elemp := p + elem := value.Index(i) if elemIndir > 0 { - up := encIndirect(elemp, elemIndir) - if up == nil { + elem = encIndirect(elem, elemIndir) + // TODO: Is elem guaranteed valid? If so we could avoid this check. + if !valid(elem) { errorf("encodeArray: nil element") } - elemp = up } - op(nil, state, elemp) - p = unsafe.Pointer(uintptr(p) + elemWid) + op(nil, state, elem) } - enc.freeEncoderState(state) } // encodeReflectValue is a helper for maps. It encodes the value v. @@ -402,13 +353,11 @@ func encodeReflectValue(state *encoderState, v reflect.Value, op encOp, indir in if !v.IsValid() { errorf("encodeReflectValue: nil element") } - op(nil, state, unsafeAddr(v)) + op(nil, state, v) } // encodeMap encodes a map as unsigned count followed by key:value pairs. -// Because map internals are not exposed, we must use reflection rather than -// addresses. -func (enc *Encoder) encodeMap(b *bytes.Buffer, mv reflect.Value, keyOp, elemOp encOp, keyIndir, elemIndir int) { +func (enc *Encoder) encodeMap(b *encBuffer, mv reflect.Value, keyOp, elemOp encOp, keyIndir, elemIndir int) { state := enc.newEncoderState(b) state.fieldnum = -1 state.sendZero = true @@ -426,7 +375,7 @@ func (enc *Encoder) encodeMap(b *bytes.Buffer, mv reflect.Value, keyOp, elemOp e // by the type identifier (which might require defining that type right now), followed // by the concrete value. A nil value gets sent as the empty string for the name, // followed by no value. -func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) { +func (enc *Encoder) encodeInterface(b *encBuffer, iv reflect.Value) { // Gobs can encode nil interface values but not typed interface // values holding nil pointers, since nil pointers point to no value. elem := iv.Elem() @@ -450,10 +399,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) { } // Send the name. state.encodeUint(uint64(len(name))) - _, err := state.b.WriteString(name) - if err != nil { - error_(err) - } + state.b.WriteString(name) // Define the type id if necessary. enc.sendTypeDescriptor(enc.writer(), state, ut) // Send the type id. @@ -461,7 +407,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) { // Encode the value into a new buffer. Any nested type definitions // should be written to b, before the encoded value. enc.pushWriter(b) - data := new(bytes.Buffer) + data := new(encBuffer) data.Write(spaceForLength) enc.encode(data, elem, ut) if enc.err != nil { @@ -470,7 +416,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) { enc.popWriter() enc.writeMessage(b, data) if enc.err != nil { - error_(err) + error_(enc.err) } enc.freeEncoderState(state) } @@ -491,7 +437,7 @@ func isZero(val reflect.Value) bool { return !val.Bool() case reflect.Complex64, reflect.Complex128: return val.Complex() == 0 - case reflect.Chan, reflect.Func, reflect.Ptr: + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr: return val.IsNil() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return val.Int() == 0 @@ -512,7 +458,7 @@ func isZero(val reflect.Value) bool { // encGobEncoder encodes a value that implements the GobEncoder interface. // The data is sent as a byte array. -func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, ut *userTypeInfo, v reflect.Value) { +func (enc *Encoder) encodeGobEncoder(b *encBuffer, ut *userTypeInfo, v reflect.Value) { // TODO: should we catch panics from the called method? var data []byte @@ -539,30 +485,30 @@ func (enc *Encoder) encodeGobEncoder(b *bytes.Buffer, ut *userTypeInfo, v reflec var encOpTable = [...]encOp{ reflect.Bool: encBool, reflect.Int: encInt, - reflect.Int8: encInt8, - reflect.Int16: encInt16, - reflect.Int32: encInt32, - reflect.Int64: encInt64, + reflect.Int8: encInt, + reflect.Int16: encInt, + reflect.Int32: encInt, + reflect.Int64: encInt, reflect.Uint: encUint, - reflect.Uint8: encUint8, - reflect.Uint16: encUint16, - reflect.Uint32: encUint32, - reflect.Uint64: encUint64, - reflect.Uintptr: encUintptr, - reflect.Float32: encFloat32, - reflect.Float64: encFloat64, - reflect.Complex64: encComplex64, - reflect.Complex128: encComplex128, + reflect.Uint8: encUint, + reflect.Uint16: encUint, + reflect.Uint32: encUint, + reflect.Uint64: encUint, + reflect.Uintptr: encUint, + reflect.Float32: encFloat, + reflect.Float64: encFloat, + reflect.Complex64: encComplex, + reflect.Complex128: encComplex, reflect.String: encString, } // encOpFor returns (a pointer to) the encoding op for the base type under rt and // the indirection count to reach it. -func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp) (*encOp, int) { +func encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp, building map[*typeInfo]bool) (*encOp, int) { ut := userType(rt) // If the type implements GobEncoder, we handle it without further processing. if ut.externalEnc != 0 { - return enc.gobEncodeOpFor(ut) + return gobEncodeOpFor(ut) } // If this type is already in progress, it's a recursive type (e.g. map[string]*T). // Return the pointer to the op we're already building. @@ -586,31 +532,27 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp break } // Slices have a header; we decode it to find the underlying array. - elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress) - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { - slice := (*reflect.SliceHeader)(p) - if !state.sendZero && slice.Len == 0 { + elemOp, elemIndir := encOpFor(t.Elem(), inProgress, building) + helper := encSliceHelper[t.Elem().Kind()] + op = func(i *encInstr, state *encoderState, slice reflect.Value) { + if !state.sendZero && slice.Len() == 0 { return } state.update(i) - state.enc.encodeArray(state.b, unsafe.Pointer(slice.Data), *elemOp, t.Elem().Size(), elemIndir, int(slice.Len)) + state.enc.encodeArray(state.b, slice, *elemOp, elemIndir, slice.Len(), helper) } case reflect.Array: // True arrays have size in the type. - elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress) - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + elemOp, elemIndir := encOpFor(t.Elem(), inProgress, building) + helper := encArrayHelper[t.Elem().Kind()] + op = func(i *encInstr, state *encoderState, array reflect.Value) { state.update(i) - state.enc.encodeArray(state.b, p, *elemOp, t.Elem().Size(), elemIndir, t.Len()) + state.enc.encodeArray(state.b, array, *elemOp, elemIndir, array.Len(), helper) } case reflect.Map: - keyOp, keyIndir := enc.encOpFor(t.Key(), inProgress) - elemOp, elemIndir := enc.encOpFor(t.Elem(), inProgress) - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { - // Maps cannot be accessed by moving addresses around the way - // that slices etc. can. We must recover a full reflection value for - // the iteration. - v := reflect.NewAt(t, unsafe.Pointer(p)).Elem() - mv := reflect.Indirect(v) + keyOp, keyIndir := encOpFor(t.Key(), inProgress, building) + elemOp, elemIndir := encOpFor(t.Elem(), inProgress, building) + op = func(i *encInstr, state *encoderState, mv reflect.Value) { // We send zero-length (but non-nil) maps because the // receiver might want to use the map. (Maps don't use append.) if !state.sendZero && mv.IsNil() { @@ -621,19 +563,16 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp } case reflect.Struct: // Generate a closure that calls out to the engine for the nested type. - enc.getEncEngine(userType(typ)) + getEncEngine(userType(typ), building) info := mustGetTypeInfo(typ) - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { + op = func(i *encInstr, state *encoderState, sv reflect.Value) { state.update(i) // indirect through info to delay evaluation for recursive structs - state.enc.encodeStruct(state.b, info.encoder, p) + enc := info.encoder.Load().(*encEngine) + state.enc.encodeStruct(state.b, enc, sv) } case reflect.Interface: - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { - // Interfaces transmit the name and contents of the concrete - // value they contain. - v := reflect.NewAt(t, unsafe.Pointer(p)).Elem() - iv := reflect.Indirect(v) + op = func(i *encInstr, state *encoderState, iv reflect.Value) { if !state.sendZero && (!iv.IsValid() || iv.IsNil()) { return } @@ -648,9 +587,8 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp return &op, indir } -// gobEncodeOpFor returns the op for a type that is known to implement -// GobEncoder. -func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { +// gobEncodeOpFor returns the op for a type that is known to implement GobEncoder. +func gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { rt := ut.user if ut.encIndir == -1 { rt = reflect.PtrTo(rt) @@ -660,13 +598,13 @@ func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { } } var op encOp - op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { - var v reflect.Value + op = func(i *encInstr, state *encoderState, v reflect.Value) { if ut.encIndir == -1 { // Need to climb up one level to turn value into pointer. - v = reflect.NewAt(rt, unsafe.Pointer(&p)).Elem() - } else { - v = reflect.NewAt(rt, p).Elem() + if !v.CanAddr() { + errorf("unaddressable value of type %s", rt) + } + v = v.Addr() } if !state.sendZero && isZero(v) { return @@ -678,7 +616,7 @@ func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { } // compileEnc returns the engine to compile the type. -func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine { +func compileEnc(ut *userTypeInfo, building map[*typeInfo]bool) *encEngine { srt := ut.base engine := new(encEngine) seen := make(map[reflect.Type]*encOp) @@ -692,59 +630,57 @@ func (enc *Encoder) compileEnc(ut *userTypeInfo) *encEngine { if !isSent(&f) { continue } - op, indir := enc.encOpFor(f.Type, seen) - engine.instr = append(engine.instr, encInstr{*op, wireFieldNum, indir, uintptr(f.Offset)}) + op, indir := encOpFor(f.Type, seen, building) + engine.instr = append(engine.instr, encInstr{*op, wireFieldNum, f.Index, indir}) wireFieldNum++ } if srt.NumField() > 0 && len(engine.instr) == 0 { errorf("type %s has no exported fields", rt) } - engine.instr = append(engine.instr, encInstr{encStructTerminator, 0, 0, 0}) + engine.instr = append(engine.instr, encInstr{encStructTerminator, 0, nil, 0}) } else { engine.instr = make([]encInstr, 1) - op, indir := enc.encOpFor(rt, seen) - engine.instr[0] = encInstr{*op, singletonField, indir, 0} // offset is zero + op, indir := encOpFor(rt, seen, building) + engine.instr[0] = encInstr{*op, singletonField, nil, indir} } return engine } // getEncEngine returns the engine to compile the type. -// typeLock must be held (or we're in initialization and guaranteed single-threaded). -func (enc *Encoder) getEncEngine(ut *userTypeInfo) *encEngine { - info, err1 := getTypeInfo(ut) - if err1 != nil { - error_(err1) - } - if info.encoder == nil { - // Assign the encEngine now, so recursive types work correctly. But... - info.encoder = new(encEngine) - // ... if we fail to complete building the engine, don't cache the half-built machine. - // Doing this here means we won't cache a type that is itself OK but - // that contains a nested type that won't compile. The result is consistent - // error behavior when Encode is called multiple times on the top-level type. - ok := false - defer func() { - if !ok { - info.encoder = nil - } - }() - info.encoder = enc.compileEnc(ut) - ok = true +func getEncEngine(ut *userTypeInfo, building map[*typeInfo]bool) *encEngine { + info, err := getTypeInfo(ut) + if err != nil { + error_(err) } - return info.encoder + enc, ok := info.encoder.Load().(*encEngine) + if !ok { + enc = buildEncEngine(info, ut, building) + } + return enc } -// lockAndGetEncEngine is a function that locks and compiles. -// This lets us hold the lock only while compiling, not when encoding. -func (enc *Encoder) lockAndGetEncEngine(ut *userTypeInfo) *encEngine { - typeLock.Lock() - defer typeLock.Unlock() - return enc.getEncEngine(ut) +func buildEncEngine(info *typeInfo, ut *userTypeInfo, building map[*typeInfo]bool) *encEngine { + // Check for recursive types. + if building != nil && building[info] { + return nil + } + info.encInit.Lock() + defer info.encInit.Unlock() + enc, ok := info.encoder.Load().(*encEngine) + if !ok { + if building == nil { + building = make(map[*typeInfo]bool) + } + building[info] = true + enc = compileEnc(ut, building) + info.encoder.Store(enc) + } + return enc } -func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInfo) { +func (enc *Encoder) encode(b *encBuffer, value reflect.Value, ut *userTypeInfo) { defer catchError(&enc.err) - engine := enc.lockAndGetEncEngine(ut) + engine := getEncEngine(ut, nil) indir := ut.indir if ut.externalEnc != 0 { indir = int(ut.encIndir) @@ -753,8 +689,8 @@ func (enc *Encoder) encode(b *bytes.Buffer, value reflect.Value, ut *userTypeInf value = reflect.Indirect(value) } if ut.externalEnc == 0 && value.Type().Kind() == reflect.Struct { - enc.encodeStruct(b, engine, unsafeAddr(value)) + enc.encodeStruct(b, engine, value) } else { - enc.encodeSingle(b, engine, unsafeAddr(value)) + enc.encodeSingle(b, engine, value) } } diff --git a/libgo/go/encoding/gob/encoder.go b/libgo/go/encoding/gob/encoder.go index a3301c3bd3..a340e47b5e 100644 --- a/libgo/go/encoding/gob/encoder.go +++ b/libgo/go/encoding/gob/encoder.go @@ -5,7 +5,6 @@ package gob import ( - "bytes" "io" "reflect" "sync" @@ -19,7 +18,7 @@ type Encoder struct { sent map[reflect.Type]typeId // which types we've already sent countState *encoderState // stage for writing counts freeList *encoderState // list of free encoderStates; avoids reallocation - byteBuf bytes.Buffer // buffer for top-level encoderState + byteBuf encBuffer // buffer for top-level encoderState err error } @@ -34,7 +33,7 @@ func NewEncoder(w io.Writer) *Encoder { enc := new(Encoder) enc.w = []io.Writer{w} enc.sent = make(map[reflect.Type]typeId) - enc.countState = enc.newEncoderState(new(bytes.Buffer)) + enc.countState = enc.newEncoderState(new(encBuffer)) return enc } @@ -60,7 +59,7 @@ func (enc *Encoder) setError(err error) { } // writeMessage sends the data item preceded by a unsigned count of its length. -func (enc *Encoder) writeMessage(w io.Writer, b *bytes.Buffer) { +func (enc *Encoder) writeMessage(w io.Writer, b *encBuffer) { // Space has been reserved for the length at the head of the message. // This is a little dirty: we grab the slice from the bytes.Buffer and massage // it by hand. @@ -88,9 +87,7 @@ func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTyp if _, alreadySent := enc.sent[actual]; alreadySent { return false } - typeLock.Lock() info, err := getTypeInfo(ut) - typeLock.Unlock() if err != nil { enc.setError(err) return @@ -191,9 +188,7 @@ func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *use // a singleton basic type (int, []byte etc.) at top level. We don't // need to send the type info but we do need to update enc.sent. if !sent { - typeLock.Lock() info, err := getTypeInfo(ut) - typeLock.Unlock() if err != nil { enc.setError(err) return diff --git a/libgo/go/encoding/gob/encoder_test.go b/libgo/go/encoding/gob/encoder_test.go index 4ecf51d122..0ea4c0ec8e 100644 --- a/libgo/go/encoding/gob/encoder_test.go +++ b/libgo/go/encoding/gob/encoder_test.go @@ -13,6 +13,52 @@ import ( "testing" ) +// Test basic operations in a safe manner. +func TestBasicEncoderDecoder(t *testing.T) { + var values = []interface{}{ + true, + int(123), + int8(123), + int16(-12345), + int32(123456), + int64(-1234567), + uint(123), + uint8(123), + uint16(12345), + uint32(123456), + uint64(1234567), + uintptr(12345678), + float32(1.2345), + float64(1.2345678), + complex64(1.2345 + 2.3456i), + complex128(1.2345678 + 2.3456789i), + []byte("hello"), + string("hello"), + } + for _, value := range values { + b := new(bytes.Buffer) + enc := NewEncoder(b) + err := enc.Encode(value) + if err != nil { + t.Error("encoder fail:", err) + } + dec := NewDecoder(b) + result := reflect.New(reflect.TypeOf(value)) + err = dec.Decode(result.Interface()) + if err != nil { + t.Fatalf("error decoding %T: %v:", reflect.TypeOf(value), err) + } + if !reflect.DeepEqual(value, result.Elem().Interface()) { + t.Fatalf("%T: expected %v got %v", value, value, result.Elem().Interface()) + } + } +} + +type ET0 struct { + A int + B string +} + type ET2 struct { X string } @@ -40,14 +86,40 @@ type ET4 struct { func TestEncoderDecoder(t *testing.T) { b := new(bytes.Buffer) enc := NewEncoder(b) + et0 := new(ET0) + et0.A = 7 + et0.B = "gobs of fun" + err := enc.Encode(et0) + if err != nil { + t.Error("encoder fail:", err) + } + //fmt.Printf("% x %q\n", b, b) + //Debug(b) + dec := NewDecoder(b) + newEt0 := new(ET0) + err = dec.Decode(newEt0) + if err != nil { + t.Fatal("error decoding ET0:", err) + } + + if !reflect.DeepEqual(et0, newEt0) { + t.Fatalf("invalid data for et0: expected %+v; got %+v", *et0, *newEt0) + } + if b.Len() != 0 { + t.Error("not at eof;", b.Len(), "bytes left") + } + // t.FailNow() + + b = new(bytes.Buffer) + enc = NewEncoder(b) et1 := new(ET1) et1.A = 7 et1.Et2 = new(ET2) - err := enc.Encode(et1) + err = enc.Encode(et1) if err != nil { t.Error("encoder fail:", err) } - dec := NewDecoder(b) + dec = NewDecoder(b) newEt1 := new(ET1) err = dec.Decode(newEt1) if err != nil { @@ -129,6 +201,8 @@ func TestBadData(t *testing.T) { corruptDataCheck("", io.EOF, t) corruptDataCheck("\x7Fhi", io.ErrUnexpectedEOF, t) corruptDataCheck("\x03now is the time for all good men", errBadType, t) + // issue 6323. + corruptDataCheck("\x04\x24foo", errRange, t) } // Types not supported at top level by the Encoder. @@ -630,7 +704,7 @@ func TestSliceReusesMemory(t *testing.T) { // Used to crash: negative count in recvMessage. func TestBadCount(t *testing.T) { b := []byte{0xfb, 0xa5, 0x82, 0x2f, 0xca, 0x1} - if err := NewDecoder(bytes.NewBuffer(b)).Decode(nil); err == nil { + if err := NewDecoder(bytes.NewReader(b)).Decode(nil); err == nil { t.Error("expected error from bad count") } else if err.Error() != errBadCount.Error() { t.Error("expected bad count error; got", err) @@ -858,3 +932,25 @@ func Test29ElementSlice(t *testing.T) { return } } + +// Don't crash, just give error when allocating a huge slice. +// Issue 8084. +func TestErrorForHugeSlice(t *testing.T) { + // Encode an int slice. + buf := new(bytes.Buffer) + slice := []int{1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + err := NewEncoder(buf).Encode(slice) + if err != nil { + t.Fatal("encode:", err) + } + // Reach into the buffer and smash the count to make the encoded slice very long. + buf.Bytes()[buf.Len()-len(slice)-1] = 0xfa + // Decode and see error. + err = NewDecoder(buf).Decode(&slice) + if err == nil { + t.Fatal("decode: no error") + } + if !strings.Contains(err.Error(), "slice too big") { + t.Fatal("decode: expected slice too big error, got %s", err.Error()) + } +} diff --git a/libgo/go/encoding/gob/gobencdec_test.go b/libgo/go/encoding/gob/gobencdec_test.go index 0193e2b67d..eb76b481d1 100644 --- a/libgo/go/encoding/gob/gobencdec_test.go +++ b/libgo/go/encoding/gob/gobencdec_test.go @@ -279,7 +279,7 @@ func TestGobEncoderValueField(t *testing.T) { b := new(bytes.Buffer) // First a field that's a structure. enc := NewEncoder(b) - err := enc.Encode(GobTestValueEncDec{17, StringStruct{"HIJKL"}}) + err := enc.Encode(&GobTestValueEncDec{17, StringStruct{"HIJKL"}}) if err != nil { t.Fatal("encode error:", err) } @@ -326,7 +326,7 @@ func TestGobEncoderArrayField(t *testing.T) { for i := range a.A.a { a.A.a[i] = byte(i) } - err := enc.Encode(a) + err := enc.Encode(&a) if err != nil { t.Fatal("encode error:", err) } @@ -589,7 +589,8 @@ func TestGobEncoderStructSingleton(t *testing.T) { func TestGobEncoderNonStructSingleton(t *testing.T) { b := new(bytes.Buffer) enc := NewEncoder(b) - err := enc.Encode(Gobber(1234)) + var g Gobber = 1234 + err := enc.Encode(&g) if err != nil { t.Fatal("encode error:", err) } @@ -705,13 +706,14 @@ func TestGobEncoderExtraIndirect(t *testing.T) { } // Another bug: this caused a crash with the new Go1 Time type. -// We throw in a gob-encoding array, to test another case of isZero - +// We throw in a gob-encoding array, to test another case of isZero, +// and a struct containing an nil interface, to test a third. type isZeroBug struct { T time.Time S string I int A isZeroBugArray + F isZeroBugInterface } type isZeroBugArray [2]uint8 @@ -731,8 +733,20 @@ func (a *isZeroBugArray) GobDecode(data []byte) error { return nil } +type isZeroBugInterface struct { + I interface{} +} + +func (i isZeroBugInterface) GobEncode() (b []byte, e error) { + return []byte{}, nil +} + +func (i *isZeroBugInterface) GobDecode(data []byte) error { + return nil +} + func TestGobEncodeIsZero(t *testing.T) { - x := isZeroBug{time.Now(), "hello", -55, isZeroBugArray{1, 2}} + x := isZeroBug{time.Now(), "hello", -55, isZeroBugArray{1, 2}, isZeroBugInterface{}} b := new(bytes.Buffer) enc := NewEncoder(b) err := enc.Encode(x) diff --git a/libgo/go/encoding/gob/timing_test.go b/libgo/go/encoding/gob/timing_test.go index 9fbb0ac6d5..940e5ad412 100644 --- a/libgo/go/encoding/gob/timing_test.go +++ b/libgo/go/encoding/gob/timing_test.go @@ -19,33 +19,57 @@ type Bench struct { D []byte } -func benchmarkEndToEnd(r io.Reader, w io.Writer, b *testing.B) { - b.StopTimer() - enc := NewEncoder(w) - dec := NewDecoder(r) - bench := &Bench{7, 3.2, "now is the time", []byte("for all good men")} - b.StartTimer() - for i := 0; i < b.N; i++ { - if enc.Encode(bench) != nil { - panic("encode error") +func benchmarkEndToEnd(b *testing.B, ctor func() interface{}, pipe func() (r io.Reader, w io.Writer, err error)) { + b.RunParallel(func(pb *testing.PB) { + r, w, err := pipe() + if err != nil { + b.Fatal("can't get pipe:", err) } - if dec.Decode(bench) != nil { - panic("decode error") + v := ctor() + enc := NewEncoder(w) + dec := NewDecoder(r) + for pb.Next() { + if err := enc.Encode(v); err != nil { + b.Fatal("encode error:", err) + } + if err := dec.Decode(v); err != nil { + b.Fatal("decode error:", err) + } } - } + }) } func BenchmarkEndToEndPipe(b *testing.B) { - r, w, err := os.Pipe() - if err != nil { - b.Fatal("can't get pipe:", err) - } - benchmarkEndToEnd(r, w, b) + benchmarkEndToEnd(b, func() interface{} { + return &Bench{7, 3.2, "now is the time", bytes.Repeat([]byte("for all good men"), 100)} + }, func() (r io.Reader, w io.Writer, err error) { + r, w, err = os.Pipe() + return + }) } func BenchmarkEndToEndByteBuffer(b *testing.B) { - var buf bytes.Buffer - benchmarkEndToEnd(&buf, &buf, b) + benchmarkEndToEnd(b, func() interface{} { + return &Bench{7, 3.2, "now is the time", bytes.Repeat([]byte("for all good men"), 100)} + }, func() (r io.Reader, w io.Writer, err error) { + var buf bytes.Buffer + return &buf, &buf, nil + }) +} + +func BenchmarkEndToEndSliceByteBuffer(b *testing.B) { + benchmarkEndToEnd(b, func() interface{} { + v := &Bench{7, 3.2, "now is the time", nil} + Register(v) + arr := make([]interface{}, 100) + for i := range arr { + arr[i] = v + } + return &arr + }, func() (r io.Reader, w io.Writer, err error) { + var buf bytes.Buffer + return &buf, &buf, nil + }) } func TestCountEncodeMallocs(t *testing.T) { @@ -103,7 +127,199 @@ func TestCountDecodeMallocs(t *testing.T) { t.Fatal("decode:", err) } }) - if allocs != 3 { - t.Fatalf("mallocs per decode of type Bench: %v; wanted 3\n", allocs) + if allocs != 4 { + t.Fatalf("mallocs per decode of type Bench: %v; wanted 4\n", allocs) + } +} + +func BenchmarkEncodeComplex128Slice(b *testing.B) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + a := make([]complex128, 1000) + for i := range a { + a[i] = 1.2 + 3.4i + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + buf.Reset() + err := enc.Encode(a) + if err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkEncodeFloat64Slice(b *testing.B) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + a := make([]float64, 1000) + for i := range a { + a[i] = 1.23e4 + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + buf.Reset() + err := enc.Encode(a) + if err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkEncodeInt32Slice(b *testing.B) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + a := make([]int32, 1000) + for i := range a { + a[i] = 1234 + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + buf.Reset() + err := enc.Encode(a) + if err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkEncodeStringSlice(b *testing.B) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + a := make([]string, 1000) + for i := range a { + a[i] = "now is the time" + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + buf.Reset() + err := enc.Encode(a) + if err != nil { + b.Fatal(err) + } + } +} + +// benchmarkBuf is a read buffer we can reset +type benchmarkBuf struct { + offset int + data []byte +} + +func (b *benchmarkBuf) Read(p []byte) (n int, err error) { + n = copy(p, b.data[b.offset:]) + if n == 0 { + return 0, io.EOF + } + b.offset += n + return +} + +func (b *benchmarkBuf) ReadByte() (c byte, err error) { + if b.offset >= len(b.data) { + return 0, io.EOF + } + c = b.data[b.offset] + b.offset++ + return +} + +func (b *benchmarkBuf) reset() { + b.offset = 0 +} + +func BenchmarkDecodeComplex128Slice(b *testing.B) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + a := make([]complex128, 1000) + for i := range a { + a[i] = 1.2 + 3.4i + } + err := enc.Encode(a) + if err != nil { + b.Fatal(err) + } + x := make([]complex128, 1000) + bbuf := benchmarkBuf{data: buf.Bytes()} + b.ResetTimer() + for i := 0; i < b.N; i++ { + bbuf.reset() + dec := NewDecoder(&bbuf) + err := dec.Decode(&x) + if err != nil { + b.Fatal(i, err) + } + } +} + +func BenchmarkDecodeFloat64Slice(b *testing.B) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + a := make([]float64, 1000) + for i := range a { + a[i] = 1.23e4 + } + err := enc.Encode(a) + if err != nil { + b.Fatal(err) + } + x := make([]float64, 1000) + bbuf := benchmarkBuf{data: buf.Bytes()} + b.ResetTimer() + for i := 0; i < b.N; i++ { + bbuf.reset() + dec := NewDecoder(&bbuf) + err := dec.Decode(&x) + if err != nil { + b.Fatal(i, err) + } + } +} + +func BenchmarkDecodeInt32Slice(b *testing.B) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + a := make([]int32, 1000) + for i := range a { + a[i] = 1234 + } + err := enc.Encode(a) + if err != nil { + b.Fatal(err) + } + x := make([]int32, 1000) + bbuf := benchmarkBuf{data: buf.Bytes()} + b.ResetTimer() + for i := 0; i < b.N; i++ { + bbuf.reset() + dec := NewDecoder(&bbuf) + err := dec.Decode(&x) + if err != nil { + b.Fatal(i, err) + } + } +} + +func BenchmarkDecodeStringSlice(b *testing.B) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + a := make([]string, 1000) + for i := range a { + a[i] = "now is the time" + } + err := enc.Encode(a) + if err != nil { + b.Fatal(err) + } + x := make([]string, 1000) + bbuf := benchmarkBuf{data: buf.Bytes()} + b.ResetTimer() + for i := 0; i < b.N; i++ { + bbuf.reset() + dec := NewDecoder(&bbuf) + err := dec.Decode(&x) + if err != nil { + b.Fatal(i, err) + } } } diff --git a/libgo/go/encoding/gob/type.go b/libgo/go/encoding/gob/type.go index cad1452795..a49b71a867 100644 --- a/libgo/go/encoding/gob/type.go +++ b/libgo/go/encoding/gob/type.go @@ -11,6 +11,7 @@ import ( "os" "reflect" "sync" + "sync/atomic" "unicode" "unicode/utf8" ) @@ -681,29 +682,51 @@ func (w *wireType) string() string { type typeInfo struct { id typeId - encoder *encEngine + encInit sync.Mutex // protects creation of encoder + encoder atomic.Value // *encEngine wire *wireType } -var typeInfoMap = make(map[reflect.Type]*typeInfo) // protected by typeLock +// typeInfoMap is an atomic pointer to map[reflect.Type]*typeInfo. +// It's updated copy-on-write. Readers just do an atomic load +// to get the current version of the map. Writers make a full copy of +// the map and atomically update the pointer to point to the new map. +// Under heavy read contention, this is significantly faster than a map +// protected by a mutex. +var typeInfoMap atomic.Value + +func lookupTypeInfo(rt reflect.Type) *typeInfo { + m, _ := typeInfoMap.Load().(map[reflect.Type]*typeInfo) + return m[rt] +} -// typeLock must be held. func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) { rt := ut.base if ut.externalEnc != 0 { // We want the user type, not the base type. rt = ut.user } - info, ok := typeInfoMap[rt] - if ok { + if info := lookupTypeInfo(rt); info != nil { return info, nil } - info = new(typeInfo) + return buildTypeInfo(ut, rt) +} + +// buildTypeInfo constructs the type information for the type +// and stores it in the type info map. +func buildTypeInfo(ut *userTypeInfo, rt reflect.Type) (*typeInfo, error) { + typeLock.Lock() + defer typeLock.Unlock() + + if info := lookupTypeInfo(rt); info != nil { + return info, nil + } + gt, err := getBaseType(rt.Name(), rt) if err != nil { return nil, err } - info.id = gt.id() + info := &typeInfo{id: gt.id()} if ut.externalEnc != 0 { userType, err := getType(rt.Name(), ut, rt) @@ -719,25 +742,32 @@ func getTypeInfo(ut *userTypeInfo) (*typeInfo, error) { case xText: info.wire = &wireType{TextMarshalerT: gt} } - typeInfoMap[ut.user] = info - return info, nil + rt = ut.user + } else { + t := info.id.gobType() + switch typ := rt; typ.Kind() { + case reflect.Array: + info.wire = &wireType{ArrayT: t.(*arrayType)} + case reflect.Map: + info.wire = &wireType{MapT: t.(*mapType)} + case reflect.Slice: + // []byte == []uint8 is a special case handled separately + if typ.Elem().Kind() != reflect.Uint8 { + info.wire = &wireType{SliceT: t.(*sliceType)} + } + case reflect.Struct: + info.wire = &wireType{StructT: t.(*structType)} + } } - t := info.id.gobType() - switch typ := rt; typ.Kind() { - case reflect.Array: - info.wire = &wireType{ArrayT: t.(*arrayType)} - case reflect.Map: - info.wire = &wireType{MapT: t.(*mapType)} - case reflect.Slice: - // []byte == []uint8 is a special case handled separately - if typ.Elem().Kind() != reflect.Uint8 { - info.wire = &wireType{SliceT: t.(*sliceType)} - } - case reflect.Struct: - info.wire = &wireType{StructT: t.(*structType)} + // Create new map with old contents plus new entry. + newm := make(map[reflect.Type]*typeInfo) + m, _ := typeInfoMap.Load().(map[reflect.Type]*typeInfo) + for k, v := range m { + newm[k] = v } - typeInfoMap[rt] = info + newm[rt] = info + typeInfoMap.Store(newm) return info, nil } diff --git a/libgo/go/encoding/hex/hex.go b/libgo/go/encoding/hex/hex.go index 167d00e032..d1fc7024a9 100644 --- a/libgo/go/encoding/hex/hex.go +++ b/libgo/go/encoding/hex/hex.go @@ -146,6 +146,9 @@ func (h *dumper) Write(data []byte) (n int, err error) { h.buf[12] = ' ' h.buf[13] = ' ' _, err = h.w.Write(h.buf[4:]) + if err != nil { + return + } } Encode(h.buf[:], data[i:i+1]) h.buf[2] = ' ' diff --git a/libgo/go/encoding/hex/hex_test.go b/libgo/go/encoding/hex/hex_test.go index 356f590f02..b969636cd5 100644 --- a/libgo/go/encoding/hex/hex_test.go +++ b/libgo/go/encoding/hex/hex_test.go @@ -38,7 +38,10 @@ func TestEncode(t *testing.T) { } func TestDecode(t *testing.T) { - for i, test := range encDecTests { + // Case for decoding uppercase hex characters, since + // Encode always uses lowercase. + decTests := append(encDecTests, encDecTest{"F8F9FAFBFCFDFEFF", []byte{0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}}) + for i, test := range decTests { dst := make([]byte, DecodedLen(len(test.enc))) n, err := Decode(dst, []byte(test.enc)) if err != nil { @@ -79,6 +82,7 @@ type errTest struct { var errTests = []errTest{ {"0", "encoding/hex: odd length hex string"}, {"0g", "encoding/hex: invalid byte: U+0067 'g'"}, + {"00gg", "encoding/hex: invalid byte: U+0067 'g'"}, {"0\x01", "encoding/hex: invalid byte: U+0001"}, } diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go index 458fb39ec0..705bc2e17a 100644 --- a/libgo/go/encoding/json/decode.go +++ b/libgo/go/encoding/json/decode.go @@ -8,6 +8,7 @@ package json import ( + "bytes" "encoding" "encoding/base64" "errors" @@ -15,7 +16,6 @@ import ( "reflect" "runtime" "strconv" - "strings" "unicode" "unicode/utf16" "unicode/utf8" @@ -54,6 +54,11 @@ import ( // If no more serious errors are encountered, Unmarshal returns // an UnmarshalTypeError describing the earliest such error. // +// The JSON null value unmarshals into an interface, map, pointer, or slice +// by setting that Go value to nil. Because null is often used in JSON to mean +// ``not present,'' unmarshaling a JSON null into any other Go type has no effect +// on the value and produces no error. +// // When unmarshaling quoted strings, invalid UTF-8 or // invalid UTF-16 surrogate pairs are not treated as an error. // Instead, they are replaced by the Unicode replacement @@ -168,7 +173,6 @@ type decodeState struct { scan scanner nextscan scanner // for calls to nextValue savedError error - tempstr string // scratch space to avoid some allocations useNumber bool } @@ -288,6 +292,32 @@ func (d *decodeState) value(v reflect.Value) { } } +type unquotedValue struct{} + +// valueQuoted is like value but decodes a +// quoted string literal or literal null into an interface value. +// If it finds anything other than a quoted string literal or null, +// valueQuoted returns unquotedValue{}. +func (d *decodeState) valueQuoted() interface{} { + switch op := d.scanWhile(scanSkipSpace); op { + default: + d.error(errPhase) + + case scanBeginArray: + d.array(reflect.Value{}) + + case scanBeginObject: + d.object(reflect.Value{}) + + case scanBeginLiteral: + switch v := d.literalInterface().(type) { + case nil, string: + return v + } + } + return unquotedValue{} +} + // indirect walks down v allocating pointers as needed, // until it gets to a non-pointer. // if it encounters an Unmarshaler, indirect stops and returns that. @@ -439,8 +469,10 @@ func (d *decodeState) array(v reflect.Value) { } } +var nullLiteral = []byte("null") + // object consumes an object from d.data[d.off-1:], decoding into the value v. -// the first byte of the object ('{') has been read already. +// the first byte ('{') of the object has been read already. func (d *decodeState) object(v reflect.Value) { // Check for unmarshaler. u, ut, pv := d.indirect(v, false) @@ -473,7 +505,9 @@ func (d *decodeState) object(v reflect.Value) { t := v.Type() if t.Key().Kind() != reflect.String { d.saveError(&UnmarshalTypeError{"object", v.Type()}) - break + d.off-- + d.next() // skip over { } in input + return } if v.IsNil() { v.Set(reflect.MakeMap(t)) @@ -500,11 +534,11 @@ func (d *decodeState) object(v reflect.Value) { d.error(errPhase) } - // Read string key. + // Read key. start := d.off - 1 op = d.scanWhile(scanContinue) item := d.data[start : d.off-1] - key, ok := unquote(item) + key, ok := unquoteBytes(item) if !ok { d.error(errPhase) } @@ -526,11 +560,11 @@ func (d *decodeState) object(v reflect.Value) { fields := cachedTypeFields(v.Type()) for i := range fields { ff := &fields[i] - if ff.name == key { + if bytes.Equal(ff.nameBytes, key) { f = ff break } - if f == nil && strings.EqualFold(ff.name, key) { + if f == nil && ff.equalFold(ff.nameBytes, key) { f = ff } } @@ -559,8 +593,14 @@ func (d *decodeState) object(v reflect.Value) { // Read value. if destring { - d.value(reflect.ValueOf(&d.tempstr)) - d.literalStore([]byte(d.tempstr), subv, true) + switch qv := d.valueQuoted().(type) { + case nil: + d.literalStore(nullLiteral, subv, false) + case string: + d.literalStore([]byte(qv), subv, true) + default: + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", item, v.Type())) + } } else { d.value(subv) } diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go index 22c5f89f79..7235969b9f 100644 --- a/libgo/go/encoding/json/decode_test.go +++ b/libgo/go/encoding/json/decode_test.go @@ -406,6 +406,13 @@ var unmarshalTests = []unmarshalTest{ ptr: new(string), out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld", }, + + // issue 8305 + { + in: `{"2009-11-10T23:00:00Z": "hello world"}`, + ptr: &map[time.Time]string{}, + err: &UnmarshalTypeError{"object", reflect.TypeOf(map[time.Time]string{})}, + }, } func TestMarshal(t *testing.T) { @@ -514,6 +521,7 @@ func TestUnmarshal(t *testing.T) { if tt.ptr == nil { continue } + // v = new(right-type) v := reflect.New(reflect.TypeOf(tt.ptr).Elem()) dec := NewDecoder(bytes.NewReader(in)) @@ -521,7 +529,9 @@ func TestUnmarshal(t *testing.T) { dec.UseNumber() } if err := dec.Decode(v.Interface()); !reflect.DeepEqual(err, tt.err) { - t.Errorf("#%d: %v want %v", i, err, tt.err) + t.Errorf("#%d: %v, want %v", i, err, tt.err) + continue + } else if err != nil { continue } if !reflect.DeepEqual(v.Elem().Interface(), tt.out) { @@ -1060,6 +1070,28 @@ func TestEmptyString(t *testing.T) { } } +// Test that a null for ,string is not replaced with the previous quoted string (issue 7046). +// It should also not be an error (issue 2540, issue 8587). +func TestNullString(t *testing.T) { + type T struct { + A int `json:",string"` + B int `json:",string"` + C *int `json:",string"` + } + data := []byte(`{"A": "1", "B": null, "C": null}`) + var s T + s.B = 1 + s.C = new(int) + *s.C = 2 + err := Unmarshal(data, &s) + if err != nil { + t.Fatalf("Unmarshal: %v") + } + if s.B != 1 || s.C != nil { + t.Fatalf("after Unmarshal, s.B=%d, s.C=%p, want 1, nil", s.B, s.C) + } +} + func intp(x int) *int { p := new(int) *p = x @@ -1110,8 +1142,8 @@ func TestInterfaceSet(t *testing.T) { // Issue 2540 func TestUnmarshalNulls(t *testing.T) { jsonData := []byte(`{ - "Bool" : null, - "Int" : null, + "Bool" : null, + "Int" : null, "Int8" : null, "Int16" : null, "Int32" : null, @@ -1316,3 +1348,26 @@ func TestPrefilled(t *testing.T) { } } } + +var invalidUnmarshalTests = []struct { + v interface{} + want string +}{ + {nil, "json: Unmarshal(nil)"}, + {struct{}{}, "json: Unmarshal(non-pointer struct {})"}, + {(*int)(nil), "json: Unmarshal(nil *int)"}, +} + +func TestInvalidUnmarshal(t *testing.T) { + buf := []byte(`{"a":"1"}`) + for _, tt := range invalidUnmarshalTests { + err := Unmarshal(buf, tt.v) + if err == nil { + t.Errorf("Unmarshal expecting error, got nil") + continue + } + if got := err.Error(); got != tt.want { + t.Errorf("Unmarshal = %q; want %q", got, tt.want) + } + } +} diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go index 7d6c71d7a9..fca2a0980b 100644 --- a/libgo/go/encoding/json/encode.go +++ b/libgo/go/encoding/json/encode.go @@ -40,10 +40,11 @@ import ( // // Floating point, integer, and Number values encode as JSON numbers. // -// String values encode as JSON strings. InvalidUTF8Error will be returned -// if an invalid UTF-8 sequence is encountered. +// String values encode as JSON strings coerced to valid UTF-8, +// replacing invalid bytes with the Unicode replacement rune. // The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e" // to keep some browsers from misinterpreting JSON output as HTML. +// Ampersand "&" is also escaped to "\u0026" for the same reason. // // Array and slice values encode as JSON arrays, except that // []byte encodes as a base64-encoded string, and a nil slice @@ -92,6 +93,8 @@ import ( // as described in the next paragraph. // An anonymous struct field with a name given in its JSON tag is treated as // having that name, rather than being anonymous. +// An anonymous struct field of interface type is treated the same as having +// that type as its name, rather than being anonymous. // // The Go visibility rules for struct fields are amended for JSON when // deciding which field to marshal or unmarshal. If there are @@ -241,24 +244,15 @@ type encodeState struct { scratch [64]byte } -// TODO(bradfitz): use a sync.Cache here -var encodeStatePool = make(chan *encodeState, 8) +var encodeStatePool sync.Pool func newEncodeState() *encodeState { - select { - case e := <-encodeStatePool: + if v := encodeStatePool.Get(); v != nil { + e := v.(*encodeState) e.Reset() return e - default: - return new(encodeState) - } -} - -func putEncodeState(e *encodeState) { - select { - case encodeStatePool <- e: - default: } + return new(encodeState) } func (e *encodeState) marshal(v interface{}) (err error) { @@ -704,12 +698,12 @@ type ptrEncoder struct { elemEnc encoderFunc } -func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, _ bool) { +func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, quoted bool) { if v.IsNil() { e.WriteString("null") return } - pe.elemEnc(e, v.Elem(), false) + pe.elemEnc(e, v.Elem(), quoted) } func newPtrEncoder(t reflect.Type) encoderFunc { @@ -811,9 +805,12 @@ func (e *encodeState) string(s string) (int, error) { case '\r': e.WriteByte('\\') e.WriteByte('r') + case '\t': + e.WriteByte('\\') + e.WriteByte('t') default: // This encodes bytes < 0x20 except for \n and \r, - // as well as < and >. The latter are escaped because they + // as well as <, > and &. The latter are escaped because they // can lead to security holes when user-controlled strings // are rendered into JSON and served to some browsers. e.WriteString(`\u00`) @@ -884,9 +881,12 @@ func (e *encodeState) stringBytes(s []byte) (int, error) { case '\r': e.WriteByte('\\') e.WriteByte('r') + case '\t': + e.WriteByte('\\') + e.WriteByte('t') default: // This encodes bytes < 0x20 except for \n and \r, - // as well as < and >. The latter are escaped because they + // as well as <, >, and &. The latter are escaped because they // can lead to security holes when user-controlled strings // are rendered into JSON and served to some browsers. e.WriteString(`\u00`) @@ -936,6 +936,9 @@ func (e *encodeState) stringBytes(s []byte) (int, error) { // A field represents a single field found in a struct. type field struct { name string + nameBytes []byte // []byte(name) + equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent + tag bool index []int typ reflect.Type @@ -943,6 +946,12 @@ type field struct { quoted bool } +func fillField(f field) field { + f.nameBytes = []byte(f.name) + f.equalFold = foldFunc(f.nameBytes) + return f +} + // byName sorts field by name, breaking ties with depth, // then breaking ties with "name came from json tag", then // breaking ties with index sequence. @@ -1042,8 +1051,14 @@ func typeFields(t reflect.Type) []field { if name == "" { name = sf.Name } - fields = append(fields, field{name, tagged, index, ft, - opts.Contains("omitempty"), opts.Contains("string")}) + fields = append(fields, fillField(field{ + name: name, + tag: tagged, + index: index, + typ: ft, + omitEmpty: opts.Contains("omitempty"), + quoted: opts.Contains("string"), + })) if count[f.typ] > 1 { // If there were multiple instances, add a second, // so that the annihilation code will see a duplicate. @@ -1057,7 +1072,7 @@ func typeFields(t reflect.Type) []field { // Record new anonymous struct to explore in next round. nextCount[ft]++ if nextCount[ft] == 1 { - next = append(next, field{name: ft.Name(), index: index, typ: ft}) + next = append(next, fillField(field{name: ft.Name(), index: index, typ: ft})) } } } diff --git a/libgo/go/encoding/json/encode_test.go b/libgo/go/encoding/json/encode_test.go index 9395db7cb6..7abfa85db7 100644 --- a/libgo/go/encoding/json/encode_test.go +++ b/libgo/go/encoding/json/encode_test.go @@ -25,13 +25,30 @@ type Optionals struct { Mr map[string]interface{} `json:"mr"` Mo map[string]interface{} `json:",omitempty"` + + Fr float64 `json:"fr"` + Fo float64 `json:"fo,omitempty"` + + Br bool `json:"br"` + Bo bool `json:"bo,omitempty"` + + Ur uint `json:"ur"` + Uo uint `json:"uo,omitempty"` + + Str struct{} `json:"str"` + Sto struct{} `json:"sto,omitempty"` } var optionalsExpected = `{ "sr": "", "omitempty": 0, "slr": null, - "mr": {} + "mr": {}, + "fr": 0, + "br": false, + "ur": 0, + "str": {}, + "sto": {} }` func TestOmitEmpty(t *testing.T) { @@ -76,7 +93,7 @@ func TestStringTag(t *testing.T) { // Verify that it round-trips. var s2 StringTag - err = NewDecoder(bytes.NewBuffer(got)).Decode(&s2) + err = NewDecoder(bytes.NewReader(got)).Decode(&s2) if err != nil { t.Fatalf("Decode: %v", err) } @@ -425,3 +442,91 @@ func TestIssue6458(t *testing.T) { t.Errorf("Marshal(x) = %#q; want %#q", b, want) } } + +func TestHTMLEscape(t *testing.T) { + var b, want bytes.Buffer + m := `{"M":"foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `"}` + want.Write([]byte(`{"M":"\u003chtml\u003efoo \u0026\u2028 \u2029\u003c/html\u003e"}`)) + HTMLEscape(&b, []byte(m)) + if !bytes.Equal(b.Bytes(), want.Bytes()) { + t.Errorf("HTMLEscape(&b, []byte(m)) = %s; want %s", b.Bytes(), want.Bytes()) + } +} + +// golang.org/issue/8582 +func TestEncodePointerString(t *testing.T) { + type stringPointer struct { + N *int64 `json:"n,string"` + } + var n int64 = 42 + b, err := Marshal(stringPointer{N: &n}) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + if got, want := string(b), `{"n":"42"}`; got != want { + t.Errorf("Marshal = %s, want %s", got, want) + } + var back stringPointer + err = Unmarshal(b, &back) + if err != nil { + t.Fatalf("Unmarshal: %v", err) + } + if back.N == nil { + t.Fatalf("Unmarshalled nil N field") + } + if *back.N != 42 { + t.Fatalf("*N = %d; want 42", *back.N) + } +} + +var encodeStringTests = []struct { + in string + out string +}{ + {"\x00", `"\u0000"`}, + {"\x01", `"\u0001"`}, + {"\x02", `"\u0002"`}, + {"\x03", `"\u0003"`}, + {"\x04", `"\u0004"`}, + {"\x05", `"\u0005"`}, + {"\x06", `"\u0006"`}, + {"\x07", `"\u0007"`}, + {"\x08", `"\u0008"`}, + {"\x09", `"\t"`}, + {"\x0a", `"\n"`}, + {"\x0b", `"\u000b"`}, + {"\x0c", `"\u000c"`}, + {"\x0d", `"\r"`}, + {"\x0e", `"\u000e"`}, + {"\x0f", `"\u000f"`}, + {"\x10", `"\u0010"`}, + {"\x11", `"\u0011"`}, + {"\x12", `"\u0012"`}, + {"\x13", `"\u0013"`}, + {"\x14", `"\u0014"`}, + {"\x15", `"\u0015"`}, + {"\x16", `"\u0016"`}, + {"\x17", `"\u0017"`}, + {"\x18", `"\u0018"`}, + {"\x19", `"\u0019"`}, + {"\x1a", `"\u001a"`}, + {"\x1b", `"\u001b"`}, + {"\x1c", `"\u001c"`}, + {"\x1d", `"\u001d"`}, + {"\x1e", `"\u001e"`}, + {"\x1f", `"\u001f"`}, +} + +func TestEncodeString(t *testing.T) { + for _, tt := range encodeStringTests { + b, err := Marshal(tt.in) + if err != nil { + t.Errorf("Marshal(%q): %v", tt.in, err) + continue + } + out := string(b) + if out != tt.out { + t.Errorf("Marshal(%q) = %#q, want %#q", tt.in, out, tt.out) + } + } +} diff --git a/libgo/go/encoding/json/fold.go b/libgo/go/encoding/json/fold.go new file mode 100644 index 0000000000..d6f77c93e5 --- /dev/null +++ b/libgo/go/encoding/json/fold.go @@ -0,0 +1,143 @@ +// 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 json + +import ( + "bytes" + "unicode/utf8" +) + +const ( + caseMask = ^byte(0x20) // Mask to ignore case in ASCII. + kelvin = '\u212a' + smallLongEss = '\u017f' +) + +// foldFunc returns one of four different case folding equivalence +// functions, from most general (and slow) to fastest: +// +// 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8 +// 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S') +// 3) asciiEqualFold, no special, but includes non-letters (including _) +// 4) simpleLetterEqualFold, no specials, no non-letters. +// +// The letters S and K are special because they map to 3 runes, not just 2: +// * S maps to s and to U+017F 'ſ' Latin small letter long s +// * k maps to K and to U+212A 'K' Kelvin sign +// See http://play.golang.org/p/tTxjOc0OGo +// +// The returned function is specialized for matching against s and +// should only be given s. It's not curried for performance reasons. +func foldFunc(s []byte) func(s, t []byte) bool { + nonLetter := false + special := false // special letter + for _, b := range s { + if b >= utf8.RuneSelf { + return bytes.EqualFold + } + upper := b & caseMask + if upper < 'A' || upper > 'Z' { + nonLetter = true + } else if upper == 'K' || upper == 'S' { + // See above for why these letters are special. + special = true + } + } + if special { + return equalFoldRight + } + if nonLetter { + return asciiEqualFold + } + return simpleLetterEqualFold +} + +// equalFoldRight is a specialization of bytes.EqualFold when s is +// known to be all ASCII (including punctuation), but contains an 's', +// 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t. +// See comments on foldFunc. +func equalFoldRight(s, t []byte) bool { + for _, sb := range s { + if len(t) == 0 { + return false + } + tb := t[0] + if tb < utf8.RuneSelf { + if sb != tb { + sbUpper := sb & caseMask + if 'A' <= sbUpper && sbUpper <= 'Z' { + if sbUpper != tb&caseMask { + return false + } + } else { + return false + } + } + t = t[1:] + continue + } + // sb is ASCII and t is not. t must be either kelvin + // sign or long s; sb must be s, S, k, or K. + tr, size := utf8.DecodeRune(t) + switch sb { + case 's', 'S': + if tr != smallLongEss { + return false + } + case 'k', 'K': + if tr != kelvin { + return false + } + default: + return false + } + t = t[size:] + + } + if len(t) > 0 { + return false + } + return true +} + +// asciiEqualFold is a specialization of bytes.EqualFold for use when +// s is all ASCII (but may contain non-letters) and contains no +// special-folding letters. +// See comments on foldFunc. +func asciiEqualFold(s, t []byte) bool { + if len(s) != len(t) { + return false + } + for i, sb := range s { + tb := t[i] + if sb == tb { + continue + } + if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') { + if sb&caseMask != tb&caseMask { + return false + } + } else { + return false + } + } + return true +} + +// simpleLetterEqualFold is a specialization of bytes.EqualFold for +// use when s is all ASCII letters (no underscores, etc) and also +// doesn't contain 'k', 'K', 's', or 'S'. +// See comments on foldFunc. +func simpleLetterEqualFold(s, t []byte) bool { + if len(s) != len(t) { + return false + } + for i, b := range s { + if b&caseMask != t[i]&caseMask { + return false + } + } + return true +} diff --git a/libgo/go/encoding/json/fold_test.go b/libgo/go/encoding/json/fold_test.go new file mode 100644 index 0000000000..9fb94646a8 --- /dev/null +++ b/libgo/go/encoding/json/fold_test.go @@ -0,0 +1,116 @@ +// 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 json + +import ( + "bytes" + "strings" + "testing" + "unicode/utf8" +) + +var foldTests = []struct { + fn func(s, t []byte) bool + s, t string + want bool +}{ + {equalFoldRight, "", "", true}, + {equalFoldRight, "a", "a", true}, + {equalFoldRight, "", "a", false}, + {equalFoldRight, "a", "", false}, + {equalFoldRight, "a", "A", true}, + {equalFoldRight, "AB", "ab", true}, + {equalFoldRight, "AB", "ac", false}, + {equalFoldRight, "sbkKc", "ſbKKc", true}, + {equalFoldRight, "SbKkc", "ſbKKc", true}, + {equalFoldRight, "SbKkc", "ſbKK", false}, + {equalFoldRight, "e", "é", false}, + {equalFoldRight, "s", "S", true}, + + {simpleLetterEqualFold, "", "", true}, + {simpleLetterEqualFold, "abc", "abc", true}, + {simpleLetterEqualFold, "abc", "ABC", true}, + {simpleLetterEqualFold, "abc", "ABCD", false}, + {simpleLetterEqualFold, "abc", "xxx", false}, + + {asciiEqualFold, "a_B", "A_b", true}, + {asciiEqualFold, "aa@", "aa`", false}, // verify 0x40 and 0x60 aren't case-equivalent +} + +func TestFold(t *testing.T) { + for i, tt := range foldTests { + if got := tt.fn([]byte(tt.s), []byte(tt.t)); got != tt.want { + t.Errorf("%d. %q, %q = %v; want %v", i, tt.s, tt.t, got, tt.want) + } + truth := strings.EqualFold(tt.s, tt.t) + if truth != tt.want { + t.Errorf("strings.EqualFold doesn't agree with case %d", i) + } + } +} + +func TestFoldAgainstUnicode(t *testing.T) { + const bufSize = 5 + buf1 := make([]byte, 0, bufSize) + buf2 := make([]byte, 0, bufSize) + var runes []rune + for i := 0x20; i <= 0x7f; i++ { + runes = append(runes, rune(i)) + } + runes = append(runes, kelvin, smallLongEss) + + funcs := []struct { + name string + fold func(s, t []byte) bool + letter bool // must be ASCII letter + simple bool // must be simple ASCII letter (not 'S' or 'K') + }{ + { + name: "equalFoldRight", + fold: equalFoldRight, + }, + { + name: "asciiEqualFold", + fold: asciiEqualFold, + simple: true, + }, + { + name: "simpleLetterEqualFold", + fold: simpleLetterEqualFold, + simple: true, + letter: true, + }, + } + + for _, ff := range funcs { + for _, r := range runes { + if r >= utf8.RuneSelf { + continue + } + if ff.letter && !isASCIILetter(byte(r)) { + continue + } + if ff.simple && (r == 's' || r == 'S' || r == 'k' || r == 'K') { + continue + } + for _, r2 := range runes { + buf1 := append(buf1[:0], 'x') + buf2 := append(buf2[:0], 'x') + buf1 = buf1[:1+utf8.EncodeRune(buf1[1:bufSize], r)] + buf2 = buf2[:1+utf8.EncodeRune(buf2[1:bufSize], r2)] + buf1 = append(buf1, 'x') + buf2 = append(buf2, 'x') + want := bytes.EqualFold(buf1, buf2) + if got := ff.fold(buf1, buf2); got != want { + t.Errorf("%s(%q, %q) = %v; want %v", ff.name, buf1, buf2, got, want) + } + } + } + } +} + +func isASCIILetter(b byte) bool { + return ('A' <= b && b <= 'Z') || ('a' <= b && b <= 'z') +} diff --git a/libgo/go/encoding/json/indent.go b/libgo/go/encoding/json/indent.go index 11ef709cce..e1bacafd6b 100644 --- a/libgo/go/encoding/json/indent.go +++ b/libgo/go/encoding/json/indent.go @@ -69,8 +69,9 @@ func newline(dst *bytes.Buffer, prefix, indent string, depth int) { // Each element in a JSON object or array begins on a new, // indented line beginning with prefix followed by one or more // copies of indent according to the indentation nesting. -// The data appended to dst has no trailing newline, to make it easier -// to embed inside other formatted JSON data. +// The data appended to dst does not begin with the prefix nor +// any indentation, and has no trailing newline, to make it +// easier to embed inside other formatted JSON data. func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error { origLen := dst.Len() var scan scanner diff --git a/libgo/go/encoding/json/scanner_test.go b/libgo/go/encoding/json/scanner_test.go index 90e45ff036..7880342902 100644 --- a/libgo/go/encoding/json/scanner_test.go +++ b/libgo/go/encoding/json/scanner_test.go @@ -239,23 +239,16 @@ func trim(b []byte) []byte { var jsonBig []byte -const ( - big = 10000 - small = 100 -) - func initBig() { - n := big + n := 10000 if testing.Short() { - n = small + n = 100 } - if len(jsonBig) != n { - b, err := Marshal(genValue(n)) - if err != nil { - panic(err) - } - jsonBig = b + b, err := Marshal(genValue(n)) + if err != nil { + panic(err) } + jsonBig = b } func genValue(n int) interface{} { @@ -296,6 +289,9 @@ func genArray(n int) []interface{} { if f > n { f = n } + if f < 1 { + f = 1 + } x := make([]interface{}, f) for i := range x { x[i] = genValue(((i+1)*n)/f - (i*n)/f) diff --git a/libgo/go/encoding/json/stream.go b/libgo/go/encoding/json/stream.go index 1928abadb7..9566ecadcb 100644 --- a/libgo/go/encoding/json/stream.go +++ b/libgo/go/encoding/json/stream.go @@ -139,7 +139,6 @@ func nonSpace(b []byte) bool { // An Encoder writes JSON objects to an output stream. type Encoder struct { w io.Writer - e encodeState err error } @@ -148,7 +147,8 @@ func NewEncoder(w io.Writer) *Encoder { return &Encoder{w: w} } -// Encode writes the JSON encoding of v to the stream. +// Encode writes the JSON encoding of v to the stream, +// followed by a newline character. // // See the documentation for Marshal for details about the // conversion of Go values to JSON. @@ -173,7 +173,7 @@ func (enc *Encoder) Encode(v interface{}) error { if _, err = enc.w.Write(e.Bytes()); err != nil { enc.err = err } - putEncodeState(e) + encodeStatePool.Put(e) return err } diff --git a/libgo/go/encoding/xml/marshal.go b/libgo/go/encoding/xml/marshal.go index d9522e0b39..8c6342013d 100644 --- a/libgo/go/encoding/xml/marshal.go +++ b/libgo/go/encoding/xml/marshal.go @@ -184,10 +184,12 @@ var ( // EncodeToken does not call Flush, because usually it is part of a larger operation // such as Encode or EncodeElement (or a custom Marshaler's MarshalXML invoked // during those), and those will call Flush when finished. -// // Callers that create an Encoder and then invoke EncodeToken directly, without // using Encode or EncodeElement, need to call Flush when finished to ensure // that the XML is written to the underlying writer. +// +// EncodeToken allows writing a ProcInst with Target set to "xml" only as the first token +// in the stream. func (enc *Encoder) EncodeToken(t Token) error { p := &enc.p switch t := t.(type) { @@ -210,7 +212,12 @@ func (enc *Encoder) EncodeToken(t Token) error { p.WriteString("-->") return p.cachedWriteError() case ProcInst: - if t.Target == "xml" || !isNameString(t.Target) { + // First token to be encoded which is also a ProcInst with target of xml + // is the xml declaration. The only ProcInst where target of xml is allowed. + if t.Target == "xml" && p.Buffered() != 0 { + return fmt.Errorf("xml: EncodeToken of ProcInst xml target only valid for xml declaration, first token encoded") + } + if !isNameString(t.Target) { return fmt.Errorf("xml: EncodeToken of ProcInst with invalid Target") } if bytes.Contains(t.Inst, endProcInst) { diff --git a/libgo/go/encoding/xml/marshal_test.go b/libgo/go/encoding/xml/marshal_test.go index d34118a3d8..14f73a75d5 100644 --- a/libgo/go/encoding/xml/marshal_test.go +++ b/libgo/go/encoding/xml/marshal_test.go @@ -314,6 +314,31 @@ type MarshalerStruct struct { Foo MyMarshalerAttrTest `xml:",attr"` } +type InnerStruct struct { + XMLName Name `xml:"testns outer"` +} + +type OuterStruct struct { + InnerStruct + IntAttr int `xml:"int,attr"` +} + +type OuterNamedStruct struct { + InnerStruct + XMLName Name `xml:"outerns test"` + IntAttr int `xml:"int,attr"` +} + +type OuterNamedOrderedStruct struct { + XMLName Name `xml:"outerns test"` + InnerStruct + IntAttr int `xml:"int,attr"` +} + +type OuterOuterStruct struct { + OuterStruct +} + func ifaceptr(x interface{}) interface{} { return &x } @@ -883,6 +908,22 @@ var marshalTests = []struct { ExpectXML: ``, Value: &MarshalerStruct{}, }, + { + ExpectXML: ``, + Value: &OuterStruct{IntAttr: 10}, + }, + { + ExpectXML: ``, + Value: &OuterNamedStruct{XMLName: Name{Space: "outerns", Local: "test"}, IntAttr: 10}, + }, + { + ExpectXML: ``, + Value: &OuterNamedOrderedStruct{XMLName: Name{Space: "outerns", Local: "test"}, IntAttr: 10}, + }, + { + ExpectXML: ``, + Value: &OuterOuterStruct{OuterStruct{IntAttr: 10}}, + }, } func TestMarshal(t *testing.T) { @@ -1149,3 +1190,77 @@ func TestStructPointerMarshal(t *testing.T) { t.Fatal(err) } } + +var encodeTokenTests = []struct { + tok Token + want string + ok bool +}{ + {StartElement{Name{"space", "local"}, nil}, "", true}, + {StartElement{Name{"space", ""}, nil}, "", false}, + {EndElement{Name{"space", ""}}, "", false}, + {CharData("foo"), "foo", true}, + {Comment("foo"), "", true}, + {Comment("foo-->"), "", false}, + {ProcInst{"Target", []byte("Instruction")}, "", true}, + {ProcInst{"", []byte("Instruction")}, "", false}, + {ProcInst{"Target", []byte("Instruction?>")}, "", false}, + {Directive("foo"), "", true}, + {Directive("foo>"), "", false}, +} + +func TestEncodeToken(t *testing.T) { + for _, tt := range encodeTokenTests { + var buf bytes.Buffer + enc := NewEncoder(&buf) + err := enc.EncodeToken(tt.tok) + switch { + case !tt.ok && err == nil: + t.Errorf("enc.EncodeToken(%#v): expected error; got none", tt.tok) + case tt.ok && err != nil: + t.Fatalf("enc.EncodeToken: %v", err) + case !tt.ok && err != nil: + // expected error, got one + } + if err := enc.Flush(); err != nil { + t.Fatalf("enc.EncodeToken: %v", err) + } + if got := buf.String(); got != tt.want { + t.Errorf("enc.EncodeToken = %s; want: %s", got, tt.want) + } + } +} + +func TestProcInstEncodeToken(t *testing.T) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + + if err := enc.EncodeToken(ProcInst{"xml", []byte("Instruction")}); err != nil { + t.Fatalf("enc.EncodeToken: expected to be able to encode xml target ProcInst as first token, %s", err) + } + + if err := enc.EncodeToken(ProcInst{"Target", []byte("Instruction")}); err != nil { + t.Fatalf("enc.EncodeToken: expected to be able to add non-xml target ProcInst") + } + + if err := enc.EncodeToken(ProcInst{"xml", []byte("Instruction")}); err == nil { + t.Fatalf("enc.EncodeToken: expected to not be allowed to encode xml target ProcInst when not first token") + } +} + +func TestDecodeEncode(t *testing.T) { + var in, out bytes.Buffer + in.WriteString(` + + + +`) + dec := NewDecoder(&in) + enc := NewEncoder(&out) + for tok, err := dec.Token(); err == nil; tok, err = dec.Token() { + err = enc.EncodeToken(tok) + if err != nil { + t.Fatalf("enc.EncodeToken: Unable to encode token (%#v), %v", tok, err) + } + } +} diff --git a/libgo/go/encoding/xml/read.go b/libgo/go/encoding/xml/read.go index 8890508f85..75b9f2ba1b 100644 --- a/libgo/go/encoding/xml/read.go +++ b/libgo/go/encoding/xml/read.go @@ -112,7 +112,7 @@ import ( // to a freshly allocated value and then mapping the element to that value. // func Unmarshal(data []byte, v interface{}) error { - return NewDecoder(bytes.NewBuffer(data)).Decode(v) + return NewDecoder(bytes.NewReader(data)).Decode(v) } // Decode works like xml.Unmarshal, except it reads the decoder @@ -284,6 +284,15 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error { } } + // Load value from interface, but only if the result will be + // usefully addressable. + if val.Kind() == reflect.Interface && !val.IsNil() { + e := val.Elem() + if e.Kind() == reflect.Ptr && !e.IsNil() { + val = e + } + } + if val.Kind() == reflect.Ptr { if val.IsNil() { val.Set(reflect.New(val.Type().Elem())) diff --git a/libgo/go/encoding/xml/read_test.go b/libgo/go/encoding/xml/read_test.go index 1404c900f5..01f55d0dd0 100644 --- a/libgo/go/encoding/xml/read_test.go +++ b/libgo/go/encoding/xml/read_test.go @@ -685,3 +685,30 @@ func TestUnmarshaler(t *testing.T) { t.Errorf("m=%#+v\n", m) } } + +type Pea struct { + Cotelydon string +} + +type Pod struct { + Pea interface{} `xml:"Pea"` +} + +// https://code.google.com/p/go/issues/detail?id=6836 +func TestUnmarshalIntoInterface(t *testing.T) { + pod := new(Pod) + pod.Pea = new(Pea) + xml := `Green stuff` + err := Unmarshal([]byte(xml), pod) + if err != nil { + t.Fatalf("failed to unmarshal %q: %v", xml, err) + } + pea, ok := pod.Pea.(*Pea) + if !ok { + t.Fatalf("unmarshalled into wrong type: have %T want *Pea", pod.Pea) + } + have, want := pea.Cotelydon, "Green stuff" + if have != want { + t.Errorf("failed to unmarshal into interface, have %q want %q", have, want) + } +} diff --git a/libgo/go/encoding/xml/typeinfo.go b/libgo/go/encoding/xml/typeinfo.go index 83e65402c0..22248d20a6 100644 --- a/libgo/go/encoding/xml/typeinfo.go +++ b/libgo/go/encoding/xml/typeinfo.go @@ -75,6 +75,9 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) { if err != nil { return nil, err } + if tinfo.xmlname == nil { + tinfo.xmlname = inner.xmlname + } for _, finfo := range inner.fields { finfo.idx = append([]int{i}, finfo.idx...) if err := addFieldInfo(typ, tinfo, &finfo); err != nil { diff --git a/libgo/go/encoding/xml/xml.go b/libgo/go/encoding/xml/xml.go index 5b9d670024..8c15b98c3a 100644 --- a/libgo/go/encoding/xml/xml.go +++ b/libgo/go/encoding/xml/xml.go @@ -196,10 +196,13 @@ type Decoder struct { ns map[string]string err error line int + offset int64 unmarshalDepth int } // NewDecoder creates a new XML parser reading from r. +// If r does not implement io.ByteReader, NewDecoder will +// do its own buffering. func NewDecoder(r io.Reader) *Decoder { d := &Decoder{ ns: make(map[string]string), @@ -857,9 +860,17 @@ func (d *Decoder) getc() (b byte, ok bool) { if b == '\n' { d.line++ } + d.offset++ return b, true } +// InputOffset returns the input stream byte offset of the current decoder position. +// The offset gives the location of the end of the most recently returned token +// and the beginning of the next token. +func (d *Decoder) InputOffset() int64 { + return d.offset +} + // Return saved offset. // If we did ungetc (nextByte >= 0), have to back up one. func (d *Decoder) savedOffset() int { @@ -889,6 +900,7 @@ func (d *Decoder) ungetc(b byte) { d.line-- } d.nextByte = int(b) + d.offset-- } var entity = map[string]int{ diff --git a/libgo/go/encoding/xml/xml_test.go b/libgo/go/encoding/xml/xml_test.go index 7723ab1c9f..be995c0d52 100644 --- a/libgo/go/encoding/xml/xml_test.go +++ b/libgo/go/encoding/xml/xml_test.go @@ -170,7 +170,7 @@ var xmlInput = []string{ func TestRawToken(t *testing.T) { d := NewDecoder(strings.NewReader(testInput)) d.Entity = testEntity - testRawToken(t, d, rawTokens) + testRawToken(t, d, testInput, rawTokens) } const nonStrictInput = ` @@ -225,7 +225,7 @@ var nonStrictTokens = []Token{ func TestNonStrictRawToken(t *testing.T) { d := NewDecoder(strings.NewReader(nonStrictInput)) d.Strict = false - testRawToken(t, d, nonStrictTokens) + testRawToken(t, d, nonStrictInput, nonStrictTokens) } type downCaser struct { @@ -254,7 +254,7 @@ func TestRawTokenAltEncoding(t *testing.T) { } return &downCaser{t, input.(io.ByteReader)}, nil } - testRawToken(t, d, rawTokensAltEncoding) + testRawToken(t, d, testInputAltEncoding, rawTokensAltEncoding) } func TestRawTokenAltEncodingNoConverter(t *testing.T) { @@ -280,9 +280,12 @@ func TestRawTokenAltEncodingNoConverter(t *testing.T) { } } -func testRawToken(t *testing.T, d *Decoder, rawTokens []Token) { +func testRawToken(t *testing.T, d *Decoder, raw string, rawTokens []Token) { + lastEnd := int64(0) for i, want := range rawTokens { + start := d.InputOffset() have, err := d.RawToken() + end := d.InputOffset() if err != nil { t.Fatalf("token %d: unexpected error: %s", i, err) } @@ -300,6 +303,26 @@ func testRawToken(t *testing.T, d *Decoder, rawTokens []Token) { } t.Errorf("token %d = %s, want %s", i, shave, swant) } + + // Check that InputOffset returned actual token. + switch { + case start < lastEnd: + t.Errorf("token %d: position [%d,%d) for %T is before previous token", i, start, end, have) + case start >= end: + // Special case: EndElement can be synthesized. + if start == end && end == lastEnd { + break + } + t.Errorf("token %d: position [%d,%d) for %T is empty", i, start, end, have) + case end > int64(len(raw)): + t.Errorf("token %d: position [%d,%d) for %T extends beyond input", i, start, end, have) + default: + text := raw[start:end] + if strings.ContainsAny(text, "<>") && (!strings.HasPrefix(text, "<") || !strings.HasSuffix(text, ">")) { + t.Errorf("token %d: misaligned raw token %#q for %T", i, text, have) + } + } + lastEnd = end } } diff --git a/libgo/go/expvar/expvar.go b/libgo/go/expvar/expvar.go index b06599505f..9b6dab487c 100644 --- a/libgo/go/expvar/expvar.go +++ b/libgo/go/expvar/expvar.go @@ -29,6 +29,7 @@ import ( "net/http" "os" "runtime" + "sort" "strconv" "sync" ) @@ -40,8 +41,8 @@ type Var interface { // Int is a 64-bit integer variable that satisfies the Var interface. type Int struct { - i int64 mu sync.RWMutex + i int64 } func (v *Int) String() string { @@ -64,8 +65,8 @@ func (v *Int) Set(value int64) { // Float is a 64-bit float variable that satisfies the Var interface. type Float struct { - f float64 mu sync.RWMutex + f float64 } func (v *Float) String() string { @@ -90,8 +91,9 @@ func (v *Float) Set(value float64) { // Map is a string-to-Var map variable that satisfies the Var interface. type Map struct { - m map[string]Var - mu sync.RWMutex + mu sync.RWMutex + m map[string]Var + keys []string // sorted } // KeyValue represents a single entry in a Map. @@ -106,13 +108,13 @@ func (v *Map) String() string { var b bytes.Buffer fmt.Fprintf(&b, "{") first := true - for key, val := range v.m { + v.doLocked(func(kv KeyValue) { if !first { fmt.Fprintf(&b, ", ") } - fmt.Fprintf(&b, "\"%s\": %v", key, val) + fmt.Fprintf(&b, "%q: %v", kv.Key, kv.Value) first = false - } + }) fmt.Fprintf(&b, "}") return b.String() } @@ -122,6 +124,20 @@ func (v *Map) Init() *Map { return v } +// updateKeys updates the sorted list of keys in v.keys. +// must be called with v.mu held. +func (v *Map) updateKeys() { + if len(v.m) == len(v.keys) { + // No new key. + return + } + v.keys = v.keys[:0] + for k := range v.m { + v.keys = append(v.keys, k) + } + sort.Strings(v.keys) +} + func (v *Map) Get(key string) Var { v.mu.RLock() defer v.mu.RUnlock() @@ -132,6 +148,7 @@ func (v *Map) Set(key string, av Var) { v.mu.Lock() defer v.mu.Unlock() v.m[key] = av + v.updateKeys() } func (v *Map) Add(key string, delta int64) { @@ -141,9 +158,11 @@ func (v *Map) Add(key string, delta int64) { if !ok { // check again under the write lock v.mu.Lock() - if _, ok = v.m[key]; !ok { + av, ok = v.m[key] + if !ok { av = new(Int) v.m[key] = av + v.updateKeys() } v.mu.Unlock() } @@ -162,9 +181,11 @@ func (v *Map) AddFloat(key string, delta float64) { if !ok { // check again under the write lock v.mu.Lock() - if _, ok = v.m[key]; !ok { + av, ok = v.m[key] + if !ok { av = new(Float) v.m[key] = av + v.updateKeys() } v.mu.Unlock() } @@ -181,15 +202,21 @@ func (v *Map) AddFloat(key string, delta float64) { func (v *Map) Do(f func(KeyValue)) { v.mu.RLock() defer v.mu.RUnlock() - for k, v := range v.m { - f(KeyValue{k, v}) + v.doLocked(f) +} + +// doLocked calls f for each entry in the map. +// v.mu must be held for reads. +func (v *Map) doLocked(f func(KeyValue)) { + for _, k := range v.keys { + f(KeyValue{k, v.m[k]}) } } // String is a string variable, and satisfies the Var interface. type String struct { - s string mu sync.RWMutex + s string } func (v *String) String() string { @@ -215,8 +242,9 @@ func (f Func) String() string { // All published variables. var ( - mutex sync.RWMutex - vars map[string]Var = make(map[string]Var) + mutex sync.RWMutex + vars = make(map[string]Var) + varKeys []string // sorted ) // Publish declares a named exported variable. This should be called from a @@ -229,6 +257,8 @@ func Publish(name string, v Var) { log.Panicln("Reuse of exported var name:", name) } vars[name] = v + varKeys = append(varKeys, name) + sort.Strings(varKeys) } // Get retrieves a named exported variable. @@ -270,8 +300,8 @@ func NewString(name string) *String { func Do(f func(KeyValue)) { mutex.RLock() defer mutex.RUnlock() - for k, v := range vars { - f(KeyValue{k, v}) + for _, k := range varKeys { + f(KeyValue{k, vars[k]}) } } diff --git a/libgo/go/expvar/expvar_test.go b/libgo/go/expvar/expvar_test.go index 572c62beed..765e3b757e 100644 --- a/libgo/go/expvar/expvar_test.go +++ b/libgo/go/expvar/expvar_test.go @@ -5,7 +5,10 @@ package expvar import ( + "bytes" "encoding/json" + "net/http/httptest" + "strconv" "testing" ) @@ -15,6 +18,7 @@ func RemoveAll() { mutex.Lock() defer mutex.Unlock() vars = make(map[string]Var) + varKeys = nil } func TestInt(t *testing.T) { @@ -93,15 +97,15 @@ func TestMapCounter(t *testing.T) { colors.Add("red", 1) colors.Add("red", 2) colors.Add("blue", 4) - colors.AddFloat("green", 4.125) + colors.AddFloat(`green "midori"`, 4.125) if x := colors.m["red"].(*Int).i; x != 3 { t.Errorf("colors.m[\"red\"] = %v, want 3", x) } if x := colors.m["blue"].(*Int).i; x != 4 { t.Errorf("colors.m[\"blue\"] = %v, want 4", x) } - if x := colors.m["green"].(*Float).f; x != 4.125 { - t.Errorf("colors.m[\"green\"] = %v, want 3.14", x) + if x := colors.m[`green "midori"`].(*Float).f; x != 4.125 { + t.Errorf("colors.m[`green \"midori\"] = %v, want 3.14", x) } // colors.String() should be '{"red":3, "blue":4}', @@ -139,3 +143,25 @@ func TestFunc(t *testing.T) { t.Errorf(`f.String() = %q, want %q`, s, exp) } } + +func TestHandler(t *testing.T) { + RemoveAll() + m := NewMap("map1") + m.Add("a", 1) + m.Add("z", 2) + m2 := NewMap("map2") + for i := 0; i < 9; i++ { + m2.Add(strconv.Itoa(i), int64(i)) + } + rr := httptest.NewRecorder() + rr.Body = new(bytes.Buffer) + expvarHandler(rr, nil) + want := `{ +"map1": {"a": 1, "z": 2}, +"map2": {"0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8} +} +` + if got := rr.Body.String(); got != want { + t.Errorf("HTTP handler wrote:\n%s\nWant:\n%s", got, want) + } +} diff --git a/libgo/go/flag/flag.go b/libgo/go/flag/flag.go index e7c863ee92..60aef5d806 100644 --- a/libgo/go/flag/flag.go +++ b/libgo/go/flag/flag.go @@ -50,7 +50,8 @@ ("-" is a non-flag argument) or after the terminator "--". Integer flags accept 1234, 0664, 0x1234 and may be negative. - Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False. + Boolean flags may be: + 1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False Duration flags accept any input valid for time.ParseDuration. The default set of command-line flags is controlled by @@ -72,7 +73,8 @@ import ( "time" ) -// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined. +// ErrHelp is the error returned if the -help or -h flag is invoked +// but no such flag is defined. var ErrHelp = errors.New("flag: help requested") // -- bool Value @@ -269,7 +271,6 @@ type FlagSet struct { actual map[string]*Flag formal map[string]*Flag args []string // arguments after flags - exitOnError bool // does the program exit if there's an error? errorHandling ErrorHandling output io.Writer // nil means stderr; use out() accessor } @@ -405,6 +406,7 @@ func defaultUsage(f *FlagSet) { // for how to write your own usage function. // Usage prints to standard error a usage message documenting all defined command-line flags. +// It is called when an error occurs while parsing flags. // The function is a variable that may be changed to point to a custom function. var Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) @@ -628,18 +630,21 @@ func Float64(name string, value float64, usage string) *float64 { // DurationVar defines a time.Duration flag with specified name, default value, and usage string. // The argument p points to a time.Duration variable in which to store the value of the flag. +// The flag accepts a value acceptable to time.ParseDuration. func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) { f.Var(newDurationValue(value, p), name, usage) } // DurationVar defines a time.Duration flag with specified name, default value, and usage string. // The argument p points to a time.Duration variable in which to store the value of the flag. +// The flag accepts a value acceptable to time.ParseDuration. func DurationVar(p *time.Duration, name string, value time.Duration, usage string) { CommandLine.Var(newDurationValue(value, p), name, usage) } // Duration defines a time.Duration flag with specified name, default value, and usage string. // The return value is the address of a time.Duration variable that stores the value of the flag. +// The flag accepts a value acceptable to time.ParseDuration. func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration { p := new(time.Duration) f.DurationVar(p, name, value, usage) @@ -648,6 +653,7 @@ func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time // Duration defines a time.Duration flag with specified name, default value, and usage string. // The return value is the address of a time.Duration variable that stores the value of the flag. +// The flag accepts a value acceptable to time.ParseDuration. func Duration(name string, value time.Duration, usage string) *time.Duration { return CommandLine.Duration(name, value, usage) } @@ -697,13 +703,15 @@ func (f *FlagSet) failf(format string, a ...interface{}) error { return err } -// usage calls the Usage method for the flag set, or the usage function if -// the flag set is CommandLine. +// usage calls the Usage method for the flag set if one is specified, +// or the appropriate default usage function otherwise. func (f *FlagSet) usage() { - if f == CommandLine { - Usage() - } else if f.Usage == nil { - defaultUsage(f) + if f.Usage == nil { + if f == CommandLine { + Usage() + } else { + defaultUsage(f) + } } else { f.Usage() } @@ -752,10 +760,11 @@ func (f *FlagSet) parseOne() (bool, error) { } return false, f.failf("flag provided but not defined: -%s", name) } + if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg if has_value { if err := fv.Set(value); err != nil { - return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err) + return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err) } } else { fv.Set("true") @@ -784,7 +793,7 @@ func (f *FlagSet) parseOne() (bool, error) { // Parse parses flag definitions from the argument list, which should not // include the command name. Must be called after all flags in the FlagSet // are defined and before flags are accessed by the program. -// The return value will be ErrHelp if -help was set but not defined. +// The return value will be ErrHelp if -help or -h were set but not defined. func (f *FlagSet) Parse(arguments []string) error { f.parsed = true f.args = arguments @@ -826,7 +835,7 @@ func Parsed() bool { } // CommandLine is the default set of command-line flags, parsed from os.Args. -// The top-level functions such as BoolVar, Arg, and on are wrappers for the +// The top-level functions such as BoolVar, Arg, and so on are wrappers for the // methods of CommandLine. var CommandLine = NewFlagSet(os.Args[0], ExitOnError) diff --git a/libgo/go/flag/flag_test.go b/libgo/go/flag/flag_test.go index 2c03872697..8c88c8c274 100644 --- a/libgo/go/flag/flag_test.go +++ b/libgo/go/flag/flag_test.go @@ -251,6 +251,16 @@ func TestUserDefined(t *testing.T) { } } +func TestUserDefinedForCommandLine(t *testing.T) { + const help = "HELP" + var result string + ResetForTesting(func() { result = help }) + Usage() + if result != help { + t.Fatalf("got %q; expected %q", result, help) + } +} + // Declare a user-defined boolean flag type. type boolFlagVar struct { count int diff --git a/libgo/go/fmt/doc.go b/libgo/go/fmt/doc.go index 095fd03b23..ee54463e27 100644 --- a/libgo/go/fmt/doc.go +++ b/libgo/go/fmt/doc.go @@ -13,7 +13,7 @@ The verbs: General: - %v the value in a default format. + %v the value in a default format when printing structs, the plus flag (%+v) adds field names %#v a Go-syntax representation of the value %T a Go-syntax representation of the type of the value @@ -37,8 +37,9 @@ %e scientific notation, e.g. -1234.456e+78 %E scientific notation, e.g. -1234.456E+78 %f decimal point but no exponent, e.g. 123.456 - %g whichever of %e or %f produces more compact output - %G whichever of %E or %f produces more compact output + %F synonym for %f + %g %e for large exponents, %f otherwise + %G %E for large exponents, %F otherwise String and slice of bytes: %s the uninterpreted bytes of the string or slice %q a double-quoted string safely escaped with Go syntax @@ -50,23 +51,58 @@ There is no 'u' flag. Integers are printed unsigned if they have unsigned type. Similarly, there is no need to specify the size of the operand (int8, int64). - The width and precision control formatting and are in units of Unicode - code points. (This differs from C's printf where the units are numbers - of bytes.) Either or both of the flags may be replaced with the - character '*', causing their values to be obtained from the next - operand, which must be of type int. + The default format for %v is: + bool: %t + int, int8 etc.: %d + uint, uint8 etc.: %d, %x if printed with %#v + float32, complex64, etc: %g + string: %s + chan: %p + pointer: %p + For compound objects, the elements are printed using these rules, recursively, + laid out like this: + struct: {field0 field1 ...} + array, slice: [elem0 elem1 ...] + maps: map[key1:value1 key2:value2] + pointer to above: &{}, &[], &map[] + + Width is specified by an optional decimal number immediately following the verb. + If absent, the width is whatever is necessary to represent the value. + Precision is specified after the (optional) width by a period followed by a + decimal number. If no period is present, a default precision is used. + A period with no following number specifies a precision of zero. + Examples: + %f: default width, default precision + %9f width 9, default precision + %.2f default width, precision 2 + %9.2f width 9, precision 2 + %9.f width 9, precision 0 + + Width and precision are measured in units of Unicode code points, + that is, runes. (This differs from C's printf where the + units are always measured in bytes.) Either or both of the flags + may be replaced with the character '*', causing their values to be + obtained from the next operand, which must be of type int. + + For most values, width is the minimum number of runes to output, + padding the formatted form with spaces if necessary. + + For strings, byte slices and byte arrays, however, precision + limits the length of the input to be formatted (not the size of + the output), truncating if necessary. Normally it is measured in + runes, but for these types when formatted with the %x or %X format + it is measured in bytes. - For numeric values, width sets the minimum width of the field and + For floating-point values, width sets the minimum width of the field and precision sets the number of places after the decimal, if appropriate, except that for %g/%G it sets the total number of digits. For example, given 123.45 the format %6.2f prints 123.45 while %.4g prints 123.5. The default precision for %e and %f is 6; for %g it is the smallest number of digits necessary to identify the value uniquely. - For most values, width is the minimum number of characters to output, - padding the formatted form with spaces if necessary. - For strings, precision is the maximum number of characters to output, - truncating if necessary. + For complex numbers, the width and precision apply to the two + components independently and the result is parenthesized, so %f applied + to 1.2+3.4i produces (1.200000+3.400000i). Other flags: + always print a sign for numeric values; @@ -98,25 +134,42 @@ fmt.Printf("%v\n", i) will print 23. - If an operand implements interface Formatter, that interface - can be used for fine control of formatting. + Except when printed using the verbs %T and %p, special + formatting considerations apply for operands that implement + certain interfaces. In order of application: + + 1. If an operand implements the Formatter interface, it will + be invoked. Formatter provides fine control of formatting. + + 2. If the %v verb is used with the # flag (%#v) and the operand + implements the GoStringer interface, that will be invoked. If the format (which is implicitly %v for Println etc.) is valid - for a string (%s %q %v %x %X), the following two rules also apply: + for a string (%s %q %v %x %X), the following two rules apply: - 1. If an operand implements the error interface, the Error method - will be used to convert the object to a string, which will then + 3. If an operand implements the error interface, the Error method + will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any). - 2. If an operand implements method String() string, that method - will be used to convert the object to a string, which will then + 4. If an operand implements method String() string, that method + will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any). + For compound operands such as slices and structs, the format + applies to the elements of each operand, recursively, not to the + operand as a whole. Thus %q will quote each element of a slice + of strings, and %6.2f will control formatting for each element + of a floating-point array. + To avoid recursion in cases such as type X string func (x X) String() string { return Sprintf("<%s>", x) } convert the value before recurring: func (x X) String() string { return Sprintf("<%s>", string(x)) } + Infinite recursion can also be triggered by self-referential data + structures, such as a slice that contains itself as an element, if + that type has a String method. Such pathologies are rare, however, + and the package does not protect against them. Explicit argument indexes: @@ -130,7 +183,7 @@ For example, fmt.Sprintf("%[2]d %[1]d\n", 11, 22) - will yield "22, 11", while + will yield "22 11", while fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6), equivalent to fmt.Sprintf("%6.2f", 12.0), diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go index bbca2c574b..ccd8090477 100644 --- a/libgo/go/fmt/fmt_test.go +++ b/libgo/go/fmt/fmt_test.go @@ -108,6 +108,20 @@ func (p *P) String() string { var barray = [5]renamedUint8{1, 2, 3, 4, 5} var bslice = barray[:] +type byteStringer byte + +func (byteStringer) String() string { return "X" } + +var byteStringerSlice = []byteStringer{97, 98, 99, 100} + +type byteFormatter byte + +func (byteFormatter) Format(f State, _ rune) { + Fprint(f, "X") +} + +var byteFormatterSlice = []byteFormatter{97, 98, 99, 100} + var b byte var fmtTests = []struct { @@ -125,13 +139,17 @@ var fmtTests = []struct { {"%x", "xyz", "78797a"}, {"%X", "xyz", "78797A"}, {"%q", "abc", `"abc"`}, + {"%#x", []byte("abc\xff"), "0x616263ff"}, + {"%#X", []byte("abc\xff"), "0X616263FF"}, + {"%# x", []byte("abc\xff"), "0x61 0x62 0x63 0xff"}, + {"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"}, // basic bytes {"%s", []byte("abc"), "abc"}, {"%x", []byte("abc"), "616263"}, {"% x", []byte("abc\xff"), "61 62 63 ff"}, - {"%#x", []byte("abc\xff"), "0x610x620x630xff"}, - {"%#X", []byte("abc\xff"), "0X610X620X630XFF"}, + {"%#x", []byte("abc\xff"), "0x616263ff"}, + {"%#X", []byte("abc\xff"), "0X616263FF"}, {"%# x", []byte("abc\xff"), "0x61 0x62 0x63 0xff"}, {"%# X", []byte("abc\xff"), "0X61 0X62 0X63 0XFF"}, {"% X", []byte("abc\xff"), "61 62 63 FF"}, @@ -176,9 +194,18 @@ var fmtTests = []struct { {"%.5s", "日本語日本語", "日本語日本"}, {"%.5s", []byte("日本語日本語"), "日本語日本"}, {"%.5q", "abcdefghijklmnopqrstuvwxyz", `"abcde"`}, + {"%.5x", "abcdefghijklmnopqrstuvwxyz", `6162636465`}, + {"%.5q", []byte("abcdefghijklmnopqrstuvwxyz"), `"abcde"`}, + {"%.5x", []byte("abcdefghijklmnopqrstuvwxyz"), `6162636465`}, {"%.3q", "日本語日本語", `"日本語"`}, {"%.3q", []byte("日本語日本語"), `"日本語"`}, + {"%.1q", "日本語", `"日"`}, + {"%.1q", []byte("日本語"), `"日"`}, + {"%.1x", "日本語", `e6`}, + {"%.1X", []byte("日本語"), `E6`}, {"%10.1q", "日本語日本語", ` "日"`}, + {"%3c", '⌘', " ⌘"}, + {"%5q", '\u2026', ` '…'`}, {"%10v", nil, " "}, {"%-10v", nil, " "}, @@ -220,6 +247,12 @@ var fmtTests = []struct { {"%+.3e", 0.0, "+0.000e+00"}, {"%+.3e", 1.0, "+1.000e+00"}, {"%+.3f", -1.0, "-1.000"}, + {"%+.3F", -1.0, "-1.000"}, + {"%+.3F", float32(-1.0), "-1.000"}, + {"%+07.2f", 1.0, "+001.00"}, + {"%+07.2f", -1.0, "-001.00"}, + {"%+10.2f", +1.0, " +1.00"}, + {"%+10.2f", -1.0, " -1.00"}, {"% .3E", -1.0, "-1.000E+00"}, {"% .3e", 1.0, " 1.000e+00"}, {"%+.3g", 0.0, "+0"}, @@ -239,6 +272,8 @@ var fmtTests = []struct { {"%+.3g", 1 + 2i, "(+1+2i)"}, {"%.3e", 0i, "(0.000e+00+0.000e+00i)"}, {"%.3f", 0i, "(0.000+0.000i)"}, + {"%.3F", 0i, "(0.000+0.000i)"}, + {"%.3F", complex64(0i), "(0.000+0.000i)"}, {"%.3g", 0i, "(0+0i)"}, {"%.3e", 1 + 2i, "(1.000e+00+2.000e+00i)"}, {"%.3f", 1 + 2i, "(1.000+2.000i)"}, @@ -371,7 +406,7 @@ var fmtTests = []struct { {"%s", I(23), `<23>`}, {"%q", I(23), `"<23>"`}, {"%x", I(23), `3c32333e`}, - {"%#x", I(23), `0x3c0x320x330x3e`}, + {"%#x", I(23), `0x3c32333e`}, {"%# x", I(23), `0x3c 0x32 0x33 0x3e`}, {"%d", I(23), `23`}, // Stringer applies only to string formats. @@ -397,6 +432,8 @@ var fmtTests = []struct { {"%#v", "foo", `"foo"`}, {"%#v", barray, `[5]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`}, {"%#v", bslice, `[]fmt_test.renamedUint8{0x1, 0x2, 0x3, 0x4, 0x5}`}, + {"%#v", []byte(nil), "[]byte(nil)"}, + {"%#v", []int32(nil), "[]int32(nil)"}, // slices with other formats {"%#x", []int{1, 2, 15}, `[0x1 0x2 0xf]`}, @@ -495,18 +532,85 @@ var fmtTests = []struct { {"%v", map[float64]int{math.NaN(): 1, math.NaN(): 2}, "map[NaN: NaN:]"}, // Used to crash because nByte didn't allow for a sign. - {"%b", int64(-1 << 63), "-1000000000000000000000000000000000000000000000000000000000000000"}, + {"%b", int64(-1 << 63), zeroFill("-1", 63, "")}, // Used to panic. - {"%0100d", 1, "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"}, - {"%0100d", -1, "-000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"}, - {"%0.100f", 1.0, "1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, - {"%0.100f", -1.0, "-1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, + {"%0100d", 1, zeroFill("", 100, "1")}, + {"%0100d", -1, zeroFill("-", 99, "1")}, + {"%0.100f", 1.0, zeroFill("1.", 100, "")}, + {"%0.100f", -1.0, zeroFill("-1.", 100, "")}, + + // Comparison of padding rules with C printf. + /* + C program: + #include + + char *format[] = { + "[%.2f]", + "[% .2f]", + "[%+.2f]", + "[%7.2f]", + "[% 7.2f]", + "[%+7.2f]", + "[%07.2f]", + "[% 07.2f]", + "[%+07.2f]", + }; + + int main(void) { + int i; + for(i = 0; i < 9; i++) { + printf("%s: ", format[i]); + printf(format[i], 1.0); + printf(" "); + printf(format[i], -1.0); + printf("\n"); + } + } - // Zero padding floats used to put the minus sign in the middle. - {"%020f", -1.0, "-000000000001.000000"}, + Output: + [%.2f]: [1.00] [-1.00] + [% .2f]: [ 1.00] [-1.00] + [%+.2f]: [+1.00] [-1.00] + [%7.2f]: [ 1.00] [ -1.00] + [% 7.2f]: [ 1.00] [ -1.00] + [%+7.2f]: [ +1.00] [ -1.00] + [%07.2f]: [0001.00] [-001.00] + [% 07.2f]: [ 001.00] [-001.00] + [%+07.2f]: [+001.00] [-001.00] + */ + {"%.2f", 1.0, "1.00"}, + {"%.2f", -1.0, "-1.00"}, + {"% .2f", 1.0, " 1.00"}, + {"% .2f", -1.0, "-1.00"}, + {"%+.2f", 1.0, "+1.00"}, + {"%+.2f", -1.0, "-1.00"}, + {"%7.2f", 1.0, " 1.00"}, + {"%7.2f", -1.0, " -1.00"}, + {"% 7.2f", 1.0, " 1.00"}, + {"% 7.2f", -1.0, " -1.00"}, + {"%+7.2f", 1.0, " +1.00"}, + {"%+7.2f", -1.0, " -1.00"}, + {"%07.2f", 1.0, "0001.00"}, + {"%07.2f", -1.0, "-001.00"}, + {"% 07.2f", 1.0, " 001.00"}, + {"% 07.2f", -1.0, "-001.00"}, + {"%+07.2f", 1.0, "+001.00"}, + {"%+07.2f", -1.0, "-001.00"}, + + // Complex numbers: exhaustively tested in TestComplexFormatting. + {"%7.2f", 1 + 2i, "( 1.00 +2.00i)"}, + {"%+07.2f", -1 - 2i, "(-001.00-002.00i)"}, + // Zero padding does not apply to infinities. + {"%020f", math.Inf(-1), " -Inf"}, + {"%020f", math.Inf(+1), " +Inf"}, + {"% 020f", math.Inf(-1), " -Inf"}, + {"% 020f", math.Inf(+1), " Inf"}, + {"%+020f", math.Inf(-1), " -Inf"}, + {"%+020f", math.Inf(+1), " +Inf"}, {"%20f", -1.0, " -1.000000"}, - {"%0100f", -1.0, "-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.000000"}, + // Make sure we can handle very large widths. + {"%0100f", -1.0, zeroFill("-", 99, "1.000000")}, // Complex fmt used to leave the plus flag set for future entries in the array // causing +2+0i and +3+0i instead of 2+0i and 3+0i. @@ -515,6 +619,58 @@ var fmtTests = []struct { // Incomplete format specification caused crash. {"%.", 3, "%!.(int=3)"}, + + // Used to panic with out-of-bounds for very large numeric representations. + // nByte is set to handle one bit per uint64 in %b format, with a negative number. + // See issue 6777. + {"%#064x", 1, zeroFill("0x", 64, "1")}, + {"%#064x", -1, zeroFill("-0x", 63, "1")}, + {"%#064b", 1, zeroFill("", 64, "1")}, + {"%#064b", -1, zeroFill("-", 63, "1")}, + {"%#064o", 1, zeroFill("", 64, "1")}, + {"%#064o", -1, zeroFill("-", 63, "1")}, + {"%#064d", 1, zeroFill("", 64, "1")}, + {"%#064d", -1, zeroFill("-", 63, "1")}, + // Test that we handle the crossover above the size of uint64 + {"%#072x", 1, zeroFill("0x", 72, "1")}, + {"%#072x", -1, zeroFill("-0x", 71, "1")}, + {"%#072b", 1, zeroFill("", 72, "1")}, + {"%#072b", -1, zeroFill("-", 71, "1")}, + {"%#072o", 1, zeroFill("", 72, "1")}, + {"%#072o", -1, zeroFill("-", 71, "1")}, + {"%#072d", 1, zeroFill("", 72, "1")}, + {"%#072d", -1, zeroFill("-", 71, "1")}, + + // Padding for complex numbers. Has been bad, then fixed, then bad again. + {"%+10.2f", +104.66 + 440.51i, "( +104.66 +440.51i)"}, + {"%+10.2f", -104.66 + 440.51i, "( -104.66 +440.51i)"}, + {"%+10.2f", +104.66 - 440.51i, "( +104.66 -440.51i)"}, + {"%+10.2f", -104.66 - 440.51i, "( -104.66 -440.51i)"}, + {"%+010.2f", +104.66 + 440.51i, "(+000104.66+000440.51i)"}, + {"%+010.2f", -104.66 + 440.51i, "(-000104.66+000440.51i)"}, + {"%+010.2f", +104.66 - 440.51i, "(+000104.66-000440.51i)"}, + {"%+010.2f", -104.66 - 440.51i, "(-000104.66-000440.51i)"}, + + // []T where type T is a byte with a Stringer method. + {"%v", byteStringerSlice, "[X X X X]"}, + {"%s", byteStringerSlice, "abcd"}, + {"%q", byteStringerSlice, "\"abcd\""}, + {"%x", byteStringerSlice, "61626364"}, + {"%#v", byteStringerSlice, "[]fmt_test.byteStringer{0x61, 0x62, 0x63, 0x64}"}, + + // And the same for Formatter. + {"%v", byteFormatterSlice, "[X X X X]"}, + {"%s", byteFormatterSlice, "abcd"}, + {"%q", byteFormatterSlice, "\"abcd\""}, + {"%x", byteFormatterSlice, "61626364"}, + // This next case seems wrong, but the docs say the Formatter wins here. + {"%#v", byteFormatterSlice, "[]fmt_test.byteFormatter{X, X, X, X}"}, +} + +// zeroFill generates zero-filled strings of the specified width. The length +// of the suffix (but not the prefix) is compensated for in the width calculation. +func zeroFill(prefix string, width int, suffix string) string { + return prefix + strings.Repeat("0", width-len(suffix)) + suffix } func TestSprintf(t *testing.T) { @@ -554,6 +710,50 @@ func TestSprintf(t *testing.T) { } } +// TestComplexFormatting checks that a complex always formats to the same +// thing as if done by hand with two singleton prints. +func TestComplexFormatting(t *testing.T) { + var yesNo = []bool{true, false} + var values = []float64{1, 0, -1, math.Inf(1), math.Inf(-1), math.NaN()} + for _, plus := range yesNo { + for _, zero := range yesNo { + for _, space := range yesNo { + for _, char := range "fFeEgG" { + realFmt := "%" + if zero { + realFmt += "0" + } + if space { + realFmt += " " + } + if plus { + realFmt += "+" + } + realFmt += "10.2" + realFmt += string(char) + // Imaginary part always has a sign, so force + and ignore space. + imagFmt := "%" + if zero { + imagFmt += "0" + } + imagFmt += "+" + imagFmt += "10.2" + imagFmt += string(char) + for _, realValue := range values { + for _, imagValue := range values { + one := Sprintf(realFmt, complex(realValue, imagValue)) + two := Sprintf("("+realFmt+imagFmt+"i)", realValue, imagValue) + if one != two { + t.Error(f, one, two) + } + } + } + } + } + } + } +} + type SE []interface{} // slice of empty; notational compactness. var reorderTests = []struct { @@ -604,50 +804,82 @@ func TestReorder(t *testing.T) { } func BenchmarkSprintfEmpty(b *testing.B) { - for i := 0; i < b.N; i++ { - Sprintf("") - } + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("") + } + }) } func BenchmarkSprintfString(b *testing.B) { - for i := 0; i < b.N; i++ { - Sprintf("%s", "hello") - } + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("%s", "hello") + } + }) } func BenchmarkSprintfInt(b *testing.B) { - for i := 0; i < b.N; i++ { - Sprintf("%d", 5) - } + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("%d", 5) + } + }) } func BenchmarkSprintfIntInt(b *testing.B) { - for i := 0; i < b.N; i++ { - Sprintf("%d %d", 5, 6) - } + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("%d %d", 5, 6) + } + }) } func BenchmarkSprintfPrefixedInt(b *testing.B) { - for i := 0; i < b.N; i++ { - Sprintf("This is some meaningless prefix text that needs to be scanned %d", 6) - } + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("This is some meaningless prefix text that needs to be scanned %d", 6) + } + }) } func BenchmarkSprintfFloat(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + Sprintf("%g", 5.23184) + } + }) +} + +func BenchmarkManyArgs(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + var buf bytes.Buffer + for pb.Next() { + buf.Reset() + Fprintf(&buf, "%2d/%2d/%2d %d:%d:%d %s %s\n", 3, 4, 5, 11, 12, 13, "hello", "world") + } + }) +} + +func BenchmarkFprintInt(b *testing.B) { + var buf bytes.Buffer for i := 0; i < b.N; i++ { - Sprintf("%g", 5.23184) + buf.Reset() + Fprint(&buf, 123456) } } -func BenchmarkManyArgs(b *testing.B) { +func BenchmarkFprintIntNoAlloc(b *testing.B) { + var x interface{} = 123456 var buf bytes.Buffer for i := 0; i < b.N; i++ { buf.Reset() - Fprintf(&buf, "%2d/%2d/%2d %d:%d:%d %s %s\n", 3, 4, 5, 11, 12, 13, "hello", "world") + Fprint(&buf, x) } } var mallocBuf bytes.Buffer +var mallocPointer *int // A pointer so we know the interface value won't allocate. // gccgo numbers are different because gccgo does not have escape // analysis yet. @@ -661,11 +893,13 @@ var mallocTest = []struct { {5, `Sprintf("%x")`, func() { Sprintf("%x", 7) }}, {5, `Sprintf("%s")`, func() { Sprintf("%s", "hello") }}, {5, `Sprintf("%x %x")`, func() { Sprintf("%x %x", 7, 112) }}, - // For %g we use a float32, not float64, to guarantee passing the argument - // does not need to allocate memory to store the result in a pointer-sized word. - {20, `Sprintf("%g")`, func() { Sprintf("%g", float32(3.14159)) }}, - {5, `Fprintf(buf, "%x %x %x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x %x %x", 7, 8, 9) }}, + {20, `Sprintf("%g")`, func() { Sprintf("%g", float32(3.14159)) }}, // TODO: Can this be 1? {5, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%s", "hello") }}, + // If the interface value doesn't need to allocate, amortized allocation overhead should be zero. + {5, `Fprintf(buf, "%x %x %x")`, func() { + mallocBuf.Reset() + Fprintf(&mallocBuf, "%x %x %x", mallocPointer, mallocPointer, mallocPointer) + }}, } var _ bytes.Buffer @@ -687,7 +921,7 @@ func TestCountMallocs(t *testing.T) { type flagPrinter struct{} -func (*flagPrinter) Format(f State, c rune) { +func (flagPrinter) Format(f State, c rune) { s := "%" for i := 0; i < 128; i++ { if f.Flag(i) { @@ -733,11 +967,12 @@ func TestFlagParser(t *testing.T) { } func TestStructPrinter(t *testing.T) { - var s struct { + type T struct { a string b string c int } + var s T s.a = "abc" s.b = "def" s.c = 123 @@ -747,15 +982,38 @@ func TestStructPrinter(t *testing.T) { }{ {"%v", "{abc def 123}"}, {"%+v", "{a:abc b:def c:123}"}, + {"%#v", `fmt_test.T{a:"abc", b:"def", c:123}`}, } for _, tt := range tests { out := Sprintf(tt.fmt, s) if out != tt.out { - t.Errorf("Sprintf(%q, &s) = %q, want %q", tt.fmt, out, tt.out) + t.Errorf("Sprintf(%q, s) = %#q, want %#q", tt.fmt, out, tt.out) + } + // The same but with a pointer. + out = Sprintf(tt.fmt, &s) + if out != "&"+tt.out { + t.Errorf("Sprintf(%q, &s) = %#q, want %#q", tt.fmt, out, "&"+tt.out) } } } +func TestSlicePrinter(t *testing.T) { + slice := []int{} + s := Sprint(slice) + if s != "[]" { + t.Errorf("empty slice printed as %q not %q", s, "[]") + } + slice = []int{1, 2, 3} + s = Sprint(slice) + if s != "[1 2 3]" { + t.Errorf("slice: got %q expected %q", s, "[1 2 3]") + } + s = Sprint(&slice) + if s != "&[1 2 3]" { + t.Errorf("&slice: got %q expected %q", s, "&[1 2 3]") + } +} + // presentInMap checks map printing using substrings so we don't depend on the // print order. func presentInMap(s string, a []string, t *testing.T) { @@ -782,6 +1040,12 @@ func TestMapPrinter(t *testing.T) { a := []string{"1:one", "2:two", "3:three"} presentInMap(Sprintf("%v", m1), a, t) presentInMap(Sprint(m1), a, t) + // Pointer to map prints the same but with initial &. + if !strings.HasPrefix(Sprint(&m1), "&") { + t.Errorf("no initial & for address of map") + } + presentInMap(Sprintf("%v", &m1), a, t) + presentInMap(Sprint(&m1), a, t) } func TestEmptyMap(t *testing.T) { @@ -912,10 +1176,10 @@ var panictests = []struct { } func TestPanics(t *testing.T) { - for _, tt := range panictests { + for i, tt := range panictests { s := Sprintf(tt.fmt, tt.in) if s != tt.out { - t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out) + t.Errorf("%d: %q: got %q expected %q", i, tt.fmt, s, tt.out) } } } @@ -975,3 +1239,74 @@ func TestNilDoesNotBecomeTyped(t *testing.T) { t.Errorf("expected:\n\t%q\ngot:\n\t%q", expect, got) } } + +var formatterFlagTests = []struct { + in string + val interface{} + out string +}{ + // scalar values with the (unused by fmt) 'a' verb. + {"%a", flagPrinter{}, "[%a]"}, + {"%-a", flagPrinter{}, "[%-a]"}, + {"%+a", flagPrinter{}, "[%+a]"}, + {"%#a", flagPrinter{}, "[%#a]"}, + {"% a", flagPrinter{}, "[% a]"}, + {"%0a", flagPrinter{}, "[%0a]"}, + {"%1.2a", flagPrinter{}, "[%1.2a]"}, + {"%-1.2a", flagPrinter{}, "[%-1.2a]"}, + {"%+1.2a", flagPrinter{}, "[%+1.2a]"}, + {"%-+1.2a", flagPrinter{}, "[%+-1.2a]"}, + {"%-+1.2abc", flagPrinter{}, "[%+-1.2a]bc"}, + {"%-1.2abc", flagPrinter{}, "[%-1.2a]bc"}, + + // composite values with the 'a' verb + {"%a", [1]flagPrinter{}, "[[%a]]"}, + {"%-a", [1]flagPrinter{}, "[[%-a]]"}, + {"%+a", [1]flagPrinter{}, "[[%+a]]"}, + {"%#a", [1]flagPrinter{}, "[[%#a]]"}, + {"% a", [1]flagPrinter{}, "[[% a]]"}, + {"%0a", [1]flagPrinter{}, "[[%0a]]"}, + {"%1.2a", [1]flagPrinter{}, "[[%1.2a]]"}, + {"%-1.2a", [1]flagPrinter{}, "[[%-1.2a]]"}, + {"%+1.2a", [1]flagPrinter{}, "[[%+1.2a]]"}, + {"%-+1.2a", [1]flagPrinter{}, "[[%+-1.2a]]"}, + {"%-+1.2abc", [1]flagPrinter{}, "[[%+-1.2a]]bc"}, + {"%-1.2abc", [1]flagPrinter{}, "[[%-1.2a]]bc"}, + + // simple values with the 'v' verb + {"%v", flagPrinter{}, "[%v]"}, + {"%-v", flagPrinter{}, "[%-v]"}, + {"%+v", flagPrinter{}, "[%+v]"}, + {"%#v", flagPrinter{}, "[%#v]"}, + {"% v", flagPrinter{}, "[% v]"}, + {"%0v", flagPrinter{}, "[%0v]"}, + {"%1.2v", flagPrinter{}, "[%1.2v]"}, + {"%-1.2v", flagPrinter{}, "[%-1.2v]"}, + {"%+1.2v", flagPrinter{}, "[%+1.2v]"}, + {"%-+1.2v", flagPrinter{}, "[%+-1.2v]"}, + {"%-+1.2vbc", flagPrinter{}, "[%+-1.2v]bc"}, + {"%-1.2vbc", flagPrinter{}, "[%-1.2v]bc"}, + + // composite values with the 'v' verb. + {"%v", [1]flagPrinter{}, "[[%v]]"}, + {"%-v", [1]flagPrinter{}, "[[%-v]]"}, + {"%+v", [1]flagPrinter{}, "[[%+v]]"}, + {"%#v", [1]flagPrinter{}, "[1]fmt_test.flagPrinter{[%#v]}"}, + {"% v", [1]flagPrinter{}, "[[% v]]"}, + {"%0v", [1]flagPrinter{}, "[[%0v]]"}, + {"%1.2v", [1]flagPrinter{}, "[[%1.2v]]"}, + {"%-1.2v", [1]flagPrinter{}, "[[%-1.2v]]"}, + {"%+1.2v", [1]flagPrinter{}, "[[%+1.2v]]"}, + {"%-+1.2v", [1]flagPrinter{}, "[[%+-1.2v]]"}, + {"%-+1.2vbc", [1]flagPrinter{}, "[[%+-1.2v]]bc"}, + {"%-1.2vbc", [1]flagPrinter{}, "[[%-1.2v]]bc"}, +} + +func TestFormatterFlags(t *testing.T) { + for _, tt := range formatterFlagTests { + s := Sprintf(tt.in, tt.val) + if s != tt.out { + t.Errorf("Sprintf(%q, %T) = %q, want %q", tt.in, tt.val, s, tt.out) + } + } +} diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go index 2e2b0716ed..4d97d1443e 100644 --- a/libgo/go/fmt/format.go +++ b/libgo/go/fmt/format.go @@ -5,12 +5,15 @@ package fmt import ( + "math" "strconv" "unicode/utf8" ) const ( - nByte = 65 // %b of an int64, plus a sign. + // %b of an int64, plus a sign. + // Hex can add 0x and we handle it specially. + nByte = 65 ldigits = "0123456789abcdef" udigits = "0123456789ABCDEF" @@ -31,15 +34,8 @@ func init() { } } -// A fmt is the raw formatter used by Printf etc. -// It prints into a buffer that must be set up separately. -type fmt struct { - intbuf [nByte]byte - buf *buffer - // width, precision - wid int - prec int - // flags +// flags placed in a separate struct for easy clearing. +type fmtFlags struct { widPresent bool precPresent bool minus bool @@ -49,20 +45,27 @@ type fmt struct { unicode bool uniQuote bool // Use 'x'= prefix for %U if printable. zero bool + + // For the formats %+v %#v, we set the plusV/sharpV flags + // and clear the plus/sharp flags since %+v and %#v are in effect + // different, flagless formats set at the top level. + plusV bool + sharpV bool +} + +// A fmt is the raw formatter used by Printf etc. +// It prints into a buffer that must be set up separately. +type fmt struct { + intbuf [nByte]byte + buf *buffer + // width, precision + wid int + prec int + fmtFlags } func (f *fmt) clearflags() { - f.wid = 0 - f.widPresent = false - f.prec = 0 - f.precPresent = false - f.minus = false - f.plus = false - f.sharp = false - f.space = false - f.unicode = false - f.uniQuote = false - f.zero = false + f.fmtFlags = fmtFlags{} } func (f *fmt) init(buf *buffer) { @@ -111,7 +114,7 @@ func (f *fmt) pad(b []byte) { f.buf.Write(b) return } - padding, left, right := f.computePadding(len(b)) + padding, left, right := f.computePadding(utf8.RuneCount(b)) if left > 0 { f.writePadding(left, padding) } @@ -160,9 +163,16 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { } var buf []byte = f.intbuf[0:] - if f.widPresent && f.wid > nByte { - // We're going to need a bigger boat. - buf = make([]byte, f.wid) + if f.widPresent { + width := f.wid + if base == 16 && f.sharp { + // Also adds "0x". + width += 2 + } + if width > nByte { + // We're going to need a bigger boat. + buf = make([]byte, width) + } } negative := signedness == signed && a < 0 @@ -189,10 +199,36 @@ func (f *fmt) integer(a int64, base uint64, signedness bool, digits string) { // block but it's not worth the duplication, so ua has 64 bits. i := len(buf) ua := uint64(a) - for ua >= base { - i-- - buf[i] = digits[ua%base] - ua /= base + // use constants for the division and modulo for more efficient code. + // switch cases ordered by popularity. + switch base { + case 10: + for ua >= 10 { + i-- + next := ua / 10 + buf[i] = byte('0' + ua - next*10) + ua = next + } + case 16: + for ua >= 16 { + i-- + buf[i] = digits[ua&0xF] + ua >>= 4 + } + case 8: + for ua >= 8 { + i-- + buf[i] = byte('0' + ua&7) + ua >>= 3 + } + case 2: + for ua >= 2 { + i-- + buf[i] = byte('0' + ua&1) + ua >>= 1 + } + default: + panic("fmt: unknown base; can't happen") } i-- buf[i] = digits[ua] @@ -288,7 +324,7 @@ func (f *fmt) fmt_sbx(s string, b []byte, digits string) { if i > 0 && f.space { buf = append(buf, ' ') } - if f.sharp { + if f.sharp && (f.space || i == 0) { buf = append(buf, '0', x) } var c byte @@ -304,11 +340,17 @@ func (f *fmt) fmt_sbx(s string, b []byte, digits string) { // fmt_sx formats a string as a hexadecimal encoding of its bytes. func (f *fmt) fmt_sx(s, digits string) { + if f.precPresent && f.prec < len(s) { + s = s[:f.prec] + } f.fmt_sbx(s, nil, digits) } // fmt_bx formats a byte slice as a hexadecimal encoding of its bytes. func (f *fmt) fmt_bx(b []byte, digits string) { + if f.precPresent && f.prec < len(b) { + b = b[:f.prec] + } f.fmt_sbx("", b, digits) } @@ -351,35 +393,48 @@ func doPrec(f *fmt, def int) int { // formatFloat formats a float64; it is an efficient equivalent to f.pad(strconv.FormatFloat()...). func (f *fmt) formatFloat(v float64, verb byte, prec, n int) { - // We leave one byte at the beginning of f.intbuf for a sign if needed, - // and make it a space, which we might be able to use. - f.intbuf[0] = ' ' - slice := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n) - // Add a plus sign or space to the floating-point string representation if missing and required. - // The formatted number starts at slice[1]. - switch slice[1] { - case '-', '+': - // If we're zero padding, want the sign before the leading zeros. - // Achieve this by writing the sign out and padding the postive number. - if f.zero && f.widPresent && f.wid > len(slice) { - f.buf.WriteByte(slice[1]) - f.wid-- - f.pad(slice[2:]) - return + // Format number, reserving space for leading + sign if needed. + num := strconv.AppendFloat(f.intbuf[0:1], v, verb, prec, n) + if num[1] == '-' || num[1] == '+' { + num = num[1:] + } else { + num[0] = '+' + } + // Special handling for infinity, which doesn't look like a number so shouldn't be padded with zeros. + if math.IsInf(v, 0) { + if f.zero { + defer func() { f.zero = true }() + f.zero = false } - // We're set; drop the leading space. - slice = slice[1:] - default: - // There's no sign, but we might need one. - if f.plus { - slice[0] = '+' - } else if f.space { - // space is already there - } else { - slice = slice[1:] + } + // num is now a signed version of the number. + // If we're zero padding, want the sign before the leading zeros. + // Achieve this by writing the sign out and then padding the unsigned number. + if f.zero && f.widPresent && f.wid > len(num) { + if f.space && v >= 0 { + f.buf.WriteByte(' ') // This is what C does: even with zero, f.space means space. + f.wid-- + } else if f.plus || v < 0 { + f.buf.WriteByte(num[0]) + f.wid-- } + f.pad(num[1:]) + return + } + // f.space says to replace a leading + with a space. + if f.space && num[0] == '+' { + num[0] = ' ' + f.pad(num) + return + } + // Now we know the sign is attached directly to the number, if present at all. + // We want a sign if asked for, if it's negative, or if it's infinity (+Inf vs. -Inf). + if f.plus || num[0] == '-' || math.IsInf(v, 0) { + f.pad(num) + return } - f.pad(slice) + // No sign to show and the number is positive; just print the unsigned number. + f.pad(num[1:]) } // fmt_e64 formats a float64 in the form -1.23e+12. @@ -424,60 +479,46 @@ func (f *fmt) fmt_fb32(v float32) { f.formatFloat(float64(v), 'b', 0, 32) } // fmt_c64 formats a complex64 according to the verb. func (f *fmt) fmt_c64(v complex64, verb rune) { - f.buf.WriteByte('(') - r := real(v) - oldPlus := f.plus - for i := 0; ; i++ { - switch verb { - case 'b': - f.fmt_fb32(r) - case 'e': - f.fmt_e32(r) - case 'E': - f.fmt_E32(r) - case 'f': - f.fmt_f32(r) - case 'g': - f.fmt_g32(r) - case 'G': - f.fmt_G32(r) - } - if i != 0 { - break - } - f.plus = true - r = imag(v) - } - f.plus = oldPlus - f.buf.Write(irparenBytes) + f.fmt_complex(float64(real(v)), float64(imag(v)), 32, verb) } // fmt_c128 formats a complex128 according to the verb. func (f *fmt) fmt_c128(v complex128, verb rune) { + f.fmt_complex(real(v), imag(v), 64, verb) +} + +// fmt_complex formats a complex number as (r+ji). +func (f *fmt) fmt_complex(r, j float64, size int, verb rune) { f.buf.WriteByte('(') - r := real(v) oldPlus := f.plus + oldSpace := f.space + oldWid := f.wid for i := 0; ; i++ { switch verb { case 'b': - f.fmt_fb64(r) + f.formatFloat(r, 'b', 0, size) case 'e': - f.fmt_e64(r) + f.formatFloat(r, 'e', doPrec(f, 6), size) case 'E': - f.fmt_E64(r) - case 'f': - f.fmt_f64(r) + f.formatFloat(r, 'E', doPrec(f, 6), size) + case 'f', 'F': + f.formatFloat(r, 'f', doPrec(f, 6), size) case 'g': - f.fmt_g64(r) + f.formatFloat(r, 'g', doPrec(f, -1), size) case 'G': - f.fmt_G64(r) + f.formatFloat(r, 'G', doPrec(f, -1), size) } if i != 0 { break } + // Imaginary part always has a sign. f.plus = true - r = imag(v) + f.space = false + f.wid = oldWid + r = j } + f.space = oldSpace f.plus = oldPlus + f.wid = oldWid f.buf.Write(irparenBytes) } diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go index 1ea816d6d5..59a30d221e 100644 --- a/libgo/go/fmt/print.go +++ b/libgo/go/fmt/print.go @@ -124,45 +124,13 @@ type pp struct { fmt fmt } -// A cache holds a set of reusable objects. -// The slice is a stack (LIFO). -// If more are needed, the cache creates them by calling new. -type cache struct { - mu sync.Mutex - saved []interface{} - new func() interface{} +var ppFree = sync.Pool{ + New: func() interface{} { return new(pp) }, } -func (c *cache) put(x interface{}) { - c.mu.Lock() - if len(c.saved) < cap(c.saved) { - c.saved = append(c.saved, x) - } - c.mu.Unlock() -} - -func (c *cache) get() interface{} { - c.mu.Lock() - n := len(c.saved) - if n == 0 { - c.mu.Unlock() - return c.new() - } - x := c.saved[n-1] - c.saved = c.saved[0 : n-1] - c.mu.Unlock() - return x -} - -func newCache(f func() interface{}) *cache { - return &cache{saved: make([]interface{}, 0, 100), new: f} -} - -var ppFree = newCache(func() interface{} { return new(pp) }) - -// newPrinter allocates a new pp struct or grab a cached one. +// newPrinter allocates a new pp struct or grabs a cached one. func newPrinter() *pp { - p := ppFree.get().(*pp) + p := ppFree.Get().(*pp) p.panicking = false p.erroring = false p.fmt.init(&p.buf) @@ -178,7 +146,7 @@ func (p *pp) free() { p.buf = p.buf[:0] p.arg = nil p.value = reflect.Value{} - ppFree.put(p) + ppFree.Put(p) } func (p *pp) Width() (wid int, ok bool) { return p.fmt.wid, p.fmt.widPresent } @@ -329,13 +297,13 @@ func parsenum(s string, start, end int) (num int, isnum bool, newi int) { return } -func (p *pp) unknownType(v interface{}) { - if v == nil { +func (p *pp) unknownType(v reflect.Value) { + if !v.IsValid() { p.buf.Write(nilAngleBytes) return } p.buf.WriteByte('?') - p.buf.WriteString(reflect.TypeOf(v).String()) + p.buf.WriteString(v.Type().String()) p.buf.WriteByte('?') } @@ -349,11 +317,11 @@ func (p *pp) badVerb(verb rune) { case p.arg != nil: p.buf.WriteString(reflect.TypeOf(p.arg).String()) p.add('=') - p.printArg(p.arg, 'v', false, false, 0) + p.printArg(p.arg, 'v', 0) case p.value.IsValid(): p.buf.WriteString(p.value.Type().String()) p.add('=') - p.printValue(p.value, 'v', false, false, 0) + p.printValue(p.value, 'v', 0) default: p.buf.Write(nilAngleBytes) } @@ -438,7 +406,7 @@ func (p *pp) fmtUnicode(v int64) { p.fmt.sharp = sharp } -func (p *pp) fmtUint64(v uint64, verb rune, goSyntax bool) { +func (p *pp) fmtUint64(v uint64, verb rune) { switch verb { case 'b': p.fmt.integer(int64(v), 2, unsigned, ldigits) @@ -447,7 +415,7 @@ func (p *pp) fmtUint64(v uint64, verb rune, goSyntax bool) { case 'd': p.fmt.integer(int64(v), 10, unsigned, ldigits) case 'v': - if goSyntax { + if p.fmt.sharpV { p.fmt0x64(v, true) } else { p.fmt.integer(int64(v), 10, unsigned, ldigits) @@ -479,7 +447,7 @@ func (p *pp) fmtFloat32(v float32, verb rune) { p.fmt.fmt_e32(v) case 'E': p.fmt.fmt_E32(v) - case 'f': + case 'f', 'F': p.fmt.fmt_f32(v) case 'g', 'v': p.fmt.fmt_g32(v) @@ -498,7 +466,7 @@ func (p *pp) fmtFloat64(v float64, verb rune) { p.fmt.fmt_e64(v) case 'E': p.fmt.fmt_E64(v) - case 'f': + case 'f', 'F': p.fmt.fmt_f64(v) case 'g', 'v': p.fmt.fmt_g64(v) @@ -531,10 +499,10 @@ func (p *pp) fmtComplex128(v complex128, verb rune) { } } -func (p *pp) fmtString(v string, verb rune, goSyntax bool) { +func (p *pp) fmtString(v string, verb rune) { switch verb { case 'v': - if goSyntax { + if p.fmt.sharpV { p.fmt.fmt_q(v) } else { p.fmt.fmt_s(v) @@ -552,9 +520,18 @@ func (p *pp) fmtString(v string, verb rune, goSyntax bool) { } } -func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, depth int) { +func (p *pp) fmtBytes(v []byte, verb rune, typ reflect.Type, depth int) { if verb == 'v' || verb == 'd' { - if goSyntax { + if p.fmt.sharpV { + if v == nil { + if typ == nil { + p.buf.WriteString("[]byte(nil)") + } else { + p.buf.WriteString(typ.String()) + p.buf.Write(nilParenBytes) + } + return + } if typ == nil { p.buf.Write(bytesBytes) } else { @@ -566,15 +543,15 @@ func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, dept } for i, c := range v { if i > 0 { - if goSyntax { + if p.fmt.sharpV { p.buf.Write(commaSpaceBytes) } else { p.buf.WriteByte(' ') } } - p.printArg(c, 'v', p.fmt.plus, goSyntax, depth+1) + p.printArg(c, 'v', depth+1) } - if goSyntax { + if p.fmt.sharpV { p.buf.WriteByte('}') } else { p.buf.WriteByte(']') @@ -595,7 +572,7 @@ func (p *pp) fmtBytes(v []byte, verb rune, goSyntax bool, typ reflect.Type, dept } } -func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) { +func (p *pp) fmtPointer(value reflect.Value, verb rune) { use0x64 := true switch verb { case 'p', 'v': @@ -617,7 +594,7 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) { return } - if goSyntax { + if p.fmt.sharpV { p.add('(') p.buf.WriteString(value.Type().String()) p.add(')') @@ -634,7 +611,7 @@ func (p *pp) fmtPointer(value reflect.Value, verb rune, goSyntax bool) { if use0x64 { p.fmt0x64(uint64(u), !p.fmt.sharp) } else { - p.fmtUint64(uint64(u), verb, false) + p.fmtUint64(uint64(u), verb) } } } @@ -659,42 +636,65 @@ func (p *pp) catchPanic(arg interface{}, verb rune) { // Nested panics; the recursion in printArg cannot succeed. panic(err) } + p.fmt.clearflags() // We are done, and for this output we want default behavior. p.buf.Write(percentBangBytes) p.add(verb) p.buf.Write(panicBytes) p.panicking = true - p.printArg(err, 'v', false, false, 0) + p.printArg(err, 'v', 0) p.panicking = false p.buf.WriteByte(')') } } -func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString, handled bool) { +// clearSpecialFlags pushes %#v back into the regular flags and returns their old state. +func (p *pp) clearSpecialFlags() (plusV, sharpV bool) { + plusV = p.fmt.plusV + if plusV { + p.fmt.plus = true + p.fmt.plusV = false + } + sharpV = p.fmt.sharpV + if sharpV { + p.fmt.sharp = true + p.fmt.sharpV = false + } + return +} + +// restoreSpecialFlags, whose argument should be a call to clearSpecialFlags, +// restores the setting of the plusV and sharpV flags. +func (p *pp) restoreSpecialFlags(plusV, sharpV bool) { + if plusV { + p.fmt.plus = false + p.fmt.plusV = true + } + if sharpV { + p.fmt.sharp = false + p.fmt.sharpV = true + } +} + +func (p *pp) handleMethods(verb rune, depth int) (handled bool) { if p.erroring { return } // Is it a Formatter? if formatter, ok := p.arg.(Formatter); ok { handled = true - wasString = false + defer p.restoreSpecialFlags(p.clearSpecialFlags()) defer p.catchPanic(p.arg, verb) formatter.Format(p, verb) return } - // Must not touch flags before Formatter looks at them. - if plus { - p.fmt.plus = false - } // If we're doing Go syntax and the argument knows how to supply it, take care of it now. - if goSyntax { - p.fmt.sharp = false + if p.fmt.sharpV { if stringer, ok := p.arg.(GoStringer); ok { - wasString = false handled = true defer p.catchPanic(p.arg, verb) // Print the result of GoString unadorned. - p.fmtString(stringer.GoString(), 's', false) + p.fmt.fmt_s(stringer.GoString()) return } } else { @@ -705,30 +705,27 @@ func (p *pp) handleMethods(verb rune, plus, goSyntax bool, depth int) (wasString case 'v', 's', 'x', 'X', 'q': // Is it an error or Stringer? // The duplication in the bodies is necessary: - // setting wasString and handled, and deferring catchPanic, + // setting handled and deferring catchPanic // must happen before calling the method. switch v := p.arg.(type) { case error: - wasString = false handled = true defer p.catchPanic(p.arg, verb) - p.printArg(v.Error(), verb, plus, false, depth) + p.printArg(v.Error(), verb, depth) return case Stringer: - wasString = false handled = true defer p.catchPanic(p.arg, verb) - p.printArg(v.String(), verb, plus, false, depth) + p.printArg(v.String(), verb, depth) return } } } - handled = false - return + return false } -func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int) (wasString bool) { +func (p *pp) printArg(arg interface{}, verb rune, depth int) (wasString bool) { p.arg = arg p.value = reflect.Value{} @@ -745,26 +742,13 @@ func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int // %T (the value's type) and %p (its address) are special; we always do them first. switch verb { case 'T': - p.printArg(reflect.TypeOf(arg).String(), 's', false, false, 0) + p.printArg(reflect.TypeOf(arg).String(), 's', 0) return false case 'p': - p.fmtPointer(reflect.ValueOf(arg), verb, goSyntax) + p.fmtPointer(reflect.ValueOf(arg), verb) return false } - // Clear flags for base formatters. - // handleMethods needs them, so we must restore them later. - // We could call handleMethods here and avoid this work, but - // handleMethods is expensive enough to be worth delaying. - oldPlus := p.fmt.plus - oldSharp := p.fmt.sharp - if plus { - p.fmt.plus = false - } - if goSyntax { - p.fmt.sharp = false - } - // Some types can be done without reflection. switch f := arg.(type) { case bool: @@ -788,40 +772,37 @@ func (p *pp) printArg(arg interface{}, verb rune, plus, goSyntax bool, depth int case int64: p.fmtInt64(f, verb) case uint: - p.fmtUint64(uint64(f), verb, goSyntax) + p.fmtUint64(uint64(f), verb) case uint8: - p.fmtUint64(uint64(f), verb, goSyntax) + p.fmtUint64(uint64(f), verb) case uint16: - p.fmtUint64(uint64(f), verb, goSyntax) + p.fmtUint64(uint64(f), verb) case uint32: - p.fmtUint64(uint64(f), verb, goSyntax) + p.fmtUint64(uint64(f), verb) case uint64: - p.fmtUint64(f, verb, goSyntax) + p.fmtUint64(f, verb) case uintptr: - p.fmtUint64(uint64(f), verb, goSyntax) + p.fmtUint64(uint64(f), verb) case string: - p.fmtString(f, verb, goSyntax) + p.fmtString(f, verb) wasString = verb == 's' || verb == 'v' case []byte: - p.fmtBytes(f, verb, goSyntax, nil, depth) + p.fmtBytes(f, verb, nil, depth) wasString = verb == 's' default: - // Restore flags in case handleMethods finds a Formatter. - p.fmt.plus = oldPlus - p.fmt.sharp = oldSharp // If the type is not simple, it might have methods. - if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled { - return isString + if handled := p.handleMethods(verb, depth); handled { + return false } // Need to use reflection - return p.printReflectValue(reflect.ValueOf(arg), verb, plus, goSyntax, depth) + return p.printReflectValue(reflect.ValueOf(arg), verb, depth) } p.arg = nil return } // printValue is like printArg but starts with a reflect value, not an interface{} value. -func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) { +func (p *pp) printValue(value reflect.Value, verb rune, depth int) (wasString bool) { if !value.IsValid() { if verb == 'T' || verb == 'v' { p.buf.Write(nilAngleBytes) @@ -835,10 +816,10 @@ func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, dep // %T (the value's type) and %p (its address) are special; we always do them first. switch verb { case 'T': - p.printArg(value.Type().String(), 's', false, false, 0) + p.printArg(value.Type().String(), 's', 0) return false case 'p': - p.fmtPointer(value, verb, goSyntax) + p.fmtPointer(value, verb) return false } @@ -848,16 +829,18 @@ func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, dep if value.CanInterface() { p.arg = value.Interface() } - if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled { - return isString + if handled := p.handleMethods(verb, depth); handled { + return false } - return p.printReflectValue(value, verb, plus, goSyntax, depth) + return p.printReflectValue(value, verb, depth) } +var byteType = reflect.TypeOf(byte(0)) + // printReflectValue is the fallback for both printArg and printValue. // It uses reflect to print the value. -func (p *pp) printReflectValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) { +func (p *pp) printReflectValue(value reflect.Value, verb rune, depth int) (wasString bool) { oldValue := p.value p.value = value BigSwitch: @@ -867,7 +850,7 @@ BigSwitch: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: p.fmtInt64(f.Int(), verb) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - p.fmtUint64(f.Uint(), verb, goSyntax) + p.fmtUint64(f.Uint(), verb) case reflect.Float32, reflect.Float64: if f.Type().Size() == 4 { p.fmtFloat32(float32(f.Float()), verb) @@ -881,9 +864,9 @@ BigSwitch: p.fmtComplex128(f.Complex(), verb) } case reflect.String: - p.fmtString(f.String(), verb, goSyntax) + p.fmtString(f.String(), verb) case reflect.Map: - if goSyntax { + if p.fmt.sharpV { p.buf.WriteString(f.Type().String()) if f.IsNil() { p.buf.WriteString("(nil)") @@ -896,23 +879,23 @@ BigSwitch: keys := f.MapKeys() for i, key := range keys { if i > 0 { - if goSyntax { + if p.fmt.sharpV { p.buf.Write(commaSpaceBytes) } else { p.buf.WriteByte(' ') } } - p.printValue(key, verb, plus, goSyntax, depth+1) + p.printValue(key, verb, depth+1) p.buf.WriteByte(':') - p.printValue(f.MapIndex(key), verb, plus, goSyntax, depth+1) + p.printValue(f.MapIndex(key), verb, depth+1) } - if goSyntax { + if p.fmt.sharpV { p.buf.WriteByte('}') } else { p.buf.WriteByte(']') } case reflect.Struct: - if goSyntax { + if p.fmt.sharpV { p.buf.WriteString(value.Type().String()) } p.add('{') @@ -920,36 +903,40 @@ BigSwitch: t := v.Type() for i := 0; i < v.NumField(); i++ { if i > 0 { - if goSyntax { + if p.fmt.sharpV { p.buf.Write(commaSpaceBytes) } else { p.buf.WriteByte(' ') } } - if plus || goSyntax { + if p.fmt.plusV || p.fmt.sharpV { if f := t.Field(i); f.Name != "" { p.buf.WriteString(f.Name) p.buf.WriteByte(':') } } - p.printValue(getField(v, i), verb, plus, goSyntax, depth+1) + p.printValue(getField(v, i), verb, depth+1) } p.buf.WriteByte('}') case reflect.Interface: value := f.Elem() if !value.IsValid() { - if goSyntax { + if p.fmt.sharpV { p.buf.WriteString(f.Type().String()) p.buf.Write(nilParenBytes) } else { p.buf.Write(nilAngleBytes) } } else { - wasString = p.printValue(value, verb, plus, goSyntax, depth+1) + wasString = p.printValue(value, verb, depth+1) } case reflect.Array, reflect.Slice: - // Byte slices are special. - if typ := f.Type(); typ.Elem().Kind() == reflect.Uint8 { + // Byte slices are special: + // - Handle []byte (== []uint8) with fmtBytes. + // - Handle []T, where T is a named byte type, with fmtBytes only + // for the s, q, an x verbs. For other verbs, T might be a + // Stringer, so we use printValue to print each element. + if typ := f.Type(); typ.Elem().Kind() == reflect.Uint8 && (typ.Elem() == byteType || verb == 's' || verb == 'q' || verb == 'x') { var bytes []byte if f.Kind() == reflect.Slice { bytes = f.Bytes() @@ -964,11 +951,11 @@ BigSwitch: bytes[i] = byte(f.Index(i).Uint()) } } - p.fmtBytes(bytes, verb, goSyntax, typ, depth) + p.fmtBytes(bytes, verb, typ, depth) wasString = verb == 's' break } - if goSyntax { + if p.fmt.sharpV { p.buf.WriteString(value.Type().String()) if f.Kind() == reflect.Slice && f.IsNil() { p.buf.WriteString("(nil)") @@ -980,15 +967,15 @@ BigSwitch: } for i := 0; i < f.Len(); i++ { if i > 0 { - if goSyntax { + if p.fmt.sharpV { p.buf.Write(commaSpaceBytes) } else { p.buf.WriteByte(' ') } } - p.printValue(f.Index(i), verb, plus, goSyntax, depth+1) + p.printValue(f.Index(i), verb, depth+1) } - if goSyntax { + if p.fmt.sharpV { p.buf.WriteByte('}') } else { p.buf.WriteByte(']') @@ -1001,17 +988,21 @@ BigSwitch: switch a := f.Elem(); a.Kind() { case reflect.Array, reflect.Slice: p.buf.WriteByte('&') - p.printValue(a, verb, plus, goSyntax, depth+1) + p.printValue(a, verb, depth+1) break BigSwitch case reflect.Struct: p.buf.WriteByte('&') - p.printValue(a, verb, plus, goSyntax, depth+1) + p.printValue(a, verb, depth+1) + break BigSwitch + case reflect.Map: + p.buf.WriteByte('&') + p.printValue(a, verb, depth+1) break BigSwitch } } fallthrough case reflect.Chan, reflect.Func, reflect.UnsafePointer: - p.fmtPointer(value, verb, goSyntax) + p.fmtPointer(value, verb) default: p.unknownType(f) } @@ -1177,9 +1168,19 @@ func (p *pp) doPrintf(format string, a []interface{}) { arg := a[argNum] argNum++ - goSyntax := c == 'v' && p.fmt.sharp - plus := c == 'v' && p.fmt.plus - p.printArg(arg, c, plus, goSyntax, 0) + if c == 'v' { + if p.fmt.sharp { + // Go syntax. Set the flag in the fmt and clear the sharp flag. + p.fmt.sharp = false + p.fmt.sharpV = true + } + if p.fmt.plus { + // Struct-field syntax. Set the flag in the fmt and clear the plus flag. + p.fmt.plus = false + p.fmt.plusV = true + } + } + p.printArg(arg, c, 0) } // Check for extra arguments unless the call accessed the arguments @@ -1193,7 +1194,7 @@ func (p *pp) doPrintf(format string, a []interface{}) { p.buf.WriteString(reflect.TypeOf(arg).String()) p.buf.WriteByte('=') } - p.printArg(arg, 'v', false, false, 0) + p.printArg(arg, 'v', 0) if argNum+1 < len(a) { p.buf.Write(commaSpaceBytes) } @@ -1214,7 +1215,7 @@ func (p *pp) doPrint(a []interface{}, addspace, addnewline bool) { p.buf.WriteByte(' ') } } - prevString = p.printArg(arg, 'v', false, false, 0) + prevString = p.printArg(arg, 'v', 0) } if addnewline { p.buf.WriteByte('\n') diff --git a/libgo/go/fmt/scan.go b/libgo/go/fmt/scan.go index 5b1be5891b..d7befeae43 100644 --- a/libgo/go/fmt/scan.go +++ b/libgo/go/fmt/scan.go @@ -11,6 +11,7 @@ import ( "os" "reflect" "strconv" + "sync" "unicode/utf8" ) @@ -283,7 +284,6 @@ var space = [][2]uint16{ {0x0085, 0x0085}, {0x00a0, 0x00a0}, {0x1680, 0x1680}, - {0x180e, 0x180e}, {0x2000, 0x200a}, {0x2028, 0x2029}, {0x202f, 0x202f}, @@ -360,6 +360,7 @@ func (r *readRune) ReadRune() (rr rune, size int, err error) { } if r.buf[0] < utf8.RuneSelf { // fast check for common ASCII case rr = rune(r.buf[0]) + size = 1 // Known to be 1. return } var n int @@ -380,7 +381,9 @@ func (r *readRune) ReadRune() (rr rune, size int, err error) { return } -var ssFree = newCache(func() interface{} { return new(ss) }) +var ssFree = sync.Pool{ + New: func() interface{} { return new(ss) }, +} // newScanState allocates a new ss struct or grab a cached one. func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) { @@ -395,7 +398,7 @@ func newScanState(r io.Reader, nlIsSpace, nlIsEnd bool) (s *ss, old ssave) { return } - s = ssFree.get().(*ss) + s = ssFree.Get().(*ss) if rr, ok := r.(io.RuneReader); ok { s.rr = rr } else { @@ -427,7 +430,7 @@ func (s *ss) free(old ssave) { } s.buf = s.buf[:0] s.rr = nil - ssFree.put(s) + ssFree.Put(s) } // skipSpace skips spaces and maybe newlines. diff --git a/libgo/go/fmt/scan_test.go b/libgo/go/fmt/scan_test.go index d903f0c3ff..541e12df21 100644 --- a/libgo/go/fmt/scan_test.go +++ b/libgo/go/fmt/scan_test.go @@ -842,6 +842,38 @@ func TestLineByLineFscanf(t *testing.T) { } } +// TestScanStateCount verifies the correct byte count is returned. Issue 8512. + +// runeScanner implements the Scanner interface for TestScanStateCount. +type runeScanner struct { + rune rune + size int +} + +func (rs *runeScanner) Scan(state ScanState, verb rune) error { + r, size, err := state.ReadRune() + rs.rune = r + rs.size = size + return err +} + +func TestScanStateCount(t *testing.T) { + var a, b, c runeScanner + n, err := Sscanf("12➂", "%c%c%c", &a, &b, &c) + if err != nil { + t.Fatal(err) + } + if n != 3 { + t.Fatalf("expected 3 items consumed, got %d") + } + if a.rune != '1' || b.rune != '2' || c.rune != '➂' { + t.Errorf("bad scan rune: %q %q %q should be '1' '2' '➂'", a.rune, b.rune, c.rune) + } + if a.size != 1 || b.size != 1 || c.size != 3 { + t.Errorf("bad scan size: %q %q %q should be 1 1 3", a.size, b.size, c.size) + } +} + // RecursiveInt accepts a string matching %d.%d.%d.... // and parses it into a linked list. // It allows us to benchmark recursive descent style scanners. diff --git a/libgo/go/go/ast/ast.go b/libgo/go/go/ast/ast.go index 6e635cd016..312e3d1b98 100644 --- a/libgo/go/go/ast/ast.go +++ b/libgo/go/go/ast/ast.go @@ -699,9 +699,9 @@ type ( // A RangeStmt represents a for statement with a range clause. RangeStmt struct { For token.Pos // position of "for" keyword - Key, Value Expr // Value may be nil - TokPos token.Pos // position of Tok - Tok token.Token // ASSIGN, DEFINE + Key, Value Expr // Key, Value may be nil + TokPos token.Pos // position of Tok; invalid if Key == nil + Tok token.Token // ILLEGAL if Key == nil, ASSIGN, DEFINE X Expr // value to range over Body *BlockStmt } diff --git a/libgo/go/go/ast/commentmap.go b/libgo/go/go/ast/commentmap.go index 1fb4867dd2..ac999d627c 100644 --- a/libgo/go/go/ast/commentmap.go +++ b/libgo/go/go/ast/commentmap.go @@ -149,7 +149,7 @@ func NewCommentMap(fset *token.FileSet, node Node, comments []*CommentGroup) Com // set up comment reader r tmp := make([]*CommentGroup, len(comments)) - copy(tmp, comments) // don't change incomming comments + copy(tmp, comments) // don't change incoming comments sortComments(tmp) r := commentListReader{fset: fset, list: tmp} // !r.eol() because len(comments) > 0 r.next() diff --git a/libgo/go/go/ast/scope.go b/libgo/go/go/ast/scope.go index 8df5b2c656..df1529d181 100644 --- a/libgo/go/go/ast/scope.go +++ b/libgo/go/go/ast/scope.go @@ -80,7 +80,7 @@ type Object struct { Name string // declared name Decl interface{} // corresponding Field, XxxSpec, FuncDecl, LabeledStmt, AssignStmt, Scope; or nil Data interface{} // object-specific data; or nil - Type interface{} // place holder for type information; may be nil + Type interface{} // placeholder for type information; may be nil } // NewObj creates a new object of a given kind and name. diff --git a/libgo/go/go/ast/walk.go b/libgo/go/go/ast/walk.go index fedffb3f22..73ac38647a 100644 --- a/libgo/go/go/ast/walk.go +++ b/libgo/go/go/ast/walk.go @@ -275,7 +275,9 @@ func Walk(v Visitor, node Node) { Walk(v, n.Body) case *RangeStmt: - Walk(v, n.Key) + if n.Key != nil { + Walk(v, n.Key) + } if n.Value != nil { Walk(v, n.Value) } diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go index d06a9be531..e9247274b6 100644 --- a/libgo/go/go/build/build.go +++ b/libgo/go/go/build/build.go @@ -23,6 +23,7 @@ import ( "strconv" "strings" "unicode" + "unicode/utf8" ) // A Context specifies the supporting context for a build. @@ -206,9 +207,7 @@ func (ctxt *Context) gopath() []string { if p == "" || p == ctxt.GOROOT { // Empty paths are uninteresting. // If the path is the GOROOT, ignore it. - // People sometimes set GOPATH=$GOROOT, which is useless - // but would cause us to find packages with import paths - // like "pkg/math". + // People sometimes set GOPATH=$GOROOT. // Do not get confused by this common mistake. continue } @@ -238,7 +237,7 @@ func (ctxt *Context) gopath() []string { func (ctxt *Context) SrcDirs() []string { var all []string if ctxt.GOROOT != "" { - dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg") + dir := ctxt.joinPath(ctxt.GOROOT, "src") if ctxt.isDir(dir) { all = append(all, dir) } @@ -266,8 +265,18 @@ var cgoEnabled = map[string]bool{ "freebsd/amd64": true, "freebsd/arm": true, "linux/386": true, + "linux/alpha": true, "linux/amd64": true, "linux/arm": true, + "linux/arm64": true, + "linux/ppc": true, + "linux/ppc64": true, + "linux/ppc64le": true, + "linux/s390": true, + "linux/s390x": true, + "android/386": true, + "android/amd64": true, + "android/arm": true, "netbsd/386": true, "netbsd/amd64": true, "netbsd/arm": true, @@ -292,10 +301,10 @@ func defaultContext() Context { // say "+build go1.x", and code that should only be built before Go 1.x // (perhaps it is the stub to use in that case) should say "+build !go1.x". // - // When we reach Go 1.3 the line will read - // c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3"} + // When we reach Go 1.5 the line will read + // c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5"} // and so on. - c.ReleaseTags = []string{"go1.1", "go1.2"} + c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4"} switch os.Getenv("CGO_ENABLED") { case "1": @@ -303,8 +312,7 @@ func defaultContext() Context { case "0": c.CgoEnabled = false default: - // golang.org/issue/5141 - // cgo should be disabled for cross compilation builds + // cgo must be explicitly enabled for cross compilation builds if runtime.GOARCH == c.GOARCH && runtime.GOOS == c.GOOS { c.CgoEnabled = cgoEnabled[c.GOOS+"/"+c.GOARCH] break @@ -335,22 +343,29 @@ const ( // If AllowBinary is set, Import can be satisfied by a compiled // package object without corresponding sources. AllowBinary + + // If ImportComment is set, parse import comments on package statements. + // Import returns an error if it finds a comment it cannot understand + // or finds conflicting comments in multiple source files. + // See golang.org/s/go14customimport for more information. + ImportComment ) // A Package describes the Go package found in a directory. type Package struct { - Dir string // directory containing package sources - Name string // package name - Doc string // documentation synopsis - ImportPath string // import path of package ("" if unknown) - Root string // root of Go tree where this package lives - SrcRoot string // package source root directory ("" if unknown) - PkgRoot string // package install root directory ("" if unknown) - BinDir string // command install directory ("" if unknown) - Goroot bool // package found in Go root - PkgObj string // installed .a file - AllTags []string // tags that can influence file selection in this directory - ConflictDir string // this directory shadows Dir in $GOPATH + Dir string // directory containing package sources + Name string // package name + ImportComment string // path in import comment on package statement + Doc string // documentation synopsis + ImportPath string // import path of package ("" if unknown) + Root string // root of Go tree where this package lives + SrcRoot string // package source root directory ("" if unknown) + PkgRoot string // package install root directory ("" if unknown) + BinDir string // command install directory ("" if unknown) + Goroot bool // package found in Go root + PkgObj string // installed .a file + AllTags []string // tags that can influence file selection in this directory + ConflictDir string // this directory shadows Dir in $GOPATH // Source files GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) @@ -358,6 +373,7 @@ type Package struct { IgnoredGoFiles []string // .go source files ignored for this build CFiles []string // .c source files CXXFiles []string // .cc, .cpp and .cxx source files + MFiles []string // .m (Objective-C) source files HFiles []string // .h, .hh, .hpp and .hxx source files SFiles []string // .s source files SwigFiles []string // .swig files @@ -408,6 +424,19 @@ func (e *NoGoError) Error() string { return "no buildable Go source files in " + e.Dir } +// MultiplePackageError describes a directory containing +// multiple buildable Go source files for multiple packages. +type MultiplePackageError struct { + Dir string // directory containing files + Packages []string // package names found + Files []string // corresponding files: Files[i] declares package Packages[i] +} + +func (e *MultiplePackageError) Error() string { + // Error string limited to two entries for compatibility. + return fmt.Sprintf("found packages %s (%s) and %s (%s) in %s", e.Packages[0], e.Files[0], e.Packages[1], e.Files[1], e.Dir) +} + func nameExt(name string) string { i := strings.LastIndex(name, ".") if i < 0 { @@ -468,7 +497,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa } // Determine canonical import path, if any. if ctxt.GOROOT != "" { - root := ctxt.joinPath(ctxt.GOROOT, "src", "pkg") + root := ctxt.joinPath(ctxt.GOROOT, "src") if sub, ok := ctxt.hasSubdir(root, p.Dir); ok { p.Goroot = true p.ImportPath = sub @@ -484,7 +513,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa // but check that using it wouldn't find something // else first. if ctxt.GOROOT != "" { - if dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", sub); ctxt.isDir(dir) { + if dir := ctxt.joinPath(ctxt.GOROOT, "src", sub); ctxt.isDir(dir) { p.ConflictDir = dir goto Found } @@ -518,7 +547,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa // Determine directory from import path. if ctxt.GOROOT != "" { - dir := ctxt.joinPath(ctxt.GOROOT, "src", "pkg", path) + dir := ctxt.joinPath(ctxt.GOROOT, "src", path) isDir := ctxt.isDir(dir) binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(ctxt.GOROOT, pkga)) if isDir || binaryOnly { @@ -564,11 +593,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa Found: if p.Root != "" { - if p.Goroot { - p.SrcRoot = ctxt.joinPath(p.Root, "src", "pkg") - } else { - p.SrcRoot = ctxt.joinPath(p.Root, "src") - } + p.SrcRoot = ctxt.joinPath(p.Root, "src") p.PkgRoot = ctxt.joinPath(p.Root, "pkg") p.BinDir = ctxt.joinPath(p.Root, "bin") if pkga != "" { @@ -589,7 +614,7 @@ Found: } var Sfiles []string // files with ".S" (capital S) - var firstFile string + var firstFile, firstCommentFile string imported := make(map[string][]token.Position) testImported := make(map[string][]token.Position) xTestImported := make(map[string][]token.Position) @@ -622,6 +647,9 @@ Found: case ".cc", ".cpp", ".cxx": p.CXXFiles = append(p.CXXFiles, name) continue + case ".m": + p.MFiles = append(p.MFiles, name) + continue case ".h", ".hh", ".hpp", ".hxx": p.HFiles = append(p.HFiles, name) continue @@ -667,12 +695,28 @@ Found: p.Name = pkg firstFile = name } else if pkg != p.Name { - return p, fmt.Errorf("found packages %s (%s) and %s (%s) in %s", p.Name, firstFile, pkg, name, p.Dir) + return p, &MultiplePackageError{p.Dir, []string{firstFile, name}, []string{p.Name, pkg}} } if pf.Doc != nil && p.Doc == "" { p.Doc = doc.Synopsis(pf.Doc.Text()) } + if mode&ImportComment != 0 { + qcom, line := findImportComment(data) + if line != 0 { + com, err := strconv.Unquote(qcom) + if err != nil { + return p, fmt.Errorf("%s:%d: cannot parse import comment", filename, line) + } + if p.ImportComment == "" { + p.ImportComment = com + firstCommentFile = name + } else if p.ImportComment != com { + return p, fmt.Errorf("found import comments %q (%s) and %q (%s) in %s", p.ImportComment, firstCommentFile, com, name, p.Dir) + } + } + } + // Record imports and information about cgo. isCgo := false for _, decl := range pf.Decls { @@ -753,6 +797,117 @@ Found: return p, pkgerr } +func findImportComment(data []byte) (s string, line int) { + // expect keyword package + word, data := parseWord(data) + if string(word) != "package" { + return "", 0 + } + + // expect package name + _, data = parseWord(data) + + // now ready for import comment, a // or /* */ comment + // beginning and ending on the current line. + for len(data) > 0 && (data[0] == ' ' || data[0] == '\t' || data[0] == '\r') { + data = data[1:] + } + + var comment []byte + switch { + case bytes.HasPrefix(data, slashSlash): + i := bytes.Index(data, newline) + if i < 0 { + i = len(data) + } + comment = data[2:i] + case bytes.HasPrefix(data, slashStar): + data = data[2:] + i := bytes.Index(data, starSlash) + if i < 0 { + // malformed comment + return "", 0 + } + comment = data[:i] + if bytes.Contains(comment, newline) { + return "", 0 + } + } + comment = bytes.TrimSpace(comment) + + // split comment into `import`, `"pkg"` + word, arg := parseWord(comment) + if string(word) != "import" { + return "", 0 + } + + line = 1 + bytes.Count(data[:cap(data)-cap(arg)], newline) + return strings.TrimSpace(string(arg)), line +} + +var ( + slashSlash = []byte("//") + slashStar = []byte("/*") + starSlash = []byte("*/") + newline = []byte("\n") +) + +// skipSpaceOrComment returns data with any leading spaces or comments removed. +func skipSpaceOrComment(data []byte) []byte { + for len(data) > 0 { + switch data[0] { + case ' ', '\t', '\r', '\n': + data = data[1:] + continue + case '/': + if bytes.HasPrefix(data, slashSlash) { + i := bytes.Index(data, newline) + if i < 0 { + return nil + } + data = data[i+1:] + continue + } + if bytes.HasPrefix(data, slashStar) { + data = data[2:] + i := bytes.Index(data, starSlash) + if i < 0 { + return nil + } + data = data[i+2:] + continue + } + } + break + } + return data +} + +// parseWord skips any leading spaces or comments in data +// and then parses the beginning of data as an identifier or keyword, +// returning that word and what remains after the word. +func parseWord(data []byte) (word, rest []byte) { + data = skipSpaceOrComment(data) + + // Parse past leading word characters. + rest = data + for { + r, size := utf8.DecodeRune(rest) + if unicode.IsLetter(r) || '0' <= r && r <= '9' || r == '_' { + rest = rest[size:] + continue + } + break + } + + word = data[:len(data)-len(rest)] + if len(word) == 0 { + return nil, nil + } + + return word, rest +} + // MatchFile reports whether the file with the given name in the given directory // matches the context and would be included in a Package created by ImportDir // of that directory. @@ -789,7 +944,7 @@ func (ctxt *Context) matchFile(dir, name string, returnImports bool, allTags map } switch ext { - case ".go", ".c", ".cc", ".cxx", ".cpp", ".s", ".h", ".hh", ".hpp", ".hxx", ".S", ".swig", ".swigcxx": + case ".go", ".c", ".cc", ".cxx", ".cpp", ".m", ".s", ".h", ".hh", ".hpp", ".hxx", ".S", ".swig", ".swigcxx": // tentatively okay - read to make sure case ".syso": // binary, no reading @@ -1121,6 +1276,9 @@ func (ctxt *Context) match(name string, allTags map[string]bool) bool { if name == ctxt.GOOS || name == ctxt.GOARCH || name == ctxt.Compiler { return true } + if ctxt.GOOS == "android" && name == "linux" { + return true + } // other tags for _, tag := range ctxt.BuildTags { @@ -1148,10 +1306,25 @@ func (ctxt *Context) match(name string, allTags map[string]bool) bool { // name_$(GOARCH)_test.* // name_$(GOOS)_$(GOARCH)_test.* // +// An exception: if GOOS=android, then files with GOOS=linux are also matched. func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool { if dot := strings.Index(name, "."); dot != -1 { name = name[:dot] } + + // Before Go 1.4, a file called "linux.go" would be equivalent to having a + // build tag "linux" in that file. For Go 1.4 and beyond, we require this + // auto-tagging to apply only to files with a non-empty prefix, so + // "foo_linux.go" is tagged but "linux.go" is not. This allows new operating + // sytems, such as android, to arrive without breaking existing code with + // innocuous source code in "android.go". The easiest fix: cut everything + // in the name before the initial _. + i := strings.Index(name, "_") + if i < 0 { + return true + } + name = name[i:] // ignore everything before first _ + l := strings.Split(name, "_") if n := len(l); n > 0 && l[n-1] == "test" { l = l[:n-1] @@ -1162,12 +1335,21 @@ func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool { allTags[l[n-2]] = true allTags[l[n-1]] = true } - return l[n-2] == ctxt.GOOS && l[n-1] == ctxt.GOARCH + if l[n-1] != ctxt.GOARCH { + return false + } + if ctxt.GOOS == "android" && l[n-2] == "linux" { + return true + } + return l[n-2] == ctxt.GOOS } if n >= 1 && knownOS[l[n-1]] { if allTags != nil { allTags[l[n-1]] = true } + if ctxt.GOOS == "android" && l[n-1] == "linux" { + return true + } return l[n-1] == ctxt.GOOS } if n >= 1 && knownArch[l[n-1]] { @@ -1191,8 +1373,15 @@ func init() { } } -// ToolDir is the directory containing build tools. -var ToolDir = filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH) +func getToolDir() string { + if runtime.Compiler == "gccgo" { + return runtime.GCCGOTOOLDIR + } else { + return filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH) + } +} + +var ToolDir = getToolDir() // IsLocalImport reports whether the import path is // a local import path, like ".", "..", "./foo", or "../foo". @@ -1207,12 +1396,14 @@ func ArchChar(goarch string) (string, error) { switch goarch { case "386": return "8", nil - case "amd64": + case "amd64", "amd64p32": return "6", nil case "arm": return "5", nil case "arm64": return "7", nil + case "ppc64", "ppc64le": + return "9", nil } return "", errors.New("unsupported GOARCH " + goarch) } diff --git a/libgo/go/go/build/build_test.go b/libgo/go/go/build/build_test.go index fca8d4bdb2..a40def0fa0 100644 --- a/libgo/go/go/build/build_test.go +++ b/libgo/go/go/build/build_test.go @@ -85,6 +85,20 @@ func TestEmptyImport(t *testing.T) { } } +func TestEmptyFolderImport(t *testing.T) { + _, err := Import(".", "testdata/empty", 0) + if _, ok := err.(*NoGoError); !ok { + t.Fatal(`Import("testdata/empty") did not return NoGoError.`) + } +} + +func TestMultiplePackageImport(t *testing.T) { + _, err := Import(".", "testdata/multi", 0) + if _, ok := err.(*MultiplePackageError); !ok { + t.Fatal(`Import("testdata/multi") did not return MultiplePackageError.`) + } +} + func TestLocalDirectory(t *testing.T) { cwd, err := os.Getwd() if err != nil { @@ -153,22 +167,36 @@ func (r readNopCloser) Close() error { return nil } +var ( + ctxtP9 = Context{GOARCH: "arm", GOOS: "plan9"} + ctxtAndroid = Context{GOARCH: "arm", GOOS: "android"} +) + var matchFileTests = []struct { + ctxt Context name string data string match bool }{ - {"foo_arm.go", "", true}, - {"foo1_arm.go", "// +build linux\n\npackage main\n", false}, - {"foo_darwin.go", "", false}, - {"foo.go", "", true}, - {"foo1.go", "// +build linux\n\npackage main\n", false}, - {"foo.badsuffix", "", false}, + {ctxtP9, "foo_arm.go", "", true}, + {ctxtP9, "foo1_arm.go", "// +build linux\n\npackage main\n", false}, + {ctxtP9, "foo_darwin.go", "", false}, + {ctxtP9, "foo.go", "", true}, + {ctxtP9, "foo1.go", "// +build linux\n\npackage main\n", false}, + {ctxtP9, "foo.badsuffix", "", false}, + {ctxtAndroid, "foo_linux.go", "", true}, + {ctxtAndroid, "foo_android.go", "", true}, + {ctxtAndroid, "foo_plan9.go", "", false}, + {ctxtAndroid, "android.go", "", true}, + {ctxtAndroid, "plan9.go", "", true}, + {ctxtAndroid, "plan9_test.go", "", true}, + {ctxtAndroid, "arm.s", "", true}, + {ctxtAndroid, "amd64.s", "", true}, } func TestMatchFile(t *testing.T) { for _, tt := range matchFileTests { - ctxt := Context{GOARCH: "arm", GOOS: "plan9"} + ctxt := tt.ctxt ctxt.OpenFile = func(path string) (r io.ReadCloser, err error) { if path != "x+"+tt.name { t.Fatalf("OpenFile asked for %q, expected %q", path, "x+"+tt.name) @@ -184,3 +212,13 @@ func TestMatchFile(t *testing.T) { } } } + +func TestImportCmd(t *testing.T) { + p, err := Import("cmd/internal/objfile", "", 0) + if err != nil { + t.Fatal(err) + } + if !strings.HasSuffix(filepath.ToSlash(p.Dir), "src/cmd/internal/objfile") { + t.Fatalf("Import cmd/internal/objfile returned Dir=%q, want %q", filepath.ToSlash(p.Dir), ".../src/cmd/internal/objfile") + } +} diff --git a/libgo/go/go/build/deps_test.go b/libgo/go/go/build/deps_test.go index 88f3eca4ed..a335effec3 100644 --- a/libgo/go/go/build/deps_test.go +++ b/libgo/go/go/build/deps_test.go @@ -8,6 +8,7 @@ package build import ( + "runtime" "sort" "testing" ) @@ -29,7 +30,7 @@ var pkgDeps = map[string][]string{ "errors": {}, "io": {"errors", "sync"}, "runtime": {"unsafe"}, - "sync": {"sync/atomic", "unsafe"}, + "sync": {"runtime", "sync/atomic", "unsafe"}, "sync/atomic": {"unsafe"}, "unsafe": {}, @@ -125,7 +126,7 @@ var pkgDeps = map[string][]string{ "os": {"L1", "os", "syscall", "time"}, "path/filepath": {"L2", "os", "syscall"}, "io/ioutil": {"L2", "os", "path/filepath", "time"}, - "os/exec": {"L2", "os", "syscall"}, + "os/exec": {"L2", "os", "path/filepath", "syscall"}, "os/signal": {"L2", "os", "syscall"}, // OS enables basic operating system functionality, @@ -278,12 +279,12 @@ var pkgDeps = map[string][]string{ // Random byte, number generation. // This would be part of core crypto except that it imports // math/big, which imports fmt. - "crypto/rand": {"L4", "CRYPTO", "OS", "math/big", "syscall"}, + "crypto/rand": {"L4", "CRYPTO", "OS", "math/big", "syscall", "internal/syscall"}, // Mathematical crypto: dependencies on fmt (L4) and math/big. // We could avoid some of the fmt, but math/big imports fmt anyway. "crypto/dsa": {"L4", "CRYPTO", "math/big"}, - "crypto/ecdsa": {"L4", "CRYPTO", "crypto/elliptic", "math/big"}, + "crypto/ecdsa": {"L4", "CRYPTO", "crypto/elliptic", "math/big", "encoding/asn1"}, "crypto/elliptic": {"L4", "CRYPTO", "math/big"}, "crypto/rsa": {"L4", "CRYPTO", "crypto/rand", "math/big"}, @@ -301,7 +302,7 @@ var pkgDeps = map[string][]string{ // SSL/TLS. "crypto/tls": { "L4", "CRYPTO-MATH", "CGO", "OS", - "crypto/x509", "encoding/pem", "net", "syscall", + "container/list", "crypto/x509", "encoding/pem", "net", "syscall", }, "crypto/x509": { "L4", "CRYPTO-MATH", "OS", "CGO", @@ -317,6 +318,7 @@ var pkgDeps = map[string][]string{ "net/http": { "L4", "NET", "OS", "compress/gzip", "crypto/tls", "mime/multipart", "runtime/debug", + "net/http/internal", }, // HTTP-using packages. @@ -324,9 +326,9 @@ var pkgDeps = map[string][]string{ "net/http/cgi": {"L4", "NET", "OS", "crypto/tls", "net/http", "regexp"}, "net/http/fcgi": {"L4", "NET", "OS", "net/http", "net/http/cgi"}, "net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http"}, - "net/http/httputil": {"L4", "NET", "OS", "net/http"}, + "net/http/httputil": {"L4", "NET", "OS", "net/http", "net/http/internal"}, "net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof"}, - "net/rpc": {"L4", "NET", "encoding/gob", "net/http", "text/template"}, + "net/rpc": {"L4", "NET", "encoding/gob", "html/template", "net/http"}, "net/rpc/jsonrpc": {"L4", "NET", "encoding/json", "net/rpc"}, } @@ -359,7 +361,7 @@ func allowed(pkg string) map[string]bool { } var bools = []bool{false, true} -var geese = []string{"darwin", "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "plan9", "windows"} +var geese = []string{"android", "darwin", "dragonfly", "freebsd", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows"} var goarches = []string{"386", "amd64", "arm", "arm64"} type osPkg struct { @@ -374,6 +376,11 @@ var allowedErrors = map[osPkg]bool{ } func TestDependencies(t *testing.T) { + if runtime.GOOS == "nacl" { + // NaCl tests run in a limited file system and we do not + // provide access to every source file. + t.Skip("skipping on NaCl") + } var all []string for k := range pkgDeps { @@ -387,6 +394,9 @@ func TestDependencies(t *testing.T) { if isMacro(pkg) { continue } + if pkg == "runtime/cgo" && !ctxt.CgoEnabled { + continue + } p, err := ctxt.Import(pkg, "", 0) if err != nil { if allowedErrors[osPkg{ctxt.GOOS, pkg}] { diff --git a/libgo/go/go/build/doc.go b/libgo/go/go/build/doc.go index b2f04ea45c..75a827bb91 100644 --- a/libgo/go/go/build/doc.go +++ b/libgo/go/go/build/doc.go @@ -57,11 +57,15 @@ // // Build Constraints // -// A build constraint is a line comment beginning with the directive +build +// A build constraint, also known as a build tag, is a line comment that begins +// +// // +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 // they must appear near the top of the file, preceded -// only by blank lines and other line comments. +// 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. @@ -95,6 +99,8 @@ // - "cgo", if ctxt.CgoEnabled is true // - "go1.1", from Go version 1.1 onward // - "go1.2", from Go version 1.2 onward +// - "go1.3", from Go version 1.3 onward +// - "go1.4", from Go version 1.4 onward // - any additional words listed in ctxt.BuildTags // // If a file's name, after stripping the extension and a possible _test suffix, @@ -102,12 +108,10 @@ // *_GOOS // *_GOARCH // *_GOOS_GOARCH -// (example: source_windows_amd64.go) or the literals: -// GOOS -// GOARCH -// (example: windows.go) where GOOS and GOARCH represent any known operating -// system and architecture values respectively, then the file is considered to -// have an implicit build constraint requiring those terms. +// (example: source_windows_amd64.go) where GOOS and GOARCH represent +// any known operating system and architecture values respectively, then +// the file is considered to have an implicit build constraint requiring +// those terms. // // To keep a file from being considered for the build: // @@ -129,4 +133,7 @@ // building the package for Windows; similarly, math_386.s will be included // only when building the package for 32-bit x86. // +// Using GOOS=android matches build tags and files as for GOOS=linux +// in addition to android tags and files. +// package build diff --git a/libgo/go/go/build/syslist.go b/libgo/go/go/build/syslist.go index 3580d823b0..0bf4b1573c 100644 --- a/libgo/go/go/build/syslist.go +++ b/libgo/go/go/build/syslist.go @@ -4,5 +4,5 @@ package build -const goosList = "darwin dragonfly freebsd linux netbsd openbsd plan9 windows solaris " -const goarchList = "386 amd64 arm arm64 alpha m68k mipso32 mipsn32 mipsn64 mipso64 ppc ppc64 sparc sparc64 " +const goosList = "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows " +const goarchList = "386 amd64 amd64p32 arm arm64 alpha m68k mipso32 mipsn32 mipsn64 mipso64 ppc ppc64 ppc64le s390 s390x sparc sparc64 " diff --git a/libgo/go/go/build/testdata/multi/file.go b/libgo/go/go/build/testdata/multi/file.go new file mode 100644 index 0000000000..ee946eb2a2 --- /dev/null +++ b/libgo/go/go/build/testdata/multi/file.go @@ -0,0 +1,5 @@ +// Test data - not compiled. + +package main + +func main() {} diff --git a/libgo/go/go/build/testdata/multi/file_appengine.go b/libgo/go/go/build/testdata/multi/file_appengine.go new file mode 100644 index 0000000000..4ea31e7031 --- /dev/null +++ b/libgo/go/go/build/testdata/multi/file_appengine.go @@ -0,0 +1,5 @@ +// Test data - not compiled. + +package test_package + +func init() {} diff --git a/libgo/go/go/doc/comment.go b/libgo/go/go/doc/comment.go index 5c8c43e0c1..f414ca4090 100644 --- a/libgo/go/go/doc/comment.go +++ b/libgo/go/go/doc/comment.go @@ -45,13 +45,13 @@ func commentEscape(w io.Writer, text string, nice bool) { const ( // Regexp for Go identifiers - identRx = `[a-zA-Z_][a-zA-Z_0-9]*` // TODO(gri) ASCII only for now - fix this + identRx = `[\pL_][\pL_0-9]*` // Regexp for URLs - protocol = `(https?|ftp|file|gopher|mailto|news|nntp|telnet|wais|prospero):` + protocol = `https?|ftp|file|gopher|mailto|news|nntp|telnet|wais|prospero` hostPart = `[a-zA-Z0-9_@\-]+` - filePart = `[a-zA-Z0-9_?%#~&/\-+=]+` - urlRx = protocol + `//` + // http:// + filePart = `[a-zA-Z0-9_?%#~&/\-+=()]+` // parentheses may not be matching; see pairedParensPrefixLen + urlRx = `(` + protocol + `)://` + // http:// hostPart + `([.:]` + hostPart + `)*/?` + // //www.google.com:8080/ filePart + `([:.,]` + filePart + `)*` ) @@ -73,6 +73,29 @@ var ( html_endh = []byte("\n") ) +// pairedParensPrefixLen returns the length of the longest prefix of s containing paired parentheses. +func pairedParensPrefixLen(s string) int { + parens := 0 + l := len(s) + for i, ch := range s { + switch ch { + case '(': + if parens == 0 { + l = i + } + parens++ + case ')': + parens-- + if parens == 0 { + l = len(s) + } else if parens < 0 { + return i + } + } + } + return l +} + // Emphasize and escape a line of text for HTML. URLs are converted into links; // if the URL also appears in the words map, the link is taken from the map (if // the corresponding map value is the empty string, the URL is not converted @@ -92,18 +115,26 @@ func emphasize(w io.Writer, line string, words map[string]string, nice bool) { // write text before match commentEscape(w, line[0:m[0]], nice) - // analyze match + // adjust match if necessary match := line[m[0]:m[1]] + if n := pairedParensPrefixLen(match); n < len(match) { + // match contains unpaired parentheses (rare); + // redo matching with shortened line for correct indices + m = matchRx.FindStringSubmatchIndex(line[:m[0]+n]) + match = match[:n] + } + + // analyze match url := "" italics := false if words != nil { - url, italics = words[string(match)] + url, italics = words[match] } if m[2] >= 0 { // match against first parenthesized sub-regexp; must be match against urlRx if !italics { // no alternative URL in words list, use match instead - url = string(match) + url = match } italics = false // don't italicize URLs } @@ -392,7 +423,9 @@ func ToText(w io.Writer, text string, indent, preIndent string, width int) { case opPre: w.Write(nl) for _, line := range b.lines { - if !isBlank(line) { + if isBlank(line) { + w.Write([]byte("\n")) + } else { w.Write([]byte(preIndent)) w.Write([]byte(line)) } diff --git a/libgo/go/go/doc/comment_test.go b/libgo/go/go/doc/comment_test.go index aa21b8d1b3..ad65c2a27f 100644 --- a/libgo/go/go/doc/comment_test.go +++ b/libgo/go/go/doc/comment_test.go @@ -42,8 +42,9 @@ func TestIsHeading(t *testing.T) { } var blocksTests = []struct { - in string - out []block + in string + out []block + text string }{ { in: `Para 1. @@ -59,6 +60,22 @@ Para 3. pre1 Para 4. + + pre + pre1 + + pre2 + +Para 5. + + + pre + + + pre1 + pre2 + +Para 6. pre pre2 `, @@ -69,8 +86,44 @@ Para 4. {opPara, []string{"Para 3.\n"}}, {opPre, []string{"pre\n", "pre1\n"}}, {opPara, []string{"Para 4.\n"}}, + {opPre, []string{"pre\n", "pre1\n", "\n", "pre2\n"}}, + {opPara, []string{"Para 5.\n"}}, + {opPre, []string{"pre\n", "\n", "\n", "pre1\n", "pre2\n"}}, + {opPara, []string{"Para 6.\n"}}, {opPre, []string{"pre\n", "pre2\n"}}, }, + text: `. Para 1. Para 1 line 2. + +. Para 2. + + +. Section + +. Para 3. + +$ pre +$ pre1 + +. Para 4. + +$ pre +$ pre1 + +$ pre2 + +. Para 5. + +$ pre + + +$ pre1 +$ pre2 + +. Para 6. + +$ pre +$ pre2 +`, }, } @@ -83,14 +136,28 @@ func TestBlocks(t *testing.T) { } } +func TestToText(t *testing.T) { + var buf bytes.Buffer + for i, tt := range blocksTests { + ToText(&buf, tt.in, ". ", "$\t", 40) + if have := buf.String(); have != tt.text { + t.Errorf("#%d: mismatch\nhave: %s\nwant: %s\nhave vs want:\n%q\n%q", i, have, tt.text, have, tt.text) + } + buf.Reset() + } +} + var emphasizeTests = []struct { - in string - out string + in, out string }{ {"http://www.google.com/", `http://www.google.com/`}, {"https://www.google.com/", `https://www.google.com/`}, {"http://www.google.com/path.", `http://www.google.com/path.`}, + {"http://en.wikipedia.org/wiki/Camellia_(cipher)", `http://en.wikipedia.org/wiki/Camellia_(cipher)`}, {"(http://www.google.com/)", `(http://www.google.com/)`}, + {"http://gmail.com)", `http://gmail.com)`}, + {"((http://gmail.com))", `((http://gmail.com))`}, + {"http://gmail.com ((http://gmail.com)) ()", `http://gmail.com ((http://gmail.com)) ()`}, {"Foo bar http://example.com/ quux!", `Foo bar http://example.com/ quux!`}, {"Hello http://example.com/%2f/ /world.", `Hello http://example.com/%2f/ /world.`}, {"Lorem http: ipsum //host/path", "Lorem http: ipsum //host/path"}, @@ -107,3 +174,34 @@ func TestEmphasize(t *testing.T) { } } } + +var pairedParensPrefixLenTests = []struct { + in, out string +}{ + {"", ""}, + {"foo", "foo"}, + {"()", "()"}, + {"foo()", "foo()"}, + {"foo()()()", "foo()()()"}, + {"foo()((()()))", "foo()((()()))"}, + {"foo()((()()))bar", "foo()((()()))bar"}, + {"foo)", "foo"}, + {"foo))", "foo"}, + {"foo)))))", "foo"}, + {"(foo", ""}, + {"((foo", ""}, + {"(((((foo", ""}, + {"(foo)", "(foo)"}, + {"((((foo))))", "((((foo))))"}, + {"foo()())", "foo()()"}, + {"foo((()())", "foo"}, + {"foo((()())) (() foo ", "foo((()())) "}, +} + +func TestPairedParensPrefixLen(t *testing.T) { + for i, tt := range pairedParensPrefixLenTests { + if out := tt.in[:pairedParensPrefixLen(tt.in)]; out != tt.out { + t.Errorf("#%d: mismatch\nhave: %q\nwant: %q", i, out, tt.out) + } + } +} diff --git a/libgo/go/go/doc/example.go b/libgo/go/go/doc/example.go index 2358ed3890..c414e548cc 100644 --- a/libgo/go/go/doc/example.go +++ b/libgo/go/go/doc/example.go @@ -32,6 +32,17 @@ type Example struct { // Examples returns the examples found in the files, sorted by Name field. // The Order fields record the order in which the examples were encountered. +// +// Playable Examples must be in a package whose name ends in "_test". +// An Example is "playable" (the Play field is non-nil) in either of these +// circumstances: +// - The example function is self-contained: the function references only +// identifiers from other packages (or predeclared identifiers, such as +// "int") and the test file does not include a dot import. +// - The entire test file is the example: the file contains exactly one +// example function, zero test or benchmark functions, and at least one +// top-level function, type, variable, or constant declaration other +// than the example function. func Examples(files ...*ast.File) []*Example { var list []*Example for _, file := range files { @@ -244,7 +255,7 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File { } } - // Strip "Output:" commment and adjust body end position. + // Strip "Output:" comment and adjust body end position. body, comments = stripOutputComment(body, comments) // Synthesize import declaration. @@ -307,7 +318,7 @@ func playExampleFile(file *ast.File) *ast.File { return &f } -// stripOutputComment finds and removes an "Output:" commment from body +// stripOutputComment finds and removes an "Output:" comment from body // and comments, and adjusts the body block's end position. func stripOutputComment(body *ast.BlockStmt, comments []*ast.CommentGroup) (*ast.BlockStmt, []*ast.CommentGroup) { // Do nothing if no "Output:" comment found. diff --git a/libgo/go/go/doc/exports.go b/libgo/go/go/doc/exports.go index ff01285d4c..1d3b466d8c 100644 --- a/libgo/go/go/doc/exports.go +++ b/libgo/go/go/doc/exports.go @@ -6,15 +6,19 @@ package doc -import "go/ast" +import ( + "go/ast" + "go/token" +) // filterIdentList removes unexported names from list in place -// and returns the resulting list. +// and returns the resulting list. If blankOk is set, blank +// identifiers are considered exported names. // -func filterIdentList(list []*ast.Ident) []*ast.Ident { +func filterIdentList(list []*ast.Ident, blankOk bool) []*ast.Ident { j := 0 for _, x := range list { - if ast.IsExported(x.Name) { + if ast.IsExported(x.Name) || (blankOk && x.Name == "_") { list[j] = x j++ } @@ -74,7 +78,7 @@ func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList, ityp r.remember(ityp) } } else { - field.Names = filterIdentList(field.Names) + field.Names = filterIdentList(field.Names, false) if len(field.Names) < n { removedFields = true } @@ -136,13 +140,15 @@ func (r *reader) filterType(parent *namedType, typ ast.Expr) { } } -func (r *reader) filterSpec(spec ast.Spec) bool { +func (r *reader) filterSpec(spec ast.Spec, tok token.Token) bool { switch s := spec.(type) { case *ast.ImportSpec: // always keep imports so we can collect them return true case *ast.ValueSpec: - s.Names = filterIdentList(s.Names) + // special case: consider blank constants as exported + // (work-around for issue 5397) + s.Names = filterIdentList(s.Names, tok == token.CONST) if len(s.Names) > 0 { r.filterType(nil, s.Type) return true @@ -159,10 +165,10 @@ func (r *reader) filterSpec(spec ast.Spec) bool { return false } -func (r *reader) filterSpecList(list []ast.Spec) []ast.Spec { +func (r *reader) filterSpecList(list []ast.Spec, tok token.Token) []ast.Spec { j := 0 for _, s := range list { - if r.filterSpec(s) { + if r.filterSpec(s, tok) { list[j] = s j++ } @@ -173,7 +179,7 @@ func (r *reader) filterSpecList(list []ast.Spec) []ast.Spec { func (r *reader) filterDecl(decl ast.Decl) bool { switch d := decl.(type) { case *ast.GenDecl: - d.Specs = r.filterSpecList(d.Specs) + d.Specs = r.filterSpecList(d.Specs, d.Tok) return len(d.Specs) > 0 case *ast.FuncDecl: // ok to filter these methods early because any diff --git a/libgo/go/go/doc/headscan.go b/libgo/go/go/doc/headscan.go index f559347638..1ccaa15819 100644 --- a/libgo/go/go/doc/headscan.go +++ b/libgo/go/go/doc/headscan.go @@ -24,6 +24,7 @@ import ( "go/token" "os" "path/filepath" + "regexp" "runtime" "strings" ) @@ -33,10 +34,10 @@ var ( verbose = flag.Bool("v", false, "verbose mode") ) -const ( - html_h = "

" - html_endh = "

\n" -) +// ToHTML in comment.go assigns a (possibly blank) ID to each heading +var html_h = regexp.MustCompile(`

`) + +const html_endh = "

\n" func isGoFile(fi os.FileInfo) bool { return strings.HasSuffix(fi.Name(), ".go") && @@ -47,11 +48,11 @@ func appendHeadings(list []string, comment string) []string { var buf bytes.Buffer doc.ToHTML(&buf, comment, nil) for s := buf.String(); ; { - i := strings.Index(s, html_h) - if i < 0 { + loc := html_h.FindStringIndex(s) + if len(loc) == 0 { break } - i += len(html_h) + i := loc[1] j := strings.Index(s, html_endh) if j < 0 { list = append(list, s[i:]) // incorrect HTML diff --git a/libgo/go/go/doc/testdata/blank.0.golden b/libgo/go/go/doc/testdata/blank.0.golden new file mode 100644 index 0000000000..dae3ab2aff --- /dev/null +++ b/libgo/go/go/doc/testdata/blank.0.golden @@ -0,0 +1,37 @@ +// Package blank is a go/doc test for the handling of _. See issue ... +PACKAGE blank + +IMPORTPATH + testdata/blank + +FILENAMES + testdata/blank.go + +CONSTANTS + // Package constants. + const ( + _ int = iota + I1 + I2 + ) + + +TYPES + // S has a padding field. + type S struct { + H uint32 + + A uint8 + // contains filtered or unexported fields + } + + // + type T int + + // T constants. + const ( + _ T = iota + T1 + T2 + ) + diff --git a/libgo/go/go/doc/testdata/blank.1.golden b/libgo/go/go/doc/testdata/blank.1.golden new file mode 100644 index 0000000000..333d7e5b04 --- /dev/null +++ b/libgo/go/go/doc/testdata/blank.1.golden @@ -0,0 +1,46 @@ +// Package blank is a go/doc test for the handling of _. See issue ... +PACKAGE blank + +IMPORTPATH + testdata/blank + +FILENAMES + testdata/blank.go + +CONSTANTS + // Package constants. + const ( + _ int = iota + I1 + I2 + ) + + +VARIABLES + // + var _ = T(55) + + +FUNCTIONS + // + func _() + + +TYPES + // S has a padding field. + type S struct { + H uint32 + _ uint8 + A uint8 + } + + // + type T int + + // T constants. + const ( + _ T = iota + T1 + T2 + ) + diff --git a/libgo/go/go/doc/testdata/blank.2.golden b/libgo/go/go/doc/testdata/blank.2.golden new file mode 100644 index 0000000000..dae3ab2aff --- /dev/null +++ b/libgo/go/go/doc/testdata/blank.2.golden @@ -0,0 +1,37 @@ +// Package blank is a go/doc test for the handling of _. See issue ... +PACKAGE blank + +IMPORTPATH + testdata/blank + +FILENAMES + testdata/blank.go + +CONSTANTS + // Package constants. + const ( + _ int = iota + I1 + I2 + ) + + +TYPES + // S has a padding field. + type S struct { + H uint32 + + A uint8 + // contains filtered or unexported fields + } + + // + type T int + + // T constants. + const ( + _ T = iota + T1 + T2 + ) + diff --git a/libgo/go/go/doc/testdata/blank.go b/libgo/go/go/doc/testdata/blank.go new file mode 100644 index 0000000000..f812c77b77 --- /dev/null +++ b/libgo/go/go/doc/testdata/blank.go @@ -0,0 +1,38 @@ +// 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 blank is a go/doc test for the handling of _. +// See issue 5397. +package blank + +type T int + +// T constants. +const ( + _ T = iota + T1 + T2 +) + +// Package constants. +const ( + _ int = iota + I1 + I2 +) + +// Blanks not in doc output: + +// S has a padding field. +type S struct { + H uint32 + _ uint8 + A uint8 +} + +func _() {} + +type _ T + +var _ = T(55) diff --git a/libgo/go/go/format/format.go b/libgo/go/go/format/format.go index 3d00a645db..668a42df2d 100644 --- a/libgo/go/go/format/format.go +++ b/libgo/go/go/format/format.go @@ -18,6 +18,8 @@ import ( var config = printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 8} +const parserMode = parser.ParseComments + // Node formats node in canonical gofmt style and writes the result to dst. // // The node type must be *ast.File, *printer.CommentedNode, []ast.Decl, @@ -52,7 +54,7 @@ func Node(dst io.Writer, fset *token.FileSet, node interface{}) error { if err != nil { return err } - file, err = parser.ParseFile(fset, "", buf.Bytes(), parser.ParseComments) + file, err = parser.ParseFile(fset, "", buf.Bytes(), parserMode) if err != nil { // We should never get here. If we do, provide good diagnostic. return fmt.Errorf("format.Node internal error (%s)", err) @@ -80,66 +82,18 @@ func Node(dst io.Writer, fset *token.FileSet, node interface{}) error { // func Source(src []byte) ([]byte, error) { fset := token.NewFileSet() - node, err := parse(fset, src) + file, sourceAdj, indentAdj, err := parse(fset, "", src, true) if err != nil { return nil, err } - var buf bytes.Buffer - if file, ok := node.(*ast.File); ok { + if sourceAdj == nil { // Complete source file. + // TODO(gri) consider doing this always. ast.SortImports(fset, file) - err := config.Fprint(&buf, fset, file) - if err != nil { - return nil, err - } - - } else { - // Partial source file. - // Determine and prepend leading space. - i, j := 0, 0 - for j < len(src) && isSpace(src[j]) { - if src[j] == '\n' { - i = j + 1 // index of last line in leading space - } - j++ - } - buf.Write(src[:i]) - - // Determine indentation of first code line. - // Spaces are ignored unless there are no tabs, - // in which case spaces count as one tab. - indent := 0 - hasSpace := false - for _, b := range src[i:j] { - switch b { - case ' ': - hasSpace = true - case '\t': - indent++ - } - } - if indent == 0 && hasSpace { - indent = 1 - } - - // Format the source. - cfg := config - cfg.Indent = indent - err := cfg.Fprint(&buf, fset, node) - if err != nil { - return nil, err - } - - // Determine and append trailing space. - i = len(src) - for i > 0 && isSpace(src[i-1]) { - i-- - } - buf.Write(src[i:]) } - return buf.Bytes(), nil + return format(fset, file, sourceAdj, indentAdj, src, config) } func hasUnsortedImports(file *ast.File) bool { @@ -160,40 +114,153 @@ func hasUnsortedImports(file *ast.File) bool { return false } -func isSpace(b byte) bool { - return b == ' ' || b == '\t' || b == '\n' || b == '\r' -} +// ---------------------------------------------------------------------------- +// Support functions +// +// The functions parse, format, and isSpace below are identical to the +// respective functions in cmd/gofmt/gofmt.go - keep them in sync! +// +// TODO(gri) Factor out this functionality, eventually. -func parse(fset *token.FileSet, src []byte) (interface{}, error) { - // Try as a complete source file. - file, err := parser.ParseFile(fset, "", src, parser.ParseComments) - if err == nil { - return file, nil - } - // If the source is missing a package clause, try as a source fragment; otherwise fail. - if !strings.Contains(err.Error(), "expected 'package'") { - return nil, err +// parse parses src, which was read from the named file, +// as a Go source file, declaration, or statement list. +func parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) ( + file *ast.File, + sourceAdj func(src []byte, indent int) []byte, + indentAdj int, + err error, +) { + // Try as whole source file. + file, err = parser.ParseFile(fset, filename, src, parserMode) + // If there's no error, return. If the error is that the source file didn't begin with a + // package line and source fragments are ok, fall through to + // try as a source fragment. Stop and return on any other error. + if err == nil || !fragmentOk || !strings.Contains(err.Error(), "expected 'package'") { + return } - // Try as a declaration list by prepending a package clause in front of src. - // Use ';' not '\n' to keep line numbers intact. + // If this is a declaration list, make it a source file + // by inserting a package clause. + // Insert using a ;, not a newline, so that the line numbers + // in psrc match the ones in src. psrc := append([]byte("package p;"), src...) - file, err = parser.ParseFile(fset, "", psrc, parser.ParseComments) + file, err = parser.ParseFile(fset, filename, psrc, parserMode) if err == nil { - return file.Decls, nil + sourceAdj = func(src []byte, indent int) []byte { + // Remove the package clause. + // Gofmt has turned the ; into a \n. + src = src[indent+len("package p\n"):] + return bytes.TrimSpace(src) + } + return } - // If the source is missing a declaration, try as a statement list; otherwise fail. + // If the error is that the source file didn't begin with a + // declaration, fall through to try as a statement list. + // Stop and return on any other error. if !strings.Contains(err.Error(), "expected declaration") { - return nil, err + return } - // Try as statement list by wrapping a function around src. - fsrc := append(append([]byte("package p; func _() {"), src...), '}') - file, err = parser.ParseFile(fset, "", fsrc, parser.ParseComments) + // If this is a statement list, make it a source file + // by inserting a package clause and turning the list + // into a function body. This handles expressions too. + // Insert using a ;, not a newline, so that the line numbers + // in fsrc match the ones in src. + fsrc := append(append([]byte("package p; func _() {"), src...), '\n', '}') + file, err = parser.ParseFile(fset, filename, fsrc, parserMode) if err == nil { - return file.Decls[0].(*ast.FuncDecl).Body.List, nil + sourceAdj = func(src []byte, indent int) []byte { + // Cap adjusted indent to zero. + if indent < 0 { + indent = 0 + } + // Remove the wrapping. + // Gofmt has turned the ; into a \n\n. + // There will be two non-blank lines with indent, hence 2*indent. + src = src[2*indent+len("package p\n\nfunc _() {"):] + src = src[:len(src)-(indent+len("\n}\n"))] + return bytes.TrimSpace(src) + } + // Gofmt has also indented the function body one level. + // Adjust that with indentAdj. + indentAdj = -1 + } + + // Succeeded, or out of options. + return +} + +// format formats the given package file originally obtained from src +// and adjusts the result based on the original source via sourceAdj +// and indentAdj. +func format( + fset *token.FileSet, + file *ast.File, + sourceAdj func(src []byte, indent int) []byte, + indentAdj int, + src []byte, + cfg printer.Config, +) ([]byte, error) { + if sourceAdj == nil { + // Complete source file. + var buf bytes.Buffer + err := cfg.Fprint(&buf, fset, file) + if err != nil { + return nil, err + } + return buf.Bytes(), nil + } + + // Partial source file. + // Determine and prepend leading space. + i, j := 0, 0 + for j < len(src) && isSpace(src[j]) { + if src[j] == '\n' { + i = j + 1 // byte offset of last line in leading space + } + j++ + } + var res []byte + res = append(res, src[:i]...) + + // Determine and prepend indentation of first code line. + // Spaces are ignored unless there are no tabs, + // in which case spaces count as one tab. + indent := 0 + hasSpace := false + for _, b := range src[i:j] { + switch b { + case ' ': + hasSpace = true + case '\t': + indent++ + } + } + if indent == 0 && hasSpace { + indent = 1 + } + for i := 0; i < indent; i++ { + res = append(res, '\t') + } + + // Format the source. + // Write it without any leading and trailing space. + cfg.Indent = indent + indentAdj + var buf bytes.Buffer + err := cfg.Fprint(&buf, fset, file) + if err != nil { + return nil, err } + res = append(res, sourceAdj(buf.Bytes(), cfg.Indent)...) - // Failed, and out of options. - return nil, err + // Determine and append trailing space. + i = len(src) + for i > 0 && isSpace(src[i-1]) { + i-- + } + return append(res, src[i:]...), nil +} + +func isSpace(b byte) bool { + return b == ' ' || b == '\t' || b == '\n' || b == '\r' } diff --git a/libgo/go/go/format/format_test.go b/libgo/go/go/format/format_test.go index 93f0992477..d7846bec65 100644 --- a/libgo/go/go/format/format_test.go +++ b/libgo/go/go/format/format_test.go @@ -87,7 +87,11 @@ var tests = []string{ "\tx := 0\n\tgo f()\n\n\n", "\n\t\t\n\n\tx := 0\n\tgo f()\n\n\n", "\n\t\t\n\n\t\t\tx := 0\n\t\t\tgo f()\n\n\n", - "\n\t\t\n\n\t\t\tx := 0\n\t\t\tconst s = `\nfoo\n`\n\n\n", // no indentation inside raw strings + "\n\t\t\n\n\t\t\tx := 0\n\t\t\tconst s = `\nfoo\n`\n\n\n", // no indentation added inside raw strings + "\n\t\t\n\n\t\t\tx := 0\n\t\t\tconst s = `\n\t\tfoo\n`\n\n\n", // no indentation removed inside raw strings + + // comments + "i := 5 /* Comment */", // Issue 5551. // erroneous programs "ERROR1 + 2 +", diff --git a/libgo/go/go/parser/error_test.go b/libgo/go/go/parser/error_test.go index d4d4f909d3..48fb53e5b0 100644 --- a/libgo/go/go/parser/error_test.go +++ b/libgo/go/go/parser/error_test.go @@ -34,7 +34,7 @@ import ( const testdata = "testdata" -var fsetErrs *token.FileSet +var fsetErrs = token.NewFileSet() // getFile assumes that each filename occurs at most once func getFile(filename string) (file *token.File) { @@ -59,8 +59,11 @@ func getPos(filename string, offset int) token.Pos { // ERROR comments must be of the form /* ERROR "rx" */ and rx is // a regular expression that matches the expected error message. +// The special form /* ERROR HERE "rx" */ must be used for error +// messages that appear immediately after a token, rather than at +// a token's position. // -var errRx = regexp.MustCompile(`^/\* *ERROR *"([^"]*)" *\*/$`) +var errRx = regexp.MustCompile(`^/\* *ERROR *(HERE)? *"([^"]*)" *\*/$`) // expectedErrors collects the regular expressions of ERROR comments found // in files and returns them as a map of error positions to error messages. @@ -74,6 +77,7 @@ func expectedErrors(t *testing.T, filename string, src []byte) map[token.Pos]str // not match the position information collected by the parser s.Init(getFile(filename), 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 for { pos, tok, lit := s.Scan() @@ -82,11 +86,22 @@ func expectedErrors(t *testing.T, filename string, src []byte) map[token.Pos]str return errors case token.COMMENT: s := errRx.FindStringSubmatch(lit) - if len(s) == 2 { - errors[prev] = string(s[1]) + if len(s) == 3 { + pos := prev + if s[1] == "HERE" { + pos = here + } + errors[pos] = string(s[2]) } default: prev = pos + var l int // token length + if tok.IsLiteral() { + l = len(lit) + } else { + l = len(tok.String()) + } + here = prev + token.Pos(l) } } } @@ -154,7 +169,6 @@ func checkErrors(t *testing.T, filename string, input interface{}) { } func TestErrors(t *testing.T) { - fsetErrs = token.NewFileSet() list, err := ioutil.ReadDir(testdata) if err != nil { t.Fatal(err) diff --git a/libgo/go/go/parser/interface.go b/libgo/go/go/parser/interface.go index 0f83ca9314..49103058b5 100644 --- a/libgo/go/go/parser/interface.go +++ b/libgo/go/go/parser/interface.go @@ -182,6 +182,13 @@ func ParseExpr(x string) (ast.Expr, error) { p.closeScope() assert(p.topScope == nil, "unbalanced scopes") + // If a semicolon was inserted, consume it; + // report an error if there's more tokens. + if p.tok == token.SEMICOLON && p.lit == "\n" { + p.next() + } + p.expect(token.EOF) + if p.errors.Len() > 0 { p.errors.Sort() return nil, p.errors.Err() diff --git a/libgo/go/go/parser/parser.go b/libgo/go/go/parser/parser.go index c4523318f2..4a005d8ffa 100644 --- a/libgo/go/go/parser/parser.go +++ b/libgo/go/go/parser/parser.go @@ -492,6 +492,26 @@ func syncDecl(p *parser) { } } +// safePos returns a valid file position for a given position: If pos +// is valid to begin with, safePos returns pos. If pos is out-of-range, +// safePos returns the EOF position. +// +// This is hack to work around "artificial" end positions in the AST which +// are computed by adding 1 to (presumably valid) token positions. If the +// token positions are invalid due to parse errors, the resulting end position +// may be past the file's EOF position, which would lead to panics if used +// later on. +// +func (p *parser) safePos(pos token.Pos) (res token.Pos) { + defer func() { + if recover() != nil { + res = token.Pos(p.file.Base() + p.file.Size()) // EOF position + } + }() + _ = p.file.Offset(pos) // trigger a panic if position is out-of-range + return pos +} + // ---------------------------------------------------------------------------- // Identifiers @@ -621,6 +641,7 @@ func (p *parser) parseArrayType() ast.Expr { } lbrack := p.expect(token.LBRACK) + p.exprLev++ var len ast.Expr // always permit ellipsis for more fault-tolerant parsing if p.tok == token.ELLIPSIS { @@ -629,6 +650,7 @@ func (p *parser) parseArrayType() ast.Expr { } else if p.tok != token.RBRACK { len = p.parseRhs() } + p.exprLev-- p.expect(token.RBRACK) elt := p.parseType() @@ -679,7 +701,7 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field { if n := len(list); n > 1 || !isTypeName(deref(typ)) { pos := typ.Pos() p.errorExpected(pos, "anonymous field") - typ = &ast.BadExpr{From: pos, To: list[n-1].End()} + typ = &ast.BadExpr{From: pos, To: p.safePos(list[n-1].End())} } } @@ -803,9 +825,10 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [ // parameter or result variable is the function body. p.declare(field, nil, scope, ast.Var, idents...) p.resolve(typ) - if p.tok == token.COMMA { - p.next() + if !p.atComma("parameter list") { + return } + p.next() for p.tok != token.RPAREN && p.tok != token.EOF { idents := p.parseIdentList() typ := p.parseVarType(ellipsisOk) @@ -820,15 +843,15 @@ func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params [ } p.next() } - } else { - // Type { "," Type } (anonymous parameters) - params = make([]*ast.Field, len(list)) - for i, typ := range list { - p.resolve(typ) - params[i] = &ast.Field{Type: 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} + } return } @@ -1168,16 +1191,19 @@ func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr { defer un(trace(p, "IndexOrSlice")) } + const N = 3 // change the 3 to 2 to disable 3-index slices lbrack := p.expect(token.LBRACK) p.exprLev++ - var index [3]ast.Expr // change the 3 to 2 to disable slice expressions w/ cap + var index [N]ast.Expr + var colons [N - 1]token.Pos if p.tok != token.COLON { index[0] = p.parseRhs() } ncolons := 0 - for p.tok == token.COLON && ncolons < len(index)-1 { - p.next() + 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() } @@ -1187,7 +1213,21 @@ func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr { if ncolons > 0 { // slice expression - return &ast.SliceExpr{X: x, Lbrack: lbrack, Low: index[0], High: index[1], Max: index[2], Slice3: ncolons == 2, Rbrack: rbrack} + slice3 := false + if ncolons == 2 { + slice3 = true + // Check presence of 2nd and 3rd index here rather than during type-checking + // to prevent erroneous programs from passing through gofmt (was issue 7305). + if index[1] == nil { + p.error(colons[0], "2nd index required in 3-index slice") + index[1] = &ast.BadExpr{From: colons[0] + 1, To: colons[1]} + } + if index[2] == nil { + p.error(colons[1], "3rd index required in 3-index slice") + index[2] = &ast.BadExpr{From: colons[1] + 1, To: rbrack} + } + } + 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} @@ -1320,7 +1360,7 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr { default: // all other nodes are not proper expressions p.errorExpected(x.Pos(), "expression") - x = &ast.BadExpr{From: x.Pos(), To: x.End()} + x = &ast.BadExpr{From: x.Pos(), To: p.safePos(x.End())} } return x } @@ -1383,7 +1423,7 @@ func (p *parser) checkExprOrType(x ast.Expr) ast.Expr { case *ast.ArrayType: if len, isEllipsis := t.Len.(*ast.Ellipsis); isEllipsis { p.error(len.Pos(), "expected array length, found '...'") - x = &ast.BadExpr{From: x.Pos(), To: x.End()} + x = &ast.BadExpr{From: x.Pos(), To: p.safePos(x.End())} } } @@ -1669,14 +1709,14 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) { return &ast.ExprStmt{X: x[0]}, false } -func (p *parser) parseCallExpr() *ast.CallExpr { +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 { return call } if _, isBad := x.(*ast.BadExpr); !isBad { // only report error if it's a new one - p.errorExpected(x.Pos(), "function/method call") + p.error(p.safePos(x.End()), fmt.Sprintf("function must be invoked in %s statement", callType)) } return nil } @@ -1687,7 +1727,7 @@ func (p *parser) parseGoStmt() ast.Stmt { } pos := p.expect(token.GO) - call := p.parseCallExpr() + call := p.parseCallExpr("go") p.expectSemi() if call == nil { return &ast.BadStmt{From: pos, To: pos + 2} // len("go") @@ -1702,7 +1742,7 @@ func (p *parser) parseDeferStmt() ast.Stmt { } pos := p.expect(token.DEFER) - call := p.parseCallExpr() + call := p.parseCallExpr("defer") p.expectSemi() if call == nil { return &ast.BadStmt{From: pos, To: pos + 5} // len("defer") @@ -1745,15 +1785,15 @@ func (p *parser) parseBranchStmt(tok token.Token) *ast.BranchStmt { return &ast.BranchStmt{TokPos: pos, Tok: tok, Label: label} } -func (p *parser) makeExpr(s ast.Stmt) ast.Expr { +func (p *parser) makeExpr(s ast.Stmt, kind string) ast.Expr { if s == nil { return nil } if es, isExpr := s.(*ast.ExprStmt); isExpr { return p.checkExpr(es.X) } - p.error(s.Pos(), "expected condition, found simple statement") - return &ast.BadExpr{From: s.Pos(), To: s.End()} + p.error(s.Pos(), fmt.Sprintf("expected %s, found simple statement (missing parentheses around composite literal?)", kind)) + return &ast.BadExpr{From: s.Pos(), To: p.safePos(s.End())} } func (p *parser) parseIfStmt() *ast.IfStmt { @@ -1779,7 +1819,7 @@ func (p *parser) parseIfStmt() *ast.IfStmt { p.next() x = p.parseRhs() } else { - x = p.makeExpr(s) + x = p.makeExpr(s, "boolean expression") s = nil } } @@ -1910,7 +1950,7 @@ func (p *parser) parseSwitchStmt() ast.Stmt { return &ast.TypeSwitchStmt{Switch: pos, Init: s1, Assign: s2, Body: body} } - return &ast.SwitchStmt{Switch: pos, Init: s1, Tag: p.makeExpr(s2), Body: body} + return &ast.SwitchStmt{Switch: pos, Init: s1, Tag: p.makeExpr(s2, "switch expression"), Body: body} } func (p *parser) parseCommClause() *ast.CommClause { @@ -2004,7 +2044,16 @@ func (p *parser) parseForStmt() ast.Stmt { prevLev := p.exprLev p.exprLev = -1 if p.tok != token.SEMICOLON { - s2, isRange = p.parseSimpleStmt(rangeOk) + if p.tok == token.RANGE { + // "for range x" (nil lhs in assignment) + pos := p.pos + p.next() + y := []ast.Expr{&ast.UnaryExpr{OpPos: pos, Op: token.RANGE, X: p.parseRhs()}} + s2 = &ast.AssignStmt{Rhs: y} + isRange = true + } else { + s2, isRange = p.parseSimpleStmt(rangeOk) + } } if !isRange && p.tok == token.SEMICOLON { p.next() @@ -2029,13 +2078,15 @@ func (p *parser) parseForStmt() ast.Stmt { // check lhs var key, value ast.Expr switch len(as.Lhs) { - case 2: - key, value = as.Lhs[0], as.Lhs[1] + case 0: + // nothing to do case 1: key = as.Lhs[0] + case 2: + key, value = as.Lhs[0], as.Lhs[1] default: - p.errorExpected(as.Lhs[0].Pos(), "1 or 2 expressions") - return &ast.BadStmt{From: pos, To: body.End()} + p.errorExpected(as.Lhs[len(as.Lhs)-1].Pos(), "at most 2 expressions") + return &ast.BadStmt{From: pos, To: p.safePos(body.End())} } // parseSimpleStmt returned a right-hand side that // is a single unary expression of the form "range x" @@ -2055,7 +2106,7 @@ func (p *parser) parseForStmt() ast.Stmt { return &ast.ForStmt{ For: pos, Init: s1, - Cond: p.makeExpr(s2), + Cond: p.makeExpr(s2, "boolean or range expression"), Post: s3, Body: body, } @@ -2259,36 +2310,6 @@ func (p *parser) parseGenDecl(keyword token.Token, f parseSpecFunction) *ast.Gen } } -func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList { - if p.trace { - defer un(trace(p, "Receiver")) - } - - par := p.parseParameters(scope, false) - - // must have exactly one receiver - if par.NumFields() != 1 { - p.errorExpected(par.Opening, "exactly one receiver") - par.List = []*ast.Field{{Type: &ast.BadExpr{From: par.Opening, To: par.Closing + 1}}} - return par - } - - // recv type must be of the form ["*"] identifier - recv := par.List[0] - base := deref(recv.Type) - if _, isIdent := base.(*ast.Ident); !isIdent { - if _, isBad := base.(*ast.BadExpr); !isBad { - // only report error if it's a new one - p.errorExpected(base.Pos(), "(unqualified) identifier") - } - par.List = []*ast.Field{ - {Type: &ast.BadExpr{From: recv.Pos(), To: recv.End()}}, - } - } - - return par -} - func (p *parser) parseFuncDecl() *ast.FuncDecl { if p.trace { defer un(trace(p, "FunctionDecl")) @@ -2300,7 +2321,7 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl { var recv *ast.FieldList if p.tok == token.LPAREN { - recv = p.parseReceiver(scope) + recv = p.parseParameters(scope, false) } ident := p.parseIdent() diff --git a/libgo/go/go/parser/parser_test.go b/libgo/go/go/parser/parser_test.go index 0a34b7e505..85065fd182 100644 --- a/libgo/go/go/parser/parser_test.go +++ b/libgo/go/go/parser/parser_test.go @@ -74,32 +74,57 @@ func TestParseExpr(t *testing.T) { src := "a + b" x, err := ParseExpr(src) if err != nil { - t.Fatalf("ParseExpr(%s): %v", src, err) + t.Errorf("ParseExpr(%q): %v", src, err) } // sanity check if _, ok := x.(*ast.BinaryExpr); !ok { - t.Errorf("ParseExpr(%s): got %T, expected *ast.BinaryExpr", src, x) + t.Errorf("ParseExpr(%q): got %T, want *ast.BinaryExpr", src, x) } // a valid type expression src = "struct{x *int}" x, err = ParseExpr(src) if err != nil { - t.Fatalf("ParseExpr(%s): %v", src, err) + t.Errorf("ParseExpr(%q): %v", src, err) } // sanity check if _, ok := x.(*ast.StructType); !ok { - t.Errorf("ParseExpr(%s): got %T, expected *ast.StructType", src, x) + t.Errorf("ParseExpr(%q): got %T, want *ast.StructType", src, x) } // an invalid expression src = "a + *" - _, err = ParseExpr(src) - if err == nil { - t.Fatalf("ParseExpr(%s): %v", src, err) + if _, err := ParseExpr(src); err == nil { + t.Errorf("ParseExpr(%q): got no error", src) } - // it must not crash + // a valid expression followed by extra tokens is invalid + src = "a[i] := x" + if _, err := ParseExpr(src); err == nil { + t.Errorf("ParseExpr(%q): got no error", src) + } + + // a semicolon is not permitted unless automatically inserted + src = "a + b\n" + if _, err := ParseExpr(src); err != nil { + t.Errorf("ParseExpr(%q): got error %s", src, err) + } + src = "a + b;" + if _, err := ParseExpr(src); err == nil { + t.Errorf("ParseExpr(%q): got no error", src) + } + + // various other stuff following a valid expression + const validExpr = "a + b" + const anything = "dh3*#D)#_" + for _, c := range "!)]};," { + src := validExpr + string(c) + anything + if _, err := ParseExpr(src); err == nil { + t.Errorf("ParseExpr(%q): got no error", src) + } + } + + // ParseExpr must not crash for _, src := range valids { ParseExpr(src) } diff --git a/libgo/go/go/parser/short_test.go b/libgo/go/go/parser/short_test.go index 0ef0c560c4..05e44de28a 100644 --- a/libgo/go/go/parser/short_test.go +++ b/libgo/go/go/parser/short_test.go @@ -35,6 +35,11 @@ var valids = []string{ `package p; func f() { for _ = range "foo" + "bar" {} };`, `package p; func f() { var s []int; g(s[:], s[i:], s[:j], s[i:j], s[i:j:k], s[:j:k]) };`, `package p; var ( _ = (struct {*T}).m; _ = (interface {T}).m )`, + `package p; func ((T),) m() {}`, + `package p; func ((*T),) m() {}`, + `package p; func (*(T),) m() {}`, + `package p; func _(x []int) { for range x {} }`, + `package p; func _() { if [T{}.n]int{} {} }`, } func TestValid(t *testing.T) { @@ -48,14 +53,14 @@ var invalids = []string{ `package p; func f() { if { /* ERROR "expected operand" */ } };`, `package p; func f() { if ; { /* ERROR "expected operand" */ } };`, `package p; func f() { if f(); { /* ERROR "expected operand" */ } };`, - `package p; func f() { if _ /* ERROR "expected condition" */ = range x; true {} };`, - `package p; func f() { switch _ /* ERROR "expected condition" */ = range x; true {} };`, + `package p; func f() { if _ /* ERROR "expected boolean expression" */ = range x; true {} };`, + `package p; func f() { switch _ /* ERROR "expected switch expression" */ = range x; true {} };`, `package p; func f() { for _ = range x ; /* ERROR "expected '{'" */ ; {} };`, `package p; func f() { for ; ; _ = range /* ERROR "expected operand" */ x {} };`, - `package p; func f() { for ; _ /* ERROR "expected condition" */ = range x ; {} };`, - `package p; func f() { switch t /* ERROR "expected condition" */ = t.(type) {} };`, - `package p; func f() { switch t /* ERROR "expected condition" */ , t = t.(type) {} };`, - `package p; func f() { switch t /* ERROR "expected condition" */ = t.(type), t {} };`, + `package p; func f() { for ; _ /* ERROR "expected boolean or range expression" */ = range x ; {} };`, + `package p; func f() { switch t /* ERROR "expected switch expression" */ = t.(type) {} };`, + `package p; func f() { switch t /* ERROR "expected switch expression" */ , t = t.(type) {} };`, + `package p; func f() { switch t /* ERROR "expected switch expression" */ = t.(type), t {} };`, `package p; var a = [ /* ERROR "expected expression" */ 1]int;`, `package p; var a = [ /* ERROR "expected expression" */ ...]int;`, `package p; var a = struct /* ERROR "expected expression" */ {}`, @@ -76,8 +81,20 @@ var invalids = []string{ `package p; func f() { _ = x = /* ERROR "expected '=='" */ 0 {}};`, `package p; func f() { _ = 1 == func()int { var x bool; x = x = /* ERROR "expected '=='" */ true; return x }() };`, `package p; func f() { var s []int; _ = s[] /* ERROR "expected operand" */ };`, - `package p; func f() { var s []int; _ = s[::: /* ERROR "expected ']'" */ ] };`, + `package p; func f() { var s []int; _ = s[i:j: /* ERROR "3rd index required" */ ] };`, + `package p; func f() { var s []int; _ = s[i: /* ERROR "2nd index required" */ :k] };`, + `package p; func f() { var s []int; _ = s[i: /* ERROR "2nd index required" */ :] };`, + `package p; func f() { var s []int; _ = s[: /* ERROR "2nd index required" */ :] };`, + `package p; func f() { var s []int; _ = s[: /* ERROR "2nd index required" */ ::] };`, `package p; func f() { var s []int; _ = s[i:j:k: /* ERROR "expected ']'" */ l] };`, + `package p; func f() { for x /* ERROR "boolean or range expression" */ = []string {} }`, + `package p; func f() { for x /* ERROR "boolean or range expression" */ := []string {} }`, + `package p; func f() { for i /* ERROR "boolean or range expression" */ , x = []string {} }`, + `package p; func f() { for i /* ERROR "boolean or range expression" */ , x := []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 "expected '\)'" */ (){}) } } }`, + `package p; func f() (a b string /* ERROR "expected '\)'" */ , ok bool) // issue 8656`, } func TestInvalid(t *testing.T) { diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go index 583c6c3709..d5a69349be 100644 --- a/libgo/go/go/printer/nodes.go +++ b/libgo/go/go/printer/nodes.go @@ -163,8 +163,8 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp size := 0 // print all list elements + prevLine := prev.Line for i, x := range list { - prevLine := line line = p.lineFor(x.Pos()) // determine if the next linebreak, if any, needs to use formfeed: @@ -207,8 +207,8 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp } } + needsLinebreak := 0 < prevLine && prevLine < line if i > 0 { - needsLinebreak := prevLine < line && prevLine > 0 && line > 0 // use position of expression following the comma as // comma position for correct comment placement, but // only if the expression is on the same line @@ -232,16 +232,20 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp } } - if isPair && size > 0 && len(list) > 1 { - // we have a key:value expression that fits onto one line and - // is in a list with more then one entry: use a column for the - // key such that consecutive entries can align if possible + if len(list) > 1 && isPair && size > 0 && needsLinebreak { + // we have a key:value expression that fits onto one line + // and it's not on the same line as the prior expression: + // use a column for the key such that consecutive entries + // can align if possible + // (needsLinebreak is set if we started a new line before) p.expr(pair.Key) p.print(pair.Colon, token.COLON, vtab) p.expr(pair.Value) } else { p.expr0(x, depth) } + + prevLine = line } if mode&commaTerm != 0 && next.IsValid() && p.pos.Line < next.Line { @@ -378,10 +382,6 @@ func (p *printer) setLineComment(text string) { p.setComment(&ast.CommentGroup{List: []*ast.Comment{{Slash: token.NoPos, Text: text}}}) } -func (p *printer) isMultiLine(n ast.Node) bool { - return p.lineFor(n.End())-p.lineFor(n.Pos()) > 0 -} - func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) { lbrace := fields.Opening list := fields.List @@ -428,13 +428,14 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) if len(list) == 1 { sep = blank } - newSection := false + var line int for i, f := range list { if i > 0 { - p.linebreak(p.lineFor(f.Pos()), 1, ignore, newSection) + p.linebreak(p.lineFor(f.Pos()), 1, ignore, p.linesFrom(line) > 0) } extraTabs := 0 p.setComment(f.Doc) + p.recordLine(&line) if len(f.Names) > 0 { // named fields p.identList(f.Names, false) @@ -460,7 +461,6 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) } p.setComment(f.Comment) } - newSection = p.isMultiLine(f) } if isIncomplete { if len(list) > 0 { @@ -472,12 +472,13 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) } else { // interface - newSection := false + var line int for i, f := range list { if i > 0 { - p.linebreak(p.lineFor(f.Pos()), 1, ignore, newSection) + p.linebreak(p.lineFor(f.Pos()), 1, 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]) @@ -487,7 +488,6 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool) p.expr(f.Type) } p.setComment(f.Comment) - newSection = p.isMultiLine(f) } if isIncomplete { if len(list) > 0 { @@ -736,7 +736,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) { if _, hasParens := x.X.(*ast.ParenExpr); hasParens { // don't print parentheses around an already parenthesized expression // TODO(gri) consider making this more general and incorporate precedence levels - p.expr0(x.X, reduceDepth(depth)) // parentheses undo one level of depth + p.expr0(x.X, depth) } else { p.print(token.LPAREN) p.expr0(x.X, reduceDepth(depth)) // parentheses undo one level of depth @@ -826,10 +826,16 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) { } p.print(x.Lbrace, token.LBRACE) p.exprList(x.Lbrace, x.Elts, 1, commaTerm, x.Rbrace) - // do not insert extra line breaks because of comments before - // the closing '}' as it might break the code if there is no - // trailing ',' - p.print(noExtraLinebreak, x.Rbrace, token.RBRACE, noExtraLinebreak) + // do not insert extra line break following a /*-style comment + // before the closing '}' as it might break the code if there + // is no trailing ',' + mode := noExtraLinebreak + // do not insert extra blank following a /*-style comment + // before the closing '}' unless the literal is empty + if len(x.Elts) > 0 { + mode |= noExtraBlank + } + p.print(mode, x.Rbrace, token.RBRACE, mode) case *ast.Ellipsis: p.print(token.ELLIPSIS) @@ -901,20 +907,31 @@ func (p *printer) stmtList(list []ast.Stmt, nindent int, nextIsRBrace bool) { if nindent > 0 { p.print(indent) } - multiLine := false + var line int i := 0 for _, s := range list { // ignore empty statements (was issue 3466) if _, isEmpty := s.(*ast.EmptyStmt); !isEmpty { - // _indent == 0 only for lists of switch/select case clauses; + // nindent == 0 only for lists of switch/select case clauses; // in those cases each clause is a new section if len(p.output) > 0 { // only print line break if we are not at the beginning of the output // (i.e., we are not printing only a partial program) - p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || nindent == 0 || multiLine) + p.linebreak(p.lineFor(s.Pos()), 1, ignore, i == 0 || nindent == 0 || p.linesFrom(line) > 0) } + p.recordLine(&line) p.stmt(s, nextIsRBrace && i == len(list)-1) - multiLine = p.isMultiLine(s) + // labeled statements put labels on a separate line, but here + // we only care about the start line of the actual statement + // without label - correct line for each label + for t := s; ; { + lt, _ := t.(*ast.LabeledStmt) + if lt == nil { + break + } + line++ + t = lt.Stmt + } i++ } } @@ -1203,14 +1220,17 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) { case *ast.RangeStmt: p.print(token.FOR, blank) - p.expr(s.Key) - if s.Value != nil { - // use position of value following the comma as - // comma position for correct comment placement - p.print(s.Value.Pos(), token.COMMA, blank) - p.expr(s.Value) - } - p.print(blank, s.TokPos, s.Tok, blank, token.RANGE, blank) + if s.Key != nil { + p.expr(s.Key) + if s.Value != nil { + // use position of value following the comma as + // comma position for correct comment placement + p.print(s.Value.Pos(), token.COMMA, blank) + p.expr(s.Value) + } + p.print(blank, s.TokPos, s.Tok, blank) + } + p.print(token.RANGE, blank) p.expr(stripParens(s.X)) p.print(blank) p.block(s.Body, 1) @@ -1375,22 +1395,22 @@ func (p *printer) genDecl(d *ast.GenDecl) { // two or more grouped const/var declarations: // determine if the type column must be kept keepType := keepTypeColumn(d.Specs) - newSection := false + var line int for i, s := range d.Specs { if i > 0 { - p.linebreak(p.lineFor(s.Pos()), 1, ignore, newSection) + p.linebreak(p.lineFor(s.Pos()), 1, ignore, p.linesFrom(line) > 0) } + p.recordLine(&line) p.valueSpec(s.(*ast.ValueSpec), keepType[i]) - newSection = p.isMultiLine(s) } } else { - newSection := false + var line int for i, s := range d.Specs { if i > 0 { - p.linebreak(p.lineFor(s.Pos()), 1, ignore, newSection) + p.linebreak(p.lineFor(s.Pos()), 1, ignore, p.linesFrom(line) > 0) } + p.recordLine(&line) p.spec(s, n, false) - newSection = p.isMultiLine(s) } } p.print(unindent, formfeed) @@ -1448,13 +1468,16 @@ func (p *printer) bodySize(b *ast.BlockStmt, maxSize int) int { // opening and closing brace are on different lines - don't make it a one-liner return maxSize + 1 } - if len(b.List) > 5 || p.commentBefore(p.posFor(pos2)) { - // too many statements or there is a comment inside - don't make it a one-liner + if len(b.List) > 5 { + // too many statements - don't make it a one-liner return maxSize + 1 } // otherwise, estimate body size - bodySize := 0 + bodySize := p.commentSizeBefore(p.posFor(pos2)) for i, s := range b.List { + if bodySize > maxSize { + break // no need to continue + } if i > 0 { bodySize += 2 // space for a semicolon and blank } @@ -1488,7 +1511,7 @@ func (p *printer) adjBlock(headerSize int, sep whiteSpace, b *ast.BlockStmt) { } p.print(blank) } - p.print(b.Rbrace, token.RBRACE) + p.print(noExtraLinebreak, b.Rbrace, token.RBRACE, noExtraLinebreak) return } diff --git a/libgo/go/go/printer/printer.go b/libgo/go/go/printer/printer.go index e06d2edfb2..280c697a0d 100644 --- a/libgo/go/go/printer/printer.go +++ b/libgo/go/go/printer/printer.go @@ -39,9 +39,17 @@ const ( type pmode int const ( - noExtraLinebreak pmode = 1 << iota + noExtraBlank pmode = 1 << iota // disables extra blank after /*-style comment + noExtraLinebreak // disables extra line break after /*-style comment ) +type commentInfo struct { + cindex int // current comment index + comment *ast.CommentGroup // = printer.comments[cindex]; or nil + commentOffset int // = printer.posFor(printer.comments[cindex].List[0].Pos()).Offset; or infinity + commentNewline bool // true if the comment group contains newlines +} + type printer struct { // Configuration (does not change after initialization) Config @@ -52,7 +60,8 @@ type printer struct { indent int // current indentation mode pmode // current printer mode impliedSemi bool // if set, a linebreak implies a semicolon - lastTok token.Token // the last token printed (token.ILLEGAL if it's whitespace) + lastTok token.Token // last token printed (token.ILLEGAL if it's whitespace) + prevOpen token.Token // previous non-brace "open" token (, [, or token.ILLEGAL wsbuf []whiteSpace // delayed white space // Positions @@ -61,19 +70,17 @@ type printer struct { // white space). If there's a difference and SourcePos is set in // ConfigMode, //line comments are used in the output to restore // original source positions for a reader. - pos token.Position // current position in AST (source) space - out token.Position // current position in output space - last token.Position // value of pos after calling writeString + pos token.Position // current position in AST (source) space + out token.Position // current position in output space + last token.Position // value of pos after calling writeString + linePtr *int // if set, record out.Line for the next token in *linePtr // The list of all source comments, in order of appearance. comments []*ast.CommentGroup // may be nil - cindex int // current comment index useNodeComments bool // if not set, ignore lead and line comments of nodes // Information about p.comments[p.cindex]; set up by nextComment. - comment *ast.CommentGroup // = p.comments[p.cindex]; or nil - commentOffset int // = p.posFor(p.comments[p.cindex].List[0].Pos()).Offset; or infinity - commentNewline bool // true if the comment group contains newlines + commentInfo // Cache of already computed node sizes. nodeSizes map[ast.Node]int @@ -93,6 +100,14 @@ func (p *printer) init(cfg *Config, fset *token.FileSet, nodeSizes map[ast.Node] p.cachedPos = -1 } +func (p *printer) internalError(msg ...interface{}) { + if debug { + fmt.Print(p.pos.String() + ": ") + fmt.Println(msg...) + panic("go/printer") + } +} + // commentsHaveNewline reports whether a list of comments belonging to // an *ast.CommentGroup contains newlines. Because the position information // may only be partially correct, we also have to read the comment text. @@ -129,12 +144,49 @@ func (p *printer) nextComment() { p.commentOffset = infinity } -func (p *printer) internalError(msg ...interface{}) { - if debug { - fmt.Print(p.pos.String() + ": ") - fmt.Println(msg...) - panic("go/printer") +// commentBefore returns true iff the current comment group occurs +// before the next position in the source code and printing it does +// not introduce implicit semicolons. +// +func (p *printer) commentBefore(next token.Position) bool { + return p.commentOffset < next.Offset && (!p.impliedSemi || !p.commentNewline) +} + +// commentSizeBefore returns the estimated size of the +// comments on the same line before the next position. +// +func (p *printer) commentSizeBefore(next token.Position) int { + // save/restore current p.commentInfo (p.nextComment() modifies it) + defer func(info commentInfo) { + p.commentInfo = info + }(p.commentInfo) + + size := 0 + for p.commentBefore(next) { + for _, c := range p.comment.List { + size += len(c.Text) + } + p.nextComment() } + return size +} + +// recordLine records the output line number for the next non-whitespace +// token in *linePtr. It is used to compute an accurate line number for a +// formatted construct, independent of pending (not yet emitted) whitespace +// or comments. +// +func (p *printer) recordLine(linePtr *int) { + p.linePtr = linePtr +} + +// linesFrom returns the number of output lines between the current +// output line and the line argument, ignoring any pending (not yet +// emitted) whitespace or comments. It is used to compute an accurate +// size (in number of lines) for a formatted construct. +// +func (p *printer) linesFrom(line int) int { + return p.out.Line - line } func (p *printer) posFor(pos token.Pos) token.Position { @@ -675,10 +727,14 @@ func (p *printer) intersperseComments(next token.Position, tok token.Token) (wro if last != nil { // if the last comment is a /*-style comment and the next item - // follows on the same line but is not a comma or a "closing" - // token, add an extra blank for separation - if last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line && tok != token.COMMA && - tok != token.RPAREN && tok != token.RBRACK && tok != token.RBRACE { + // follows on the same line but is not a comma, and not a "closing" + // token immediately following its corresponding "opening" token, + // add an extra blank for separation unless explicitly disabled + if p.mode&noExtraBlank == 0 && + last.Text[1] == '*' && p.lineFor(last.Pos()) == next.Line && + tok != token.COMMA && + (tok != token.RPAREN || p.prevOpen == token.LPAREN) && + (tok != token.RBRACK || p.prevOpen == token.LBRACK) { p.writeByte(' ', 1) } // ensure that there is a line break after a //-style comment, @@ -735,12 +791,8 @@ func (p *printer) writeWhitespace(n int) { } // shift remaining entries down - i := 0 - for ; n < len(p.wsbuf); n++ { - p.wsbuf[i] = p.wsbuf[n] - i++ - } - p.wsbuf = p.wsbuf[0:i] + l := copy(p.wsbuf, p.wsbuf[n:]) + p.wsbuf = p.wsbuf[:l] } // ---------------------------------------------------------------------------- @@ -790,6 +842,17 @@ func (p *printer) print(args ...interface{}) { var isLit bool var impliedSemi bool // value for p.impliedSemi after this arg + // record previous opening token, if any + switch p.lastTok { + case token.ILLEGAL: + // ignore (white space) + case token.LPAREN, token.LBRACK: + p.prevOpen = p.lastTok + default: + // other tokens followed any opening token + p.prevOpen = token.ILLEGAL + } + switch x := arg.(type) { case pmode: // toggle printer mode @@ -899,19 +962,17 @@ func (p *printer) print(args ...interface{}) { } } + // the next token starts now - record its line number if requested + if p.linePtr != nil { + *p.linePtr = p.out.Line + p.linePtr = nil + } + p.writeString(next, data, isLit) p.impliedSemi = impliedSemi } } -// commentBefore returns true iff the current comment group occurs -// before the next position in the source code and printing it does -// not introduce implicit semicolons. -// -func (p *printer) commentBefore(next token.Position) (result bool) { - return p.commentOffset < next.Offset && (!p.impliedSemi || !p.commentNewline) -} - // flush prints any pending comments and whitespace occurring textually // before the position of the next token tok. The flush result indicates // if a newline was written or if a formfeed was dropped from the whitespace diff --git a/libgo/go/go/printer/printer_test.go b/libgo/go/go/printer/printer_test.go index 8454ac12b9..3b0570e5b5 100644 --- a/libgo/go/go/printer/printer_test.go +++ b/libgo/go/go/printer/printer_test.go @@ -63,7 +63,7 @@ func format(src []byte, mode checkMode) ([]byte, error) { return nil, fmt.Errorf("print: %s", err) } - // make sure formated output is syntactically correct + // make sure formatted output is syntactically correct res := buf.Bytes() if _, err := parser.ParseFile(fset, "", res, 0); err != nil { return nil, fmt.Errorf("re-parse: %s\n%s", err, buf.Bytes()) @@ -159,13 +159,6 @@ func runcheck(t *testing.T, source, golden string, mode checkMode) { } func check(t *testing.T, source, golden string, mode checkMode) { - // start a timer to produce a time-out signal - tc := make(chan int) - go func() { - time.Sleep(10 * time.Second) // plenty of a safety margin, even for very slow machines - tc <- 0 - }() - // run the test cc := make(chan int) go func() { @@ -173,13 +166,13 @@ func check(t *testing.T, source, golden string, mode checkMode) { cc <- 0 }() - // wait for the first finisher + // wait with timeout select { - case <-tc: + case <-time.After(10 * time.Second): // plenty of a safety margin, even for very slow machines // test running past time out t.Errorf("%s: running too slowly", source) case <-cc: - // test finished within alloted time margin + // test finished within allotted time margin } } @@ -212,7 +205,7 @@ func TestFiles(t *testing.T) { } } -// TestLineComments, using a simple test case, checks that consequtive line +// TestLineComments, using a simple test case, checks that consecutive line // comments are properly terminated with a newline even if the AST position // information is incorrect. // @@ -357,7 +350,7 @@ func idents(f *ast.File) <-chan *ast.Ident { // identCount returns the number of identifiers found in f. func identCount(f *ast.File) int { n := 0 - for _ = range idents(f) { + for range idents(f) { n++ } return n diff --git a/libgo/go/go/printer/testdata/comments.golden b/libgo/go/go/printer/testdata/comments.golden index 610a42a68b..b1af7958a9 100644 --- a/libgo/go/go/printer/testdata/comments.golden +++ b/libgo/go/go/printer/testdata/comments.golden @@ -494,16 +494,21 @@ func _() { func _( /* this */ x /* is */ /* an */ int) { } -func _( /* no params */) {} +func _( /* no params - extra blank before and after comment */ ) {} +func _(a, b int /* params - no extra blank after comment */) {} + +func _() { f( /* no args - extra blank before and after comment */ ) } +func _() { f(a, b /* args - no extra blank after comment */) } func _() { - f( /* no args */) + f( /* no args - extra blank before and after comment */ ) + f(a, b /* args - no extra blank after comment */) } func ( /* comment1 */ T /* comment2 */) _() {} -func _() { /* one-line functions with comments are formatted as multi-line functions */ -} +func _() { /* "short-ish one-line functions with comments are formatted as multi-line functions */ } +func _() { x := 0; /* comment */ y = x /* comment */ } func _() { _ = 0 diff --git a/libgo/go/go/printer/testdata/comments.input b/libgo/go/go/printer/testdata/comments.input index d121dd4be7..983e2b2c97 100644 --- a/libgo/go/go/printer/testdata/comments.input +++ b/libgo/go/go/printer/testdata/comments.input @@ -500,15 +500,21 @@ func _() { func _(/* this */x/* is *//* an */ int) { } -func _(/* no params */) {} +func _(/* no params - extra blank before and after comment */) {} +func _(a, b int /* params - no extra blank after comment */) {} + +func _() { f(/* no args - extra blank before and after comment */) } +func _() { f(a, b /* args - no extra blank after comment */) } func _() { - f(/* no args */) + f(/* no args - extra blank before and after comment */) + f(a, b /* args - no extra blank after comment */) } func (/* comment1 */ T /* comment2 */) _() {} -func _() { /* one-line functions with comments are formatted as multi-line functions */ } +func _() { /* "short-ish one-line functions with comments are formatted as multi-line functions */ } +func _() { x := 0; /* comment */ y = x /* comment */ } func _() { _ = 0 diff --git a/libgo/go/go/printer/testdata/comments2.golden b/libgo/go/go/printer/testdata/comments2.golden index d3b50bf3e0..7676a26c12 100644 --- a/libgo/go/go/printer/testdata/comments2.golden +++ b/libgo/go/go/printer/testdata/comments2.golden @@ -77,3 +77,29 @@ func main() { println("test") } } + +func issue5623() { +L: + _ = yyyyyyyyyyyyyyyy // comment - should be aligned + _ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx /* comment */ + + _ = yyyyyyyyyyyyyyyy /* comment - should be aligned */ + _ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx // comment + +LLLLLLL: + _ = yyyyyyyyyyyyyyyy // comment - should be aligned + _ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx // comment + +LL: +LLLLL: + _ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx /* comment */ + _ = yyyyyyyyyyyyyyyy /* comment - should be aligned */ + + _ = xxxxxxxxxxxxxxxxxxxxxxxxxxxx // comment + _ = yyyyyyyyyyyyyyyy // comment - should be aligned + + // test case from issue +label: + mask := uint64(1)< 0 { if line, err := strconv.Atoi(string(text[i+1:])); err == nil && line > 0 { - // valid //line filename:line comment; - filename := filepath.Clean(string(text[len(prefix):i])) - if !filepath.IsAbs(filename) { - // make filename relative to current directory - filename = filepath.Join(s.dir, filename) + // valid //line filename:line comment + filename := string(bytes.TrimSpace(text[len(prefix):i])) + if filename != "" { + filename = filepath.Clean(filename) + if !filepath.IsAbs(filename) { + // make filename relative to current directory + filename = filepath.Join(s.dir, filename) + } } // update scanner position s.file.AddLineInfo(s.lineOffset+len(text)+1, filename, line) // +len(text)+1 since comment applies to next line @@ -358,73 +361,94 @@ exit: return tok, string(s.src[offs:s.offset]) } -func (s *Scanner) scanEscape(quote rune) { +// scanEscape parses an escape sequence where rune is the accepted +// escaped quote. In case of a syntax error, it stops at the offending +// character (without consuming it) and returns false. Otherwise +// it returns true. +func (s *Scanner) scanEscape(quote rune) bool { offs := s.offset - var i, base, max uint32 + var n int + var base, max uint32 switch s.ch { case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote: s.next() - return + return true case '0', '1', '2', '3', '4', '5', '6', '7': - i, base, max = 3, 8, 255 + n, base, max = 3, 8, 255 case 'x': s.next() - i, base, max = 2, 16, 255 + n, base, max = 2, 16, 255 case 'u': s.next() - i, base, max = 4, 16, unicode.MaxRune + n, base, max = 4, 16, unicode.MaxRune case 'U': s.next() - i, base, max = 8, 16, unicode.MaxRune + n, base, max = 8, 16, unicode.MaxRune default: - s.next() // always make progress - s.error(offs, "unknown escape sequence") - return + msg := "unknown escape sequence" + if s.ch < 0 { + msg = "escape sequence not terminated" + } + s.error(offs, msg) + return false } var x uint32 - for ; i > 0 && s.ch != quote && s.ch >= 0; i-- { + for n > 0 { d := uint32(digitVal(s.ch)) if d >= base { - s.error(s.offset, "illegal character in escape sequence") - break + msg := fmt.Sprintf("illegal character %#U in escape sequence", s.ch) + if s.ch < 0 { + msg = "escape sequence not terminated" + } + s.error(s.offset, msg) + return false } x = x*base + d s.next() + n-- } - // in case of an error, consume remaining chars - for ; i > 0 && s.ch != quote && s.ch >= 0; i-- { - s.next() - } + if x > max || 0xD800 <= x && x < 0xE000 { s.error(offs, "escape sequence is invalid Unicode code point") + return false } + + return true } -func (s *Scanner) scanChar() string { +func (s *Scanner) scanRune() string { // '\'' opening already consumed offs := s.offset - 1 + valid := true n := 0 - for s.ch != '\'' { + for { ch := s.ch - n++ - s.next() if ch == '\n' || ch < 0 { - s.error(offs, "character literal not terminated") - n = 1 + // only report error if we don't have one already + if valid { + s.error(offs, "rune literal not terminated") + valid = false + } break } + s.next() + if ch == '\'' { + break + } + n++ if ch == '\\' { - s.scanEscape('\'') + if !s.scanEscape('\'') { + valid = false + } + // continue to read to closing quote } } - s.next() - - if n != 1 { - s.error(offs, "illegal character literal") + if valid && n != 1 { + s.error(offs, "illegal rune literal") } return string(s.src[offs:s.offset]) @@ -434,11 +458,14 @@ func (s *Scanner) scanString() string { // '"' opening already consumed offs := s.offset - 1 - for s.ch != '"' { + for { ch := s.ch - s.next() if ch == '\n' || ch < 0 { - s.error(offs, "string not terminated") + s.error(offs, "string literal not terminated") + break + } + s.next() + if ch == '"' { break } if ch == '\\' { @@ -446,8 +473,6 @@ func (s *Scanner) scanString() string { } } - s.next() - return string(s.src[offs:s.offset]) } @@ -468,20 +493,21 @@ func (s *Scanner) scanRawString() string { offs := s.offset - 1 hasCR := false - for s.ch != '`' { + for { ch := s.ch + if ch < 0 { + s.error(offs, "raw string literal not terminated") + break + } s.next() + if ch == '`' { + break + } if ch == '\r' { hasCR = true } - if ch < 0 { - s.error(offs, "string not terminated") - break - } } - s.next() - lit := s.src[offs:s.offset] if hasCR { lit = stripCR(lit) @@ -617,7 +643,7 @@ scanAgain: case '\'': insertSemi = true tok = token.CHAR - lit = s.scanChar() + lit = s.scanRune() case '`': insertSemi = true tok = token.STRING diff --git a/libgo/go/go/scanner/scanner_test.go b/libgo/go/go/scanner/scanner_test.go index 8c64c2b95f..fc450d8a6e 100644 --- a/libgo/go/go/scanner/scanner_test.go +++ b/libgo/go/go/scanner/scanner_test.go @@ -493,9 +493,9 @@ var segments = []segment{ {"\nline3 //line File1.go:100", filepath.Join("dir", "TestLineComments"), 3}, // bad line comment, ignored {"\nline4", filepath.Join("dir", "TestLineComments"), 4}, {"\n//line File1.go:100\n line100", filepath.Join("dir", "File1.go"), 100}, + {"\n//line \t :42\n line1", "", 42}, {"\n//line File2.go:200\n line200", filepath.Join("dir", "File2.go"), 200}, - {"\n//line :1\n line1", "dir", 1}, - {"\n//line foo:42\n line42", filepath.Join("dir", "foo"), 42}, + {"\n//line foo\t:42\n line42", filepath.Join("dir", "foo"), 42}, {"\n //line foo:42\n line44", filepath.Join("dir", "foo"), 44}, // bad line comment, ignored {"\n//line foo 42\n line46", filepath.Join("dir", "foo"), 46}, // bad line comment, ignored {"\n//line foo:42 extra text\n line48", filepath.Join("dir", "foo"), 48}, // bad line comment, ignored @@ -631,7 +631,7 @@ type errorCollector struct { pos token.Position // last error position encountered } -func checkError(t *testing.T, src string, tok token.Token, pos int, err string) { +func checkError(t *testing.T, src string, tok token.Token, pos int, lit, err string) { var s Scanner var h errorCollector eh := func(pos token.Position, msg string) { @@ -640,13 +640,12 @@ func checkError(t *testing.T, src string, tok token.Token, pos int, err string) h.pos = pos } s.Init(fset.AddFile("", fset.Base(), len(src)), []byte(src), eh, ScanComments|dontInsertSemis) - _, tok0, _ := s.Scan() - _, tok1, _ := s.Scan() + _, tok0, lit0 := s.Scan() if tok0 != tok { t.Errorf("%q: got %s, expected %s", src, tok0, tok) } - if tok1 != token.EOF { - t.Errorf("%q: got %s, expected EOF", src, tok1) + if tok0 != token.ILLEGAL && lit0 != lit { + t.Errorf("%q: got literal %q, expected %q", src, lit0, lit) } cnt := 0 if err != "" { @@ -667,43 +666,71 @@ var errors = []struct { src string tok token.Token pos int + lit string err string }{ - {"\a", token.ILLEGAL, 0, "illegal character U+0007"}, - {`#`, token.ILLEGAL, 0, "illegal character U+0023 '#'"}, - {`…`, token.ILLEGAL, 0, "illegal character U+2026 '…'"}, - {`' '`, token.CHAR, 0, ""}, - {`''`, token.CHAR, 0, "illegal character literal"}, - {`'\8'`, token.CHAR, 2, "unknown escape sequence"}, - {`'\08'`, token.CHAR, 3, "illegal character in escape sequence"}, - {`'\x0g'`, token.CHAR, 4, "illegal character in escape sequence"}, - {`'\Uffffffff'`, token.CHAR, 2, "escape sequence is invalid Unicode code point"}, - {`'`, token.CHAR, 0, "character literal not terminated"}, - {`""`, token.STRING, 0, ""}, - {`"`, token.STRING, 0, "string not terminated"}, - {"``", token.STRING, 0, ""}, - {"`", token.STRING, 0, "string not terminated"}, - {"/**/", token.COMMENT, 0, ""}, - {"/*", token.COMMENT, 0, "comment not terminated"}, - {"077", token.INT, 0, ""}, - {"078.", token.FLOAT, 0, ""}, - {"07801234567.", token.FLOAT, 0, ""}, - {"078e0", token.FLOAT, 0, ""}, - {"078", token.INT, 0, "illegal octal number"}, - {"07800000009", token.INT, 0, "illegal octal number"}, - {"0x", token.INT, 0, "illegal hexadecimal number"}, - {"0X", token.INT, 0, "illegal hexadecimal number"}, - {"\"abc\x00def\"", token.STRING, 4, "illegal character NUL"}, - {"\"abc\x80def\"", token.STRING, 4, "illegal UTF-8 encoding"}, - {"\ufeff\ufeff", token.ILLEGAL, 3, "illegal byte order mark"}, // only first BOM is ignored - {"//\ufeff", token.COMMENT, 2, "illegal byte order mark"}, // only first BOM is ignored - {"'\ufeff" + `'`, token.CHAR, 1, "illegal byte order mark"}, // only first BOM is ignored - {`"` + "abc\ufeffdef" + `"`, token.STRING, 4, "illegal byte order mark"}, // only first BOM is ignored + {"\a", token.ILLEGAL, 0, "", "illegal character U+0007"}, + {`#`, token.ILLEGAL, 0, "", "illegal character U+0023 '#'"}, + {`…`, token.ILLEGAL, 0, "", "illegal character U+2026 '…'"}, + {`' '`, token.CHAR, 0, `' '`, ""}, + {`''`, token.CHAR, 0, `''`, "illegal rune literal"}, + {`'12'`, token.CHAR, 0, `'12'`, "illegal rune literal"}, + {`'123'`, token.CHAR, 0, `'123'`, "illegal rune literal"}, + {`'\0'`, token.CHAR, 3, `'\0'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\07'`, token.CHAR, 4, `'\07'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\8'`, token.CHAR, 2, `'\8'`, "unknown escape sequence"}, + {`'\08'`, token.CHAR, 3, `'\08'`, "illegal character U+0038 '8' in escape sequence"}, + {`'\x'`, token.CHAR, 3, `'\x'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\x0'`, token.CHAR, 4, `'\x0'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\x0g'`, token.CHAR, 4, `'\x0g'`, "illegal character U+0067 'g' in escape sequence"}, + {`'\u'`, token.CHAR, 3, `'\u'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\u0'`, token.CHAR, 4, `'\u0'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\u00'`, token.CHAR, 5, `'\u00'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\u000'`, token.CHAR, 6, `'\u000'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\u000`, token.CHAR, 6, `'\u000`, "escape sequence not terminated"}, + {`'\u0000'`, token.CHAR, 0, `'\u0000'`, ""}, + {`'\U'`, token.CHAR, 3, `'\U'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\U0'`, token.CHAR, 4, `'\U0'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\U00'`, token.CHAR, 5, `'\U00'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\U000'`, token.CHAR, 6, `'\U000'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\U0000'`, token.CHAR, 7, `'\U0000'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\U00000'`, token.CHAR, 8, `'\U00000'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\U000000'`, token.CHAR, 9, `'\U000000'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\U0000000'`, token.CHAR, 10, `'\U0000000'`, "illegal character U+0027 ''' in escape sequence"}, + {`'\U0000000`, token.CHAR, 10, `'\U0000000`, "escape sequence not terminated"}, + {`'\U00000000'`, token.CHAR, 0, `'\U00000000'`, ""}, + {`'\Uffffffff'`, token.CHAR, 2, `'\Uffffffff'`, "escape sequence is invalid Unicode code point"}, + {`'`, token.CHAR, 0, `'`, "rune literal not terminated"}, + {`'\`, token.CHAR, 2, `'\`, "escape sequence not terminated"}, + {"'\n", token.CHAR, 0, "'", "rune literal not terminated"}, + {"'\n ", token.CHAR, 0, "'", "rune literal not terminated"}, + {`""`, token.STRING, 0, `""`, ""}, + {`"abc`, token.STRING, 0, `"abc`, "string literal not terminated"}, + {"\"abc\n", token.STRING, 0, `"abc`, "string literal not terminated"}, + {"\"abc\n ", token.STRING, 0, `"abc`, "string literal not terminated"}, + {"``", token.STRING, 0, "``", ""}, + {"`", token.STRING, 0, "`", "raw string literal not terminated"}, + {"/**/", token.COMMENT, 0, "/**/", ""}, + {"/*", token.COMMENT, 0, "/*", "comment not terminated"}, + {"077", token.INT, 0, "077", ""}, + {"078.", token.FLOAT, 0, "078.", ""}, + {"07801234567.", token.FLOAT, 0, "07801234567.", ""}, + {"078e0", token.FLOAT, 0, "078e0", ""}, + {"078", token.INT, 0, "078", "illegal octal number"}, + {"07800000009", token.INT, 0, "07800000009", "illegal octal number"}, + {"0x", token.INT, 0, "0x", "illegal hexadecimal number"}, + {"0X", token.INT, 0, "0X", "illegal hexadecimal number"}, + {"\"abc\x00def\"", token.STRING, 4, "\"abc\x00def\"", "illegal character NUL"}, + {"\"abc\x80def\"", token.STRING, 4, "\"abc\x80def\"", "illegal UTF-8 encoding"}, + {"\ufeff\ufeff", token.ILLEGAL, 3, "\ufeff\ufeff", "illegal byte order mark"}, // only first BOM is ignored + {"//\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 } func TestScanErrors(t *testing.T) { for _, e := range errors { - checkError(t, e.src, e.tok, e.pos, e.err) + checkError(t, e.src, e.tok, e.pos, e.lit, e.err) } } diff --git a/libgo/go/go/token/position.go b/libgo/go/go/token/position.go index e6f0ae6a67..82d90eeb72 100644 --- a/libgo/go/go/token/position.go +++ b/libgo/go/go/token/position.go @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// TODO(gri) consider making this a separate package outside the go directory. - package token import ( @@ -184,6 +182,7 @@ func (f *File) SetLines(lines []int) bool { } // SetLinesForContent sets the line offsets for the given file content. +// It ignores position-altering //line comments. func (f *File) SetLinesForContent(content []byte) { var lines []int line := 0 @@ -255,7 +254,6 @@ func (f *File) Offset(p Pos) int { // p must be a Pos value in that file or NoPos. // func (f *File) Line(p Pos) int { - // TODO(gri) this can be implemented much more efficiently return f.Position(p).Line } @@ -263,13 +261,16 @@ func searchLineInfos(a []lineInfo, x int) int { return sort.Search(len(a), func(i int) bool { return a[i].Offset > x }) - 1 } -// info returns the file name, line, and column number for a file offset. -func (f *File) info(offset int) (filename string, line, column int) { +// unpack returns the filename and line and column number for a file offset. +// If adjusted is set, unpack will return the filename and line information +// possibly adjusted by //line comments; otherwise those comments are ignored. +// +func (f *File) unpack(offset int, adjusted bool) (filename string, line, column int) { filename = f.name if i := searchInts(f.lines, offset); i >= 0 { line, column = i+1, offset-f.lines[i]+1 } - if len(f.infos) > 0 { + if adjusted && len(f.infos) > 0 { // almost no files have extra line infos if i := searchLineInfos(f.infos, offset); i >= 0 { alt := &f.infos[i] @@ -282,26 +283,35 @@ func (f *File) info(offset int) (filename string, line, column int) { return } -func (f *File) position(p Pos) (pos Position) { +func (f *File) position(p Pos, adjusted bool) (pos Position) { offset := int(p) - f.base pos.Offset = offset - pos.Filename, pos.Line, pos.Column = f.info(offset) + pos.Filename, pos.Line, pos.Column = f.unpack(offset, adjusted) return } -// Position returns the Position value for the given file position p; -// p must be a Pos value in that file or NoPos. +// PositionFor returns the Position value for the given file position p. +// If adjusted is set, the position may be adjusted by position-altering +// //line comments; otherwise those comments are ignored. +// p must be a Pos value in f or NoPos. // -func (f *File) Position(p Pos) (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("illegal Pos value") } - pos = f.position(p) + pos = f.position(p, adjusted) } return } +// Position returns the Position value for the given file position p. +// Calling f.Position(p) is equivalent to calling f.PositionFor(p, true). +// +func (f *File) Position(p Pos) (pos Position) { + return f.PositionFor(p, true) +} + // ----------------------------------------------------------------------------- // FileSet @@ -427,16 +437,27 @@ func (s *FileSet) File(p Pos) (f *File) { return } -// Position converts a Pos in the fileset into a general Position. -func (s *FileSet) Position(p Pos) (pos Position) { +// PositionFor converts a Pos p in the fileset into a Position value. +// If adjusted is set, the position may be adjusted by position-altering +// //line comments; otherwise those comments are ignored. +// p must be a Pos value in s or NoPos. +// +func (s *FileSet) PositionFor(p Pos, adjusted bool) (pos Position) { if p != NoPos { if f := s.file(p); f != nil { - pos = f.position(p) + pos = f.position(p, adjusted) } } return } +// Position converts a Pos p in the fileset into a Position value. +// Calling s.Position(p) is equivalent to calling s.PositionFor(p, true). +// +func (s *FileSet) Position(p Pos) (pos Position) { + return s.PositionFor(p, true) +} + // ----------------------------------------------------------------------------- // Helper functions diff --git a/libgo/go/go/token/position_test.go b/libgo/go/go/token/position_test.go index ef6cfd93c2..d26939ce27 100644 --- a/libgo/go/go/token/position_test.go +++ b/libgo/go/go/token/position_test.go @@ -11,18 +11,18 @@ import ( "testing" ) -func checkPos(t *testing.T, msg string, p, q Position) { - if p.Filename != q.Filename { - t.Errorf("%s: expected filename = %q; got %q", msg, q.Filename, p.Filename) +func checkPos(t *testing.T, msg string, got, want Position) { + if got.Filename != want.Filename { + t.Errorf("%s: got filename = %q; want %q", msg, got.Filename, want.Filename) } - if p.Offset != q.Offset { - t.Errorf("%s: expected offset = %d; got %d", msg, q.Offset, p.Offset) + if got.Offset != want.Offset { + t.Errorf("%s: got offset = %d; want %d", msg, got.Offset, want.Offset) } - if p.Line != q.Line { - t.Errorf("%s: expected line = %d; got %d", msg, q.Line, p.Line) + if got.Line != want.Line { + t.Errorf("%s: got line = %d; want %d", msg, got.Line, want.Line) } - if p.Column != q.Column { - t.Errorf("%s: expected column = %d; got %d", msg, q.Column, p.Column) + if got.Column != want.Column { + t.Errorf("%s: got column = %d; want %d", msg, got.Column, want.Column) } } @@ -68,7 +68,7 @@ func verifyPositions(t *testing.T, fset *FileSet, f *File, lines []int) { p := f.Pos(offs) offs2 := f.Offset(p) if offs2 != offs { - t.Errorf("%s, Offset: expected offset %d; got %d", f.Name(), offs, offs2) + t.Errorf("%s, Offset: got offset %d; want %d", f.Name(), offs2, offs) } line, col := linecol(lines, offs) msg := fmt.Sprintf("%s (offs = %d, p = %d)", f.Name(), offs, p) @@ -93,16 +93,16 @@ func TestPositions(t *testing.T) { for _, test := range tests { // verify consistency of test case if test.source != nil && len(test.source) != test.size { - t.Errorf("%s: inconsistent test case: expected file size %d; got %d", test.filename, test.size, len(test.source)) + t.Errorf("%s: inconsistent test case: got file size %d; want %d", test.filename, len(test.source), test.size) } // add file and verify name and size f := fset.AddFile(test.filename, fset.Base()+delta, test.size) if f.Name() != test.filename { - t.Errorf("expected filename %q; got %q", test.filename, f.Name()) + t.Errorf("got filename %q; want %q", f.Name(), test.filename) } if f.Size() != test.size { - t.Errorf("%s: expected file size %d; got %d", f.Name(), test.size, f.Size()) + t.Errorf("%s: got file size %d; want %d", f.Name(), f.Size(), test.size) } if fset.File(f.Pos(0)) != f { t.Errorf("%s: f.Pos(0) was not found in f", f.Name()) @@ -112,12 +112,12 @@ func TestPositions(t *testing.T) { for i, offset := range test.lines { f.AddLine(offset) if f.LineCount() != i+1 { - t.Errorf("%s, AddLine: expected line count %d; got %d", f.Name(), i+1, f.LineCount()) + t.Errorf("%s, AddLine: got line count %d; want %d", f.Name(), f.LineCount(), i+1) } // adding the same offset again should be ignored f.AddLine(offset) if f.LineCount() != i+1 { - t.Errorf("%s, AddLine: expected unchanged line count %d; got %d", f.Name(), i+1, f.LineCount()) + t.Errorf("%s, AddLine: got unchanged line count %d; want %d", f.Name(), f.LineCount(), i+1) } verifyPositions(t, fset, f, test.lines[0:i+1]) } @@ -127,7 +127,7 @@ func TestPositions(t *testing.T) { t.Errorf("%s: SetLines failed", f.Name()) } if f.LineCount() != len(test.lines) { - t.Errorf("%s, SetLines: expected line count %d; got %d", f.Name(), len(test.lines), f.LineCount()) + t.Errorf("%s, SetLines: got line count %d; want %d", f.Name(), f.LineCount(), len(test.lines)) } verifyPositions(t, fset, f, test.lines) @@ -139,7 +139,7 @@ func TestPositions(t *testing.T) { } f.SetLinesForContent(src) if f.LineCount() != len(test.lines) { - t.Errorf("%s, SetLinesForContent: expected line count %d; got %d", f.Name(), len(test.lines), f.LineCount()) + t.Errorf("%s, SetLinesForContent: got line count %d; want %d", f.Name(), f.LineCount(), len(test.lines)) } verifyPositions(t, fset, f, test.lines) } @@ -177,13 +177,13 @@ func TestFiles(t *testing.T) { j := 0 fset.Iterate(func(f *File) bool { if f.Name() != tests[j].filename { - t.Errorf("expected filename = %s; got %s", tests[j].filename, f.Name()) + t.Errorf("got filename = %s; want %s", f.Name(), tests[j].filename) } j++ return true }) if j != i+1 { - t.Errorf("expected %d files; got %d", i+1, j) + t.Errorf("got %d files; want %d", j, i+1) } } } @@ -195,7 +195,7 @@ func TestFileSetPastEnd(t *testing.T) { fset.AddFile(test.filename, fset.Base(), test.size) } if f := fset.File(Pos(fset.Base())); f != nil { - t.Errorf("expected nil, got %v", f) + t.Errorf("got %v, want nil", f) } } @@ -209,7 +209,7 @@ func TestFileSetCacheUnlikely(t *testing.T) { for file, pos := range offsets { f := fset.File(Pos(pos)) if f.Name() != file { - t.Errorf("expecting %q at position %d, got %q", file, pos, f.Name()) + t.Errorf("got %q at position %d, want %q", f.Name(), pos, file) } } } @@ -236,3 +236,62 @@ func TestFileSetRace(t *testing.T) { } stop.Wait() } + +func TestPositionFor(t *testing.T) { + src := []byte(` +foo +b +ar +//line :100 +foobar +//line bar:3 +done +`) + + const filename = "foo" + fset := NewFileSet() + f := fset.AddFile(filename, fset.Base(), len(src)) + f.SetLinesForContent(src) + + // verify position info + for i, offs := range f.lines { + got1 := f.PositionFor(f.Pos(offs), false) + got2 := f.PositionFor(f.Pos(offs), true) + got3 := f.Position(f.Pos(offs)) + want := Position{filename, offs, i + 1, 1} + checkPos(t, "1. PositionFor unadjusted", got1, want) + checkPos(t, "1. PositionFor adjusted", got2, want) + checkPos(t, "1. Position", got3, want) + } + + // manually add //line info on lines l1, l2 + const l1, l2 = 5, 7 + f.AddLineInfo(f.lines[l1-1], "", 100) + f.AddLineInfo(f.lines[l2-1], "bar", 3) + + // unadjusted position info must remain unchanged + for i, offs := range f.lines { + got1 := f.PositionFor(f.Pos(offs), false) + want := Position{filename, offs, i + 1, 1} + checkPos(t, "2. PositionFor unadjusted", got1, want) + } + + // adjusted position info should have changed + for i, offs := range f.lines { + got2 := f.PositionFor(f.Pos(offs), true) + got3 := f.Position(f.Pos(offs)) + want := Position{filename, offs, i + 1, 1} + // manually compute wanted filename and line + line := want.Line + if i+1 >= l1 { + want.Filename = "" + want.Line = line - l1 + 100 + } + if i+1 >= l2 { + want.Filename = "bar" + want.Line = line - l2 + 3 + } + checkPos(t, "3. PositionFor adjusted", got2, want) + checkPos(t, "3. Position", got3, want) + } +} diff --git a/libgo/go/go/types/testdata/builtins.src b/libgo/go/go/types/testdata/builtins.src deleted file mode 100644 index 6c848fc277..0000000000 --- a/libgo/go/go/types/testdata/builtins.src +++ /dev/null @@ -1,302 +0,0 @@ -// 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. - -// builtin calls - -package builtins - -import "unsafe" - -func _append() { - var x int - var s []byte - _0 := append /* ERROR "argument" */ () - _1 := append("foo" /* ERROR "not a typed slice" */) - _2 := append(nil /* ERROR "not a typed slice" */, s) - _3 := append(x /* ERROR "not a typed slice" */, s) - _4 := append(s) - append /* ERROR "not used" */ (s) -} - -func _cap() { - var a [10]bool - var p *[20]int - var s []int - var c chan string - _0 := cap /* ERROR "argument" */ () - _1 := cap /* ERROR "argument" */ (1, 2) - _2 := cap(42 /* ERROR "invalid" */) - const _3 = cap(a) - assert(_3 == 10) - const _4 = cap(p) - assert(_4 == 20) - _5 := cap(c) - cap /* ERROR "not used" */ (c) -} - -func _close() { - var c chan int - var r <-chan int - close /* ERROR "argument" */ () - close /* ERROR "argument" */ (1, 2) - close(42 /* ERROR "not a channel" */) - close(r /* ERROR "receive-only channel" */) - close(c) -} - -func _complex() { - var i32 int32 - var f32 float32 - var f64 float64 - var c64 complex64 - _ = complex /* ERROR "argument" */ () - _ = complex /* ERROR "argument" */ (1) - _ = complex(true /* ERROR "invalid argument" */ , 0) - _ = complex(i32 /* ERROR "invalid argument" */ , 0) - _ = complex("foo" /* ERROR "invalid argument" */ , 0) - _ = complex(c64 /* ERROR "invalid argument" */ , 0) - _ = complex(0, true /* ERROR "invalid argument" */ ) - _ = complex(0, i32 /* ERROR "invalid argument" */ ) - _ = complex(0, "foo" /* ERROR "invalid argument" */ ) - _ = complex(0, c64 /* ERROR "invalid argument" */ ) - _ = complex(f32, f32) - _ = complex(f32, 1) - _ = complex(f32, 1.0) - _ = complex(f32, 'a') - _ = complex(f64, f64) - _ = complex(f64, 1) - _ = complex(f64, 1.0) - _ = complex(f64, 'a') - _ = complex(f32 /* ERROR "mismatched types" */, f64) - _ = complex(f64 /* ERROR "mismatched types" */, f32) - _ = complex(1, 1) - _ = complex(1, 1.1) - _ = complex(1, 'a') - complex /* ERROR "not used" */ (1, 2) -} - -func _copy() { - copy /* ERROR "not enough arguments" */ () - copy /* ERROR "not enough arguments" */ ("foo") - copy([ /* ERROR "copy expects slice arguments" */ ...]int{}, []int{}) - copy([ /* ERROR "copy expects slice arguments" */ ]int{}, [...]int{}) - copy([ /* ERROR "different element types" */ ]int8{}, "foo") - - // spec examples - var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7} - var s = make([]int, 6) - var b = make([]byte, 5) - n1 := copy(s, a[0:]) // n1 == 6, s == []int{0, 1, 2, 3, 4, 5} - n2 := copy(s, s[2:]) // n2 == 4, s == []int{2, 3, 4, 5, 4, 5} - n3 := copy(b, "Hello, World!") // n3 == 5, b == []byte("Hello") -} - -func _delete() { - var m map[string]int - var s string - delete /* ERROR "argument" */ () - delete /* ERROR "argument" */ (1) - delete /* ERROR "argument" */ (1, 2, 3) - delete(m, 0 /* ERROR "not assignable" */) - delete(m, s) -} - -func _imag() { - var f32 float32 - var f64 float64 - var c64 complex64 - var c128 complex128 - _ = imag /* ERROR "argument" */ () - _ = imag /* ERROR "argument" */ (1, 2) - _ = imag(10 /* ERROR "must be a complex number" */) - _ = imag(2.7182818 /* ERROR "must be a complex number" */) - _ = imag("foo" /* ERROR "must be a complex number" */) - const _5 = imag(1 + 2i) - assert(_5 == 2) - f32 = _5 - f64 = _5 - const _6 = imag(0i) - assert(_6 == 0) - f32 = imag(c64) - f64 = imag(c128) - f32 = imag /* ERROR "cannot assign" */ (c128) - f64 = imag /* ERROR "cannot assign" */ (c64) - imag /* ERROR "not used" */ (c64) -} - -func _len() { - const c = "foobar" - var a [10]bool - var p *[20]int - var s []int - var m map[string]complex128 - _ = len /* ERROR "argument" */ () - _ = len /* ERROR "argument" */ (1, 2) - _ = len(42 /* ERROR "invalid" */) - const _3 = len(c) - assert(_3 == 6) - const _4 = len(a) - assert(_4 == 10) - const _5 = len(p) - assert(_5 == 20) - _ = len(m) - len /* ERROR "not used" */ (c) - - // esoteric case - var t string - var hash map[interface{}][]*[10]int - const n = len /* ERROR "not constant" */ (hash[recover()][len(t)]) - assert /* ERROR "failed" */ (n == 10) - var ch <-chan int - const nn = len /* ERROR "not constant" */ (hash[<-ch][len(t)]) - _ = nn // TODO(gri) remove this once unused constants get type-checked -} - -func _make() { - n := 0 - - _ = make /* ERROR "argument" */ () - _ = make(1 /* ERROR "not a type" */) - _ = make(int /* ERROR "cannot make" */) - - // slices - _ = make/* ERROR "arguments" */ ([]int) - _ = make/* ERROR "arguments" */ ([]int, 2, 3, 4) - _ = make([]int, int /* ERROR "not an expression" */) - _ = make([]int, 10, float32 /* ERROR "not an expression" */) - _ = make([]int, "foo" /* ERROR "must be an integer" */) - _ = make([]int, 10, 2.3 /* ERROR "must be an integer" */) - _ = make([]int, 5, 10.0) - _ = make([]int, 0i) - _ = make([]int, - /* ERROR "must not be negative" */ 1, 10) - _ = make([]int, 0, - /* ERROR "must not be negative" */ 1) - _ = make([]int, - /* ERROR "must not be negative" */ 1, - /* ERROR "must not be negative" */ 1) - _ = make([]int, 1<<100, 1<<100) // run-time panic - _ = make([]int, 1 /* ERROR "length and capacity swapped" */ <<100 + 1, 1<<100) - _ = make([]int, 1 /* ERROR "length and capacity swapped" */ <<100, 12345) - - // maps - _ = make /* ERROR "arguments" */ (map[int]string, 10, 20) - _ = make(map[int]float32, int /* ERROR "not an expression" */) - _ = make(map[int]float32, "foo" /* ERROR "must be an integer" */) - _ = make(map[int]float32, 10) - _ = make(map[int]float32, n) - _ = make(map[int]float32, int64(n)) - - // channels - _ = make /* ERROR "arguments" */ (chan int, 10, 20) - _ = make(chan int, int /* ERROR "not an expression" */) - _ = make(chan<- int, "foo" /* ERROR "must be an integer" */) - _ = make(<-chan float64, 10) - _ = make(chan chan int, n) - _ = make(chan string, int64(n)) - - make /* ERROR "not used" */ ([]int, 10) -} - -func _new() { - _ = new /* ERROR "argument" */ () - _ = new /* ERROR "argument" */ (1, 2) - _ = new("foo" /* ERROR "not a type" */) - p := new(float64) - _ = new(struct{ x, y int }) - q := new(*float64) - _ = *p == **q - new /* ERROR "not used" */ (int) -} - -func _real() { - var f32 float32 - var f64 float64 - var c64 complex64 - var c128 complex128 - _ = real /* ERROR "argument" */ () - _ = real /* ERROR "argument" */ (1, 2) - _ = real(10 /* ERROR "must be a complex number" */) - _ = real(2.7182818 /* ERROR "must be a complex number" */) - _ = real("foo" /* ERROR "must be a complex number" */) - const _5 = real(1 + 2i) - assert(_5 == 1) - f32 = _5 - f64 = _5 - const _6 = real(0i) - assert(_6 == 0) - f32 = real(c64) - f64 = real(c128) - f32 = real /* ERROR "cannot assign" */ (c128) - f64 = real /* ERROR "cannot assign" */ (c64) - real /* ERROR "not used" */ (c64) -} - -func _recover() { - _ = recover() - _ = recover /* ERROR "argument" */ (10) - recover() -} - -func _Alignof() { - var x int - _ = unsafe /* ERROR "argument" */ .Alignof() - _ = unsafe /* ERROR "argument" */ .Alignof(1, 2) - _ = unsafe.Alignof(int /* ERROR "not an expression" */) - _ = unsafe.Alignof(42) - _ = unsafe.Alignof(new(struct{})) - unsafe /* ERROR "not used" */ .Alignof(x) -} - -func _Offsetof() { - var x struct{ f int } - _ = unsafe /* ERROR "argument" */ .Offsetof() - _ = unsafe /* ERROR "argument" */ .Offsetof(1, 2) - _ = unsafe.Offsetof(int /* ERROR "not an expression" */) - _ = unsafe.Offsetof(x /* ERROR "not a selector" */) - _ = unsafe.Offsetof(x.f) - _ = unsafe.Offsetof((x.f)) - _ = unsafe.Offsetof((((((((x))).f))))) - unsafe /* ERROR "not used" */ .Offsetof(x.f) -} - -func _Sizeof() { - var x int - _ = unsafe /* ERROR "argument" */ .Sizeof() - _ = unsafe /* ERROR "argument" */ .Sizeof(1, 2) - _ = unsafe.Sizeof(int /* ERROR "not an expression" */) - _ = unsafe.Sizeof(42) - _ = unsafe.Sizeof(new(complex128)) - unsafe /* ERROR "not used" */ .Sizeof(x) - - // basic types have size guarantees - assert(unsafe.Sizeof(byte(0)) == 1) - assert(unsafe.Sizeof(uint8(0)) == 1) - assert(unsafe.Sizeof(int8(0)) == 1) - assert(unsafe.Sizeof(uint16(0)) == 2) - assert(unsafe.Sizeof(int16(0)) == 2) - assert(unsafe.Sizeof(uint32(0)) == 4) - assert(unsafe.Sizeof(int32(0)) == 4) - assert(unsafe.Sizeof(float32(0)) == 4) - assert(unsafe.Sizeof(uint64(0)) == 8) - assert(unsafe.Sizeof(int64(0)) == 8) - assert(unsafe.Sizeof(float64(0)) == 8) - assert(unsafe.Sizeof(complex64(0)) == 8) - assert(unsafe.Sizeof(complex128(0)) == 16) -} - -// self-testing only -func _assert() { - var x int - assert /* ERROR "argument" */ () - assert /* ERROR "argument" */ (1, 2) - assert("foo" /* ERROR "boolean constant" */ ) - assert(x /* ERROR "boolean constant" */) - assert(true) - assert /* ERROR "failed" */ (false) -} - -// self-testing only -func _trace() { - // Uncomment the code below to test trace - will produce console output - // _ = trace /* ERROR "no value" */ () - // _ = trace(1) - // _ = trace(true, 1.2, '\'', "foo", 42i, "foo" <= "bar") -} diff --git a/libgo/go/go/types/testdata/const0.src b/libgo/go/go/types/testdata/const0.src deleted file mode 100644 index a2ca344c78..0000000000 --- a/libgo/go/go/types/testdata/const0.src +++ /dev/null @@ -1,215 +0,0 @@ -// 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. - -// constant declarations - -package const0 - -// constants declarations must be initialized by constants -var x = 0 -const c0 = x /* ERROR "not constant" */ - -// untyped constants -const ( - // boolean values - ub0 = false - ub1 = true - ub2 = 2 < 1 - ub3 = ui1 == uf1 - ub4 = true /* ERROR "cannot convert" */ == 0 - - // integer values - ui0 = 0 - ui1 = 1 - ui2 = 42 - ui3 = 3141592653589793238462643383279502884197169399375105820974944592307816406286 - ui4 = -10 - - ui5 = ui0 + ui1 - ui6 = ui1 - ui1 - ui7 = ui2 * ui1 - ui8 = ui3 / ui3 - ui9 = ui3 % ui3 - - ui10 = 1 / 0 /* ERROR "division by zero" */ - ui11 = ui1 / 0 /* ERROR "division by zero" */ - ui12 = ui3 / ui0 /* ERROR "division by zero" */ - ui13 = 1 % 0 /* ERROR "division by zero" */ - ui14 = ui1 % 0 /* ERROR "division by zero" */ - ui15 = ui3 % ui0 /* ERROR "division by zero" */ - - ui16 = ui2 & ui3 - ui17 = ui2 | ui3 - ui18 = ui2 ^ ui3 - - // floating point values - uf0 = 0. - uf1 = 1. - uf2 = 4.2e1 - uf3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286 - uf4 = 1e-1 - - uf5 = uf0 + uf1 - uf6 = uf1 - uf1 - uf7 = uf2 * uf1 - uf8 = uf3 / uf3 - uf9 = uf3 /* ERROR "not defined" */ % uf3 - - uf10 = 1 / 0 /* ERROR "division by zero" */ - uf11 = uf1 / 0 /* ERROR "division by zero" */ - uf12 = uf3 / uf0 /* ERROR "division by zero" */ - - uf16 = uf2 /* ERROR "not defined" */ & uf3 - uf17 = uf2 /* ERROR "not defined" */ | uf3 - uf18 = uf2 /* ERROR "not defined" */ ^ uf3 - - // complex values - uc0 = 0.i - uc1 = 1.i - uc2 = 4.2e1i - uc3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286i - uc4 = 1e-1i - - uc5 = uc0 + uc1 - uc6 = uc1 - uc1 - uc7 = uc2 * uc1 - uc8 = uc3 / uc3 - uc9 = uc3 /* ERROR "not defined" */ % uc3 - - uc10 = 1 / 0 /* ERROR "division by zero" */ - uc11 = uc1 / 0 /* ERROR "division by zero" */ - uc12 = uc3 / uc0 /* ERROR "division by zero" */ - - uc16 = uc2 /* ERROR "not defined" */ & uc3 - uc17 = uc2 /* ERROR "not defined" */ | uc3 - uc18 = uc2 /* ERROR "not defined" */ ^ uc3 -) - -type ( - mybool bool - myint int - myfloat float64 - mycomplex complex128 -) - -// typed constants -const ( - // boolean values - tb0 bool = false - tb1 bool = true - tb2 mybool = 2 < 1 - tb3 mybool = ti1 /* ERROR "cannot compare" */ == tf1 - - // integer values - ti0 int8 = ui0 - ti1 int32 = ui1 - ti2 int64 = ui2 - ti3 myint = ui3 /* ERROR "overflows" */ - ti4 myint = ui4 - - ti5 = ti0 /* ERROR "mismatched types" */ + ti1 - ti6 = ti1 - ti1 - ti7 = ti2 /* ERROR "mismatched types" */ * ti1 - //ti8 = ti3 / ti3 // TODO(gri) enable this - //ti9 = ti3 % ti3 // TODO(gri) enable this - - ti10 = 1 / 0 /* ERROR "division by zero" */ - ti11 = ti1 / 0 /* ERROR "division by zero" */ - ti12 = ti3 /* ERROR "mismatched types" */ / ti0 - ti13 = 1 % 0 /* ERROR "division by zero" */ - ti14 = ti1 % 0 /* ERROR "division by zero" */ - ti15 = ti3 /* ERROR "mismatched types" */ % ti0 - - ti16 = ti2 /* ERROR "mismatched types" */ & ti3 - ti17 = ti2 /* ERROR "mismatched types" */ | ti4 - ti18 = ti2 ^ ti5 // no mismatched types error because the type of ti5 is unknown - - // floating point values - tf0 float32 = 0. - tf1 float32 = 1. - tf2 float64 = 4.2e1 - tf3 myfloat = 3.141592653589793238462643383279502884197169399375105820974944592307816406286 - tf4 myfloat = 1e-1 - - tf5 = tf0 + tf1 - tf6 = tf1 - tf1 - tf7 = tf2 /* ERROR "mismatched types" */ * tf1 - // tf8 = tf3 / tf3 // TODO(gri) enable this - tf9 = tf3 /* ERROR "not defined" */ % tf3 - - tf10 = 1 / 0 /* ERROR "division by zero" */ - tf11 = tf1 / 0 /* ERROR "division by zero" */ - tf12 = tf3 /* ERROR "mismatched types" */ / tf0 - - tf16 = tf2 /* ERROR "mismatched types" */ & tf3 - tf17 = tf2 /* ERROR "mismatched types" */ | tf3 - tf18 = tf2 /* ERROR "mismatched types" */ ^ tf3 - - // complex values - tc0 = 0.i - tc1 = 1.i - tc2 = 4.2e1i - tc3 = 3.141592653589793238462643383279502884197169399375105820974944592307816406286i - tc4 = 1e-1i - - tc5 = tc0 + tc1 - tc6 = tc1 - tc1 - tc7 = tc2 * tc1 - tc8 = tc3 / tc3 - tc9 = tc3 /* ERROR "not defined" */ % tc3 - - tc10 = 1 / 0 /* ERROR "division by zero" */ - tc11 = tc1 / 0 /* ERROR "division by zero" */ - tc12 = tc3 / tc0 /* ERROR "division by zero" */ - - tc16 = tc2 /* ERROR "not defined" */ & tc3 - tc17 = tc2 /* ERROR "not defined" */ | tc3 - tc18 = tc2 /* ERROR "not defined" */ ^ tc3 -) - -// initialization cycles -const ( - a /* ERROR "cycle" */ = a - b /* ERROR "cycle" */ , c /* ERROR "cycle" */, d, e = e, d, c, b // TODO(gri) should only have one cycle error - f float64 = d -) - -// multiple initialization -const ( - a1, a2, a3 = 7, 3.1415926, "foo" - b1, b2, b3 = b3, b1, 42 - _p0 = assert(a1 == 7) - _p1 = assert(a2 == 3.1415926) - _p2 = assert(a3 == "foo") - _p3 = assert(b1 == 42) - _p4 = assert(b2 == 42) - _p5 = assert(b3 == 42) -) - -// iota -const ( - iota0 = iota - iota1 = iota - iota2 = iota*2 - _a0 = assert(iota0 == 0) - _a1 = assert(iota1 == 1) - _a2 = assert(iota2 == 4) - iota6 = iota*3 - - iota7 - iota8 - _a3 = assert(iota7 == 21) - _a4 = assert(iota8 == 24) -) - -const ( - _b0 = iota - _b1 = assert(iota + iota2 == 5) -) - -// special cases -const ( - _n0 = nil /* ERROR "invalid constant type" */ - _n1 = [ /* ERROR "not constant" */ ]int{} -) \ No newline at end of file diff --git a/libgo/go/go/types/testdata/conversions.src b/libgo/go/go/types/testdata/conversions.src deleted file mode 100644 index 1b1518366f..0000000000 --- a/libgo/go/go/types/testdata/conversions.src +++ /dev/null @@ -1,18 +0,0 @@ -// 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. - -// conversions - -package conversions - -// argument count -var ( - _v0 = int /* ERROR "one argument" */ () - _v1 = int /* ERROR "one argument" */ (1, 2) -) - -// -var ( - _v2 = int8(0) -) \ No newline at end of file diff --git a/libgo/go/go/types/testdata/decls0.src b/libgo/go/go/types/testdata/decls0.src deleted file mode 100644 index 33d4b38014..0000000000 --- a/libgo/go/go/types/testdata/decls0.src +++ /dev/null @@ -1,177 +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. - -// type declarations - -package decls0 - -import ( - "unsafe" - // we can have multiple blank imports (was bug) - _ "math" - _ "net/rpc" -) - -const pi = 3.1415 - -type ( - N undeclared /* ERROR "undeclared" */ - B bool - I int32 - A [10]P - T struct { - x, y P - } - P *T - R (*R) - F func(A) I - Y interface { - f(A) I - } - S [](((P))) - M map[I]F - C chan<- I - - // blank types must be typechecked - _ pi /* ERROR "not a type" */ - _ struct{} - _ struct{ pi /* ERROR "not a type" */ } -) - - -// invalid array types -type ( - iA0 [... /* ERROR "invalid use of '...'" */ ]byte - iA1 [1 /* ERROR "invalid array length" */ <<100]int - iA2 [- /* ERROR "invalid array length" */ 1]complex128 - iA3 ["foo" /* ERROR "invalid array length" */ ]string -) - - -type ( - p1 pi /* ERROR "no single field or method foo" */ .foo - p2 unsafe.Pointer -) - - -type ( - Pi pi /* ERROR "not a type" */ - - a /* ERROR "illegal cycle" */ a - a /* ERROR "redeclared" */ int - - // where the cycle error appears depends on the - // order in which declarations are processed - // (which depends on the order in which a map - // is iterated through) - b /* ERROR "illegal cycle" */ c - c d - d e - e b - - t *t - - U V - V *W - W U - - P1 *S2 - P2 P1 - - S0 struct { - } - S1 struct { - a, b, c int - u, v, a /* ERROR "redeclared" */ float32 - } - S2 struct { - U // anonymous field - // TODO(gri) recognize double-declaration below - // U /* ERROR "redeclared" */ int - } - S3 struct { - x S2 - } - S4/* ERROR "illegal cycle" */ struct { - S4 - } - S5 /* ERROR "illegal cycle" */ struct { - S6 - } - S6 struct { - field S7 - } - S7 struct { - S5 - } - - L1 []L1 - L2 []int - - A1 [10.0]int - A2 /* ERROR "illegal cycle" */ [10]A2 - A3 /* ERROR "illegal cycle" */ [10]struct { - x A4 - } - A4 [10]A3 - - F1 func() - F2 func(x, y, z float32) - F3 func(x, y, x /* ERROR "redeclared" */ float32) - F4 func() (x, y, x /* ERROR "redeclared" */ float32) - F5 func(x int) (x /* ERROR "redeclared" */ float32) - F6 func(x ...int) - - I1 interface{} - I2 interface { - m1() - } - I3 interface { /* ERROR "multiple methods named m1" */ - m1() - m1 /* ERROR "redeclared" */ () - } - I4 interface { - m1(x, y, x /* ERROR "redeclared" */ float32) - m2() (x, y, x /* ERROR "redeclared" */ float32) - m3(x int) (x /* ERROR "redeclared" */ float32) - } - I5 interface { - m1(I5) - } - I6 interface { - S0 /* ERROR "not an interface" */ - } - I7 interface { - I1 - I1 - } - I8 /* ERROR "illegal cycle" */ interface { - I8 - } - // Use I09 (rather than I9) because it appears lexically before - // I10 so that we get the illegal cycle here rather then in the - // declaration of I10. If the implementation sorts by position - // rather than name, the error message will still be here. - I09 /* ERROR "illegal cycle" */ interface { - I10 - } - I10 interface { - I11 - } - I11 interface { - I09 - } - - C1 chan int - C2 <-chan int - C3 chan<- C3 - C4 chan C5 - C5 chan C6 - C6 chan C4 - - M1 map[Last]string - M2 map[string]M2 - - Last int -) diff --git a/libgo/go/go/types/testdata/decls1.src b/libgo/go/go/types/testdata/decls1.src deleted file mode 100644 index dd63ba9809..0000000000 --- a/libgo/go/go/types/testdata/decls1.src +++ /dev/null @@ -1,132 +0,0 @@ -// 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. - -// variable declarations - -package decls1 - -import ( - "math" -) - -// Global variables without initialization -var ( - a, b bool - c byte - d uint8 - r rune - i int - j, k, l int - x, y float32 - xx, yy float64 - u, v complex64 - uu, vv complex128 - s, t string - array []byte - iface interface{} - - blank _ /* ERROR "cannot use _" */ -) - -// Global variables with initialization -var ( - s1 = i + j - s2 = i /* ERROR "mismatched types" */ + x - s3 = c + d - s4 = s + t - s5 = s /* ERROR "invalid operation" */ / t - s6 = array[t1] - s7 = array[x /* ERROR "index" */] - s8 = &a - s10 = &42 /* ERROR "cannot take address" */ - s11 = &v - s12 = -(u + *t11) / *&v - s13 = a /* ERROR "shifted operand" */ << d - s14 = i << j /* ERROR "must be unsigned" */ - s18 = math.Pi * 10.0 - s19 = s1 /* ERROR "cannot call" */ () - s20 = f0 /* ERROR "no value" */ () - s21 = f6(1, s1, i) - s22 = f6(1, s1, uu /* ERROR "cannot assign" */ ) - - t1 int = i + j - t2 int = i /* ERROR "mismatched types" */ + x - t3 int = c /* ERROR "cannot assign" */ + d - t4 string = s + t - t5 string = s /* ERROR "invalid operation" */ / t - t6 byte = array[t1] - t7 byte = array[x /* ERROR "index" */] - t8 *int = & /* ERROR "cannot assign" */ a - t10 *int = &42 /* ERROR "cannot take address" */ - t11 *complex64 = &v - t12 complex64 = -(u + *t11) / *&v - t13 int = a /* ERROR "shifted operand" */ << d - t14 int = i << j /* ERROR "must be unsigned" */ - t15 math /* ERROR "not in selector" */ - t16 math.xxx /* ERROR "unexported" */ - t17 math /* ERROR "not a type" */ .Pi - t18 float64 = math.Pi * 10.0 - t19 int = t1 /* ERROR "cannot call" */ () - t20 int = f0 /* ERROR "no value" */ () -) - -// Various more complex expressions -var ( - u1 = x /* ERROR "not an interface" */ .(int) - u2 = iface.([]int) - u3 = iface.(a /* ERROR "not a type" */ ) - u4, ok = iface.(int) - u5 /* ERROR "assignment count mismatch" */ , ok2, ok3 = iface.(int) -) - -// Constant expression initializations -var ( - v1 = 1 /* ERROR "cannot convert" */ + "foo" - v2 = c + 255 - v3 = c + 256 /* ERROR "overflows" */ - v4 = r + 2147483647 - v5 = r + 2147483648 /* ERROR "overflows" */ - v6 = 42 - v7 = v6 + 2147483647 - v8 = v6 + 2147483648 /* ERROR "overflows" */ - v9 = i + 1 << 10 - v10 byte = 1024 /* ERROR "overflows" */ - v11 = xx/yy*yy - xx - v12 = true && false - v13 = nil /* ERROR "use of untyped nil" */ -) - -// Multiple assignment expressions -var ( - m1a, m1b = 1, 2 - m2a /* ERROR "assignment count mismatch" */ , m2b, m2c = 1, 2 - m3a /* ERROR "assignment count mismatch" */ , m3b = 1, 2, 3 -) - -// Declaration of parameters and results -func f0() {} -func f1(a /* ERROR "not a type" */) {} -func f2(a, b, c d /* ERROR "not a type" */) {} - -func f3() int {} -func f4() a /* ERROR "not a type" */ {} -func f5() (a, b, c d /* ERROR "not a type" */) {} - -func f6(a, b, c int) complex128 { return 0 } - -// Declaration of receivers -type T struct{} - -func (T) m0() {} -func (*T) m1() {} -func (x T) m2() {} -func (x *T) m3() {} - - -// Initialization functions -func init() {} -func /* ERROR "no arguments and no return values" */ init(int) {} -func /* ERROR "no arguments and no return values" */ init() int { return 0 } -func /* ERROR "no arguments and no return values" */ init(int) int {} -func (T) init(int) int { return 0 } diff --git a/libgo/go/go/types/testdata/decls2a.src b/libgo/go/go/types/testdata/decls2a.src deleted file mode 100644 index 3867be7376..0000000000 --- a/libgo/go/go/types/testdata/decls2a.src +++ /dev/null @@ -1,67 +0,0 @@ -// 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. - -// method declarations - -package decls2 - -import "time" - -// T1 declared before its methods. -type T1 struct{ - f int -} - -func (T1) m() {} -func (T1) m /* ERROR "redeclared" */ () {} -func (x *T1) f /* ERROR "field and method" */ () {} - -// T2's method declared before the type. -func (*T2) f /* ERROR "field and method" */ () {} - -type T2 struct { - f int -} - -// Methods declared without a declared type. -func (undeclared /* ERROR "undeclared" */) m() {} -func (x *undeclared /* ERROR "undeclared" */) m() {} - -// TODO(gri) try to get rid of double error reporting here -func (pi /* ERROR "not a type" */) m1() {} -func (x pi /* ERROR "not a type" */) m2() {} -func (x *pi /* ERROR "not a type" */ ) m3() {} // TODO(gri) not closing the last /* comment crashes the system - -// Blank types. -type _ struct { m int } -type _ struct { m int } - -// TODO(gri) blank idents not fully checked - disabled for now -// func (_ /* ERROR "cannot use _" */) m() {} -// func (_ /* ERROR "cannot use _" */) m() {} - -// Methods with receiver base type declared in another file. -func (T3) m1() {} -func (*T3) m2() {} -func (x T3) m3() {} -func (x *T3) f /* ERROR "field and method" */ () {} - -// Methods of non-struct type. -type T4 func() - -func (self T4) m() func() { return self } - -// Methods associated with an interface. -type T5 interface { - m() int -} - -func (T5 /* ERROR "invalid receiver" */) m1() {} -func (T5 /* ERROR "invalid receiver" */) m2() {} - -// Methods associated with non-local or unnamed types. -func (int /* ERROR "non-local type" */ ) m() {} -func ([ /* ERROR "expected" */ ]int) m() {} -func (time /* ERROR "expected" */ .Time) m() {} -func (x interface /* ERROR "expected" */ {}) m() {} diff --git a/libgo/go/go/types/testdata/decls2b.src b/libgo/go/go/types/testdata/decls2b.src deleted file mode 100644 index c7f9ddf01a..0000000000 --- a/libgo/go/go/types/testdata/decls2b.src +++ /dev/null @@ -1,28 +0,0 @@ -// 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. - -// method declarations - -package decls2 - -const pi = 3.1415 - -func (T1) m /* ERROR "redeclared" */ () {} - -type T3 struct { - f *T3 -} - -type T6 struct { - x int -} - -func (t *T6) m1() int { - return t.x -} - -func f() { - var t *T6 - t.m1() -} \ No newline at end of file diff --git a/libgo/go/go/types/testdata/decls3.src b/libgo/go/go/types/testdata/decls3.src deleted file mode 100644 index 4bc7d41494..0000000000 --- a/libgo/go/go/types/testdata/decls3.src +++ /dev/null @@ -1,231 +0,0 @@ -// 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. - -// embedded types - -package decls3 - -// fields with the same name at the same level cancel each other out - -func _() { - type ( - T1 struct { X int } - T2 struct { X int } - T3 struct { T1; T2 } // X is embedded twice at the same level via T1->X, T2->X - ) - - var t T3 - _ = t /* ERROR "no single field or method" */ .X -} - -func _() { - type ( - T1 struct { X int } - T2 struct { T1 } - T3 struct { T1 } - T4 struct { T2; T3 } // X is embedded twice at the same level via T2->T1->X, T3->T1->X - ) - - var t T4 - _ = t /* ERROR "no single field or method" */ .X -} - -func issue4355() { - type ( - T1 struct {X int} - T2 struct {T1} - T3 struct {T2} - T4 struct {T2} - T5 struct {T3; T4} // X is embedded twice at the same level via T3->T2->T1->X, T4->T2->T1->X - ) - - var t T5 - _ = t /* ERROR "no single field or method" */ .X -} - -// Borrowed from the FieldByName test cases in reflect/all_test.go. - -type D1 struct { - d int -} -type D2 struct { - d int -} - -type S0 struct { - A, B, C int - D1 - D2 -} - -type S1 struct { - B int - S0 -} - -type S2 struct { - A int - *S1 -} - -type S1x struct { - S1 -} - -type S1y struct { - S1 -} - -type S3 struct { - S1x - S2 - D, E int - *S1y -} - -type S4 struct { - *S4 - A int -} - -// The X in S6 and S7 annihilate, but they also block the X in S8.S9. -type S5 struct { - S6 - S7 - S8 -} - -type S6 struct { - X int -} - -type S7 S6 - -type S8 struct { - S9 -} - -type S9 struct { - X int - Y int -} - -// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9. -type S10 struct { - S11 - S12 - S13 -} - -type S11 struct { - S6 -} - -type S12 struct { - S6 -} - -type S13 struct { - S8 -} - -func _() { - _ = struct /* ERROR "no single field or method" */ {}{}.Foo - _ = S0{}.A - _ = S0 /* ERROR "no single field or method" */ {}.D - _ = S1{}.A - _ = S1{}.B - _ = S1{}.S0 - _ = S1{}.C - _ = S2{}.A - _ = S2{}.S1 - _ = S2{}.B - _ = S2{}.C - _ = S2 /* ERROR "no single field or method" */ {}.D - _ = S3 /* ERROR "no single field or method" */ {}.S1 - _ = S3{}.A - _ = S3 /* ERROR "no single field or method" */ {}.B - _ = S3{}.D - _ = S3{}.E - _ = S4{}.A - _ = S4 /* ERROR "no single field or method" */ {}.B - _ = S5 /* ERROR "no single field or method" */ {}.X - _ = S5{}.Y - _ = S10 /* ERROR "no single field or method" */ {}.X - _ = S10{}.Y -} - -// Borrowed from the FieldByName benchmark in reflect/all_test.go. - -type R0 struct { - *R1 - *R2 - *R3 - *R4 -} - -type R1 struct { - *R5 - *R6 - *R7 - *R8 -} - -type R2 R1 -type R3 R1 -type R4 R1 - -type R5 struct { - *R9 - *R10 - *R11 - *R12 -} - -type R6 R5 -type R7 R5 -type R8 R5 - -type R9 struct { - *R13 - *R14 - *R15 - *R16 -} - -type R10 R9 -type R11 R9 -type R12 R9 - -type R13 struct { - *R17 - *R18 - *R19 - *R20 -} - -type R14 R13 -type R15 R13 -type R16 R13 - -type R17 struct { - *R21 - *R22 - *R23 - *R24 -} - -type R18 R17 -type R19 R17 -type R20 R17 - -type R21 struct { - X int -} - -type R22 R21 -type R23 R21 -type R24 R21 - -var _ = R0 /* ERROR "no single field or method" */ {}.X \ No newline at end of file diff --git a/libgo/go/go/types/testdata/expr0.src b/libgo/go/go/types/testdata/expr0.src deleted file mode 100644 index c3233d36fe..0000000000 --- a/libgo/go/go/types/testdata/expr0.src +++ /dev/null @@ -1,151 +0,0 @@ -// 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. - -// unary expressions - -package expr0 - -var ( - // bool - b0 = true - b1 bool = b0 - b2 = !true - b3 = !b1 - b4 bool = !true - b5 bool = !b4 - b6 = +b0 /* ERROR "not defined" */ - b7 = -b0 /* ERROR "not defined" */ - b8 = ^b0 /* ERROR "not defined" */ - b9 = *b0 /* ERROR "cannot indirect" */ - b10 = &true /* ERROR "cannot take address" */ - b11 = &b0 - b12 = <-b0 /* ERROR "cannot receive" */ - - // int - i0 = 1 - i1 int = i0 - i2 = +1 - i3 = +i0 - i4 int = +1 - i5 int = +i4 - i6 = -1 - i7 = -i0 - i8 int = -1 - i9 int = -i4 - i10 = !i0 /* ERROR "not defined" */ - i11 = ^1 - i12 = ^i0 - i13 int = ^1 - i14 int = ^i4 - i15 = *i0 /* ERROR "cannot indirect" */ - i16 = &i0 - i17 = *i16 - i18 = <-i16 /* ERROR "cannot receive" */ - - // uint - u0 = uint(1) - u1 uint = u0 - u2 = +1 - u3 = +u0 - u4 uint = +1 - u5 uint = +u4 - u6 = -1 - u7 = -u0 - u8 uint = - /* ERROR "overflows" */ 1 - u9 uint = -u4 - u10 = !u0 /* ERROR "not defined" */ - u11 = ^1 - u12 = ^i0 - u13 uint = ^ /* ERROR "overflows" */ 1 - u14 uint = ^u4 - u15 = *u0 /* ERROR "cannot indirect" */ - u16 = &u0 - u17 = *u16 - u18 = <-u16 /* ERROR "cannot receive" */ - u19 = ^uint(0) - - // float64 - f0 = float64(1) - f1 float64 = f0 - f2 = +1 - f3 = +f0 - f4 float64 = +1 - f5 float64 = +f4 /* ERROR not defined */ - f6 = -1 - f7 = -f0 - f8 float64 = -1 - f9 float64 = -f4 - f10 = !f0 /* ERROR "not defined" */ - f11 = ^1 - f12 = ^i0 - f13 float64 = ^1 - f14 float64 = ^f4 /* ERROR "not defined" */ - f15 = *f0 /* ERROR "cannot indirect" */ - f16 = &f0 - f17 = *u16 - f18 = <-u16 /* ERROR "cannot receive" */ - - // complex128 - c0 = complex128(1) - c1 complex128 = c0 - c2 = +1 - c3 = +c0 - c4 complex128 = +1 - c5 complex128 = +c4 /* ERROR not defined */ - c6 = -1 - c7 = -c0 - c8 complex128 = -1 - c9 complex128 = -c4 - c10 = !c0 /* ERROR "not defined" */ - c11 = ^1 - c12 = ^i0 - c13 complex128 = ^1 - c14 complex128 = ^c4 /* ERROR "not defined" */ - c15 = *c0 /* ERROR "cannot indirect" */ - c16 = &c0 - c17 = *u16 - c18 = <-u16 /* ERROR "cannot receive" */ - - // string - s0 = "foo" - s1 = +"foo" /* ERROR "not defined" */ - s2 = -s0 /* ERROR "not defined" */ - s3 = !s0 /* ERROR "not defined" */ - s4 = ^s0 /* ERROR "not defined" */ - s5 = *s4 /* ERROR "cannot indirect" */ - s6 = &s4 - s7 = *s6 - s8 = <-s7 /* ERROR "cannot receive" */ - - // channel - ch chan int - rc <-chan float64 - sc chan <- string - ch0 = +ch /* ERROR "not defined" */ - ch1 = -ch /* ERROR "not defined" */ - ch2 = !ch /* ERROR "not defined" */ - ch3 = ^ch /* ERROR "not defined" */ - ch4 = *ch /* ERROR "cannot indirect" */ - ch5 = &ch - ch6 = *ch5 - ch7 = <-ch - ch8 = <-rc - ch9 = <-sc /* ERROR "cannot receive" */ -) - -// address of composite literals -type T struct{x, y int} - -func f() T { return T{} } - -var ( - _ = &T{1, 2} - _ = &[...]int{} - _ = &[]int{} - _ = &[]int{} - _ = &map[string]T{} - _ = &(T{1, 2}) - _ = &((((T{1, 2})))) - _ = &f /* ERROR "cannot take address" */ () -) diff --git a/libgo/go/go/types/testdata/expr1.src b/libgo/go/go/types/testdata/expr1.src deleted file mode 100644 index 8ef0aed6d2..0000000000 --- a/libgo/go/go/types/testdata/expr1.src +++ /dev/null @@ -1,7 +0,0 @@ -// 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. - -// binary expressions - -package expr1 diff --git a/libgo/go/go/types/testdata/expr2.src b/libgo/go/go/types/testdata/expr2.src deleted file mode 100644 index 674be4005d..0000000000 --- a/libgo/go/go/types/testdata/expr2.src +++ /dev/null @@ -1,23 +0,0 @@ -// 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. - -// comparisons - -package expr2 - -func _bool() { - const t = true == true - const f = true == false - _ = t /* ERROR "cannot compare" */ < f - _ = 0 /* ERROR "cannot convert" */ == t - var b bool - var x, y float32 - b = x < y - _ = struct{b bool}{x < y} -} - -// corner cases -var ( - v0 = nil /* ERROR "cannot compare" */ == nil -) \ No newline at end of file diff --git a/libgo/go/go/types/testdata/expr3.src b/libgo/go/go/types/testdata/expr3.src deleted file mode 100644 index 519e3f567a..0000000000 --- a/libgo/go/go/types/testdata/expr3.src +++ /dev/null @@ -1,367 +0,0 @@ -// 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. - -// various expressions - -package expr3 - -func shifts1() { - var ( - i0 int - u0 uint - ) - - var ( - v0 = 1<<0 - v1 = 1<. stateHTMLCmt // stateRCDATA occurs inside an RCDATA element (