summaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2017-01-14 00:05:42 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2017-01-14 00:05:42 +0000
commitc2047754c300b68c05d65faa8dc2925fe67b71b4 (patch)
treee183ae81a1f48a02945cb6de463a70c5be1b06f6 /libgo
parent829afb8f05602bb31c9c597b24df7377fed4f059 (diff)
libgo: update to Go 1.8 release candidate 1
Compiler changes: * Change map assignment to use mapassign and assign value directly. * Change string iteration to use decoderune, faster for ASCII strings. * Change makeslice to take int, and use makeslice64 for larger values. * Add new noverflow field to hmap struct used for maps. Unresolved problems, to be fixed later: * Commented out test in go/types/sizes_test.go that doesn't compile. * Commented out reflect.TestStructOf test for padding after zero-sized field. Reviewed-on: https://go-review.googlesource.com/35231 gotools/: Updates for Go 1.8rc1. * Makefile.am (go_cmd_go_files): Add bug.go. (s-zdefaultcc): Write defaultPkgConfig. * Makefile.in: Rebuild. From-SVN: r244456
Diffstat (limited to 'libgo')
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/Makefile.am43
-rw-r--r--libgo/Makefile.in46
-rw-r--r--libgo/VERSION2
-rw-r--r--libgo/go/archive/tar/common.go27
-rw-r--r--libgo/go/archive/tar/reader.go531
-rw-r--r--libgo/go/archive/tar/reader_test.go773
-rw-r--r--libgo/go/archive/tar/strconv.go252
-rw-r--r--libgo/go/archive/tar/strconv_test.go319
-rw-r--r--libgo/go/archive/tar/tar_test.go236
-rw-r--r--libgo/go/archive/tar/testdata/gnu-incremental.tarbin0 -> 2560 bytes
-rw-r--r--libgo/go/archive/tar/testdata/pax-bad-hdr-file.tarbin0 -> 2560 bytes
-rw-r--r--libgo/go/archive/tar/testdata/pax-bad-mtime-file.tarbin0 -> 2560 bytes
-rw-r--r--libgo/go/archive/tar/testdata/pax-pos-size-file.tarbin0 -> 2560 bytes
-rw-r--r--libgo/go/archive/tar/testdata/ustar.issue12594.tarbin0 -> 3072 bytes
-rw-r--r--libgo/go/archive/tar/testdata/writer-big-long.tarbin4096 -> 4096 bytes
-rw-r--r--libgo/go/archive/tar/writer.go106
-rw-r--r--libgo/go/archive/tar/writer_test.go483
-rw-r--r--libgo/go/archive/zip/writer.go11
-rw-r--r--libgo/go/archive/zip/zip_test.go324
-rw-r--r--libgo/go/bufio/bufio.go29
-rw-r--r--libgo/go/bufio/bufio_test.go21
-rw-r--r--libgo/go/bufio/scan.go1
-rw-r--r--libgo/go/builtin/builtin.go4
-rw-r--r--libgo/go/bytes/buffer.go43
-rw-r--r--libgo/go/bytes/buffer_test.go13
-rw-r--r--libgo/go/bytes/bytes.go146
-rw-r--r--libgo/go/bytes/bytes_amd64.go117
-rw-r--r--libgo/go/bytes/bytes_generic.go41
-rw-r--r--libgo/go/bytes/bytes_s390x.go120
-rw-r--r--libgo/go/bytes/bytes_test.go194
-rw-r--r--libgo/go/bytes/example_test.go203
-rw-r--r--libgo/go/cmd/cgo/ast.go3
-rw-r--r--libgo/go/cmd/cgo/doc.go12
-rw-r--r--libgo/go/cmd/cgo/gcc.go429
-rw-r--r--libgo/go/cmd/cgo/main.go15
-rw-r--r--libgo/go/cmd/cgo/out.go86
-rw-r--r--libgo/go/cmd/go/alldocs.go196
-rw-r--r--libgo/go/cmd/go/bootstrap.go3
-rw-r--r--libgo/go/cmd/go/bug.go213
-rw-r--r--libgo/go/cmd/go/build.go455
-rw-r--r--libgo/go/cmd/go/build_test.go44
-rw-r--r--libgo/go/cmd/go/env.go43
-rw-r--r--libgo/go/cmd/go/generate.go10
-rw-r--r--libgo/go/cmd/go/get.go100
-rw-r--r--libgo/go/cmd/go/go_test.go939
-rw-r--r--libgo/go/cmd/go/go_windows_test.go3
-rw-r--r--libgo/go/cmd/go/help.go54
-rw-r--r--libgo/go/cmd/go/http.go5
-rw-r--r--libgo/go/cmd/go/list.go19
-rw-r--r--libgo/go/cmd/go/main.go9
-rw-r--r--libgo/go/cmd/go/pkg.go263
-rw-r--r--libgo/go/cmd/go/test.go146
-rw-r--r--libgo/go/cmd/go/testdata/src/canonical/a/a.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/canonical/a/c/c.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/canonical/b/b.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/canonical/d/d.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover/p.go (renamed from libgo/go/cmd/go/testdata/cgocover/p.go)0
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover/p_test.go (renamed from libgo/go/cmd/go/testdata/cgocover/p_test.go)0
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover2/p.go19
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover2/x_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover3/p.go19
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover3/p_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover3/x_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover4/notcgo.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover4/p.go19
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover4/x_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/src/dupload/dupload.go8
-rw-r--r--libgo/go/cmd/go/testdata/src/dupload/p/p.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/dupload/p2/p2.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkg/pkg.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgtest/pkg.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgtest/test_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/pkg.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/test_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/xtest_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgxtest/pkg.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/pkgxtest/xtest_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/test/test_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/testxtest/test_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/testxtest/xtest_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/empty/xtest/xtest_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/gencycle/gencycle.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/importmain/ismain/main.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/importmain/test/test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/importmain/test/test_test.go6
-rw-r--r--libgo/go/cmd/go/testdata/src/my.pkg/main/main.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/my.pkg/pkg.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/testrace/race_test.go29
-rw-r--r--libgo/go/cmd/go/testdata/standalone_benchmark_test.go6
-rw-r--r--libgo/go/cmd/go/testdata/standalone_fail_sub_test.go8
-rw-r--r--libgo/go/cmd/go/testdata/standalone_parallel_sub_test.go14
-rw-r--r--libgo/go/cmd/go/testdata/standalone_sub_test.go7
-rw-r--r--libgo/go/cmd/go/testdata/testterminal18153/terminal_test.go39
-rw-r--r--libgo/go/cmd/go/testflag.go4
-rw-r--r--libgo/go/cmd/go/tool.go2
-rw-r--r--libgo/go/cmd/go/vcs.go70
-rw-r--r--libgo/go/cmd/go/vcs_test.go69
-rw-r--r--libgo/go/cmd/go/vendor_test.go36
-rw-r--r--libgo/go/cmd/gofmt/doc.go5
-rw-r--r--libgo/go/cmd/gofmt/gofmt.go52
-rw-r--r--libgo/go/cmd/gofmt/gofmt_test.go13
-rw-r--r--libgo/go/cmd/gofmt/simplify.go60
-rw-r--r--libgo/go/cmd/gofmt/testdata/composites.golden14
-rw-r--r--libgo/go/cmd/gofmt/testdata/composites.input14
-rw-r--r--libgo/go/cmd/internal/browser/browser.go46
-rw-r--r--libgo/go/compress/flate/deflate.go20
-rw-r--r--libgo/go/compress/flate/deflate_test.go183
-rw-r--r--libgo/go/compress/flate/deflatefast.go186
-rw-r--r--libgo/go/compress/flate/example_test.go245
-rw-r--r--libgo/go/compress/flate/flate_test.go1
-rw-r--r--libgo/go/compress/flate/huffman_bit_writer.go2
-rw-r--r--libgo/go/compress/flate/inflate.go3
-rw-r--r--libgo/go/compress/flate/inflate_test.go29
-rw-r--r--libgo/go/compress/flate/writer_test.go9
-rw-r--r--libgo/go/compress/gzip/example_test.go130
-rw-r--r--libgo/go/compress/gzip/gunzip.go7
-rw-r--r--libgo/go/compress/gzip/gunzip_test.go20
-rw-r--r--libgo/go/compress/gzip/gzip.go23
-rw-r--r--libgo/go/compress/gzip/gzip_test.go4
-rw-r--r--libgo/go/compress/gzip/issue14937_test.go9
-rw-r--r--libgo/go/compress/zlib/reader_test.go18
-rw-r--r--libgo/go/compress/zlib/writer.go11
-rw-r--r--libgo/go/compress/zlib/writer_test.go5
-rw-r--r--libgo/go/container/heap/heap.go9
-rwxr-xr-xlibgo/go/container/list/list_test.go6
-rw-r--r--libgo/go/context/benchmark_test.go44
-rw-r--r--libgo/go/context/context.go26
-rw-r--r--libgo/go/context/context_test.go88
-rw-r--r--libgo/go/context/example_test.go116
-rw-r--r--libgo/go/context/net_test.go21
-rw-r--r--libgo/go/context/withtimeout_test.go35
-rw-r--r--libgo/go/context/x_test.go29
-rw-r--r--libgo/go/crypto/aes/aes_gcm.go7
-rw-r--r--libgo/go/crypto/aes/cbc_s390x.go4
-rw-r--r--libgo/go/crypto/aes/cipher_amd64.go4
-rw-r--r--libgo/go/crypto/aes/cipher_s390x.go10
-rw-r--r--libgo/go/crypto/aes/const.go7
-rw-r--r--libgo/go/crypto/aes/gcm_s390x.go272
-rw-r--r--libgo/go/crypto/cipher/cipher_test.go54
-rw-r--r--libgo/go/crypto/cipher/example_test.go4
-rw-r--r--libgo/go/crypto/cipher/gcm.go14
-rw-r--r--libgo/go/crypto/cipher/gcm_test.go158
-rw-r--r--libgo/go/crypto/dsa/dsa.go20
-rw-r--r--libgo/go/crypto/dsa/dsa_test.go38
-rw-r--r--libgo/go/crypto/ecdsa/ecdsa.go2
-rw-r--r--libgo/go/crypto/ecdsa/ecdsa_test.go12
-rw-r--r--libgo/go/crypto/elliptic/elliptic.go6
-rw-r--r--libgo/go/crypto/elliptic/elliptic_test.go2
-rw-r--r--libgo/go/crypto/elliptic/p224.go4
-rw-r--r--libgo/go/crypto/elliptic/p256.go28
-rw-r--r--libgo/go/crypto/elliptic/p256_generic.go16
-rw-r--r--libgo/go/crypto/elliptic/p256_s390x.go513
-rw-r--r--libgo/go/crypto/hmac/hmac.go2
-rw-r--r--libgo/go/crypto/internal/cipherhw/cipherhw_amd64.go16
-rw-r--r--libgo/go/crypto/internal/cipherhw/cipherhw_s390x.go18
-rw-r--r--libgo/go/crypto/internal/cipherhw/doc.go7
-rw-r--r--libgo/go/crypto/internal/cipherhw/generic.go11
-rw-r--r--libgo/go/crypto/rand/util_test.go9
-rw-r--r--libgo/go/crypto/rsa/rsa.go25
-rw-r--r--libgo/go/crypto/rsa/rsa_test.go11
-rw-r--r--libgo/go/crypto/sha1/sha1.go70
-rw-r--r--libgo/go/crypto/sha1/sha1_test.go17
-rw-r--r--libgo/go/crypto/sha1/sha1block_amd64.go2
-rw-r--r--libgo/go/crypto/sha256/example_test.go43
-rw-r--r--libgo/go/crypto/sha256/sha256block_decl.go2
-rw-r--r--libgo/go/crypto/sha256/sha256block_generic.go2
-rw-r--r--libgo/go/crypto/sha512/sha512block_decl.go2
-rw-r--r--libgo/go/crypto/sha512/sha512block_generic.go2
-rw-r--r--libgo/go/crypto/tls/alert.go2
-rw-r--r--libgo/go/crypto/tls/cipher_suites.go155
-rw-r--r--libgo/go/crypto/tls/common.go230
-rw-r--r--libgo/go/crypto/tls/conn.go214
-rw-r--r--libgo/go/crypto/tls/conn_test.go22
-rw-r--r--libgo/go/crypto/tls/handshake_client.go198
-rw-r--r--libgo/go/crypto/tls/handshake_client_test.go592
-rw-r--r--libgo/go/crypto/tls/handshake_messages.go7
-rw-r--r--libgo/go/crypto/tls/handshake_messages_test.go63
-rw-r--r--libgo/go/crypto/tls/handshake_server.go130
-rw-r--r--libgo/go/crypto/tls/handshake_server_test.go307
-rw-r--r--libgo/go/crypto/tls/handshake_test.go71
-rw-r--r--libgo/go/crypto/tls/key_agreement.go156
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA112
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA175
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA176
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA239
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES93
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES168
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4145
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES95
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES170
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4145
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256149
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-SHA25689
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384149
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN165
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch158
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA119
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA177
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384250
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA183
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA240
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES95
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM87
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA25691
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA38487
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY130577
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES170
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA25695
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY130581
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4145
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce456
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice751
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected463
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected168
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-SCT162
-rw-r--r--libgo/go/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE-RSA-AES-GCM85
-rw-r--r--libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES140
-rw-r--r--libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES142
-rw-r--r--libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4132
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES81
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-3DES132
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES138
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4126
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv11-FallbackSCSV21
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv11-RSA-RC4126
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN181
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch182
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA97
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA173
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven163
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven227
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven145
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES83
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicket154
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable154
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-3DES137
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES141
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM149
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384149
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4131
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-Resume64
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-ResumeDisabled160
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-SNI131
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate131
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound131
-rw-r--r--libgo/go/crypto/tls/testdata/Server-TLSv12-X25519-ECDHE-RSA-AES-GCM79
-rw-r--r--libgo/go/crypto/tls/tls.go6
-rw-r--r--libgo/go/crypto/tls/tls_test.go150
-rw-r--r--libgo/go/crypto/x509/cert_pool.go30
-rw-r--r--libgo/go/crypto/x509/pkix/pkix.go56
-rw-r--r--libgo/go/crypto/x509/root_cgo_darwin.go83
-rw-r--r--libgo/go/crypto/x509/root_darwin.go225
-rw-r--r--libgo/go/crypto/x509/root_linux.go9
-rw-r--r--libgo/go/crypto/x509/root_windows.go35
-rw-r--r--libgo/go/crypto/x509/verify.go80
-rw-r--r--libgo/go/crypto/x509/verify_test.go309
-rw-r--r--libgo/go/crypto/x509/x509.go227
-rw-r--r--libgo/go/crypto/x509/x509_test.go248
-rw-r--r--libgo/go/database/sql/convert.go91
-rw-r--r--libgo/go/database/sql/convert_test.go83
-rw-r--r--libgo/go/database/sql/ctxutil.go163
-rw-r--r--libgo/go/database/sql/driver/driver.go195
-rw-r--r--libgo/go/database/sql/driver/types.go42
-rw-r--r--libgo/go/database/sql/driver/types_test.go16
-rw-r--r--libgo/go/database/sql/fakedb_test.go375
-rw-r--r--libgo/go/database/sql/sql.go916
-rw-r--r--libgo/go/database/sql/sql_test.go555
-rw-r--r--libgo/go/debug/elf/file.go44
-rw-r--r--libgo/go/debug/elf/file_test.go38
-rw-r--r--libgo/go/debug/elf/testdata/go-relocation-test-gcc492-mipsle.objbin0 -> 2864 bytes
-rw-r--r--libgo/go/debug/elf/testdata/go-relocation-test-gcc540-mips.objbin0 -> 3064 bytes
-rw-r--r--libgo/go/debug/gosym/pclntab.go3
-rw-r--r--libgo/go/debug/gosym/pclntab_test.go4
-rw-r--r--libgo/go/debug/macho/macho.go2
-rw-r--r--libgo/go/debug/pe/file.go21
-rw-r--r--libgo/go/debug/pe/file_test.go2
-rw-r--r--libgo/go/debug/pe/section.go14
-rw-r--r--libgo/go/debug/pe/string.go14
-rw-r--r--libgo/go/debug/pe/symbol.go13
-rw-r--r--libgo/go/encoding/asn1/asn1.go9
-rw-r--r--libgo/go/encoding/asn1/asn1_test.go41
-rw-r--r--libgo/go/encoding/asn1/marshal.go623
-rw-r--r--libgo/go/encoding/asn1/marshal_test.go34
-rw-r--r--libgo/go/encoding/base64/base64.go24
-rw-r--r--libgo/go/encoding/base64/base64_test.go21
-rw-r--r--libgo/go/encoding/binary/binary.go59
-rw-r--r--libgo/go/encoding/binary/binary_test.go39
-rw-r--r--libgo/go/encoding/csv/reader.go68
-rw-r--r--libgo/go/encoding/csv/reader_test.go72
-rw-r--r--libgo/go/encoding/gob/encoder.go3
-rw-r--r--libgo/go/encoding/gob/encoder_test.go14
-rw-r--r--libgo/go/encoding/hex/example_test.go100
-rw-r--r--libgo/go/encoding/hex/hex.go15
-rw-r--r--libgo/go/encoding/hex/hex_test.go16
-rw-r--r--libgo/go/encoding/json/decode.go129
-rw-r--r--libgo/go/encoding/json/decode_test.go297
-rw-r--r--libgo/go/encoding/json/encode.go132
-rw-r--r--libgo/go/encoding/json/encode_test.go273
-rw-r--r--libgo/go/encoding/json/example_marshaling_test.go75
-rw-r--r--libgo/go/encoding/json/scanner_test.go1
-rw-r--r--libgo/go/encoding/json/stream.go9
-rw-r--r--libgo/go/encoding/json/tables.go218
-rw-r--r--libgo/go/encoding/json/tagkey_test.go5
-rw-r--r--libgo/go/encoding/pem/example_test.go46
-rw-r--r--libgo/go/encoding/pem/pem.go19
-rw-r--r--libgo/go/encoding/pem/pem_test.go42
-rw-r--r--libgo/go/encoding/xml/marshal.go180
-rw-r--r--libgo/go/encoding/xml/marshal_test.go91
-rw-r--r--libgo/go/encoding/xml/read.go92
-rw-r--r--libgo/go/encoding/xml/read_test.go21
-rw-r--r--libgo/go/encoding/xml/typeinfo.go8
-rw-r--r--libgo/go/expvar/expvar.go27
-rw-r--r--libgo/go/expvar/expvar_test.go28
-rw-r--r--libgo/go/flag/export_test.go1
-rw-r--r--libgo/go/flag/flag.go37
-rw-r--r--libgo/go/fmt/doc.go70
-rw-r--r--libgo/go/fmt/export_test.go1
-rw-r--r--libgo/go/fmt/fmt_test.go55
-rw-r--r--libgo/go/fmt/format.go2
-rw-r--r--libgo/go/fmt/print.go31
-rw-r--r--libgo/go/fmt/scan.go96
-rw-r--r--libgo/go/fmt/scan_test.go143
-rw-r--r--libgo/go/go/ast/ast.go4
-rw-r--r--libgo/go/go/build/build.go96
-rw-r--r--libgo/go/go/build/build_test.go1
-rw-r--r--libgo/go/go/build/deps_test.go140
-rw-r--r--libgo/go/go/build/doc.go1
-rw-r--r--libgo/go/go/build/syslist.go2
-rw-r--r--libgo/go/go/constant/value.go40
-rw-r--r--libgo/go/go/doc/comment.go2
-rw-r--r--libgo/go/go/doc/comment_test.go1
-rw-r--r--libgo/go/go/doc/reader.go24
-rw-r--r--libgo/go/go/doc/testdata/issue17788.0.golden8
-rw-r--r--libgo/go/go/doc/testdata/issue17788.1.golden8
-rw-r--r--libgo/go/go/doc/testdata/issue17788.2.golden8
-rw-r--r--libgo/go/go/doc/testdata/issue17788.go8
-rw-r--r--libgo/go/go/doc/testdata/predeclared.0.golden8
-rw-r--r--libgo/go/go/doc/testdata/predeclared.1.golden22
-rw-r--r--libgo/go/go/doc/testdata/predeclared.2.golden8
-rw-r--r--libgo/go/go/doc/testdata/predeclared.go22
-rw-r--r--libgo/go/go/format/format_test.go27
-rw-r--r--libgo/go/go/internal/gccgoimporter/importer.go5
-rw-r--r--libgo/go/go/internal/gccgoimporter/importer_test.go8
-rw-r--r--libgo/go/go/internal/gccgoimporter/parser.go54
-rw-r--r--libgo/go/go/internal/gccgoimporter/testdata/conversions.go5
-rw-r--r--libgo/go/go/internal/gcimporter/bimport.go288
-rw-r--r--libgo/go/go/internal/gcimporter/exportdata.go10
-rw-r--r--libgo/go/go/internal/gcimporter/gcimporter.go881
-rw-r--r--libgo/go/go/internal/gcimporter/gcimporter_test.go85
-rw-r--r--libgo/go/go/internal/gcimporter/testdata/exports.go7
-rw-r--r--libgo/go/go/internal/gcimporter/testdata/versions/test.go25
-rw-r--r--libgo/go/go/parser/interface.go2
-rw-r--r--libgo/go/go/printer/printer.go38
-rw-r--r--libgo/go/go/printer/printer_test.go55
-rw-r--r--libgo/go/go/printer/testdata/comments.golden26
-rw-r--r--libgo/go/go/printer/testdata/comments.input18
-rw-r--r--libgo/go/go/scanner/scanner.go6
-rw-r--r--libgo/go/go/scanner/scanner_test.go1
-rw-r--r--libgo/go/go/token/position.go2
-rw-r--r--libgo/go/go/token/position_test.go31
-rw-r--r--libgo/go/go/types/api.go15
-rw-r--r--libgo/go/go/types/api_test.go392
-rw-r--r--libgo/go/go/types/assignments.go4
-rw-r--r--libgo/go/go/types/builtins.go6
-rw-r--r--libgo/go/go/types/call.go27
-rw-r--r--libgo/go/go/types/check.go1
-rw-r--r--libgo/go/go/types/check_test.go2
-rw-r--r--libgo/go/go/types/conversions.go11
-rw-r--r--libgo/go/go/types/decl.go104
-rw-r--r--libgo/go/go/types/expr.go41
-rw-r--r--libgo/go/go/types/initorder.go230
-rw-r--r--libgo/go/go/types/object.go53
-rw-r--r--libgo/go/go/types/ordering.go20
-rw-r--r--libgo/go/go/types/predicates.go35
-rw-r--r--libgo/go/go/types/resolver.go22
-rw-r--r--libgo/go/go/types/sizes.go51
-rw-r--r--libgo/go/go/types/sizes_test.go119
-rw-r--r--libgo/go/go/types/stdlib_test.go2
-rw-r--r--libgo/go/go/types/stmt.go26
-rw-r--r--libgo/go/go/types/type.go11
-rw-r--r--libgo/go/go/types/typexpr.go25
-rw-r--r--libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305.go83
-rw-r--r--libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go80
-rw-r--r--libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go70
-rw-r--r--libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go15
-rw-r--r--libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_test.go182
-rw-r--r--libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_test_vectors.go332
-rw-r--r--libgo/go/golang_org/x/crypto/chacha20poly1305/internal/chacha20/chacha_generic.go199
-rw-r--r--libgo/go/golang_org/x/crypto/chacha20poly1305/internal/chacha20/chacha_test.go29
-rw-r--r--libgo/go/golang_org/x/crypto/curve25519/curve25519.go841
-rw-r--r--libgo/go/golang_org/x/crypto/curve25519/curve25519_test.go29
-rw-r--r--libgo/go/golang_org/x/crypto/curve25519/doc.go23
-rw-r--r--libgo/go/golang_org/x/crypto/curve25519/mont25519_amd64.go240
-rw-r--r--libgo/go/golang_org/x/crypto/poly1305/poly1305.go32
-rw-r--r--libgo/go/golang_org/x/crypto/poly1305/poly1305_test.go92
-rw-r--r--libgo/go/golang_org/x/crypto/poly1305/sum_amd64.go22
-rw-r--r--libgo/go/golang_org/x/crypto/poly1305/sum_arm.go22
-rw-r--r--libgo/go/golang_org/x/crypto/poly1305/sum_ref.go1531
-rw-r--r--libgo/go/golang_org/x/net/idna/idna.go68
-rw-r--r--libgo/go/golang_org/x/net/idna/idna_test.go43
-rw-r--r--libgo/go/golang_org/x/net/idna/punycode.go200
-rw-r--r--libgo/go/golang_org/x/net/idna/punycode_test.go198
-rw-r--r--libgo/go/golang_org/x/net/lex/httplex/httplex.go39
-rw-r--r--libgo/go/golang_org/x/net/lex/httplex/httplex_test.go18
-rw-r--r--libgo/go/golang_org/x/net/lif/address.go105
-rw-r--r--libgo/go/golang_org/x/net/lif/address_test.go121
-rw-r--r--libgo/go/golang_org/x/net/lif/binary.go68
-rw-r--r--libgo/go/golang_org/x/net/lif/defs_solaris.go90
-rw-r--r--libgo/go/golang_org/x/net/lif/lif.go43
-rw-r--r--libgo/go/golang_org/x/net/lif/link.go122
-rw-r--r--libgo/go/golang_org/x/net/lif/link_test.go61
-rw-r--r--libgo/go/golang_org/x/net/lif/syscall.go33
-rw-r--r--libgo/go/golang_org/x/net/lif/zsys_solaris_amd64.go103
-rw-r--r--libgo/go/golang_org/x/net/route/address.go18
-rw-r--r--libgo/go/golang_org/x/net/route/interface_freebsd.go12
-rw-r--r--libgo/go/golang_org/x/net/route/interface_openbsd.go9
-rw-r--r--libgo/go/golang_org/x/net/route/message.go6
-rw-r--r--libgo/go/golang_org/x/net/route/message_test.go23
-rw-r--r--libgo/go/golang_org/x/net/route/route_openbsd.go6
-rw-r--r--libgo/go/golang_org/x/net/route/route_test.go35
-rw-r--r--libgo/go/golang_org/x/text/transform/transform.go705
-rw-r--r--libgo/go/golang_org/x/text/unicode/norm/composition.go514
-rw-r--r--libgo/go/golang_org/x/text/unicode/norm/forminfo.go256
-rw-r--r--libgo/go/golang_org/x/text/unicode/norm/input.go105
-rw-r--r--libgo/go/golang_org/x/text/unicode/norm/iter.go450
-rw-r--r--libgo/go/golang_org/x/text/unicode/norm/normalize.go608
-rw-r--r--libgo/go/golang_org/x/text/unicode/norm/readwriter.go125
-rw-r--r--libgo/go/golang_org/x/text/unicode/norm/tables.go7627
-rw-r--r--libgo/go/golang_org/x/text/unicode/norm/transform.go88
-rw-r--r--libgo/go/golang_org/x/text/unicode/norm/trie.go54
-rw-r--r--libgo/go/golang_org/x/text/unicode/norm/triegen.go117
-rw-r--r--libgo/go/golang_org/x/text/width/kind_string.go16
-rw-r--r--libgo/go/golang_org/x/text/width/tables.go1284
-rw-r--r--libgo/go/golang_org/x/text/width/transform.go239
-rw-r--r--libgo/go/golang_org/x/text/width/trieval.go30
-rw-r--r--libgo/go/golang_org/x/text/width/width.go206
-rw-r--r--libgo/go/hash/crc32/crc32.go160
-rw-r--r--libgo/go/hash/crc32/crc32_amd64.go214
-rw-r--r--libgo/go/hash/crc32/crc32_amd64p32.go37
-rw-r--r--libgo/go/hash/crc32/crc32_generic.go92
-rw-r--r--libgo/go/hash/crc32/crc32_otherarch.go15
-rw-r--r--libgo/go/hash/crc32/crc32_s390x.go81
-rw-r--r--libgo/go/hash/crc32/crc32_test.go215
-rw-r--r--libgo/go/html/template/clone_test.go68
-rw-r--r--libgo/go/html/template/content_test.go41
-rw-r--r--libgo/go/html/template/context.go14
-rw-r--r--libgo/go/html/template/doc.go2
-rw-r--r--libgo/go/html/template/error.go2
-rw-r--r--libgo/go/html/template/escape.go14
-rw-r--r--libgo/go/html/template/escape_test.go14
-rw-r--r--libgo/go/html/template/js.go44
-rw-r--r--libgo/go/html/template/js_test.go19
-rw-r--r--libgo/go/html/template/template.go81
-rw-r--r--libgo/go/html/template/template_test.go130
-rw-r--r--libgo/go/html/template/transition.go30
-rw-r--r--libgo/go/html/template/url.go2
-rw-r--r--libgo/go/image/color/color.go23
-rw-r--r--libgo/go/image/color/ycbcr.go94
-rw-r--r--libgo/go/image/color/ycbcr_test.go63
-rw-r--r--libgo/go/image/draw/bench_test.go2
-rw-r--r--libgo/go/image/draw/draw.go16
-rw-r--r--libgo/go/image/draw/example_test.go50
-rw-r--r--libgo/go/image/gif/reader.go83
-rw-r--r--libgo/go/image/gif/reader_test.go17
-rw-r--r--libgo/go/image/png/example_test.go79
-rw-r--r--libgo/go/image/png/reader.go266
-rw-r--r--libgo/go/image/png/reader_test.go175
-rw-r--r--libgo/go/image/png/testdata/pngsuite/README21
-rw-r--r--libgo/go/image/png/writer.go5
-rw-r--r--libgo/go/index/suffixarray/example_test.go24
-rw-r--r--libgo/go/internal/pprof/profile/encode.go470
-rw-r--r--libgo/go/internal/pprof/profile/filter.go158
-rw-r--r--libgo/go/internal/pprof/profile/legacy_profile.go1266
-rw-r--r--libgo/go/internal/pprof/profile/profile.go572
-rw-r--r--libgo/go/internal/pprof/profile/profile_test.go79
-rw-r--r--libgo/go/internal/pprof/profile/proto.go360
-rw-r--r--libgo/go/internal/pprof/profile/proto_test.go67
-rw-r--r--libgo/go/internal/pprof/profile/prune.go97
-rw-r--r--libgo/go/internal/race/norace.go2
-rw-r--r--libgo/go/internal/race/race.go4
-rw-r--r--libgo/go/internal/syscall/unix/getrandom_linux_mipsx.go11
-rw-r--r--libgo/go/internal/syscall/windows/mksyscall.go7
-rw-r--r--libgo/go/internal/syscall/windows/registry/mksyscall.go7
-rw-r--r--libgo/go/internal/syscall/windows/registry/syscall.go2
-rw-r--r--libgo/go/internal/syscall/windows/registry/zsyscall_windows.go27
-rw-r--r--libgo/go/internal/syscall/windows/reparse_windows.go64
-rw-r--r--libgo/go/internal/syscall/windows/security_windows.go57
-rw-r--r--libgo/go/internal/syscall/windows/syscall_windows.go26
-rw-r--r--libgo/go/internal/syscall/windows/zsyscall_windows.go174
-rw-r--r--libgo/go/internal/testenv/testenv.go52
-rw-r--r--libgo/go/internal/testenv/testenv_notwin.go20
-rw-r--r--libgo/go/internal/testenv/testenv_windows.go49
-rw-r--r--libgo/go/internal/trace/goroutines.go6
-rw-r--r--libgo/go/internal/trace/mkcanned.bash19
-rw-r--r--libgo/go/internal/trace/order.go5
-rw-r--r--libgo/go/internal/trace/parser.go33
-rw-r--r--libgo/go/internal/trace/parser_test.go47
-rw-r--r--libgo/go/internal/trace/testdata/http_1_7_goodbin0 -> 1971 bytes
-rw-r--r--libgo/go/internal/trace/testdata/stress_1_7_goodbin0 -> 396526 bytes
-rw-r--r--libgo/go/internal/trace/testdata/stress_start_stop_1_7_goodbin0 -> 2055 bytes
-rw-r--r--libgo/go/internal/trace/writer.go45
-rw-r--r--libgo/go/io/io.go8
-rw-r--r--libgo/go/io/ioutil/ioutil.go9
-rw-r--r--libgo/go/io/ioutil/tempfile.go5
-rw-r--r--libgo/go/io/ioutil/tempfile_test.go16
-rw-r--r--libgo/go/io/multi.go11
-rw-r--r--libgo/go/io/multi_test.go60
-rw-r--r--libgo/go/io/pipe.go19
-rw-r--r--libgo/go/io/pipe_test.go12
-rw-r--r--libgo/go/log/log.go2
-rw-r--r--libgo/go/log/syslog/doc.go2
-rw-r--r--libgo/go/log/syslog/example_test.go24
-rw-r--r--libgo/go/log/syslog/syslog.go2
-rw-r--r--libgo/go/log/syslog/syslog_test.go5
-rw-r--r--libgo/go/math/all_test.go145
-rw-r--r--libgo/go/math/arith_s390x.go31
-rw-r--r--libgo/go/math/arith_s390x_test.go146
-rw-r--r--libgo/go/math/big/arith_decl_s390x.go23
-rw-r--r--libgo/go/math/big/arith_s390x_test.go45
-rw-r--r--libgo/go/math/big/arith_test.go13
-rw-r--r--libgo/go/math/big/decimal.go7
-rw-r--r--libgo/go/math/big/decimal_test.go22
-rw-r--r--libgo/go/math/big/doc.go2
-rw-r--r--libgo/go/math/big/float.go44
-rw-r--r--libgo/go/math/big/float_test.go47
-rw-r--r--libgo/go/math/big/floatconv.go24
-rw-r--r--libgo/go/math/big/floatconv_test.go52
-rw-r--r--libgo/go/math/big/floatexample_test.go6
-rw-r--r--libgo/go/math/big/floatmarsh.go2
-rw-r--r--libgo/go/math/big/ftoa.go2
-rw-r--r--libgo/go/math/big/gcd_test.go3
-rw-r--r--libgo/go/math/big/int.go44
-rw-r--r--libgo/go/math/big/int_test.go173
-rw-r--r--libgo/go/math/big/intconv.go4
-rw-r--r--libgo/go/math/big/intmarsh.go6
-rw-r--r--libgo/go/math/big/nat.go176
-rw-r--r--libgo/go/math/big/natconv_test.go6
-rw-r--r--libgo/go/math/big/prime.go320
-rw-r--r--libgo/go/math/big/prime_test.go214
-rw-r--r--libgo/go/math/big/rat_test.go12
-rw-r--r--libgo/go/math/big/ratconv.go16
-rw-r--r--libgo/go/math/big/ratconv_test.go11
-rw-r--r--libgo/go/math/cmplx/cmath_test.go8
-rw-r--r--libgo/go/math/cmplx/example_test.go30
-rw-r--r--libgo/go/math/cmplx/tan.go12
-rw-r--r--libgo/go/math/expm1.go2
-rw-r--r--libgo/go/math/export_s390x_test.go14
-rw-r--r--libgo/go/math/gamma.go43
-rw-r--r--libgo/go/math/j0.go38
-rw-r--r--libgo/go/math/j1.go38
-rw-r--r--libgo/go/math/jn.go2
-rw-r--r--libgo/go/math/log1p.go7
-rw-r--r--libgo/go/math/rand/gen_cooked.go89
-rw-r--r--libgo/go/math/rand/race_test.go1
-rw-r--r--libgo/go/math/rand/rand.go42
-rw-r--r--libgo/go/math/rand/rand_test.go15
-rw-r--r--libgo/go/math/rand/regress_test.go20
-rw-r--r--libgo/go/math/rand/rng.go295
-rw-r--r--libgo/go/math/sin.go8
-rw-r--r--libgo/go/math/sincos.go4
-rw-r--r--libgo/go/math/tan.go4
-rw-r--r--libgo/go/mime/mediatype.go37
-rw-r--r--libgo/go/mime/mediatype_test.go14
-rw-r--r--libgo/go/mime/multipart/formdata.go4
-rw-r--r--libgo/go/mime/multipart/multipart.go219
-rw-r--r--libgo/go/mime/multipart/multipart_test.go69
-rw-r--r--libgo/go/mime/quotedprintable/example_test.go39
-rw-r--r--libgo/go/mime/quotedprintable/reader.go13
-rw-r--r--libgo/go/mime/quotedprintable/reader_test.go16
-rw-r--r--libgo/go/net/addrselect.go51
-rw-r--r--libgo/go/net/addrselect_test.go85
-rw-r--r--libgo/go/net/cgo_unix.go10
-rw-r--r--libgo/go/net/conf.go26
-rw-r--r--libgo/go/net/conf_test.go114
-rw-r--r--libgo/go/net/dial.go44
-rw-r--r--libgo/go/net/dial_test.go19
-rw-r--r--libgo/go/net/dnsclient.go16
-rw-r--r--libgo/go/net/dnsclient_unix.go83
-rw-r--r--libgo/go/net/dnsclient_unix_test.go121
-rw-r--r--libgo/go/net/dnsconfig_unix.go25
-rw-r--r--libgo/go/net/dnsconfig_unix_test.go83
-rw-r--r--libgo/go/net/dnsmsg.go2
-rw-r--r--libgo/go/net/dnsmsg_test.go6
-rw-r--r--libgo/go/net/dnsname_test.go27
-rw-r--r--libgo/go/net/error_test.go21
-rw-r--r--libgo/go/net/fd_io_plan9.go93
-rw-r--r--libgo/go/net/fd_plan9.go149
-rw-r--r--libgo/go/net/fd_poll_nacl.go2
-rw-r--r--libgo/go/net/fd_poll_runtime.go4
-rw-r--r--libgo/go/net/fd_unix.go15
-rw-r--r--libgo/go/net/fd_windows.go66
-rw-r--r--libgo/go/net/file.go3
-rw-r--r--libgo/go/net/file_plan9.go2
-rw-r--r--libgo/go/net/http/client.go411
-rw-r--r--libgo/go/net/http/client_test.go697
-rw-r--r--libgo/go/net/http/clientserver_test.go171
-rw-r--r--libgo/go/net/http/cookie.go66
-rw-r--r--libgo/go/net/http/cookie_test.go98
-rw-r--r--libgo/go/net/http/cookiejar/dummy_publicsuffix_test.go23
-rw-r--r--libgo/go/net/http/cookiejar/example_test.go67
-rw-r--r--libgo/go/net/http/cookiejar/jar.go33
-rw-r--r--libgo/go/net/http/doc.go30
-rw-r--r--libgo/go/net/http/export_test.go39
-rw-r--r--libgo/go/net/http/fcgi/fcgi.go6
-rw-r--r--libgo/go/net/http/fs.go339
-rw-r--r--libgo/go/net/http/fs_test.go160
-rw-r--r--libgo/go/net/http/h2_bundle.go2269
-rw-r--r--libgo/go/net/http/header.go6
-rw-r--r--libgo/go/net/http/http.go98
-rw-r--r--libgo/go/net/http/http_test.go20
-rw-r--r--libgo/go/net/http/httptest/httptest.go3
-rw-r--r--libgo/go/net/http/httptest/recorder.go58
-rw-r--r--libgo/go/net/http/httptest/recorder_test.go22
-rw-r--r--libgo/go/net/http/httptest/server.go15
-rw-r--r--libgo/go/net/http/httptrace/example_test.go31
-rw-r--r--libgo/go/net/http/httptrace/trace.go31
-rw-r--r--libgo/go/net/http/httptrace/trace_test.go29
-rw-r--r--libgo/go/net/http/httputil/dump.go13
-rw-r--r--libgo/go/net/http/httputil/dump_test.go12
-rw-r--r--libgo/go/net/http/httputil/persist.go9
-rw-r--r--libgo/go/net/http/httputil/reverseproxy.go151
-rw-r--r--libgo/go/net/http/httputil/reverseproxy_test.go179
-rw-r--r--libgo/go/net/http/internal/chunked.go30
-rw-r--r--libgo/go/net/http/internal/chunked_test.go27
-rw-r--r--libgo/go/net/http/main_test.go21
-rw-r--r--libgo/go/net/http/npn_test.go1
-rw-r--r--libgo/go/net/http/range_test.go2
-rw-r--r--libgo/go/net/http/readrequest_test.go26
-rw-r--r--libgo/go/net/http/request.go212
-rw-r--r--libgo/go/net/http/request_test.go195
-rw-r--r--libgo/go/net/http/requestwrite_test.go296
-rw-r--r--libgo/go/net/http/response.go4
-rw-r--r--libgo/go/net/http/response_test.go35
-rw-r--r--libgo/go/net/http/responsewrite_test.go21
-rw-r--r--libgo/go/net/http/serve_test.go672
-rw-r--r--libgo/go/net/http/server.go719
-rw-r--r--libgo/go/net/http/sniff_test.go2
-rw-r--r--libgo/go/net/http/transfer.go216
-rw-r--r--libgo/go/net/http/transport.go286
-rw-r--r--libgo/go/net/http/transport_internal_test.go67
-rw-r--r--libgo/go/net/http/transport_test.go400
-rw-r--r--libgo/go/net/interface.go31
-rw-r--r--libgo/go/net/interface_plan9.go198
-rw-r--r--libgo/go/net/interface_solaris.go107
-rw-r--r--libgo/go/net/interface_stub.go2
-rw-r--r--libgo/go/net/interface_test.go11
-rw-r--r--libgo/go/net/ip.go109
-rw-r--r--libgo/go/net/ip_test.go16
-rw-r--r--libgo/go/net/iprawsock.go23
-rw-r--r--libgo/go/net/iprawsock_posix.go16
-rw-r--r--libgo/go/net/iprawsock_test.go27
-rw-r--r--libgo/go/net/ipsock.go61
-rw-r--r--libgo/go/net/ipsock_plan9.go60
-rw-r--r--libgo/go/net/ipsock_posix.go10
-rw-r--r--libgo/go/net/ipsock_test.go14
-rw-r--r--libgo/go/net/lookup.go291
-rw-r--r--libgo/go/net/lookup_nacl.go52
-rw-r--r--libgo/go/net/lookup_plan9.go41
-rw-r--r--libgo/go/net/lookup_stub.go52
-rw-r--r--libgo/go/net/lookup_test.go85
-rw-r--r--libgo/go/net/lookup_unix.go52
-rw-r--r--libgo/go/net/lookup_windows.go59
-rw-r--r--libgo/go/net/mail/message.go15
-rw-r--r--libgo/go/net/mail/message_test.go23
-rw-r--r--libgo/go/net/main_test.go2
-rw-r--r--libgo/go/net/net.go122
-rw-r--r--libgo/go/net/net_test.go104
-rw-r--r--libgo/go/net/parse.go58
-rw-r--r--libgo/go/net/parse_test.go7
-rw-r--r--libgo/go/net/port_unix.go32
-rw-r--r--libgo/go/net/rpc/client.go2
-rw-r--r--libgo/go/net/rpc/client_test.go4
-rw-r--r--libgo/go/net/rpc/server.go6
-rw-r--r--libgo/go/net/rpc/server_test.go3
-rw-r--r--libgo/go/net/smtp/smtp.go5
-rw-r--r--libgo/go/net/smtp/smtp_test.go71
-rw-r--r--libgo/go/net/sock_linux.go2
-rw-r--r--libgo/go/net/sock_posix.go3
-rw-r--r--libgo/go/net/tcpsock.go10
-rw-r--r--libgo/go/net/tcpsock_posix.go4
-rw-r--r--libgo/go/net/tcpsock_test.go125
-rw-r--r--libgo/go/net/tcpsock_unix_test.go4
-rw-r--r--libgo/go/net/testdata/invalid-ndots-resolv.conf1
-rw-r--r--libgo/go/net/testdata/large-ndots-resolv.conf1
-rw-r--r--libgo/go/net/testdata/negative-ndots-resolv.conf1
-rw-r--r--libgo/go/net/textproto/header.go4
-rw-r--r--libgo/go/net/timeout_test.go47
-rw-r--r--libgo/go/net/udpsock.go14
-rw-r--r--libgo/go/net/udpsock_plan9.go38
-rw-r--r--libgo/go/net/udpsock_plan9_test.go69
-rw-r--r--libgo/go/net/udpsock_posix.go4
-rw-r--r--libgo/go/net/udpsock_test.go31
-rw-r--r--libgo/go/net/unixsock.go14
-rw-r--r--libgo/go/net/unixsock_posix.go25
-rw-r--r--libgo/go/net/unixsock_test.go124
-rw-r--r--libgo/go/net/url/url.go185
-rw-r--r--libgo/go/net/url/url_test.go327
-rw-r--r--libgo/go/net/writev_test.go225
-rw-r--r--libgo/go/net/writev_unix.go95
-rw-r--r--libgo/go/os/dir.go128
-rw-r--r--libgo/go/os/dir_gccgo.go102
-rw-r--r--libgo/go/os/dir_unix.go38
-rw-r--r--libgo/go/os/doc.go139
-rw-r--r--libgo/go/os/env.go3
-rw-r--r--libgo/go/os/env_test.go28
-rw-r--r--libgo/go/os/env_unix_test.go26
-rw-r--r--libgo/go/os/error.go14
-rw-r--r--libgo/go/os/error_plan9.go48
-rw-r--r--libgo/go/os/error_test.go2
-rw-r--r--libgo/go/os/error_unix.go33
-rw-r--r--libgo/go/os/error_windows.go34
-rw-r--r--libgo/go/os/error_windows_test.go4
-rw-r--r--libgo/go/os/example_test.go106
-rw-r--r--libgo/go/os/exec.go87
-rw-r--r--libgo/go/os/exec/exec.go63
-rw-r--r--libgo/go/os/exec/exec_test.go62
-rw-r--r--libgo/go/os/exec_windows.go4
-rw-r--r--libgo/go/os/executable.go23
-rw-r--r--libgo/go/os/executable_darwin.go24
-rw-r--r--libgo/go/os/executable_freebsd.go33
-rw-r--r--libgo/go/os/executable_plan9.go19
-rw-r--r--libgo/go/os/executable_procfs.go36
-rw-r--r--libgo/go/os/executable_solaris.go27
-rw-r--r--libgo/go/os/executable_test.go87
-rw-r--r--libgo/go/os/executable_windows.go32
-rw-r--r--libgo/go/os/export_windows_test.go13
-rw-r--r--libgo/go/os/file.go47
-rw-r--r--libgo/go/os/file_plan9.go14
-rw-r--r--libgo/go/os/file_posix.go22
-rw-r--r--libgo/go/os/file_unix.go97
-rw-r--r--libgo/go/os/os_test.go156
-rw-r--r--libgo/go/os/os_unix_test.go39
-rw-r--r--libgo/go/os/path_test.go10
-rw-r--r--libgo/go/os/path_unix.go18
-rw-r--r--libgo/go/os/path_windows.go193
-rw-r--r--libgo/go/os/path_windows_test.go46
-rw-r--r--libgo/go/os/stat_plan9.go10
-rw-r--r--libgo/go/os/stat_unix.go52
-rw-r--r--libgo/go/os/sys.go10
-rw-r--r--libgo/go/os/types.go5
-rw-r--r--libgo/go/os/types_plan9.go13
-rw-r--r--libgo/go/os/types_unix.go6
-rw-r--r--libgo/go/os/user/user.go36
-rw-r--r--libgo/go/os/wait_wait6.go1
-rw-r--r--libgo/go/os/wait_waitid.go2
-rw-r--r--libgo/go/path/filepath/match.go18
-rw-r--r--libgo/go/path/filepath/match_test.go11
-rw-r--r--libgo/go/path/filepath/path.go11
-rw-r--r--libgo/go/path/filepath/path_plan9.go3
-rw-r--r--libgo/go/path/filepath/path_test.go103
-rw-r--r--libgo/go/path/filepath/path_unix.go3
-rw-r--r--libgo/go/path/filepath/path_windows.go11
-rw-r--r--libgo/go/path/filepath/symlink.go5
-rw-r--r--libgo/go/path/filepath/symlink_windows.go2
-rw-r--r--libgo/go/path/path.go2
-rw-r--r--libgo/go/plugin/plugin.go73
-rw-r--r--libgo/go/plugin/plugin_dlopen.go138
-rw-r--r--libgo/go/plugin/plugin_stubs.go17
-rw-r--r--libgo/go/reflect/all_test.go247
-rw-r--r--libgo/go/reflect/deepequal.go11
-rw-r--r--libgo/go/reflect/example_test.go41
-rw-r--r--libgo/go/reflect/export_test.go4
-rw-r--r--libgo/go/reflect/makefunc.go2
-rw-r--r--libgo/go/reflect/swapper.go74
-rw-r--r--libgo/go/reflect/type.go122
-rw-r--r--libgo/go/reflect/value.go4
-rw-r--r--libgo/go/regexp/all_test.go124
-rw-r--r--libgo/go/regexp/exec.go31
-rw-r--r--libgo/go/regexp/exec_test.go6
-rw-r--r--libgo/go/regexp/onepass.go5
-rw-r--r--libgo/go/regexp/regexp.go56
-rw-r--r--libgo/go/runtime/alg.go13
-rw-r--r--libgo/go/runtime/append_test.go16
-rw-r--r--libgo/go/runtime/cgocheck.go4
-rw-r--r--libgo/go/runtime/chan.go49
-rw-r--r--libgo/go/runtime/chan_test.go11
-rw-r--r--libgo/go/runtime/cpuprof.go3
-rw-r--r--libgo/go/runtime/crash_cgo_test.go113
-rw-r--r--libgo/go/runtime/crash_test.go55
-rw-r--r--libgo/go/runtime/crash_unix_test.go4
-rw-r--r--libgo/go/runtime/debug/garbage.go8
-rw-r--r--libgo/go/runtime/debug/garbage_test.go19
-rw-r--r--libgo/go/runtime/export_mmap_test.go9
-rw-r--r--libgo/go/runtime/export_test.go20
-rw-r--r--libgo/go/runtime/extern.go5
-rw-r--r--libgo/go/runtime/fastlog2.go4
-rw-r--r--libgo/go/runtime/gc_test.go45
-rw-r--r--libgo/go/runtime/gcinfo_test.go2
-rw-r--r--libgo/go/runtime/hashmap.go307
-rw-r--r--libgo/go/runtime/hashmap_fast.go36
-rw-r--r--libgo/go/runtime/iface.go4
-rw-r--r--libgo/go/runtime/internal/atomic/atomic.c14
-rw-r--r--libgo/go/runtime/internal/atomic/atomic_test.go44
-rw-r--r--libgo/go/runtime/internal/atomic/bench_test.go28
-rw-r--r--libgo/go/runtime/internal/sys/intrinsics.go22
-rw-r--r--libgo/go/runtime/internal/sys/intrinsics_test.go16
-rw-r--r--libgo/go/runtime/malloc_test.go12
-rw-r--r--libgo/go/runtime/map_test.go1
-rw-r--r--libgo/go/runtime/mcache.go11
-rw-r--r--libgo/go/runtime/mksizeclasses.go325
-rw-r--r--libgo/go/runtime/mmap.go21
-rw-r--r--libgo/go/runtime/mprof.go100
-rw-r--r--libgo/go/runtime/mstats.go413
-rw-r--r--libgo/go/runtime/mstkbar.go4
-rw-r--r--libgo/go/runtime/net_plan9.go29
-rw-r--r--libgo/go/runtime/netpoll.go4
-rw-r--r--libgo/go/runtime/os_darwin.go5
-rw-r--r--libgo/go/runtime/os_freebsd.go16
-rw-r--r--libgo/go/runtime/os_gccgo.go25
-rw-r--r--libgo/go/runtime/os_linux.go65
-rw-r--r--libgo/go/runtime/os_linux_ppc64x.go61
-rw-r--r--libgo/go/runtime/panic.go90
-rw-r--r--libgo/go/runtime/pprof/internal/protopprof/protomemprofile.go83
-rw-r--r--libgo/go/runtime/pprof/internal/protopprof/protomemprofile_test.go104
-rw-r--r--libgo/go/runtime/pprof/internal/protopprof/protopprof.go105
-rw-r--r--libgo/go/runtime/pprof/internal/protopprof/protopprof_test.go171
-rw-r--r--libgo/go/runtime/pprof/mprof_test.go29
-rw-r--r--libgo/go/runtime/pprof/pprof.go221
-rw-r--r--libgo/go/runtime/pprof/pprof_test.go185
-rw-r--r--libgo/go/runtime/print.go36
-rw-r--r--libgo/go/runtime/proc.go134
-rw-r--r--libgo/go/runtime/race/race_linux_test.go37
-rw-r--r--libgo/go/runtime/race/race_windows_test.go46
-rw-r--r--libgo/go/runtime/race/testdata/issue12225_test.go20
-rw-r--r--libgo/go/runtime/race/testdata/issue12664_test.go76
-rw-r--r--libgo/go/runtime/race/testdata/issue13264_test.go13
-rw-r--r--libgo/go/runtime/rune.go219
-rw-r--r--libgo/go/runtime/runtime-lldb_test.go4
-rw-r--r--libgo/go/runtime/runtime.go3
-rw-r--r--libgo/go/runtime/runtime1.go23
-rw-r--r--libgo/go/runtime/runtime2.go56
-rw-r--r--libgo/go/runtime/runtime_mmap_test.go35
-rw-r--r--libgo/go/runtime/runtime_test.go9
-rw-r--r--libgo/go/runtime/select.go77
-rw-r--r--libgo/go/runtime/sema.go44
-rw-r--r--libgo/go/runtime/signal1_unix.go337
-rw-r--r--libgo/go/runtime/signal2_unix.go66
-rw-r--r--libgo/go/runtime/signal_gccgo.go84
-rw-r--r--libgo/go/runtime/signal_sighandler.go11
-rw-r--r--libgo/go/runtime/signal_sigtramp.go40
-rw-r--r--libgo/go/runtime/signal_unix.go582
-rw-r--r--libgo/go/runtime/sigpanic_unix.go48
-rw-r--r--libgo/go/runtime/sizeclasses.go95
-rw-r--r--libgo/go/runtime/slice.go34
-rw-r--r--libgo/go/runtime/stack.go71
-rw-r--r--libgo/go/runtime/string.go174
-rw-r--r--libgo/go/runtime/string_test.go166
-rw-r--r--libgo/go/runtime/stubs.go97
-rw-r--r--libgo/go/runtime/stubs2.go6
-rw-r--r--libgo/go/runtime/testdata/testprog/deadlock.go11
-rw-r--r--libgo/go/runtime/testdata/testprog/gc.go18
-rw-r--r--libgo/go/runtime/testdata/testprog/map.go77
-rw-r--r--libgo/go/runtime/testdata/testprogcgo/pprof.go2
-rw-r--r--libgo/go/runtime/testdata/testprogcgo/raceprof.go78
-rw-r--r--libgo/go/runtime/testdata/testprogcgo/racesig.go102
-rw-r--r--libgo/go/runtime/testdata/testprogcgo/threadpprof.go35
-rw-r--r--libgo/go/runtime/testdata/testprogcgo/threadprof.go9
-rw-r--r--libgo/go/runtime/time.go8
-rw-r--r--libgo/go/runtime/trace.go122
-rw-r--r--libgo/go/runtime/trace/trace.go42
-rw-r--r--libgo/go/runtime/trace/trace_stack_test.go282
-rw-r--r--libgo/go/runtime/trace/trace_test.go489
-rw-r--r--libgo/go/runtime/unaligned2.go2
-rw-r--r--libgo/go/runtime/utf8.go130
-rw-r--r--libgo/go/runtime/vdso_none.go1
-rw-r--r--libgo/go/runtime/write_err_android.go4
-rw-r--r--libgo/go/sort/example_search_test.go42
-rw-r--r--libgo/go/sort/example_test.go19
-rw-r--r--libgo/go/sort/genzfunc.go122
-rw-r--r--libgo/go/sort/sort.go68
-rw-r--r--libgo/go/sort/sort_test.go92
-rw-r--r--libgo/go/sort/zfuncversion.go265
-rw-r--r--libgo/go/strconv/atoi.go4
-rw-r--r--libgo/go/strconv/decimal.go6
-rw-r--r--libgo/go/strconv/ftoa_test.go3
-rw-r--r--libgo/go/strconv/quote.go10
-rw-r--r--libgo/go/strconv/quote_test.go3
-rw-r--r--libgo/go/strconv/strconv_test.go38
-rw-r--r--libgo/go/strings/strings.go163
-rw-r--r--libgo/go/strings/strings_amd64.go52
-rw-r--r--libgo/go/strings/strings_generic.go2
-rw-r--r--libgo/go/strings/strings_s390x.go100
-rw-r--r--libgo/go/strings/strings_test.go182
-rw-r--r--libgo/go/sync/atomic/atomic.c20
-rw-r--r--libgo/go/sync/atomic/atomic_test.go31
-rw-r--r--libgo/go/sync/cond_test.go4
-rw-r--r--libgo/go/sync/example_pool_test.go45
-rw-r--r--libgo/go/sync/mutex.go8
-rw-r--r--libgo/go/sync/mutex_test.go108
-rw-r--r--libgo/go/sync/pool.go81
-rw-r--r--libgo/go/sync/pool_test.go3
-rw-r--r--libgo/go/sync/runtime.go3
-rw-r--r--libgo/go/sync/rwmutex.go4
-rw-r--r--libgo/go/sync/rwmutex_test.go42
-rw-r--r--libgo/go/syscall/const_plan9.go11
-rw-r--r--libgo/go/syscall/dir_plan9.go2
-rw-r--r--libgo/go/syscall/dirent.go102
-rw-r--r--libgo/go/syscall/endian_big.go9
-rw-r--r--libgo/go/syscall/endian_little.go9
-rw-r--r--libgo/go/syscall/env_windows.go2
-rw-r--r--libgo/go/syscall/exec_linux.go4
-rw-r--r--libgo/go/syscall/exec_linux_test.go10
-rw-r--r--libgo/go/syscall/exec_unix.go2
-rw-r--r--libgo/go/syscall/exec_windows.go2
-rw-r--r--libgo/go/syscall/libcall_linux.go21
-rw-r--r--libgo/go/syscall/libcall_posix.go20
-rw-r--r--libgo/go/syscall/netlink_linux.go5
-rw-r--r--libgo/go/syscall/setuidgid_32_linux.go13
-rw-r--r--libgo/go/syscall/setuidgid_linux.go13
-rw-r--r--libgo/go/syscall/sockcmsg_linux.go3
-rw-r--r--libgo/go/syscall/sockcmsg_unix.go7
-rw-r--r--libgo/go/syscall/syscall.go6
-rw-r--r--libgo/go/syscall/syscall_darwin.go19
-rw-r--r--libgo/go/syscall/syscall_darwin_test.go23
-rw-r--r--libgo/go/syscall/syscall_dragonfly.go23
-rw-r--r--libgo/go/syscall/syscall_freebsd.go19
-rw-r--r--libgo/go/syscall/syscall_linux.go23
-rw-r--r--libgo/go/syscall/syscall_linux_mipsx.go12
-rw-r--r--libgo/go/syscall/syscall_linux_test.go28
-rw-r--r--libgo/go/syscall/syscall_netbsd.go19
-rw-r--r--libgo/go/syscall/syscall_openbsd.go19
-rw-r--r--libgo/go/syscall/syscall_solaris.go18
-rw-r--r--libgo/go/syscall/syscall_test.go14
-rw-r--r--libgo/go/syscall/syscall_unix.go1
-rw-r--r--libgo/go/syscall/syscall_unix_test.go9
-rw-r--r--libgo/go/syscall/timestruct.go40
-rw-r--r--libgo/go/testing/benchmark.go22
-rw-r--r--libgo/go/testing/example.go10
-rw-r--r--libgo/go/testing/internal/testdeps/deps.go51
-rw-r--r--libgo/go/testing/quick/quick.go2
-rw-r--r--libgo/go/testing/sub_test.go4
-rw-r--r--libgo/go/testing/testing.go250
-rw-r--r--libgo/go/text/tabwriter/tabwriter.go1
-rw-r--r--libgo/go/text/template/exec.go47
-rw-r--r--libgo/go/text/template/exec_test.go106
-rw-r--r--libgo/go/text/template/funcs.go80
-rw-r--r--libgo/go/text/template/multi_test.go36
-rw-r--r--libgo/go/text/template/parse/lex.go77
-rw-r--r--libgo/go/text/template/parse/lex_test.go259
-rw-r--r--libgo/go/text/template/parse/parse.go25
-rw-r--r--libgo/go/text/template/parse/parse_test.go34
-rw-r--r--libgo/go/text/template/template.go15
-rw-r--r--libgo/go/time/example_test.go18
-rw-r--r--libgo/go/time/export_android_test.go12
-rw-r--r--libgo/go/time/format.go62
-rw-r--r--libgo/go/time/format_test.go4
-rw-r--r--libgo/go/time/sleep.go28
-rw-r--r--libgo/go/time/time.go77
-rw-r--r--libgo/go/time/time_test.go139
-rw-r--r--libgo/go/time/zoneinfo.go2
-rw-r--r--libgo/go/time/zoneinfo_abbrs_windows.go183
-rw-r--r--libgo/go/time/zoneinfo_android.go119
-rw-r--r--libgo/go/time/zoneinfo_android_test.go18
-rw-r--r--libgo/go/time/zoneinfo_unix.go2
-rw-r--r--libgo/go/time/zoneinfo_windows.go2
-rw-r--r--libgo/go/unicode/letter.go7
-rw-r--r--libgo/go/unicode/letter_test.go4
-rw-r--r--libgo/go/unicode/utf8/utf8.go15
-rw-r--r--libgo/go/unicode/utf8/utf8_test.go91
-rwxr-xr-xlibgo/match.sh8
-rwxr-xr-xlibgo/merge.sh60
-rw-r--r--libgo/runtime/go-construct-map.c11
-rw-r--r--libgo/runtime/go-fieldtrack.c12
-rw-r--r--libgo/runtime/go-memclr.c6
-rw-r--r--libgo/runtime/malloc.goc2
-rw-r--r--libgo/runtime/mcache.c2
-rw-r--r--libgo/runtime/mgc0.c35
-rw-r--r--libgo/runtime/parfor.c2
-rw-r--r--libgo/runtime/proc.c60
-rw-r--r--libgo/runtime/runtime.h8
-rw-r--r--libgo/runtime/runtime_c.c6
-rwxr-xr-xlibgo/testsuite/gotest18
973 files changed, 69003 insertions, 17420 deletions
diff --git a/libgo/MERGE b/libgo/MERGE
index 160cfe323cb..a126b52ed78 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-f75aafdf56dd90eab75cfeac8cf69358f73ba171
+3de6e96e4b8147f5267a2e8218a7c780b09a434f
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 fed41117716..0d9b7a7f6ad 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -346,7 +346,8 @@ toolexeclibgoruntimedir = $(toolexeclibgodir)/runtime
toolexeclibgoruntime_DATA = \
runtime/debug.gox \
- runtime/pprof.gox
+ runtime/pprof.gox \
+ runtime/trace.gox
toolexeclibgosyncdir = $(toolexeclibgodir)/sync
@@ -669,6 +670,7 @@ PACKAGES = \
archive/zip \
bufio \
bytes \
+ cmd/internal/browser \
compress/bzip2 \
compress/flate \
compress/gzip \
@@ -686,6 +688,7 @@ PACKAGES = \
crypto/ecdsa \
crypto/elliptic \
crypto/hmac \
+ crypto/internal/cipherhw \
crypto/md5 \
crypto/rand \
crypto/rc4 \
@@ -736,8 +739,16 @@ PACKAGES = \
go/scanner \
go/token \
go/types \
+ golang_org/x/crypto/chacha20poly1305 \
+ golang_org/x/crypto/chacha20poly1305/internal/chacha20 \
+ golang_org/x/crypto/curve25519 \
+ golang_org/x/crypto/poly1305 \
golang_org/x/net/http2/hpack \
+ golang_org/x/net/idna \
golang_org/x/net/lex/httplex \
+ golang_org/x/text/transform \
+ golang_org/x/text/unicode/norm \
+ golang_org/x/text/width \
hash \
hash/adler32 \
hash/crc32 \
@@ -755,6 +766,7 @@ PACKAGES = \
image/png \
index/suffixarray \
internal/nettrace \
+ internal/pprof/profile \
internal/race \
internal/singleflight \
internal/syscall/unix \
@@ -802,6 +814,8 @@ PACKAGES = \
runtime/internal/atomic \
runtime/internal/sys \
runtime/pprof \
+ runtime/pprof/internal/protopprof \
+ runtime/trace \
sort \
strconv \
strings \
@@ -809,6 +823,7 @@ PACKAGES = \
sync/atomic \
syscall \
testing \
+ testing/internal/testdeps \
testing/iotest \
testing/quick \
text/scanner \
@@ -829,6 +844,7 @@ libgo_go_objs = \
syscall/errno.lo \
syscall/signame.lo \
syscall/wait.lo \
+ $(golang_org_x_net_lif_lo) \
$(golang_org_x_net_route_lo) \
log/syslog/syslog_c.lo \
$(os_lib_inotify_lo) \
@@ -1113,7 +1129,7 @@ if LIBGO_IS_BSD
# Build golang_org/x/net/route only on BSD systems.
-$(eval $(call PACKAGE_template,golang_org/x/net/route)
+$(eval $(call PACKAGE_template,golang_org/x/net/route))
golang_org_x_net_route_lo = \
golang_org/x/net/route/route.lo
@@ -1122,6 +1138,19 @@ golang_org_x_net_route_check = \
endif
+if LIBGO_IS_SOLARIS
+
+# Build golang_org/x/net/lif only on Solaris systems.
+
+$(eval $(call PACKAGE_template,golang_org/x/net/lif))
+
+golang_org_x_net_lif_lo = \
+ golang_org/x/net/lif/lif.lo
+golang_org_x_net_lif_check = \
+ golang_org/x/net/lif/check
+
+endif
+
TEST_PACKAGES = \
bufio/check \
bytes/check \
@@ -1209,8 +1238,14 @@ TEST_PACKAGES = \
go/scanner/check \
go/token/check \
go/types/check \
+ golang_org/x/crypto/chacha20poly1305/check \
+ golang_org/x/crypto/chacha20poly1305/internal/chacha20/check \
+ golang_org/x/crypto/curve25519/check \
+ golang_org/x/crypto/poly1305/check \
golang_org/x/net/http2/hpack/check \
+ golang_org/x/net/idna/check \
golang_org/x/net/lex/httplex/check \
+ $(golang_org_x_net_lif_check) \
$(golang_org_x_net_route_check) \
hash/adler32/check \
hash/crc32/check \
@@ -1221,6 +1256,7 @@ TEST_PACKAGES = \
image/jpeg/check \
image/png/check \
index/suffixarray/check \
+ internal/pprof/profile/check \
internal/singleflight/check \
internal/trace/check \
io/ioutil/check \
@@ -1251,9 +1287,10 @@ TEST_PACKAGES = \
path/filepath/check \
regexp/syntax/check \
runtime/debug/check \
- runtime/pprof/check \
runtime/internal/atomic/check \
runtime/internal/sys/check \
+ runtime/pprof/check \
+ runtime/pprof/internal/protopprof/check \
sync/atomic/check \
text/scanner/check \
text/tabwriter/check \
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 581607a96c4..4b46076b010 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -168,9 +168,9 @@ LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
am__DEPENDENCIES_2 = $(addsuffix .lo,$(PACKAGES)) bytes/index.lo \
reflect/makefunc_ffi_c.lo strings/index.lo \
$(am__DEPENDENCIES_1) syscall/errno.lo syscall/signame.lo \
- syscall/wait.lo $(golang_org_x_net_route_lo) \
- log/syslog/syslog_c.lo runtime/internal/atomic_c.lo \
- sync/atomic_c.lo
+ syscall/wait.lo $(golang_org_x_net_lif_lo) \
+ $(golang_org_x_net_route_lo) log/syslog/syslog_c.lo \
+ runtime/internal/atomic_c.lo sync/atomic_c.lo
am__DEPENDENCIES_3 =
am__DEPENDENCIES_4 = $(am__DEPENDENCIES_2) \
../libbacktrace/libbacktrace.la $(am__DEPENDENCIES_3) \
@@ -728,7 +728,8 @@ toolexeclibgoregexp_DATA = \
toolexeclibgoruntimedir = $(toolexeclibgodir)/runtime
toolexeclibgoruntime_DATA = \
runtime/debug.gox \
- runtime/pprof.gox
+ runtime/pprof.gox \
+ runtime/trace.gox
toolexeclibgosyncdir = $(toolexeclibgodir)/sync
toolexeclibgosync_DATA = \
@@ -834,6 +835,7 @@ PACKAGES = \
archive/zip \
bufio \
bytes \
+ cmd/internal/browser \
compress/bzip2 \
compress/flate \
compress/gzip \
@@ -851,6 +853,7 @@ PACKAGES = \
crypto/ecdsa \
crypto/elliptic \
crypto/hmac \
+ crypto/internal/cipherhw \
crypto/md5 \
crypto/rand \
crypto/rc4 \
@@ -901,8 +904,16 @@ PACKAGES = \
go/scanner \
go/token \
go/types \
+ golang_org/x/crypto/chacha20poly1305 \
+ golang_org/x/crypto/chacha20poly1305/internal/chacha20 \
+ golang_org/x/crypto/curve25519 \
+ golang_org/x/crypto/poly1305 \
golang_org/x/net/http2/hpack \
+ golang_org/x/net/idna \
golang_org/x/net/lex/httplex \
+ golang_org/x/text/transform \
+ golang_org/x/text/unicode/norm \
+ golang_org/x/text/width \
hash \
hash/adler32 \
hash/crc32 \
@@ -920,6 +931,7 @@ PACKAGES = \
image/png \
index/suffixarray \
internal/nettrace \
+ internal/pprof/profile \
internal/race \
internal/singleflight \
internal/syscall/unix \
@@ -967,6 +979,8 @@ PACKAGES = \
runtime/internal/atomic \
runtime/internal/sys \
runtime/pprof \
+ runtime/pprof/internal/protopprof \
+ runtime/trace \
sort \
strconv \
strings \
@@ -974,6 +988,7 @@ PACKAGES = \
sync/atomic \
syscall \
testing \
+ testing/internal/testdeps \
testing/iotest \
testing/quick \
text/scanner \
@@ -994,6 +1009,7 @@ libgo_go_objs = \
syscall/errno.lo \
syscall/signame.lo \
syscall/wait.lo \
+ $(golang_org_x_net_lif_lo) \
$(golang_org_x_net_route_lo) \
log/syslog/syslog_c.lo \
$(os_lib_inotify_lo) \
@@ -1161,6 +1177,12 @@ extra_go_files_runtime_internal_sys = version.go
@LIBGO_IS_BSD_TRUE@golang_org_x_net_route_check = \
@LIBGO_IS_BSD_TRUE@ golang_org/x/net/route/check
+@LIBGO_IS_SOLARIS_TRUE@golang_org_x_net_lif_lo = \
+@LIBGO_IS_SOLARIS_TRUE@ golang_org/x/net/lif/lif.lo
+
+@LIBGO_IS_SOLARIS_TRUE@golang_org_x_net_lif_check = \
+@LIBGO_IS_SOLARIS_TRUE@ golang_org/x/net/lif/check
+
TEST_PACKAGES = \
bufio/check \
bytes/check \
@@ -1248,8 +1270,14 @@ TEST_PACKAGES = \
go/scanner/check \
go/token/check \
go/types/check \
+ golang_org/x/crypto/chacha20poly1305/check \
+ golang_org/x/crypto/chacha20poly1305/internal/chacha20/check \
+ golang_org/x/crypto/curve25519/check \
+ golang_org/x/crypto/poly1305/check \
golang_org/x/net/http2/hpack/check \
+ golang_org/x/net/idna/check \
golang_org/x/net/lex/httplex/check \
+ $(golang_org_x_net_lif_check) \
$(golang_org_x_net_route_check) \
hash/adler32/check \
hash/crc32/check \
@@ -1260,6 +1288,7 @@ TEST_PACKAGES = \
image/jpeg/check \
image/png/check \
index/suffixarray/check \
+ internal/pprof/profile/check \
internal/singleflight/check \
internal/trace/check \
io/ioutil/check \
@@ -1290,9 +1319,10 @@ TEST_PACKAGES = \
path/filepath/check \
regexp/syntax/check \
runtime/debug/check \
- runtime/pprof/check \
runtime/internal/atomic/check \
runtime/internal/sys/check \
+ runtime/pprof/check \
+ runtime/pprof/internal/protopprof/check \
sync/atomic/check \
text/scanner/check \
text/tabwriter/check \
@@ -3316,7 +3346,11 @@ syscall/wait.lo: go/syscall/wait.c runtime.inc
# Build golang_org/x/net/route only on BSD systems.
-@LIBGO_IS_BSD_TRUE@$(eval $(call PACKAGE_template,golang_org/x/net/route)
+@LIBGO_IS_BSD_TRUE@$(eval $(call PACKAGE_template,golang_org/x/net/route))
+
+# Build golang_org/x/net/lif only on Solaris systems.
+
+@LIBGO_IS_SOLARIS_TRUE@$(eval $(call PACKAGE_template,golang_org/x/net/lif))
check: check-tail
check-recursive: check-head
diff --git a/libgo/VERSION b/libgo/VERSION
index ee106b3bb2d..3076f40768f 100644
--- a/libgo/VERSION
+++ b/libgo/VERSION
@@ -1 +1 @@
-go1.7.1
+go1.8rc1
diff --git a/libgo/go/archive/tar/common.go b/libgo/go/archive/tar/common.go
index 2a1e4321826..d2ae66d554d 100644
--- a/libgo/go/archive/tar/common.go
+++ b/libgo/go/archive/tar/common.go
@@ -13,7 +13,6 @@
package tar
import (
- "bytes"
"errors"
"fmt"
"os"
@@ -21,6 +20,10 @@ import (
"time"
)
+// BUG: Use of the Uid and Gid fields in Header could overflow on 32-bit
+// architectures. If a large value is encountered when decoding, the result
+// stored in Header will be the truncated version.
+
// Header type flags.
const (
TypeReg = '0' // regular file
@@ -271,28 +274,6 @@ func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
return h, nil
}
-func isASCII(s string) bool {
- for _, c := range s {
- if c >= 0x80 {
- return false
- }
- }
- return true
-}
-
-func toASCII(s string) string {
- if isASCII(s) {
- return s
- }
- var buf bytes.Buffer
- for _, c := range s {
- if c < 0x80 {
- buf.WriteByte(byte(c))
- }
- }
- return buf.String()
-}
-
// isHeaderOnlyType checks if the given type flag is of the type that has no
// data section even if a size is specified.
func isHeaderOnlyType(flag byte) bool {
diff --git a/libgo/go/archive/tar/reader.go b/libgo/go/archive/tar/reader.go
index 096ef082bf8..9abe888218f 100644
--- a/libgo/go/archive/tar/reader.go
+++ b/libgo/go/archive/tar/reader.go
@@ -22,22 +22,20 @@ var (
ErrHeader = errors.New("archive/tar: invalid tar header")
)
-const maxNanoSecondIntSize = 9
-
// A Reader provides sequential access to the contents of a tar archive.
// A tar archive consists of a sequence of files.
// 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
pad int64 // amount of padding (ignored) after current file entry
curr numBytesReader // reader for current file entry
blk block // buffer to use as temporary local storage
-}
-type parser struct {
- err error // Last error seen
+ // err is a persistent error.
+ // It is only the responsibility of every exported method of Reader to
+ // ensure that this error is sticky.
+ err error
}
// A numBytesReader is an io.Reader with a numBytes method, returning the number
@@ -108,8 +106,12 @@ func (tr *Reader) Next() (*Header, error) {
if tr.err != nil {
return nil, tr.err
}
+ hdr, err := tr.next()
+ tr.err = err
+ return hdr, err
+}
- var hdr *Header
+func (tr *Reader) next() (*Header, error) {
var extHdrs map[string]string
// Externally, Next iterates through the tar archive as if it is a series of
@@ -119,29 +121,29 @@ func (tr *Reader) Next() (*Header, error) {
// one or more "header files" until it finds a "normal file".
loop:
for {
- tr.err = tr.skipUnread()
- if tr.err != nil {
- return nil, tr.err
+ if err := tr.skipUnread(); err != nil {
+ return nil, err
}
-
- hdr = tr.readHeader()
- if tr.err != nil {
- return nil, tr.err
+ hdr, rawHdr, err := tr.readHeader()
+ if err != nil {
+ return nil, err
+ }
+ if err := tr.handleRegularFile(hdr); err != nil {
+ return nil, err
}
// Check for PAX/GNU special headers and files.
switch hdr.Typeflag {
case TypeXHeader:
- extHdrs, tr.err = parsePAX(tr)
- if tr.err != nil {
- return nil, tr.err
+ extHdrs, err = parsePAX(tr)
+ if err != nil {
+ return nil, err
}
continue loop // This is a meta header affecting the next header
case TypeGNULongName, TypeGNULongLink:
- var realname []byte
- realname, tr.err = ioutil.ReadAll(tr)
- if tr.err != nil {
- return nil, tr.err
+ realname, err := ioutil.ReadAll(tr)
+ if err != nil {
+ return nil, err
}
// Convert GNU extensions to use PAX headers.
@@ -156,31 +158,73 @@ loop:
extHdrs[paxLinkpath] = p.parseString(realname)
}
if p.err != nil {
- tr.err = p.err
- return nil, tr.err
+ return nil, p.err
}
continue loop // This is a meta header affecting the next header
default:
- mergePAX(hdr, extHdrs)
+ // The old GNU sparse format is handled here since it is technically
+ // just a regular file with additional attributes.
- // Check for a PAX format sparse file
- sp, err := tr.checkForGNUSparsePAXHeaders(hdr, extHdrs)
- if err != nil {
- tr.err = err
+ if err := mergePAX(hdr, extHdrs); err != nil {
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, tr.err = newSparseFileReader(tr.curr, sp, hdr.Size)
- if tr.err != nil {
- return nil, tr.err
- }
+
+ // The extended headers may have updated the size.
+ // Thus, setup the regFileReader again after merging PAX headers.
+ if err := tr.handleRegularFile(hdr); err != nil {
+ return nil, err
+ }
+
+ // Sparse formats rely on being able to read from the logical data
+ // section; there must be a preceding call to handleRegularFile.
+ if err := tr.handleSparseFile(hdr, rawHdr, extHdrs); err != nil {
+ return nil, err
}
- break loop // This is a file, so stop
+ return hdr, nil // This is a file, so stop
+ }
+ }
+}
+
+// handleRegularFile sets up the current file reader and padding such that it
+// can only read the following logical data section. It will properly handle
+// special headers that contain no data section.
+func (tr *Reader) handleRegularFile(hdr *Header) error {
+ nb := hdr.Size
+ if isHeaderOnlyType(hdr.Typeflag) {
+ nb = 0
+ }
+ if nb < 0 {
+ return ErrHeader
+ }
+
+ tr.pad = -nb & (blockSize - 1) // blockSize is a power of two
+ tr.curr = &regFileReader{r: tr.r, nb: nb}
+ return nil
+}
+
+// handleSparseFile checks if the current file is a sparse format of any type
+// and sets the curr reader appropriately.
+func (tr *Reader) handleSparseFile(hdr *Header, rawHdr *block, extHdrs map[string]string) error {
+ var sp []sparseEntry
+ var err error
+ if hdr.Typeflag == TypeGNUSparse {
+ sp, err = tr.readOldGNUSparseMap(hdr, rawHdr)
+ if err != nil {
+ return err
+ }
+ } else {
+ sp, err = tr.checkForGNUSparsePAXHeaders(hdr, extHdrs)
+ if err != nil {
+ return err
}
}
- return hdr, nil
+
+ // If sp is non-nil, then this is a sparse file.
+ // Note that it is possible for len(sp) to be zero.
+ if sp != nil {
+ tr.curr, err = newSparseFileReader(tr.curr, sp, hdr.Size)
+ }
+ return err
}
// checkForGNUSparsePAXHeaders checks the PAX headers for GNU sparse headers. If they are found, then
@@ -219,13 +263,13 @@ func (tr *Reader) checkForGNUSparsePAXHeaders(hdr *Header, headers map[string]st
hdr.Name = sparseName
}
if sparseSizeOk {
- realSize, err := strconv.ParseInt(sparseSize, 10, 0)
+ realSize, err := strconv.ParseInt(sparseSize, 10, 64)
if err != nil {
return nil, ErrHeader
}
hdr.Size = realSize
} else if sparseRealSizeOk {
- realSize, err := strconv.ParseInt(sparseRealSize, 10, 0)
+ realSize, err := strconv.ParseInt(sparseRealSize, 10, 64)
if err != nil {
return nil, ErrHeader
}
@@ -249,53 +293,32 @@ func (tr *Reader) checkForGNUSparsePAXHeaders(hdr *Header, headers map[string]st
// in the header struct overwrite those found in the header
// struct with higher precision or longer values. Esp. useful
// for name and linkname fields.
-func mergePAX(hdr *Header, headers map[string]string) error {
+func mergePAX(hdr *Header, headers map[string]string) (err error) {
+ var id64 int64
for k, v := range headers {
switch k {
case paxPath:
hdr.Name = v
case paxLinkpath:
hdr.Linkname = v
- case paxGname:
- hdr.Gname = v
case paxUname:
hdr.Uname = v
+ case paxGname:
+ hdr.Gname = v
case paxUid:
- uid, err := strconv.ParseInt(v, 10, 0)
- if err != nil {
- return err
- }
- hdr.Uid = int(uid)
+ id64, err = strconv.ParseInt(v, 10, 64)
+ hdr.Uid = int(id64) // Integer overflow possible
case paxGid:
- gid, err := strconv.ParseInt(v, 10, 0)
- if err != nil {
- return err
- }
- hdr.Gid = int(gid)
+ id64, err = strconv.ParseInt(v, 10, 64)
+ hdr.Gid = int(id64) // Integer overflow possible
case paxAtime:
- t, err := parsePAXTime(v)
- if err != nil {
- return err
- }
- hdr.AccessTime = t
+ hdr.AccessTime, err = parsePAXTime(v)
case paxMtime:
- t, err := parsePAXTime(v)
- if err != nil {
- return err
- }
- hdr.ModTime = t
+ hdr.ModTime, err = parsePAXTime(v)
case paxCtime:
- t, err := parsePAXTime(v)
- if err != nil {
- return err
- }
- hdr.ChangeTime = t
+ hdr.ChangeTime, err = parsePAXTime(v)
case paxSize:
- size, err := strconv.ParseInt(v, 10, 0)
- if err != nil {
- return err
- }
- hdr.Size = size
+ hdr.Size, err = strconv.ParseInt(v, 10, 64)
default:
if strings.HasPrefix(k, paxXattr) {
if hdr.Xattrs == nil {
@@ -304,44 +327,11 @@ func mergePAX(hdr *Header, headers map[string]string) error {
hdr.Xattrs[k[len(paxXattr):]] = v
}
}
- }
- return nil
-}
-
-// parsePAXTime takes a string of the form %d.%d as described in
-// the PAX specification.
-func parsePAXTime(t string) (time.Time, error) {
- buf := []byte(t)
- pos := bytes.IndexByte(buf, '.')
- var seconds, nanoseconds int64
- var err error
- if pos == -1 {
- seconds, err = strconv.ParseInt(t, 10, 0)
- if err != nil {
- return time.Time{}, err
- }
- } else {
- seconds, err = strconv.ParseInt(string(buf[:pos]), 10, 0)
- if err != nil {
- return time.Time{}, err
- }
- nanoBuf := string(buf[pos+1:])
- // Pad as needed before converting to a decimal.
- // For example .030 -> .030000000 -> 30000000 nanoseconds
- if len(nanoBuf) < maxNanoSecondIntSize {
- // Right pad
- nanoBuf += strings.Repeat("0", maxNanoSecondIntSize-len(nanoBuf))
- } else if len(nanoBuf) > maxNanoSecondIntSize {
- // Right truncate
- nanoBuf = nanoBuf[:maxNanoSecondIntSize]
- }
- nanoseconds, err = strconv.ParseInt(nanoBuf, 10, 0)
if err != nil {
- return time.Time{}, err
+ return ErrHeader
}
}
- ts := time.Unix(seconds, nanoseconds)
- return ts, nil
+ return nil
}
// parsePAX parses PAX headers.
@@ -354,12 +344,11 @@ func parsePAX(r io.Reader) (map[string]string, error) {
sbuf := string(buf)
// 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
+ // This function transforms the sparse format 0.0 headers into format 0.1
+ // headers since 0.0 headers were not PAX compliant.
+ var sparseMap []string
- headers := make(map[string]string)
- // Each record is constructed as
- // "%d %s=%s\n", length, keyword, value
+ extHdrs := make(map[string]string)
for len(sbuf) > 0 {
key, value, residual, err := parsePAXRecord(sbuf)
if err != nil {
@@ -367,127 +356,29 @@ func parsePAX(r io.Reader) (map[string]string, error) {
}
sbuf = residual
- keyStr := key
- if keyStr == paxGNUSparseOffset || keyStr == paxGNUSparseNumBytes {
- // GNU sparse format 0.0 special key. Write to sparseMap instead of using the headers map.
- sparseMap.WriteString(value)
- sparseMap.Write([]byte{','})
- } else {
- // Normal key. Set the value in the headers map.
- headers[keyStr] = 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
-}
-
-// parsePAXRecord parses the input PAX record string into a key-value pair.
-// If parsing is successful, it will slice off the currently read record and
-// return the remainder as r.
-//
-// A PAX record is of the following form:
-// "%d %s=%s\n" % (size, key, value)
-func parsePAXRecord(s string) (k, v, r string, err error) {
- // The size field ends at the first space.
- sp := strings.IndexByte(s, ' ')
- if sp == -1 {
- return "", "", s, ErrHeader
- }
-
- // Parse the first token as a decimal integer.
- n, perr := strconv.ParseInt(s[:sp], 10, 0) // Intentionally parse as native int
- if perr != nil || n < 5 || int64(len(s)) < n {
- return "", "", s, ErrHeader
- }
-
- // Extract everything between the space and the final newline.
- rec, nl, rem := s[sp+1:n-1], s[n-1:n], s[n:]
- if nl != "\n" {
- return "", "", s, ErrHeader
- }
-
- // The first equals separates the key from the value.
- eq := strings.IndexByte(rec, '=')
- if eq == -1 {
- return "", "", s, ErrHeader
- }
- return rec[:eq], rec[eq+1:], rem, nil
-}
-
-// parseString parses bytes as a NUL-terminated C-style string.
-// If a NUL byte is not found then the whole slice is returned as a string.
-func (*parser) parseString(b []byte) string {
- n := 0
- for n < len(b) && b[n] != 0 {
- n++
- }
- return string(b[0:n])
-}
-
-// parseNumeric parses the input as being encoded in either base-256 or octal.
-// This function may return negative numbers.
-// If parsing fails or an integer overflow occurs, err will be set.
-func (p *parser) parseNumeric(b []byte) int64 {
- // Check for base-256 (binary) format first.
- // If the first bit is set, then all following bits constitute a two's
- // complement encoded number in big-endian byte order.
- if len(b) > 0 && b[0]&0x80 != 0 {
- // Handling negative numbers relies on the following identity:
- // -a-1 == ^a
- //
- // If the number is negative, we use an inversion mask to invert the
- // data bytes and treat the value as an unsigned number.
- var inv byte // 0x00 if positive or zero, 0xff if negative
- if b[0]&0x40 != 0 {
- inv = 0xff
- }
-
- var x uint64
- for i, c := range b {
- c ^= inv // Inverts c only if inv is 0xff, otherwise does nothing
- if i == 0 {
- c &= 0x7f // Ignore signal bit in first byte
+ switch key {
+ case paxGNUSparseOffset, paxGNUSparseNumBytes:
+ // Validate sparse header order and value.
+ if (len(sparseMap)%2 == 0 && key != paxGNUSparseOffset) ||
+ (len(sparseMap)%2 == 1 && key != paxGNUSparseNumBytes) ||
+ strings.Contains(value, ",") {
+ return nil, ErrHeader
}
- if (x >> 56) > 0 {
- p.err = ErrHeader // Integer overflow
- return 0
+ sparseMap = append(sparseMap, value)
+ default:
+ // According to PAX specification, a value is stored only if it is
+ // non-empty. Otherwise, the key is deleted.
+ if len(value) > 0 {
+ extHdrs[key] = value
+ } else {
+ delete(extHdrs, key)
}
- x = x<<8 | uint64(c)
- }
- if (x >> 63) > 0 {
- p.err = ErrHeader // Integer overflow
- return 0
}
- if inv == 0xff {
- return ^int64(x)
- }
- return int64(x)
- }
-
- // Normal case is base-8 (octal) format.
- return p.parseOctal(b)
-}
-
-func (p *parser) parseOctal(b []byte) int64 {
- // Because unused fields are filled with NULs, we need
- // to skip leading NULs. Fields may also be padded with
- // spaces or NULs.
- // So we remove leading and trailing NULs and spaces to
- // be sure.
- b = bytes.Trim(b, " \x00")
-
- if len(b) == 0 {
- return 0
}
- x, perr := strconv.ParseUint(p.parseString(b), 8, 64)
- if perr != nil {
- p.err = ErrHeader
+ if len(sparseMap) > 0 {
+ extHdrs[paxGNUSparseMap] = strings.Join(sparseMap, ",")
}
- return int64(x)
+ return extHdrs, nil
}
// skipUnread skips any unread bytes in the existing file entry, as well as any
@@ -516,51 +407,46 @@ func (tr *Reader) skipUnread() error {
// Seek seems supported, so perform the real Seek.
pos2, err := sr.Seek(dataSkip-1, io.SeekCurrent)
if err != nil {
- tr.err = err
- return tr.err
+ return err
}
seekSkipped = pos2 - pos1
}
}
- var copySkipped int64 // Number of bytes skipped via CopyN
- copySkipped, tr.err = io.CopyN(ioutil.Discard, tr.r, totalSkip-seekSkipped)
- if tr.err == io.EOF && seekSkipped+copySkipped < dataSkip {
- tr.err = io.ErrUnexpectedEOF
+ copySkipped, err := io.CopyN(ioutil.Discard, tr.r, totalSkip-seekSkipped)
+ if err == io.EOF && seekSkipped+copySkipped < dataSkip {
+ err = io.ErrUnexpectedEOF
}
- return tr.err
+ return err
}
// readHeader reads the next block header and assumes that the underlying reader
-// is already aligned to a block boundary.
+// is already aligned to a block boundary. It returns the raw block of the
+// header in case further processing is required.
//
// The err will be set to io.EOF only when one of the following occurs:
// * Exactly 0 bytes are read and EOF is hit.
// * Exactly 1 block of zeros is read and EOF is hit.
// * At least 2 blocks of zeros are read.
-func (tr *Reader) readHeader() *Header {
- if _, tr.err = io.ReadFull(tr.r, tr.blk[:]); tr.err != nil {
- return nil // io.EOF is okay here
- }
-
+func (tr *Reader) readHeader() (*Header, *block, error) {
// Two blocks of zero bytes marks the end of the archive.
+ if _, err := io.ReadFull(tr.r, tr.blk[:]); err != nil {
+ return nil, nil, err // EOF is okay here; exactly 0 bytes read
+ }
if bytes.Equal(tr.blk[:], zeroBlock[:]) {
- if _, tr.err = io.ReadFull(tr.r, tr.blk[:]); tr.err != nil {
- return nil // io.EOF is okay here
+ if _, err := io.ReadFull(tr.r, tr.blk[:]); err != nil {
+ return nil, nil, err // EOF is okay here; exactly 1 block of zeros read
}
if bytes.Equal(tr.blk[:], zeroBlock[:]) {
- tr.err = io.EOF
- } else {
- tr.err = ErrHeader // zero block and then non-zero block
+ return nil, nil, io.EOF // normal EOF; exactly 2 block of zeros read
}
- return nil
+ return nil, nil, ErrHeader // Zero block and then non-zero block
}
// Verify the header matches a known format.
format := tr.blk.GetFormat()
if format == formatUnknown {
- tr.err = ErrHeader
- return nil
+ return nil, nil, ErrHeader
}
var p parser
@@ -577,6 +463,26 @@ func (tr *Reader) readHeader() *Header {
hdr.Typeflag = v7.TypeFlag()[0]
hdr.Linkname = p.parseString(v7.LinkName())
+ // The atime and ctime fields are often left unused. Some versions of Go
+ // had a bug in the tar.Writer where it would output an invalid tar file
+ // in certain rare situations because the logic incorrectly believed that
+ // the old GNU format had a prefix field. This is wrong and leads to
+ // an outputted file that actually mangles the atime and ctime fields.
+ //
+ // In order to continue reading tar files created by a buggy writer, we
+ // try to parse the atime and ctime fields, but just return the zero value
+ // of time.Time when we cannot parse them.
+ //
+ // See https://golang.org/issues/12594
+ tryParseTime := func(b []byte) time.Time {
+ var p parser
+ n := p.parseNumeric(b)
+ if b[0] != 0x00 && p.err == nil {
+ return time.Unix(n, 0)
+ }
+ return time.Time{}
+ }
+
// Unpack format specific fields.
if format > formatV7 {
ustar := tr.blk.USTAR()
@@ -589,9 +495,7 @@ func (tr *Reader) readHeader() *Header {
var prefix string
switch format {
- case formatUSTAR, formatGNU:
- // TODO(dsnet): Do not use the prefix field for the GNU format!
- // See golang.org/issues/12594
+ case formatUSTAR:
ustar := tr.blk.USTAR()
prefix = p.parseString(ustar.Prefix())
case formatSTAR:
@@ -599,97 +503,68 @@ func (tr *Reader) readHeader() *Header {
prefix = p.parseString(star.Prefix())
hdr.AccessTime = time.Unix(p.parseNumeric(star.AccessTime()), 0)
hdr.ChangeTime = time.Unix(p.parseNumeric(star.ChangeTime()), 0)
+ case formatGNU:
+ gnu := tr.blk.GNU()
+ hdr.AccessTime = tryParseTime(gnu.AccessTime())
+ hdr.ChangeTime = tryParseTime(gnu.ChangeTime())
}
if len(prefix) > 0 {
hdr.Name = prefix + "/" + hdr.Name
}
}
+ return hdr, &tr.blk, p.err
+}
- nb := hdr.Size
- if isHeaderOnlyType(hdr.Typeflag) {
- nb = 0
- }
- if nb < 0 {
- tr.err = ErrHeader
- return nil
- }
-
- // Set the current file reader.
- tr.pad = -nb & (blockSize - 1) // blockSize is a power of two
- tr.curr = &regFileReader{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 = p.parseNumeric(tr.blk.GNU().RealSize())
- if p.err != nil {
- tr.err = p.err
- return nil
- }
-
- // Read the sparse map.
- sp := tr.readOldGNUSparseMap(&tr.blk)
- if tr.err != nil {
- return nil
- }
-
- // Current file is a GNU sparse file. Update the current file reader.
- tr.curr, tr.err = newSparseFileReader(tr.curr, sp, hdr.Size)
- if tr.err != nil {
- return nil
- }
+// readOldGNUSparseMap reads the sparse map from 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.
+//
+// The Header.Size does not reflect the size of any extended headers used.
+// Thus, this function will read from the raw io.Reader to fetch extra headers.
+// This method mutates blk in the process.
+func (tr *Reader) readOldGNUSparseMap(hdr *Header, blk *block) ([]sparseEntry, error) {
+ // Make sure that the input format is GNU.
+ // Unfortunately, the STAR format also has a sparse header format that uses
+ // the same type flag but has a completely different layout.
+ if blk.GetFormat() != formatGNU {
+ return nil, ErrHeader
}
+ var p parser
+ hdr.Size = p.parseNumeric(blk.GNU().RealSize())
if p.err != nil {
- tr.err = p.err
- return nil
+ return nil, p.err
}
-
- return hdr
-}
-
-// 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(blk *block) []sparseEntry {
- var p parser
var s sparseArray = blk.GNU().Sparse()
var sp = make([]sparseEntry, 0, s.MaxEntries())
- for i := 0; i < s.MaxEntries(); i++ {
- offset := p.parseOctal(s.Entry(i).Offset())
- numBytes := p.parseOctal(s.Entry(i).NumBytes())
- if p.err != nil {
- tr.err = p.err
- return nil
- }
- if offset == 0 && numBytes == 0 {
- break
- }
- sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
- }
-
- for s.IsExtended()[0] > 0 {
- // There are more entries. Read an extension header and parse its entries.
- var blk block
- if _, tr.err = io.ReadFull(tr.r, blk[:]); tr.err != nil {
- return nil
- }
- s = blk.Sparse()
-
+ for {
for i := 0; i < s.MaxEntries(); i++ {
- offset := p.parseOctal(s.Entry(i).Offset())
- numBytes := p.parseOctal(s.Entry(i).NumBytes())
- if p.err != nil {
- tr.err = p.err
- return nil
+ // This termination condition is identical to GNU and BSD tar.
+ if s.Entry(i).Offset()[0] == 0x00 {
+ break // Don't return, need to process extended headers (even if empty)
}
- if offset == 0 && numBytes == 0 {
- break
+ offset := p.parseNumeric(s.Entry(i).Offset())
+ numBytes := p.parseNumeric(s.Entry(i).NumBytes())
+ if p.err != nil {
+ return nil, p.err
}
sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
}
+
+ if s.IsExtended()[0] > 0 {
+ // There are more entries. Read an extension header and parse its entries.
+ if _, err := io.ReadFull(tr.r, blk[:]); err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return nil, err
+ }
+ s = blk.Sparse()
+ continue
+ }
+ return sp, nil // Done
}
- return sp
}
// readGNUSparseMap1x0 reads the sparse map as stored in GNU's PAX sparse format
@@ -817,7 +692,7 @@ func (tr *Reader) numBytes() int64 {
// Calling Read on special types like TypeLink, TypeSymLink, TypeChar,
// TypeBlock, TypeDir, and TypeFifo returns 0, io.EOF regardless of what
// the Header.Size claims.
-func (tr *Reader) Read(b []byte) (n int, err error) {
+func (tr *Reader) Read(b []byte) (int, error) {
if tr.err != nil {
return 0, tr.err
}
@@ -825,11 +700,11 @@ func (tr *Reader) Read(b []byte) (n int, err error) {
return 0, io.EOF
}
- n, err = tr.curr.Read(b)
+ n, err := tr.curr.Read(b)
if err != nil && err != io.EOF {
tr.err = err
}
- return
+ return n, err
}
func (rfr *regFileReader) Read(b []byte) (n int, err error) {
diff --git a/libgo/go/archive/tar/reader_test.go b/libgo/go/archive/tar/reader_test.go
index 7b148b5122b..338686836b6 100644
--- a/libgo/go/archive/tar/reader_test.go
+++ b/libgo/go/archive/tar/reader_test.go
@@ -18,17 +18,15 @@ import (
"time"
)
-type untarTest struct {
- file string // Test input file
- headers []*Header // Expected output headers
- chksums []string // MD5 checksum of files, leave as nil if not checked
- err error // Expected error to occur
-}
-
-var gnuTarTest = &untarTest{
- file: "testdata/gnu.tar",
- headers: []*Header{
- {
+func TestReader(t *testing.T) {
+ vectors := []struct {
+ file string // Test input file
+ headers []*Header // Expected output headers
+ chksums []string // MD5 checksum of files, leave as nil if not checked
+ err error // Expected error to occur
+ }{{
+ file: "testdata/gnu.tar",
+ headers: []*Header{{
Name: "small.txt",
Mode: 0640,
Uid: 73025,
@@ -38,8 +36,7 @@ var gnuTarTest = &untarTest{
Typeflag: '0',
Uname: "dsymonds",
Gname: "eng",
- },
- {
+ }, {
Name: "small2.txt",
Mode: 0640,
Uid: 73025,
@@ -49,18 +46,14 @@ var gnuTarTest = &untarTest{
Typeflag: '0',
Uname: "dsymonds",
Gname: "eng",
+ }},
+ chksums: []string{
+ "e38b27eaccb4391bdec553a7f3ae6b2f",
+ "c65bd2e50a56a2138bf1716f2fd56fe9",
},
- },
- chksums: []string{
- "e38b27eaccb4391bdec553a7f3ae6b2f",
- "c65bd2e50a56a2138bf1716f2fd56fe9",
- },
-}
-
-var sparseTarTest = &untarTest{
- file: "testdata/sparse-formats.tar",
- headers: []*Header{
- {
+ }, {
+ file: "testdata/sparse-formats.tar",
+ headers: []*Header{{
Name: "sparse-gnu",
Mode: 420,
Uid: 1000,
@@ -73,8 +66,7 @@ var sparseTarTest = &untarTest{
Gname: "david",
Devmajor: 0,
Devminor: 0,
- },
- {
+ }, {
Name: "sparse-posix-0.0",
Mode: 420,
Uid: 1000,
@@ -87,8 +79,7 @@ var sparseTarTest = &untarTest{
Gname: "david",
Devmajor: 0,
Devminor: 0,
- },
- {
+ }, {
Name: "sparse-posix-0.1",
Mode: 420,
Uid: 1000,
@@ -101,8 +92,7 @@ var sparseTarTest = &untarTest{
Gname: "david",
Devmajor: 0,
Devminor: 0,
- },
- {
+ }, {
Name: "sparse-posix-1.0",
Mode: 420,
Uid: 1000,
@@ -115,8 +105,7 @@ var sparseTarTest = &untarTest{
Gname: "david",
Devmajor: 0,
Devminor: 0,
- },
- {
+ }, {
Name: "end",
Mode: 420,
Uid: 1000,
@@ -129,209 +118,237 @@ var sparseTarTest = &untarTest{
Gname: "david",
Devmajor: 0,
Devminor: 0,
+ }},
+ chksums: []string{
+ "6f53234398c2449fe67c1812d993012f",
+ "6f53234398c2449fe67c1812d993012f",
+ "6f53234398c2449fe67c1812d993012f",
+ "6f53234398c2449fe67c1812d993012f",
+ "b0061974914468de549a2af8ced10316",
},
- },
- chksums: []string{
- "6f53234398c2449fe67c1812d993012f",
- "6f53234398c2449fe67c1812d993012f",
- "6f53234398c2449fe67c1812d993012f",
- "6f53234398c2449fe67c1812d993012f",
- "b0061974914468de549a2af8ced10316",
- },
-}
-
-var untarTests = []*untarTest{
- gnuTarTest,
- sparseTarTest,
- {
+ }, {
file: "testdata/star.tar",
- headers: []*Header{
- {
- Name: "small.txt",
- Mode: 0640,
- Uid: 73025,
- Gid: 5000,
- Size: 5,
- ModTime: time.Unix(1244592783, 0),
- Typeflag: '0',
- Uname: "dsymonds",
- Gname: "eng",
- AccessTime: time.Unix(1244592783, 0),
- ChangeTime: time.Unix(1244592783, 0),
- },
- {
- Name: "small2.txt",
- Mode: 0640,
- Uid: 73025,
- Gid: 5000,
- Size: 11,
- ModTime: time.Unix(1244592783, 0),
- Typeflag: '0',
- Uname: "dsymonds",
- Gname: "eng",
- AccessTime: time.Unix(1244592783, 0),
- ChangeTime: time.Unix(1244592783, 0),
- },
- },
- },
- {
+ headers: []*Header{{
+ Name: "small.txt",
+ Mode: 0640,
+ Uid: 73025,
+ Gid: 5000,
+ Size: 5,
+ ModTime: time.Unix(1244592783, 0),
+ Typeflag: '0',
+ Uname: "dsymonds",
+ Gname: "eng",
+ AccessTime: time.Unix(1244592783, 0),
+ ChangeTime: time.Unix(1244592783, 0),
+ }, {
+ Name: "small2.txt",
+ Mode: 0640,
+ Uid: 73025,
+ Gid: 5000,
+ Size: 11,
+ ModTime: time.Unix(1244592783, 0),
+ Typeflag: '0',
+ Uname: "dsymonds",
+ Gname: "eng",
+ AccessTime: time.Unix(1244592783, 0),
+ ChangeTime: time.Unix(1244592783, 0),
+ }},
+ }, {
file: "testdata/v7.tar",
- headers: []*Header{
- {
- Name: "small.txt",
- Mode: 0444,
- Uid: 73025,
- Gid: 5000,
- Size: 5,
- ModTime: time.Unix(1244593104, 0),
- Typeflag: '\x00',
- },
- {
- Name: "small2.txt",
- Mode: 0444,
- Uid: 73025,
- Gid: 5000,
- Size: 11,
- ModTime: time.Unix(1244593104, 0),
- Typeflag: '\x00',
- },
- },
- },
- {
+ headers: []*Header{{
+ Name: "small.txt",
+ Mode: 0444,
+ Uid: 73025,
+ Gid: 5000,
+ Size: 5,
+ ModTime: time.Unix(1244593104, 0),
+ Typeflag: '\x00',
+ }, {
+ Name: "small2.txt",
+ Mode: 0444,
+ Uid: 73025,
+ Gid: 5000,
+ Size: 11,
+ ModTime: time.Unix(1244593104, 0),
+ Typeflag: '\x00',
+ }},
+ }, {
file: "testdata/pax.tar",
- headers: []*Header{
- {
- Name: "a/123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
- Mode: 0664,
- Uid: 1000,
- Gid: 1000,
- Uname: "shane",
- Gname: "shane",
- Size: 7,
- ModTime: time.Unix(1350244992, 23960108),
- ChangeTime: time.Unix(1350244992, 23960108),
- AccessTime: time.Unix(1350244992, 23960108),
- Typeflag: TypeReg,
- },
- {
- Name: "a/b",
- Mode: 0777,
- Uid: 1000,
- Gid: 1000,
- Uname: "shane",
- Gname: "shane",
- Size: 0,
- ModTime: time.Unix(1350266320, 910238425),
- ChangeTime: time.Unix(1350266320, 910238425),
- AccessTime: time.Unix(1350266320, 910238425),
- Typeflag: TypeSymlink,
- Linkname: "123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
- },
+ headers: []*Header{{
+ Name: "a/123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
+ Mode: 0664,
+ Uid: 1000,
+ Gid: 1000,
+ Uname: "shane",
+ Gname: "shane",
+ Size: 7,
+ ModTime: time.Unix(1350244992, 23960108),
+ ChangeTime: time.Unix(1350244992, 23960108),
+ AccessTime: time.Unix(1350244992, 23960108),
+ Typeflag: TypeReg,
+ }, {
+ Name: "a/b",
+ Mode: 0777,
+ Uid: 1000,
+ Gid: 1000,
+ Uname: "shane",
+ Gname: "shane",
+ Size: 0,
+ ModTime: time.Unix(1350266320, 910238425),
+ ChangeTime: time.Unix(1350266320, 910238425),
+ AccessTime: time.Unix(1350266320, 910238425),
+ Typeflag: TypeSymlink,
+ Linkname: "123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100",
+ }},
+ }, {
+ file: "testdata/pax-bad-hdr-file.tar",
+ err: ErrHeader,
+ }, {
+ file: "testdata/pax-bad-mtime-file.tar",
+ err: ErrHeader,
+ }, {
+ file: "testdata/pax-pos-size-file.tar",
+ headers: []*Header{{
+ Name: "foo",
+ Mode: 0640,
+ Uid: 319973,
+ Gid: 5000,
+ Size: 999,
+ ModTime: time.Unix(1442282516, 0),
+ Typeflag: '0',
+ Uname: "joetsai",
+ Gname: "eng",
+ }},
+ chksums: []string{
+ "0afb597b283fe61b5d4879669a350556",
},
- },
- {
+ }, {
file: "testdata/nil-uid.tar", // golang.org/issue/5290
- headers: []*Header{
- {
- Name: "P1050238.JPG.log",
- Mode: 0664,
- Uid: 0,
- Gid: 0,
- Size: 14,
- ModTime: time.Unix(1365454838, 0),
- Typeflag: TypeReg,
- Linkname: "",
- Uname: "eyefi",
- Gname: "eyefi",
- Devmajor: 0,
- Devminor: 0,
- },
- },
- },
- {
+ headers: []*Header{{
+ Name: "P1050238.JPG.log",
+ Mode: 0664,
+ Uid: 0,
+ Gid: 0,
+ Size: 14,
+ ModTime: time.Unix(1365454838, 0),
+ Typeflag: TypeReg,
+ Linkname: "",
+ Uname: "eyefi",
+ Gname: "eyefi",
+ Devmajor: 0,
+ Devminor: 0,
+ }},
+ }, {
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",
- },
+ 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",
- },
+ }, {
+ 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",
},
- },
- },
- {
+ }},
+ }, {
// Matches the behavior of GNU, BSD, and STAR tar utilities.
file: "testdata/gnu-multi-hdrs.tar",
- headers: []*Header{
- {
- Name: "GNU2/GNU2/long-path-name",
- Linkname: "GNU4/GNU4/long-linkpath-name",
- ModTime: time.Unix(0, 0),
- Typeflag: '2',
- },
- },
- },
- {
+ headers: []*Header{{
+ Name: "GNU2/GNU2/long-path-name",
+ Linkname: "GNU4/GNU4/long-linkpath-name",
+ ModTime: time.Unix(0, 0),
+ Typeflag: '2',
+ }},
+ }, {
+ // GNU tar file with atime and ctime fields set.
+ // Created with the GNU tar v1.27.1.
+ // tar --incremental -S -cvf gnu-incremental.tar test2
+ file: "testdata/gnu-incremental.tar",
+ headers: []*Header{{
+ Name: "test2/",
+ Mode: 16877,
+ Uid: 1000,
+ Gid: 1000,
+ Size: 14,
+ ModTime: time.Unix(1441973427, 0),
+ Typeflag: 'D',
+ Uname: "rawr",
+ Gname: "dsnet",
+ AccessTime: time.Unix(1441974501, 0),
+ ChangeTime: time.Unix(1441973436, 0),
+ }, {
+ Name: "test2/foo",
+ Mode: 33188,
+ Uid: 1000,
+ Gid: 1000,
+ Size: 64,
+ ModTime: time.Unix(1441973363, 0),
+ Typeflag: '0',
+ Uname: "rawr",
+ Gname: "dsnet",
+ AccessTime: time.Unix(1441974501, 0),
+ ChangeTime: time.Unix(1441973436, 0),
+ }, {
+ Name: "test2/sparse",
+ Mode: 33188,
+ Uid: 1000,
+ Gid: 1000,
+ Size: 536870912,
+ ModTime: time.Unix(1441973427, 0),
+ Typeflag: 'S',
+ Uname: "rawr",
+ Gname: "dsnet",
+ AccessTime: time.Unix(1441991948, 0),
+ ChangeTime: time.Unix(1441973436, 0),
+ }},
+ }, {
// Matches the behavior of GNU and BSD tar utilities.
file: "testdata/pax-multi-hdrs.tar",
- headers: []*Header{
- {
- Name: "bar",
- Linkname: "PAX4/PAX4/long-linkpath-name",
- ModTime: time.Unix(0, 0),
- Typeflag: '2',
- },
- },
- },
- {
+ headers: []*Header{{
+ Name: "bar",
+ Linkname: "PAX4/PAX4/long-linkpath-name",
+ ModTime: time.Unix(0, 0),
+ Typeflag: '2',
+ }},
+ }, {
file: "testdata/neg-size.tar",
err: ErrHeader,
- },
- {
+ }, {
file: "testdata/issue10968.tar",
err: ErrHeader,
- },
- {
+ }, {
file: "testdata/issue11169.tar",
err: ErrHeader,
- },
- {
+ }, {
file: "testdata/issue12435.tar",
err: ErrHeader,
- },
-}
+ }}
-func TestReader(t *testing.T) {
- for i, v := range untarTests {
+ for i, v := range vectors {
f, err := os.Open(v.file)
if err != nil {
t.Errorf("file %s, test %d: unexpected error: %v", v.file, i, err)
@@ -440,83 +457,8 @@ func TestPartialRead(t *testing.T) {
}
}
-func TestParsePAXHeader(t *testing.T) {
- paxTests := [][3]string{
- {"a", "a=name", "10 a=name\n"}, // Test case involving multiple acceptable lengths
- {"a", "a=name", "9 a=name\n"}, // Test case involving multiple acceptable length
- {"mtime", "mtime=1350244992.023960108", "30 mtime=1350244992.023960108\n"}}
- for _, test := range paxTests {
- key, expected, raw := test[0], test[1], test[2]
- reader := bytes.NewReader([]byte(raw))
- headers, err := parsePAX(reader)
- if err != nil {
- t.Errorf("Couldn't parse correctly formatted headers: %v", err)
- continue
- }
- if strings.EqualFold(headers[key], expected) {
- t.Errorf("mtime header incorrectly parsed: got %s, wanted %s", headers[key], expected)
- continue
- }
- trailer := make([]byte, 100)
- n, err := reader.Read(trailer)
- if err != io.EOF || n != 0 {
- t.Error("Buffer wasn't consumed")
- }
- }
- badHeaderTests := [][]byte{
- []byte("3 somelongkey=\n"),
- []byte("50 tooshort=\n"),
- }
- for _, test := range badHeaderTests {
- if _, err := parsePAX(bytes.NewReader(test)); err != ErrHeader {
- t.Fatal("Unexpected success when parsing bad header")
- }
- }
-}
-
-func TestParsePAXTime(t *testing.T) {
- // Some valid PAX time values
- timestamps := map[string]time.Time{
- "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
- }
- for input, expected := range timestamps {
- ts, err := parsePAXTime(input)
- if err != nil {
- t.Fatal(err)
- }
- if !ts.Equal(expected) {
- t.Fatalf("Time parsing failure %s %s", ts, expected)
- }
- }
-}
-
-func TestMergePAX(t *testing.T) {
- hdr := new(Header)
- // Test a string, integer, and time based value.
- headers := map[string]string{
- "path": "a/b/c",
- "uid": "1000",
- "mtime": "1350244992.023960108",
- }
- err := mergePAX(hdr, headers)
- if err != nil {
- t.Fatal(err)
- }
- want := &Header{
- Name: "a/b/c",
- Uid: 1000,
- ModTime: time.Unix(1350244992, 23960108),
- }
- if !reflect.DeepEqual(hdr, want) {
- t.Errorf("incorrect merge: got %+v, want %+v", hdr, want)
- }
-}
-
func TestSparseFileReader(t *testing.T) {
- var vectors = []struct {
+ vectors := []struct {
realSize int64 // Real size of the output file
sparseMap []sparseEntry // Input sparse map
sparseData string // Input compact data
@@ -639,9 +581,11 @@ func TestSparseFileReader(t *testing.T) {
r := bytes.NewReader([]byte(v.sparseData))
rfr := &regFileReader{r: r, nb: int64(len(v.sparseData))}
- var sfr *sparseFileReader
- var err error
- var buf []byte
+ var (
+ sfr *sparseFileReader
+ err error
+ buf []byte
+ )
sfr, err = newSparseFileReader(rfr, v.sparseMap, v.realSize)
if err != nil {
@@ -668,6 +612,64 @@ func TestSparseFileReader(t *testing.T) {
}
}
+func TestReadOldGNUSparseMap(t *testing.T) {
+ const (
+ t00 = "00000000000\x0000000000000\x00"
+ t11 = "00000000001\x0000000000001\x00"
+ t12 = "00000000001\x0000000000002\x00"
+ t21 = "00000000002\x0000000000001\x00"
+ )
+
+ mkBlk := func(size, sp0, sp1, sp2, sp3, ext string, format int) *block {
+ var blk block
+ copy(blk.GNU().RealSize(), size)
+ copy(blk.GNU().Sparse().Entry(0), sp0)
+ copy(blk.GNU().Sparse().Entry(1), sp1)
+ copy(blk.GNU().Sparse().Entry(2), sp2)
+ copy(blk.GNU().Sparse().Entry(3), sp3)
+ copy(blk.GNU().Sparse().IsExtended(), ext)
+ if format != formatUnknown {
+ blk.SetFormat(format)
+ }
+ return &blk
+ }
+
+ vectors := []struct {
+ data string // Input data
+ rawHdr *block // Input raw header
+ want []sparseEntry // Expected sparse entries to be outputted
+ err error // Expected error to be returned
+ }{
+ {"", mkBlk("", "", "", "", "", "", formatUnknown), nil, ErrHeader},
+ {"", mkBlk("1234", "fewa", "", "", "", "", formatGNU), nil, ErrHeader},
+ {"", mkBlk("0031", "", "", "", "", "", formatGNU), nil, nil},
+ {"", mkBlk("1234", t00, t11, "", "", "", formatGNU),
+ []sparseEntry{{0, 0}, {1, 1}}, nil},
+ {"", mkBlk("1234", t11, t12, t21, t11, "", formatGNU),
+ []sparseEntry{{1, 1}, {1, 2}, {2, 1}, {1, 1}}, nil},
+ {"", mkBlk("1234", t11, t12, t21, t11, "\x80", formatGNU),
+ []sparseEntry{}, io.ErrUnexpectedEOF},
+ {t11 + t11,
+ mkBlk("1234", t11, t12, t21, t11, "\x80", formatGNU),
+ []sparseEntry{}, io.ErrUnexpectedEOF},
+ {t11 + t21 + strings.Repeat("\x00", 512),
+ mkBlk("1234", t11, t12, t21, t11, "\x80", formatGNU),
+ []sparseEntry{{1, 1}, {1, 2}, {2, 1}, {1, 1}, {1, 1}, {2, 1}}, nil},
+ }
+
+ for i, v := range vectors {
+ tr := Reader{r: strings.NewReader(v.data)}
+ hdr := new(Header)
+ got, err := tr.readOldGNUSparseMap(hdr, v.rawHdr)
+ if !reflect.DeepEqual(got, v.want) && !(len(got) == 0 && len(v.want) == 0) {
+ t.Errorf("test %d, readOldGNUSparseMap(...): got %v, want %v", i, got, v.want)
+ }
+ if err != v.err {
+ t.Errorf("test %d, unexpected error: got %v, want %v", i, err, v.err)
+ }
+ }
+}
+
func TestReadGNUSparseMap0x1(t *testing.T) {
const (
maxUint = ^uint(0)
@@ -679,7 +681,7 @@ func TestReadGNUSparseMap0x1(t *testing.T) {
big3 = fmt.Sprintf("%d", (int64(maxInt) / 3))
)
- var vectors = []struct {
+ vectors := []struct {
extHdrs map[string]string // Input data
sparseMap []sparseEntry // Expected sparse entries to be outputted
err error // Expected errors that may be raised
@@ -745,12 +747,12 @@ func TestReadGNUSparseMap0x1(t *testing.T) {
}
func TestReadGNUSparseMap1x0(t *testing.T) {
- var sp = []sparseEntry{{1, 2}, {3, 4}}
+ sp := []sparseEntry{{1, 2}, {3, 4}}
for i := 0; i < 98; i++ {
sp = append(sp, sparseEntry{54321, 12345})
}
- var vectors = []struct {
+ vectors := []struct {
input string // Input data
sparseMap []sparseEntry // Expected sparse entries to be outputted
cnt int // Expected number of bytes read
@@ -825,8 +827,7 @@ func TestReadGNUSparseMap1x0(t *testing.T) {
}
func TestUninitializedRead(t *testing.T) {
- test := gnuTarTest
- f, err := os.Open(test.file)
+ f, err := os.Open("testdata/gnu.tar")
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
@@ -868,7 +869,7 @@ func TestReadTruncation(t *testing.T) {
data2 += strings.Repeat("\x00", 10*512)
trash := strings.Repeat("garbage ", 64) // Exactly 512 bytes
- var vectors = []struct {
+ vectors := []struct {
input string // Input stream
cnt int // Expected number of headers read
err error // Expected error outcome
@@ -904,8 +905,7 @@ func TestReadTruncation(t *testing.T) {
{pax + trash[:1], 0, io.ErrUnexpectedEOF},
{pax + trash[:511], 0, io.ErrUnexpectedEOF},
{sparse[:511], 0, io.ErrUnexpectedEOF},
- // TODO(dsnet): This should pass, but currently fails.
- // {sparse[:512], 0, io.ErrUnexpectedEOF},
+ {sparse[:512], 0, io.ErrUnexpectedEOF},
{sparse[:3584], 1, io.EOF},
{sparse[:9200], 1, io.EOF}, // Terminate in padding of sparse header
{sparse[:9216], 1, io.EOF},
@@ -1002,7 +1002,7 @@ func TestReadHeaderOnly(t *testing.T) {
t.Fatalf("len(hdrs): got %d, want %d", len(hdrs), 16)
}
for i := 0; i < 8; i++ {
- var hdr1, hdr2 = hdrs[i+0], hdrs[i+8]
+ hdr1, hdr2 := hdrs[i+0], hdrs[i+8]
hdr1.Size, hdr2.Size = 0, 0
if !reflect.DeepEqual(*hdr1, *hdr2) {
t.Errorf("incorrect header:\ngot %+v\nwant %+v", *hdr1, *hdr2)
@@ -1010,116 +1010,87 @@ func TestReadHeaderOnly(t *testing.T) {
}
}
-func TestParsePAXRecord(t *testing.T) {
- var medName = strings.Repeat("CD", 50)
- var longName = strings.Repeat("AB", 100)
-
- var vectors = []struct {
- input string
- residual string
- outputKey string
- outputVal string
- ok bool
- }{
- {"6 k=v\n\n", "\n", "k", "v", true},
- {"19 path=/etc/hosts\n", "", "path", "/etc/hosts", true},
- {"210 path=" + longName + "\nabc", "abc", "path", longName, true},
- {"110 path=" + medName + "\n", "", "path", medName, true},
- {"9 foo=ba\n", "", "foo", "ba", true},
- {"11 foo=bar\n\x00", "\x00", "foo", "bar", true},
- {"18 foo=b=\nar=\n==\x00\n", "", "foo", "b=\nar=\n==\x00", true},
- {"27 foo=hello9 foo=ba\nworld\n", "", "foo", "hello9 foo=ba\nworld", true},
- {"27 ☺☻☹=日a本b語ç\nmeow mix", "meow mix", "☺☻☹", "日a本b語ç", true},
- {"17 \x00hello=\x00world\n", "", "\x00hello", "\x00world", true},
- {"1 k=1\n", "1 k=1\n", "", "", false},
- {"6 k~1\n", "6 k~1\n", "", "", false},
- {"6_k=1\n", "6_k=1\n", "", "", false},
- {"6 k=1 ", "6 k=1 ", "", "", false},
- {"632 k=1\n", "632 k=1\n", "", "", false},
- {"16 longkeyname=hahaha\n", "16 longkeyname=hahaha\n", "", "", false},
- {"3 somelongkey=\n", "3 somelongkey=\n", "", "", false},
- {"50 tooshort=\n", "50 tooshort=\n", "", "", false},
- }
+func TestMergePAX(t *testing.T) {
+ vectors := []struct {
+ in map[string]string
+ want *Header
+ ok bool
+ }{{
+ in: map[string]string{
+ "path": "a/b/c",
+ "uid": "1000",
+ "mtime": "1350244992.023960108",
+ },
+ want: &Header{
+ Name: "a/b/c",
+ Uid: 1000,
+ ModTime: time.Unix(1350244992, 23960108),
+ },
+ ok: true,
+ }, {
+ in: map[string]string{
+ "gid": "gtgergergersagersgers",
+ },
+ }, {
+ in: map[string]string{
+ "missing": "missing",
+ "SCHILY.xattr.key": "value",
+ },
+ want: &Header{
+ Xattrs: map[string]string{"key": "value"},
+ },
+ ok: true,
+ }}
- for _, v := range vectors {
- key, val, res, err := parsePAXRecord(v.input)
- ok := (err == nil)
- if v.ok != ok {
- if v.ok {
- t.Errorf("parsePAXRecord(%q): got parsing failure, want success", v.input)
- } else {
- t.Errorf("parsePAXRecord(%q): got parsing success, want failure", v.input)
- }
- }
- if ok && (key != v.outputKey || val != v.outputVal) {
- t.Errorf("parsePAXRecord(%q): got (%q: %q), want (%q: %q)",
- v.input, key, val, v.outputKey, v.outputVal)
+ for i, v := range vectors {
+ got := new(Header)
+ err := mergePAX(got, v.in)
+ if v.ok && !reflect.DeepEqual(*got, *v.want) {
+ t.Errorf("test %d, mergePAX(...):\ngot %+v\nwant %+v", i, *got, *v.want)
}
- if res != v.residual {
- t.Errorf("parsePAXRecord(%q): got residual %q, want residual %q",
- v.input, res, v.residual)
+ if ok := err == nil; ok != v.ok {
+ t.Errorf("test %d, mergePAX(...): got %v, want %v", i, ok, v.ok)
}
}
}
-func TestParseNumeric(t *testing.T) {
- var vectors = []struct {
- input string
- output int64
- ok bool
+func TestParsePAX(t *testing.T) {
+ vectors := []struct {
+ in string
+ want map[string]string
+ ok bool
}{
- // Test base-256 (binary) encoded values.
- {"", 0, true},
- {"\x80", 0, true},
- {"\x80\x00", 0, true},
- {"\x80\x00\x00", 0, true},
- {"\xbf", (1 << 6) - 1, true},
- {"\xbf\xff", (1 << 14) - 1, true},
- {"\xbf\xff\xff", (1 << 22) - 1, true},
- {"\xff", -1, true},
- {"\xff\xff", -1, true},
- {"\xff\xff\xff", -1, true},
- {"\xc0", -1 * (1 << 6), true},
- {"\xc0\x00", -1 * (1 << 14), true},
- {"\xc0\x00\x00", -1 * (1 << 22), true},
- {"\x87\x76\xa2\x22\xeb\x8a\x72\x61", 537795476381659745, true},
- {"\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", 537795476381659745, true},
- {"\xf7\x76\xa2\x22\xeb\x8a\x72\x61", -615126028225187231, true},
- {"\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", -615126028225187231, true},
- {"\x80\x7f\xff\xff\xff\xff\xff\xff\xff", math.MaxInt64, true},
- {"\x80\x80\x00\x00\x00\x00\x00\x00\x00", 0, false},
- {"\xff\x80\x00\x00\x00\x00\x00\x00\x00", math.MinInt64, true},
- {"\xff\x7f\xff\xff\xff\xff\xff\xff\xff", 0, false},
- {"\xf5\xec\xd1\xc7\x7e\x5f\x26\x48\x81\x9f\x8f\x9b", 0, false},
-
- // Test base-8 (octal) encoded values.
- {"0000000\x00", 0, true},
- {" \x0000000\x00", 0, true},
- {" \x0000003\x00", 3, true},
- {"00000000227\x00", 0227, true},
- {"032033\x00 ", 032033, true},
- {"320330\x00 ", 0320330, true},
- {"0000660\x00 ", 0660, true},
- {"\x00 0000660\x00 ", 0660, true},
- {"0123456789abcdef", 0, false},
- {"0123456789\x00abcdef", 0, false},
- {"01234567\x0089abcdef", 342391, true},
- {"0123\x7e\x5f\x264123", 0, false},
+ {"", nil, true},
+ {"6 k=1\n", map[string]string{"k": "1"}, true},
+ {"10 a=name\n", map[string]string{"a": "name"}, true},
+ {"9 a=name\n", map[string]string{"a": "name"}, true},
+ {"30 mtime=1350244992.023960108\n", map[string]string{"mtime": "1350244992.023960108"}, true},
+ {"3 somelongkey=\n", nil, false},
+ {"50 tooshort=\n", nil, false},
+ {"13 key1=haha\n13 key2=nana\n13 key3=kaka\n",
+ map[string]string{"key1": "haha", "key2": "nana", "key3": "kaka"}, true},
+ {"13 key1=val1\n13 key2=val2\n8 key1=\n",
+ map[string]string{"key2": "val2"}, true},
+ {"22 GNU.sparse.size=10\n26 GNU.sparse.numblocks=2\n" +
+ "23 GNU.sparse.offset=1\n25 GNU.sparse.numbytes=2\n" +
+ "23 GNU.sparse.offset=3\n25 GNU.sparse.numbytes=4\n",
+ map[string]string{paxGNUSparseSize: "10", paxGNUSparseNumBlocks: "2", paxGNUSparseMap: "1,2,3,4"}, true},
+ {"22 GNU.sparse.size=10\n26 GNU.sparse.numblocks=1\n" +
+ "25 GNU.sparse.numbytes=2\n23 GNU.sparse.offset=1\n",
+ nil, false},
+ {"22 GNU.sparse.size=10\n26 GNU.sparse.numblocks=1\n" +
+ "25 GNU.sparse.offset=1,2\n25 GNU.sparse.numbytes=2\n",
+ nil, false},
}
- for _, v := range vectors {
- var p parser
- num := p.parseNumeric([]byte(v.input))
- ok := (p.err == nil)
- if v.ok != ok {
- if v.ok {
- t.Errorf("parseNumeric(%q): got parsing failure, want success", v.input)
- } else {
- t.Errorf("parseNumeric(%q): got parsing success, want failure", v.input)
- }
+ for i, v := range vectors {
+ r := strings.NewReader(v.in)
+ got, err := parsePAX(r)
+ if !reflect.DeepEqual(got, v.want) && !(len(got) == 0 && len(v.want) == 0) {
+ t.Errorf("test %d, parsePAX(...):\ngot %v\nwant %v", i, got, v.want)
}
- if ok && num != v.output {
- t.Errorf("parseNumeric(%q): got %d, want %d", v.input, num, v.output)
+ if ok := err == nil; ok != v.ok {
+ t.Errorf("test %d, parsePAX(...): got %v, want %v", i, ok, v.ok)
}
}
}
diff --git a/libgo/go/archive/tar/strconv.go b/libgo/go/archive/tar/strconv.go
new file mode 100644
index 00000000000..bb5b51c02de
--- /dev/null
+++ b/libgo/go/archive/tar/strconv.go
@@ -0,0 +1,252 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tar
+
+import (
+ "bytes"
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+)
+
+func isASCII(s string) bool {
+ for _, c := range s {
+ if c >= 0x80 {
+ return false
+ }
+ }
+ return true
+}
+
+func toASCII(s string) string {
+ if isASCII(s) {
+ return s
+ }
+ var buf bytes.Buffer
+ for _, c := range s {
+ if c < 0x80 {
+ buf.WriteByte(byte(c))
+ }
+ }
+ return buf.String()
+}
+
+type parser struct {
+ err error // Last error seen
+}
+
+type formatter struct {
+ err error // Last error seen
+}
+
+// parseString parses bytes as a NUL-terminated C-style string.
+// If a NUL byte is not found then the whole slice is returned as a string.
+func (*parser) parseString(b []byte) string {
+ n := 0
+ for n < len(b) && b[n] != 0 {
+ n++
+ }
+ return string(b[0:n])
+}
+
+// Write s into b, terminating it with a NUL if there is room.
+func (f *formatter) formatString(b []byte, s string) {
+ if len(s) > len(b) {
+ f.err = ErrFieldTooLong
+ return
+ }
+ ascii := toASCII(s)
+ copy(b, ascii)
+ if len(ascii) < len(b) {
+ b[len(ascii)] = 0
+ }
+}
+
+// fitsInBase256 reports whether x can be encoded into n bytes using base-256
+// encoding. Unlike octal encoding, base-256 encoding does not require that the
+// string ends with a NUL character. Thus, all n bytes are available for output.
+//
+// If operating in binary mode, this assumes strict GNU binary mode; which means
+// that the first byte can only be either 0x80 or 0xff. Thus, the first byte is
+// equivalent to the sign bit in two's complement form.
+func fitsInBase256(n int, x int64) bool {
+ var binBits = uint(n-1) * 8
+ return n >= 9 || (x >= -1<<binBits && x < 1<<binBits)
+}
+
+// parseNumeric parses the input as being encoded in either base-256 or octal.
+// This function may return negative numbers.
+// If parsing fails or an integer overflow occurs, err will be set.
+func (p *parser) parseNumeric(b []byte) int64 {
+ // Check for base-256 (binary) format first.
+ // If the first bit is set, then all following bits constitute a two's
+ // complement encoded number in big-endian byte order.
+ if len(b) > 0 && b[0]&0x80 != 0 {
+ // Handling negative numbers relies on the following identity:
+ // -a-1 == ^a
+ //
+ // If the number is negative, we use an inversion mask to invert the
+ // data bytes and treat the value as an unsigned number.
+ var inv byte // 0x00 if positive or zero, 0xff if negative
+ if b[0]&0x40 != 0 {
+ inv = 0xff
+ }
+
+ var x uint64
+ for i, c := range b {
+ c ^= inv // Inverts c only if inv is 0xff, otherwise does nothing
+ if i == 0 {
+ c &= 0x7f // Ignore signal bit in first byte
+ }
+ if (x >> 56) > 0 {
+ p.err = ErrHeader // Integer overflow
+ return 0
+ }
+ x = x<<8 | uint64(c)
+ }
+ if (x >> 63) > 0 {
+ p.err = ErrHeader // Integer overflow
+ return 0
+ }
+ if inv == 0xff {
+ return ^int64(x)
+ }
+ return int64(x)
+ }
+
+ // Normal case is base-8 (octal) format.
+ return p.parseOctal(b)
+}
+
+// Write x into b, as binary (GNUtar/star extension).
+func (f *formatter) formatNumeric(b []byte, x int64) {
+ if fitsInBase256(len(b), x) {
+ for i := len(b) - 1; i >= 0; i-- {
+ b[i] = byte(x)
+ x >>= 8
+ }
+ b[0] |= 0x80 // Highest bit indicates binary format
+ return
+ }
+
+ f.formatOctal(b, 0) // Last resort, just write zero
+ f.err = ErrFieldTooLong
+}
+
+func (p *parser) parseOctal(b []byte) int64 {
+ // Because unused fields are filled with NULs, we need
+ // to skip leading NULs. Fields may also be padded with
+ // spaces or NULs.
+ // So we remove leading and trailing NULs and spaces to
+ // be sure.
+ b = bytes.Trim(b, " \x00")
+
+ if len(b) == 0 {
+ return 0
+ }
+ x, perr := strconv.ParseUint(p.parseString(b), 8, 64)
+ if perr != nil {
+ p.err = ErrHeader
+ }
+ return int64(x)
+}
+
+func (f *formatter) formatOctal(b []byte, x int64) {
+ s := strconv.FormatInt(x, 8)
+ // Add leading zeros, but leave room for a NUL.
+ if n := len(b) - len(s) - 1; n > 0 {
+ s = strings.Repeat("0", n) + s
+ }
+ f.formatString(b, s)
+}
+
+// parsePAXTime takes a string of the form %d.%d as described in the PAX
+// specification. Note that this implementation allows for negative timestamps,
+// which is allowed for by the PAX specification, but not always portable.
+func parsePAXTime(s string) (time.Time, error) {
+ const maxNanoSecondDigits = 9
+
+ // Split string into seconds and sub-seconds parts.
+ ss, sn := s, ""
+ if pos := strings.IndexByte(s, '.'); pos >= 0 {
+ ss, sn = s[:pos], s[pos+1:]
+ }
+
+ // Parse the seconds.
+ secs, err := strconv.ParseInt(ss, 10, 64)
+ if err != nil {
+ return time.Time{}, ErrHeader
+ }
+ if len(sn) == 0 {
+ return time.Unix(secs, 0), nil // No sub-second values
+ }
+
+ // Parse the nanoseconds.
+ if strings.Trim(sn, "0123456789") != "" {
+ return time.Time{}, ErrHeader
+ }
+ if len(sn) < maxNanoSecondDigits {
+ sn += strings.Repeat("0", maxNanoSecondDigits-len(sn)) // Right pad
+ } else {
+ sn = sn[:maxNanoSecondDigits] // Right truncate
+ }
+ nsecs, _ := strconv.ParseInt(sn, 10, 64) // Must succeed
+ if len(ss) > 0 && ss[0] == '-' {
+ return time.Unix(secs, -1*int64(nsecs)), nil // Negative correction
+ }
+ return time.Unix(secs, int64(nsecs)), nil
+}
+
+// TODO(dsnet): Implement formatPAXTime.
+
+// parsePAXRecord parses the input PAX record string into a key-value pair.
+// If parsing is successful, it will slice off the currently read record and
+// return the remainder as r.
+//
+// A PAX record is of the following form:
+// "%d %s=%s\n" % (size, key, value)
+func parsePAXRecord(s string) (k, v, r string, err error) {
+ // The size field ends at the first space.
+ sp := strings.IndexByte(s, ' ')
+ if sp == -1 {
+ return "", "", s, ErrHeader
+ }
+
+ // Parse the first token as a decimal integer.
+ n, perr := strconv.ParseInt(s[:sp], 10, 0) // Intentionally parse as native int
+ if perr != nil || n < 5 || int64(len(s)) < n {
+ return "", "", s, ErrHeader
+ }
+
+ // Extract everything between the space and the final newline.
+ rec, nl, rem := s[sp+1:n-1], s[n-1:n], s[n:]
+ if nl != "\n" {
+ return "", "", s, ErrHeader
+ }
+
+ // The first equals separates the key from the value.
+ eq := strings.IndexByte(rec, '=')
+ if eq == -1 {
+ return "", "", s, ErrHeader
+ }
+ return rec[:eq], rec[eq+1:], rem, nil
+}
+
+// formatPAXRecord formats a single PAX record, prefixing it with the
+// appropriate length.
+func formatPAXRecord(k, v string) string {
+ const padding = 3 // Extra padding for ' ', '=', and '\n'
+ size := len(k) + len(v) + padding
+ size += len(strconv.Itoa(size))
+ record := fmt.Sprintf("%d %s=%s\n", size, k, v)
+
+ // Final adjustment if adding size field increased the record size.
+ if len(record) != size {
+ size = len(record)
+ record = fmt.Sprintf("%d %s=%s\n", size, k, v)
+ }
+ return record
+}
diff --git a/libgo/go/archive/tar/strconv_test.go b/libgo/go/archive/tar/strconv_test.go
new file mode 100644
index 00000000000..beb70938bfd
--- /dev/null
+++ b/libgo/go/archive/tar/strconv_test.go
@@ -0,0 +1,319 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tar
+
+import (
+ "math"
+ "strings"
+ "testing"
+ "time"
+)
+
+func TestFitsInBase256(t *testing.T) {
+ vectors := []struct {
+ in int64
+ width int
+ ok bool
+ }{
+ {+1, 8, true},
+ {0, 8, true},
+ {-1, 8, true},
+ {1 << 56, 8, false},
+ {(1 << 56) - 1, 8, true},
+ {-1 << 56, 8, true},
+ {(-1 << 56) - 1, 8, false},
+ {121654, 8, true},
+ {-9849849, 8, true},
+ {math.MaxInt64, 9, true},
+ {0, 9, true},
+ {math.MinInt64, 9, true},
+ {math.MaxInt64, 12, true},
+ {0, 12, true},
+ {math.MinInt64, 12, true},
+ }
+
+ for _, v := range vectors {
+ ok := fitsInBase256(v.width, v.in)
+ if ok != v.ok {
+ t.Errorf("fitsInBase256(%d, %d): got %v, want %v", v.in, v.width, ok, v.ok)
+ }
+ }
+}
+
+func TestParseNumeric(t *testing.T) {
+ vectors := []struct {
+ in string
+ want int64
+ ok bool
+ }{
+ // Test base-256 (binary) encoded values.
+ {"", 0, true},
+ {"\x80", 0, true},
+ {"\x80\x00", 0, true},
+ {"\x80\x00\x00", 0, true},
+ {"\xbf", (1 << 6) - 1, true},
+ {"\xbf\xff", (1 << 14) - 1, true},
+ {"\xbf\xff\xff", (1 << 22) - 1, true},
+ {"\xff", -1, true},
+ {"\xff\xff", -1, true},
+ {"\xff\xff\xff", -1, true},
+ {"\xc0", -1 * (1 << 6), true},
+ {"\xc0\x00", -1 * (1 << 14), true},
+ {"\xc0\x00\x00", -1 * (1 << 22), true},
+ {"\x87\x76\xa2\x22\xeb\x8a\x72\x61", 537795476381659745, true},
+ {"\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", 537795476381659745, true},
+ {"\xf7\x76\xa2\x22\xeb\x8a\x72\x61", -615126028225187231, true},
+ {"\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", -615126028225187231, true},
+ {"\x80\x7f\xff\xff\xff\xff\xff\xff\xff", math.MaxInt64, true},
+ {"\x80\x80\x00\x00\x00\x00\x00\x00\x00", 0, false},
+ {"\xff\x80\x00\x00\x00\x00\x00\x00\x00", math.MinInt64, true},
+ {"\xff\x7f\xff\xff\xff\xff\xff\xff\xff", 0, false},
+ {"\xf5\xec\xd1\xc7\x7e\x5f\x26\x48\x81\x9f\x8f\x9b", 0, false},
+
+ // Test base-8 (octal) encoded values.
+ {"0000000\x00", 0, true},
+ {" \x0000000\x00", 0, true},
+ {" \x0000003\x00", 3, true},
+ {"00000000227\x00", 0227, true},
+ {"032033\x00 ", 032033, true},
+ {"320330\x00 ", 0320330, true},
+ {"0000660\x00 ", 0660, true},
+ {"\x00 0000660\x00 ", 0660, true},
+ {"0123456789abcdef", 0, false},
+ {"0123456789\x00abcdef", 0, false},
+ {"01234567\x0089abcdef", 342391, true},
+ {"0123\x7e\x5f\x264123", 0, false},
+ }
+
+ for _, v := range vectors {
+ var p parser
+ got := p.parseNumeric([]byte(v.in))
+ ok := (p.err == nil)
+ if ok != v.ok {
+ if v.ok {
+ t.Errorf("parseNumeric(%q): got parsing failure, want success", v.in)
+ } else {
+ t.Errorf("parseNumeric(%q): got parsing success, want failure", v.in)
+ }
+ }
+ if ok && got != v.want {
+ t.Errorf("parseNumeric(%q): got %d, want %d", v.in, got, v.want)
+ }
+ }
+}
+
+func TestFormatNumeric(t *testing.T) {
+ vectors := []struct {
+ in int64
+ want string
+ ok bool
+ }{
+ // Test base-256 (binary) encoded values.
+ {-1, "\xff", true},
+ {-1, "\xff\xff", true},
+ {-1, "\xff\xff\xff", true},
+ {(1 << 0), "0", false},
+ {(1 << 8) - 1, "\x80\xff", true},
+ {(1 << 8), "0\x00", false},
+ {(1 << 16) - 1, "\x80\xff\xff", true},
+ {(1 << 16), "00\x00", false},
+ {-1 * (1 << 0), "\xff", true},
+ {-1*(1<<0) - 1, "0", false},
+ {-1 * (1 << 8), "\xff\x00", true},
+ {-1*(1<<8) - 1, "0\x00", false},
+ {-1 * (1 << 16), "\xff\x00\x00", true},
+ {-1*(1<<16) - 1, "00\x00", false},
+ {537795476381659745, "0000000\x00", false},
+ {537795476381659745, "\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", true},
+ {-615126028225187231, "0000000\x00", false},
+ {-615126028225187231, "\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", true},
+ {math.MaxInt64, "0000000\x00", false},
+ {math.MaxInt64, "\x80\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff", true},
+ {math.MinInt64, "0000000\x00", false},
+ {math.MinInt64, "\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
+ {math.MaxInt64, "\x80\x7f\xff\xff\xff\xff\xff\xff\xff", true},
+ {math.MinInt64, "\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
+ }
+
+ for _, v := range vectors {
+ var f formatter
+ got := make([]byte, len(v.want))
+ f.formatNumeric(got, v.in)
+ ok := (f.err == nil)
+ if ok != v.ok {
+ if v.ok {
+ t.Errorf("formatNumeric(%d): got formatting failure, want success", v.in)
+ } else {
+ t.Errorf("formatNumeric(%d): got formatting success, want failure", v.in)
+ }
+ }
+ if string(got) != v.want {
+ t.Errorf("formatNumeric(%d): got %q, want %q", v.in, got, v.want)
+ }
+ }
+}
+
+func TestParsePAXTime(t *testing.T) {
+ vectors := []struct {
+ in string
+ want time.Time
+ ok bool
+ }{
+ {"1350244992.023960108", time.Unix(1350244992, 23960108), true},
+ {"1350244992.02396010", time.Unix(1350244992, 23960100), true},
+ {"1350244992.0239601089", time.Unix(1350244992, 23960108), true},
+ {"1350244992.3", time.Unix(1350244992, 300000000), true},
+ {"1350244992", time.Unix(1350244992, 0), true},
+ {"-1.000000001", time.Unix(-1, -1e0+0e0), true},
+ {"-1.000001", time.Unix(-1, -1e3+0e0), true},
+ {"-1.001000", time.Unix(-1, -1e6+0e0), true},
+ {"-1", time.Unix(-1, -0e0+0e0), true},
+ {"-1.999000", time.Unix(-1, -1e9+1e6), true},
+ {"-1.999999", time.Unix(-1, -1e9+1e3), true},
+ {"-1.999999999", time.Unix(-1, -1e9+1e0), true},
+ {"0.000000001", time.Unix(0, 1e0+0e0), true},
+ {"0.000001", time.Unix(0, 1e3+0e0), true},
+ {"0.001000", time.Unix(0, 1e6+0e0), true},
+ {"0", time.Unix(0, 0e0), true},
+ {"0.999000", time.Unix(0, 1e9-1e6), true},
+ {"0.999999", time.Unix(0, 1e9-1e3), true},
+ {"0.999999999", time.Unix(0, 1e9-1e0), true},
+ {"1.000000001", time.Unix(+1, +1e0-0e0), true},
+ {"1.000001", time.Unix(+1, +1e3-0e0), true},
+ {"1.001000", time.Unix(+1, +1e6-0e0), true},
+ {"1", time.Unix(+1, +0e0-0e0), true},
+ {"1.999000", time.Unix(+1, +1e9-1e6), true},
+ {"1.999999", time.Unix(+1, +1e9-1e3), true},
+ {"1.999999999", time.Unix(+1, +1e9-1e0), true},
+ {"-1350244992.023960108", time.Unix(-1350244992, -23960108), true},
+ {"-1350244992.02396010", time.Unix(-1350244992, -23960100), true},
+ {"-1350244992.0239601089", time.Unix(-1350244992, -23960108), true},
+ {"-1350244992.3", time.Unix(-1350244992, -300000000), true},
+ {"-1350244992", time.Unix(-1350244992, 0), true},
+ {"", time.Time{}, false},
+ {"0", time.Unix(0, 0), true},
+ {"1.", time.Unix(1, 0), true},
+ {"0.0", time.Unix(0, 0), true},
+ {".5", time.Time{}, false},
+ {"-1.3", time.Unix(-1, -3e8), true},
+ {"-1.0", time.Unix(-1, -0e0), true},
+ {"-0.0", time.Unix(-0, -0e0), true},
+ {"-0.1", time.Unix(-0, -1e8), true},
+ {"-0.01", time.Unix(-0, -1e7), true},
+ {"-0.99", time.Unix(-0, -99e7), true},
+ {"-0.98", time.Unix(-0, -98e7), true},
+ {"-1.1", time.Unix(-1, -1e8), true},
+ {"-1.01", time.Unix(-1, -1e7), true},
+ {"-2.99", time.Unix(-2, -99e7), true},
+ {"-5.98", time.Unix(-5, -98e7), true},
+ {"-", time.Time{}, false},
+ {"+", time.Time{}, false},
+ {"-1.-1", time.Time{}, false},
+ {"99999999999999999999999999999999999999999999999", time.Time{}, false},
+ {"0.123456789abcdef", time.Time{}, false},
+ {"foo", time.Time{}, false},
+ {"\x00", time.Time{}, false},
+ {"𝟵𝟴𝟳𝟲𝟱.𝟰𝟯𝟮𝟭𝟬", time.Time{}, false}, // Unicode numbers (U+1D7EC to U+1D7F5)
+ {"98765﹒43210", time.Time{}, false}, // Unicode period (U+FE52)
+ }
+
+ for _, v := range vectors {
+ ts, err := parsePAXTime(v.in)
+ ok := (err == nil)
+ if v.ok != ok {
+ if v.ok {
+ t.Errorf("parsePAXTime(%q): got parsing failure, want success", v.in)
+ } else {
+ t.Errorf("parsePAXTime(%q): got parsing success, want failure", v.in)
+ }
+ }
+ if ok && !ts.Equal(v.want) {
+ t.Errorf("parsePAXTime(%q): got (%ds %dns), want (%ds %dns)",
+ v.in, ts.Unix(), ts.Nanosecond(), v.want.Unix(), v.want.Nanosecond())
+ }
+ }
+}
+
+func TestParsePAXRecord(t *testing.T) {
+ medName := strings.Repeat("CD", 50)
+ longName := strings.Repeat("AB", 100)
+
+ vectors := []struct {
+ in string
+ wantRes string
+ wantKey string
+ wantVal string
+ ok bool
+ }{
+ {"6 k=v\n\n", "\n", "k", "v", true},
+ {"19 path=/etc/hosts\n", "", "path", "/etc/hosts", true},
+ {"210 path=" + longName + "\nabc", "abc", "path", longName, true},
+ {"110 path=" + medName + "\n", "", "path", medName, true},
+ {"9 foo=ba\n", "", "foo", "ba", true},
+ {"11 foo=bar\n\x00", "\x00", "foo", "bar", true},
+ {"18 foo=b=\nar=\n==\x00\n", "", "foo", "b=\nar=\n==\x00", true},
+ {"27 foo=hello9 foo=ba\nworld\n", "", "foo", "hello9 foo=ba\nworld", true},
+ {"27 ☺☻☹=日a本b語ç\nmeow mix", "meow mix", "☺☻☹", "日a本b語ç", true},
+ {"17 \x00hello=\x00world\n", "", "\x00hello", "\x00world", true},
+ {"1 k=1\n", "1 k=1\n", "", "", false},
+ {"6 k~1\n", "6 k~1\n", "", "", false},
+ {"6_k=1\n", "6_k=1\n", "", "", false},
+ {"6 k=1 ", "6 k=1 ", "", "", false},
+ {"632 k=1\n", "632 k=1\n", "", "", false},
+ {"16 longkeyname=hahaha\n", "16 longkeyname=hahaha\n", "", "", false},
+ {"3 somelongkey=\n", "3 somelongkey=\n", "", "", false},
+ {"50 tooshort=\n", "50 tooshort=\n", "", "", false},
+ }
+
+ for _, v := range vectors {
+ key, val, res, err := parsePAXRecord(v.in)
+ ok := (err == nil)
+ if ok != v.ok {
+ if v.ok {
+ t.Errorf("parsePAXRecord(%q): got parsing failure, want success", v.in)
+ } else {
+ t.Errorf("parsePAXRecord(%q): got parsing success, want failure", v.in)
+ }
+ }
+ if v.ok && (key != v.wantKey || val != v.wantVal) {
+ t.Errorf("parsePAXRecord(%q): got (%q: %q), want (%q: %q)",
+ v.in, key, val, v.wantKey, v.wantVal)
+ }
+ if res != v.wantRes {
+ t.Errorf("parsePAXRecord(%q): got residual %q, want residual %q",
+ v.in, res, v.wantRes)
+ }
+ }
+}
+
+func TestFormatPAXRecord(t *testing.T) {
+ medName := strings.Repeat("CD", 50)
+ longName := strings.Repeat("AB", 100)
+
+ vectors := []struct {
+ inKey string
+ inVal string
+ want string
+ }{
+ {"k", "v", "6 k=v\n"},
+ {"path", "/etc/hosts", "19 path=/etc/hosts\n"},
+ {"path", longName, "210 path=" + longName + "\n"},
+ {"path", medName, "110 path=" + medName + "\n"},
+ {"foo", "ba", "9 foo=ba\n"},
+ {"foo", "bar", "11 foo=bar\n"},
+ {"foo", "b=\nar=\n==\x00", "18 foo=b=\nar=\n==\x00\n"},
+ {"foo", "hello9 foo=ba\nworld", "27 foo=hello9 foo=ba\nworld\n"},
+ {"☺☻☹", "日a本b語ç", "27 ☺☻☹=日a本b語ç\n"},
+ {"\x00hello", "\x00world", "17 \x00hello=\x00world\n"},
+ }
+
+ for _, v := range vectors {
+ got := formatPAXRecord(v.inKey, v.inVal)
+ if got != v.want {
+ t.Errorf("formatPAXRecord(%q, %q): got %q, want %q",
+ v.inKey, v.inVal, got, v.want)
+ }
+ }
+}
diff --git a/libgo/go/archive/tar/tar_test.go b/libgo/go/archive/tar/tar_test.go
index d63c072eb9a..cf8337c2ad9 100644
--- a/libgo/go/archive/tar/tar_test.go
+++ b/libgo/go/archive/tar/tar_test.go
@@ -135,190 +135,178 @@ type headerRoundTripTest struct {
}
func TestHeaderRoundTrip(t *testing.T) {
- golden := []headerRoundTripTest{
+ vectors := []headerRoundTripTest{{
// regular file.
- {
- h: &Header{
- Name: "test.txt",
- Mode: 0644 | c_ISREG,
- Size: 12,
- ModTime: time.Unix(1360600916, 0),
- Typeflag: TypeReg,
- },
- fm: 0644,
+ h: &Header{
+ Name: "test.txt",
+ Mode: 0644 | c_ISREG,
+ Size: 12,
+ ModTime: time.Unix(1360600916, 0),
+ Typeflag: TypeReg,
},
+ fm: 0644,
+ }, {
// symbolic link.
- {
- h: &Header{
- Name: "link.txt",
- Mode: 0777 | c_ISLNK,
- Size: 0,
- ModTime: time.Unix(1360600852, 0),
- Typeflag: TypeSymlink,
- },
- fm: 0777 | os.ModeSymlink,
+ h: &Header{
+ Name: "link.txt",
+ Mode: 0777 | c_ISLNK,
+ Size: 0,
+ ModTime: time.Unix(1360600852, 0),
+ Typeflag: TypeSymlink,
},
+ fm: 0777 | os.ModeSymlink,
+ }, {
// character device node.
- {
- h: &Header{
- Name: "dev/null",
- Mode: 0666 | c_ISCHR,
- Size: 0,
- ModTime: time.Unix(1360578951, 0),
- Typeflag: TypeChar,
- },
- fm: 0666 | os.ModeDevice | os.ModeCharDevice,
+ h: &Header{
+ Name: "dev/null",
+ Mode: 0666 | c_ISCHR,
+ Size: 0,
+ ModTime: time.Unix(1360578951, 0),
+ Typeflag: TypeChar,
},
+ fm: 0666 | os.ModeDevice | os.ModeCharDevice,
+ }, {
// block device node.
- {
- h: &Header{
- Name: "dev/sda",
- Mode: 0660 | c_ISBLK,
- Size: 0,
- ModTime: time.Unix(1360578954, 0),
- Typeflag: TypeBlock,
- },
- fm: 0660 | os.ModeDevice,
+ h: &Header{
+ Name: "dev/sda",
+ Mode: 0660 | c_ISBLK,
+ Size: 0,
+ ModTime: time.Unix(1360578954, 0),
+ Typeflag: TypeBlock,
},
+ fm: 0660 | os.ModeDevice,
+ }, {
// directory.
- {
- h: &Header{
- Name: "dir/",
- Mode: 0755 | c_ISDIR,
- Size: 0,
- ModTime: time.Unix(1360601116, 0),
- Typeflag: TypeDir,
- },
- fm: 0755 | os.ModeDir,
+ h: &Header{
+ Name: "dir/",
+ Mode: 0755 | c_ISDIR,
+ Size: 0,
+ ModTime: time.Unix(1360601116, 0),
+ Typeflag: TypeDir,
},
+ fm: 0755 | os.ModeDir,
+ }, {
// fifo node.
- {
- h: &Header{
- Name: "dev/initctl",
- Mode: 0600 | c_ISFIFO,
- Size: 0,
- ModTime: time.Unix(1360578949, 0),
- Typeflag: TypeFifo,
- },
- fm: 0600 | os.ModeNamedPipe,
+ h: &Header{
+ Name: "dev/initctl",
+ Mode: 0600 | c_ISFIFO,
+ Size: 0,
+ ModTime: time.Unix(1360578949, 0),
+ Typeflag: TypeFifo,
},
+ fm: 0600 | os.ModeNamedPipe,
+ }, {
// setuid.
- {
- h: &Header{
- Name: "bin/su",
- Mode: 0755 | c_ISREG | c_ISUID,
- Size: 23232,
- ModTime: time.Unix(1355405093, 0),
- Typeflag: TypeReg,
- },
- fm: 0755 | os.ModeSetuid,
+ h: &Header{
+ Name: "bin/su",
+ Mode: 0755 | c_ISREG | c_ISUID,
+ Size: 23232,
+ ModTime: time.Unix(1355405093, 0),
+ Typeflag: TypeReg,
},
+ fm: 0755 | os.ModeSetuid,
+ }, {
// setguid.
- {
- h: &Header{
- Name: "group.txt",
- Mode: 0750 | c_ISREG | c_ISGID,
- Size: 0,
- ModTime: time.Unix(1360602346, 0),
- Typeflag: TypeReg,
- },
- fm: 0750 | os.ModeSetgid,
+ h: &Header{
+ Name: "group.txt",
+ Mode: 0750 | c_ISREG | c_ISGID,
+ Size: 0,
+ ModTime: time.Unix(1360602346, 0),
+ Typeflag: TypeReg,
},
+ fm: 0750 | os.ModeSetgid,
+ }, {
// sticky.
- {
- h: &Header{
- Name: "sticky.txt",
- Mode: 0600 | c_ISREG | c_ISVTX,
- Size: 7,
- ModTime: time.Unix(1360602540, 0),
- Typeflag: TypeReg,
- },
- fm: 0600 | os.ModeSticky,
+ h: &Header{
+ Name: "sticky.txt",
+ Mode: 0600 | c_ISREG | c_ISVTX,
+ Size: 7,
+ ModTime: time.Unix(1360602540, 0),
+ Typeflag: TypeReg,
},
+ fm: 0600 | os.ModeSticky,
+ }, {
// hard link.
- {
- h: &Header{
- Name: "hard.txt",
- Mode: 0644 | c_ISREG,
- Size: 0,
- Linkname: "file.txt",
- ModTime: time.Unix(1360600916, 0),
- Typeflag: TypeLink,
- },
- fm: 0644,
+ h: &Header{
+ Name: "hard.txt",
+ Mode: 0644 | c_ISREG,
+ Size: 0,
+ Linkname: "file.txt",
+ ModTime: time.Unix(1360600916, 0),
+ Typeflag: TypeLink,
},
+ fm: 0644,
+ }, {
// More information.
- {
- h: &Header{
- Name: "info.txt",
- Mode: 0600 | c_ISREG,
- Size: 0,
- Uid: 1000,
- Gid: 1000,
- ModTime: time.Unix(1360602540, 0),
- Uname: "slartibartfast",
- Gname: "users",
- Typeflag: TypeReg,
- },
- fm: 0600,
+ h: &Header{
+ Name: "info.txt",
+ Mode: 0600 | c_ISREG,
+ Size: 0,
+ Uid: 1000,
+ Gid: 1000,
+ ModTime: time.Unix(1360602540, 0),
+ Uname: "slartibartfast",
+ Gname: "users",
+ Typeflag: TypeReg,
},
- }
+ fm: 0600,
+ }}
- for i, g := range golden {
- fi := g.h.FileInfo()
+ for i, v := range vectors {
+ fi := v.h.FileInfo()
h2, err := FileInfoHeader(fi, "")
if err != nil {
t.Error(err)
continue
}
if strings.Contains(fi.Name(), "/") {
- t.Errorf("FileInfo of %q contains slash: %q", g.h.Name, fi.Name())
+ t.Errorf("FileInfo of %q contains slash: %q", v.h.Name, fi.Name())
}
- name := path.Base(g.h.Name)
+ name := path.Base(v.h.Name)
if fi.IsDir() {
name += "/"
}
if got, want := h2.Name, name; got != want {
t.Errorf("i=%d: Name: got %v, want %v", i, got, want)
}
- if got, want := h2.Size, g.h.Size; got != want {
+ if got, want := h2.Size, v.h.Size; got != want {
t.Errorf("i=%d: Size: got %v, want %v", i, got, want)
}
- if got, want := h2.Uid, g.h.Uid; got != want {
+ if got, want := h2.Uid, v.h.Uid; got != want {
t.Errorf("i=%d: Uid: got %d, want %d", i, got, want)
}
- if got, want := h2.Gid, g.h.Gid; got != want {
+ if got, want := h2.Gid, v.h.Gid; got != want {
t.Errorf("i=%d: Gid: got %d, want %d", i, got, want)
}
- if got, want := h2.Uname, g.h.Uname; got != want {
+ if got, want := h2.Uname, v.h.Uname; got != want {
t.Errorf("i=%d: Uname: got %q, want %q", i, got, want)
}
- if got, want := h2.Gname, g.h.Gname; got != want {
+ if got, want := h2.Gname, v.h.Gname; got != want {
t.Errorf("i=%d: Gname: got %q, want %q", i, got, want)
}
- if got, want := h2.Linkname, g.h.Linkname; got != want {
+ if got, want := h2.Linkname, v.h.Linkname; got != want {
t.Errorf("i=%d: Linkname: got %v, want %v", i, got, want)
}
- if got, want := h2.Typeflag, g.h.Typeflag; got != want {
- t.Logf("%#v %#v", g.h, fi.Sys())
+ if got, want := h2.Typeflag, v.h.Typeflag; got != want {
+ t.Logf("%#v %#v", v.h, fi.Sys())
t.Errorf("i=%d: Typeflag: got %q, want %q", i, got, want)
}
- if got, want := h2.Mode, g.h.Mode; got != want {
+ if got, want := h2.Mode, v.h.Mode; got != want {
t.Errorf("i=%d: Mode: got %o, want %o", i, got, want)
}
- if got, want := fi.Mode(), g.fm; got != want {
+ if got, want := fi.Mode(), v.fm; got != want {
t.Errorf("i=%d: fi.Mode: got %o, want %o", i, got, want)
}
- if got, want := h2.AccessTime, g.h.AccessTime; got != want {
+ if got, want := h2.AccessTime, v.h.AccessTime; got != want {
t.Errorf("i=%d: AccessTime: got %v, want %v", i, got, want)
}
- if got, want := h2.ChangeTime, g.h.ChangeTime; got != want {
+ if got, want := h2.ChangeTime, v.h.ChangeTime; got != want {
t.Errorf("i=%d: ChangeTime: got %v, want %v", i, got, want)
}
- if got, want := h2.ModTime, g.h.ModTime; got != want {
+ if got, want := h2.ModTime, v.h.ModTime; got != want {
t.Errorf("i=%d: ModTime: got %v, want %v", i, got, want)
}
- if sysh, ok := fi.Sys().(*Header); !ok || sysh != g.h {
+ if sysh, ok := fi.Sys().(*Header); !ok || sysh != v.h {
t.Errorf("i=%d: Sys didn't return original *Header", i)
}
}
diff --git a/libgo/go/archive/tar/testdata/gnu-incremental.tar b/libgo/go/archive/tar/testdata/gnu-incremental.tar
new file mode 100644
index 00000000000..4c442e5b82d
--- /dev/null
+++ b/libgo/go/archive/tar/testdata/gnu-incremental.tar
Binary files differ
diff --git a/libgo/go/archive/tar/testdata/pax-bad-hdr-file.tar b/libgo/go/archive/tar/testdata/pax-bad-hdr-file.tar
new file mode 100644
index 00000000000..b97cc981f29
--- /dev/null
+++ b/libgo/go/archive/tar/testdata/pax-bad-hdr-file.tar
Binary files differ
diff --git a/libgo/go/archive/tar/testdata/pax-bad-mtime-file.tar b/libgo/go/archive/tar/testdata/pax-bad-mtime-file.tar
new file mode 100644
index 00000000000..9b22f7e8d94
--- /dev/null
+++ b/libgo/go/archive/tar/testdata/pax-bad-mtime-file.tar
Binary files differ
diff --git a/libgo/go/archive/tar/testdata/pax-pos-size-file.tar b/libgo/go/archive/tar/testdata/pax-pos-size-file.tar
new file mode 100644
index 00000000000..aed9a8aa48f
--- /dev/null
+++ b/libgo/go/archive/tar/testdata/pax-pos-size-file.tar
Binary files differ
diff --git a/libgo/go/archive/tar/testdata/ustar.issue12594.tar b/libgo/go/archive/tar/testdata/ustar.issue12594.tar
new file mode 100644
index 00000000000..c7910ae9f43
--- /dev/null
+++ b/libgo/go/archive/tar/testdata/ustar.issue12594.tar
Binary files differ
diff --git a/libgo/go/archive/tar/testdata/writer-big-long.tar b/libgo/go/archive/tar/testdata/writer-big-long.tar
index 5960ee82478..52bd748f3b2 100644
--- a/libgo/go/archive/tar/testdata/writer-big-long.tar
+++ b/libgo/go/archive/tar/testdata/writer-big-long.tar
Binary files differ
diff --git a/libgo/go/archive/tar/writer.go b/libgo/go/archive/tar/writer.go
index 426e4434eb7..596fb8b9e17 100644
--- a/libgo/go/archive/tar/writer.go
+++ b/libgo/go/archive/tar/writer.go
@@ -42,10 +42,6 @@ type Writer struct {
paxHdrBuff block // buffer to use in writeHeader when writing a PAX header
}
-type formatter struct {
- err error // Last error seen
-}
-
// NewWriter creates a new Writer writing to w.
func NewWriter(w io.Writer) *Writer { return &Writer{w: w} }
@@ -71,56 +67,6 @@ func (tw *Writer) Flush() error {
return tw.err
}
-// Write s into b, terminating it with a NUL if there is room.
-func (f *formatter) formatString(b []byte, s string) {
- if len(s) > len(b) {
- f.err = ErrFieldTooLong
- return
- }
- ascii := toASCII(s)
- copy(b, ascii)
- if len(ascii) < len(b) {
- b[len(ascii)] = 0
- }
-}
-
-// Encode x as an octal ASCII string and write it into b with leading zeros.
-func (f *formatter) formatOctal(b []byte, x int64) {
- s := strconv.FormatInt(x, 8)
- // leading zeros, but leave room for a NUL.
- for len(s)+1 < len(b) {
- s = "0" + s
- }
- f.formatString(b, s)
-}
-
-// fitsInBase256 reports whether x can be encoded into n bytes using base-256
-// encoding. Unlike octal encoding, base-256 encoding does not require that the
-// string ends with a NUL character. Thus, all n bytes are available for output.
-//
-// If operating in binary mode, this assumes strict GNU binary mode; which means
-// that the first byte can only be either 0x80 or 0xff. Thus, the first byte is
-// equivalent to the sign bit in two's complement form.
-func fitsInBase256(n int, x int64) bool {
- var binBits = uint(n-1) * 8
- return n >= 9 || (x >= -1<<binBits && x < 1<<binBits)
-}
-
-// Write x into b, as binary (GNUtar/star extension).
-func (f *formatter) formatNumeric(b []byte, x int64) {
- if fitsInBase256(len(b), x) {
- for i := len(b) - 1; i >= 0; i-- {
- b[i] = byte(x)
- x >>= 8
- }
- b[0] |= 0x80 // Highest bit indicates binary format
- return
- }
-
- f.formatOctal(b, 0) // Last resort, just write zero
- f.err = ErrFieldTooLong
-}
-
var (
minTime = time.Unix(0, 0)
// There is room for 11 octal digits (33 bits) of mtime.
@@ -224,9 +170,41 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
formatNumeric(ustar.DevMajor(), hdr.Devmajor, paxNone)
formatNumeric(ustar.DevMinor(), hdr.Devminor, paxNone)
+ // TODO(dsnet): The logic surrounding the prefix field is broken when trying
+ // to encode the header as GNU format. The challenge with the current logic
+ // is that we are unsure what format we are using at any given moment until
+ // we have processed *all* of the fields. The problem is that by the time
+ // all fields have been processed, some work has already been done to handle
+ // each field under the assumption that it is for one given format or
+ // another. In some situations, this causes the Writer to be confused and
+ // encode a prefix field when the format being used is GNU. Thus, producing
+ // an invalid tar file.
+ //
+ // As a short-term fix, we disable the logic to use the prefix field, which
+ // will force the badly generated GNU files to become encoded as being
+ // the PAX format.
+ //
+ // As an alternative fix, we could hard-code preferPax to be true. However,
+ // this is problematic for the following reasons:
+ // * The preferPax functionality is not tested at all.
+ // * This can result in headers that try to use both the GNU and PAX
+ // features at the same time, which is also wrong.
+ //
+ // The proper fix for this is to use a two-pass method:
+ // * The first pass simply determines what set of formats can possibly
+ // encode the given header.
+ // * The second pass actually encodes the header as that given format
+ // without worrying about violating the format.
+ //
+ // See the following:
+ // https://golang.org/issue/12594
+ // https://golang.org/issue/17630
+ // https://golang.org/issue/9683
+ const usePrefix = false
+
// try to use a ustar header when only the name is too long
_, paxPathUsed := paxHeaders[paxPath]
- if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed {
+ if usePrefix && !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed {
prefix, suffix, ok := splitUSTARPath(hdr.Name)
if ok {
// Since we can encode in USTAR format, disable PAX header.
@@ -317,7 +295,7 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) erro
var buf bytes.Buffer
// Keys are sorted before writing to body to allow deterministic output.
- var keys []string
+ keys := make([]string, 0, len(paxHeaders))
for k := range paxHeaders {
keys = append(keys, k)
}
@@ -340,22 +318,6 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) erro
return nil
}
-// formatPAXRecord formats a single PAX record, prefixing it with the
-// appropriate length.
-func formatPAXRecord(k, v string) string {
- const padding = 3 // Extra padding for ' ', '=', and '\n'
- size := len(k) + len(v) + padding
- size += len(strconv.Itoa(size))
- record := fmt.Sprintf("%d %s=%s\n", size, k, v)
-
- // Final adjustment if adding size field increased the record size.
- if len(record) != size {
- size = len(record)
- record = fmt.Sprintf("%d %s=%s\n", size, k, v)
- }
- return record
-}
-
// Write writes to the current entry in the tar archive.
// Write returns the error ErrWriteTooLong if more than
// hdr.Size bytes are written after WriteHeader.
diff --git a/libgo/go/archive/tar/writer_test.go b/libgo/go/archive/tar/writer_test.go
index 27aa8e5dab6..d88b8f41ca8 100644
--- a/libgo/go/archive/tar/writer_test.go
+++ b/libgo/go/archive/tar/writer_test.go
@@ -9,7 +9,6 @@ import (
"fmt"
"io"
"io/ioutil"
- "math"
"os"
"reflect"
"sort"
@@ -19,176 +18,6 @@ import (
"time"
)
-type writerTestEntry struct {
- header *Header
- contents string
-}
-
-type writerTest struct {
- file string // filename of expected output
- entries []*writerTestEntry
-}
-
-var writerTests = []*writerTest{
- // The writer test file was produced with this command:
- // tar (GNU tar) 1.26
- // ln -s small.txt link.txt
- // tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt
- {
- file: "testdata/writer.tar",
- entries: []*writerTestEntry{
- {
- header: &Header{
- Name: "small.txt",
- Mode: 0640,
- Uid: 73025,
- Gid: 5000,
- Size: 5,
- ModTime: time.Unix(1246508266, 0),
- Typeflag: '0',
- Uname: "dsymonds",
- Gname: "eng",
- },
- contents: "Kilts",
- },
- {
- header: &Header{
- Name: "small2.txt",
- Mode: 0640,
- Uid: 73025,
- Gid: 5000,
- Size: 11,
- ModTime: time.Unix(1245217492, 0),
- Typeflag: '0',
- Uname: "dsymonds",
- Gname: "eng",
- },
- contents: "Google.com\n",
- },
- {
- header: &Header{
- Name: "link.txt",
- Mode: 0777,
- Uid: 1000,
- Gid: 1000,
- Size: 0,
- ModTime: time.Unix(1314603082, 0),
- Typeflag: '2',
- Linkname: "small.txt",
- Uname: "strings",
- Gname: "strings",
- },
- // no contents
- },
- },
- },
- // The truncated test file was produced using these commands:
- // dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
- // tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
- {
- file: "testdata/writer-big.tar",
- entries: []*writerTestEntry{
- {
- header: &Header{
- Name: "tmp/16gig.txt",
- Mode: 0640,
- Uid: 73025,
- Gid: 5000,
- Size: 16 << 30,
- ModTime: time.Unix(1254699560, 0),
- Typeflag: '0',
- Uname: "dsymonds",
- Gname: "eng",
- },
- // fake contents
- contents: strings.Repeat("\x00", 4<<10),
- },
- },
- },
- // 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
- {
- file: "testdata/ustar.tar",
- entries: []*writerTestEntry{
- {
- header: &Header{
- Name: strings.Repeat("longname/", 15) + "file.txt",
- Mode: 0644,
- Uid: 0765,
- Gid: 024,
- Size: 06,
- ModTime: time.Unix(1360135598, 0),
- Typeflag: '0',
- Uname: "shane",
- Gname: "staff",
- },
- contents: "hello\n",
- },
- },
- },
- // This file was produced using gnu tar 1.26
- // echo "Slartibartfast" > file.txt
- // ln file.txt hard.txt
- // tar -b 1 --format=ustar -c -f hardlink.tar file.txt hard.txt
- {
- file: "testdata/hardlink.tar",
- entries: []*writerTestEntry{
- {
- header: &Header{
- Name: "file.txt",
- Mode: 0644,
- Uid: 1000,
- Gid: 100,
- Size: 15,
- ModTime: time.Unix(1425484303, 0),
- Typeflag: '0',
- Uname: "vbatts",
- Gname: "users",
- },
- contents: "Slartibartfast\n",
- },
- {
- header: &Header{
- Name: "hard.txt",
- Mode: 0644,
- Uid: 1000,
- Gid: 100,
- Size: 0,
- ModTime: time.Unix(1425484303, 0),
- Typeflag: '1',
- Linkname: "file.txt",
- Uname: "vbatts",
- Gname: "users",
- },
- // no contents
- },
- },
- },
-}
-
// Render byte array in a two-character hexadecimal string, spaced for easy visual inspection.
func bytestr(offset int, b []byte) string {
const rowLen = 32
@@ -228,9 +57,168 @@ func bytediff(a []byte, b []byte) string {
}
func TestWriter(t *testing.T) {
+ type entry struct {
+ header *Header
+ contents string
+ }
+
+ vectors := []struct {
+ file string // filename of expected output
+ entries []*entry
+ }{{
+ // The writer test file was produced with this command:
+ // tar (GNU tar) 1.26
+ // ln -s small.txt link.txt
+ // tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt
+ file: "testdata/writer.tar",
+ entries: []*entry{{
+ header: &Header{
+ Name: "small.txt",
+ Mode: 0640,
+ Uid: 73025,
+ Gid: 5000,
+ Size: 5,
+ ModTime: time.Unix(1246508266, 0),
+ Typeflag: '0',
+ Uname: "dsymonds",
+ Gname: "eng",
+ },
+ contents: "Kilts",
+ }, {
+ header: &Header{
+ Name: "small2.txt",
+ Mode: 0640,
+ Uid: 73025,
+ Gid: 5000,
+ Size: 11,
+ ModTime: time.Unix(1245217492, 0),
+ Typeflag: '0',
+ Uname: "dsymonds",
+ Gname: "eng",
+ },
+ contents: "Google.com\n",
+ }, {
+ header: &Header{
+ Name: "link.txt",
+ Mode: 0777,
+ Uid: 1000,
+ Gid: 1000,
+ Size: 0,
+ ModTime: time.Unix(1314603082, 0),
+ Typeflag: '2',
+ Linkname: "small.txt",
+ Uname: "strings",
+ Gname: "strings",
+ },
+ // no contents
+ }},
+ }, {
+ // The truncated test file was produced using these commands:
+ // dd if=/dev/zero bs=1048576 count=16384 > /tmp/16gig.txt
+ // tar -b 1 -c -f- /tmp/16gig.txt | dd bs=512 count=8 > writer-big.tar
+ file: "testdata/writer-big.tar",
+ entries: []*entry{{
+ header: &Header{
+ Name: "tmp/16gig.txt",
+ Mode: 0640,
+ Uid: 73025,
+ Gid: 5000,
+ Size: 16 << 30,
+ ModTime: time.Unix(1254699560, 0),
+ Typeflag: '0',
+ Uname: "dsymonds",
+ Gname: "eng",
+ },
+ // fake contents
+ contents: strings.Repeat("\x00", 4<<10),
+ }},
+ }, {
+ // This truncated file was produced using this library.
+ // It was verified to work with GNU tar 1.27.1 and BSD tar 3.1.2.
+ // dd if=/dev/zero bs=1G count=16 >> writer-big-long.tar
+ // gnutar -xvf writer-big-long.tar
+ // bsdtar -xvf writer-big-long.tar
+ //
+ // This file is in PAX format.
+ file: "testdata/writer-big-long.tar",
+ entries: []*entry{{
+ 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),
+ }},
+ }, {
+ // TODO(dsnet): The Writer output should match the following file.
+ // To fix an issue (see https://golang.org/issue/12594), we disabled
+ // prefix support, which alters the generated output.
+ /*
+ // This file was produced using gnu tar 1.17
+ // gnutar -b 4 --format=ustar (longname/)*15 + file.txt
+ file: "testdata/ustar.tar"
+ */
+ file: "testdata/ustar.issue12594.tar", // This is a valid tar file, but not expected
+ entries: []*entry{{
+ header: &Header{
+ Name: strings.Repeat("longname/", 15) + "file.txt",
+ Mode: 0644,
+ Uid: 0765,
+ Gid: 024,
+ Size: 06,
+ ModTime: time.Unix(1360135598, 0),
+ Typeflag: '0',
+ Uname: "shane",
+ Gname: "staff",
+ },
+ contents: "hello\n",
+ }},
+ }, {
+ // This file was produced using gnu tar 1.26
+ // echo "Slartibartfast" > file.txt
+ // ln file.txt hard.txt
+ // tar -b 1 --format=ustar -c -f hardlink.tar file.txt hard.txt
+ file: "testdata/hardlink.tar",
+ entries: []*entry{{
+ header: &Header{
+ Name: "file.txt",
+ Mode: 0644,
+ Uid: 1000,
+ Gid: 100,
+ Size: 15,
+ ModTime: time.Unix(1425484303, 0),
+ Typeflag: '0',
+ Uname: "vbatts",
+ Gname: "users",
+ },
+ contents: "Slartibartfast\n",
+ }, {
+ header: &Header{
+ Name: "hard.txt",
+ Mode: 0644,
+ Uid: 1000,
+ Gid: 100,
+ Size: 0,
+ ModTime: time.Unix(1425484303, 0),
+ Typeflag: '1',
+ Linkname: "file.txt",
+ Uname: "vbatts",
+ Gname: "users",
+ },
+ // no contents
+ }},
+ }}
+
testLoop:
- for i, test := range writerTests {
- expected, err := ioutil.ReadFile(test.file)
+ for i, v := range vectors {
+ expected, err := ioutil.ReadFile(v.file)
if err != nil {
t.Errorf("test %d: Unexpected error: %v", i, err)
continue
@@ -239,7 +227,7 @@ testLoop:
buf := new(bytes.Buffer)
tw := NewWriter(iotest.TruncateWriter(buf, 4<<10)) // only catch the first 4 KB
big := false
- for j, entry := range test.entries {
+ for j, entry := range v.entries {
big = big || entry.header.Size > 1<<10
if err := tw.WriteHeader(entry.header); err != nil {
t.Errorf("test %d, entry %d: Failed writing header: %v", i, j, err)
@@ -576,9 +564,9 @@ func TestWriteAfterClose(t *testing.T) {
}
func TestSplitUSTARPath(t *testing.T) {
- var sr = strings.Repeat
+ sr := strings.Repeat
- var vectors = []struct {
+ vectors := []struct {
input string // Input path
prefix string // Expected output prefix
suffix string // Expected output suffix
@@ -609,114 +597,51 @@ func TestSplitUSTARPath(t *testing.T) {
}
}
-func TestFormatPAXRecord(t *testing.T) {
- var medName = strings.Repeat("CD", 50)
- var longName = strings.Repeat("AB", 100)
-
- var vectors = []struct {
- inputKey string
- inputVal string
- output string
- }{
- {"k", "v", "6 k=v\n"},
- {"path", "/etc/hosts", "19 path=/etc/hosts\n"},
- {"path", longName, "210 path=" + longName + "\n"},
- {"path", medName, "110 path=" + medName + "\n"},
- {"foo", "ba", "9 foo=ba\n"},
- {"foo", "bar", "11 foo=bar\n"},
- {"foo", "b=\nar=\n==\x00", "18 foo=b=\nar=\n==\x00\n"},
- {"foo", "hello9 foo=ba\nworld", "27 foo=hello9 foo=ba\nworld\n"},
- {"☺☻☹", "日a本b語ç", "27 ☺☻☹=日a本b語ç\n"},
- {"\x00hello", "\x00world", "17 \x00hello=\x00world\n"},
- }
-
- for _, v := range vectors {
- output := formatPAXRecord(v.inputKey, v.inputVal)
- if output != v.output {
- t.Errorf("formatPAXRecord(%q, %q): got %q, want %q",
- v.inputKey, v.inputVal, output, v.output)
+// TestIssue12594 tests that the Writer does not attempt to populate the prefix
+// field when encoding a header in the GNU format. The prefix field is valid
+// in USTAR and PAX, but not GNU.
+func TestIssue12594(t *testing.T) {
+ names := []string{
+ "0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/file.txt",
+ "0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/file.txt",
+ "0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/333/file.txt",
+ "0/1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36/37/38/39/40/file.txt",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000/file.txt",
+ "/home/support/.openoffice.org/3/user/uno_packages/cache/registry/com.sun.star.comp.deployment.executable.PackageRegistryBackend",
+ }
+
+ for i, name := range names {
+ var b bytes.Buffer
+
+ tw := NewWriter(&b)
+ if err := tw.WriteHeader(&Header{
+ Name: name,
+ Uid: 1 << 25, // Prevent USTAR format
+ }); err != nil {
+ t.Errorf("test %d, unexpected WriteHeader error: %v", i, err)
}
- }
-}
-
-func TestFitsInBase256(t *testing.T) {
- var vectors = []struct {
- input int64
- width int
- ok bool
- }{
- {+1, 8, true},
- {0, 8, true},
- {-1, 8, true},
- {1 << 56, 8, false},
- {(1 << 56) - 1, 8, true},
- {-1 << 56, 8, true},
- {(-1 << 56) - 1, 8, false},
- {121654, 8, true},
- {-9849849, 8, true},
- {math.MaxInt64, 9, true},
- {0, 9, true},
- {math.MinInt64, 9, true},
- {math.MaxInt64, 12, true},
- {0, 12, true},
- {math.MinInt64, 12, true},
- }
-
- for _, v := range vectors {
- ok := fitsInBase256(v.width, v.input)
- if ok != v.ok {
- t.Errorf("checkNumeric(%d, %d): got %v, want %v", v.input, v.width, ok, v.ok)
+ if err := tw.Close(); err != nil {
+ t.Errorf("test %d, unexpected Close error: %v", i, err)
}
- }
-}
-func TestFormatNumeric(t *testing.T) {
- var vectors = []struct {
- input int64
- output string
- ok bool
- }{
- // Test base-256 (binary) encoded values.
- {-1, "\xff", true},
- {-1, "\xff\xff", true},
- {-1, "\xff\xff\xff", true},
- {(1 << 0), "0", false},
- {(1 << 8) - 1, "\x80\xff", true},
- {(1 << 8), "0\x00", false},
- {(1 << 16) - 1, "\x80\xff\xff", true},
- {(1 << 16), "00\x00", false},
- {-1 * (1 << 0), "\xff", true},
- {-1*(1<<0) - 1, "0", false},
- {-1 * (1 << 8), "\xff\x00", true},
- {-1*(1<<8) - 1, "0\x00", false},
- {-1 * (1 << 16), "\xff\x00\x00", true},
- {-1*(1<<16) - 1, "00\x00", false},
- {537795476381659745, "0000000\x00", false},
- {537795476381659745, "\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", true},
- {-615126028225187231, "0000000\x00", false},
- {-615126028225187231, "\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", true},
- {math.MaxInt64, "0000000\x00", false},
- {math.MaxInt64, "\x80\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff", true},
- {math.MinInt64, "0000000\x00", false},
- {math.MinInt64, "\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
- {math.MaxInt64, "\x80\x7f\xff\xff\xff\xff\xff\xff\xff", true},
- {math.MinInt64, "\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
- }
+ // The prefix field should never appear in the GNU format.
+ var blk block
+ copy(blk[:], b.Bytes())
+ prefix := string(blk.USTAR().Prefix())
+ if i := strings.IndexByte(prefix, 0); i >= 0 {
+ prefix = prefix[:i] // Truncate at the NUL terminator
+ }
+ if blk.GetFormat() == formatGNU && len(prefix) > 0 && strings.HasPrefix(name, prefix) {
+ t.Errorf("test %d, found prefix in GNU format: %s", i, prefix)
+ }
- for _, v := range vectors {
- var f formatter
- output := make([]byte, len(v.output))
- f.formatNumeric(output, v.input)
- ok := (f.err == nil)
- if ok != v.ok {
- if v.ok {
- t.Errorf("formatNumeric(%d): got formatting failure, want success", v.input)
- } else {
- t.Errorf("formatNumeric(%d): got formatting success, want failure", v.input)
- }
+ tr := NewReader(&b)
+ hdr, err := tr.Next()
+ if err != nil {
+ t.Errorf("test %d, unexpected Next error: %v", i, err)
}
- if string(output) != v.output {
- t.Errorf("formatNumeric(%d): got %q, want %q", v.input, output, v.output)
+ if hdr.Name != name {
+ t.Errorf("test %d, hdr.Name = %s, want %s", i, hdr.Name, name)
}
}
}
diff --git a/libgo/go/archive/zip/writer.go b/libgo/go/archive/zip/writer.go
index 3a9292e3807..8940e25560e 100644
--- a/libgo/go/archive/zip/writer.go
+++ b/libgo/go/archive/zip/writer.go
@@ -22,6 +22,10 @@ type Writer struct {
last *fileWriter
closed bool
compressors map[uint16]Compressor
+
+ // testHookCloseSizeOffset if non-nil is called with the size
+ // of offset of the central directory at Close.
+ testHookCloseSizeOffset func(size, offset uint64)
}
type header struct {
@@ -98,6 +102,7 @@ func (w *Writer) Close() error {
b.uint32(h.CompressedSize)
b.uint32(h.UncompressedSize)
}
+
b.uint16(uint16(len(h.Name)))
b.uint16(uint16(len(h.Extra)))
b.uint16(uint16(len(h.Comment)))
@@ -127,7 +132,11 @@ func (w *Writer) Close() error {
size := uint64(end - start)
offset := uint64(start)
- if records > uint16max || size > uint32max || offset > uint32max {
+ if f := w.testHookCloseSizeOffset; f != nil {
+ f(size, offset)
+ }
+
+ if records >= uint16max || size >= uint32max || offset >= uint32max {
var buf [directory64EndLen + directory64LocLen]byte
b := writeBuf(buf[:])
diff --git a/libgo/go/archive/zip/zip_test.go b/libgo/go/archive/zip/zip_test.go
index 3a3c915d34e..57edb2cabf4 100644
--- a/libgo/go/archive/zip/zip_test.go
+++ b/libgo/go/archive/zip/zip_test.go
@@ -8,8 +8,10 @@ package zip
import (
"bytes"
+ "errors"
"fmt"
"hash"
+ "internal/race"
"internal/testenv"
"io"
"io/ioutil"
@@ -232,6 +234,7 @@ func TestZip64(t *testing.T) {
if testing.Short() {
t.Skip("slow test; skipping")
}
+ t.Parallel()
const size = 1 << 32 // before the "END\n" part
buf := testZip64(t, size)
testZip64DirectoryRecordLength(buf, t)
@@ -241,6 +244,7 @@ func TestZip64EdgeCase(t *testing.T) {
if testing.Short() {
t.Skip("slow test; skipping")
}
+ t.Parallel()
// Test a zip file with uncompressed size 0xFFFFFFFF.
// That's the magic marker for a 64-bit file, so even though
// it fits in a 32-bit field we must use the 64-bit field.
@@ -251,6 +255,256 @@ func TestZip64EdgeCase(t *testing.T) {
testZip64DirectoryRecordLength(buf, t)
}
+// Tests that we generate a zip64 file if the the directory at offset
+// 0xFFFFFFFF, but not before.
+func TestZip64DirectoryOffset(t *testing.T) {
+ if testing.Short() && race.Enabled {
+ t.Skip("skipping in short mode")
+ }
+ t.Parallel()
+ const filename = "huge.txt"
+ gen := func(wantOff uint64) func(*Writer) {
+ return func(w *Writer) {
+ w.testHookCloseSizeOffset = func(size, off uint64) {
+ if off != wantOff {
+ t.Errorf("central directory offset = %d (%x); want %d", off, off, wantOff)
+ }
+ }
+ f, err := w.CreateHeader(&FileHeader{
+ Name: filename,
+ Method: Store,
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ f.(*fileWriter).crc32 = fakeHash32{}
+ size := wantOff - fileHeaderLen - uint64(len(filename)) - dataDescriptorLen
+ if _, err := io.CopyN(f, zeros{}, int64(size)); err != nil {
+ t.Fatal(err)
+ }
+ if err := w.Close(); err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+ t.Run("uint32max-2_NoZip64", func(t *testing.T) {
+ t.Parallel()
+ if generatesZip64(t, gen(0xfffffffe)) {
+ t.Error("unexpected zip64")
+ }
+ })
+ t.Run("uint32max-1_Zip64", func(t *testing.T) {
+ t.Parallel()
+ if !generatesZip64(t, gen(0xffffffff)) {
+ t.Error("expected zip64")
+ }
+ })
+}
+
+// At 16k records, we need to generate a zip64 file.
+func TestZip64ManyRecords(t *testing.T) {
+ if testing.Short() && race.Enabled {
+ t.Skip("skipping in short mode")
+ }
+ t.Parallel()
+ gen := func(numRec int) func(*Writer) {
+ return func(w *Writer) {
+ for i := 0; i < numRec; i++ {
+ _, err := w.CreateHeader(&FileHeader{
+ Name: "a.txt",
+ Method: Store,
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ if err := w.Close(); err != nil {
+ t.Fatal(err)
+ }
+ }
+ }
+ // 16k-1 records shouldn't make a zip64:
+ t.Run("uint16max-1_NoZip64", func(t *testing.T) {
+ t.Parallel()
+ if generatesZip64(t, gen(0xfffe)) {
+ t.Error("unexpected zip64")
+ }
+ })
+ // 16k records should make a zip64:
+ t.Run("uint16max_Zip64", func(t *testing.T) {
+ t.Parallel()
+ if !generatesZip64(t, gen(0xffff)) {
+ t.Error("expected zip64")
+ }
+ })
+}
+
+// suffixSaver is an io.Writer & io.ReaderAt that remembers the last 0
+// to 'keep' bytes of data written to it. Call Suffix to get the
+// suffix bytes.
+type suffixSaver struct {
+ keep int
+ buf []byte
+ start int
+ size int64
+}
+
+func (ss *suffixSaver) Size() int64 { return ss.size }
+
+var errDiscardedBytes = errors.New("ReadAt of discarded bytes")
+
+func (ss *suffixSaver) ReadAt(p []byte, off int64) (n int, err error) {
+ back := ss.size - off
+ if back > int64(ss.keep) {
+ return 0, errDiscardedBytes
+ }
+ suf := ss.Suffix()
+ n = copy(p, suf[len(suf)-int(back):])
+ if n != len(p) {
+ err = io.EOF
+ }
+ return
+}
+
+func (ss *suffixSaver) Suffix() []byte {
+ if len(ss.buf) < ss.keep {
+ return ss.buf
+ }
+ buf := make([]byte, ss.keep)
+ n := copy(buf, ss.buf[ss.start:])
+ copy(buf[n:], ss.buf[:])
+ return buf
+}
+
+func (ss *suffixSaver) Write(p []byte) (n int, err error) {
+ n = len(p)
+ ss.size += int64(len(p))
+ if len(ss.buf) < ss.keep {
+ space := ss.keep - len(ss.buf)
+ add := len(p)
+ if add > space {
+ add = space
+ }
+ ss.buf = append(ss.buf, p[:add]...)
+ p = p[add:]
+ }
+ for len(p) > 0 {
+ n := copy(ss.buf[ss.start:], p)
+ p = p[n:]
+ ss.start += n
+ if ss.start == ss.keep {
+ ss.start = 0
+ }
+ }
+ return
+}
+
+// generatesZip64 reports whether f wrote a zip64 file.
+// f is also responsible for closing w.
+func generatesZip64(t *testing.T, f func(w *Writer)) bool {
+ ss := &suffixSaver{keep: 10 << 20}
+ w := NewWriter(ss)
+ f(w)
+ return suffixIsZip64(t, ss)
+}
+
+type sizedReaderAt interface {
+ io.ReaderAt
+ Size() int64
+}
+
+func suffixIsZip64(t *testing.T, zip sizedReaderAt) bool {
+ d := make([]byte, 1024)
+ if _, err := zip.ReadAt(d, zip.Size()-int64(len(d))); err != nil {
+ t.Fatalf("ReadAt: %v", err)
+ }
+
+ sigOff := findSignatureInBlock(d)
+ if sigOff == -1 {
+ t.Errorf("failed to find signature in block")
+ return false
+ }
+
+ dirOff, err := findDirectory64End(zip, zip.Size()-int64(len(d))+int64(sigOff))
+ if err != nil {
+ t.Fatalf("findDirectory64End: %v", err)
+ }
+ if dirOff == -1 {
+ return false
+ }
+
+ d = make([]byte, directory64EndLen)
+ if _, err := zip.ReadAt(d, dirOff); err != nil {
+ t.Fatalf("ReadAt(off=%d): %v", dirOff, err)
+ }
+
+ b := readBuf(d)
+ if sig := b.uint32(); sig != directory64EndSignature {
+ return false
+ }
+
+ size := b.uint64()
+ if size != directory64EndLen-12 {
+ t.Errorf("expected length of %d, got %d", directory64EndLen-12, size)
+ }
+ return true
+}
+
+// Zip64 is required if the total size of the records is uint32max.
+func TestZip64LargeDirectory(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in short mode")
+ }
+ t.Parallel()
+ // gen returns a func that writes a zip with a wantLen bytes
+ // of central directory.
+ gen := func(wantLen int64) func(*Writer) {
+ return func(w *Writer) {
+ w.testHookCloseSizeOffset = func(size, off uint64) {
+ if size != uint64(wantLen) {
+ t.Errorf("Close central directory size = %d; want %d", size, wantLen)
+ }
+ }
+
+ uint16string := strings.Repeat(".", uint16max)
+ remain := wantLen
+ for remain > 0 {
+ commentLen := int(uint16max) - directoryHeaderLen - 1
+ thisRecLen := directoryHeaderLen + int(uint16max) + commentLen
+ if int64(thisRecLen) > remain {
+ remove := thisRecLen - int(remain)
+ commentLen -= remove
+ thisRecLen -= remove
+ }
+ remain -= int64(thisRecLen)
+ f, err := w.CreateHeader(&FileHeader{
+ Name: uint16string,
+ Comment: uint16string[:commentLen],
+ })
+ if err != nil {
+ t.Fatalf("CreateHeader: %v", err)
+ }
+ f.(*fileWriter).crc32 = fakeHash32{}
+ }
+ if err := w.Close(); err != nil {
+ t.Fatalf("Close: %v", err)
+ }
+ }
+ }
+ t.Run("uint32max-1_NoZip64", func(t *testing.T) {
+ t.Parallel()
+ if generatesZip64(t, gen(uint32max-1)) {
+ t.Error("unexpected zip64")
+ }
+ })
+ t.Run("uint32max_HasZip64", func(t *testing.T) {
+ t.Parallel()
+ if !generatesZip64(t, gen(uint32max)) {
+ t.Error("expected zip64")
+ }
+ })
+}
+
func testZip64(t testing.TB, size int64) *rleBuffer {
const chunkSize = 1024
chunks := int(size / chunkSize)
@@ -339,30 +593,8 @@ func testZip64(t testing.TB, size int64) *rleBuffer {
// Issue 9857
func testZip64DirectoryRecordLength(buf *rleBuffer, t *testing.T) {
- d := make([]byte, 1024)
- if _, err := buf.ReadAt(d, buf.Size()-int64(len(d))); err != nil {
- t.Fatal("read:", err)
- }
-
- sigOff := findSignatureInBlock(d)
- dirOff, err := findDirectory64End(buf, buf.Size()-int64(len(d))+int64(sigOff))
- if err != nil {
- t.Fatal("findDirectory64End:", err)
- }
-
- d = make([]byte, directory64EndLen)
- if _, err := buf.ReadAt(d, dirOff); err != nil {
- t.Fatal("read:", err)
- }
-
- b := readBuf(d)
- if sig := b.uint32(); sig != directory64EndSignature {
- t.Fatalf("Expected directory64EndSignature (%d), got %d", directory64EndSignature, sig)
- }
-
- size := b.uint64()
- if size != directory64EndLen-12 {
- t.Fatalf("Expected length of %d, got %d", directory64EndLen-12, size)
+ if !suffixIsZip64(t, buf) {
+ t.Fatal("not a zip64")
}
}
@@ -448,3 +680,47 @@ func BenchmarkZip64Test(b *testing.B) {
testZip64(b, 1<<26)
}
}
+
+func TestSuffixSaver(t *testing.T) {
+ const keep = 10
+ ss := &suffixSaver{keep: keep}
+ ss.Write([]byte("abc"))
+ if got := string(ss.Suffix()); got != "abc" {
+ t.Errorf("got = %q; want abc", got)
+ }
+ ss.Write([]byte("defghijklmno"))
+ if got := string(ss.Suffix()); got != "fghijklmno" {
+ t.Errorf("got = %q; want fghijklmno", got)
+ }
+ if got, want := ss.Size(), int64(len("abc")+len("defghijklmno")); got != want {
+ t.Errorf("Size = %d; want %d", got, want)
+ }
+ buf := make([]byte, ss.Size())
+ for off := int64(0); off < ss.Size(); off++ {
+ for size := 1; size <= int(ss.Size()-off); size++ {
+ readBuf := buf[:size]
+ n, err := ss.ReadAt(readBuf, off)
+ if off < ss.Size()-keep {
+ if err != errDiscardedBytes {
+ t.Errorf("off %d, size %d = %v, %v (%q); want errDiscardedBytes", off, size, n, err, readBuf[:n])
+ }
+ continue
+ }
+ want := "abcdefghijklmno"[off : off+int64(size)]
+ got := string(readBuf[:n])
+ if err != nil || got != want {
+ t.Errorf("off %d, size %d = %v, %v (%q); want %q", off, size, n, err, got, want)
+ }
+ }
+ }
+
+}
+
+type zeros struct{}
+
+func (zeros) Read(p []byte) (int, error) {
+ for i := range p {
+ p[i] = 0
+ }
+ return len(p), nil
+}
diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go
index 3b30b8b80cd..e1e8fb22720 100644
--- a/libgo/go/bufio/bufio.go
+++ b/libgo/go/bufio/bufio.go
@@ -206,10 +206,18 @@ func (b *Reader) Read(p []byte) (n int, err error) {
}
return n, b.readErr()
}
- b.fill() // buffer is empty
- if b.r == b.w {
+ // One read.
+ // Do not use b.fill, which will loop.
+ b.r = 0
+ b.w = 0
+ n, b.err = b.rd.Read(b.buf)
+ if n < 0 {
+ panic(errNegativeRead)
+ }
+ if n == 0 {
return 0, b.readErr()
}
+ b.w += n
}
// copy as much as we can
@@ -549,11 +557,6 @@ func (b *Writer) Reset(w io.Writer) {
// Flush writes any buffered data to the underlying io.Writer.
func (b *Writer) Flush() error {
- err := b.flush()
- return err
-}
-
-func (b *Writer) flush() error {
if b.err != nil {
return b.err
}
@@ -596,7 +599,7 @@ func (b *Writer) Write(p []byte) (nn int, err error) {
} else {
n = copy(b.buf[b.n:], p)
b.n += n
- b.flush()
+ b.Flush()
}
nn += n
p = p[n:]
@@ -615,7 +618,7 @@ func (b *Writer) WriteByte(c byte) error {
if b.err != nil {
return b.err
}
- if b.Available() <= 0 && b.flush() != nil {
+ if b.Available() <= 0 && b.Flush() != nil {
return b.err
}
b.buf[b.n] = c
@@ -638,7 +641,7 @@ func (b *Writer) WriteRune(r rune) (size int, err error) {
}
n := b.Available()
if n < utf8.UTFMax {
- if b.flush(); b.err != nil {
+ if b.Flush(); b.err != nil {
return 0, b.err
}
n = b.Available()
@@ -663,7 +666,7 @@ func (b *Writer) WriteString(s string) (int, error) {
b.n += n
nn += n
s = s[n:]
- b.flush()
+ b.Flush()
}
if b.err != nil {
return nn, b.err
@@ -684,7 +687,7 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
var m int
for {
if b.Available() == 0 {
- if err1 := b.flush(); err1 != nil {
+ if err1 := b.Flush(); err1 != nil {
return n, err1
}
}
@@ -708,7 +711,7 @@ func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) {
if err == io.EOF {
// If we filled the buffer exactly, flush preemptively.
if b.Available() == 0 {
- err = b.flush()
+ err = b.Flush()
} else {
err = nil
}
diff --git a/libgo/go/bufio/bufio_test.go b/libgo/go/bufio/bufio_test.go
index 858048696e4..ef0f6c834e8 100644
--- a/libgo/go/bufio/bufio_test.go
+++ b/libgo/go/bufio/bufio_test.go
@@ -1236,6 +1236,27 @@ func TestWriterReadFromErrNoProgress(t *testing.T) {
}
}
+func TestReadZero(t *testing.T) {
+ for _, size := range []int{100, 2} {
+ t.Run(fmt.Sprintf("bufsize=%d", size), func(t *testing.T) {
+ r := io.MultiReader(strings.NewReader("abc"), &emptyThenNonEmptyReader{r: strings.NewReader("def"), n: 1})
+ br := NewReaderSize(r, size)
+ want := func(s string, wantErr error) {
+ p := make([]byte, 50)
+ n, err := br.Read(p)
+ if err != wantErr || n != len(s) || string(p[:n]) != s {
+ t.Fatalf("read(%d) = %q, %v, want %q, %v", len(p), string(p[:n]), err, s, wantErr)
+ }
+ t.Logf("read(%d) = %q, %v", len(p), string(p[:n]), err)
+ }
+ want("abc", nil)
+ want("", nil)
+ want("def", nil)
+ want("", io.EOF)
+ })
+ }
+}
+
func TestReaderReset(t *testing.T) {
r := NewReader(strings.NewReader("foo foo"))
buf := make([]byte, 3)
diff --git a/libgo/go/bufio/scan.go b/libgo/go/bufio/scan.go
index 27a0f004595..9f741c98307 100644
--- a/libgo/go/bufio/scan.go
+++ b/libgo/go/bufio/scan.go
@@ -199,7 +199,6 @@ func (s *Scanner) Scan() bool {
s.buf = newBuf
s.end -= s.start
s.start = 0
- continue
}
// Finally we can read some input. Make sure we don't get stuck with
// a misbehaving Reader. Officially we don't need to do this, but let's
diff --git a/libgo/go/builtin/builtin.go b/libgo/go/builtin/builtin.go
index d63ad22c32d..281de0b4368 100644
--- a/libgo/go/builtin/builtin.go
+++ b/libgo/go/builtin/builtin.go
@@ -173,8 +173,8 @@ func cap(v Type) int
// specify a different capacity; it must be no smaller than the
// length, so make([]int, 0, 10) allocates a slice of length 0 and
// capacity 10.
-// Map: An initial allocation is made according to the size but the
-// resulting map has length 0. The size may be omitted, in which case
+// Map: An empty map is allocated with enough space to hold the
+// specified number of elements. The size may be omitted, in which case
// a small starting size is allocated.
// Channel: The channel's buffer is initialized with the specified
// buffer capacity. If zero, or the size is omitted, the channel is
diff --git a/libgo/go/bytes/buffer.go b/libgo/go/bytes/buffer.go
index 9154a1b9545..196419dc3da 100644
--- a/libgo/go/bytes/buffer.go
+++ b/libgo/go/bytes/buffer.go
@@ -15,22 +15,25 @@ import (
// A Buffer is a variable-sized buffer of bytes with Read and Write methods.
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
- buf []byte // contents are the bytes buf[off : len(buf)]
- off int // read at &buf[off], write at &buf[len(buf)]
- runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each call to WriteRune
- bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
- lastRead readOp // last read operation, so that Unread* can work correctly.
+ buf []byte // contents are the bytes buf[off : len(buf)]
+ off int // read at &buf[off], write at &buf[len(buf)]
+ bootstrap [64]byte // memory to hold first slice; helps small buffers avoid allocation.
+ lastRead readOp // last read operation, so that Unread* can work correctly.
}
// The readOp constants describe the last action performed on
-// the buffer, so that UnreadRune and UnreadByte can
-// check for invalid usage.
+// the buffer, so that UnreadRune and UnreadByte can check for
+// invalid usage. opReadRuneX constants are chosen such that
+// converted to int they correspond to the rune size that was read.
type readOp int
const (
- opInvalid readOp = iota // Non-read operation.
- opReadRune // Read rune.
- opRead // Any other read operation.
+ opRead readOp = -1 // Any other read operation.
+ opInvalid = 0 // Non-read operation.
+ opReadRune1 = 1 // Read rune of size 1.
+ opReadRune2 = 2 // Read rune of size 2.
+ opReadRune3 = 3 // Read rune of size 3.
+ opReadRune4 = 4 // Read rune of size 4.
)
// ErrTooLarge is passed to panic if memory cannot be allocated to store data in a buffer.
@@ -246,8 +249,10 @@ func (b *Buffer) WriteRune(r rune) (n int, err error) {
b.WriteByte(byte(r))
return 1, nil
}
- n = utf8.EncodeRune(b.runeBytes[0:], r)
- b.Write(b.runeBytes[0:n])
+ b.lastRead = opInvalid
+ m := b.grow(utf8.UTFMax)
+ n = utf8.EncodeRune(b.buf[m:m+utf8.UTFMax], r)
+ b.buf = b.buf[:m+n]
return n, nil
}
@@ -318,14 +323,15 @@ func (b *Buffer) ReadRune() (r rune, size int, err error) {
b.Truncate(0)
return 0, 0, io.EOF
}
- b.lastRead = opReadRune
c := b.buf[b.off]
if c < utf8.RuneSelf {
b.off++
+ b.lastRead = opReadRune1
return rune(c), 1, nil
}
r, n := utf8.DecodeRune(b.buf[b.off:])
b.off += n
+ b.lastRead = readOp(n)
return r, n, nil
}
@@ -335,14 +341,13 @@ func (b *Buffer) ReadRune() (r rune, size int, err error) {
// it is stricter than UnreadByte, which will unread the last byte
// from any read operation.)
func (b *Buffer) UnreadRune() error {
- if b.lastRead != opReadRune {
+ if b.lastRead <= opInvalid {
return errors.New("bytes.Buffer: UnreadRune: previous operation was not ReadRune")
}
- b.lastRead = opInvalid
- if b.off > 0 {
- _, n := utf8.DecodeLastRune(b.buf[0:b.off])
- b.off -= n
+ if b.off >= int(b.lastRead) {
+ b.off -= int(b.lastRead)
}
+ b.lastRead = opInvalid
return nil
}
@@ -350,7 +355,7 @@ func (b *Buffer) UnreadRune() error {
// read operation. If write has happened since the last read, UnreadByte
// returns an error.
func (b *Buffer) UnreadByte() error {
- if b.lastRead != opReadRune && b.lastRead != opRead {
+ if b.lastRead == opInvalid {
return errors.New("bytes.Buffer: UnreadByte: previous operation was not a read")
}
b.lastRead = opInvalid
diff --git a/libgo/go/bytes/buffer_test.go b/libgo/go/bytes/buffer_test.go
index 7de17ae47e2..b1b85f979af 100644
--- a/libgo/go/bytes/buffer_test.go
+++ b/libgo/go/bytes/buffer_test.go
@@ -514,6 +514,19 @@ func TestBufferGrowth(t *testing.T) {
}
}
+func BenchmarkWriteRune(b *testing.B) {
+ const n = 4 << 10
+ const r = '☺'
+ b.SetBytes(int64(n * utf8.RuneLen(r)))
+ buf := NewBuffer(make([]byte, n*utf8.UTFMax))
+ for i := 0; i < b.N; i++ {
+ buf.Reset()
+ for i := 0; i < n; i++ {
+ buf.WriteRune(r)
+ }
+ }
+}
+
// From Issue 5154.
func BenchmarkBufferNotEmptyWriteRead(b *testing.B) {
buf := make([]byte, 1024)
diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go
index 305c85d9f41..406a38257a7 100644
--- a/libgo/go/bytes/bytes.go
+++ b/libgo/go/bytes/bytes.go
@@ -93,37 +93,6 @@ func ContainsRune(b []byte, r rune) bool {
return IndexRune(b, r) >= 0
}
-// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
-func Index(s, sep []byte) int {
- n := len(sep)
- if n == 0 {
- return 0
- }
- if n > len(s) {
- return -1
- }
- c := sep[0]
- if n == 1 {
- return IndexByte(s, c)
- }
- i := 0
- t := s[:len(s)-n+1]
- for i < len(t) {
- if t[i] != c {
- o := IndexByte(t[i:], c)
- if o < 0 {
- break
- }
- i += o
- }
- if Equal(s[i:i+n], sep) {
- return i
- }
- i++
- }
- return -1
-}
-
func indexBytePortable(s []byte, c byte) int {
for i, b := range s {
if b == c {
@@ -161,15 +130,28 @@ func LastIndexByte(s []byte, c byte) int {
// IndexRune interprets s as a sequence of UTF-8-encoded Unicode code points.
// It returns the byte index of the first occurrence in s of the given rune.
// It returns -1 if rune is not present in s.
+// If r is utf8.RuneError, it returns the first instance of any
+// invalid UTF-8 byte sequence.
func IndexRune(s []byte, r rune) int {
- for i := 0; i < len(s); {
- r1, size := utf8.DecodeRune(s[i:])
- if r == r1 {
- return i
+ switch {
+ case 0 <= r && r < utf8.RuneSelf:
+ return IndexByte(s, byte(r))
+ case r == utf8.RuneError:
+ for i := 0; i < len(s); {
+ r1, n := utf8.DecodeRune(s[i:])
+ if r1 == utf8.RuneError {
+ return i
+ }
+ i += n
}
- i += size
+ return -1
+ case !utf8.ValidRune(r):
+ return -1
+ default:
+ var b [utf8.UTFMax]byte
+ n := utf8.EncodeRune(b[:], r)
+ return Index(s, b[:n])
}
- return -1
}
// IndexAny interprets s as a sequence of UTF-8-encoded Unicode code points.
@@ -178,10 +160,19 @@ func IndexRune(s []byte, r rune) int {
// point in common.
func IndexAny(s []byte, chars string) int {
if len(chars) > 0 {
- var r rune
+ if len(s) > 8 {
+ if as, isASCII := makeASCIISet(chars); isASCII {
+ for i, c := range s {
+ if as.contains(c) {
+ return i
+ }
+ }
+ return -1
+ }
+ }
var width int
for i := 0; i < len(s); i += width {
- r = rune(s[i])
+ r := rune(s[i])
if r < utf8.RuneSelf {
width = 1
} else {
@@ -203,11 +194,21 @@ func IndexAny(s []byte, chars string) int {
// there is no code point in common.
func LastIndexAny(s []byte, chars string) int {
if len(chars) > 0 {
+ if len(s) > 8 {
+ if as, isASCII := makeASCIISet(chars); isASCII {
+ for i := len(s) - 1; i >= 0; i-- {
+ if as.contains(s[i]) {
+ return i
+ }
+ }
+ return -1
+ }
+ }
for i := len(s); i > 0; {
- r, size := utf8.DecodeLastRune(s[0:i])
+ r, size := utf8.DecodeLastRune(s[:i])
i -= size
- for _, ch := range chars {
- if r == ch {
+ for _, c := range chars {
+ if r == c {
return i
}
}
@@ -398,7 +399,20 @@ func Map(mapping func(r rune) rune, s []byte) []byte {
}
// Repeat returns a new byte slice consisting of count copies of b.
+//
+// It panics if count is negative or if
+// the result of (len(b) * count) overflows.
func Repeat(b []byte, count int) []byte {
+ // Since we cannot return an error on overflow,
+ // we should panic if the repeat will generate
+ // an overflow.
+ // See Issue golang.org/issue/16237.
+ if count < 0 {
+ panic("bytes: negative Repeat count")
+ } else if count > 0 && len(b)*count/count != len(b) {
+ panic("bytes: Repeat count causes overflow")
+ }
+
nb := make([]byte, len(b)*count)
bp := copy(nb, b)
for bp < len(nb) {
@@ -419,20 +433,20 @@ func ToTitle(s []byte) []byte { return Map(unicode.ToTitle, s) }
// ToUpperSpecial returns a copy of the byte slice s with all Unicode letters mapped to their
// upper case, giving priority to the special casing rules.
-func ToUpperSpecial(_case unicode.SpecialCase, s []byte) []byte {
- return Map(func(r rune) rune { return _case.ToUpper(r) }, s)
+func ToUpperSpecial(c unicode.SpecialCase, s []byte) []byte {
+ return Map(func(r rune) rune { return c.ToUpper(r) }, s)
}
// ToLowerSpecial returns a copy of the byte slice s with all Unicode letters mapped to their
// lower case, giving priority to the special casing rules.
-func ToLowerSpecial(_case unicode.SpecialCase, s []byte) []byte {
- return Map(func(r rune) rune { return _case.ToLower(r) }, s)
+func ToLowerSpecial(c unicode.SpecialCase, s []byte) []byte {
+ return Map(func(r rune) rune { return c.ToLower(r) }, s)
}
// ToTitleSpecial returns a copy of the byte slice s with all Unicode letters mapped to their
// title case, giving priority to the special casing rules.
-func ToTitleSpecial(_case unicode.SpecialCase, s []byte) []byte {
- return Map(func(r rune) rune { return _case.ToTitle(r) }, s)
+func ToTitleSpecial(c unicode.SpecialCase, s []byte) []byte {
+ return Map(func(r rune) rune { return c.ToTitle(r) }, s)
}
// isSeparator reports whether the rune could mark a word boundary.
@@ -578,7 +592,43 @@ func lastIndexFunc(s []byte, f func(r rune) bool, truth bool) int {
return -1
}
+// asciiSet is a 32-byte value, where each bit represents the presence of a
+// given ASCII character in the set. The 128-bits of the lower 16 bytes,
+// starting with the least-significant bit of the lowest word to the
+// most-significant bit of the highest word, map to the full range of all
+// 128 ASCII characters. The 128-bits of the upper 16 bytes will be zeroed,
+// ensuring that any non-ASCII character will be reported as not in the set.
+type asciiSet [8]uint32
+
+// makeASCIISet creates a set of ASCII characters and reports whether all
+// characters in chars are ASCII.
+func makeASCIISet(chars string) (as asciiSet, ok bool) {
+ for i := 0; i < len(chars); i++ {
+ c := chars[i]
+ if c >= utf8.RuneSelf {
+ return as, false
+ }
+ as[c>>5] |= 1 << uint(c&31)
+ }
+ return as, true
+}
+
+// contains reports whether c is inside the set.
+func (as *asciiSet) contains(c byte) bool {
+ return (as[c>>5] & (1 << uint(c&31))) != 0
+}
+
func makeCutsetFunc(cutset string) func(r rune) bool {
+ if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
+ return func(r rune) bool {
+ return r == rune(cutset[0])
+ }
+ }
+ if as, isASCII := makeASCIISet(cutset); isASCII {
+ return func(r rune) bool {
+ return r < utf8.RuneSelf && as.contains(byte(r))
+ }
+ }
return func(r rune) bool {
for _, c := range cutset {
if c == r {
diff --git a/libgo/go/bytes/bytes_amd64.go b/libgo/go/bytes/bytes_amd64.go
new file mode 100644
index 00000000000..58a07efc58f
--- /dev/null
+++ b/libgo/go/bytes/bytes_amd64.go
@@ -0,0 +1,117 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package bytes
+
+//go:noescape
+
+// indexShortStr returns the index of the first instance of c in s, or -1 if c is not present in s.
+// indexShortStr requires 2 <= len(c) <= shortStringLen
+func indexShortStr(s, c []byte) int // ../runtime/asm_$GOARCH.s
+func supportAVX2() bool // ../runtime/asm_$GOARCH.s
+
+var shortStringLen int
+
+func init() {
+ if supportAVX2() {
+ shortStringLen = 63
+ } else {
+ shortStringLen = 31
+ }
+}
+
+// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
+func Index(s, sep []byte) int {
+ n := len(sep)
+ switch {
+ case n == 0:
+ return 0
+ case n == 1:
+ return IndexByte(s, sep[0])
+ case n == len(s):
+ if Equal(sep, s) {
+ return 0
+ }
+ return -1
+ case n > len(s):
+ return -1
+ case n <= shortStringLen:
+ // Use brute force when s and sep both are small
+ if len(s) <= 64 {
+ return indexShortStr(s, sep)
+ }
+ c := sep[0]
+ i := 0
+ t := s[:len(s)-n+1]
+ fails := 0
+ for i < len(t) {
+ if t[i] != c {
+ // IndexByte skips 16/32 bytes per iteration,
+ // so it's faster than indexShortStr.
+ o := IndexByte(t[i:], c)
+ if o < 0 {
+ return -1
+ }
+ i += o
+ }
+ if Equal(s[i:i+n], sep) {
+ return i
+ }
+ fails++
+ i++
+ // Switch to indexShortStr when IndexByte produces too many false positives.
+ // Too many means more that 1 error per 8 characters.
+ // Allow some errors in the beginning.
+ if fails > (i+16)/8 {
+ r := indexShortStr(s[i:], sep)
+ if r >= 0 {
+ return r + i
+ }
+ return -1
+ }
+ }
+ return -1
+ }
+ // Rabin-Karp search
+ hashsep, pow := hashStr(sep)
+ var h uint32
+ for i := 0; i < n; i++ {
+ h = h*primeRK + uint32(s[i])
+ }
+ if h == hashsep && Equal(s[:n], sep) {
+ return 0
+ }
+ for i := n; i < len(s); {
+ h *= primeRK
+ h += uint32(s[i])
+ h -= pow * uint32(s[i-n])
+ i++
+ if h == hashsep && Equal(s[i-n:i], sep) {
+ return i - n
+ }
+ }
+ return -1
+}
+
+// primeRK is the prime base used in Rabin-Karp algorithm.
+const primeRK = 16777619
+
+// hashStr returns the hash and the appropriate multiplicative
+// factor for use in Rabin-Karp algorithm.
+func hashStr(sep []byte) (uint32, uint32) {
+ hash := uint32(0)
+ for i := 0; i < len(sep); i++ {
+ hash = hash*primeRK + uint32(sep[i])
+ }
+ var pow, sq uint32 = 1, primeRK
+ for i := len(sep); i > 0; i >>= 1 {
+ if i&1 != 0 {
+ pow *= sq
+ }
+ sq *= sq
+ }
+ return hash, pow
+}
diff --git a/libgo/go/bytes/bytes_generic.go b/libgo/go/bytes/bytes_generic.go
new file mode 100644
index 00000000000..91baa22aa23
--- /dev/null
+++ b/libgo/go/bytes/bytes_generic.go
@@ -0,0 +1,41 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// -build !amd64,!s390x
+
+package bytes
+
+// TODO: implements short string optimization on non amd64 platforms
+// and get rid of bytes_amd64.go
+
+// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
+func Index(s, sep []byte) int {
+ n := len(sep)
+ if n == 0 {
+ return 0
+ }
+ if n > len(s) {
+ return -1
+ }
+ c := sep[0]
+ if n == 1 {
+ return IndexByte(s, c)
+ }
+ i := 0
+ t := s[:len(s)-n+1]
+ for i < len(t) {
+ if t[i] != c {
+ o := IndexByte(t[i:], c)
+ if o < 0 {
+ break
+ }
+ i += o
+ }
+ if Equal(s[i:i+n], sep) {
+ return i
+ }
+ i++
+ }
+ return -1
+}
diff --git a/libgo/go/bytes/bytes_s390x.go b/libgo/go/bytes/bytes_s390x.go
new file mode 100644
index 00000000000..a05ca47aa16
--- /dev/null
+++ b/libgo/go/bytes/bytes_s390x.go
@@ -0,0 +1,120 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package bytes
+
+//go:noescape
+
+// indexShortStr returns the index of the first instance of sep in s,
+// or -1 if sep is not present in s.
+// indexShortStr requires 2 <= len(sep) <= shortStringLen
+func indexShortStr(s, c []byte) int // ../runtime/asm_s390x.s
+
+// supportsVX reports whether the vector facility is available.
+// indexShortStr must not be called if the vector facility is not
+// available.
+func supportsVX() bool // ../runtime/asm_s390x.s
+
+var shortStringLen = -1
+
+func init() {
+ if supportsVX() {
+ shortStringLen = 64
+ }
+}
+
+// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
+func Index(s, sep []byte) int {
+ n := len(sep)
+ switch {
+ case n == 0:
+ return 0
+ case n == 1:
+ return IndexByte(s, sep[0])
+ case n == len(s):
+ if Equal(sep, s) {
+ return 0
+ }
+ return -1
+ case n > len(s):
+ return -1
+ case n <= shortStringLen:
+ // Use brute force when s and sep both are small
+ if len(s) <= 64 {
+ return indexShortStr(s, sep)
+ }
+ c := sep[0]
+ i := 0
+ t := s[:len(s)-n+1]
+ fails := 0
+ for i < len(t) {
+ if t[i] != c {
+ // IndexByte skips 16/32 bytes per iteration,
+ // so it's faster than indexShortStr.
+ o := IndexByte(t[i:], c)
+ if o < 0 {
+ return -1
+ }
+ i += o
+ }
+ if Equal(s[i:i+n], sep) {
+ return i
+ }
+ fails++
+ i++
+ // Switch to indexShortStr when IndexByte produces too many false positives.
+ // Too many means more that 1 error per 8 characters.
+ // Allow some errors in the beginning.
+ if fails > (i+16)/8 {
+ r := indexShortStr(s[i:], sep)
+ if r >= 0 {
+ return r + i
+ }
+ return -1
+ }
+ }
+ return -1
+ }
+ // Rabin-Karp search
+ hashsep, pow := hashStr(sep)
+ var h uint32
+ for i := 0; i < n; i++ {
+ h = h*primeRK + uint32(s[i])
+ }
+ if h == hashsep && Equal(s[:n], sep) {
+ return 0
+ }
+ for i := n; i < len(s); {
+ h *= primeRK
+ h += uint32(s[i])
+ h -= pow * uint32(s[i-n])
+ i++
+ if h == hashsep && Equal(s[i-n:i], sep) {
+ return i - n
+ }
+ }
+ return -1
+}
+
+// primeRK is the prime base used in Rabin-Karp algorithm.
+const primeRK = 16777619
+
+// hashStr returns the hash and the appropriate multiplicative
+// factor for use in Rabin-Karp algorithm.
+func hashStr(sep []byte) (uint32, uint32) {
+ hash := uint32(0)
+ for i := 0; i < len(sep); i++ {
+ hash = hash*primeRK + uint32(sep[i])
+ }
+ var pow, sq uint32 = 1, primeRK
+ for i := len(sep); i > 0; i >>= 1 {
+ if i&1 != 0 {
+ pow *= sq
+ }
+ sq *= sq
+ }
+ return hash, pow
+}
diff --git a/libgo/go/bytes/bytes_test.go b/libgo/go/bytes/bytes_test.go
index c48f662e10d..26eac5e08c6 100644
--- a/libgo/go/bytes/bytes_test.go
+++ b/libgo/go/bytes/bytes_test.go
@@ -7,8 +7,10 @@ package bytes_test
import (
. "bytes"
"fmt"
+ "internal/testenv"
"math/rand"
"reflect"
+ "strings"
"testing"
"unicode"
"unicode/utf8"
@@ -165,8 +167,12 @@ var indexAnyTests = []BinOpTest{
{"abc", "xyz", -1},
{"abc", "xcz", 2},
{"ab☺c", "x☺yz", 2},
+ {"a☺b☻c☹d", "cx", len("a☺b☻")},
+ {"a☺b☻c☹d", "uvw☻xyz", len("a☺b")},
{"aRegExp*", ".(|)*+?^$[]", 7},
{dots + dots + dots, " ", -1},
+ {"012abcba210", "\xffb", 4},
+ {"012\x80bcb\x80210", "\xffb", 3},
}
var lastIndexAnyTests = []BinOpTest{
@@ -178,18 +184,13 @@ var lastIndexAnyTests = []BinOpTest{
{"aaa", "a", 2},
{"abc", "xyz", -1},
{"abc", "ab", 1},
- {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
+ {"ab☺c", "x☺yz", 2},
+ {"a☺b☻c☹d", "cx", len("a☺b☻")},
+ {"a☺b☻c☹d", "uvw☻xyz", len("a☺b")},
{"a.RegExp*", ".(|)*+?^$[]", 8},
{dots + dots + dots, " ", -1},
-}
-
-var indexRuneTests = []BinOpTest{
- {"", "a", -1},
- {"", "☺", -1},
- {"foo", "☹", -1},
- {"foo", "o", 1},
- {"foo☺bar", "☺", 3},
- {"foo☺☻☹bar", "☹", 9},
+ {"012abcba210", "\xffb", 6},
+ {"012\x80bcb\x80210", "\xffb", 7},
}
// Execute f on each test case. funcName should be the name of f; it's used
@@ -346,13 +347,52 @@ func TestIndexByteSmall(t *testing.T) {
}
func TestIndexRune(t *testing.T) {
- for _, tt := range indexRuneTests {
- a := []byte(tt.a)
- r, _ := utf8.DecodeRuneInString(tt.b)
- pos := IndexRune(a, r)
- if pos != tt.i {
- t.Errorf(`IndexRune(%q, '%c') = %v`, tt.a, r, pos)
+ tests := []struct {
+ in string
+ rune rune
+ want int
+ }{
+ {"", 'a', -1},
+ {"", '☺', -1},
+ {"foo", '☹', -1},
+ {"foo", 'o', 1},
+ {"foo☺bar", '☺', 3},
+ {"foo☺☻☹bar", '☹', 9},
+ {"a A x", 'A', 2},
+ {"some_text=some_value", '=', 9},
+ {"☺a", 'a', 3},
+ {"a☻☺b", '☺', 4},
+
+ // RuneError should match any invalid UTF-8 byte sequence.
+ {"�", '�', 0},
+ {"\xff", '�', 0},
+ {"☻x�", '�', len("☻x")},
+ {"☻x\xe2\x98", '�', len("☻x")},
+ {"☻x\xe2\x98�", '�', len("☻x")},
+ {"☻x\xe2\x98x", '�', len("☻x")},
+
+ // Invalid rune values should never match.
+ {"a☺b☻c☹d\xe2\x98�\xff�\xed\xa0\x80", -1, -1},
+ {"a☺b☻c☹d\xe2\x98�\xff�\xed\xa0\x80", 0xD800, -1}, // Surrogate pair
+ {"a☺b☻c☹d\xe2\x98�\xff�\xed\xa0\x80", utf8.MaxRune + 1, -1},
+ }
+ for _, tt := range tests {
+ if got := IndexRune([]byte(tt.in), tt.rune); got != tt.want {
+ t.Errorf("IndexRune(%q, %d) = %v; want %v", tt.in, tt.rune, got, tt.want)
+ }
+ }
+
+ haystack := []byte("test世界")
+ allocs := testing.AllocsPerRun(1000, func() {
+ if i := IndexRune(haystack, 's'); i != 2 {
+ t.Fatalf("'s' at %d; want 2", i)
+ }
+ if i := IndexRune(haystack, '世'); i != 4 {
+ t.Fatalf("'世' at %d; want 4", i)
}
+ })
+ if allocs != 0 {
+ t.Errorf("expected no allocations, got %f", allocs)
}
}
@@ -370,6 +410,9 @@ func valName(x int) string {
func benchBytes(b *testing.B, sizes []int, f func(b *testing.B, n int)) {
for _, n := range sizes {
+ if isRaceBuilder && n > 4<<10 {
+ continue
+ }
b.Run(valName(n), func(b *testing.B) {
if len(bmbuf) < n {
bmbuf = make([]byte, n)
@@ -382,6 +425,8 @@ func benchBytes(b *testing.B, sizes []int, f func(b *testing.B, n int)) {
var indexSizes = []int{10, 32, 4 << 10, 4 << 20, 64 << 20}
+var isRaceBuilder = strings.HasSuffix(testenv.Builder(), "-race")
+
func BenchmarkIndexByte(b *testing.B) {
benchBytes(b, indexSizes, bmIndexByte(IndexByte))
}
@@ -404,6 +449,44 @@ func bmIndexByte(index func([]byte, byte) int) func(b *testing.B, n int) {
}
}
+func BenchmarkIndexRune(b *testing.B) {
+ benchBytes(b, indexSizes, bmIndexRune(IndexRune))
+}
+
+func BenchmarkIndexRuneASCII(b *testing.B) {
+ benchBytes(b, indexSizes, bmIndexRuneASCII(IndexRune))
+}
+
+func bmIndexRuneASCII(index func([]byte, rune) int) func(b *testing.B, n int) {
+ return func(b *testing.B, n int) {
+ buf := bmbuf[0:n]
+ buf[n-1] = 'x'
+ for i := 0; i < b.N; i++ {
+ j := index(buf, 'x')
+ if j != n-1 {
+ b.Fatal("bad index", j)
+ }
+ }
+ buf[n-1] = '\x00'
+ }
+}
+
+func bmIndexRune(index func([]byte, rune) int) func(b *testing.B, n int) {
+ return func(b *testing.B, n int) {
+ buf := bmbuf[0:n]
+ utf8.EncodeRune(buf[n-3:], '世')
+ for i := 0; i < b.N; i++ {
+ j := index(buf, '世')
+ if j != n-3 {
+ b.Fatal("bad index", j)
+ }
+ }
+ buf[n-3] = '\x00'
+ buf[n-2] = '\x00'
+ buf[n-1] = '\x00'
+ }
+}
+
func BenchmarkEqual(b *testing.B) {
b.Run("0", func(b *testing.B) {
var buf [4]byte
@@ -844,6 +927,54 @@ func TestRepeat(t *testing.T) {
}
}
+func repeat(b []byte, count int) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ switch v := r.(type) {
+ case error:
+ err = v
+ default:
+ err = fmt.Errorf("%s", v)
+ }
+ }
+ }()
+
+ Repeat(b, count)
+
+ return
+}
+
+// See Issue golang.org/issue/16237
+func TestRepeatCatchesOverflow(t *testing.T) {
+ tests := [...]struct {
+ s string
+ count int
+ errStr string
+ }{
+ 0: {"--", -2147483647, "negative"},
+ 1: {"", int(^uint(0) >> 1), ""},
+ 2: {"-", 10, ""},
+ 3: {"gopher", 0, ""},
+ 4: {"-", -1, "negative"},
+ 5: {"--", -102, "negative"},
+ 6: {string(make([]byte, 255)), int((^uint(0))/255 + 1), "overflow"},
+ }
+
+ for i, tt := range tests {
+ err := repeat([]byte(tt.s), tt.count)
+ if tt.errStr == "" {
+ if err != nil {
+ t.Errorf("#%d panicked %v", i, err)
+ }
+ continue
+ }
+
+ if err == nil || !strings.Contains(err.Error(), tt.errStr) {
+ t.Errorf("#%d expected %q got %q", i, tt.errStr, err)
+ }
+ }
+}
+
func runesEqual(a, b []rune) bool {
if len(a) != len(b) {
return false
@@ -906,6 +1037,9 @@ var trimTests = []TrimTest{
{"Trim", "* listitem", " *", "listitem"},
{"Trim", `"quote"`, `"`, "quote"},
{"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
+ {"Trim", "\x80test\xff", "\xff", "test"},
+ {"Trim", " Ġ ", " ", "Ġ"},
+ {"Trim", " Ġİ0", "0 ", "Ġİ"},
//empty string tests
{"Trim", "abba", "", "abba"},
{"Trim", "", "123", ""},
@@ -1325,3 +1459,31 @@ func BenchmarkBytesCompare(b *testing.B) {
})
}
}
+
+func BenchmarkIndexAnyASCII(b *testing.B) {
+ x := Repeat([]byte{'#'}, 4096) // Never matches set
+ cs := "0123456789abcdef"
+ for k := 1; k <= 4096; k <<= 4 {
+ for j := 1; j <= 16; j <<= 1 {
+ b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ IndexAny(x[:k], cs[:j])
+ }
+ })
+ }
+ }
+}
+
+func BenchmarkTrimASCII(b *testing.B) {
+ cs := "0123456789abcdef"
+ for k := 1; k <= 4096; k <<= 4 {
+ for j := 1; j <= 16; j <<= 1 {
+ b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) {
+ x := Repeat([]byte(cs[:j]), k) // Always matches set
+ for i := 0; i < b.N; i++ {
+ Trim(x[:k], cs[:j])
+ }
+ })
+ }
+ }
+}
diff --git a/libgo/go/bytes/example_test.go b/libgo/go/bytes/example_test.go
index ad2dbc69b77..0d35a0dc9c5 100644
--- a/libgo/go/bytes/example_test.go
+++ b/libgo/go/bytes/example_test.go
@@ -11,6 +11,7 @@ import (
"io"
"os"
"sort"
+ "unicode"
)
func ExampleBuffer() {
@@ -83,3 +84,205 @@ func ExampleTrimPrefix() {
fmt.Printf("Hello%s", b)
// Output: Hello, world!
}
+
+func ExampleFields() {
+ fmt.Printf("Fields are: %q", bytes.Fields([]byte(" foo bar baz ")))
+ // Output: Fields are: ["foo" "bar" "baz"]
+}
+
+func ExampleFieldsFunc() {
+ f := func(c rune) bool {
+ return !unicode.IsLetter(c) && !unicode.IsNumber(c)
+ }
+ fmt.Printf("Fields are: %q", bytes.FieldsFunc([]byte(" foo1;bar2,baz3..."), f))
+ // Output: Fields are: ["foo1" "bar2" "baz3"]
+}
+
+func ExampleContains() {
+ fmt.Println(bytes.Contains([]byte("seafood"), []byte("foo")))
+ fmt.Println(bytes.Contains([]byte("seafood"), []byte("bar")))
+ fmt.Println(bytes.Contains([]byte("seafood"), []byte("")))
+ fmt.Println(bytes.Contains([]byte(""), []byte("")))
+ // Output:
+ // true
+ // false
+ // true
+ // true
+}
+
+func ExampleCount() {
+ fmt.Println(bytes.Count([]byte("cheese"), []byte("e")))
+ fmt.Println(bytes.Count([]byte("five"), []byte(""))) // before & after each rune
+ // Output:
+ // 3
+ // 5
+}
+
+func ExampleEqualFold() {
+ fmt.Println(bytes.EqualFold([]byte("Go"), []byte("go")))
+ // Output: true
+}
+
+func ExampleHasPrefix() {
+ fmt.Println(bytes.HasPrefix([]byte("Gopher"), []byte("Go")))
+ fmt.Println(bytes.HasPrefix([]byte("Gopher"), []byte("C")))
+ fmt.Println(bytes.HasPrefix([]byte("Gopher"), []byte("")))
+ // Output:
+ // true
+ // false
+ // true
+}
+
+func ExampleHasSuffix() {
+ fmt.Println(bytes.HasSuffix([]byte("Amigo"), []byte("go")))
+ fmt.Println(bytes.HasSuffix([]byte("Amigo"), []byte("O")))
+ fmt.Println(bytes.HasSuffix([]byte("Amigo"), []byte("Ami")))
+ fmt.Println(bytes.HasSuffix([]byte("Amigo"), []byte("")))
+ // Output:
+ // true
+ // false
+ // false
+ // true
+}
+
+func ExampleIndex() {
+ fmt.Println(bytes.Index([]byte("chicken"), []byte("ken")))
+ fmt.Println(bytes.Index([]byte("chicken"), []byte("dmr")))
+ // Output:
+ // 4
+ // -1
+}
+
+func ExampleIndexFunc() {
+ f := func(c rune) bool {
+ return unicode.Is(unicode.Han, c)
+ }
+ fmt.Println(bytes.IndexFunc([]byte("Hello, 世界"), f))
+ fmt.Println(bytes.IndexFunc([]byte("Hello, world"), f))
+ // Output:
+ // 7
+ // -1
+}
+
+func ExampleIndexAny() {
+ fmt.Println(bytes.IndexAny([]byte("chicken"), "aeiouy"))
+ fmt.Println(bytes.IndexAny([]byte("crwth"), "aeiouy"))
+ // Output:
+ // 2
+ // -1
+}
+
+func ExampleIndexRune() {
+ fmt.Println(bytes.IndexRune([]byte("chicken"), 'k'))
+ fmt.Println(bytes.IndexRune([]byte("chicken"), 'd'))
+ // Output:
+ // 4
+ // -1
+}
+
+func ExampleLastIndex() {
+ fmt.Println(bytes.Index([]byte("go gopher"), []byte("go")))
+ fmt.Println(bytes.LastIndex([]byte("go gopher"), []byte("go")))
+ fmt.Println(bytes.LastIndex([]byte("go gopher"), []byte("rodent")))
+ // Output:
+ // 0
+ // 3
+ // -1
+}
+
+func ExampleJoin() {
+ s := [][]byte{[]byte("foo"), []byte("bar"), []byte("baz")}
+ fmt.Printf("%s", bytes.Join(s, []byte(", ")))
+ // Output: foo, bar, baz
+}
+
+func ExampleRepeat() {
+ fmt.Printf("ba%s", bytes.Repeat([]byte("na"), 2))
+ // Output: banana
+}
+
+func ExampleReplace() {
+ fmt.Printf("%s\n", bytes.Replace([]byte("oink oink oink"), []byte("k"), []byte("ky"), 2))
+ fmt.Printf("%s\n", bytes.Replace([]byte("oink oink oink"), []byte("oink"), []byte("moo"), -1))
+ // Output:
+ // oinky oinky oink
+ // moo moo moo
+}
+
+func ExampleSplit() {
+ fmt.Printf("%q\n", bytes.Split([]byte("a,b,c"), []byte(",")))
+ fmt.Printf("%q\n", bytes.Split([]byte("a man a plan a canal panama"), []byte("a ")))
+ fmt.Printf("%q\n", bytes.Split([]byte(" xyz "), []byte("")))
+ fmt.Printf("%q\n", bytes.Split([]byte(""), []byte("Bernardo O'Higgins")))
+ // Output:
+ // ["a" "b" "c"]
+ // ["" "man " "plan " "canal panama"]
+ // [" " "x" "y" "z" " "]
+ // [""]
+}
+
+func ExampleSplitN() {
+ fmt.Printf("%q\n", bytes.SplitN([]byte("a,b,c"), []byte(","), 2))
+ z := bytes.SplitN([]byte("a,b,c"), []byte(","), 0)
+ fmt.Printf("%q (nil = %v)\n", z, z == nil)
+ // Output:
+ // ["a" "b,c"]
+ // [] (nil = true)
+}
+
+func ExampleSplitAfter() {
+ fmt.Printf("%q\n", bytes.SplitAfter([]byte("a,b,c"), []byte(",")))
+ // Output: ["a," "b," "c"]
+}
+
+func ExampleSplitAfterN() {
+ fmt.Printf("%q\n", bytes.SplitAfterN([]byte("a,b,c"), []byte(","), 2))
+ // Output: ["a," "b,c"]
+}
+
+func ExampleTitle() {
+ fmt.Printf("%s", bytes.Title([]byte("her royal highness")))
+ // Output: Her Royal Highness
+}
+
+func ExampleToTitle() {
+ fmt.Printf("%s\n", bytes.ToTitle([]byte("loud noises")))
+ fmt.Printf("%s\n", bytes.ToTitle([]byte("хлеб")))
+ // Output:
+ // LOUD NOISES
+ // ХЛЕБ
+}
+
+func ExampleTrim() {
+ fmt.Printf("[%q]", bytes.Trim([]byte(" !!! Achtung! Achtung! !!! "), "! "))
+ // Output: ["Achtung! Achtung"]
+}
+
+func ExampleMap() {
+ rot13 := func(r rune) rune {
+ switch {
+ case r >= 'A' && r <= 'Z':
+ return 'A' + (r-'A'+13)%26
+ case r >= 'a' && r <= 'z':
+ return 'a' + (r-'a'+13)%26
+ }
+ return r
+ }
+ fmt.Printf("%s", bytes.Map(rot13, []byte("'Twas brillig and the slithy gopher...")))
+ // Output: 'Gjnf oevyyvt naq gur fyvgul tbcure...
+}
+
+func ExampleTrimSpace() {
+ fmt.Printf("%s", bytes.TrimSpace([]byte(" \t\n a lone gopher \n\t\r\n")))
+ // Output: a lone gopher
+}
+
+func ExampleToUpper() {
+ fmt.Printf("%s", bytes.ToUpper([]byte("Gopher")))
+ // Output: GOPHER
+}
+
+func ExampleToLower() {
+ fmt.Printf("%s", bytes.ToLower([]byte("Gopher")))
+ // Output: gopher
+}
diff --git a/libgo/go/cmd/cgo/ast.go b/libgo/go/cmd/cgo/ast.go
index 000ecd44685..8ce824196d9 100644
--- a/libgo/go/cmd/cgo/ast.go
+++ b/libgo/go/cmd/cgo/ast.go
@@ -87,6 +87,7 @@ func (f *File) ReadGo(name string) {
if cg != nil {
f.Preamble += fmt.Sprintf("#line %d %q\n", sourceLine(cg), name)
f.Preamble += commentText(cg) + "\n"
+ f.Preamble += "#line 1 \"cgo-generated-wrapper\"\n"
}
}
}
@@ -296,7 +297,7 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
// everything else just recurs
default:
- error_(token.NoPos, "unexpected type %T in walk", x, visit)
+ error_(token.NoPos, "unexpected type %T in walk", x)
panic("unexpected type")
case nil:
diff --git a/libgo/go/cmd/cgo/doc.go b/libgo/go/cmd/cgo/doc.go
index d3a7b6d2a73..85441e61c04 100644
--- a/libgo/go/cmd/cgo/doc.go
+++ b/libgo/go/cmd/cgo/doc.go
@@ -53,6 +53,8 @@ For example:
// #include <png.h>
import "C"
+The default pkg-config tool may be changed by setting the PKG_CONFIG environment variable.
+
When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS, CGO_FFLAGS and
CGO_LDFLAGS environment variables are added to the flags derived from
these directives. Package-specific flags should be set using the
@@ -214,6 +216,13 @@ by making copies of the data. In pseudo-Go definitions:
// C data with explicit length to Go []byte
func C.GoBytes(unsafe.Pointer, C.int) []byte
+As a special case, C.malloc does not call the C library malloc directly
+but instead calls a Go helper function that wraps the C library malloc
+but guarantees never to return nil. If C's malloc indicates out of memory,
+the helper function crashes the program, like when Go itself runs out
+of memory. Because C.malloc cannot fail, it has no two-result form
+that returns errno.
+
C references to Go
Go functions can be exported for use by C code in the following way:
@@ -317,6 +326,9 @@ The following options are available when running cgo directly:
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.
+ -srcdir directory
+ Find the Go input files, listed on the command line,
+ in directory.
-objdir directory
Put all generated files in directory.
-importpath string
diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go
index fc1d01100d2..5ea2d941ca2 100644
--- a/libgo/go/cmd/cgo/gcc.go
+++ b/libgo/go/cmd/cgo/gcc.go
@@ -167,7 +167,23 @@ func (p *Package) Translate(f *File) {
if len(needType) > 0 {
p.loadDWARF(f, needType)
}
- p.rewriteCalls(f)
+ if p.rewriteCalls(f) {
+ // Add `import _cgo_unsafe "unsafe"` as the first decl
+ // after the package statement.
+ imp := &ast.GenDecl{
+ Tok: token.IMPORT,
+ Specs: []ast.Spec{
+ &ast.ImportSpec{
+ Name: ast.NewIdent("_cgo_unsafe"),
+ Path: &ast.BasicLit{
+ Kind: token.STRING,
+ Value: `"unsafe"`,
+ },
+ },
+ },
+ }
+ f.AST.Decls = append([]ast.Decl{imp}, f.AST.Decls...)
+ }
p.rewriteRef(f)
}
@@ -413,6 +429,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
var b bytes.Buffer
b.WriteString(f.Preamble)
b.WriteString(builtinProlog)
+ b.WriteString("#line 1 \"cgo-dwarf-inference\"\n")
for i, n := range names {
fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
if n.Kind == "const" {
@@ -578,7 +595,9 @@ func (p *Package) mangleName(n *Name) {
// rewriteCalls rewrites all calls that pass pointers to check that
// they follow the rules for passing pointers between Go and C.
-func (p *Package) rewriteCalls(f *File) {
+// This returns whether the package needs to import unsafe as _cgo_unsafe.
+func (p *Package) rewriteCalls(f *File) bool {
+ needsUnsafe := false
for _, call := range f.Calls {
// This is a call to C.xxx; set goname to "xxx".
goname := call.Call.Fun.(*ast.SelectorExpr).Sel.Name
@@ -590,18 +609,24 @@ func (p *Package) rewriteCalls(f *File) {
// Probably a type conversion.
continue
}
- p.rewriteCall(f, call, name)
+ if p.rewriteCall(f, call, name) {
+ needsUnsafe = true
+ }
}
+ return needsUnsafe
}
-// rewriteCall rewrites one call to add pointer checks. We replace
-// each pointer argument x with _cgoCheckPointer(x).(T).
-func (p *Package) rewriteCall(f *File, call *Call, name *Name) {
+// rewriteCall rewrites one call to add pointer checks.
+// If any pointer checks are required, we rewrite the call into a
+// function literal that calls _cgoCheckPointer for each pointer
+// argument and then calls the original function.
+// This returns whether the package needs to import unsafe as _cgo_unsafe.
+func (p *Package) rewriteCall(f *File, call *Call, name *Name) bool {
// Avoid a crash if the number of arguments is
// less than the number of parameters.
// This will be caught when the generated file is compiled.
if len(call.Call.Args) < len(name.FuncType.Params) {
- return
+ return false
}
any := false
@@ -612,38 +637,60 @@ func (p *Package) rewriteCall(f *File, call *Call, name *Name) {
}
}
if !any {
- return
+ return false
}
// We need to rewrite this call.
//
- // We are going to rewrite C.f(p) to C.f(_cgoCheckPointer(p)).
- // If the call to C.f is deferred, that will check p at the
- // point of the defer statement, not when the function is called, so
- // rewrite to func(_cgo0 ptype) { C.f(_cgoCheckPointer(_cgo0)) }(p)
-
- var dargs []ast.Expr
- if call.Deferred {
- dargs = make([]ast.Expr, len(name.FuncType.Params))
- }
+ // We are going to rewrite C.f(p) to
+ // func (_cgo0 ptype) {
+ // _cgoCheckPointer(_cgo0)
+ // C.f(_cgo0)
+ // }(p)
+ // Using a function literal like this lets us do correct
+ // argument type checking, and works correctly if the call is
+ // deferred.
+ needsUnsafe := false
+ params := make([]*ast.Field, len(name.FuncType.Params))
+ nargs := make([]ast.Expr, len(name.FuncType.Params))
+ var stmts []ast.Stmt
for i, param := range name.FuncType.Params {
+ // params is going to become the parameters of the
+ // function literal.
+ // nargs is going to become the list of arguments made
+ // by the call within the function literal.
+ // nparam is the parameter of the function literal that
+ // corresponds to param.
+
origArg := call.Call.Args[i]
- darg := origArg
+ nparam := ast.NewIdent(fmt.Sprintf("_cgo%d", i))
+ nargs[i] = nparam
- if call.Deferred {
- dargs[i] = darg
- darg = ast.NewIdent(fmt.Sprintf("_cgo%d", i))
- call.Call.Args[i] = darg
+ // The Go version of the C type might use unsafe.Pointer,
+ // but the file might not import unsafe.
+ // Rewrite the Go type if necessary to use _cgo_unsafe.
+ ptype := p.rewriteUnsafe(param.Go)
+ if ptype != param.Go {
+ needsUnsafe = true
+ }
+
+ params[i] = &ast.Field{
+ Names: []*ast.Ident{nparam},
+ Type: ptype,
}
if !p.needsPointerCheck(f, param.Go, origArg) {
continue
}
+ // Run the cgo pointer checks on nparam.
+
+ // Change the function literal to call the real function
+ // with the parameter passed through _cgoCheckPointer.
c := &ast.CallExpr{
Fun: ast.NewIdent("_cgoCheckPointer"),
Args: []ast.Expr{
- darg,
+ nparam,
},
}
@@ -651,95 +698,83 @@ func (p *Package) rewriteCall(f *File, call *Call, name *Name) {
// expression.
c.Args = p.checkAddrArgs(f, c.Args, origArg)
- // _cgoCheckPointer returns interface{}.
- // We need to type assert that to the type we want.
- // If the Go version of this C type uses
- // unsafe.Pointer, we can't use a type assertion,
- // because the Go file might not import unsafe.
- // Instead we use a local variant of _cgoCheckPointer.
-
- var arg ast.Expr
- if n := p.unsafeCheckPointerName(param.Go, call.Deferred); n != "" {
- c.Fun = ast.NewIdent(n)
- arg = c
- } else {
- // In order for the type assertion to succeed,
- // we need it to match the actual type of the
- // argument. The only type we have is the
- // type of the function parameter. We know
- // that the argument type must be assignable
- // to the function parameter type, or the code
- // would not compile, but there is nothing
- // requiring that the types be exactly the
- // same. Add a type conversion to the
- // argument so that the type assertion will
- // succeed.
- c.Args[0] = &ast.CallExpr{
- Fun: param.Go,
- Args: []ast.Expr{
- c.Args[0],
- },
- }
-
- arg = &ast.TypeAssertExpr{
- X: c,
- Type: param.Go,
- }
+ stmt := &ast.ExprStmt{
+ X: c,
}
-
- call.Call.Args[i] = arg
+ stmts = append(stmts, stmt)
}
- if call.Deferred {
- params := make([]*ast.Field, len(name.FuncType.Params))
- for i, param := range name.FuncType.Params {
- ptype := param.Go
- if p.hasUnsafePointer(ptype) {
- // Avoid generating unsafe.Pointer by using
- // interface{}. This works because we are
- // going to call a _cgoCheckPointer function
- // anyhow.
- ptype = &ast.InterfaceType{
- Methods: &ast.FieldList{},
- }
- }
- params[i] = &ast.Field{
- Names: []*ast.Ident{
- ast.NewIdent(fmt.Sprintf("_cgo%d", i)),
- },
- Type: ptype,
- }
- }
-
- dbody := &ast.CallExpr{
- Fun: call.Call.Fun,
- Args: call.Call.Args,
+ fcall := &ast.CallExpr{
+ Fun: call.Call.Fun,
+ Args: nargs,
+ }
+ ftype := &ast.FuncType{
+ Params: &ast.FieldList{
+ List: params,
+ },
+ }
+ if name.FuncType.Result != nil {
+ rtype := p.rewriteUnsafe(name.FuncType.Result.Go)
+ if rtype != name.FuncType.Result.Go {
+ needsUnsafe = true
}
- call.Call.Fun = &ast.FuncLit{
- Type: &ast.FuncType{
- Params: &ast.FieldList{
- List: params,
- },
- },
- Body: &ast.BlockStmt{
- List: []ast.Stmt{
- &ast.ExprStmt{
- X: dbody,
- },
+ ftype.Results = &ast.FieldList{
+ List: []*ast.Field{
+ &ast.Field{
+ Type: rtype,
},
},
}
- call.Call.Args = dargs
- call.Call.Lparen = token.NoPos
- call.Call.Rparen = token.NoPos
+ }
- // There is a Ref pointing to the old call.Call.Fun.
- for _, ref := range f.Ref {
- if ref.Expr == &call.Call.Fun {
- ref.Expr = &dbody.Fun
+ // There is a Ref pointing to the old call.Call.Fun.
+ for _, ref := range f.Ref {
+ if ref.Expr == &call.Call.Fun {
+ ref.Expr = &fcall.Fun
+
+ // If this call expects two results, we have to
+ // adjust the results of the function we generated.
+ if ref.Context == "call2" {
+ if ftype.Results == nil {
+ // An explicit void argument
+ // looks odd but it seems to
+ // be how cgo has worked historically.
+ ftype.Results = &ast.FieldList{
+ List: []*ast.Field{
+ &ast.Field{
+ Type: ast.NewIdent("_Ctype_void"),
+ },
+ },
+ }
+ }
+ ftype.Results.List = append(ftype.Results.List,
+ &ast.Field{
+ Type: ast.NewIdent("error"),
+ })
}
}
}
+
+ var fbody ast.Stmt
+ if ftype.Results == nil {
+ fbody = &ast.ExprStmt{
+ X: fcall,
+ }
+ } else {
+ fbody = &ast.ReturnStmt{
+ Results: []ast.Expr{fcall},
+ }
+ }
+ call.Call.Fun = &ast.FuncLit{
+ Type: ftype,
+ Body: &ast.BlockStmt{
+ List: append(stmts, fbody),
+ },
+ }
+ call.Call.Lparen = token.NoPos
+ call.Call.Rparen = token.NoPos
+
+ return needsUnsafe
}
// needsPointerCheck returns whether the type t needs a pointer check.
@@ -782,6 +817,11 @@ func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
if !top {
return true
}
+ // Check whether this is a pointer to a C union (or class)
+ // type that contains a pointer.
+ if unionWithPointer[t.X] {
+ return true
+ }
return p.hasPointer(f, t.X, false)
case *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
return true
@@ -935,69 +975,52 @@ func (p *Package) isType(t ast.Expr) bool {
return false
}
-// unsafeCheckPointerName is given the Go version of a C type. If the
-// type uses unsafe.Pointer, we arrange to build a version of
-// _cgoCheckPointer that returns that type. This avoids using a type
-// assertion to unsafe.Pointer in our copy of user code. We return
-// the name of the _cgoCheckPointer function we are going to build, or
-// the empty string if the type does not use unsafe.Pointer.
-//
-// The deferred parameter is true if this check is for the argument of
-// a deferred function. In that case we need to use an empty interface
-// as the argument type, because the deferred function we introduce in
-// rewriteCall will use an empty interface type, and we can't add a
-// type assertion. This is handled by keeping a separate list, and
-// writing out the lists separately in writeDefs.
-func (p *Package) unsafeCheckPointerName(t ast.Expr, deferred bool) string {
- if !p.hasUnsafePointer(t) {
- return ""
- }
- var buf bytes.Buffer
- conf.Fprint(&buf, fset, t)
- s := buf.String()
- checks := &p.CgoChecks
- if deferred {
- checks = &p.DeferredCgoChecks
- }
- for i, t := range *checks {
- if s == t {
- return p.unsafeCheckPointerNameIndex(i, deferred)
- }
- }
- *checks = append(*checks, s)
- return p.unsafeCheckPointerNameIndex(len(*checks)-1, deferred)
-}
-
-// hasUnsafePointer returns whether the Go type t uses unsafe.Pointer.
-// t is the Go version of a C type, so we don't need to handle every case.
-// We only care about direct references, not references via typedefs.
-func (p *Package) hasUnsafePointer(t ast.Expr) bool {
+// rewriteUnsafe returns a version of t with references to unsafe.Pointer
+// rewritten to use _cgo_unsafe.Pointer instead.
+func (p *Package) rewriteUnsafe(t ast.Expr) ast.Expr {
switch t := t.(type) {
case *ast.Ident:
// We don't see a SelectorExpr for unsafe.Pointer;
// this is created by code in this file.
- return t.Name == "unsafe.Pointer"
+ if t.Name == "unsafe.Pointer" {
+ return ast.NewIdent("_cgo_unsafe.Pointer")
+ }
case *ast.ArrayType:
- return p.hasUnsafePointer(t.Elt)
+ t1 := p.rewriteUnsafe(t.Elt)
+ if t1 != t.Elt {
+ r := *t
+ r.Elt = t1
+ return &r
+ }
case *ast.StructType:
+ changed := false
+ fields := *t.Fields
+ fields.List = nil
for _, f := range t.Fields.List {
- if p.hasUnsafePointer(f.Type) {
- return true
+ ft := p.rewriteUnsafe(f.Type)
+ if ft == f.Type {
+ fields.List = append(fields.List, f)
+ } else {
+ fn := *f
+ fn.Type = ft
+ fields.List = append(fields.List, &fn)
+ changed = true
}
}
+ if changed {
+ r := *t
+ r.Fields = &fields
+ return &r
+ }
case *ast.StarExpr: // Pointer type.
- return p.hasUnsafePointer(t.X)
- }
- return false
-}
-
-// unsafeCheckPointerNameIndex returns the name to use for a
-// _cgoCheckPointer variant based on the index in the CgoChecks slice.
-func (p *Package) unsafeCheckPointerNameIndex(i int, deferred bool) string {
- if deferred {
- return fmt.Sprintf("_cgoCheckPointerInDefer%d", i)
+ x1 := p.rewriteUnsafe(t.X)
+ if x1 != t.X {
+ r := *t
+ r.X = x1
+ return &r
+ }
}
- return fmt.Sprintf("_cgoCheckPointer%d", i)
+ return t
}
// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
@@ -1187,6 +1210,8 @@ func (p *Package) gccMachine() []string {
return []string{"-m64"}
case "mips64", "mips64le":
return []string{"-mabi=64"}
+ case "mips", "mipsle":
+ return []string{"-mabi=32"}
}
return nil
}
@@ -1415,6 +1440,10 @@ var tagGen int
var typedef = make(map[string]*Type)
var goIdent = make(map[string]*ast.Ident)
+// unionWithPointer is true for a Go type that represents a C union (or class)
+// that may contain a pointer. This is used for cgo pointer checking.
+var unionWithPointer = make(map[ast.Expr]bool)
+
func (c *typeConv) Init(ptrSize, intSize int64) {
c.ptrSize = ptrSize
c.intSize = intSize
@@ -1464,6 +1493,19 @@ func base(dt dwarf.Type) dwarf.Type {
return dt
}
+// unqual strips away qualifiers from a DWARF type.
+// In general we don't care about top-level qualifiers.
+func unqual(dt dwarf.Type) dwarf.Type {
+ for {
+ if d, ok := dt.(*dwarf.QualType); ok {
+ dt = d.Type
+ } else {
+ break
+ }
+ }
+ return dt
+}
+
// Map from dwarf text names to aliases we use in package "C".
var dwarfToName = map[string]string{
"long int": "long",
@@ -1641,7 +1683,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
case 16:
t.Go = c.complex128
}
- if t.Align = t.Size; t.Align >= c.ptrSize {
+ if t.Align = t.Size / 2; t.Align >= c.ptrSize {
t.Align = c.ptrSize
}
@@ -1687,6 +1729,15 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
t.Go = c.goVoidPtr
t.C.Set("void*")
+ dq := dt.Type
+ for {
+ if d, ok := dq.(*dwarf.QualType); ok {
+ t.C.Set(d.Qual + " " + t.C.String())
+ dq = d.Type
+ } else {
+ break
+ }
+ }
break
}
@@ -1699,9 +1750,16 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *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
+ t1 := c.Type(dt.Type, pos)
+ t.Size = t1.Size
+ t.Align = t1.Align
+ t.Go = t1.Go
+ if unionWithPointer[t1.Go] {
+ unionWithPointer[t.Go] = true
+ }
+ t.EnumValues = nil
+ t.Typedef = ""
+ t.C.Set("%s "+dt.Qual, t1.C)
return t
case *dwarf.StructType:
@@ -1733,6 +1791,9 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
switch dt.Kind {
case "class", "union":
t.Go = c.Opaque(t.Size)
+ if c.dwarfHasPointer(dt, pos) {
+ unionWithPointer[t.Go] = true
+ }
if t.C.Empty() {
t.C.Set("__typeof__(unsigned char[%d])", t.Size)
}
@@ -1775,6 +1836,9 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
goIdent[name.Name] = name
sub := c.Type(dt.Type, pos)
t.Go = name
+ if unionWithPointer[sub.Go] {
+ unionWithPointer[t.Go] = true
+ }
t.Size = sub.Size
t.Align = sub.Align
oldType := typedef[name.Name]
@@ -1905,7 +1969,7 @@ func isStructUnionClass(x ast.Expr) bool {
// 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)
+ t := c.Type(unqual(dtype), pos)
switch dt := dtype.(type) {
case *dwarf.ArrayType:
// Arrays are passed implicitly as pointers in C.
@@ -1935,9 +1999,12 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
return nil
}
- // Remember the C spelling, in case the struct
- // has __attribute__((unavailable)) on it. See issue 2888.
- t.Typedef = dt.Name
+ // For a struct/union/class, remember the C spelling,
+ // in case it has __attribute__((unavailable)).
+ // See issue 2888.
+ if isStructUnionClass(t.Go) {
+ t.Typedef = dt.Name
+ }
}
}
return t
@@ -1966,7 +2033,7 @@ func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType {
if _, ok := dtype.ReturnType.(*dwarf.VoidType); ok {
gr = []*ast.Field{{Type: c.goVoid}}
} else if dtype.ReturnType != nil {
- r = c.Type(dtype.ReturnType, pos)
+ r = c.Type(unqual(dtype.ReturnType), pos)
gr = []*ast.Field{{Type: r.Go}}
}
return &FuncType{
@@ -2153,6 +2220,44 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
return
}
+// dwarfHasPointer returns whether the DWARF type dt contains a pointer.
+func (c *typeConv) dwarfHasPointer(dt dwarf.Type, pos token.Pos) bool {
+ switch dt := dt.(type) {
+ default:
+ fatalf("%s: unexpected type: %s", lineno(pos), dt)
+ return false
+
+ case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.EnumType,
+ *dwarf.FloatType, *dwarf.ComplexType, *dwarf.FuncType,
+ *dwarf.IntType, *dwarf.UcharType, *dwarf.UintType, *dwarf.VoidType:
+
+ return false
+
+ case *dwarf.ArrayType:
+ return c.dwarfHasPointer(dt.Type, pos)
+
+ case *dwarf.PtrType:
+ return true
+
+ case *dwarf.QualType:
+ return c.dwarfHasPointer(dt.Type, pos)
+
+ case *dwarf.StructType:
+ for _, f := range dt.Field {
+ if c.dwarfHasPointer(f.Type, pos) {
+ return true
+ }
+ }
+ return false
+
+ case *dwarf.TypedefType:
+ if dt.Name == "_GoString_" || dt.Name == "_GoBytes_" {
+ return true
+ }
+ return c.dwarfHasPointer(dt.Type, pos)
+ }
+}
+
func upper(s string) string {
if s == "" {
return ""
diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go
index 219b2527323..c91c830260f 100644
--- a/libgo/go/cmd/cgo/main.go
+++ b/libgo/go/cmd/cgo/main.go
@@ -42,10 +42,6 @@ type Package struct {
GoFiles []string // list of Go files
GccFiles []string // list of gcc output files
Preamble string // collected preamble for _cgo_export.h
-
- // See unsafeCheckPointerName.
- CgoChecks []string
- DeferredCgoChecks []string
}
// A File collects information about a single Go input file.
@@ -153,6 +149,8 @@ var ptrSizeMap = map[string]int64{
"mipsn32": 4,
"mipso64": 8,
"mipsn64": 8,
+ "mips": 4,
+ "mipsle": 4,
"mips64": 8,
"mips64le": 8,
"ppc": 4,
@@ -175,6 +173,8 @@ var intSizeMap = map[string]int64{
"mipsn32": 4,
"mipso64": 8,
"mipsn64": 8,
+ "mips": 4,
+ "mipsle": 4,
"mips64": 8,
"mips64le": 8,
"ppc": 4,
@@ -200,6 +200,7 @@ var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information
// 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 srcDir = flag.String("srcdir", "", "source directory")
var objDir = flag.String("objdir", "", "object directory")
var importPath = flag.String("importpath", "", "import path of package being built (for comments in generated files)")
var exportHeader = flag.String("exportheader", "", "where to write export header if any exported functions")
@@ -278,6 +279,9 @@ func main() {
// Use the beginning of the md5 of the input to disambiguate.
h := md5.New()
for _, input := range goFiles {
+ if *srcDir != "" {
+ input = filepath.Join(*srcDir, input)
+ }
f, err := os.Open(input)
if err != nil {
fatalf("%s", err)
@@ -289,6 +293,9 @@ func main() {
fs := make([]*File, len(goFiles))
for i, input := range goFiles {
+ if *srcDir != "" {
+ input = filepath.Join(*srcDir, input)
+ }
f := new(File)
f.ReadGo(input)
f.DiscardCgoDirectives()
diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go
index 842b1c5ef80..e82ec375a27 100644
--- a/libgo/go/cmd/cgo/out.go
+++ b/libgo/go/cmd/cgo/out.go
@@ -19,7 +19,10 @@ import (
"strings"
)
-var conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
+var (
+ conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
+ noSourceConf = printer.Config{Tabwidth: 8}
+)
// writeDefs creates output files to be compiled by gc and gcc.
func (p *Package) writeDefs() {
@@ -95,7 +98,19 @@ func (p *Package) writeDefs() {
for _, name := range typedefNames {
def := typedef[name]
fmt.Fprintf(fgo2, "type %s ", name)
- conf.Fprint(fgo2, fset, def.Go)
+ // We don't have source info for these types, so write them out without source info.
+ // Otherwise types would look like:
+ //
+ // type _Ctype_struct_cb struct {
+ // //line :1
+ // on_test *[0]byte
+ // //line :1
+ // }
+ //
+ // Which is not useful. Moreover we never override source info,
+ // so subsequent source code uses the same source info.
+ // Moreover, empty file name makes compile emit no source debug info at all.
+ noSourceConf.Fprint(fgo2, fset, def.Go)
fmt.Fprintf(fgo2, "\n\n")
}
if *gccgo {
@@ -111,17 +126,11 @@ func (p *Package) writeDefs() {
fmt.Fprint(fgo2, goProlog)
}
- for i, t := range p.CgoChecks {
- n := p.unsafeCheckPointerNameIndex(i, false)
- fmt.Fprintf(fgo2, "\nfunc %s(p %s, args ...interface{}) %s {\n", n, t, t)
- fmt.Fprintf(fgo2, "\treturn _cgoCheckPointer(p, args...).(%s)\n", t)
- fmt.Fprintf(fgo2, "}\n")
+ if fc != nil {
+ fmt.Fprintf(fc, "#line 1 \"cgo-generated-wrappers\"\n")
}
- for i, t := range p.DeferredCgoChecks {
- n := p.unsafeCheckPointerNameIndex(i, true)
- fmt.Fprintf(fgo2, "\nfunc %s(p interface{}, args ...interface{}) %s {\n", n, t)
- fmt.Fprintf(fgo2, "\treturn _cgoCheckPointer(p, args...).(%s)\n", t)
- fmt.Fprintf(fgo2, "}\n")
+ if fm != nil {
+ fmt.Fprintf(fm, "#line 1 \"cgo-generated-wrappers\"\n")
}
gccgoSymbolPrefix := p.gccgoSymbolPrefix()
@@ -346,11 +355,7 @@ func (p *Package) structType(n *Name) (string, int64) {
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)
+ fmt.Fprintf(&buf, "\t\t%s r;\n", t.C)
off += t.Size
}
if off%p.PtrSize != 0 {
@@ -611,20 +616,10 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
}
}
fmt.Fprintf(fgcc, "%s(", n.C)
- for i, t := range n.FuncType.Params {
+ for i := 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")
@@ -684,14 +679,10 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
}
}
fmt.Fprintf(fgcc, "%s(", n.C)
- for i, t := range n.FuncType.Params {
+ for i := 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")
@@ -1217,8 +1208,8 @@ var goTypes = map[string]*Type{
"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")},
+ "complex64": {Size: 8, Align: 4, C: c("GoComplex64")},
+ "complex128": {Size: 16, Align: 8, C: c("GoComplex128")},
}
// Map an ast type to a Type.
@@ -1299,6 +1290,7 @@ func (p *Package) cgoType(e ast.Expr) *Type {
}
const gccProlog = `
+#line 1 "cgo-gcc-prolog"
/*
If x and y are not equal, the type will be invalid
(have a negative array count) and an inscrutable error will come
@@ -1332,6 +1324,7 @@ const noTsanProlog = `
// This must match the TSAN code in runtime/cgo/libcgo.h.
const yesTsanProlog = `
+#line 1 "cgo-tsan-prolog"
#define CGO_NO_SANITIZE_THREAD __attribute__ ((no_sanitize_thread))
long long _cgo_sync __attribute__ ((common));
@@ -1354,6 +1347,7 @@ static void _cgo_tsan_release() {
var tsanProlog = noTsanProlog
const builtinProlog = `
+#line 1 "cgo-builtin-prolog"
#include <stddef.h> /* for ptrdiff_t and size_t below */
/* Define intgo when compiling with GCC. */
@@ -1377,14 +1371,14 @@ func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32
func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr, uintptr)
//go:linkname _cgoCheckPointer runtime.cgoCheckPointer
-func _cgoCheckPointer(interface{}, ...interface{}) interface{}
+func _cgoCheckPointer(interface{}, ...interface{})
//go:linkname _cgoCheckResult runtime.cgoCheckResult
func _cgoCheckResult(interface{})
`
const gccgoGoProlog = `
-func _cgoCheckPointer(interface{}, ...interface{}) interface{}
+func _cgoCheckPointer(interface{}, ...interface{})
func _cgoCheckResult(interface{})
`
@@ -1461,9 +1455,15 @@ const cMallocDefGo = `
var __cgofn__cgoPREFIX_Cfunc__Cmalloc byte
var _cgoPREFIX_Cfunc__Cmalloc = unsafe.Pointer(&__cgofn__cgoPREFIX_Cfunc__Cmalloc)
+//go:linkname runtime_throw runtime.throw
+func runtime_throw(string)
+
//go:cgo_unsafe_args
func _cgo_cmalloc(p0 uint64) (r1 unsafe.Pointer) {
_cgo_runtime_cgocall(_cgoPREFIX_Cfunc__Cmalloc, uintptr(unsafe.Pointer(&p0)))
+ if r1 == nil {
+ runtime_throw("runtime: C malloc failed")
+ }
return
}
`
@@ -1500,6 +1500,7 @@ func (p *Package) cPrologGccgo() string {
}
const cPrologGccgo = `
+#line 1 "cgo-c-prolog-gccgo"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -1564,18 +1565,17 @@ typedef struct __go_empty_interface {
void *__object;
} Eface;
-extern Eface runtimeCgoCheckPointer(Eface, Slice)
+extern void runtimeCgoCheckPointer(Eface, Slice)
__asm__("runtime.cgoCheckPointer")
__attribute__((weak));
-extern Eface localCgoCheckPointer(Eface, Slice)
+extern void localCgoCheckPointer(Eface, Slice)
__asm__("GCCGOSYMBOLPREF._cgoCheckPointer");
-Eface localCgoCheckPointer(Eface ptr, Slice args) {
+void localCgoCheckPointer(Eface ptr, Slice args) {
if(runtimeCgoCheckPointer) {
- return runtimeCgoCheckPointer(ptr, args);
+ runtimeCgoCheckPointer(ptr, args);
}
- return ptr;
}
extern void runtimeCgoCheckResult(Eface)
@@ -1598,6 +1598,7 @@ func (p *Package) gccExportHeaderProlog() string {
const gccExportHeaderProlog = `
/* Start of boilerplate cgo prologue. */
+#line 1 "cgo-gcc-export-header-prolog"
#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H
@@ -1651,6 +1652,7 @@ const gccExportHeaderEpilog = `
// We use weak declarations, and test the addresses, so that this code
// works with older versions of gccgo.
const gccgoExportFileProlog = `
+#line 1 "cgo-gccgo-export-file-prolog"
extern _Bool runtime_iscgo __attribute__ ((weak));
static void GoInit(void) __attribute__ ((constructor));
diff --git a/libgo/go/cmd/go/alldocs.go b/libgo/go/cmd/go/alldocs.go
index 58b0d16b2b0..e93fd6ebed7 100644
--- a/libgo/go/cmd/go/alldocs.go
+++ b/libgo/go/cmd/go/alldocs.go
@@ -17,6 +17,7 @@
// clean remove object files
// doc show documentation for package or symbol
// env print Go environment information
+// bug print information for bug reports
// fix run go tool fix on packages
// fmt run gofmt on package sources
// generate generate Go files by processing source
@@ -323,6 +324,17 @@
// each named variable on its own line.
//
//
+// Print information for bug reports
+//
+// Usage:
+//
+// go bug
+//
+// Bug prints information that helps file effective bug reports.
+//
+// Bugs may be reported at https://golang.org/issue/new.
+//
+//
// Run go tool fix on packages
//
// Usage:
@@ -367,7 +379,7 @@
//
// 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.
+// create or update Go source files.
//
// Go generate is never run automatically by go build, go get, go test,
// and so on. It must be run explicitly.
@@ -430,10 +442,10 @@
// can be used to create aliases or to handle multiword generators.
// For example,
//
-// //go:generate -command yacc go tool yacc
+// //go:generate -command foo go tool foo
//
-// specifies that the command "yacc" represents the generator
-// "go tool yacc".
+// specifies that the command "foo" represents the generator
+// "go tool foo".
//
// 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
@@ -496,11 +508,13 @@
// 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.
//
+// The -v flag enables verbose progress and debug output.
+//
// Get also accepts build flags to control the installation. See 'go help build'.
//
// When checking out a new package, get creates the target directory
// GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
-// get uses the first one. See 'go help gopath'.
+// get uses the first one. For more details see: 'go help gopath'.
//
// 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
@@ -584,6 +598,8 @@
// SwigFiles []string // .swig files
// SwigCXXFiles []string // .swigcxx files
// SysoFiles []string // .syso object files to add to archive
+// TestGoFiles []string // _test.go files in package
+// XTestGoFiles []string // _test.go files outside package
//
// // Cgo directives
// CgoCFLAGS []string // cgo: flags for C compiler
@@ -594,20 +610,23 @@
// CgoPkgConfig []string // cgo: pkg-config names
//
// // Dependency information
-// Imports []string // import paths used by this package
-// Deps []string // all (recursively) imported dependencies
+// Imports []string // import paths used by this package
+// Deps []string // all (recursively) imported dependencies
+// TestImports []string // imports from TestGoFiles
+// XTestImports []string // imports from XTestGoFiles
//
// // Error information
// Incomplete bool // this package or a dependency has an error
// 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
// }
//
+// Packages stored in vendor directories report an ImportPath that includes the
+// path to the vendor directory (for example, "d/vendor/p" instead of "p"),
+// so that the ImportPath uniquely identifies a given copy of a package.
+// The Imports, Deps, TestImports, and XTestImports lists also contain these
+// expanded imports paths. See golang.org/s/go15vendor for more about vendoring.
+//
// The error information, if any, is
//
// type PackageError struct {
@@ -852,6 +871,10 @@
// position independent executables (PIE). Packages not named
// main are ignored.
//
+// -buildmode=plugin
+// Build the listed main packages, plus all packages that they
+// import, into a Go plugin. Packages not named main are ignored.
+//
//
// File types
//
@@ -906,8 +929,13 @@
// 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.
+// If the environment variable is unset, GOPATH defaults
+// to a subdirectory named "go" in the user's home directory
+// ($HOME/go on Unix, %USERPROFILE%\go on Windows),
+// unless that directory holds a Go distribution.
+// Run "go env GOPATH" to see the current GOPATH.
+//
+// See https://golang.org/wiki/SettingGOPATH to set a custom GOPATH.
//
// Each directory listed in GOPATH must have a prescribed structure:
//
@@ -935,9 +963,9 @@
//
// Here's an example directory layout:
//
-// GOPATH=/home/user/gocode
+// GOPATH=/home/user/go
//
-// /home/user/gocode/
+// /home/user/go/
// src/
// foo/
// bar/ (go code in package bar)
@@ -963,7 +991,7 @@
// by code in the directory tree rooted at the parent of "internal".
// Here's an extended version of the directory layout above:
//
-// /home/user/gocode/
+// /home/user/go/
// src/
// crash/
// bang/ (go code in package bang)
@@ -1001,7 +1029,7 @@
// but with the "internal" directory renamed to "vendor"
// and a new foo/vendor/crash/bang directory added:
//
-// /home/user/gocode/
+// /home/user/go/
// src/
// crash/
// bang/ (go code in package bang)
@@ -1060,7 +1088,7 @@
// The operating system for which to compile code.
// Examples are linux, darwin, windows, netbsd.
// GOPATH
-// See 'go help gopath'.
+// For more details see: 'go help gopath'.
// GORACE
// Options for the race detector.
// See https://golang.org/doc/articles/race_detector.html.
@@ -1082,10 +1110,15 @@
// CGO_CXXFLAGS
// Flags that cgo will pass to the compiler when compiling
// C++ code.
+// CGO_FFLAGS
+// Flags that cgo will pass to the compiler when compiling
+// Fortran code.
// CGO_LDFLAGS
// Flags that cgo will pass to the compiler when linking.
// CXX
// The command to use to compile C++ code.
+// PKG_CONFIG
+// Path to pkg-config tool.
//
// Architecture-specific environment variables:
//
@@ -1107,14 +1140,18 @@
// Whether the linker should use external linking mode
// when using -linkmode=auto with code that uses cgo.
// Set to 0 to disable external linking mode, 1 to enable it.
+// GIT_ALLOW_PROTOCOL
+// Defined by Git. A colon-separated list of schemes that are allowed to be used
+// with git fetch/clone. If set, any scheme not explicitly mentioned will be
+// considered insecure by 'go get'.
//
//
// 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').
+// 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 (For more
+// details see: 'go help gopath').
//
// Relative import paths
//
@@ -1206,6 +1243,11 @@
// each is tried in turn when downloading. For example, a Git
// download tries https://, then git+ssh://.
//
+// By default, downloads are restricted to known secure protocols
+// (e.g. https, ssh). To override this setting for Git downloads, the
+// GIT_ALLOW_PROTOCOL environment variable can be set (For more details see:
+// 'go help environment').
+//
// 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 <meta> tag in the document's HTML
@@ -1246,8 +1288,8 @@
// 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').
+// New downloaded packages are written to the first directory listed in the GOPATH
+// environment variable (For more details see: 'go help gopath').
//
// The go command attempts to download the version of the
// package appropriate for the Go release being used.
@@ -1291,7 +1333,7 @@
//
// 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').
+// environment variable (For more details see: 'go help gopath').
//
// If no import paths are given, the action applies to the
// package in the current directory.
@@ -1311,6 +1353,9 @@
// - "cmd" expands to the Go repository's commands and their
// internal libraries.
//
+// Import paths beginning with "cmd/" only match source code in
+// the Go repository.
+//
// 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
@@ -1366,28 +1411,11 @@
// 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 'go doc 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.
-//
// -count n
// Run each test and benchmark n times (default 1).
// If -cpu is set, run n times for each GOMAXPROCS value.
@@ -1413,33 +1441,11 @@
// 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 'go doc 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
@@ -1465,13 +1471,64 @@
// If a test runs longer than t, panic.
// The default is 10 minutes (10m).
//
-// -trace trace.out
-// Write an execution trace to the specified file before exiting.
-//
// -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 following flags are also recognized by 'go test' and can be used to
+// profile the tests during execution:
+//
+// -benchmem
+// Print memory allocation statistics for benchmarks.
+//
+// -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 'go doc 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.
+//
+// -coverprofile cover.out
+// Write a coverage profile to the file after all tests have passed.
+// Sets -cover.
+//
+// -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 'go doc runtime.MemProfileRate'.
+// To profile all memory allocations, use -test.memprofilerate=1
+// and pass --alloc_space flag to the pprof tool.
+//
+// -mutexprofile mutex.out
+// Write a mutex contention profile to the specified file
+// when all tests are complete.
+// Writes test binary as -c would.
+//
+// -mutexprofilefraction n
+// Sample 1 in n stack traces of goroutines holding a
+// contended mutex.
+//
+// -outputdir directory
+// Place output files from profiling in the specified directory,
+// by default the directory in which "go test" is running.
+//
+// -trace trace.out
+// Write an execution trace to the specified file before exiting.
+//
// Each of these flags is also recognized with an optional 'test.' prefix,
// as in -test.v. When invoking the generated test binary (the result of
// 'go test -c') directly, however, the prefix is mandatory.
@@ -1551,7 +1608,8 @@
// is compared exactly against the comment (see examples below). If the last
// comment begins with "Unordered output:" then the output is compared to the
// comment, however the order of the lines is ignored. An example with no such
-// comment, or with no text after "Output:" is compiled but not executed.
+// comment is compiled but not executed. An example with no text after
+// "Output:" is compiled, executed, and expected to produce no output.
//
// Godoc displays the body of ExampleXXX to demonstrate the use
// of the function, constant, or variable XXX. An example of a method M with
diff --git a/libgo/go/cmd/go/bootstrap.go b/libgo/go/cmd/go/bootstrap.go
index caa96769d84..2148d12685a 100644
--- a/libgo/go/cmd/go/bootstrap.go
+++ b/libgo/go/cmd/go/bootstrap.go
@@ -36,3 +36,6 @@ func httpsOrHTTP(importPath string, security securityMode) (string, io.ReadClose
func parseMetaGoImports(r io.Reader) ([]metaImport, error) {
panic("unreachable")
}
+
+func queryEscape(s string) string { panic("unreachable") }
+func openBrowser(url string) bool { panic("unreachable") }
diff --git a/libgo/go/cmd/go/bug.go b/libgo/go/cmd/go/bug.go
new file mode 100644
index 00000000000..cbd258b80bd
--- /dev/null
+++ b/libgo/go/cmd/go/bug.go
@@ -0,0 +1,213 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "regexp"
+ "runtime"
+ "strings"
+)
+
+var cmdBug = &Command{
+ Run: runBug,
+ UsageLine: "bug",
+ Short: "print information for bug reports",
+ Long: `
+Bug prints information that helps file effective bug reports.
+
+Bugs may be reported at https://golang.org/issue/new.
+ `,
+}
+
+func init() {
+ cmdBug.Flag.BoolVar(&buildV, "v", false, "")
+}
+
+func runBug(cmd *Command, args []string) {
+ var buf bytes.Buffer
+ buf.WriteString(bugHeader)
+ inspectGoVersion(&buf)
+ fmt.Fprint(&buf, "#### System details\n\n")
+ fmt.Fprintln(&buf, "```")
+ fmt.Fprintf(&buf, "go version %s %s/%s\n", runtime.Version(), runtime.GOOS, runtime.GOARCH)
+ env := newEnv
+ env = append(env, extraEnvVars()...)
+ for _, e := range env {
+ // Hide the TERM environment variable from "go bug".
+ // See issue #18128
+ if e.name != "TERM" {
+ fmt.Fprintf(&buf, "%s=\"%s\"\n", e.name, e.value)
+ }
+ }
+ printGoDetails(&buf)
+ printOSDetails(&buf)
+ printCDetails(&buf)
+ fmt.Fprintln(&buf, "```")
+
+ body := buf.String()
+ url := "https://github.com/golang/go/issues/new?body=" + queryEscape(body)
+ if !openBrowser(url) {
+ fmt.Print("Please file a new issue at golang.org/issue/new using this template:\n\n")
+ fmt.Print(body)
+ }
+}
+
+const bugHeader = `Please answer these questions before submitting your issue. Thanks!
+
+#### What did you do?
+If possible, provide a recipe for reproducing the error.
+A complete runnable program is good.
+A link on play.golang.org is best.
+
+
+#### What did you expect to see?
+
+
+#### What did you see instead?
+
+
+`
+
+func printGoDetails(w io.Writer) {
+ printCmdOut(w, "GOROOT/bin/go version: ", filepath.Join(runtime.GOROOT(), "bin/go"), "version")
+ printCmdOut(w, "GOROOT/bin/go tool compile -V: ", filepath.Join(runtime.GOROOT(), "bin/go"), "tool", "compile", "-V")
+}
+
+func printOSDetails(w io.Writer) {
+ switch runtime.GOOS {
+ case "darwin":
+ printCmdOut(w, "uname -v: ", "uname", "-v")
+ printCmdOut(w, "", "sw_vers")
+ case "linux":
+ printCmdOut(w, "uname -sr: ", "uname", "-sr")
+ printCmdOut(w, "", "lsb_release", "-a")
+ printGlibcVersion(w)
+ case "openbsd", "netbsd", "freebsd", "dragonfly":
+ printCmdOut(w, "uname -v: ", "uname", "-v")
+ case "solaris":
+ out, err := ioutil.ReadFile("/etc/release")
+ if err == nil {
+ fmt.Fprintf(w, "/etc/release: %s\n", out)
+ } else {
+ if buildV {
+ fmt.Printf("failed to read /etc/release: %v\n", err)
+ }
+ }
+ }
+}
+
+func printCDetails(w io.Writer) {
+ printCmdOut(w, "lldb --version: ", "lldb", "--version")
+ cmd := exec.Command("gdb", "--version")
+ out, err := cmd.Output()
+ if err == nil {
+ // There's apparently no combination of command line flags
+ // to get gdb to spit out its version without the license and warranty.
+ // Print up to the first newline.
+ fmt.Fprintf(w, "gdb --version: %s\n", firstLine(out))
+ } else {
+ if buildV {
+ fmt.Printf("failed to run gdb --version: %v\n", err)
+ }
+ }
+}
+
+func inspectGoVersion(w io.Writer) {
+ data, err := httpGET("https://golang.org/VERSION?m=text")
+ if err != nil {
+ if buildV {
+ fmt.Printf("failed to read from golang.org/VERSION: %v\n", err)
+ }
+ return
+ }
+
+ // golang.org/VERSION currently returns a whitespace-free string,
+ // but just in case, protect against that changing.
+ // Similarly so for runtime.Version.
+ release := string(bytes.TrimSpace(data))
+ vers := strings.TrimSpace(runtime.Version())
+
+ if vers == release {
+ // Up to date
+ return
+ }
+
+ // Devel version or outdated release. Either way, this request is apropos.
+ fmt.Fprintf(w, "#### Does this issue reproduce with the latest release (%s)?\n\n\n", release)
+}
+
+// printCmdOut prints the output of running the given command.
+// It ignores failures; 'go bug' is best effort.
+func printCmdOut(w io.Writer, prefix, path string, args ...string) {
+ cmd := exec.Command(path, args...)
+ out, err := cmd.Output()
+ if err != nil {
+ if buildV {
+ fmt.Printf("%s %s: %v\n", path, strings.Join(args, " "), err)
+ }
+ return
+ }
+ fmt.Fprintf(w, "%s%s\n", prefix, bytes.TrimSpace(out))
+}
+
+// firstLine returns the first line of a given byte slice.
+func firstLine(buf []byte) []byte {
+ idx := bytes.IndexByte(buf, '\n')
+ if idx > 0 {
+ buf = buf[:idx]
+ }
+ return bytes.TrimSpace(buf)
+}
+
+// printGlibcVersion prints information about the glibc version.
+// It ignores failures.
+func printGlibcVersion(w io.Writer) {
+ tempdir := os.TempDir()
+ if tempdir == "" {
+ return
+ }
+ src := []byte(`int main() {}`)
+ srcfile := filepath.Join(tempdir, "go-bug.c")
+ outfile := filepath.Join(tempdir, "go-bug")
+ err := ioutil.WriteFile(srcfile, src, 0644)
+ if err != nil {
+ return
+ }
+ defer os.Remove(srcfile)
+ cmd := exec.Command("gcc", "-o", outfile, srcfile)
+ if _, err = cmd.CombinedOutput(); err != nil {
+ return
+ }
+ defer os.Remove(outfile)
+
+ cmd = exec.Command("ldd", outfile)
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ return
+ }
+ re := regexp.MustCompile(`libc\.so[^ ]* => ([^ ]+)`)
+ m := re.FindStringSubmatch(string(out))
+ if m == nil {
+ return
+ }
+ cmd = exec.Command(m[1])
+ out, err = cmd.Output()
+ if err != nil {
+ return
+ }
+ fmt.Fprintf(w, "%s: %s\n", m[1], firstLine(out))
+
+ // print another line (the one containing version string) in case of musl libc
+ if idx := bytes.IndexByte(out, '\n'); bytes.Index(out, []byte("musl")) != -1 && idx > -1 {
+ fmt.Fprintf(w, "%s\n", firstLine(out[idx+1:]))
+ }
+}
diff --git a/libgo/go/cmd/go/build.go b/libgo/go/cmd/go/build.go
index 10116f282f0..a8f90344c30 100644
--- a/libgo/go/cmd/go/build.go
+++ b/libgo/go/cmd/go/build.go
@@ -346,6 +346,13 @@ func buildModeInit() {
case "darwin/arm", "darwin/arm64":
codegenArg = "-shared"
default:
+ switch goos {
+ case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
+ // Use -shared so that the result is
+ // suitable for inclusion in a PIE or
+ // shared library.
+ codegenArg = "-shared"
+ }
}
exeSuffix = ".a"
ldBuildmode = "c-archive"
@@ -407,6 +414,21 @@ func buildModeInit() {
fatalf("-buildmode=shared and -o not supported together")
}
ldBuildmode = "shared"
+ case "plugin":
+ pkgsFilter = pkgsMain
+ if gccgo {
+ codegenArg = "-fPIC"
+ } else {
+ switch platform {
+ case "linux/amd64", "linux/arm", "linux/arm64", "linux/386",
+ "android/amd64", "android/arm", "android/arm64", "android/386":
+ default:
+ fatalf("-buildmode=plugin not supported on %s\n", platform)
+ }
+ codegenArg = "-dynlink"
+ }
+ exeSuffix = ".so"
+ ldBuildmode = "plugin"
default:
fatalf("buildmode=%s not supported", buildBuildmode)
}
@@ -432,10 +454,13 @@ func buildModeInit() {
buildAsmflags = append(buildAsmflags, codegenArg)
buildGcflags = append(buildGcflags, codegenArg)
}
- if buildContext.InstallSuffix != "" {
- buildContext.InstallSuffix += "_"
+ // Don't alter InstallSuffix when modifying default codegen args.
+ if buildBuildmode != "default" || buildLinkshared {
+ if buildContext.InstallSuffix != "" {
+ buildContext.InstallSuffix += "_"
+ }
+ buildContext.InstallSuffix += codegenArg[1:]
}
- buildContext.InstallSuffix += codegenArg[1:]
}
}
@@ -452,6 +477,11 @@ func runBuild(cmd *Command, args []string) {
*buildO += exeSuffix
}
+ // Special case -o /dev/null by not writing at all.
+ if *buildO == os.DevNull {
+ *buildO = ""
+ }
+
// sanity check some often mis-used options
switch buildContext.Compiler {
case "gccgo":
@@ -580,6 +610,10 @@ func libname(args []string, pkgs []*Package) (string, error) {
}
func runInstall(cmd *Command, args []string) {
+ installPackages(args, false)
+}
+
+func installPackages(args []string, forGet bool) {
if gobin != "" && !filepath.IsAbs(gobin) {
fatalf("cannot install, GOBIN must be an absolute path")
}
@@ -599,7 +633,7 @@ func runInstall(cmd *Command, args []string) {
errorf("go install: no install location for %s: hidden by %s", p.Dir, p.ConflictDir)
default:
errorf("go install: no install location for directory %s outside GOPATH\n"+
- "\tFor more details see: go help gopath", p.Dir)
+ "\tFor more details see: 'go help gopath'", p.Dir)
}
}
}
@@ -607,6 +641,8 @@ func runInstall(cmd *Command, args []string) {
var b builder
b.init()
+ // Set the behavior for `go get` to not error on packages with test files only.
+ b.testFilesOnlyOK = forGet
var a *action
if buildBuildmode == "shared" {
if libName, err := libname(args, pkgs); err != nil {
@@ -697,6 +733,8 @@ type builder struct {
flagCache map[string]bool // a cache of supported compiler flags
print func(args ...interface{}) (int, error)
+ testFilesOnlyOK bool // do not error if the packages only have test files
+
output sync.Mutex
scriptDir string // current directory in printed script
@@ -1283,6 +1321,8 @@ func (b *builder) do(root *action) {
if err != nil {
if err == errPrintedOutput {
setExitStatus(2)
+ } else if _, ok := err.(*build.NoGoError); ok && len(a.p.TestGoFiles) > 0 && b.testFilesOnlyOK {
+ // Ignore the "no buildable Go source files" error for a package with only test files.
} else {
errorf("%s", err)
}
@@ -1369,7 +1409,7 @@ func (b *builder) build(a *action) (err error) {
}
defer func() {
- if err != nil && err != errPrintedOutput {
+ if _, ok := err.(*build.NoGoError); err != nil && err != errPrintedOutput && !(ok && b.testFilesOnlyOK && len(a.p.TestGoFiles) > 0) {
err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err)
}
}()
@@ -1400,7 +1440,7 @@ func (b *builder) build(a *action) (err error) {
}
}
- var gofiles, cgofiles, cfiles, sfiles, cxxfiles, objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string
+ var gofiles, cgofiles, objdirCgofiles, cfiles, sfiles, cxxfiles, objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string
gofiles = append(gofiles, a.p.GoFiles...)
cgofiles = append(cgofiles, a.p.CgoFiles...)
@@ -1422,7 +1462,7 @@ func (b *builder) build(a *action) (err error) {
if err != nil {
return err
}
- cgofiles = append(cgofiles, outGo...)
+ objdirCgofiles = append(objdirCgofiles, outGo...)
cfiles = append(cfiles, outC...)
cxxfiles = append(cxxfiles, outCXX...)
}
@@ -1457,7 +1497,7 @@ func (b *builder) build(a *action) (err error) {
if a.cgo != nil && a.cgo.target != "" {
cgoExe = a.cgo.target
}
- outGo, outObj, err := b.cgo(a.p, cgoExe, obj, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, cxxfiles, a.p.MFiles, a.p.FFiles)
+ outGo, outObj, err := b.cgo(a, cgoExe, obj, pcCFLAGS, pcLDFLAGS, cgofiles, objdirCgofiles, gccfiles, cxxfiles, a.p.MFiles, a.p.FFiles)
if err != nil {
return err
}
@@ -1555,12 +1595,12 @@ func (b *builder) build(a *action) (err error) {
}
// Assemble .s files.
- for _, file := range sfiles {
- out := file[:len(file)-len(".s")] + ".o"
- if err := buildToolchain.asm(b, a.p, obj, obj+out, file); err != nil {
+ if len(sfiles) > 0 {
+ ofiles, err := buildToolchain.asm(b, a.p, obj, sfiles)
+ if err != nil {
return err
}
- objects = append(objects, out)
+ objects = append(objects, ofiles...)
}
// NOTE(rsc): On Windows, it is critically important that the
@@ -1599,23 +1639,62 @@ func (b *builder) build(a *action) (err error) {
return nil
}
+// pkgconfigCmd returns a pkg-config binary name
+// defaultPkgConfig is defined in zdefaultcc.go, written by cmd/dist.
+func (b *builder) pkgconfigCmd() string {
+ return envList("PKG_CONFIG", defaultPkgConfig)[0]
+}
+
+// splitPkgConfigOutput parses the pkg-config output into a slice of
+// flags. pkg-config always uses \ to escape special characters.
+func splitPkgConfigOutput(out []byte) []string {
+ if len(out) == 0 {
+ return nil
+ }
+ var flags []string
+ flag := make([]byte, len(out))
+ r, w := 0, 0
+ for r < len(out) {
+ switch out[r] {
+ case ' ', '\t', '\r', '\n':
+ if w > 0 {
+ flags = append(flags, string(flag[:w]))
+ }
+ w = 0
+ case '\\':
+ r++
+ fallthrough
+ default:
+ if r < len(out) {
+ flag[w] = out[r]
+ w++
+ }
+ }
+ r++
+ }
+ if w > 0 {
+ flags = append(flags, string(flag[:w]))
+ }
+ return flags
+}
+
// 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)
+ out, err = b.runOut(p.Dir, p.ImportPath, nil, b.pkgconfigCmd(), "--cflags", pkgs)
if err != nil {
- b.showOutput(p.Dir, "pkg-config --cflags "+strings.Join(pkgs, " "), string(out))
+ b.showOutput(p.Dir, b.pkgconfigCmd()+" --cflags "+strings.Join(pkgs, " "), string(out))
b.print(err.Error() + "\n")
err = errPrintedOutput
return
}
if len(out) > 0 {
- cflags = strings.Fields(string(out))
+ cflags = splitPkgConfigOutput(out)
}
- out, err = b.runOut(p.Dir, p.ImportPath, nil, "pkg-config", "--libs", pkgs)
+ out, err = b.runOut(p.Dir, p.ImportPath, nil, b.pkgconfigCmd(), "--libs", pkgs)
if err != nil {
- b.showOutput(p.Dir, "pkg-config --libs "+strings.Join(pkgs, " "), string(out))
+ b.showOutput(p.Dir, b.pkgconfigCmd()+" --libs "+strings.Join(pkgs, " "), string(out))
b.print(err.Error() + "\n")
err = errPrintedOutput
return
@@ -1656,7 +1735,7 @@ func (b *builder) install(a *action) (err error) {
perm := os.FileMode(0666)
if a1.link {
switch buildBuildmode {
- case "c-archive", "c-shared":
+ case "c-archive", "c-shared", "plugin":
default:
perm = 0777
}
@@ -2197,9 +2276,9 @@ type toolchain interface {
// 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
+ // asm runs the assembler in a specific directory on specific files
+ // and returns a list of named output files.
+ asm(b *builder, p *Package, obj string, sfiles []string) ([]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
@@ -2236,8 +2315,8 @@ func (noToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
return "", nil, noCompiler()
}
-func (noToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
- return noCompiler()
+func (noToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error) {
+ return nil, noCompiler()
}
func (noToolchain) pkgpath(basedir string, p *Package) string {
@@ -2342,11 +2421,10 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
return ofile, output, err
}
-func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
+func (gcToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error) {
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
inc := filepath.Join(goroot, "pkg", "include")
- sfile = mkAbs(p.Dir, sfile)
- args := []interface{}{buildToolExec, tool("asm"), "-o", ofile, "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, buildAsmflags}
+ args := []interface{}{buildToolExec, tool("asm"), "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, buildAsmflags}
if p.ImportPath == "runtime" && goarch == "386" {
for _, arg := range buildAsmflags {
if arg == "-dynlink" {
@@ -2354,11 +2432,16 @@ func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error {
}
}
}
- args = append(args, sfile)
- if err := b.run(p.Dir, p.ImportPath, nil, args...); err != nil {
- return err
+ var ofiles []string
+ for _, sfile := range sfiles {
+ ofile := obj + sfile[:len(sfile)-len(".s")] + ".o"
+ ofiles = append(ofiles, ofile)
+ a := append(args, "-o", ofile, mkAbs(p.Dir, sfile))
+ if err := b.run(p.Dir, p.ImportPath, nil, a...); err != nil {
+ return nil, err
+ }
}
- return nil
+ return ofiles, nil
}
// toolVerify checks that the command line args writes the same output file
@@ -2516,6 +2599,13 @@ func (gcToolchain) ld(b *builder, root *action, out string, allactions []*action
if root.p.omitDWARF {
ldflags = append(ldflags, "-w")
}
+ if buildBuildmode == "plugin" {
+ pluginpath := root.p.ImportPath
+ if pluginpath == "command-line-arguments" {
+ pluginpath = "plugin/unnamed-" + root.p.buildID
+ }
+ ldflags = append(ldflags, "-pluginpath", pluginpath)
+ }
// If the user has not specified the -extld option, then specify the
// appropriate linker. In case of C++ code, use the compiler named
@@ -2625,15 +2715,24 @@ func (tools gccgoToolchain) gc(b *builder, p *Package, archive, obj string, asmh
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)
+func (tools gccgoToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error) {
+ var ofiles []string
+ for _, sfile := range sfiles {
+ ofile := obj + sfile[:len(sfile)-len(".s")] + ".o"
+ ofiles = append(ofiles, ofile)
+ 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 = tools.maybePIC(defs)
+ defs = append(defs, b.gccArchArgs()...)
+ err := b.run(p.Dir, p.ImportPath, nil, tools.compiler(), "-xassembler-with-cpp", "-I", obj, "-c", "-o", ofile, defs, sfile)
+ if err != nil {
+ return nil, err
+ }
}
- defs = tools.maybePIC(defs)
- defs = append(defs, b.gccArchArgs()...)
- return b.run(p.Dir, p.ImportPath, nil, tools.compiler(), "-xassembler-with-cpp", "-I", obj, "-c", "-o", ofile, defs, sfile)
+ return ofiles, nil
}
func (gccgoToolchain) pkgpath(basedir string, p *Package) string {
@@ -2755,7 +2854,7 @@ func (tools gccgoToolchain) link(b *builder, root *action, out string, allaction
if !apackagePathsSeen[a.p.ImportPath] {
apackagePathsSeen[a.p.ImportPath] = true
target := a.target
- if len(a.p.CgoFiles) > 0 {
+ if len(a.p.CgoFiles) > 0 || a.p.usesSwig() {
target, err = readAndRemoveCgoFlags(target)
if err != nil {
return
@@ -2947,7 +3046,7 @@ func (tools gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile stri
// maybePIC adds -fPIC to the list of arguments if needed.
func (tools gccgoToolchain) maybePIC(args []string) []string {
switch buildBuildmode {
- case "c-shared", "shared":
+ case "c-shared", "shared", "plugin":
args = append(args, "-fPIC")
}
return args
@@ -2988,9 +3087,19 @@ func (b *builder) gfortran(p *Package, out string, flags []string, ffile string)
}
// 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 {
+func (b *builder) ccompile(p *Package, outfile 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)
+ desc := p.ImportPath
+ output, err := b.runOut(p.Dir, desc, nil, compiler, flags, "-o", outfile, "-c", file)
+ if len(output) > 0 {
+ b.showOutput(p.Dir, desc, b.processOutput(output))
+ if err != nil {
+ err = errPrintedOutput
+ } else if os.Getenv("GO_BUILDER_NAME") != "" {
+ return errors.New("C compiler warning promoted to error on Go builders")
+ }
+ }
+ return err
}
// gccld runs the gcc linker to create an executable from a set of object files.
@@ -3129,6 +3238,8 @@ func (b *builder) gccArchArgs() []string {
return []string{"-m64", "-march=z196"}
case "mips64", "mips64le":
return []string{"-mabi=64"}
+ case "mips", "mipsle":
+ return []string{"-mabi=32", "-march=mips32"}
}
return nil
}
@@ -3144,11 +3255,8 @@ func envList(key, def string) []string {
}
// Return the flags to use when invoking the C, C++ or Fortran compilers, or cgo.
-func (b *builder) cflags(p *Package, def bool) (cppflags, cflags, cxxflags, fflags, ldflags []string) {
- var defaults string
- if def {
- defaults = "-g -O2"
- }
+func (b *builder) cflags(p *Package) (cppflags, cflags, cxxflags, fflags, ldflags []string) {
+ defaults := "-g -O2"
cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
@@ -3160,9 +3268,9 @@ func (b *builder) cflags(p *Package, def bool) (cppflags, cflags, cxxflags, ffla
var cgoRe = regexp.MustCompile(`[/\\:]`)
-func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, gxxfiles, mfiles, ffiles []string) (outGo, outObj []string, err error) {
- cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS := b.cflags(p, true)
- _, cgoexeCFLAGS, _, _, _ := b.cflags(p, false)
+func (b *builder) cgo(a *action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofiles, objdirCgofiles, gccfiles, gxxfiles, mfiles, ffiles []string) (outGo, outObj []string, err error) {
+ p := a.p
+ cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS := b.cflags(p)
cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...)
cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...)
// If we are compiling Objective-C code, then we need to link against libobjc
@@ -3183,7 +3291,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
}
}
- if buildMSan && p.ImportPath != "runtime/cgo" {
+ if buildMSan {
cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...)
cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...)
}
@@ -3191,20 +3299,33 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
// Allows including _cgo_export.h from .[ch] files in the package.
cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj)
+ // If we have cgo files in the object directory, then copy any
+ // other cgo files into the object directory, and pass a
+ // -srcdir option to cgo.
+ var srcdirarg []string
+ if len(objdirCgofiles) > 0 {
+ for _, fn := range cgofiles {
+ if err := b.copyFile(a, obj+filepath.Base(fn), filepath.Join(p.Dir, fn), 0666, false); err != nil {
+ return nil, nil, err
+ }
+ }
+ cgofiles = append(cgofiles, objdirCgofiles...)
+ srcdirarg = []string{"-srcdir", obj}
+ }
+
// cgo
// TODO: CGO_FLAGS?
gofiles := []string{obj + "_cgo_gotypes.go"}
- cfiles := []string{"_cgo_main.c", "_cgo_export.c"}
+ cfiles := []string{"_cgo_export.c"}
for _, fn := range 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?
+ cgoflags := []string{}
if p.Standard && p.ImportPath == "runtime/cgo" {
cgoflags = append(cgoflags, "-import_runtime_cgo=false")
}
@@ -3241,165 +3362,166 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
cgoflags = append(cgoflags, "-exportheader="+obj+"_cgo_install.h")
}
- if err := b.run(p.Dir, p.ImportPath, cgoenv, buildToolExec, cgoExe, "-objdir", obj, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoexeCFLAGS, cgofiles); err != nil {
+ if err := b.run(p.Dir, p.ImportPath, cgoenv, buildToolExec, cgoExe, srcdirarg, "-objdir", obj, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
return nil, nil, err
}
outGo = append(outGo, gofiles...)
- // cc _cgo_defun.c
- _, gccgo := buildToolchain.(gccgoToolchain)
- if gccgo {
- defunObj := obj + "_cgo_defun.o"
- 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
- // When linking relocatable objects, various flags need to be
- // filtered out as they are inapplicable and can cause some linkers
- // to fail.
- 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"):
- // 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
- // runpath flags not applicable unless building a shared
- // object or executable; see issue 12115 for details. This
- // is necessary as Go currently does not offer a way to
- // specify the set of LDFLAGS that only apply to shared
- // objects.
- case strings.HasPrefix(f, "-Wl,-rpath"):
- if f == "-Wl,-rpath" || f == "-Wl,-rpath-link" {
- // Skip following argument to -rpath* too.
- i++
- }
- default:
- bareLDFLAGS = append(bareLDFLAGS, f)
- }
- }
-
- var staticLibs []string
- if goos == "windows" {
- // libmingw32 and libmingwex have some inter-dependencies,
- // so must use linker groups.
- staticLibs = []string{"-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group"}
- }
-
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)
- }
+ outObj = append(outObj, ofile)
}
for _, file := range gccfiles {
- ofile := obj + cgoRe.ReplaceAllString(file[:len(file)-1], "_") + "o"
+ base := filepath.Base(file)
+ ofile := obj + cgoRe.ReplaceAllString(base[:len(base)-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"
+ ofile := obj + cgoRe.ReplaceAllString(filepath.Base(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"
+ ofile := obj + cgoRe.ReplaceAllString(filepath.Base(file), "_") + ".o"
if err := b.gcc(p, ofile, cflags, file); err != nil {
return nil, nil, err
}
- linkobj = append(linkobj, ofile)
outObj = append(outObj, ofile)
}
fflags := stringList(cgoCPPFLAGS, cgoFFLAGS)
for _, file := range ffiles {
// Append .o to the file, just in case the pkg has file.c and file.f
- ofile := obj + cgoRe.ReplaceAllString(file, "_") + ".o"
+ ofile := obj + cgoRe.ReplaceAllString(filepath.Base(file), "_") + ".o"
if err := b.gfortran(p, ofile, fflags, 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
+ switch buildToolchain.(type) {
+ case gcToolchain:
+ importGo := obj + "_cgo_import.go"
+ if err := b.dynimport(p, obj, importGo, cgoExe, cflags, cgoLDFLAGS, outObj); err != nil {
+ return nil, nil, err
+ }
+ outGo = append(outGo, importGo)
+
+ ofile := obj + "_all.o"
+ if err := b.collect(p, obj, ofile, cgoLDFLAGS, outObj); err != nil {
+ return nil, nil, err
+ }
+ outObj = []string{ofile}
+
+ case gccgoToolchain:
+ defunC := obj + "_cgo_defun.c"
+ defunObj := obj + "_cgo_defun.o"
+ if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
+ return nil, nil, err
+ }
+ outObj = append(outObj, defunObj)
+
+ default:
+ noCompiler()
}
- if pie { // but we don't need -pie for normal cgo programs
- cgoLDFLAGS = cgoLDFLAGS[0 : len(cgoLDFLAGS)-1]
+
+ return outGo, outObj, nil
+}
+
+// dynimport creates a Go source file named importGo containing
+// //go:cgo_import_dynamic directives for each symbol or library
+// dynamically imported by the object files outObj.
+func (b *builder) dynimport(p *Package, obj, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) error {
+ cfile := obj + "_cgo_main.c"
+ ofile := obj + "_cgo_main.o"
+ if err := b.gcc(p, ofile, cflags, cfile); err != nil {
+ return err
}
- if _, ok := buildToolchain.(gccgoToolchain); ok {
- // we don't use dynimport when using gccgo.
- return outGo, outObj, nil
+ linkobj := stringList(ofile, outObj, p.SysoFiles)
+ dynobj := obj + "_cgo_.o"
+
+ // we need to use -pie for Linux/ARM to get accurate imported sym
+ ldflags := cgoLDFLAGS
+ if (goarch == "arm" && goos == "linux") || goos == "android" {
+ ldflags = append(ldflags, "-pie")
+ }
+ if err := b.gccld(p, dynobj, ldflags, linkobj); err != nil {
+ return err
}
// cgo -dynimport
- importGo := obj + "_cgo_import.go"
- cgoflags = []string{}
+ var 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, buildToolExec, cgoExe, "-objdir", obj, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags); err != nil {
- return nil, nil, err
+ cgoflags = []string{"-dynlinker"} // record path to dynamic linker
}
- outGo = append(outGo, importGo)
+ return b.run(p.Dir, p.ImportPath, nil, buildToolExec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
+}
- 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)
+// collect partially links the object files outObj into a single
+// relocatable object file named ofile.
+func (b *builder) collect(p *Package, obj, ofile string, cgoLDFLAGS, outObj []string) error {
+ // When linking relocatable objects, various flags need to be
+ // filtered out as they are inapplicable and can cause some linkers
+ // to fail.
+ var ldflags []string
+ 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,o,a}"
+ case strings.HasSuffix(f, ".dylib"),
+ strings.HasSuffix(f, ".so"),
+ strings.HasSuffix(f, ".dll"),
+ strings.HasSuffix(f, ".o"),
+ strings.HasSuffix(f, ".a"):
+ // 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
+ // runpath flags not applicable unless building a shared
+ // object or executable; see issue 12115 for details. This
+ // is necessary as Go currently does not offer a way to
+ // specify the set of LDFLAGS that only apply to shared
+ // objects.
+ case strings.HasPrefix(f, "-Wl,-rpath"):
+ if f == "-Wl,-rpath" || f == "-Wl,-rpath-link" {
+ // Skip following argument to -rpath* too.
+ i++
+ }
+ default:
+ ldflags = append(ldflags, f)
}
}
- ldflags := stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs)
+
+ ldflags = append(ldflags, "-Wl,-r", "-nostdlib")
if b.gccSupportsNoPie() {
ldflags = append(ldflags, "-no-pie")
@@ -3408,16 +3530,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
// We are creating an object file, so we don't want a build ID.
ldflags = b.disableBuildID(ldflags)
- 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. https://golang.org/issue/2601
- outObj = stringList(nonGccObjs, ofile)
-
- return outGo, outObj, nil
+ return b.gccld(p, ofile, ldflags, outObj)
}
// Run SWIG on all SWIG input files.
@@ -3570,7 +3683,7 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) {
// Run SWIG on one SWIG input file.
func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) {
- cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _ := b.cflags(p, true)
+ cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _ := b.cflags(p)
var cflags []string
if cxx {
cflags = stringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
@@ -3633,7 +3746,7 @@ func (b *builder) swigOne(p *Package, file, obj string, pcCFLAGS []string, cxx b
b.showOutput(p.Dir, p.ImportPath, b.processOutput(out)) // swig warning
}
- return obj + goFile, obj + gccBase + gccExt, nil
+ return goFile, obj + gccBase + gccExt, nil
}
// disableBuildID adjusts a linker command line to avoid creating a
@@ -3682,7 +3795,11 @@ func instrumentInit() {
return
}
if buildRace && buildMSan {
- fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously", flag.Args()[0])
+ fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0])
+ os.Exit(2)
+ }
+ if buildMSan && (goos != "linux" || goarch != "amd64") {
+ fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", goos, goarch)
os.Exit(2)
}
if goarch != "amd64" || goos != "linux" && goos != "freebsd" && goos != "darwin" && goos != "windows" {
diff --git a/libgo/go/cmd/go/build_test.go b/libgo/go/cmd/go/build_test.go
new file mode 100644
index 00000000000..79bbd545915
--- /dev/null
+++ b/libgo/go/cmd/go/build_test.go
@@ -0,0 +1,44 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "os"
+ "reflect"
+ "testing"
+)
+
+func TestRemoveDevNull(t *testing.T) {
+ fi, err := os.Lstat(os.DevNull)
+ if err != nil {
+ t.Skip(err)
+ }
+ if fi.Mode().IsRegular() {
+ t.Errorf("Lstat(%s).Mode().IsRegular() = true; expected false", os.DevNull)
+ }
+ mayberemovefile(os.DevNull)
+ _, err = os.Lstat(os.DevNull)
+ if err != nil {
+ t.Errorf("mayberemovefile(%s) did remove it; oops", os.DevNull)
+ }
+}
+
+func TestSplitPkgConfigOutput(t *testing.T) {
+ for _, test := range []struct {
+ in []byte
+ want []string
+ }{
+ {[]byte(`-r:foo -L/usr/white\ space/lib -lfoo\ bar -lbar\ baz`), []string{"-r:foo", "-L/usr/white space/lib", "-lfoo bar", "-lbar baz"}},
+ {[]byte(`-lextra\ fun\ arg\\`), []string{`-lextra fun arg\`}},
+ {[]byte(`broken flag\`), []string{"broken", "flag"}},
+ {[]byte("\textra whitespace\r\n"), []string{"extra", "whitespace"}},
+ {[]byte(" \r\n "), nil},
+ } {
+ got := splitPkgConfigOutput(test.in)
+ if !reflect.DeepEqual(got, test.want) {
+ t.Errorf("splitPkgConfigOutput(%v) = %v; want %v", test.in, got, test.want)
+ }
+ }
+}
diff --git a/libgo/go/cmd/go/env.go b/libgo/go/cmd/go/env.go
index 8aaaf463292..31710b7e6d6 100644
--- a/libgo/go/cmd/go/env.go
+++ b/libgo/go/cmd/go/env.go
@@ -40,7 +40,7 @@ func mkEnv() []envVar {
{"GOHOSTARCH", runtime.GOARCH},
{"GOHOSTOS", runtime.GOOS},
{"GOOS", goos},
- {"GOPATH", os.Getenv("GOPATH")},
+ {"GOPATH", buildContext.GOPATH},
{"GORACE", os.Getenv("GORACE")},
{"GOROOT", goroot},
{"GOTOOLDIR", toolDir},
@@ -49,14 +49,25 @@ func mkEnv() []envVar {
{"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 gccgoBin != "" {
+ env = append(env, envVar{"GCCGO", gccgoBin})
+ } else {
+ env = append(env, envVar{"GCCGO", gccgoName})
+ }
+
+ switch goarch {
+ case "arm":
+ env = append(env, envVar{"GOARM", os.Getenv("GOARM")})
+ case "386":
+ env = append(env, envVar{"GO386", os.Getenv("GO386")})
}
+ 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 {
@@ -75,8 +86,24 @@ func findEnv(env []envVar, name string) string {
return ""
}
+// extraEnvVars returns environment variables that should not leak into child processes.
+func extraEnvVars() []envVar {
+ var b builder
+ b.init()
+ cppflags, cflags, cxxflags, fflags, ldflags := b.cflags(&Package{})
+ return []envVar{
+ {"PKG_CONFIG", b.pkgconfigCmd()},
+ {"CGO_CFLAGS", strings.Join(cflags, " ")},
+ {"CGO_CPPFLAGS", strings.Join(cppflags, " ")},
+ {"CGO_CXXFLAGS", strings.Join(cxxflags, " ")},
+ {"CGO_FFLAGS", strings.Join(fflags, " ")},
+ {"CGO_LDFLAGS", strings.Join(ldflags, " ")},
+ }
+}
+
func runEnv(cmd *Command, args []string) {
- env := mkEnv()
+ env := newEnv
+ env = append(env, extraEnvVars()...)
if len(args) > 0 {
for _, name := range args {
fmt.Printf("%s\n", findEnv(env, name))
diff --git a/libgo/go/cmd/go/generate.go b/libgo/go/cmd/go/generate.go
index 3c6065e89aa..2d92a0c100c 100644
--- a/libgo/go/cmd/go/generate.go
+++ b/libgo/go/cmd/go/generate.go
@@ -25,7 +25,7 @@ var cmdGenerate = &Command{
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.
+create or update Go source files.
Go generate is never run automatically by go build, go get, go test,
and so on. It must be run explicitly.
@@ -88,10 +88,10 @@ 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
+ //go:generate -command foo go tool foo
-specifies that the command "yacc" represents the generator
-"go tool yacc".
+specifies that the command "foo" represents the generator
+"go tool foo".
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
@@ -136,6 +136,8 @@ func init() {
}
func runGenerate(cmd *Command, args []string) {
+ ignoreImports = true
+
if generateRunFlag != "" {
var err error
generateRunRE, err = regexp.Compile(generateRunFlag)
diff --git a/libgo/go/cmd/go/get.go b/libgo/go/cmd/go/get.go
index 19858f7e55d..1d7677c615c 100644
--- a/libgo/go/cmd/go/get.go
+++ b/libgo/go/cmd/go/get.go
@@ -43,11 +43,13 @@ 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.
+The -v flag enables verbose progress and debug output.
+
Get also accepts build flags to control the installation. See 'go help build'.
When checking out a new package, get creates the target directory
GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
-get uses the first one. See 'go help gopath'.
+get uses the first one. For more details see: 'go help gopath'.
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
@@ -96,13 +98,31 @@ func runGet(cmd *Command, args []string) {
os.Setenv("GIT_TERMINAL_PROMPT", "0")
}
+ // Disable any ssh connection pooling by Git.
+ // If a Git subprocess forks a child into the background to cache a new connection,
+ // that child keeps stdout/stderr open. After the Git subprocess exits,
+ // os /exec expects to be able to read from the stdout/stderr pipe
+ // until EOF to get all the data that the Git subprocess wrote before exiting.
+ // The EOF doesn't come until the child exits too, because the child
+ // is holding the write end of the pipe.
+ // This is unfortunate, but it has come up at least twice
+ // (see golang.org/issue/13453 and golang.org/issue/16104)
+ // and confuses users when it does.
+ // If the user has explicitly set GIT_SSH or GIT_SSH_COMMAND,
+ // assume they know what they are doing and don't step on it.
+ // But default to turning off ControlMaster.
+ if os.Getenv("GIT_SSH") == "" && os.Getenv("GIT_SSH_COMMAND") == "" {
+ os.Setenv("GIT_SSH_COMMAND", "ssh -o ControlMaster=no")
+ }
+
// Phase 1. Download/update.
var stk importStack
mode := 0
if *getT {
mode |= getTestDeps
}
- for _, arg := range downloadPaths(args) {
+ args = downloadPaths(args)
+ for _, arg := range args {
download(arg, nil, &stk, mode)
}
exitIfErrors()
@@ -137,7 +157,7 @@ func runGet(cmd *Command, args []string) {
return
}
- runInstall(cmd, args)
+ installPackages(args, true)
}
// downloadPaths prepares the list of paths to pass to download.
@@ -177,7 +197,7 @@ 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
+// For example, all the packages in the github.com/google/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{}
@@ -185,6 +205,10 @@ 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, parent *Package, stk *importStack, mode int) {
+ if mode&useVendor != 0 {
+ // Caller is responsible for expanding vendor paths.
+ panic("internal error: download mode has useVendor set")
+ }
load := func(path string, mode int) *Package {
if parent == nil {
return loadPackage(path, stk)
@@ -295,32 +319,42 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
}
// Process dependencies, now that we know what they are.
- for _, path := range p.Imports {
+ imports := p.Imports
+ if mode&getTestDeps != 0 {
+ // Process test dependencies when -t is specified.
+ // (But don't get test dependencies for test dependencies:
+ // we always pass mode 0 to the recursive calls below.)
+ imports = stringList(imports, p.TestImports, p.XTestImports)
+ }
+ for i, path := range imports {
if path == "C" {
continue
}
- // Don't get test dependencies recursively.
- // Imports is already vendor-expanded.
- download(path, p, stk, 0)
- }
- if mode&getTestDeps != 0 {
- // Process test dependencies when -t is specified.
- // (Don't get test dependencies for test dependencies.)
- // We pass useVendor here because p.load does not
- // vendor-expand TestImports and XTestImports.
- // The call to loadImport inside download needs to do that.
- for _, path := range p.TestImports {
- if path == "C" {
- continue
- }
- download(path, p, stk, useVendor)
+ // Fail fast on import naming full vendor path.
+ // Otherwise expand path as needed for test imports.
+ // Note that p.Imports can have additional entries beyond p.build.Imports.
+ orig := path
+ if i < len(p.build.Imports) {
+ orig = p.build.Imports[i]
}
- for _, path := range p.XTestImports {
- if path == "C" {
- continue
+ if j, ok := findVendor(orig); ok {
+ stk.push(path)
+ err := &PackageError{
+ ImportStack: stk.copy(),
+ Err: "must be imported as " + path[j+len("vendor/"):],
}
- download(path, p, stk, useVendor)
+ stk.pop()
+ errorf("%s", err)
+ continue
+ }
+ // If this is a test import, apply vendor lookup now.
+ // We cannot pass useVendor to download, because
+ // download does caching based on the value of path,
+ // so it must be the fully qualified path already.
+ if i >= len(p.Imports) {
+ path = vendoredImportPath(p, path)
}
+ download(path, p, stk, 0)
}
if isWildcard {
@@ -368,7 +402,7 @@ func downloadPackage(p *Package) error {
repo = resolved
}
}
- if remote != repo && p.ImportComment != "" {
+ if remote != repo && rr.isCustom {
return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.root, repo, dir, remote)
}
}
@@ -391,12 +425,16 @@ func downloadPackage(p *Package) error {
// 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")
+ 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")
+ return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: 'go help gopath'")
}
+ if _, err := os.Stat(filepath.Join(list[0], "src/cmd/go/alldocs.go")); err == nil {
+ return fmt.Errorf("cannot download, %s is a GOROOT, not a GOPATH. For more details see: 'go help gopath'", list[0])
+ }
+ p.build.Root = list[0]
p.build.SrcRoot = filepath.Join(list[0], "src")
p.build.PkgRoot = filepath.Join(list[0], "pkg")
}
@@ -425,11 +463,19 @@ func downloadPackage(p *Package) error {
if _, err := os.Stat(root); err == nil {
return fmt.Errorf("%s exists but %s does not - stale checkout?", root, meta)
}
+
+ _, err := os.Stat(p.build.Root)
+ gopathExisted := err == nil
+
// 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 buildV && !gopathExisted && p.build.Root == buildContext.GOPATH {
+ fmt.Fprintf(os.Stderr, "created GOPATH=%s; see 'go help gopath'\n", p.build.Root)
+ }
+
if err = vcs.create(root, repo); err != nil {
return err
}
diff --git a/libgo/go/cmd/go/go_test.go b/libgo/go/cmd/go/go_test.go
index 66c641347cb..5727eb094e5 100644
--- a/libgo/go/cmd/go/go_test.go
+++ b/libgo/go/cmd/go/go_test.go
@@ -6,7 +6,6 @@ package main_test
import (
"bytes"
- "flag"
"fmt"
"go/build"
"go/format"
@@ -50,6 +49,17 @@ func init() {
// many linux/arm machines are too slow to run
// the full set of external tests.
skipExternal = true
+ case "mips", "mipsle", "mips64", "mips64le":
+ // Also slow.
+ skipExternal = true
+ if testenv.Builder() != "" {
+ // On the builders, skip the cmd/go
+ // tests. They're too slow and already
+ // covered by other ports. There's
+ // nothing os/arch specific in the
+ // tests.
+ canRun = false
+ }
}
case "freebsd":
switch runtime.GOARCH {
@@ -67,8 +77,6 @@ func init() {
// The TestMain function creates a go command for testing purposes and
// deletes it after the tests have been run.
func TestMain(m *testing.M) {
- flag.Parse()
-
if canRun {
args := []string{"build", "-tags", "testgo", "-o", "testgo" + exeSuffix}
if race.Enabled {
@@ -99,6 +107,14 @@ func TestMain(m *testing.M) {
// Don't let these environment variables confuse the test.
os.Unsetenv("GOBIN")
os.Unsetenv("GOPATH")
+ os.Unsetenv("GIT_ALLOW_PROTOCOL")
+ if home, ccacheDir := os.Getenv("HOME"), os.Getenv("CCACHE_DIR"); home != "" && ccacheDir == "" {
+ // On some systems the default C compiler is ccache.
+ // Setting HOME to a non-existent directory will break
+ // those systems. Set CCACHE_DIR to cope. Issue 17668.
+ os.Setenv("CCACHE_DIR", filepath.Join(home, ".ccache"))
+ }
+ os.Setenv("HOME", "/test-go-home-does-not-exist")
r := m.Run()
@@ -627,6 +643,7 @@ func TestProgramNameInCrashMessages(t *testing.T) {
func TestBrokenTestsWithoutTestFunctionsAllFail(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ // TODO: tg.parallel()
tg.runFail("test", "./testdata/src/badtest/...")
tg.grepBothNot("^ok", "test passed unexpectedly")
tg.grepBoth("FAIL.*badtest/badexec", "test did not run everything")
@@ -742,6 +759,7 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
func TestGoListStandard(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ // TODO: tg.parallel()
tg.cd(runtime.GOROOT() + "/src")
tg.run("list", "-f", "{{if not .Standard}}{{.ImportPath}}{{end}}", "./...")
stdout := tg.getStdout()
@@ -766,6 +784,7 @@ func TestGoListStandard(t *testing.T) {
func TestGoInstallCleansUpAfterGoBuild(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ // TODO: tg.parallel()
tg.tempFile("src/mycmd/main.go", `package main; func main(){}`)
tg.setenv("GOPATH", tg.path("."))
tg.cd(tg.path("src/mycmd"))
@@ -857,6 +876,7 @@ func TestGoInstallDetectsRemovedFiles(t *testing.T) {
func TestWildcardMatchesSyntaxErrorDirs(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ // TODO: tg.parallel()
tg.tempFile("src/mypkg/x.go", `package mypkg`)
tg.tempFile("src/mypkg/y.go", `pkg mypackage`)
tg.setenv("GOPATH", tg.path("."))
@@ -1013,6 +1033,7 @@ func copyBad(tg *testgoData) {
func TestBadImportsEasy(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ // TODO: tg.parallel()
copyBad(tg)
testLocalEasy(tg, badDirName)
}
@@ -1042,14 +1063,14 @@ func TestInternalPackagesInGOROOTAreRespected(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.runFail("build", "-v", "./testdata/testinternal")
- tg.grepBoth("use of internal package not allowed", "wrong error message for testdata/testinternal")
+ tg.grepBoth(`testinternal(\/|\\)p\.go\:3\:8\: use of internal package not allowed`, "wrong error message for testdata/testinternal")
}
func TestInternalPackagesOutsideGOROOTAreRespected(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.runFail("build", "-v", "./testdata/testinternal2")
- tg.grepBoth("use of internal package not allowed", "wrote error message for testdata/testinternal2")
+ tg.grepBoth(`testinternal2(\/|\\)p\.go\:3\:8\: use of internal package not allowed`, "wrote error message for testdata/testinternal2")
}
func TestRunInternal(t *testing.T) {
@@ -1059,7 +1080,7 @@ func TestRunInternal(t *testing.T) {
tg.setenv("GOPATH", dir)
tg.run("run", filepath.Join(dir, "src/run/good.go"))
tg.runFail("run", filepath.Join(dir, "src/run/bad.go"))
- tg.grepStderr("use of internal package not allowed", "unexpected error for run/bad.go")
+ tg.grepStderr(`testdata(\/|\\)src(\/|\\)run(\/|\\)bad\.go\:3\:8\: use of internal package not allowed`, "unexpected error for run/bad.go")
}
func testMove(t *testing.T, vcs, url, base, config string) {
@@ -1180,6 +1201,23 @@ func TestIssue10952(t *testing.T) {
tg.run("get", "-d", "-u", importPath)
}
+func TestIssue16471(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+ if _, err := exec.LookPath("git"); err != nil {
+ t.Skip("skipping because git binary not found")
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.tempDir("src")
+ tg.setenv("GOPATH", tg.path("."))
+ tg.must(os.MkdirAll(tg.path("src/rsc.io/go-get-issue-10952"), 0755))
+ tg.runGit(tg.path("src/rsc.io"), "clone", "https://github.com/zombiezen/go-get-issue-10952")
+ tg.runFail("get", "-u", "rsc.io/go-get-issue-10952")
+ tg.grepStderr("rsc.io/go-get-issue-10952 is a custom import path for https://github.com/rsc/go-get-issue-10952, but .* is checked out from https://github.com/zombiezen/go-get-issue-10952", "did not detect updated import path")
+}
+
// Test git clone URL that uses SCP-like syntax and custom import path checking.
func TestIssue11457(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
@@ -1192,7 +1230,7 @@ func TestIssue11457(t *testing.T) {
tg.parallel()
tg.tempDir("src")
tg.setenv("GOPATH", tg.path("."))
- const importPath = "github.com/rsc/go-get-issue-11457"
+ const importPath = "rsc.io/go-get-issue-11457"
tg.run("get", "-d", "-u", importPath)
repoDir := tg.path("src/" + importPath)
tg.runGit(repoDir, "remote", "set-url", "origin", "git@github.com:rsc/go-get-issue-11457")
@@ -1267,11 +1305,23 @@ func TestRelativeImportsGoTestDashI(t *testing.T) {
func TestRelativeImportsInCommandLinePackage(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ // TODO: tg.parallel()
files, err := filepath.Glob("./testdata/testimport/*.go")
tg.must(err)
tg.run(append([]string{"test"}, files...)...)
}
+func TestNonCanonicalImportPaths(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.runFail("build", "canonical/d")
+ tg.grepStderr("package canonical/d", "did not report canonical/d")
+ tg.grepStderr("imports canonical/b", "did not report canonical/b")
+ tg.grepStderr("imports canonical/a/: non-canonical", "did not report canonical/a/")
+}
+
func TestVersionControlErrorMessageIncludesCorrectDirectory(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -1317,9 +1367,6 @@ func TestInstallIntoGOPATH(t *testing.T) {
// Issue 12407
func TestBuildOutputToDevNull(t *testing.T) {
- if runtime.GOOS == "plan9" {
- t.Skip("skipping because /dev/null is a regular file on plan9")
- }
tg := testgo(t)
defer tg.cleanup()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
@@ -1430,6 +1477,17 @@ func TestGoGetNonPkg(t *testing.T) {
tg.grepStderr("golang.org/x/tools: no buildable Go source files", "missing error")
}
+func TestGoGetTestOnlyPkg(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.tempDir("gopath")
+ tg.setenv("GOPATH", tg.path("gopath"))
+ tg.run("get", "golang.org/x/tour/content")
+ tg.run("get", "-t", "golang.org/x/tour/content")
+}
+
func TestInstalls(t *testing.T) {
if testing.Short() {
t.Skip("don't install into GOROOT in short mode")
@@ -1511,6 +1569,7 @@ func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
func TestGoListHasAConsistentOrder(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.run("list", "std")
first := tg.getStdout()
tg.run("list", "std")
@@ -1522,6 +1581,7 @@ func TestGoListHasAConsistentOrder(t *testing.T) {
func TestGoListStdDoesNotIncludeCommands(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.run("list", "std")
tg.grepStdoutNot("cmd/", "go list std shows commands")
}
@@ -1529,6 +1589,7 @@ func TestGoListStdDoesNotIncludeCommands(t *testing.T) {
func TestGoListCmdOnlyShowsCommands(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.run("list", "cmd")
out := strings.TrimSpace(tg.getStdout())
for _, line := range strings.Split(out, "\n") {
@@ -1542,6 +1603,7 @@ func TestGoListCmdOnlyShowsCommands(t *testing.T) {
func TestGoListDedupsPackages(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ // TODO: tg.parallel()
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
tg.run("list", "xtestonly", "./testdata/src/xtestonly/...")
got := strings.TrimSpace(tg.getStdout())
@@ -1555,6 +1617,7 @@ func TestGoListDedupsPackages(t *testing.T) {
func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.runFail("install", "foo/quxx")
if tg.grepCountBoth(`cannot find package "foo/quxx" in any of`) != 1 {
t.Error(`go install foo/quxx expected error: .*cannot find package "foo/quxx" in any of`)
@@ -1564,6 +1627,7 @@ func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
func TestGOROOTSearchFailureReporting(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.runFail("install", "foo/quxx")
if tg.grepCountBoth(regexp.QuoteMeta(filepath.Join("foo", "quxx"))+` \(from \$GOROOT\)$`) != 1 {
t.Error(`go install foo/quxx expected error: .*foo/quxx (from $GOROOT)`)
@@ -1573,6 +1637,7 @@ func TestGOROOTSearchFailureReporting(t *testing.T) {
func TestMultipleGOPATHEntriesReportedSeparately(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
sep := string(filepath.ListSeparator)
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
tg.runFail("install", "foo/quxx")
@@ -1585,6 +1650,7 @@ func TestMultipleGOPATHEntriesReportedSeparately(t *testing.T) {
func TestMentionGOPATHInFirstGOPATHEntry(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
sep := string(filepath.ListSeparator)
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
tg.runFail("install", "foo/quxx")
@@ -1597,6 +1663,7 @@ func TestMentionGOPATHInFirstGOPATHEntry(t *testing.T) {
func TestMentionGOPATHNotOnSecondEntry(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
sep := string(filepath.ListSeparator)
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata", "a")+sep+filepath.Join(tg.pwd(), "testdata", "b"))
tg.runFail("install", "foo/quxx")
@@ -1605,14 +1672,156 @@ func TestMentionGOPATHNotOnSecondEntry(t *testing.T) {
}
}
-// Test missing GOPATH is reported.
-func TestMissingGOPATHIsReported(t *testing.T) {
+func homeEnvName() string {
+ switch runtime.GOOS {
+ case "windows":
+ return "USERPROFILE"
+ case "plan9":
+ return "home"
+ default:
+ return "HOME"
+ }
+}
+
+// Test go env missing GOPATH shows default.
+func TestMissingGOPATHEnvShowsDefault(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.setenv("GOPATH", "")
- tg.runFail("install", "foo/quxx")
- if tg.grepCountBoth(`\(\$GOPATH not set\)$`) != 1 {
- t.Error(`go install foo/quxx expected error: ($GOPATH not set)`)
+ tg.run("env", "GOPATH")
+
+ want := filepath.Join(os.Getenv(homeEnvName()), "go")
+ got := strings.TrimSpace(tg.getStdout())
+ if got != want {
+ t.Errorf("got %q; want %q", got, want)
+ }
+}
+
+// Test go get missing GOPATH causes go get to warn if directory doesn't exist.
+func TestMissingGOPATHGetWarnsIfNotExists(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ if _, err := exec.LookPath("git"); err != nil {
+ t.Skip("skipping because git binary not found")
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+
+ // setenv variables for test and defer deleting temporary home directory.
+ tg.setenv("GOPATH", "")
+ tmp, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("could not create tmp home: %v", err)
+ }
+ defer os.RemoveAll(tmp)
+ tg.setenv(homeEnvName(), tmp)
+
+ tg.run("get", "-v", "github.com/golang/example/hello")
+
+ want := fmt.Sprintf("created GOPATH=%s; see 'go help gopath'", filepath.Join(tmp, "go"))
+ got := strings.TrimSpace(tg.getStderr())
+ if !strings.Contains(got, want) {
+ t.Errorf("got %q; want %q", got, want)
+ }
+}
+
+// Test go get missing GOPATH causes no warning if directory exists.
+func TestMissingGOPATHGetDoesntWarnIfExists(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ if _, err := exec.LookPath("git"); err != nil {
+ t.Skip("skipping because git binary not found")
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+
+ // setenv variables for test and defer resetting them.
+ tg.setenv("GOPATH", "")
+ tmp, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("could not create tmp home: %v", err)
+ }
+ defer os.RemoveAll(tmp)
+ if err := os.Mkdir(filepath.Join(tmp, "go"), 0777); err != nil {
+ t.Fatalf("could not create $HOME/go: %v", err)
+ }
+
+ tg.setenv(homeEnvName(), tmp)
+
+ tg.run("get", "github.com/golang/example/hello")
+
+ got := strings.TrimSpace(tg.getStderr())
+ if got != "" {
+ t.Errorf("got %q; wants empty", got)
+ }
+}
+
+// Test go get missing GOPATH fails if pointed file is not a directory.
+func TestMissingGOPATHGetFailsIfItsNotDirectory(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ tg := testgo(t)
+ defer tg.cleanup()
+
+ // setenv variables for test and defer resetting them.
+ tg.setenv("GOPATH", "")
+ tmp, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("could not create tmp home: %v", err)
+ }
+ defer os.RemoveAll(tmp)
+
+ path := filepath.Join(tmp, "go")
+ if err := ioutil.WriteFile(path, nil, 0777); err != nil {
+ t.Fatalf("could not create GOPATH at %s: %v", path, err)
+ }
+ tg.setenv(homeEnvName(), tmp)
+
+ const pkg = "github.com/golang/example/hello"
+ tg.runFail("get", pkg)
+
+ msg := "not a directory"
+ if runtime.GOOS == "windows" {
+ msg = "The system cannot find the path specified."
+ }
+ want := fmt.Sprintf("package %s: mkdir %s: %s", pkg, filepath.Join(tmp, "go"), msg)
+ got := strings.TrimSpace(tg.getStderr())
+ if got != want {
+ t.Errorf("got %q; wants %q", got, want)
+ }
+}
+
+// Test go install of missing package when missing GOPATH fails and shows default GOPATH.
+func TestMissingGOPATHInstallMissingPackageFailsAndShowsDefault(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+
+ // setenv variables for test and defer resetting them.
+ tg.setenv("GOPATH", "")
+ tmp, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("could not create tmp home: %v", err)
+ }
+ defer os.RemoveAll(tmp)
+ if err := os.Mkdir(filepath.Join(tmp, "go"), 0777); err != nil {
+ t.Fatalf("could not create $HOME/go: %v", err)
+ }
+ tg.setenv(homeEnvName(), tmp)
+
+ const pkg = "github.com/golang/example/hello"
+ tg.runFail("install", pkg)
+
+ pkgPath := filepath.Join(strings.Split(pkg, "/")...)
+ want := fmt.Sprintf("can't load package: package %s: cannot find package \"%s\" in any of:", pkg, pkg) +
+ fmt.Sprintf("\n\t%s (from $GOROOT)", filepath.Join(runtime.GOROOT(), "src", pkgPath)) +
+ fmt.Sprintf("\n\t%s (from $GOPATH)", filepath.Join(tmp, "go", "src", pkgPath))
+
+ got := strings.TrimSpace(tg.getStderr())
+ if got != want {
+ t.Errorf("got %q; wants %q", got, want)
}
}
@@ -1659,6 +1868,7 @@ func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
func TestGoTestCpuprofileLeavesBinaryBehind(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ // TODO: tg.parallel()
tg.makeTempdir()
tg.cd(tg.path("."))
tg.run("test", "-cpuprofile", "errors.prof", "errors")
@@ -1668,12 +1878,33 @@ func TestGoTestCpuprofileLeavesBinaryBehind(t *testing.T) {
func TestGoTestCpuprofileDashOControlsBinaryLocation(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ // TODO: tg.parallel()
tg.makeTempdir()
tg.cd(tg.path("."))
tg.run("test", "-cpuprofile", "errors.prof", "-o", "myerrors.test"+exeSuffix, "errors")
tg.wantExecutable("myerrors.test"+exeSuffix, "go test -cpuprofile -o myerrors.test did not create myerrors.test")
}
+func TestGoTestMutexprofileLeavesBinaryBehind(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ // TODO: tg.parallel()
+ tg.makeTempdir()
+ tg.cd(tg.path("."))
+ tg.run("test", "-mutexprofile", "errors.prof", "errors")
+ tg.wantExecutable("errors.test"+exeSuffix, "go test -mutexprofile did not create errors.test")
+}
+
+func TestGoTestMutexprofileDashOControlsBinaryLocation(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ // TODO: tg.parallel()
+ tg.makeTempdir()
+ tg.cd(tg.path("."))
+ tg.run("test", "-mutexprofile", "errors.prof", "-o", "myerrors.test"+exeSuffix, "errors")
+ tg.wantExecutable("myerrors.test"+exeSuffix, "go test -mutexprofile -o myerrors.test did not create myerrors.test")
+}
+
func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -1692,6 +1923,16 @@ func TestGoTestDashOWritesBinary(t *testing.T) {
tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
}
+func TestGoTestDashIDashOWritesBinary(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.makeTempdir()
+ tg.run("test", "-v", "-i", "-o", tg.path("myerrors.test"+exeSuffix), "errors")
+ tg.grepBothNot("PASS|FAIL", "test should not have run")
+ tg.wantExecutable(tg.path("myerrors.test"+exeSuffix), "go test -o myerrors.test did not create myerrors.test")
+}
+
// Issue 4568.
func TestSymlinksList(t *testing.T) {
switch runtime.GOOS {
@@ -1701,6 +1942,7 @@ func TestSymlinksList(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ // TODO: tg.parallel()
tg.tempDir("src")
tg.must(os.Symlink(tg.path("."), tg.path("src/dir1")))
tg.tempFile("src/dir1/p.go", "package p")
@@ -1721,6 +1963,7 @@ func TestSymlinksVendor(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ // TODO: tg.parallel()
tg.tempDir("gopath/src/dir1/vendor/v")
tg.tempFile("gopath/src/dir1/p.go", "package main\nimport _ `v`\nfunc main(){}")
tg.tempFile("gopath/src/dir1/vendor/v/v.go", "package v")
@@ -1738,6 +1981,27 @@ func TestSymlinksVendor(t *testing.T) {
tg.run("install")
}
+// Issue 15201.
+func TestSymlinksVendor15201(t *testing.T) {
+ switch runtime.GOOS {
+ case "plan9", "windows":
+ t.Skipf("skipping symlink test on %s", runtime.GOOS)
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+
+ tg.tempDir("gopath/src/x/y/_vendor/src/x")
+ tg.must(os.Symlink("../../..", tg.path("gopath/src/x/y/_vendor/src/x/y")))
+ tg.tempFile("gopath/src/x/y/w/w.go", "package w\nimport \"x/y/z\"\n")
+ tg.must(os.Symlink("../_vendor/src", tg.path("gopath/src/x/y/w/vendor")))
+ tg.tempFile("gopath/src/x/y/z/z.go", "package z\n")
+
+ tg.setenv("GOPATH", tg.path("gopath/src/x/y/_vendor")+string(filepath.ListSeparator)+tg.path("gopath"))
+ tg.cd(tg.path("gopath/src"))
+ tg.run("list", "./...")
+}
+
func TestSymlinksInternal(t *testing.T) {
switch runtime.GOOS {
case "plan9", "windows":
@@ -1829,9 +2093,7 @@ func TestCaseCollisions(t *testing.T) {
// Issue 8181.
func TestGoGetDashTIssue8181(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping test that uses network in short mode")
- }
+ testenv.MustHaveExternalNetwork(t)
tg := testgo(t)
defer tg.cleanup()
@@ -1840,14 +2102,12 @@ func TestGoGetDashTIssue8181(t *testing.T) {
tg.setenv("GOPATH", tg.path("."))
tg.run("get", "-v", "-t", "github.com/rsc/go-get-issue-8181/a", "github.com/rsc/go-get-issue-8181/b")
tg.run("list", "...")
- tg.grepStdout("x/build/cmd/cl", "missing expected x/build/cmd/cl")
+ tg.grepStdout("x/build/gerrit", "missing expected x/build/gerrit")
}
func TestIssue11307(t *testing.T) {
// go get -u was not working except in checkout directory
- if testing.Short() {
- t.Skip("skipping test that uses network in short mode")
- }
+ testenv.MustHaveExternalNetwork(t)
tg := testgo(t)
defer tg.cleanup()
@@ -1997,6 +2257,38 @@ func TestCoverageUsesActualSettingToOverrideEvenForRace(t *testing.T) {
checkCoverage(tg, data)
}
+func TestCoverageImportMainLoop(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.runFail("test", "importmain/test")
+ tg.grepStderr("not an importable package", "did not detect import main")
+ tg.runFail("test", "-cover", "importmain/test")
+ tg.grepStderr("not an importable package", "did not detect import main")
+}
+
+func TestTestEmpty(t *testing.T) {
+ if !canRace {
+ t.Skip("no race detector")
+ }
+
+ wd, _ := os.Getwd()
+ testdata := filepath.Join(wd, "testdata")
+
+ for _, dir := range []string{"pkg", "test", "xtest", "pkgtest", "pkgxtest", "pkgtestxtest", "testxtest"} {
+ t.Run(dir, func(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", testdata)
+ tg.cd(filepath.Join(testdata, "src/empty/"+dir))
+ tg.run("test", "-cover", "-coverpkg=.", "-race")
+ })
+ if testing.Short() {
+ break
+ }
+ }
+}
+
func TestBuildDryRunWithCgo(t *testing.T) {
if !canCgo {
t.Skip("skipping because cgo not enabled")
@@ -2023,11 +2315,17 @@ func TestCoverageWithCgo(t *testing.T) {
t.Skip("skipping because cgo not enabled")
}
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "-short", "-cover", "./testdata/cgocover")
- data := tg.getStdout() + tg.getStderr()
- checkCoverage(tg, data)
+ for _, dir := range []string{"cgocover", "cgocover2", "cgocover3", "cgocover4"} {
+ t.Run(dir, func(t *testing.T) {
+ tg := testgo(t)
+ tg.parallel()
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.run("test", "-short", "-cover", dir)
+ data := tg.getStdout() + tg.getStderr()
+ checkCoverage(tg, data)
+ })
+ }
}
func TestCgoDependsOnSyscall(t *testing.T) {
@@ -2090,10 +2388,57 @@ func TestCgoHandlesWlORIGIN(t *testing.T) {
tg.run("build", "origin")
}
+func TestCgoPkgConfig(t *testing.T) {
+ if !canCgo {
+ t.Skip("skipping because cgo not enabled")
+ }
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+
+ tg.run("env", "PKG_CONFIG")
+ pkgConfig := strings.TrimSpace(tg.getStdout())
+ if out, err := exec.Command(pkgConfig, "--atleast-pkgconfig-version", "0.24").CombinedOutput(); err != nil {
+ t.Skipf("%s --atleast-pkgconfig-version 0.24: %v\n%s", pkgConfig, err, out)
+ }
+
+ // OpenBSD's pkg-config is strict about whitespace and only
+ // supports backslash-escaped whitespace. It does not support
+ // quotes, which the normal freedesktop.org pkg-config does
+ // support. See http://man.openbsd.org/pkg-config.1
+ tg.tempFile("foo.pc", `
+Name: foo
+Description: The foo library
+Version: 1.0.0
+Cflags: -Dhello=10 -Dworld=+32 -DDEFINED_FROM_PKG_CONFIG=hello\ world
+`)
+ tg.tempFile("foo.go", `package main
+
+/*
+#cgo pkg-config: foo
+int value() {
+ return DEFINED_FROM_PKG_CONFIG;
+}
+*/
+import "C"
+import "os"
+
+func main() {
+ if C.value() != 42 {
+ println("value() =", C.value(), "wanted 42")
+ os.Exit(1)
+ }
+}
+`)
+ tg.setenv("PKG_CONFIG_PATH", tg.path("."))
+ tg.run("run", tg.path("foo.go"))
+}
+
// "go test -c -test.bench=XXX errors" should not hang
func TestIssue6480(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ // TODO: tg.parallel()
tg.makeTempdir()
tg.cd(tg.path("."))
tg.run("test", "-c", "-test.bench=XXX", "errors")
@@ -2124,8 +2469,7 @@ func main() { C.f() }`)
}
func TestListTemplateContextFunction(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
+ t.Parallel()
for _, tt := range []struct {
v string
want string
@@ -2141,14 +2485,20 @@ func TestListTemplateContextFunction(t *testing.T) {
{"ReleaseTags", ""},
{"InstallSuffix", ""},
} {
- tmpl := "{{context." + tt.v + "}}"
- tg.run("list", "-f", tmpl)
- if tt.want == "" {
- continue
- }
- if got := strings.TrimSpace(tg.getStdout()); got != tt.want {
- t.Errorf("go list -f %q: got %q; want %q", tmpl, got, tt.want)
- }
+ tt := tt
+ t.Run(tt.v, func(t *testing.T) {
+ tg := testgo(t)
+ tg.parallel()
+ defer tg.cleanup()
+ tmpl := "{{context." + tt.v + "}}"
+ tg.run("list", "-f", tmpl)
+ if tt.want == "" {
+ return
+ }
+ if got := strings.TrimSpace(tg.getStdout()); got != tt.want {
+ t.Errorf("go list -f %q: got %q; want %q", tmpl, got, tt.want)
+ }
+ })
}
}
@@ -2307,6 +2657,20 @@ func TestGoGenerateEnv(t *testing.T) {
}
}
+func TestGoGenerateBadImports(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Skip("skipping because windows has no echo command")
+ }
+
+ // This package has an invalid import causing an import cycle,
+ // but go generate is supposed to still run.
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.run("generate", "gencycle")
+ tg.grepStdout("hello world", "go generate gencycle did not run generator")
+}
+
func TestGoGetCustomDomainWildcard(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
@@ -2382,35 +2746,254 @@ func TestGoGetHTTPS404(t *testing.T) {
}
// Test that you cannot import a main package.
-func TestIssue4210(t *testing.T) {
+// See golang.org/issue/4210 and golang.org/issue/17475.
+func TestImportMain(t *testing.T) {
tg := testgo(t)
+ tg.parallel()
defer tg.cleanup()
+
+ // Importing package main from that package main's test should work.
tg.tempFile("src/x/main.go", `package main
var X int
func main() {}`)
- tg.tempFile("src/y/main.go", `package main
- import "fmt"
+ tg.tempFile("src/x/main_test.go", `package main_test
import xmain "x"
- func main() {
- fmt.Println(xmain.X)
- }`)
+ import "testing"
+ var _ = xmain.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.setenv("GOPATH", tg.path("."))
+ tg.creatingTemp("x")
+ tg.run("build", "x")
+ tg.run("test", "x")
+
+ // Importing package main from another package should fail.
+ tg.tempFile("src/p1/p.go", `package p1
+ import xmain "x"
+ var _ = xmain.X
+ `)
+ tg.runFail("build", "p1")
+ tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main")
+
+ // ... even in that package's test.
+ tg.tempFile("src/p2/p.go", `package p2
+ `)
+ tg.tempFile("src/p2/p_test.go", `package p2
+ import xmain "x"
+ import "testing"
+ var _ = xmain.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.run("build", "p2")
+ tg.runFail("test", "p2")
+ tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main")
+
+ // ... even if that package's test is an xtest.
+ tg.tempFile("src/p3/p.go", `package p
+ `)
+ tg.tempFile("src/p3/p_test.go", `package p_test
+ import xmain "x"
+ import "testing"
+ var _ = xmain.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.run("build", "p3")
+ tg.runFail("test", "p3")
+ tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main")
+
+ // ... even if that package is a package main
+ tg.tempFile("src/p4/p.go", `package main
+ func main() {}
+ `)
+ tg.tempFile("src/p4/p_test.go", `package main
+ import xmain "x"
+ import "testing"
+ var _ = xmain.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.creatingTemp("p4" + exeSuffix)
+ tg.run("build", "p4")
+ tg.runFail("test", "p4")
+ tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main")
+
+ // ... even if that package is a package main using an xtest.
+ tg.tempFile("src/p5/p.go", `package main
+ func main() {}
+ `)
+ tg.tempFile("src/p5/p_test.go", `package main_test
+ import xmain "x"
+ import "testing"
+ var _ = xmain.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.creatingTemp("p5" + exeSuffix)
+ tg.run("build", "p5")
+ tg.runFail("test", "p5")
+ tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main")
+}
+
+// Test that you cannot use a local import in a package
+// accessed by a non-local import (found in a GOPATH/GOROOT).
+// See golang.org/issue/17475.
+func TestImportLocal(t *testing.T) {
+ tg := testgo(t)
+ tg.parallel()
+ defer tg.cleanup()
+
+ tg.tempFile("src/dir/x/x.go", `package x
+ var X int
+ `)
tg.setenv("GOPATH", tg.path("."))
- tg.runFail("build", "y")
- tg.grepBoth("is a program", `did not find expected error message ("is a program")`)
+ tg.run("build", "dir/x")
+
+ // Ordinary import should work.
+ tg.tempFile("src/dir/p0/p.go", `package p0
+ import "dir/x"
+ var _ = x.X
+ `)
+ tg.run("build", "dir/p0")
+
+ // Relative import should not.
+ tg.tempFile("src/dir/p1/p.go", `package p1
+ import "../x"
+ var _ = x.X
+ `)
+ tg.runFail("build", "dir/p1")
+ tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
+
+ // ... even in a test.
+ tg.tempFile("src/dir/p2/p.go", `package p2
+ `)
+ tg.tempFile("src/dir/p2/p_test.go", `package p2
+ import "../x"
+ import "testing"
+ var _ = x.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.run("build", "dir/p2")
+ tg.runFail("test", "dir/p2")
+ tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
+
+ // ... even in an xtest.
+ tg.tempFile("src/dir/p2/p_test.go", `package p2_test
+ import "../x"
+ import "testing"
+ var _ = x.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.run("build", "dir/p2")
+ tg.runFail("test", "dir/p2")
+ tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
+
+ // Relative import starting with ./ should not work either.
+ tg.tempFile("src/dir/d.go", `package dir
+ import "./x"
+ var _ = x.X
+ `)
+ tg.runFail("build", "dir")
+ tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
+
+ // ... even in a test.
+ tg.tempFile("src/dir/d.go", `package dir
+ `)
+ tg.tempFile("src/dir/d_test.go", `package dir
+ import "./x"
+ import "testing"
+ var _ = x.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.run("build", "dir")
+ tg.runFail("test", "dir")
+ tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
+
+ // ... even in an xtest.
+ tg.tempFile("src/dir/d_test.go", `package dir_test
+ import "./x"
+ import "testing"
+ var _ = x.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.run("build", "dir")
+ tg.runFail("test", "dir")
+ tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
+
+ // Relative import plain ".." should not work.
+ tg.tempFile("src/dir/x/y/y.go", `package dir
+ import ".."
+ var _ = x.X
+ `)
+ tg.runFail("build", "dir/x/y")
+ tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
+
+ // ... even in a test.
+ tg.tempFile("src/dir/x/y/y.go", `package y
+ `)
+ tg.tempFile("src/dir/x/y/y_test.go", `package y
+ import ".."
+ import "testing"
+ var _ = x.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.run("build", "dir/x/y")
+ tg.runFail("test", "dir/x/y")
+ tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
+
+ // ... even in an x test.
+ tg.tempFile("src/dir/x/y/y_test.go", `package y_test
+ import ".."
+ import "testing"
+ var _ = x.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.run("build", "dir/x/y")
+ tg.runFail("test", "dir/x/y")
+ tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
+
+ // Relative import "." should not work.
+ tg.tempFile("src/dir/x/xx.go", `package x
+ import "."
+ var _ = x.X
+ `)
+ tg.runFail("build", "dir/x")
+ tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
+
+ // ... even in a test.
+ tg.tempFile("src/dir/x/xx.go", `package x
+ `)
+ tg.tempFile("src/dir/x/xx_test.go", `package x
+ import "."
+ import "testing"
+ var _ = x.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.run("build", "dir/x")
+ tg.runFail("test", "dir/x")
+ tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
+
+ // ... even in an xtest.
+ tg.tempFile("src/dir/x/xx.go", `package x
+ `)
+ tg.tempFile("src/dir/x/xx_test.go", `package x_test
+ import "."
+ import "testing"
+ var _ = x.X
+ func TestFoo(t *testing.T) {}
+ `)
+ tg.run("build", "dir/x")
+ tg.runFail("test", "dir/x")
+ tg.grepStderr("local import.*in non-local package", "did not diagnose local import")
}
func TestGoGetInsecure(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
- t.Skip("golang.org/issue/15410")
-
tg := testgo(t)
defer tg.cleanup()
tg.makeTempdir()
tg.setenv("GOPATH", tg.path("."))
tg.failSSH()
- const repo = "wh3rd.net/git.git"
+ const repo = "insecure.go-get-issue-15410.appspot.com/pkg/p"
// Try go get -d of HTTP-only repo (should fail).
tg.runFail("get", "-d", repo)
@@ -2454,7 +3037,7 @@ func TestGoGetInsecureCustomDomain(t *testing.T) {
tg.makeTempdir()
tg.setenv("GOPATH", tg.path("."))
- const repo = "wh3rd.net/repo"
+ const repo = "insecure.go-get-issue-15410.appspot.com/pkg/p"
tg.runFail("get", "-d", repo)
tg.run("get", "-d", "-insecure", repo)
}
@@ -2471,6 +3054,7 @@ func TestGoRunDirs(t *testing.T) {
func TestGoInstallPkgdir(t *testing.T) {
tg := testgo(t)
+ tg.parallel()
defer tg.cleanup()
tg.makeTempdir()
pkg := tg.path(".")
@@ -2509,6 +3093,27 @@ func TestGoTestRaceInstallCgo(t *testing.T) {
}
}
+func TestGoTestRaceFailures(t *testing.T) {
+ if !canRace {
+ t.Skip("skipping because race detector not supported")
+ }
+
+ tg := testgo(t)
+ tg.parallel()
+ defer tg.cleanup()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+
+ tg.run("test", "testrace")
+
+ tg.runFail("test", "-race", "testrace")
+ tg.grepStdout("FAIL: TestRace", "TestRace did not fail")
+ tg.grepBothNot("PASS", "something passed")
+
+ tg.runFail("test", "-race", "testrace", "-run", "XXX", "-bench", ".")
+ tg.grepStdout("FAIL: BenchmarkRace", "BenchmarkRace did not fail")
+ tg.grepBothNot("PASS", "something passed")
+}
+
func TestGoTestImportErrorStack(t *testing.T) {
const out = `package testdep/p1 (test)
imports testdep/p2
@@ -2773,6 +3378,7 @@ func TestIssue13655(t *testing.T) {
// For issue 14337.
func TestParallelTest(t *testing.T) {
tg := testgo(t)
+ tg.parallel()
defer tg.cleanup()
tg.makeTempdir()
const testSrc = `package package_test
@@ -2793,9 +3399,11 @@ func TestCgoConsistentResults(t *testing.T) {
if !canCgo {
t.Skip("skipping because cgo not enabled")
}
- if runtime.GOOS == "solaris" {
- // See https://golang.org/issue/13247
- t.Skip("skipping because Solaris builds are known to be inconsistent; see #13247")
+ switch runtime.GOOS {
+ case "freebsd":
+ testenv.SkipFlaky(t, 15405)
+ case "solaris":
+ testenv.SkipFlaky(t, 13247)
}
tg := testgo(t)
@@ -2832,10 +3440,23 @@ func TestGoGetUpdateAllDoesNotTryToLoadDuplicates(t *testing.T) {
tg.grepStderrNot("duplicate loads of", "did not remove old packages from cache")
}
+// Issue 17119 more duplicate load errors
+func TestIssue17119(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.runFail("build", "dupload")
+ tg.grepBothNot("duplicate load|internal error", "internal error")
+}
+
func TestFatalInBenchmarkCauseNonZeroExitStatus(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
- tg.runFail("test", "-bench", ".", "./testdata/src/benchfatal")
+ // TODO: tg.parallel()
+ tg.runFail("test", "-run", "^$", "-bench", ".", "./testdata/src/benchfatal")
tg.grepBothNot("^ok", "test passed unexpectedly")
tg.grepBoth("FAIL.*benchfatal", "test did not run everything")
}
@@ -2843,6 +3464,7 @@ func TestFatalInBenchmarkCauseNonZeroExitStatus(t *testing.T) {
func TestBinaryOnlyPackages(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.makeTempdir()
tg.setenv("GOPATH", tg.path("."))
@@ -2907,6 +3529,16 @@ func TestBinaryOnlyPackages(t *testing.T) {
tg.run("run", tg.path("src/p3/p3.go"))
tg.grepStdout("hello from p1", "did not see message from p1")
+
+ tg.tempFile("src/p4/p4.go", `package main`)
+ tg.tempFile("src/p4/p4not.go", `//go:binary-only-package
+
+ // +build asdf
+
+ package main
+ `)
+ tg.run("list", "-f", "{{.BinaryOnly}}", "p4")
+ tg.grepStdout("false", "did not see BinaryOnly=false for p4")
}
// Issue 16050.
@@ -2954,3 +3586,204 @@ func TestGenerateUsesBuildContext(t *testing.T) {
tg.run("generate", "gen")
tg.grepStdout("darwin 386", "unexpected GOOS/GOARCH combination")
}
+
+// Issue 14450: go get -u .../ tried to import not downloaded package
+func TestGoGetUpdateWithWildcard(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("."))
+ const aPkgImportPath = "github.com/tmwh/go-get-issue-14450/a"
+ tg.run("get", aPkgImportPath)
+ tg.run("get", "-u", ".../")
+ tg.grepStderrNot("cannot find package", "did not update packages given wildcard path")
+
+ var expectedPkgPaths = []string{
+ "src/github.com/tmwh/go-get-issue-14450/b",
+ "src/github.com/tmwh/go-get-issue-14450-b-dependency/c",
+ "src/github.com/tmwh/go-get-issue-14450-b-dependency/d",
+ }
+
+ for _, importPath := range expectedPkgPaths {
+ _, err := os.Stat(tg.path(importPath))
+ tg.must(err)
+ }
+ const notExpectedPkgPath = "src/github.com/tmwh/go-get-issue-14450-c-dependency/e"
+ tg.mustNotExist(tg.path(notExpectedPkgPath))
+}
+
+func TestGoEnv(t *testing.T) {
+ tg := testgo(t)
+ tg.parallel()
+ defer tg.cleanup()
+ tg.setenv("GOARCH", "arm")
+ tg.run("env", "GOARCH")
+ tg.grepStdout("^arm$", "GOARCH not honored")
+
+ tg.run("env", "GCCGO")
+ tg.grepStdout(".", "GCCGO unexpectedly empty")
+
+ tg.run("env", "CGO_CFLAGS")
+ tg.grepStdout(".", "default CGO_CFLAGS unexpectedly empty")
+
+ tg.setenv("CGO_CFLAGS", "-foobar")
+ tg.run("env", "CGO_CFLAGS")
+ tg.grepStdout("^-foobar$", "CGO_CFLAGS not honored")
+
+ tg.setenv("CC", "gcc -fmust -fgo -ffaster")
+ tg.run("env", "CC")
+ tg.grepStdout("gcc", "CC not found")
+ tg.run("env", "GOGCCFLAGS")
+ tg.grepStdout("-ffaster", "CC arguments not found")
+}
+
+const (
+ noMatchesPattern = `(?m)^ok.*\[no tests to run\]`
+ okPattern = `(?m)^ok`
+)
+
+func TestMatchesNoTests(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ // TODO: tg.parallel()
+ tg.run("test", "-run", "ThisWillNotMatch", "testdata/standalone_test.go")
+ tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]")
+}
+
+func TestMatchesNoTestsDoesNotOverrideBuildFailure(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ tg.runFail("test", "-run", "ThisWillNotMatch", "syntaxerror")
+ tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
+ tg.grepBoth("FAIL", "go test did not say FAIL")
+}
+
+func TestMatchesNoBenchmarksIsOK(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ // TODO: tg.parallel()
+ tg.run("test", "-run", "^$", "-bench", "ThisWillNotMatch", "testdata/standalone_benchmark_test.go")
+ tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
+ tg.grepBoth(okPattern, "go test did not say ok")
+}
+
+func TestMatchesOnlyExampleIsOK(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ // TODO: tg.parallel()
+ tg.run("test", "-run", "Example", "testdata/example1_test.go")
+ tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
+ tg.grepBoth(okPattern, "go test did not say ok")
+}
+
+func TestMatchesOnlyBenchmarkIsOK(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ // TODO: tg.parallel()
+ tg.run("test", "-run", "^$", "-bench", ".", "testdata/standalone_benchmark_test.go")
+ tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
+ tg.grepBoth(okPattern, "go test did not say ok")
+}
+
+func TestMatchesOnlyTestIsOK(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ // TODO: tg.parallel()
+ tg.run("test", "-run", "Test", "testdata/standalone_test.go")
+ tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
+ tg.grepBoth(okPattern, "go test did not say ok")
+}
+
+func TestMatchesNoTestsWithSubtests(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.run("test", "-run", "ThisWillNotMatch", "testdata/standalone_sub_test.go")
+ tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]")
+}
+
+func TestMatchesNoSubtestsMatch(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.run("test", "-run", "Test/ThisWillNotMatch", "testdata/standalone_sub_test.go")
+ tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]")
+}
+
+func TestMatchesNoSubtestsDoesNotOverrideFailure(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.runFail("test", "-run", "TestThatFails/ThisWillNotMatch", "testdata/standalone_fail_sub_test.go")
+ tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
+ tg.grepBoth("FAIL", "go test did not say FAIL")
+}
+
+func TestMatchesOnlySubtestIsOK(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.run("test", "-run", "Test/Sub", "testdata/standalone_sub_test.go")
+ tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
+ tg.grepBoth(okPattern, "go test did not say ok")
+}
+
+func TestMatchesNoSubtestsParallel(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.run("test", "-run", "Test/Sub/ThisWillNotMatch", "testdata/standalone_parallel_sub_test.go")
+ tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]")
+}
+
+func TestMatchesOnlySubtestParallelIsOK(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.run("test", "-run", "Test/Sub/Nested", "testdata/standalone_parallel_sub_test.go")
+ tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
+ tg.grepBoth(okPattern, "go test did not say ok")
+}
+
+func TestLinkXImportPathEscape(t *testing.T) {
+ // golang.org/issue/16710
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+ exe := "./linkx" + exeSuffix
+ tg.creatingTemp(exe)
+ tg.run("build", "-o", exe, "-ldflags", "-X=my.pkg.Text=linkXworked", "my.pkg/main")
+ out, err := exec.Command(exe).CombinedOutput()
+ if err != nil {
+ tg.t.Fatal(err)
+ }
+ if string(out) != "linkXworked\n" {
+ tg.t.Log(string(out))
+ tg.t.Fatal(`incorrect output: expected "linkXworked\n"`)
+ }
+}
+
+// Issue 18044.
+func TestLdBindNow(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.setenv("LD_BIND_NOW", "1")
+ tg.run("help")
+}
+
+// Issue 18225.
+// This is really a cmd/asm issue but this is a convenient place to test it.
+func TestConcurrentAsm(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ asm := `DATA ·constants<>+0x0(SB)/8,$0
+GLOBL ·constants<>(SB),8,$8
+`
+ tg.tempFile("go/src/p/a.s", asm)
+ tg.tempFile("go/src/p/b.s", asm)
+ tg.tempFile("go/src/p/p.go", `package p`)
+ tg.setenv("GOPATH", tg.path("go"))
+ tg.run("build", "p")
+}
diff --git a/libgo/go/cmd/go/go_windows_test.go b/libgo/go/cmd/go/go_windows_test.go
index 53d695cccc8..d8d04aaf497 100644
--- a/libgo/go/cmd/go/go_windows_test.go
+++ b/libgo/go/cmd/go/go_windows_test.go
@@ -5,6 +5,7 @@
package main
import (
+ "internal/testenv"
"io/ioutil"
"os"
"os/exec"
@@ -45,7 +46,7 @@ func TestAbsolutePath(t *testing.T) {
noVolume := file[len(filepath.VolumeName(file)):]
wrongPath := filepath.Join(dir, noVolume)
- output, err := exec.Command("go", "build", noVolume).CombinedOutput()
+ output, err := exec.Command(testenv.GoToolPath(t), "build", noVolume).CombinedOutput()
if err == nil {
t.Fatal("build should fail")
}
diff --git a/libgo/go/cmd/go/help.go b/libgo/go/cmd/go/help.go
index 056a0af1125..0c663ad463f 100644
--- a/libgo/go/cmd/go/help.go
+++ b/libgo/go/cmd/go/help.go
@@ -42,7 +42,7 @@ 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').
+environment variable (For more details see: 'go help gopath').
If no import paths are given, the action applies to the
package in the current directory.
@@ -62,6 +62,9 @@ Go library.
- "cmd" expands to the Go repository's commands and their
internal libraries.
+Import paths beginning with "cmd/" only match source code in
+the Go repository.
+
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
@@ -102,10 +105,10 @@ var helpImportPath = &Command{
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').
+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 (For more
+details see: 'go help gopath').
Relative import paths
@@ -197,6 +200,11 @@ When a version control system supports multiple protocols,
each is tried in turn when downloading. For example, a Git
download tries https://, then git+ssh://.
+By default, downloads are restricted to known secure protocols
+(e.g. https, ssh). To override this setting for Git downloads, the
+GIT_ALLOW_PROTOCOL environment variable can be set (For more details see:
+'go help environment').
+
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 <meta> tag in the document's HTML
@@ -237,8 +245,8 @@ 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').
+New downloaded packages are written to the first directory listed in the GOPATH
+environment variable (For more details see: 'go help gopath').
The go command attempts to download the version of the
package appropriate for the Go release being used.
@@ -281,8 +289,13 @@ 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.
+If the environment variable is unset, GOPATH defaults
+to a subdirectory named "go" in the user's home directory
+($HOME/go on Unix, %USERPROFILE%\go on Windows),
+unless that directory holds a Go distribution.
+Run "go env GOPATH" to see the current GOPATH.
+
+See https://golang.org/wiki/SettingGOPATH to set a custom GOPATH.
Each directory listed in GOPATH must have a prescribed structure:
@@ -310,9 +323,9 @@ of DIR/bin. GOBIN must be an absolute path.
Here's an example directory layout:
- GOPATH=/home/user/gocode
+ GOPATH=/home/user/go
- /home/user/gocode/
+ /home/user/go/
src/
foo/
bar/ (go code in package bar)
@@ -338,7 +351,7 @@ Code in or below a directory named "internal" is importable only
by code in the directory tree rooted at the parent of "internal".
Here's an extended version of the directory layout above:
- /home/user/gocode/
+ /home/user/go/
src/
crash/
bang/ (go code in package bang)
@@ -376,7 +389,7 @@ Here's the example from the previous section,
but with the "internal" directory renamed to "vendor"
and a new foo/vendor/crash/bang directory added:
- /home/user/gocode/
+ /home/user/go/
src/
crash/
bang/ (go code in package bang)
@@ -439,7 +452,7 @@ General-purpose environment variables:
The operating system for which to compile code.
Examples are linux, darwin, windows, netbsd.
GOPATH
- See 'go help gopath'.
+ For more details see: 'go help gopath'.
GORACE
Options for the race detector.
See https://golang.org/doc/articles/race_detector.html.
@@ -461,10 +474,15 @@ Environment variables for use with cgo:
CGO_CXXFLAGS
Flags that cgo will pass to the compiler when compiling
C++ code.
+ CGO_FFLAGS
+ Flags that cgo will pass to the compiler when compiling
+ Fortran code.
CGO_LDFLAGS
Flags that cgo will pass to the compiler when linking.
CXX
The command to use to compile C++ code.
+ PKG_CONFIG
+ Path to pkg-config tool.
Architecture-specific environment variables:
@@ -486,6 +504,10 @@ Special-purpose environment variables:
Whether the linker should use external linking mode
when using -linkmode=auto with code that uses cgo.
Set to 0 to disable external linking mode, 1 to enable it.
+ GIT_ALLOW_PROTOCOL
+ Defined by Git. A colon-separated list of schemes that are allowed to be used
+ with git fetch/clone. If set, any scheme not explicitly mentioned will be
+ considered insecure by 'go get'.
`,
}
@@ -577,5 +599,9 @@ are:
Build the listed main packages and everything they import into
position independent executables (PIE). Packages not named
main are ignored.
+
+ -buildmode=plugin
+ Build the listed main packages, plus all packages that they
+ import, into a Go plugin. Packages not named main are ignored.
`,
}
diff --git a/libgo/go/cmd/go/http.go b/libgo/go/cmd/go/http.go
index 05ea5030499..dcb4e9fea5f 100644
--- a/libgo/go/cmd/go/http.go
+++ b/libgo/go/cmd/go/http.go
@@ -12,6 +12,7 @@
package main
import (
+ "cmd/internal/browser"
"crypto/tls"
"fmt"
"io"
@@ -32,6 +33,7 @@ var httpClient = http.DefaultClient
var impatientInsecureHTTPClient = &http.Client{
Timeout: 5 * time.Second,
Transport: &http.Transport{
+ Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
@@ -113,3 +115,6 @@ func httpsOrHTTP(importPath string, security securityMode) (urlStr string, body
}
return urlStr, res.Body, nil
}
+
+func queryEscape(s string) string { return url.QueryEscape(s) }
+func openBrowser(url string) bool { return browser.Open(url) }
diff --git a/libgo/go/cmd/go/list.go b/libgo/go/cmd/go/list.go
index 48678e73955..2f240834b2a 100644
--- a/libgo/go/cmd/go/list.go
+++ b/libgo/go/cmd/go/list.go
@@ -59,6 +59,8 @@ syntax of package template. The default output is equivalent to -f
SwigFiles []string // .swig files
SwigCXXFiles []string // .swigcxx files
SysoFiles []string // .syso object files to add to archive
+ TestGoFiles []string // _test.go files in package
+ XTestGoFiles []string // _test.go files outside package
// Cgo directives
CgoCFLAGS []string // cgo: flags for C compiler
@@ -69,20 +71,23 @@ syntax of package template. The default output is equivalent to -f
CgoPkgConfig []string // cgo: pkg-config names
// Dependency information
- Imports []string // import paths used by this package
- Deps []string // all (recursively) imported dependencies
+ Imports []string // import paths used by this package
+ Deps []string // all (recursively) imported dependencies
+ TestImports []string // imports from TestGoFiles
+ XTestImports []string // imports from XTestGoFiles
// Error information
Incomplete bool // this package or a dependency has an error
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
}
+Packages stored in vendor directories report an ImportPath that includes the
+path to the vendor directory (for example, "d/vendor/p" instead of "p"),
+so that the ImportPath uniquely identifies a given copy of a package.
+The Imports, Deps, TestImports, and XTestImports lists also contain these
+expanded imports paths. See golang.org/s/go15vendor for more about vendoring.
+
The error information, if any, is
type PackageError struct {
diff --git a/libgo/go/cmd/go/main.go b/libgo/go/cmd/go/main.go
index 65ec61bd7db..07fc4e2a905 100644
--- a/libgo/go/cmd/go/main.go
+++ b/libgo/go/cmd/go/main.go
@@ -79,6 +79,7 @@ var commands = []*Command{
cmdClean,
cmdDoc,
cmdEnv,
+ cmdBug,
cmdFix,
cmdFmt,
cmdGenerate,
@@ -114,6 +115,7 @@ func setExitStatus(n int) {
}
var origEnv []string
+var newEnv []envVar
func main() {
_ = go11tag
@@ -134,7 +136,7 @@ func main() {
// 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() {
+ if gopath := buildContext.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) {
@@ -146,7 +148,7 @@ func main() {
os.Exit(2)
}
if !filepath.IsAbs(p) {
- fmt.Fprintf(os.Stderr, "go: GOPATH entry is relative; must be absolute path: %q.\nRun 'go help gopath' for usage.\n", p)
+ fmt.Fprintf(os.Stderr, "go: GOPATH entry is relative; must be absolute path: %q.\nFor more details see: 'go help gopath'\n", p)
os.Exit(2)
}
}
@@ -163,7 +165,8 @@ func main() {
// but in practice there might be skew
// This makes sure we all agree.
origEnv = os.Environ()
- for _, env := range mkEnv() {
+ newEnv = mkEnv()
+ for _, env := range newEnv {
if os.Getenv(env.name) != env.value {
os.Setenv(env.name, env.value)
}
diff --git a/libgo/go/cmd/go/pkg.go b/libgo/go/cmd/go/pkg.go
index ea223d6203d..af8c1d959fa 100644
--- a/libgo/go/cmd/go/pkg.go
+++ b/libgo/go/cmd/go/pkg.go
@@ -24,6 +24,8 @@ import (
"unicode"
)
+var ignoreImports bool // control whether we ignore imports in packages
+
// 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.
@@ -180,11 +182,18 @@ func (p *Package) copyBuild(pp *build.Package) {
p.CgoCXXFLAGS = pp.CgoCXXFLAGS
p.CgoLDFLAGS = pp.CgoLDFLAGS
p.CgoPkgConfig = pp.CgoPkgConfig
- p.Imports = pp.Imports
+ // We modify p.Imports in place, so make copy now.
+ p.Imports = make([]string, len(pp.Imports))
+ copy(p.Imports, pp.Imports)
p.TestGoFiles = pp.TestGoFiles
p.TestImports = pp.TestImports
p.XTestGoFiles = pp.XTestGoFiles
p.XTestImports = pp.XTestImports
+ if ignoreImports {
+ p.Imports = nil
+ p.TestImports = nil
+ p.XTestImports = nil
+ }
}
// isStandardImportPath reports whether $GOROOT/src/path should be considered
@@ -338,62 +347,98 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
importPath = path
}
- if p := packageCache[importPath]; p != nil {
- if perr := disallowInternal(srcDir, p, stk); perr != p {
- return perr
+ p := packageCache[importPath]
+ if p != nil {
+ p = reusePackage(p, stk)
+ } else {
+ 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.
+ buildMode := build.ImportComment
+ if mode&useVendor == 0 || path != origPath {
+ // Not vendoring, or we already found the vendored path.
+ buildMode |= build.IgnoreVendor
}
- if mode&useVendor != 0 {
- if perr := disallowVendor(srcDir, origPath, p, stk); perr != p {
- return perr
- }
+ bp, err := buildContext.Import(path, srcDir, buildMode)
+ bp.ImportPath = importPath
+ if gobin != "" {
+ bp.BinDir = gobin
+ }
+ if err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path &&
+ !strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/") {
+ err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment)
+ }
+ p.load(stk, bp, err)
+ if p.Error != nil && p.Error.Pos == "" {
+ p = setErrorPos(p, importPos)
}
- 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.
- buildMode := build.ImportComment
- if mode&useVendor == 0 || path != origPath {
- // Not vendoring, or we already found the vendored path.
- buildMode |= build.IgnoreVendor
- }
- bp, err := buildContext.Import(path, srcDir, buildMode)
- bp.ImportPath = importPath
- if gobin != "" {
- bp.BinDir = gobin
- }
- if err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path &&
- !strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/") {
- err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment)
- }
- p.load(stk, bp, err)
- if p.Error != nil && p.Error.Pos == "" && len(importPos) > 0 {
- pos := importPos[0]
- pos.Filename = shortPath(pos.Filename)
- p.Error.Pos = pos.String()
+ if origPath != cleanImport(origPath) {
+ p.Error = &PackageError{
+ ImportStack: stk.copy(),
+ Err: fmt.Sprintf("non-canonical import path: %q should be %q", origPath, pathpkg.Clean(origPath)),
+ }
+ p.Incomplete = true
+ }
}
+ // Checked on every import because the rules depend on the code doing the importing.
if perr := disallowInternal(srcDir, p, stk); perr != p {
- return perr
+ return setErrorPos(perr, importPos)
}
if mode&useVendor != 0 {
if perr := disallowVendor(srcDir, origPath, p, stk); perr != p {
- return perr
+ return setErrorPos(perr, importPos)
+ }
+ }
+
+ if p.Name == "main" && parent != nil && parent.Dir != p.Dir {
+ perr := *p
+ perr.Error = &PackageError{
+ ImportStack: stk.copy(),
+ Err: fmt.Sprintf("import %q is a program, not an importable package", path),
}
+ return setErrorPos(&perr, importPos)
}
+ if p.local && parent != nil && !parent.local {
+ perr := *p
+ perr.Error = &PackageError{
+ ImportStack: stk.copy(),
+ Err: fmt.Sprintf("local import %q in non-local package", path),
+ }
+ return setErrorPos(&perr, importPos)
+ }
+
+ return p
+}
+
+func setErrorPos(p *Package, importPos []token.Position) *Package {
+ if len(importPos) > 0 {
+ pos := importPos[0]
+ pos.Filename = shortPath(pos.Filename)
+ p.Error.Pos = pos.String()
+ }
return p
}
+func cleanImport(path string) string {
+ orig := path
+ path = pathpkg.Clean(path)
+ if strings.HasPrefix(orig, "./") && path != ".." && path != "." && !strings.HasPrefix(path, "../") {
+ path = "./" + path
+ }
+ return path
+}
+
var isDirCache = map[string]bool{}
func isDir(path string) bool {
@@ -419,13 +464,26 @@ func vendoredImportPath(parent *Package, path string) (found string) {
dir := filepath.Clean(parent.Dir)
root := filepath.Join(parent.Root, "src")
- if !hasFilePathPrefix(dir, root) {
+ if !hasFilePathPrefix(dir, root) || parent.ImportPath != "command-line-arguments" && filepath.Join(root, parent.ImportPath) != dir {
// Look for symlinks before reporting error.
dir = expandPath(dir)
root = expandPath(root)
}
- if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator {
- fatalf("invalid vendoredImportPath: dir=%q root=%q separator=%q", dir, root, string(filepath.Separator))
+
+ if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || parent.ImportPath != "command-line-arguments" && !parent.local && filepath.Join(root, parent.ImportPath) != dir {
+ fatalf("unexpected directory layout:\n"+
+ " import path: %s\n"+
+ " root: %s\n"+
+ " dir: %s\n"+
+ " expand root: %s\n"+
+ " expand dir: %s\n"+
+ " separator: %s",
+ parent.ImportPath,
+ filepath.Join(parent.Root, "src"),
+ filepath.Clean(parent.Dir),
+ root,
+ dir,
+ string(filepath.Separator))
}
vpath := "vendor/" + path
@@ -523,6 +581,14 @@ func disallowInternal(srcDir string, p *Package, stk *importStack) *Package {
return p
}
+ // The generated 'testmain' package is allowed to access testing/internal/...,
+ // as if it were generated into the testing directory tree
+ // (it's actually in a temporary directory outside any Go tree).
+ // This cleans up a former kludge in passing functionality to the testing package.
+ if strings.HasPrefix(p.ImportPath, "testing/internal") && len(*stk) >= 2 && (*stk)[len(*stk)-2] == "testmain" {
+ return p
+ }
+
// We can't check standard packages with gccgo.
if buildContext.Compiler == "gccgo" && p.Standard {
return p
@@ -700,24 +766,23 @@ const (
// 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/asm": toTool,
- "cmd/compile": toTool,
- "cmd/cgo": toTool,
- "cmd/cover": toTool,
- "cmd/dist": toTool,
- "cmd/doc": toTool,
- "cmd/fix": toTool,
- "cmd/link": toTool,
- "cmd/newlink": toTool,
- "cmd/nm": toTool,
- "cmd/objdump": toTool,
- "cmd/pack": toTool,
- "cmd/pprof": toTool,
- "cmd/trace": toTool,
- "cmd/vet": toTool,
- "cmd/yacc": toTool,
+ "cmd/addr2line": toTool,
+ "cmd/api": toTool,
+ "cmd/asm": toTool,
+ "cmd/compile": toTool,
+ "cmd/cgo": toTool,
+ "cmd/cover": toTool,
+ "cmd/dist": toTool,
+ "cmd/doc": toTool,
+ "cmd/fix": toTool,
+ "cmd/link": toTool,
+ "cmd/newlink": toTool,
+ "cmd/nm": toTool,
+ "cmd/objdump": toTool,
+ "cmd/pack": toTool,
+ "cmd/pprof": toTool,
+ "cmd/trace": toTool,
+ "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,
@@ -792,7 +857,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
useBindir := p.Name == "main"
if !p.Standard {
switch buildBuildmode {
- case "c-archive", "c-shared":
+ case "c-archive", "c-shared", "plugin":
useBindir = false
}
}
@@ -867,11 +932,25 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
importPaths = append(importPaths, "syscall")
}
- // Currently build modes c-shared, pie, and -linkshared force
- // external linking mode, and external linking mode forces an
- // import of runtime/cgo.
- if p.Name == "main" && !p.Goroot && (buildBuildmode == "c-shared" || buildBuildmode == "pie" || buildLinkshared) {
- importPaths = append(importPaths, "runtime/cgo")
+ if buildContext.CgoEnabled && p.Name == "main" && !p.Goroot {
+ // Currently build modes c-shared, pie (on systems that do not
+ // support PIE with internal linking mode), plugin, and
+ // -linkshared force external linking mode, as of course does
+ // -ldflags=-linkmode=external. External linking mode forces
+ // an import of runtime/cgo.
+ pieCgo := buildBuildmode == "pie" && (buildContext.GOOS != "linux" || buildContext.GOARCH != "amd64")
+ linkmodeExternal := false
+ for i, a := range buildLdflags {
+ if a == "-linkmode=external" {
+ linkmodeExternal = true
+ }
+ if a == "-linkmode" && i+1 < len(buildLdflags) && buildLdflags[i+1] == "external" {
+ linkmodeExternal = true
+ }
+ }
+ if buildBuildmode == "c-shared" || buildBuildmode == "plugin" || pieCgo || buildLinkshared || linkmodeExternal {
+ importPaths = append(importPaths, "runtime/cgo")
+ }
}
// Everything depends on runtime, except runtime, its internal
@@ -891,6 +970,10 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
if p.Name == "main" && goarch == "arm" {
importPaths = append(importPaths, "math")
}
+ // In coverage atomic mode everything depends on sync/atomic.
+ if testCoverMode == "atomic" && (!p.Standard || (p.ImportPath != "runtime/cgo" && p.ImportPath != "runtime/race" && p.ImportPath != "sync/atomic")) {
+ importPaths = append(importPaths, "sync/atomic")
+ }
}
// Runtime and its internal packages depend on runtime/internal/sys,
@@ -953,6 +1036,16 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
// Build list of imported packages and full dependency list.
imports := make([]*Package, 0, len(p.Imports))
deps := make(map[string]*Package)
+ save := func(path string, p1 *Package) {
+ // The same import path could produce an error or not,
+ // depending on what tries to import it.
+ // Prefer to record entries with errors, so we can report them.
+ p0 := deps[path]
+ if p0 == nil || p1.Error != nil && (p0.Error == nil || len(p0.Error.ImportStack) > len(p1.Error.ImportStack)) {
+ deps[path] = p1
+ }
+ }
+
for i, path := range importPaths {
if path == "C" {
continue
@@ -961,28 +1054,6 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
if !reqStdPkgSrc && p1.Standard {
continue
}
- if p1.Name == "main" {
- p.Error = &PackageError{
- ImportStack: stk.copy(),
- Err: fmt.Sprintf("import %q is a program, not an importable package", path),
- }
- pos := p.build.ImportPos[path]
- if len(pos) > 0 {
- p.Error.Pos = pos[0].String()
- }
- }
- 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()
- }
- }
- }
if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil {
p.Error = &PackageError{
ImportStack: stk.copy(),
@@ -999,15 +1070,11 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
if i < len(p.Imports) {
p.Imports[i] = path
}
- deps[path] = p1
+
+ save(path, p1)
imports = append(imports, p1)
for _, dep := range p1.deps {
- // The same import path could produce an error or not,
- // depending on what tries to import it.
- // Prefer to record entries with errors, so we can report them.
- if deps[dep.ImportPath] == nil || dep.Error != nil {
- deps[dep.ImportPath] = dep
- }
+ save(dep.ImportPath, dep)
}
if p1.Incomplete {
p.Incomplete = true
diff --git a/libgo/go/cmd/go/test.go b/libgo/go/cmd/go/test.go
index 1de915a2533..37f6327fffe 100644
--- a/libgo/go/cmd/go/test.go
+++ b/libgo/go/cmd/go/test.go
@@ -135,28 +135,11 @@ const testFlag2 = `
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 'go doc 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.
-
-count n
Run each test and benchmark n times (default 1).
If -cpu is set, run n times for each GOMAXPROCS value.
@@ -182,33 +165,11 @@ const testFlag2 = `
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 'go doc 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
@@ -234,13 +195,64 @@ const testFlag2 = `
If a test runs longer than t, panic.
The default is 10 minutes (10m).
- -trace trace.out
- Write an execution trace to the specified file before exiting.
-
-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 following flags are also recognized by 'go test' and can be used to
+profile the tests during execution:
+
+ -benchmem
+ Print memory allocation statistics for benchmarks.
+
+ -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 'go doc 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.
+
+ -coverprofile cover.out
+ Write a coverage profile to the file after all tests have passed.
+ Sets -cover.
+
+ -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 'go doc runtime.MemProfileRate'.
+ To profile all memory allocations, use -test.memprofilerate=1
+ and pass --alloc_space flag to the pprof tool.
+
+ -mutexprofile mutex.out
+ Write a mutex contention profile to the specified file
+ when all tests are complete.
+ Writes test binary as -c would.
+
+ -mutexprofilefraction n
+ Sample 1 in n stack traces of goroutines holding a
+ contended mutex.
+
+ -outputdir directory
+ Place output files from profiling in the specified directory,
+ by default the directory in which "go test" is running.
+
+ -trace trace.out
+ Write an execution trace to the specified file before exiting.
+
Each of these flags is also recognized with an optional 'test.' prefix,
as in -test.v. When invoking the generated test binary (the result of
'go test -c') directly, however, the prefix is mandatory.
@@ -322,7 +334,8 @@ If the last comment in the function starts with "Output:" then the output
is compared exactly against the comment (see examples below). If the last
comment begins with "Unordered output:" then the output is compared to the
comment, however the order of the lines is ignored. An example with no such
-comment, or with no text after "Output:" is compiled but not executed.
+comment is compiled but not executed. An example with no text after
+"Output:" is compiled, executed, and expected to produce no output.
Godoc displays the body of ExampleXXX to demonstrate the use
of the function, constant, or variable XXX. An example of a method M with
@@ -381,9 +394,9 @@ var (
var testMainDeps = map[string]bool{
// Dependencies for testmain.
- "testing": true,
- "regexp": true,
- "os": true,
+ "testing": true,
+ "testing/internal/testdeps": true,
+ "os": true,
}
func runTest(cmd *Command, args []string) {
@@ -432,6 +445,11 @@ func runTest(cmd *Command, args []string) {
testStreamOutput = len(pkgArgs) == 0 || testBench ||
(testShowPass && (len(pkgs) == 1 || buildP == 1))
+ // For 'go test -i -o x.test', we want to build x.test. Imply -c to make the logic easier.
+ if buildI && testO != "" {
+ testC = true
+ }
+
var b builder
b.init()
@@ -861,7 +879,7 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
if err != nil {
return nil, nil, nil, err
}
- if len(ptest.GoFiles) > 0 {
+ if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 {
pmain.imports = append(pmain.imports, ptest)
t.ImportTest = true
}
@@ -1089,6 +1107,8 @@ func declareCoverVars(importPath string, files ...string) map[string]*CoverVar {
return coverVars
}
+var noTestsToRun = []byte("\ntesting: warning: no tests to run\n")
+
// runTest is the action for running a test binary.
func (b *builder) runTest(a *action) error {
args := stringList(findExecCmd(), a.deps[0].target, testArgs)
@@ -1179,10 +1199,14 @@ func (b *builder) runTest(a *action) error {
out := buf.Bytes()
t := fmt.Sprintf("%.3fs", time.Since(t0).Seconds())
if err == nil {
+ norun := ""
if testShowPass {
a.testOutput.Write(out)
}
- fmt.Fprintf(a.testOutput, "ok \t%s\t%s%s\n", a.p.ImportPath, t, coveragePercentage(out))
+ if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) {
+ norun = " [no tests to run]"
+ }
+ fmt.Fprintf(a.testOutput, "ok \t%s\t%s%s%s\n", a.p.ImportPath, t, coveragePercentage(out), norun)
return nil
}
@@ -1406,7 +1430,7 @@ func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
}
}
ex := doc.Examples(f)
- sort.Sort(byOrder(ex))
+ sort.Slice(ex, func(i, j int) bool { return ex[i].Order < ex[j].Order })
for _, e := range ex {
*doImport = true // import test file whether executed or not
if e.Output == "" && !e.EmptyOutput {
@@ -1428,12 +1452,6 @@ func checkTestFunc(fn *ast.FuncDecl, arg string) error {
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
@@ -1441,8 +1459,8 @@ import (
{{if not .TestMain}}
"os"
{{end}}
- "regexp"
"testing"
+ "testing/internal/testdeps"
{{if .ImportTest}}
{{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}}
@@ -1477,20 +1495,6 @@ var examples = []testing.InternalExample{
{{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.
@@ -1539,7 +1543,7 @@ func main() {
CoveredPackages: {{printf "%q" .Covered}},
})
{{end}}
- m := testing.MainStart(matchString, tests, benchmarks, examples)
+ m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, examples)
{{with .TestMain}}
{{.Package}}.{{.Name}}(m)
{{else}}
diff --git a/libgo/go/cmd/go/testdata/src/canonical/a/a.go b/libgo/go/cmd/go/testdata/src/canonical/a/a.go
new file mode 100644
index 00000000000..486cc4843fd
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/canonical/a/a.go
@@ -0,0 +1,3 @@
+package a
+
+import _ "c"
diff --git a/libgo/go/cmd/go/testdata/src/canonical/a/c/c.go b/libgo/go/cmd/go/testdata/src/canonical/a/c/c.go
new file mode 100644
index 00000000000..7f96c221c2d
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/canonical/a/c/c.go
@@ -0,0 +1 @@
+package c
diff --git a/libgo/go/cmd/go/testdata/src/canonical/b/b.go b/libgo/go/cmd/go/testdata/src/canonical/b/b.go
new file mode 100644
index 00000000000..ce0f4ce3035
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/canonical/b/b.go
@@ -0,0 +1,3 @@
+package b
+
+import _ "canonical/a/"
diff --git a/libgo/go/cmd/go/testdata/src/canonical/d/d.go b/libgo/go/cmd/go/testdata/src/canonical/d/d.go
new file mode 100644
index 00000000000..ef7dd7dd461
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/canonical/d/d.go
@@ -0,0 +1,3 @@
+package d
+
+import _ "canonical/b"
diff --git a/libgo/go/cmd/go/testdata/cgocover/p.go b/libgo/go/cmd/go/testdata/src/cgocover/p.go
index a6a3891cd4e..a6a3891cd4e 100644
--- a/libgo/go/cmd/go/testdata/cgocover/p.go
+++ b/libgo/go/cmd/go/testdata/src/cgocover/p.go
diff --git a/libgo/go/cmd/go/testdata/cgocover/p_test.go b/libgo/go/cmd/go/testdata/src/cgocover/p_test.go
index a8f057e3587..a8f057e3587 100644
--- a/libgo/go/cmd/go/testdata/cgocover/p_test.go
+++ b/libgo/go/cmd/go/testdata/src/cgocover/p_test.go
diff --git a/libgo/go/cmd/go/testdata/src/cgocover2/p.go b/libgo/go/cmd/go/testdata/src/cgocover2/p.go
new file mode 100644
index 00000000000..a6a3891cd4e
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/cgocover2/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/src/cgocover2/x_test.go b/libgo/go/cmd/go/testdata/src/cgocover2/x_test.go
new file mode 100644
index 00000000000..f4790d2367b
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/cgocover2/x_test.go
@@ -0,0 +1,10 @@
+package p_test
+
+import (
+ . "cgocover2"
+ "testing"
+)
+
+func TestF(t *testing.T) {
+ F()
+}
diff --git a/libgo/go/cmd/go/testdata/src/cgocover3/p.go b/libgo/go/cmd/go/testdata/src/cgocover3/p.go
new file mode 100644
index 00000000000..a6a3891cd4e
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/cgocover3/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/src/cgocover3/p_test.go b/libgo/go/cmd/go/testdata/src/cgocover3/p_test.go
new file mode 100644
index 00000000000..c89cd18d0fe
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/cgocover3/p_test.go
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testdata/src/cgocover3/x_test.go b/libgo/go/cmd/go/testdata/src/cgocover3/x_test.go
new file mode 100644
index 00000000000..97d0e0f0989
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/cgocover3/x_test.go
@@ -0,0 +1,10 @@
+package p_test
+
+import (
+ . "cgocover3"
+ "testing"
+)
+
+func TestF(t *testing.T) {
+ F()
+}
diff --git a/libgo/go/cmd/go/testdata/src/cgocover4/notcgo.go b/libgo/go/cmd/go/testdata/src/cgocover4/notcgo.go
new file mode 100644
index 00000000000..c89cd18d0fe
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/cgocover4/notcgo.go
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testdata/src/cgocover4/p.go b/libgo/go/cmd/go/testdata/src/cgocover4/p.go
new file mode 100644
index 00000000000..a6a3891cd4e
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/cgocover4/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/src/cgocover4/x_test.go b/libgo/go/cmd/go/testdata/src/cgocover4/x_test.go
new file mode 100644
index 00000000000..fd9bae743cc
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/cgocover4/x_test.go
@@ -0,0 +1,10 @@
+package p_test
+
+import (
+ . "cgocover4"
+ "testing"
+)
+
+func TestF(t *testing.T) {
+ F()
+}
diff --git a/libgo/go/cmd/go/testdata/src/dupload/dupload.go b/libgo/go/cmd/go/testdata/src/dupload/dupload.go
new file mode 100644
index 00000000000..2f078525b9d
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/dupload/dupload.go
@@ -0,0 +1,8 @@
+package main
+
+import (
+ _ "dupload/p2"
+ _ "p"
+)
+
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/src/dupload/p/p.go b/libgo/go/cmd/go/testdata/src/dupload/p/p.go
new file mode 100644
index 00000000000..c89cd18d0fe
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/dupload/p/p.go
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testdata/src/dupload/p2/p2.go b/libgo/go/cmd/go/testdata/src/dupload/p2/p2.go
new file mode 100644
index 00000000000..8a80979b4e6
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/dupload/p2/p2.go
@@ -0,0 +1,3 @@
+package p2
+
+import _ "dupload/vendor/p"
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkg/pkg.go b/libgo/go/cmd/go/testdata/src/empty/pkg/pkg.go
new file mode 100644
index 00000000000..c89cd18d0fe
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/empty/pkg/pkg.go
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgtest/pkg.go b/libgo/go/cmd/go/testdata/src/empty/pkgtest/pkg.go
new file mode 100644
index 00000000000..c89cd18d0fe
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/empty/pkgtest/pkg.go
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgtest/test_test.go b/libgo/go/cmd/go/testdata/src/empty/pkgtest/test_test.go
new file mode 100644
index 00000000000..c89cd18d0fe
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/empty/pkgtest/test_test.go
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/pkg.go b/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/pkg.go
new file mode 100644
index 00000000000..c89cd18d0fe
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/pkg.go
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/test_test.go b/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/test_test.go
new file mode 100644
index 00000000000..c89cd18d0fe
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/test_test.go
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/xtest_test.go b/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/xtest_test.go
new file mode 100644
index 00000000000..9b64e8e1a26
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/empty/pkgtestxtest/xtest_test.go
@@ -0,0 +1 @@
+package p_test
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgxtest/pkg.go b/libgo/go/cmd/go/testdata/src/empty/pkgxtest/pkg.go
new file mode 100644
index 00000000000..c89cd18d0fe
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/empty/pkgxtest/pkg.go
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/pkgxtest/xtest_test.go b/libgo/go/cmd/go/testdata/src/empty/pkgxtest/xtest_test.go
new file mode 100644
index 00000000000..9b64e8e1a26
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/empty/pkgxtest/xtest_test.go
@@ -0,0 +1 @@
+package p_test
diff --git a/libgo/go/cmd/go/testdata/src/empty/test/test_test.go b/libgo/go/cmd/go/testdata/src/empty/test/test_test.go
new file mode 100644
index 00000000000..c89cd18d0fe
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/empty/test/test_test.go
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/testxtest/test_test.go b/libgo/go/cmd/go/testdata/src/empty/testxtest/test_test.go
new file mode 100644
index 00000000000..c89cd18d0fe
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/empty/testxtest/test_test.go
@@ -0,0 +1 @@
+package p
diff --git a/libgo/go/cmd/go/testdata/src/empty/testxtest/xtest_test.go b/libgo/go/cmd/go/testdata/src/empty/testxtest/xtest_test.go
new file mode 100644
index 00000000000..9b64e8e1a26
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/empty/testxtest/xtest_test.go
@@ -0,0 +1 @@
+package p_test
diff --git a/libgo/go/cmd/go/testdata/src/empty/xtest/xtest_test.go b/libgo/go/cmd/go/testdata/src/empty/xtest/xtest_test.go
new file mode 100644
index 00000000000..9b64e8e1a26
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/empty/xtest/xtest_test.go
@@ -0,0 +1 @@
+package p_test
diff --git a/libgo/go/cmd/go/testdata/src/gencycle/gencycle.go b/libgo/go/cmd/go/testdata/src/gencycle/gencycle.go
new file mode 100644
index 00000000000..600afd93e93
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/gencycle/gencycle.go
@@ -0,0 +1,5 @@
+//go:generate echo hello world
+
+package gencycle
+
+import _ "gencycle"
diff --git a/libgo/go/cmd/go/testdata/src/importmain/ismain/main.go b/libgo/go/cmd/go/testdata/src/importmain/ismain/main.go
new file mode 100644
index 00000000000..bf019076dd5
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/importmain/ismain/main.go
@@ -0,0 +1,5 @@
+package main
+
+import _ "importmain/test"
+
+func main() {}
diff --git a/libgo/go/cmd/go/testdata/src/importmain/test/test.go b/libgo/go/cmd/go/testdata/src/importmain/test/test.go
new file mode 100644
index 00000000000..56e54040790
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/importmain/test/test.go
@@ -0,0 +1 @@
+package test
diff --git a/libgo/go/cmd/go/testdata/src/importmain/test/test_test.go b/libgo/go/cmd/go/testdata/src/importmain/test/test_test.go
new file mode 100644
index 00000000000..2268a8267ed
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/importmain/test/test_test.go
@@ -0,0 +1,6 @@
+package test_test
+
+import "testing"
+import _ "importmain/ismain"
+
+func TestCase(t *testing.T) {}
diff --git a/libgo/go/cmd/go/testdata/src/my.pkg/main/main.go b/libgo/go/cmd/go/testdata/src/my.pkg/main/main.go
new file mode 100644
index 00000000000..c3e8de1276d
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/my.pkg/main/main.go
@@ -0,0 +1,7 @@
+package main
+
+import "my.pkg"
+
+func main() {
+ println(pkg.Text)
+}
diff --git a/libgo/go/cmd/go/testdata/src/my.pkg/pkg.go b/libgo/go/cmd/go/testdata/src/my.pkg/pkg.go
new file mode 100644
index 00000000000..17702a680bb
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/my.pkg/pkg.go
@@ -0,0 +1,3 @@
+package pkg
+
+var Text = "unset"
diff --git a/libgo/go/cmd/go/testdata/src/testrace/race_test.go b/libgo/go/cmd/go/testdata/src/testrace/race_test.go
new file mode 100644
index 00000000000..264dcf0d8a0
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/src/testrace/race_test.go
@@ -0,0 +1,29 @@
+package testrace
+
+import "testing"
+
+func TestRace(t *testing.T) {
+ for i := 0; i < 10; i++ {
+ c := make(chan int)
+ x := 1
+ go func() {
+ x = 2
+ c <- 1
+ }()
+ x = 3
+ <-c
+ }
+}
+
+func BenchmarkRace(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ c := make(chan int)
+ x := 1
+ go func() {
+ x = 2
+ c <- 1
+ }()
+ x = 3
+ <-c
+ }
+}
diff --git a/libgo/go/cmd/go/testdata/standalone_benchmark_test.go b/libgo/go/cmd/go/testdata/standalone_benchmark_test.go
new file mode 100644
index 00000000000..4850f98d80c
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/standalone_benchmark_test.go
@@ -0,0 +1,6 @@
+package standalone_benchmark
+
+import "testing"
+
+func Benchmark(b *testing.B) {
+}
diff --git a/libgo/go/cmd/go/testdata/standalone_fail_sub_test.go b/libgo/go/cmd/go/testdata/standalone_fail_sub_test.go
new file mode 100644
index 00000000000..ac483f9e0c4
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/standalone_fail_sub_test.go
@@ -0,0 +1,8 @@
+package standalone_fail_sub_test
+
+import "testing"
+
+func TestThatFails(t *testing.T) {
+ t.Run("Sub", func(t *testing.T) {})
+ t.Fail()
+}
diff --git a/libgo/go/cmd/go/testdata/standalone_parallel_sub_test.go b/libgo/go/cmd/go/testdata/standalone_parallel_sub_test.go
new file mode 100644
index 00000000000..d326de0a5ac
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/standalone_parallel_sub_test.go
@@ -0,0 +1,14 @@
+package standalone_parallel_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+ ch := make(chan bool, 1)
+ t.Run("Sub", func(t *testing.T) {
+ t.Parallel()
+ <-ch
+ t.Run("Nested", func(t *testing.T) {})
+ })
+ // Ensures that Sub will finish after its t.Run call already returned.
+ ch <- true
+}
diff --git a/libgo/go/cmd/go/testdata/standalone_sub_test.go b/libgo/go/cmd/go/testdata/standalone_sub_test.go
new file mode 100644
index 00000000000..f6c31db9c81
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/standalone_sub_test.go
@@ -0,0 +1,7 @@
+package standalone_sub_test
+
+import "testing"
+
+func Test(t *testing.T) {
+ t.Run("Sub", func(t *testing.T) {})
+}
diff --git a/libgo/go/cmd/go/testdata/testterminal18153/terminal_test.go b/libgo/go/cmd/go/testdata/testterminal18153/terminal_test.go
new file mode 100644
index 00000000000..d662e55ee55
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/testterminal18153/terminal_test.go
@@ -0,0 +1,39 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+
+// This test is run by src/cmd/dist/test.go (cmd_go_test_terminal),
+// and not by cmd/go's tests. This is because this test requires that
+// that it be called with its stdout and stderr being a terminal.
+// dist doesn't run `cmd/go test` against this test directory if
+// dist's stdout/stderr aren't terminals.
+//
+// See issue 18153.
+
+package p
+
+import (
+ "syscall"
+ "testing"
+ "unsafe"
+)
+
+const ioctlReadTermios = syscall.TCGETS
+
+// isTerminal reports whether fd is a terminal.
+func isTerminal(fd uintptr) bool {
+ var termios syscall.Termios
+ _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
+ return err == 0
+}
+
+func TestIsTerminal(t *testing.T) {
+ if !isTerminal(1) {
+ t.Errorf("stdout is not a terminal")
+ }
+ if !isTerminal(2) {
+ t.Errorf("stderr is not a terminal")
+ }
+}
diff --git a/libgo/go/cmd/go/testflag.go b/libgo/go/cmd/go/testflag.go
index a65ed1f3840..fa53bfcdf09 100644
--- a/libgo/go/cmd/go/testflag.go
+++ b/libgo/go/cmd/go/testflag.go
@@ -50,6 +50,8 @@ var testFlagDefn = []*testFlagSpec{
{name: "memprofilerate", passToTest: true},
{name: "blockprofile", passToTest: true},
{name: "blockprofilerate", passToTest: true},
+ {name: "mutexprofile", passToTest: true},
+ {name: "mutexprofilefraction", passToTest: true},
{name: "outputdir", passToTest: true},
{name: "parallel", passToTest: true},
{name: "run", passToTest: true},
@@ -149,7 +151,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
testBench = true
case "timeout":
testTimeout = value
- case "blockprofile", "cpuprofile", "memprofile":
+ case "blockprofile", "cpuprofile", "memprofile", "mutexprofile":
testProfile = true
testNeedBinary = true
case "trace":
diff --git a/libgo/go/cmd/go/tool.go b/libgo/go/cmd/go/tool.go
index 65bf1ff33b0..6e2c68fbf53 100644
--- a/libgo/go/cmd/go/tool.go
+++ b/libgo/go/cmd/go/tool.go
@@ -66,7 +66,7 @@ func tool(toolName string) string {
} else {
fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
}
- setExitStatus(3)
+ setExitStatus(2)
exit()
}
return toolPath
diff --git a/libgo/go/cmd/go/vcs.go b/libgo/go/cmd/go/vcs.go
index 53ddbe694ee..fcdce220a7c 100644
--- a/libgo/go/cmd/go/vcs.go
+++ b/libgo/go/cmd/go/vcs.go
@@ -41,7 +41,7 @@ type vcsCmd struct {
resolveRepo func(v *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error)
}
-var isSecureScheme = map[string]bool{
+var defaultSecureScheme = map[string]bool{
"https": true,
"git+ssh": true,
"bzr+ssh": true,
@@ -55,7 +55,25 @@ func (v *vcsCmd) isSecure(repo string) bool {
// If repo is not a URL, it's not secure.
return false
}
- return isSecureScheme[u.Scheme]
+ return v.isSecureScheme(u.Scheme)
+}
+
+func (v *vcsCmd) isSecureScheme(scheme string) bool {
+ switch v.cmd {
+ case "git":
+ // GIT_ALLOW_PROTOCOL is an environment variable defined by Git. It is a
+ // colon-separated list of schemes that are allowed to be used with git
+ // fetch/clone. Any scheme not mentioned will be considered insecure.
+ if allow := os.Getenv("GIT_ALLOW_PROTOCOL"); allow != "" {
+ for _, s := range strings.Split(allow, ":") {
+ if s == scheme {
+ return true
+ }
+ }
+ return false
+ }
+ }
+ return defaultSecureScheme[scheme]
}
// A tagCmd describes a command to list available tags
@@ -482,7 +500,7 @@ func vcsFromDir(dir, srcRoot string) (vcs *vcsCmd, root string, err error) {
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() {
+ if _, err := os.Stat(filepath.Join(dir, "."+vcs.cmd)); err == nil {
return vcs, filepath.ToSlash(dir[len(srcRoot)+1:]), nil
}
}
@@ -510,6 +528,9 @@ type repoRoot struct {
// root is the import path corresponding to the root of the
// repository
root string
+
+ // isCustom is true for custom import paths (those defined by HTML meta tags)
+ isCustom bool
}
var httpPrefixRE = regexp.MustCompile(`^https?:`)
@@ -612,7 +633,7 @@ func repoRootFromVCSPaths(importPath, scheme string, security securityMode, vcsP
match["repo"] = scheme + "://" + match["repo"]
} else {
for _, scheme := range vcs.scheme {
- if security == secure && !isSecureScheme[scheme] {
+ if security == secure && !vcs.isSecureScheme(scheme) {
continue
}
if vcs.ping(scheme, match["repo"]) == nil {
@@ -661,10 +682,10 @@ func repoRootForImportDynamic(importPath string, security securityMode) (*repoRo
// Find the matched meta import.
mmi, err := matchGoImport(imports, importPath)
if err != nil {
- if err != errNoMatch {
+ if _, ok := err.(ImportMismatchError); !ok {
return nil, fmt.Errorf("parse %s: %v", urlStr, err)
}
- return nil, fmt.Errorf("parse %s: no go-import meta tags", urlStr)
+ return nil, fmt.Errorf("parse %s: no go-import meta tags (%s)", urlStr, err)
}
if buildV {
log.Printf("get %q: found meta tag %#v at %s", importPath, mmi, urlStr)
@@ -695,9 +716,10 @@ func repoRootForImportDynamic(importPath string, security securityMode) (*repoRo
return nil, fmt.Errorf("%s: invalid repo root %q; no scheme", urlStr, mmi.RepoRoot)
}
rr := &repoRoot{
- vcs: vcsByCmd(mmi.VCS),
- repo: mmi.RepoRoot,
- root: mmi.Prefix,
+ vcs: vcsByCmd(mmi.VCS),
+ repo: mmi.RepoRoot,
+ root: mmi.Prefix,
+ isCustom: true,
}
if rr.vcs == nil {
return nil, fmt.Errorf("%s: unknown vcs %q", urlStr, mmi.VCS)
@@ -764,9 +786,6 @@ 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")
-
func splitPathHasPrefix(path, prefix []string) bool {
if len(path) < len(prefix) {
return false
@@ -779,28 +798,45 @@ func splitPathHasPrefix(path, prefix []string) bool {
return true
}
+// A ImportMismatchError is returned where metaImport/s are present
+// but none match our import path.
+type ImportMismatchError struct {
+ importPath string
+ mismatches []string // the meta imports that were discarded for not matching our importPath
+}
+
+func (m ImportMismatchError) Error() string {
+ formattedStrings := make([]string, len(m.mismatches))
+ for i, pre := range m.mismatches {
+ formattedStrings[i] = fmt.Sprintf("meta tag %s did not match import path %s", pre, m.importPath)
+ }
+ return strings.Join(formattedStrings, ", ")
+}
+
// 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) {
+func matchGoImport(imports []metaImport, importPath string) (metaImport, error) {
match := -1
imp := strings.Split(importPath, "/")
+
+ errImportMismatch := ImportMismatchError{importPath: importPath}
for i, im := range imports {
pre := strings.Split(im.Prefix, "/")
if !splitPathHasPrefix(imp, pre) {
+ errImportMismatch.mismatches = append(errImportMismatch.mismatches, im.Prefix)
continue
}
if match != -1 {
- err = fmt.Errorf("multiple meta tags match import path %q", importPath)
- return
+ return metaImport{}, fmt.Errorf("multiple meta tags match import path %q", importPath)
}
match = i
}
+
if match == -1 {
- err = errNoMatch
- return
+ return metaImport{}, errImportMismatch
}
return imports[match], nil
}
diff --git a/libgo/go/cmd/go/vcs_test.go b/libgo/go/cmd/go/vcs_test.go
index 25e3866df06..c73f5d0e85b 100644
--- a/libgo/go/cmd/go/vcs_test.go
+++ b/libgo/go/cmd/go/vcs_test.go
@@ -102,7 +102,7 @@ func TestRepoRootForImportPath(t *testing.T) {
"git.openstack.org/openstack/swift.git",
&repoRoot{
vcs: vcsGit,
- repo: "https://git.openstack.org/openstack/swift",
+ repo: "https://git.openstack.org/openstack/swift.git",
},
},
{
@@ -174,11 +174,23 @@ func TestFromDir(t *testing.T) {
}
defer os.RemoveAll(tempDir)
- for _, vcs := range vcsList {
+ for j, vcs := range vcsList {
dir := filepath.Join(tempDir, "example.com", vcs.name, "."+vcs.cmd)
- err := os.MkdirAll(dir, 0755)
- if err != nil {
- t.Fatal(err)
+ if j&1 == 0 {
+ err := os.MkdirAll(dir, 0755)
+ if err != nil {
+ t.Fatal(err)
+ }
+ } else {
+ err := os.MkdirAll(filepath.Dir(dir), 0755)
+ if err != nil {
+ t.Fatal(err)
+ }
+ f, err := os.Create(dir)
+ if err != nil {
+ t.Fatal(err)
+ }
+ f.Close()
}
want := repoRoot{
@@ -229,6 +241,46 @@ func TestIsSecure(t *testing.T) {
}
}
+func TestIsSecureGitAllowProtocol(t *testing.T) {
+ tests := []struct {
+ vcs *vcsCmd
+ url string
+ secure bool
+ }{
+ // Same as TestIsSecure to verify same behavior.
+ {vcsGit, "http://example.com/foo.git", false},
+ {vcsGit, "https://example.com/foo.git", true},
+ {vcsBzr, "http://example.com/foo.bzr", false},
+ {vcsBzr, "https://example.com/foo.bzr", true},
+ {vcsSvn, "http://example.com/svn", false},
+ {vcsSvn, "https://example.com/svn", true},
+ {vcsHg, "http://example.com/foo.hg", false},
+ {vcsHg, "https://example.com/foo.hg", true},
+ {vcsGit, "user@server:path/to/repo.git", false},
+ {vcsGit, "user@server:", false},
+ {vcsGit, "server:repo.git", false},
+ {vcsGit, "server:path/to/repo.git", false},
+ {vcsGit, "example.com:path/to/repo.git", false},
+ {vcsGit, "path/that/contains/a:colon/repo.git", false},
+ {vcsHg, "ssh://user@example.com/path/to/repo.hg", true},
+ // New behavior.
+ {vcsGit, "ssh://user@example.com/foo.git", false},
+ {vcsGit, "foo://example.com/bar.git", true},
+ {vcsHg, "foo://example.com/bar.hg", false},
+ {vcsSvn, "foo://example.com/svn", false},
+ {vcsBzr, "foo://example.com/bar.bzr", false},
+ }
+
+ defer os.Unsetenv("GIT_ALLOW_PROTOCOL")
+ os.Setenv("GIT_ALLOW_PROTOCOL", "https:foo")
+ for _, test := range tests {
+ secure := test.vcs.isSecure(test.url)
+ if secure != test.secure {
+ t.Errorf("%s isSecure(%q) = %t; want %t", test.vcs, test.url, secure, test.secure)
+ }
+ }
+}
+
func TestMatchGoImport(t *testing.T) {
tests := []struct {
imports []metaImport
@@ -306,6 +358,13 @@ func TestMatchGoImport(t *testing.T) {
path: "example.com",
err: errors.New("pathologically short path"),
},
+ {
+ imports: []metaImport{
+ {Prefix: "example.com/user/foo", VCS: "git", RepoRoot: "https://example.com/repo/target"},
+ },
+ path: "different.example.com/user/foo",
+ err: errors.New("meta tags do not match import path"),
+ },
}
for _, test := range tests {
diff --git a/libgo/go/cmd/go/vendor_test.go b/libgo/go/cmd/go/vendor_test.go
index 226b5377b98..deec02e3413 100644
--- a/libgo/go/cmd/go/vendor_test.go
+++ b/libgo/go/cmd/go/vendor_test.go
@@ -188,6 +188,42 @@ func TestVendorGetUpdate(t *testing.T) {
tg.run("get", "-u", "github.com/rsc/go-get-issue-11864")
}
+func TestVendorGetU(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("."))
+ tg.run("get", "-u", "github.com/rsc/go-get-issue-11864")
+}
+
+func TestVendorGetTU(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("."))
+ tg.run("get", "-t", "-u", "github.com/rsc/go-get-issue-11864/...")
+}
+
+func TestVendorGetBadVendor(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ for _, suffix := range []string{"bad/imp", "bad/imp2", "bad/imp3", "..."} {
+ t.Run(suffix, func(t *testing.T) {
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("."))
+ tg.runFail("get", "-t", "-u", "github.com/rsc/go-get-issue-18219/"+suffix)
+ tg.grepStderr("must be imported as", "did not find error about vendor import")
+ tg.mustNotExist(tg.path("src/github.com/rsc/vendor"))
+ })
+ }
+}
+
func TestGetSubmodules(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
diff --git a/libgo/go/cmd/gofmt/doc.go b/libgo/go/cmd/gofmt/doc.go
index 9d0cd328623..8b22f03f653 100644
--- a/libgo/go/cmd/gofmt/doc.go
+++ b/libgo/go/cmd/gofmt/doc.go
@@ -32,7 +32,8 @@ The flags are:
-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.
+ with gofmt's version. If an error occurred during overwriting,
+ the original file is restored from an automatic backup.
Debugging support:
-cpuprofile filename
@@ -98,3 +99,5 @@ This may result in changes that are incompatible with earlier versions of Go.
package main
// BUG(rsc): The implementation of -r is a bit slow.
+// BUG(gri): If -w fails, the restored original file may not have some of the
+// original file attributes.
diff --git a/libgo/go/cmd/gofmt/gofmt.go b/libgo/go/cmd/gofmt/gofmt.go
index f29b6cb83d9..e1ef0ddb837 100644
--- a/libgo/go/cmd/gofmt/gofmt.go
+++ b/libgo/go/cmd/gofmt/gofmt.go
@@ -18,6 +18,7 @@ import (
"os"
"os/exec"
"path/filepath"
+ "runtime"
"runtime/pprof"
"strings"
)
@@ -72,13 +73,19 @@ func isGoFile(f os.FileInfo) bool {
// 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 {
+ var perm os.FileMode = 0644
if in == nil {
f, err := os.Open(filename)
if err != nil {
return err
}
defer f.Close()
+ fi, err := f.Stat()
+ if err != nil {
+ return err
+ }
in = f
+ perm = fi.Mode().Perm()
}
src, err := ioutil.ReadAll(in)
@@ -116,7 +123,17 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
fmt.Fprintln(out, filename)
}
if *write {
- err = ioutil.WriteFile(filename, res, 0644)
+ // make a temporary backup before overwriting original
+ bakname, err := backupFile(filename+".", src, perm)
+ if err != nil {
+ return err
+ }
+ err = ioutil.WriteFile(filename, res, perm)
+ if err != nil {
+ os.Rename(bakname, filename)
+ return err
+ }
+ err = os.Remove(bakname)
if err != nil {
return err
}
@@ -235,3 +252,36 @@ func diff(b1, b2 []byte) (data []byte, err error) {
return
}
+
+const chmodSupported = runtime.GOOS != "windows"
+
+// backupFile writes data to a new file named filename<number> with permissions perm,
+// with <number randomly chosen such that the file name is unique. backupFile returns
+// the chosen file name.
+func backupFile(filename string, data []byte, perm os.FileMode) (string, error) {
+ // create backup file
+ f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename))
+ if err != nil {
+ return "", err
+ }
+ bakname := f.Name()
+ if chmodSupported {
+ err = f.Chmod(perm)
+ if err != nil {
+ f.Close()
+ os.Remove(bakname)
+ return bakname, err
+ }
+ }
+
+ // write data to backup file
+ n, err := f.Write(data)
+ if err == nil && n < len(data) {
+ err = io.ErrShortWrite
+ }
+ if err1 := f.Close(); err == nil {
+ err = err1
+ }
+
+ return bakname, err
+}
diff --git a/libgo/go/cmd/gofmt/gofmt_test.go b/libgo/go/cmd/gofmt/gofmt_test.go
index dea012764b3..b7ca9e8d119 100644
--- a/libgo/go/cmd/gofmt/gofmt_test.go
+++ b/libgo/go/cmd/gofmt/gofmt_test.go
@@ -171,3 +171,16 @@ func TestCRLF(t *testing.T) {
t.Errorf("%s contains CR's", golden)
}
}
+
+func TestBackupFile(t *testing.T) {
+ dir, err := ioutil.TempDir("", "gofmt_test")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+ name, err := backupFile(filepath.Join(dir, "foo.go"), []byte(" package main"), 0644)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Logf("Created: %s", name)
+}
diff --git a/libgo/go/cmd/gofmt/simplify.go b/libgo/go/cmd/gofmt/simplify.go
index 2ebf4cde0be..1a0e8174afa 100644
--- a/libgo/go/cmd/gofmt/simplify.go
+++ b/libgo/go/cmd/gofmt/simplify.go
@@ -17,47 +17,33 @@ func (s simplifier) Visit(node ast.Node) ast.Visitor {
case *ast.CompositeLit:
// array, slice, and map composite literals may be simplified
outer := n
- var eltType ast.Expr
+ var keyType, eltType ast.Expr
switch typ := outer.Type.(type) {
case *ast.ArrayType:
eltType = typ.Elt
case *ast.MapType:
+ keyType = typ.Key
eltType = typ.Value
}
if eltType != nil {
+ var ktyp reflect.Value
+ if keyType != nil {
+ ktyp = reflect.ValueOf(keyType)
+ }
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 {
+ if keyType != nil {
+ s.simplifyLiteral(ktyp, keyType, t.Key, &t.Key)
+ }
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 &
- }
- }
- }
- }
+ s.simplifyLiteral(typ, eltType, x, px)
}
-
// node was simplified - stop walk (there are no subnodes to simplify)
return nil
}
@@ -113,6 +99,32 @@ func (s simplifier) Visit(node ast.Node) ast.Visitor {
return s
}
+func (s simplifier) simplifyLiteral(typ reflect.Value, astType, x ast.Expr, px *ast.Expr) {
+ 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 := astType.(*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 &
+ }
+ }
+ }
+ }
+}
+
func isBlank(x ast.Expr) bool {
ident, ok := x.(*ast.Ident)
return ok && ident.Name == "_"
diff --git a/libgo/go/cmd/gofmt/testdata/composites.golden b/libgo/go/cmd/gofmt/testdata/composites.golden
index fc9c98e625b..a06a69d0965 100644
--- a/libgo/go/cmd/gofmt/testdata/composites.golden
+++ b/libgo/go/cmd/gofmt/testdata/composites.golden
@@ -6,6 +6,10 @@ type T struct {
x, y int
}
+type T2 struct {
+ w, z int
+}
+
var _ = [42]T{
{},
{1, 2},
@@ -202,3 +206,13 @@ var pieces4 = []*Piece{
{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 _ = map[T]T2{
+ {1, 2}: {3, 4},
+ {5, 6}: {7, 8},
+}
+
+var _ = map[*T]*T2{
+ {1, 2}: {3, 4},
+ {5, 6}: {7, 8},
+}
diff --git a/libgo/go/cmd/gofmt/testdata/composites.input b/libgo/go/cmd/gofmt/testdata/composites.input
index fc7598af99e..9d28ac7ed31 100644
--- a/libgo/go/cmd/gofmt/testdata/composites.input
+++ b/libgo/go/cmd/gofmt/testdata/composites.input
@@ -6,6 +6,10 @@ type T struct {
x, y int
}
+type T2 struct {
+ w, z int
+}
+
var _ = [42]T{
T{},
T{1, 2},
@@ -202,3 +206,13 @@ var pieces4 = []*Piece{
&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 _ = map[T]T2{
+ T{1, 2}: T2{3, 4},
+ T{5, 6}: T2{7, 8},
+}
+
+var _ = map[*T]*T2{
+ &T{1, 2}: &T2{3, 4},
+ &T{5, 6}: &T2{7, 8},
+}
diff --git a/libgo/go/cmd/internal/browser/browser.go b/libgo/go/cmd/internal/browser/browser.go
new file mode 100644
index 00000000000..897086f4717
--- /dev/null
+++ b/libgo/go/cmd/internal/browser/browser.go
@@ -0,0 +1,46 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package browser provides utilities for interacting with users' browsers.
+package browser
+
+import (
+ "os"
+ "os/exec"
+ "runtime"
+)
+
+// Commands returns a list of possible commands to use to open a url.
+func Commands() [][]string {
+ var cmds [][]string
+ if exe := os.Getenv("BROWSER"); exe != "" {
+ cmds = append(cmds, []string{exe})
+ }
+ switch runtime.GOOS {
+ case "darwin":
+ cmds = append(cmds, []string{"/usr/bin/open"})
+ case "windows":
+ cmds = append(cmds, []string{"cmd", "/c", "start"})
+ default:
+ cmds = append(cmds, []string{"xdg-open"})
+ }
+ cmds = append(cmds,
+ []string{"chrome"},
+ []string{"google-chrome"},
+ []string{"chromium"},
+ []string{"firefox"},
+ )
+ return cmds
+}
+
+// Open tries to open url in a browser and reports whether it succeeded.
+func Open(url string) bool {
+ for _, args := range Commands() {
+ cmd := exec.Command(args[0], append(args[1:], url)...)
+ if cmd.Start() == nil {
+ return true
+ }
+ }
+ return false
+}
diff --git a/libgo/go/compress/flate/deflate.go b/libgo/go/compress/flate/deflate.go
index 9f53d51a6e7..97265b3ca27 100644
--- a/libgo/go/compress/flate/deflate.go
+++ b/libgo/go/compress/flate/deflate.go
@@ -84,9 +84,10 @@ type compressor struct {
bulkHasher func([]byte, []uint32)
// compression algorithm
- fill func(*compressor, []byte) int // copy data to window
- step func(*compressor) // process window
- sync bool // requesting flush
+ fill func(*compressor, []byte) int // copy data to window
+ step func(*compressor) // process window
+ sync bool // requesting flush
+ bestSpeed *deflateFast // Encoder for BestSpeed
// Input hash chains
// hashHead[hashValue] contains the largest inputIndex with the specified hash value
@@ -346,12 +347,13 @@ func (d *compressor) encSpeed() {
d.err = d.w.err
}
d.windowEnd = 0
+ d.bestSpeed.reset()
return
}
}
// Encode the block.
- d.tokens = encodeBestSpeed(d.tokens[:0], d.window[:d.windowEnd])
+ d.tokens = d.bestSpeed.encode(d.tokens[:0], d.window[:d.windowEnd])
// If we removed less than 1/16th, Huffman compress the block.
if len(d.tokens) > d.windowEnd-(d.windowEnd>>4) {
@@ -519,10 +521,10 @@ func (d *compressor) fillStore(b []byte) int {
}
func (d *compressor) store() {
- if d.windowEnd > 0 {
+ if d.windowEnd > 0 && (d.windowEnd == maxStoreBlockSize || d.sync) {
d.err = d.writeStoredBlock(d.window[:d.windowEnd])
+ d.windowEnd = 0
}
- d.windowEnd = 0
}
// storeHuff compresses and stores the currently added data
@@ -584,6 +586,7 @@ func (d *compressor) init(w io.Writer, level int) (err error) {
d.window = make([]byte, maxStoreBlockSize)
d.fill = (*compressor).fillStore
d.step = (*compressor).encSpeed
+ d.bestSpeed = newDeflateFast()
d.tokens = make([]token, maxStoreBlockSize)
case level == DefaultCompression:
level = 6
@@ -609,6 +612,7 @@ func (d *compressor) reset(w io.Writer) {
case BestSpeed:
d.windowEnd = 0
d.tokens = d.tokens[:0]
+ d.bestSpeed.reset()
default:
d.chainHead = -1
for i := range d.hashHead {
@@ -702,10 +706,12 @@ func (w *Writer) Write(data []byte) (n int, err error) {
return w.d.write(data)
}
-// Flush flushes any pending compressed data to the underlying writer.
+// Flush flushes any pending data to the underlying writer.
// It is useful mainly in compressed network protocols, to ensure that
// a remote reader has enough data to reconstruct a packet.
// Flush does not return until the data has been written.
+// Calling Flush when there is no pending data still causes the Writer
+// to emit a sync marker of at least 4 bytes.
// If the underlying writer returns an error, Flush returns that error.
//
// In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH.
diff --git a/libgo/go/compress/flate/deflate_test.go b/libgo/go/compress/flate/deflate_test.go
index 3322c40845d..521a2603658 100644
--- a/libgo/go/compress/flate/deflate_test.go
+++ b/libgo/go/compress/flate/deflate_test.go
@@ -342,6 +342,7 @@ func testToFromWithLimit(t *testing.T, input []byte, name string, limit [11]int)
}
func TestDeflateInflate(t *testing.T) {
+ t.Parallel()
for i, h := range deflateInflateTests {
testToFromWithLimit(t, h.in, fmt.Sprintf("#%d", i), [11]int{})
}
@@ -376,6 +377,7 @@ var deflateInflateStringTests = []deflateInflateStringTest{
}
func TestDeflateInflateString(t *testing.T) {
+ t.Parallel()
if testing.Short() && testenv.Builder() == "" {
t.Skip("skipping in short mode")
}
@@ -463,6 +465,7 @@ func TestRegression2508(t *testing.T) {
}
func TestWriterReset(t *testing.T) {
+ t.Parallel()
for level := 0; level <= 9; level++ {
if testing.Short() && level > 1 {
break
@@ -490,6 +493,7 @@ func TestWriterReset(t *testing.T) {
w.d.fill, wref.d.fill = nil, nil
w.d.step, wref.d.step = nil, nil
w.d.bulkHasher, wref.d.bulkHasher = nil, nil
+ w.d.bestSpeed, wref.d.bestSpeed = nil, nil
// hashMatch is always overwritten when used.
copy(w.d.hashMatch[:], wref.d.hashMatch[:])
if len(w.d.tokens) != 0 {
@@ -558,6 +562,7 @@ func testResetOutput(t *testing.T, newWriter func(w io.Writer) (*Writer, error))
// compressor.encSpeed method (0, 16, 128), as well as near maxStoreBlockSize
// (65535).
func TestBestSpeed(t *testing.T) {
+ t.Parallel()
abc := make([]byte, 128)
for i := range abc {
abc[i] = byte(i)
@@ -647,6 +652,7 @@ func (w *failWriter) Write(b []byte) (int, error) {
}
func TestWriterPersistentError(t *testing.T) {
+ t.Parallel()
d, err := ioutil.ReadFile("../testdata/Mark.Twain-Tom.Sawyer.txt")
if err != nil {
t.Fatalf("ReadFile: %v", err)
@@ -681,3 +687,180 @@ func TestWriterPersistentError(t *testing.T) {
}
}
}
+
+func TestBestSpeedMatch(t *testing.T) {
+ t.Parallel()
+ cases := []struct {
+ previous, current []byte
+ t, s, want int32
+ }{{
+ previous: []byte{0, 0, 0, 1, 2},
+ current: []byte{3, 4, 5, 0, 1, 2, 3, 4, 5},
+ t: -3,
+ s: 3,
+ want: 6,
+ }, {
+ previous: []byte{0, 0, 0, 1, 2},
+ current: []byte{2, 4, 5, 0, 1, 2, 3, 4, 5},
+ t: -3,
+ s: 3,
+ want: 3,
+ }, {
+ previous: []byte{0, 0, 0, 1, 1},
+ current: []byte{3, 4, 5, 0, 1, 2, 3, 4, 5},
+ t: -3,
+ s: 3,
+ want: 2,
+ }, {
+ previous: []byte{0, 0, 0, 1, 2},
+ current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5},
+ t: -1,
+ s: 0,
+ want: 4,
+ }, {
+ previous: []byte{0, 0, 0, 1, 2, 3, 4, 5, 2, 2},
+ current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5},
+ t: -7,
+ s: 4,
+ want: 5,
+ }, {
+ previous: []byte{9, 9, 9, 9, 9},
+ current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5},
+ t: -1,
+ s: 0,
+ want: 0,
+ }, {
+ previous: []byte{9, 9, 9, 9, 9},
+ current: []byte{9, 2, 2, 2, 1, 2, 3, 4, 5},
+ t: 0,
+ s: 1,
+ want: 0,
+ }, {
+ previous: []byte{},
+ current: []byte{9, 2, 2, 2, 1, 2, 3, 4, 5},
+ t: -5,
+ s: 1,
+ want: 0,
+ }, {
+ previous: []byte{},
+ current: []byte{9, 2, 2, 2, 1, 2, 3, 4, 5},
+ t: -1,
+ s: 1,
+ want: 0,
+ }, {
+ previous: []byte{},
+ current: []byte{2, 2, 2, 2, 1, 2, 3, 4, 5},
+ t: 0,
+ s: 1,
+ want: 3,
+ }, {
+ previous: []byte{3, 4, 5},
+ current: []byte{3, 4, 5},
+ t: -3,
+ s: 0,
+ want: 3,
+ }, {
+ previous: make([]byte, 1000),
+ current: make([]byte, 1000),
+ t: -1000,
+ s: 0,
+ want: maxMatchLength - 4,
+ }, {
+ previous: make([]byte, 200),
+ current: make([]byte, 500),
+ t: -200,
+ s: 0,
+ want: maxMatchLength - 4,
+ }, {
+ previous: make([]byte, 200),
+ current: make([]byte, 500),
+ t: 0,
+ s: 1,
+ want: maxMatchLength - 4,
+ }, {
+ previous: make([]byte, maxMatchLength-4),
+ current: make([]byte, 500),
+ t: -(maxMatchLength - 4),
+ s: 0,
+ want: maxMatchLength - 4,
+ }, {
+ previous: make([]byte, 200),
+ current: make([]byte, 500),
+ t: -200,
+ s: 400,
+ want: 100,
+ }, {
+ previous: make([]byte, 10),
+ current: make([]byte, 500),
+ t: 200,
+ s: 400,
+ want: 100,
+ }}
+ for i, c := range cases {
+ e := deflateFast{prev: c.previous}
+ got := e.matchLen(c.s, c.t, c.current)
+ if got != c.want {
+ t.Errorf("Test %d: match length, want %d, got %d", i, c.want, got)
+ }
+ }
+}
+
+func TestBestSpeedMaxMatchOffset(t *testing.T) {
+ t.Parallel()
+ const abc, xyz = "abcdefgh", "stuvwxyz"
+ for _, matchBefore := range []bool{false, true} {
+ for _, extra := range []int{0, inputMargin - 1, inputMargin, inputMargin + 1, 2 * inputMargin} {
+ for offsetAdj := -5; offsetAdj <= +5; offsetAdj++ {
+ report := func(desc string, err error) {
+ t.Errorf("matchBefore=%t, extra=%d, offsetAdj=%d: %s%v",
+ matchBefore, extra, offsetAdj, desc, err)
+ }
+
+ offset := maxMatchOffset + offsetAdj
+
+ // Make src to be a []byte of the form
+ // "%s%s%s%s%s" % (abc, zeros0, xyzMaybe, abc, zeros1)
+ // where:
+ // zeros0 is approximately maxMatchOffset zeros.
+ // xyzMaybe is either xyz or the empty string.
+ // zeros1 is between 0 and 30 zeros.
+ // The difference between the two abc's will be offset, which
+ // is maxMatchOffset plus or minus a small adjustment.
+ src := make([]byte, offset+len(abc)+extra)
+ copy(src, abc)
+ if !matchBefore {
+ copy(src[offset-len(xyz):], xyz)
+ }
+ copy(src[offset:], abc)
+
+ buf := new(bytes.Buffer)
+ w, err := NewWriter(buf, BestSpeed)
+ if err != nil {
+ report("NewWriter: ", err)
+ continue
+ }
+ if _, err := w.Write(src); err != nil {
+ report("Write: ", err)
+ continue
+ }
+ if err := w.Close(); err != nil {
+ report("Writer.Close: ", err)
+ continue
+ }
+
+ r := NewReader(buf)
+ dst, err := ioutil.ReadAll(r)
+ r.Close()
+ if err != nil {
+ report("ReadAll: ", err)
+ continue
+ }
+
+ if !bytes.Equal(dst, src) {
+ report("", fmt.Errorf("bytes differ after round-tripping"))
+ continue
+ }
+ }
+ }
+ }
+}
diff --git a/libgo/go/compress/flate/deflatefast.go b/libgo/go/compress/flate/deflatefast.go
index 6b881a477c4..a1636a37d67 100644
--- a/libgo/go/compress/flate/deflatefast.go
+++ b/libgo/go/compress/flate/deflatefast.go
@@ -14,12 +14,12 @@ const (
tableShift = 32 - tableBits // Right-shift to get the tableBits most significant bits of a uint32.
)
-func load32(b []byte, i int) uint32 {
+func load32(b []byte, i int32) uint32 {
b = b[i : i+4 : len(b)] // Help the compiler eliminate bounds checks on the next line.
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
-func load64(b []byte, i int) uint64 {
+func load64(b []byte, i int32) uint64 {
b = b[i : i+8 : len(b)] // Help the compiler eliminate bounds checks on the next line.
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
@@ -38,31 +38,49 @@ const (
minNonLiteralBlockSize = 1 + 1 + inputMargin
)
-func encodeBestSpeed(dst []token, src []byte) []token {
+type tableEntry struct {
+ val uint32 // Value at destination
+ offset int32
+}
+
+// deflateFast maintains the table for matches,
+// and the previous byte block for cross block matching.
+type deflateFast struct {
+ table [tableSize]tableEntry
+ prev []byte // Previous block, zero length if unknown.
+ cur int32 // Current match offset.
+}
+
+func newDeflateFast() *deflateFast {
+ return &deflateFast{cur: maxStoreBlockSize, prev: make([]byte, 0, maxStoreBlockSize)}
+}
+
+// encode encodes a block given in src and appends tokens
+// to dst and returns the result.
+func (e *deflateFast) encode(dst []token, src []byte) []token {
+ // Ensure that e.cur doesn't wrap.
+ if e.cur > 1<<30 {
+ *e = deflateFast{cur: maxStoreBlockSize, prev: e.prev[:0]}
+ }
+
// This check isn't in the Snappy implementation, but there, the caller
// instead of the callee handles this case.
if len(src) < minNonLiteralBlockSize {
+ e.cur += maxStoreBlockSize
+ e.prev = e.prev[:0]
return emitLiteral(dst, src)
}
- // Initialize the hash table.
- //
- // The table element type is uint16, as s < sLimit and sLimit < len(src)
- // and len(src) <= maxStoreBlockSize and maxStoreBlockSize == 65535.
- var table [tableSize]uint16
-
// sLimit is when to stop looking for offset/length copies. The inputMargin
// lets us use a fast path for emitLiteral in the main loop, while we are
// looking for copies.
- sLimit := len(src) - inputMargin
+ sLimit := int32(len(src) - inputMargin)
// nextEmit is where in src the next emitLiteral should start from.
- nextEmit := 0
-
- // The encoded form must start with a literal, as there are no previous
- // bytes to copy, so we start looking for hash matches at s == 1.
- s := 1
- nextHash := hash(load32(src, s))
+ nextEmit := int32(0)
+ s := int32(0)
+ cv := load32(src, s)
+ nextHash := hash(cv)
for {
// Copied from the C++ snappy implementation:
@@ -80,10 +98,10 @@ func encodeBestSpeed(dst []token, src []byte) []token {
// The "skip" variable keeps track of how many bytes there are since
// the last match; dividing it by 32 (ie. right-shifting by five) gives
// the number of bytes to move ahead for each iteration.
- skip := 32
+ skip := int32(32)
nextS := s
- candidate := 0
+ var candidate tableEntry
for {
s = nextS
bytesBetweenHashLookups := skip >> 5
@@ -92,13 +110,18 @@ func encodeBestSpeed(dst []token, src []byte) []token {
if nextS > sLimit {
goto emitRemainder
}
- candidate = int(table[nextHash&tableMask])
- table[nextHash&tableMask] = uint16(s)
- nextHash = hash(load32(src, nextS))
- // TODO: < should be <=, and add a test for that.
- if s-candidate < maxMatchOffset && load32(src, s) == load32(src, candidate) {
- break
+ candidate = e.table[nextHash&tableMask]
+ now := load32(src, nextS)
+ e.table[nextHash&tableMask] = tableEntry{offset: s + e.cur, val: cv}
+ nextHash = hash(now)
+
+ offset := s - (candidate.offset - e.cur)
+ if offset > maxMatchOffset || cv != candidate.val {
+ // Out of range or not matched.
+ cv = now
+ continue
}
+ break
}
// A 4-byte match has been found. We'll later see if more than 4 bytes
@@ -117,22 +140,16 @@ func encodeBestSpeed(dst []token, src []byte) []token {
for {
// Invariant: we have a 4-byte match at s, and no need to emit any
// literal bytes prior to s.
- base := s
// Extend the 4-byte match as long as possible.
//
- // This is an inlined version of Snappy's:
- // s = extendMatch(src, candidate+4, s+4)
s += 4
- s1 := base + maxMatchLength
- if s1 > len(src) {
- s1 = len(src)
- }
- for i := candidate + 4; s < s1 && src[i] == src[s]; i, s = i+1, s+1 {
- }
+ t := candidate.offset - e.cur + 4
+ l := e.matchLen(s, t, src)
- // matchToken is flate's equivalent of Snappy's emitCopy.
- dst = append(dst, matchToken(uint32(s-base-baseMatchLength), uint32(base-candidate-baseMatchOffset)))
+ // matchToken is flate's equivalent of Snappy's emitCopy. (length,offset)
+ dst = append(dst, matchToken(uint32(l+4-baseMatchLength), uint32(s-t-baseMatchOffset)))
+ s += l
nextEmit = s
if s >= sLimit {
goto emitRemainder
@@ -145,14 +162,17 @@ func encodeBestSpeed(dst []token, src []byte) []token {
// are faster as one load64 call (with some shifts) instead of
// three load32 calls.
x := load64(src, s-1)
- prevHash := hash(uint32(x >> 0))
- table[prevHash&tableMask] = uint16(s - 1)
- currHash := hash(uint32(x >> 8))
- candidate = int(table[currHash&tableMask])
- table[currHash&tableMask] = uint16(s)
- // TODO: >= should be >, and add a test for that.
- if s-candidate >= maxMatchOffset || uint32(x>>8) != load32(src, candidate) {
- nextHash = hash(uint32(x >> 16))
+ prevHash := hash(uint32(x))
+ e.table[prevHash&tableMask] = tableEntry{offset: e.cur + s - 1, val: uint32(x)}
+ x >>= 8
+ currHash := hash(uint32(x))
+ candidate = e.table[currHash&tableMask]
+ e.table[currHash&tableMask] = tableEntry{offset: e.cur + s, val: uint32(x)}
+
+ offset := s - (candidate.offset - e.cur)
+ if offset > maxMatchOffset || uint32(x) != candidate.val {
+ cv = uint32(x >> 8)
+ nextHash = hash(cv)
s++
break
}
@@ -160,15 +180,91 @@ func encodeBestSpeed(dst []token, src []byte) []token {
}
emitRemainder:
- if nextEmit < len(src) {
+ if int(nextEmit) < len(src) {
dst = emitLiteral(dst, src[nextEmit:])
}
+ e.cur += int32(len(src))
+ e.prev = e.prev[:len(src)]
+ copy(e.prev, src)
return dst
}
func emitLiteral(dst []token, lit []byte) []token {
for _, v := range lit {
- dst = append(dst, token(v))
+ dst = append(dst, literalToken(uint32(v)))
}
return dst
}
+
+// matchLen returns the match length between src[s:] and src[t:].
+// t can be negative to indicate the match is starting in e.prev.
+// We assume that src[s-4:s] and src[t-4:t] already match.
+func (e *deflateFast) matchLen(s, t int32, src []byte) int32 {
+ s1 := int(s) + maxMatchLength - 4
+ if s1 > len(src) {
+ s1 = len(src)
+ }
+
+ // If we are inside the current block
+ if t >= 0 {
+ b := src[t:]
+ a := src[s:s1]
+ b = b[:len(a)]
+ // Extend the match to be as long as possible.
+ for i := range a {
+ if a[i] != b[i] {
+ return int32(i)
+ }
+ }
+ return int32(len(a))
+ }
+
+ // We found a match in the previous block.
+ tp := int32(len(e.prev)) + t
+ if tp < 0 {
+ return 0
+ }
+
+ // Extend the match to be as long as possible.
+ a := src[s:s1]
+ b := e.prev[tp:]
+ if len(b) > len(a) {
+ b = b[:len(a)]
+ }
+ a = a[:len(b)]
+ for i := range b {
+ if a[i] != b[i] {
+ return int32(i)
+ }
+ }
+
+ // If we reached our limit, we matched everything we are
+ // allowed to in the previous block and we return.
+ n := int32(len(b))
+ if int(s+n) == s1 {
+ return n
+ }
+
+ // Continue looking for more matches in the current block.
+ a = src[s+n : s1]
+ b = src[:len(a)]
+ for i := range a {
+ if a[i] != b[i] {
+ return int32(i) + n
+ }
+ }
+ return int32(len(a)) + n
+}
+
+// Reset resets the encoding history.
+// This ensures that no matches are made to the previous block.
+func (e *deflateFast) reset() {
+ e.prev = e.prev[:0]
+ // Bump the offset, so all matches will fail distance check.
+ e.cur += maxMatchOffset
+
+ // Protect against e.cur wraparound.
+ if e.cur > 1<<30 {
+ *e = deflateFast{cur: maxStoreBlockSize, prev: e.prev[:0]}
+ }
+}
diff --git a/libgo/go/compress/flate/example_test.go b/libgo/go/compress/flate/example_test.go
new file mode 100644
index 00000000000..3d44dde7ae1
--- /dev/null
+++ b/libgo/go/compress/flate/example_test.go
@@ -0,0 +1,245 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package flate_test
+
+import (
+ "bytes"
+ "compress/flate"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "strings"
+ "sync"
+)
+
+// In performance critical applications, Reset can be used to discard the
+// current compressor or decompressor state and reinitialize them quickly
+// by taking advantage of previously allocated memory.
+func Example_reset() {
+ proverbs := []string{
+ "Don't communicate by sharing memory, share memory by communicating.\n",
+ "Concurrency is not parallelism.\n",
+ "The bigger the interface, the weaker the abstraction.\n",
+ "Documentation is for users.\n",
+ }
+
+ var r strings.Reader
+ var b bytes.Buffer
+ buf := make([]byte, 32<<10)
+
+ zw, err := flate.NewWriter(nil, flate.DefaultCompression)
+ if err != nil {
+ log.Fatal(err)
+ }
+ zr := flate.NewReader(nil)
+
+ for _, s := range proverbs {
+ r.Reset(s)
+ b.Reset()
+
+ // Reset the compressor and encode from some input stream.
+ zw.Reset(&b)
+ if _, err := io.CopyBuffer(zw, &r, buf); err != nil {
+ log.Fatal(err)
+ }
+ if err := zw.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Reset the decompressor and decode to some output stream.
+ if err := zr.(flate.Resetter).Reset(&b, nil); err != nil {
+ log.Fatal(err)
+ }
+ if _, err := io.CopyBuffer(os.Stdout, zr, buf); err != nil {
+ log.Fatal(err)
+ }
+ if err := zr.Close(); err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ // Output:
+ // Don't communicate by sharing memory, share memory by communicating.
+ // Concurrency is not parallelism.
+ // The bigger the interface, the weaker the abstraction.
+ // Documentation is for users.
+}
+
+// A preset dictionary can be used to improve the compression ratio.
+// The downside to using a dictionary is that the compressor and decompressor
+// must agree in advance what dictionary to use.
+func Example_dictionary() {
+ // The dictionary is a string of bytes. When compressing some input data,
+ // the compressor will attempt to substitute substrings with matches found
+ // in the dictionary. As such, the dictionary should only contain substrings
+ // that are expected to be found in the actual data stream.
+ const dict = `<?xml version="1.0"?>` + `<book>` + `<data>` + `<meta name="` + `" content="`
+
+ // The data to compress should (but is not required to) contain frequent
+ // substrings that match those in the dictionary.
+ const data = `<?xml version="1.0"?>
+<book>
+ <meta name="title" content="The Go Programming Language"/>
+ <meta name="authors" content="Alan Donovan and Brian Kernighan"/>
+ <meta name="published" content="2015-10-26"/>
+ <meta name="isbn" content="978-0134190440"/>
+ <data>...</data>
+</book>
+`
+
+ var b bytes.Buffer
+
+ // Compress the data using the specially crafted dictionary.
+ zw, err := flate.NewWriterDict(&b, flate.DefaultCompression, []byte(dict))
+ if err != nil {
+ log.Fatal(err)
+ }
+ if _, err := io.Copy(zw, strings.NewReader(data)); err != nil {
+ log.Fatal(err)
+ }
+ if err := zw.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // The decompressor must use the same dictionary as the compressor.
+ // Otherwise, the input may appear as corrupted.
+ fmt.Println("Decompressed output using the dictionary:")
+ zr := flate.NewReaderDict(bytes.NewReader(b.Bytes()), []byte(dict))
+ if _, err := io.Copy(os.Stdout, zr); err != nil {
+ log.Fatal(err)
+ }
+ if err := zr.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println()
+
+ // Substitute all of the bytes in the dictionary with a '#' to visually
+ // demonstrate the approximate effectiveness of using a preset dictionary.
+ fmt.Println("Substrings matched by the dictionary are marked with #:")
+ hashDict := []byte(dict)
+ for i := range hashDict {
+ hashDict[i] = '#'
+ }
+ zr = flate.NewReaderDict(&b, hashDict)
+ if _, err := io.Copy(os.Stdout, zr); err != nil {
+ log.Fatal(err)
+ }
+ if err := zr.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // Decompressed output using the dictionary:
+ // <?xml version="1.0"?>
+ // <book>
+ // <meta name="title" content="The Go Programming Language"/>
+ // <meta name="authors" content="Alan Donovan and Brian Kernighan"/>
+ // <meta name="published" content="2015-10-26"/>
+ // <meta name="isbn" content="978-0134190440"/>
+ // <data>...</data>
+ // </book>
+ //
+ // Substrings matched by the dictionary are marked with #:
+ // #####################
+ // ######
+ // ############title###########The Go Programming Language"/#
+ // ############authors###########Alan Donovan and Brian Kernighan"/#
+ // ############published###########2015-10-26"/#
+ // ############isbn###########978-0134190440"/#
+ // ######...</#####
+ // </#####
+}
+
+// DEFLATE is suitable for transmitting compressed data across the network.
+func Example_synchronization() {
+ var wg sync.WaitGroup
+ defer wg.Wait()
+
+ // Use io.Pipe to simulate a network connection.
+ // A real network application should take care to properly close the
+ // underlying connection.
+ rp, wp := io.Pipe()
+
+ // Start a goroutine to act as the transmitter.
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+
+ zw, err := flate.NewWriter(wp, flate.BestSpeed)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ b := make([]byte, 256)
+ for _, m := range strings.Fields("A long time ago in a galaxy far, far away...") {
+ // We use a simple framing format where the first byte is the
+ // message length, followed the message itself.
+ b[0] = uint8(copy(b[1:], m))
+
+ if _, err := zw.Write(b[:1+len(m)]); err != nil {
+ log.Fatal(err)
+ }
+
+ // Flush ensures that the receiver can read all data sent so far.
+ if err := zw.Flush(); err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ if err := zw.Close(); err != nil {
+ log.Fatal(err)
+ }
+ }()
+
+ // Start a goroutine to act as the receiver.
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+
+ zr := flate.NewReader(rp)
+
+ b := make([]byte, 256)
+ for {
+ // Read the message length.
+ // This is guaranteed to return for every corresponding
+ // Flush and Close on the transmitter side.
+ if _, err := io.ReadFull(zr, b[:1]); err != nil {
+ if err == io.EOF {
+ break // The transmitter closed the stream
+ }
+ log.Fatal(err)
+ }
+
+ // Read the message content.
+ n := int(b[0])
+ if _, err := io.ReadFull(zr, b[:n]); err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Printf("Received %d bytes: %s\n", n, b[:n])
+ }
+ fmt.Println()
+
+ if err := zr.Close(); err != nil {
+ log.Fatal(err)
+ }
+ }()
+
+ // Output:
+ // Received 1 bytes: A
+ // Received 4 bytes: long
+ // Received 4 bytes: time
+ // Received 3 bytes: ago
+ // Received 2 bytes: in
+ // Received 1 bytes: a
+ // Received 6 bytes: galaxy
+ // Received 4 bytes: far,
+ // Received 3 bytes: far
+ // Received 7 bytes: away...
+}
diff --git a/libgo/go/compress/flate/flate_test.go b/libgo/go/compress/flate/flate_test.go
index 83c20498cc4..1e45077bd5b 100644
--- a/libgo/go/compress/flate/flate_test.go
+++ b/libgo/go/compress/flate/flate_test.go
@@ -281,6 +281,7 @@ func TestTruncatedStreams(t *testing.T) {
//
// See https://github.com/google/go-github/pull/317 for background.
func TestReaderEarlyEOF(t *testing.T) {
+ t.Parallel()
testSizes := []int{
1, 2, 3, 4, 5, 6, 7, 8,
100, 1000, 10000, 100000,
diff --git a/libgo/go/compress/flate/huffman_bit_writer.go b/libgo/go/compress/flate/huffman_bit_writer.go
index d8b5a3ebd7b..6cd6281249b 100644
--- a/libgo/go/compress/flate/huffman_bit_writer.go
+++ b/libgo/go/compress/flate/huffman_bit_writer.go
@@ -520,7 +520,7 @@ func (w *huffmanBitWriter) writeBlockDynamic(tokens []token, eof bool, input []b
// the literalEncoding and the offsetEncoding.
w.generateCodegen(numLiterals, numOffsets, w.literalEncoding, w.offsetEncoding)
w.codegenEncoding.generate(w.codegenFreq[:], 7)
- size, numCodegens := w.dynamicSize(w.literalEncoding, huffOffset, 0)
+ size, numCodegens := w.dynamicSize(w.literalEncoding, w.offsetEncoding, 0)
// Store bytes, if we don't get a reasonable improvement.
if ssize, storable := w.storedSize(input); storable && ssize < (size+size>>4) {
diff --git a/libgo/go/compress/flate/inflate.go b/libgo/go/compress/flate/inflate.go
index 68cc232052b..9a8c4fc455a 100644
--- a/libgo/go/compress/flate/inflate.go
+++ b/libgo/go/compress/flate/inflate.go
@@ -344,6 +344,9 @@ func (f *decompressor) Read(b []byte) (int, error) {
return 0, f.err
}
f.step(f)
+ if f.err != nil && len(f.toRead) == 0 {
+ f.toRead = f.dict.readFlush() // Flush what's left in case of error
+ }
}
}
diff --git a/libgo/go/compress/flate/inflate_test.go b/libgo/go/compress/flate/inflate_test.go
index e0bce71d6f2..951decd7754 100644
--- a/libgo/go/compress/flate/inflate_test.go
+++ b/libgo/go/compress/flate/inflate_test.go
@@ -7,6 +7,8 @@ package flate
import (
"bytes"
"io"
+ "io/ioutil"
+ "strings"
"testing"
)
@@ -38,6 +40,33 @@ func TestReset(t *testing.T) {
}
}
+func TestReaderTruncated(t *testing.T) {
+ vectors := []struct{ input, output string }{
+ {"\x00", ""},
+ {"\x00\f", ""},
+ {"\x00\f\x00", ""},
+ {"\x00\f\x00\xf3\xff", ""},
+ {"\x00\f\x00\xf3\xffhello", "hello"},
+ {"\x00\f\x00\xf3\xffhello, world", "hello, world"},
+ {"\x02", ""},
+ {"\xf2H\xcd", "He"},
+ {"\xf2H͙0a\u0084\t", "Hel\x90\x90\x90\x90\x90"},
+ {"\xf2H͙0a\u0084\t\x00", "Hel\x90\x90\x90\x90\x90"},
+ }
+
+ for i, v := range vectors {
+ r := strings.NewReader(v.input)
+ zr := NewReader(r)
+ b, err := ioutil.ReadAll(zr)
+ if err != io.ErrUnexpectedEOF {
+ t.Errorf("test %d, error mismatch: got %v, want io.ErrUnexpectedEOF", i, err)
+ }
+ if string(b) != v.output {
+ t.Errorf("test %d, output mismatch: got %q, want %q", i, b, v.output)
+ }
+ }
+}
+
func TestResetDict(t *testing.T) {
dict := []byte("the lorem fox")
ss := []string{
diff --git a/libgo/go/compress/flate/writer_test.go b/libgo/go/compress/flate/writer_test.go
index 21cd0b22eef..c4d36aa37e9 100644
--- a/libgo/go/compress/flate/writer_test.go
+++ b/libgo/go/compress/flate/writer_test.go
@@ -56,6 +56,7 @@ func (e *errorWriter) Write(b []byte) (int, error) {
// Test if errors from the underlying writer is passed upwards.
func TestWriteError(t *testing.T) {
+ t.Parallel()
buf := new(bytes.Buffer)
n := 65536
if !testing.Short() {
@@ -75,7 +76,7 @@ func TestWriteError(t *testing.T) {
if err != nil {
t.Fatalf("NewWriter: level %d: %v", l, err)
}
- n, err := io.CopyBuffer(w, bytes.NewBuffer(in), copyBuffer)
+ n, err := io.CopyBuffer(w, struct{ io.Reader }{bytes.NewBuffer(in)}, copyBuffer)
if err == nil {
t.Fatalf("Level %d: Expected an error, writer was %#v", l, ew)
}
@@ -113,6 +114,7 @@ func TestWriteError(t *testing.T) {
// Test if two runs produce identical results
// even when writing different sizes to the Writer.
func TestDeterministic(t *testing.T) {
+ t.Parallel()
for i := 0; i <= 9; i++ {
t.Run(fmt.Sprint("L", i), func(t *testing.T) { testDeterministic(i, t) })
}
@@ -120,6 +122,7 @@ func TestDeterministic(t *testing.T) {
}
func testDeterministic(i int, t *testing.T) {
+ t.Parallel()
// Test so much we cross a good number of block boundaries.
var length = maxStoreBlockSize*30 + 500
if testing.Short() {
@@ -142,7 +145,7 @@ func testDeterministic(i int, t *testing.T) {
}
// Use a very small prime sized buffer.
cbuf := make([]byte, 787)
- _, err = io.CopyBuffer(w, br, cbuf)
+ _, err = io.CopyBuffer(w, struct{ io.Reader }{br}, cbuf)
if err != nil {
t.Fatal(err)
}
@@ -157,7 +160,7 @@ func testDeterministic(i int, t *testing.T) {
if err != nil {
t.Fatal(err)
}
- _, err = io.CopyBuffer(w2, br2, cbuf)
+ _, err = io.CopyBuffer(w2, struct{ io.Reader }{br2}, cbuf)
if err != nil {
t.Fatal(err)
}
diff --git a/libgo/go/compress/gzip/example_test.go b/libgo/go/compress/gzip/example_test.go
new file mode 100644
index 00000000000..4764bcb090a
--- /dev/null
+++ b/libgo/go/compress/gzip/example_test.go
@@ -0,0 +1,130 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package gzip_test
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "time"
+)
+
+func Example_writerReader() {
+ var buf bytes.Buffer
+ zw := gzip.NewWriter(&buf)
+
+ // Setting the Header fields is optional.
+ zw.Name = "a-new-hope.txt"
+ zw.Comment = "an epic space opera by George Lucas"
+ zw.ModTime = time.Date(1977, time.May, 25, 0, 0, 0, 0, time.UTC)
+
+ _, err := zw.Write([]byte("A long time ago in a galaxy far, far away..."))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if err := zw.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ zr, err := gzip.NewReader(&buf)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Printf("Name: %s\nComment: %s\nModTime: %s\n\n", zr.Name, zr.Comment, zr.ModTime.UTC())
+
+ if _, err := io.Copy(os.Stdout, zr); err != nil {
+ log.Fatal(err)
+ }
+
+ if err := zr.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // Name: a-new-hope.txt
+ // Comment: an epic space opera by George Lucas
+ // ModTime: 1977-05-25 00:00:00 +0000 UTC
+ //
+ // A long time ago in a galaxy far, far away...
+}
+
+func ExampleReader_Multistream() {
+ var buf bytes.Buffer
+ zw := gzip.NewWriter(&buf)
+
+ var files = []struct {
+ name string
+ comment string
+ modTime time.Time
+ data string
+ }{
+ {"file-1.txt", "file-header-1", time.Date(2006, time.February, 1, 3, 4, 5, 0, time.UTC), "Hello Gophers - 1"},
+ {"file-2.txt", "file-header-2", time.Date(2007, time.March, 2, 4, 5, 6, 1, time.UTC), "Hello Gophers - 2"},
+ }
+
+ for _, file := range files {
+ zw.Name = file.name
+ zw.Comment = file.comment
+ zw.ModTime = file.modTime
+
+ if _, err := zw.Write([]byte(file.data)); err != nil {
+ log.Fatal(err)
+ }
+
+ if err := zw.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ zw.Reset(&buf)
+ }
+
+ zr, err := gzip.NewReader(&buf)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ for {
+ zr.Multistream(false)
+ fmt.Printf("Name: %s\nComment: %s\nModTime: %s\n\n", zr.Name, zr.Comment, zr.ModTime.UTC())
+
+ if _, err := io.Copy(os.Stdout, zr); err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Print("\n\n")
+
+ err = zr.Reset(&buf)
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ log.Fatal(err)
+ }
+ }
+
+ if err := zr.Close(); err != nil {
+ log.Fatal(err)
+ }
+
+ // Output:
+ // Name: file-1.txt
+ // Comment: file-header-1
+ // ModTime: 2006-02-01 03:04:05 +0000 UTC
+ //
+ // Hello Gophers - 1
+ //
+ // Name: file-2.txt
+ // Comment: file-header-2
+ // ModTime: 2007-03-02 04:05:06 +0000 UTC
+ //
+ // Hello Gophers - 2
+}
diff --git a/libgo/go/compress/gzip/gunzip.go b/libgo/go/compress/gzip/gunzip.go
index 7e640692f3f..8bd750bd8b3 100644
--- a/libgo/go/compress/gzip/gunzip.go
+++ b/libgo/go/compress/gzip/gunzip.go
@@ -186,7 +186,11 @@ func (z *Reader) readHeader() (hdr Header, err error) {
return hdr, ErrHeader
}
flg := z.buf[3]
- hdr.ModTime = time.Unix(int64(le.Uint32(z.buf[4:8])), 0)
+ if t := int64(le.Uint32(z.buf[4:8])); t > 0 {
+ // Section 2.3.1, the zero value for MTIME means that the
+ // modified time is not set.
+ hdr.ModTime = time.Unix(t, 0)
+ }
// z.buf[8] is XFL and is currently ignored.
hdr.OS = z.buf[9]
z.digest = crc32.ChecksumIEEE(z.buf[:10])
@@ -238,6 +242,7 @@ func (z *Reader) readHeader() (hdr Header, err error) {
return hdr, nil
}
+// Read implements io.Reader, reading uncompressed bytes from its underlying Reader.
func (z *Reader) Read(p []byte) (n int, err error) {
if z.err != nil {
return 0, z.err
diff --git a/libgo/go/compress/gzip/gunzip_test.go b/libgo/go/compress/gzip/gunzip_test.go
index fdce91989a6..fdea0c5d5ff 100644
--- a/libgo/go/compress/gzip/gunzip_test.go
+++ b/libgo/go/compress/gzip/gunzip_test.go
@@ -339,6 +339,26 @@ var gunzipTests = []gunzipTest{
},
nil,
},
+ {
+ "",
+ "truncated gzip file amid raw-block",
+ "hello",
+ []byte{
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x0c, 0x00, 0xf3, 0xff, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
+ },
+ io.ErrUnexpectedEOF,
+ },
+ {
+ "",
+ "truncated gzip file amid fixed-block",
+ "He",
+ []byte{
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0xf2, 0x48, 0xcd,
+ },
+ io.ErrUnexpectedEOF,
+ },
}
func TestDecompressor(t *testing.T) {
diff --git a/libgo/go/compress/gzip/gzip.go b/libgo/go/compress/gzip/gzip.go
index c702c493c11..aafb442a667 100644
--- a/libgo/go/compress/gzip/gzip.go
+++ b/libgo/go/compress/gzip/gzip.go
@@ -10,6 +10,7 @@ import (
"fmt"
"hash/crc32"
"io"
+ "time"
)
// These constants are copied from the flate package, so that code that imports
@@ -19,6 +20,7 @@ const (
BestSpeed = flate.BestSpeed
BestCompression = flate.BestCompression
DefaultCompression = flate.DefaultCompression
+ HuffmanOnly = flate.HuffmanOnly
)
// A Writer is an io.WriteCloser.
@@ -52,11 +54,11 @@ func NewWriter(w io.Writer) *Writer {
// NewWriterLevel is like NewWriter but specifies the compression level instead
// of assuming DefaultCompression.
//
-// The compression level can be DefaultCompression, NoCompression, or any
-// integer value between BestSpeed and BestCompression inclusive. The error
-// returned will be nil if the level is valid.
+// The compression level can be DefaultCompression, NoCompression, HuffmanOnly
+// or any integer value between BestSpeed and BestCompression inclusive.
+// The error returned will be nil if the level is valid.
func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
- if level < DefaultCompression || level > BestCompression {
+ if level < HuffmanOnly || level > BestCompression {
return nil, fmt.Errorf("gzip: invalid compression level: %d", level)
}
z := new(Writer)
@@ -142,10 +144,7 @@ func (z *Writer) Write(p []byte) (int, error) {
// Write the GZIP header lazily.
if !z.wroteHeader {
z.wroteHeader = true
- z.buf[0] = gzipID1
- z.buf[1] = gzipID2
- z.buf[2] = gzipDeflate
- z.buf[3] = 0
+ z.buf = [10]byte{0: gzipID1, 1: gzipID2, 2: gzipDeflate}
if z.Extra != nil {
z.buf[3] |= 0x04
}
@@ -155,13 +154,15 @@ func (z *Writer) Write(p []byte) (int, error) {
if z.Comment != "" {
z.buf[3] |= 0x10
}
- le.PutUint32(z.buf[4:8], uint32(z.ModTime.Unix()))
+ if z.ModTime.After(time.Unix(0, 0)) {
+ // Section 2.3.1, the zero value for MTIME means that the
+ // modified time is not set.
+ le.PutUint32(z.buf[4:8], uint32(z.ModTime.Unix()))
+ }
if z.level == BestCompression {
z.buf[8] = 2
} else if z.level == BestSpeed {
z.buf[8] = 4
- } else {
- z.buf[8] = 0
}
z.buf[9] = z.OS
n, z.err = z.w.Write(z.buf[:10])
diff --git a/libgo/go/compress/gzip/gzip_test.go b/libgo/go/compress/gzip/gzip_test.go
index 09271b24e92..865c529f55c 100644
--- a/libgo/go/compress/gzip/gzip_test.go
+++ b/libgo/go/compress/gzip/gzip_test.go
@@ -8,6 +8,7 @@ import (
"bufio"
"bytes"
"io/ioutil"
+ "reflect"
"testing"
"time"
)
@@ -24,6 +25,9 @@ func TestEmpty(t *testing.T) {
if err != nil {
t.Fatalf("NewReader: %v", err)
}
+ if want := (Header{OS: 255}); !reflect.DeepEqual(r.Header, want) {
+ t.Errorf("Header mismatch:\ngot %#v\nwant %#v", r.Header, want)
+ }
b, err := ioutil.ReadAll(r)
if err != nil {
t.Fatalf("ReadAll: %v", err)
diff --git a/libgo/go/compress/gzip/issue14937_test.go b/libgo/go/compress/gzip/issue14937_test.go
index 432ad16b1c2..e76d47cc4ee 100644
--- a/libgo/go/compress/gzip/issue14937_test.go
+++ b/libgo/go/compress/gzip/issue14937_test.go
@@ -7,7 +7,6 @@ import (
"runtime"
"strings"
"testing"
- "time"
)
// Per golang.org/issue/14937, check that every .gz file
@@ -16,8 +15,12 @@ func TestGZIPFilesHaveZeroMTimes(t *testing.T) {
if testing.Short() && testenv.Builder() == "" {
t.Skip("skipping in short mode")
}
+ goroot, err := filepath.EvalSymlinks(runtime.GOROOT())
+ if err != nil {
+ t.Fatal("error evaluating GOROOT: ", err)
+ }
var files []string
- err := filepath.Walk(runtime.GOROOT(), func(path string, info os.FileInfo, err error) error {
+ err = filepath.Walk(goroot, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
@@ -53,7 +56,7 @@ func checkZeroMTime(t *testing.T, path string) {
return
}
defer gz.Close()
- if !gz.ModTime.Equal(time.Unix(0, 0)) {
+ if !gz.ModTime.IsZero() {
t.Errorf("gzip file %s has non-zero mtime (%s)", path, gz.ModTime)
}
}
diff --git a/libgo/go/compress/zlib/reader_test.go b/libgo/go/compress/zlib/reader_test.go
index f74bff1f3cc..7e27aecb47d 100644
--- a/libgo/go/compress/zlib/reader_test.go
+++ b/libgo/go/compress/zlib/reader_test.go
@@ -121,6 +121,24 @@ var zlibTests = []zlibTest{
},
ErrDictionary,
},
+ {
+ "truncated zlib stream amid raw-block",
+ "hello",
+ []byte{
+ 0x78, 0x9c, 0x00, 0x0c, 0x00, 0xf3, 0xff, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
+ },
+ nil,
+ io.ErrUnexpectedEOF,
+ },
+ {
+ "truncated zlib stream amid fixed-block",
+ "He",
+ []byte{
+ 0x78, 0x9c, 0xf2, 0x48, 0xcd,
+ },
+ nil,
+ io.ErrUnexpectedEOF,
+ },
}
func TestDecompressor(t *testing.T) {
diff --git a/libgo/go/compress/zlib/writer.go b/libgo/go/compress/zlib/writer.go
index 3b4313a8bea..1620c00c523 100644
--- a/libgo/go/compress/zlib/writer.go
+++ b/libgo/go/compress/zlib/writer.go
@@ -19,6 +19,7 @@ const (
BestSpeed = flate.BestSpeed
BestCompression = flate.BestCompression
DefaultCompression = flate.DefaultCompression
+ HuffmanOnly = flate.HuffmanOnly
)
// A Writer takes data written to it and writes the compressed
@@ -47,9 +48,9 @@ func NewWriter(w io.Writer) *Writer {
// NewWriterLevel is like NewWriter but specifies the compression level instead
// of assuming DefaultCompression.
//
-// The compression level can be DefaultCompression, NoCompression, or any
-// integer value between BestSpeed and BestCompression inclusive. The error
-// returned will be nil if the level is valid.
+// The compression level can be DefaultCompression, NoCompression, HuffmanOnly
+// or any integer value between BestSpeed and BestCompression inclusive.
+// The error returned will be nil if the level is valid.
func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
return NewWriterLevelDict(w, level, nil)
}
@@ -60,7 +61,7 @@ func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
// The dictionary may be nil. If not, its contents should not be modified until
// the Writer is closed.
func NewWriterLevelDict(w io.Writer, level int, dict []byte) (*Writer, error) {
- if level < DefaultCompression || level > BestCompression {
+ if level < HuffmanOnly || level > BestCompression {
return nil, fmt.Errorf("zlib: invalid compression level: %d", level)
}
return &Writer{
@@ -99,7 +100,7 @@ func (z *Writer) writeHeader() (err error) {
// The next bit, FDICT, is set if a dictionary is given.
// The final five FCHECK bits form a mod-31 checksum.
switch z.level {
- case 0, 1:
+ case -2, 0, 1:
z.scratch[1] = 0 << 6
case 2, 3, 4, 5:
z.scratch[1] = 1 << 6
diff --git a/libgo/go/compress/zlib/writer_test.go b/libgo/go/compress/zlib/writer_test.go
index dd941655206..d5019740783 100644
--- a/libgo/go/compress/zlib/writer_test.go
+++ b/libgo/go/compress/zlib/writer_test.go
@@ -147,6 +147,7 @@ func TestWriter(t *testing.T) {
tag := fmt.Sprintf("#%d", i)
testLevelDict(t, tag, b, DefaultCompression, "")
testLevelDict(t, tag, b, NoCompression, "")
+ testLevelDict(t, tag, b, HuffmanOnly, "")
for level := BestSpeed; level <= BestCompression; level++ {
testLevelDict(t, tag, b, level, "")
}
@@ -157,6 +158,7 @@ func TestWriterBig(t *testing.T) {
for i, fn := range filenames {
testFileLevelDict(t, fn, DefaultCompression, "")
testFileLevelDict(t, fn, NoCompression, "")
+ testFileLevelDict(t, fn, HuffmanOnly, "")
for level := BestSpeed; level <= BestCompression; level++ {
testFileLevelDict(t, fn, level, "")
if level >= 1 && testing.Short() && testenv.Builder() == "" {
@@ -174,6 +176,7 @@ func TestWriterDict(t *testing.T) {
for i, fn := range filenames {
testFileLevelDict(t, fn, DefaultCompression, dictionary)
testFileLevelDict(t, fn, NoCompression, dictionary)
+ testFileLevelDict(t, fn, HuffmanOnly, dictionary)
for level := BestSpeed; level <= BestCompression; level++ {
testFileLevelDict(t, fn, level, dictionary)
if level >= 1 && testing.Short() && testenv.Builder() == "" {
@@ -191,8 +194,10 @@ func TestWriterReset(t *testing.T) {
for _, fn := range filenames {
testFileLevelDictReset(t, fn, NoCompression, nil)
testFileLevelDictReset(t, fn, DefaultCompression, nil)
+ testFileLevelDictReset(t, fn, HuffmanOnly, nil)
testFileLevelDictReset(t, fn, NoCompression, []byte(dictionary))
testFileLevelDictReset(t, fn, DefaultCompression, []byte(dictionary))
+ testFileLevelDictReset(t, fn, HuffmanOnly, []byte(dictionary))
if testing.Short() {
break
}
diff --git a/libgo/go/container/heap/heap.go b/libgo/go/container/heap/heap.go
index 5fe23b95372..7110c513f08 100644
--- a/libgo/go/container/heap/heap.go
+++ b/libgo/go/container/heap/heap.go
@@ -83,8 +83,9 @@ func Remove(h Interface, i int) interface{} {
// 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().
func Fix(h Interface, i int) {
- down(h, i, h.Len())
- up(h, i)
+ if !down(h, i, h.Len()) {
+ up(h, i)
+ }
}
func up(h Interface, j int) {
@@ -98,7 +99,8 @@ func up(h Interface, j int) {
}
}
-func down(h Interface, i, n int) {
+func down(h Interface, i0, n int) bool {
+ i := i0
for {
j1 := 2*i + 1
if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
@@ -114,4 +116,5 @@ func down(h Interface, i, n int) {
h.Swap(i, j)
i = j
}
+ return i > i0
}
diff --git a/libgo/go/container/list/list_test.go b/libgo/go/container/list/list_test.go
index e3bfe53a498..99e006f39fd 100755
--- a/libgo/go/container/list/list_test.go
+++ b/libgo/go/container/list/list_test.go
@@ -271,7 +271,7 @@ func TestMove(t *testing.T) {
l.MoveBefore(e2, e4)
checkListPointers(t, l, []*Element{e1, e3, e2, e4})
- e1, e2, e3, e4 = e1, e3, e2, e4
+ e2, e3 = e3, e2
l.MoveBefore(e4, e1)
checkListPointers(t, l, []*Element{e4, e1, e2, e3})
@@ -279,11 +279,11 @@ func TestMove(t *testing.T) {
l.MoveAfter(e4, e1)
checkListPointers(t, l, []*Element{e1, e4, e2, e3})
- e1, e2, e3, e4 = e1, e4, e2, e3
+ e2, e3, e4 = e4, e2, e3
l.MoveAfter(e2, e3)
checkListPointers(t, l, []*Element{e1, e3, e2, e4})
- e1, e2, e3, e4 = e1, e3, e2, e4
+ e2, e3 = e3, e2
}
// Test PushFront, PushBack, PushFrontList, PushBackList with uninitialized List
diff --git a/libgo/go/context/benchmark_test.go b/libgo/go/context/benchmark_test.go
new file mode 100644
index 00000000000..b79232704eb
--- /dev/null
+++ b/libgo/go/context/benchmark_test.go
@@ -0,0 +1,44 @@
+// 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 context_test
+
+import (
+ . "context"
+ "fmt"
+ "testing"
+)
+
+func BenchmarkContextCancelTree(b *testing.B) {
+ depths := []int{1, 10, 100, 1000}
+ for _, d := range depths {
+ b.Run(fmt.Sprintf("depth=%d", d), func(b *testing.B) {
+ b.Run("Root=Background", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ buildContextTree(Background(), d)
+ }
+ })
+ b.Run("Root=OpenCanceler", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ctx, cancel := WithCancel(Background())
+ buildContextTree(ctx, d)
+ cancel()
+ }
+ })
+ b.Run("Root=ClosedCanceler", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ctx, cancel := WithCancel(Background())
+ cancel()
+ buildContextTree(ctx, d)
+ }
+ })
+ })
+ }
+}
+
+func buildContextTree(root Context, depth int) {
+ for d := 0; d < depth; d++ {
+ root, _ = WithCancel(root)
+ }
+}
diff --git a/libgo/go/context/context.go b/libgo/go/context/context.go
index f8ce9ccdb85..0aa7c24df9a 100644
--- a/libgo/go/context/context.go
+++ b/libgo/go/context/context.go
@@ -159,9 +159,9 @@ var DeadlineExceeded error = deadlineExceededError{}
type deadlineExceededError struct{}
-func (deadlineExceededError) Error() string { return "context deadline exceeded" }
-
-func (deadlineExceededError) Timeout() bool { return true }
+func (deadlineExceededError) Error() string { return "context deadline exceeded" }
+func (deadlineExceededError) Timeout() bool { return true }
+func (deadlineExceededError) Temporary() bool { return true }
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
// struct{}, since vars of this type must have distinct addresses.
@@ -252,9 +252,9 @@ func propagateCancel(parent Context, child canceler) {
child.cancel(false, p.err)
} else {
if p.children == nil {
- p.children = make(map[canceler]bool)
+ p.children = make(map[canceler]struct{})
}
- p.children[child] = true
+ p.children[child] = struct{}{}
}
p.mu.Unlock()
} else {
@@ -314,8 +314,8 @@ type cancelCtx struct {
done chan struct{} // closed by the first cancel call.
mu sync.Mutex
- children map[canceler]bool // set to nil by the first cancel call
- err error // set to non-nil by the first cancel call
+ children map[canceler]struct{} // set to nil by the first cancel call
+ err error // set to non-nil by the first cancel call
}
func (c *cancelCtx) Done() <-chan struct{} {
@@ -376,7 +376,7 @@ func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
deadline: deadline,
}
propagateCancel(parent, c)
- d := deadline.Sub(time.Now())
+ d := time.Until(deadline)
if d <= 0 {
c.cancel(true, DeadlineExceeded) // deadline has already passed
return c, func() { c.cancel(true, Canceled) }
@@ -406,7 +406,7 @@ func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
}
func (c *timerCtx) String() string {
- return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, c.deadline.Sub(time.Now()))
+ return fmt.Sprintf("%v.WithDeadline(%s [%s])", c.cancelCtx.Context, c.deadline, time.Until(c.deadline))
}
func (c *timerCtx) cancel(removeFromParent bool, err error) {
@@ -443,7 +443,13 @@ func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
// Use context Values only for request-scoped data that transits processes and
// APIs, not for passing optional parameters to functions.
//
-// The provided key must be comparable.
+// The provided key must be comparable and should not be of type
+// string or any other built-in type to avoid collisions between
+// packages using context. Users of WithValue should define their own
+// types for keys. To avoid allocating when assigning to an
+// interface{}, context keys often have concrete type
+// struct{}. Alternatively, exported context key variables' static
+// type should be a pointer or interface.
func WithValue(parent Context, key, val interface{}) Context {
if key == nil {
panic("nil key")
diff --git a/libgo/go/context/context_test.go b/libgo/go/context/context_test.go
index cdfec079c37..b5e599fe82f 100644
--- a/libgo/go/context/context_test.go
+++ b/libgo/go/context/context_test.go
@@ -10,10 +10,26 @@ import (
"runtime"
"strings"
"sync"
- "testing"
"time"
)
+type testingT interface {
+ Error(args ...interface{})
+ Errorf(format string, args ...interface{})
+ Fail()
+ FailNow()
+ Failed() bool
+ Fatal(args ...interface{})
+ Fatalf(format string, args ...interface{})
+ Log(args ...interface{})
+ Logf(format string, args ...interface{})
+ Name() string
+ Skip(args ...interface{})
+ SkipNow()
+ Skipf(format string, args ...interface{})
+ Skipped() bool
+}
+
// otherContext is a Context that's not one of the types defined in context.go.
// This lets us test code paths that differ based on the underlying type of the
// Context.
@@ -21,7 +37,7 @@ type otherContext struct {
Context
}
-func TestBackground(t *testing.T) {
+func XTestBackground(t testingT) {
c := Background()
if c == nil {
t.Fatalf("Background returned nil")
@@ -36,7 +52,7 @@ func TestBackground(t *testing.T) {
}
}
-func TestTODO(t *testing.T) {
+func XTestTODO(t testingT) {
c := TODO()
if c == nil {
t.Fatalf("TODO returned nil")
@@ -51,7 +67,7 @@ func TestTODO(t *testing.T) {
}
}
-func TestWithCancel(t *testing.T) {
+func XTestWithCancel(t testingT) {
c1, cancel := WithCancel(Background())
if got, want := fmt.Sprint(c1), "context.Background.WithCancel"; got != want {
@@ -92,7 +108,12 @@ func TestWithCancel(t *testing.T) {
}
}
-func TestParentFinishesChild(t *testing.T) {
+func contains(m map[canceler]struct{}, key canceler) bool {
+ _, ret := m[key]
+ return ret
+}
+
+func XTestParentFinishesChild(t testingT) {
// Context tree:
// parent -> cancelChild
// parent -> valueChild -> timerChild
@@ -120,7 +141,7 @@ func TestParentFinishesChild(t *testing.T) {
cc := cancelChild.(*cancelCtx)
tc := timerChild.(*timerCtx)
pc.mu.Lock()
- if len(pc.children) != 2 || !pc.children[cc] || !pc.children[tc] {
+ if len(pc.children) != 2 || !contains(pc.children, cc) || !contains(pc.children, tc) {
t.Errorf("bad linkage: pc.children = %v, want %v and %v",
pc.children, cc, tc)
}
@@ -169,7 +190,7 @@ func TestParentFinishesChild(t *testing.T) {
}
}
-func TestChildFinishesFirst(t *testing.T) {
+func XTestChildFinishesFirst(t testingT) {
cancelable, stop := WithCancel(Background())
defer stop()
for _, parent := range []Context{Background(), cancelable} {
@@ -191,7 +212,7 @@ func TestChildFinishesFirst(t *testing.T) {
if pcok {
pc.mu.Lock()
- if len(pc.children) != 1 || !pc.children[cc] {
+ if len(pc.children) != 1 || !contains(pc.children, cc) {
t.Errorf("bad linkage: pc.children = %v, cc = %v", pc.children, cc)
}
pc.mu.Unlock()
@@ -229,7 +250,7 @@ func TestChildFinishesFirst(t *testing.T) {
}
}
-func testDeadline(c Context, name string, failAfter time.Duration, t *testing.T) {
+func testDeadline(c Context, name string, failAfter time.Duration, t testingT) {
select {
case <-time.After(failAfter):
t.Fatalf("%s: context should have timed out", name)
@@ -240,7 +261,7 @@ func testDeadline(c Context, name string, failAfter time.Duration, t *testing.T)
}
}
-func TestDeadline(t *testing.T) {
+func XTestDeadline(t testingT) {
c, _ := WithDeadline(Background(), time.Now().Add(50*time.Millisecond))
if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
t.Errorf("c.String() = %q want prefix %q", got, prefix)
@@ -263,7 +284,7 @@ func TestDeadline(t *testing.T) {
testDeadline(c, "WithDeadline+now", time.Second, t)
}
-func TestTimeout(t *testing.T) {
+func XTestTimeout(t testingT) {
c, _ := WithTimeout(Background(), 50*time.Millisecond)
if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
t.Errorf("c.String() = %q want prefix %q", got, prefix)
@@ -280,7 +301,7 @@ func TestTimeout(t *testing.T) {
testDeadline(c, "WithTimeout+otherContext+WithTimeout", 2*time.Second, t)
}
-func TestCanceledTimeout(t *testing.T) {
+func XTestCanceledTimeout(t testingT) {
c, _ := WithTimeout(Background(), time.Second)
o := otherContext{c}
c, cancel := WithTimeout(o, 2*time.Second)
@@ -303,7 +324,7 @@ var k1 = key1(1)
var k2 = key2(1) // same int as k1, different type
var k3 = key2(3) // same type as k2, different int
-func TestValues(t *testing.T) {
+func XTestValues(t testingT) {
check := func(c Context, nm, v1, v2, v3 string) {
if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 {
t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0)
@@ -351,7 +372,7 @@ func TestValues(t *testing.T) {
check(o4, "o4", "", "c2k2", "")
}
-func TestAllocs(t *testing.T) {
+func XTestAllocs(t testingT, testingShort func() bool, testingAllocsPerRun func(int, func()) float64) {
bg := Background()
for _, test := range []struct {
desc string
@@ -411,16 +432,16 @@ func TestAllocs(t *testing.T) {
limit = test.gccgoLimit
}
numRuns := 100
- if testing.Short() {
+ if testingShort() {
numRuns = 10
}
- if n := testing.AllocsPerRun(numRuns, test.f); n > limit {
+ if n := testingAllocsPerRun(numRuns, test.f); n > limit {
t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit))
}
}
}
-func TestSimultaneousCancels(t *testing.T) {
+func XTestSimultaneousCancels(t testingT) {
root, cancel := WithCancel(Background())
m := map[Context]CancelFunc{root: cancel}
q := []Context{root}
@@ -468,7 +489,7 @@ func TestSimultaneousCancels(t *testing.T) {
}
}
-func TestInterlockedCancels(t *testing.T) {
+func XTestInterlockedCancels(t testingT) {
parent, cancelParent := WithCancel(Background())
child, cancelChild := WithCancel(parent)
go func() {
@@ -485,15 +506,15 @@ func TestInterlockedCancels(t *testing.T) {
}
}
-func TestLayersCancel(t *testing.T) {
+func XTestLayersCancel(t testingT) {
testLayers(t, time.Now().UnixNano(), false)
}
-func TestLayersTimeout(t *testing.T) {
+func XTestLayersTimeout(t testingT) {
testLayers(t, time.Now().UnixNano(), true)
}
-func testLayers(t *testing.T, seed int64, testTimeout bool) {
+func testLayers(t testingT, seed int64, testTimeout bool) {
rand.Seed(seed)
errorf := func(format string, a ...interface{}) {
t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...)
@@ -562,7 +583,7 @@ func testLayers(t *testing.T, seed int64, testTimeout bool) {
}
}
-func TestCancelRemoves(t *testing.T) {
+func XTestCancelRemoves(t testingT) {
checkChildren := func(when string, ctx Context, want int) {
if got := len(ctx.(*cancelCtx).children); got != want {
t.Errorf("%s: context has %d children, want %d", when, got, want)
@@ -574,17 +595,32 @@ func TestCancelRemoves(t *testing.T) {
_, cancel := WithCancel(ctx)
checkChildren("with WithCancel child ", ctx, 1)
cancel()
- checkChildren("after cancelling WithCancel child", ctx, 0)
+ checkChildren("after canceling WithCancel child", ctx, 0)
ctx, _ = WithCancel(Background())
checkChildren("after creation", ctx, 0)
_, cancel = WithTimeout(ctx, 60*time.Minute)
checkChildren("with WithTimeout child ", ctx, 1)
cancel()
- checkChildren("after cancelling WithTimeout child", ctx, 0)
+ checkChildren("after canceling WithTimeout child", ctx, 0)
+}
+
+func XTestWithCancelCanceledParent(t testingT) {
+ parent, pcancel := WithCancel(Background())
+ pcancel()
+
+ c, _ := WithCancel(parent)
+ select {
+ case <-c.Done():
+ case <-time.After(5 * time.Second):
+ t.Fatal("timeout waiting for Done")
+ }
+ if got, want := c.Err(), Canceled; got != want {
+ t.Errorf("child not cancelled; got = %v, want = %v", got, want)
+ }
}
-func TestWithValueChecksKey(t *testing.T) {
+func XTestWithValueChecksKey(t testingT) {
panicVal := recoveredValue(func() { WithValue(Background(), []byte("foo"), "bar") })
if panicVal == nil {
t.Error("expected panic")
@@ -601,7 +637,7 @@ func recoveredValue(fn func()) (v interface{}) {
return
}
-func TestDeadlineExceededSupportsTimeout(t *testing.T) {
+func XTestDeadlineExceededSupportsTimeout(t testingT) {
i, ok := DeadlineExceeded.(interface {
Timeout() bool
})
diff --git a/libgo/go/context/example_test.go b/libgo/go/context/example_test.go
new file mode 100644
index 00000000000..2d48d4e82bb
--- /dev/null
+++ b/libgo/go/context/example_test.go
@@ -0,0 +1,116 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package context_test
+
+import (
+ "context"
+ "fmt"
+ "time"
+)
+
+// This example demonstrates the use of a cancelable context to prevent a
+// goroutine leak. By the end of the example function, the goroutine started
+// by gen will return without leaking.
+func ExampleWithCancel() {
+ // gen generates integers in a separate goroutine and
+ // sends them to the returned channel.
+ // The callers of gen need to cancel the context once
+ // they are done consuming generated integers not to leak
+ // the internal goroutine started by gen.
+ gen := func(ctx context.Context) <-chan int {
+ dst := make(chan int)
+ n := 1
+ go func() {
+ for {
+ select {
+ case <-ctx.Done():
+ return // returning not to leak the goroutine
+ case dst <- n:
+ n++
+ }
+ }
+ }()
+ return dst
+ }
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel() // cancel when we are finished consuming integers
+
+ for n := range gen(ctx) {
+ fmt.Println(n)
+ if n == 5 {
+ break
+ }
+ }
+ // Output:
+ // 1
+ // 2
+ // 3
+ // 4
+ // 5
+}
+
+// This example passes a context with a arbitrary deadline to tell a blocking
+// function that it should abandon its work as soon as it gets to it.
+func ExampleWithDeadline() {
+ d := time.Now().Add(50 * time.Millisecond)
+ ctx, cancel := context.WithDeadline(context.Background(), d)
+
+ // Even though ctx will be expired, it is good practice to call its
+ // cancelation function in any case. Failure to do so may keep the
+ // context and its parent alive longer than necessary.
+ defer cancel()
+
+ select {
+ case <-time.After(1 * time.Second):
+ fmt.Println("overslept")
+ case <-ctx.Done():
+ fmt.Println(ctx.Err())
+ }
+
+ // Output:
+ // context deadline exceeded
+}
+
+// This example passes a context with a timeout to tell a blocking function that
+// it should abandon its work after the timeout elapses.
+func ExampleWithTimeout() {
+ // Pass a context with a timeout to tell a blocking function that it
+ // should abandon its work after the timeout elapses.
+ ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
+ defer cancel()
+
+ select {
+ case <-time.After(1 * time.Second):
+ fmt.Println("overslept")
+ case <-ctx.Done():
+ fmt.Println(ctx.Err()) // prints "context deadline exceeded"
+ }
+
+ // Output:
+ // context deadline exceeded
+}
+
+func ExampleWithValue() {
+ type favContextKey string
+
+ f := func(ctx context.Context, k favContextKey) {
+ if v := ctx.Value(k); v != nil {
+ fmt.Println("found value:", v)
+ return
+ }
+ fmt.Println("key not found:", k)
+ }
+
+ k := favContextKey("language")
+ ctx := context.WithValue(context.Background(), k, "Go")
+
+ f(ctx, k)
+ f(ctx, favContextKey("color"))
+
+ // Output:
+ // found value: Go
+ // key not found: color
+}
diff --git a/libgo/go/context/net_test.go b/libgo/go/context/net_test.go
new file mode 100644
index 00000000000..a007689d363
--- /dev/null
+++ b/libgo/go/context/net_test.go
@@ -0,0 +1,21 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package context_test
+
+import (
+ "context"
+ "net"
+ "testing"
+)
+
+func TestDeadlineExceededIsNetError(t *testing.T) {
+ err, ok := context.DeadlineExceeded.(net.Error)
+ if !ok {
+ t.Fatal("DeadlineExceeded does not implement net.Error")
+ }
+ if !err.Timeout() || !err.Temporary() {
+ t.Fatalf("Timeout() = %v, Temporary() = %v, want true, true", err.Timeout(), err.Temporary())
+ }
+}
diff --git a/libgo/go/context/withtimeout_test.go b/libgo/go/context/withtimeout_test.go
deleted file mode 100644
index c74600b47b4..00000000000
--- a/libgo/go/context/withtimeout_test.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-package context_test
-
-import (
- "context"
- "fmt"
- "time"
-)
-
-func ExampleWithTimeout() {
- // Pass a context with a timeout to tell a blocking function that it
- // should abandon its work after the timeout elapses.
- ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
-
- select {
- case <-time.After(1 * time.Second):
- fmt.Println("overslept")
- case <-ctx.Done():
- fmt.Println(ctx.Err()) // prints "context deadline exceeded"
- }
-
- // Even though ctx should have expired already, it is good
- // practice to call its cancelation function in any case.
- // Failure to do so may keep the context and its parent alive
- // longer than necessary.
- cancel()
-
- // Output:
- // context deadline exceeded
-}
diff --git a/libgo/go/context/x_test.go b/libgo/go/context/x_test.go
new file mode 100644
index 00000000000..d14b6f1a32b
--- /dev/null
+++ b/libgo/go/context/x_test.go
@@ -0,0 +1,29 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package context_test
+
+import (
+ . "context"
+ "testing"
+)
+
+func TestBackground(t *testing.T) { XTestBackground(t) }
+func TestTODO(t *testing.T) { XTestTODO(t) }
+func TestWithCancel(t *testing.T) { XTestWithCancel(t) }
+func TestParentFinishesChild(t *testing.T) { XTestParentFinishesChild(t) }
+func TestChildFinishesFirst(t *testing.T) { XTestChildFinishesFirst(t) }
+func TestDeadline(t *testing.T) { XTestDeadline(t) }
+func TestTimeout(t *testing.T) { XTestTimeout(t) }
+func TestCanceledTimeout(t *testing.T) { XTestCanceledTimeout(t) }
+func TestValues(t *testing.T) { XTestValues(t) }
+func TestAllocs(t *testing.T) { XTestAllocs(t, testing.Short, testing.AllocsPerRun) }
+func TestSimultaneousCancels(t *testing.T) { XTestSimultaneousCancels(t) }
+func TestInterlockedCancels(t *testing.T) { XTestInterlockedCancels(t) }
+func TestLayersCancel(t *testing.T) { XTestLayersCancel(t) }
+func TestLayersTimeout(t *testing.T) { XTestLayersTimeout(t) }
+func TestCancelRemoves(t *testing.T) { XTestCancelRemoves(t) }
+func TestWithCancelCanceledParent(t *testing.T) { XTestWithCancelCanceledParent(t) }
+func TestWithValueChecksKey(t *testing.T) { XTestWithValueChecksKey(t) }
+func TestDeadlineExceededSupportsTimeout(t *testing.T) { XTestDeadlineExceededSupportsTimeout(t) }
diff --git a/libgo/go/crypto/aes/aes_gcm.go b/libgo/go/crypto/aes/aes_gcm.go
index b59e8671006..3e5e2359d86 100644
--- a/libgo/go/crypto/aes/aes_gcm.go
+++ b/libgo/go/crypto/aes/aes_gcm.go
@@ -100,6 +100,9 @@ func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte {
if len(nonce) != g.nonceSize {
panic("cipher: incorrect nonce length given to GCM")
}
+ if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize {
+ panic("cipher: message too large for GCM")
+ }
var counter, tagMask [gcmBlockSize]byte
@@ -138,6 +141,10 @@ func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
if len(ciphertext) < gcmTagSize {
return nil, errOpen
}
+ if uint64(len(ciphertext)) > ((1<<32)-2)*BlockSize+gcmTagSize {
+ return nil, errOpen
+ }
+
tag := ciphertext[len(ciphertext)-gcmTagSize:]
ciphertext = ciphertext[:len(ciphertext)-gcmTagSize]
diff --git a/libgo/go/crypto/aes/cbc_s390x.go b/libgo/go/crypto/aes/cbc_s390x.go
index 8346b5eea01..6b011b28b5f 100644
--- a/libgo/go/crypto/aes/cbc_s390x.go
+++ b/libgo/go/crypto/aes/cbc_s390x.go
@@ -50,7 +50,9 @@ func (x *cbc) CryptBlocks(dst, src []byte) {
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
- cryptBlocksChain(x.c, &x.iv[0], &x.b.key[0], &dst[0], &src[0], len(src))
+ if len(src) > 0 {
+ cryptBlocksChain(x.c, &x.iv[0], &x.b.key[0], &dst[0], &src[0], len(src))
+ }
}
func (x *cbc) SetIV(iv []byte) {
diff --git a/libgo/go/crypto/aes/cipher_amd64.go b/libgo/go/crypto/aes/cipher_amd64.go
index 22769b9eef0..fbd157e49e7 100644
--- a/libgo/go/crypto/aes/cipher_amd64.go
+++ b/libgo/go/crypto/aes/cipher_amd64.go
@@ -8,10 +8,10 @@ package aes
import (
"crypto/cipher"
+ "crypto/internal/cipherhw"
)
// defined in asm_amd64.s
-func hasAsm() bool
func encryptBlockAsm(nr int, xk *uint32, dst, src *byte)
func decryptBlockAsm(nr int, xk *uint32, dst, src *byte)
func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32)
@@ -20,7 +20,7 @@ type aesCipherAsm struct {
aesCipher
}
-var useAsm = hasAsm()
+var useAsm = cipherhw.AESGCMSupport()
func newCipher(key []byte) (cipher.Block, error) {
if !useAsm {
diff --git a/libgo/go/crypto/aes/cipher_s390x.go b/libgo/go/crypto/aes/cipher_s390x.go
index c9d60e90595..253ce893892 100644
--- a/libgo/go/crypto/aes/cipher_s390x.go
+++ b/libgo/go/crypto/aes/cipher_s390x.go
@@ -8,6 +8,7 @@ package aes
import (
"crypto/cipher"
+ "crypto/internal/cipherhw"
)
type code int
@@ -25,18 +26,13 @@ type aesCipherAsm struct {
storage [256]byte // array backing key slice
}
-// hasAsm reports whether the AES-128, AES-192 and AES-256
-// cipher message (KM) function codes are supported.
-// Note: this function call is expensive.
-func hasAsm() bool
-
// cryptBlocks invokes the cipher message (KM) instruction with
// the given function code. This is equivalent to AES in ECB
// mode. The length must be a multiple of BlockSize (16).
-//go:noesape
+//go:noescape
func cryptBlocks(c code, key, dst, src *byte, length int)
-var useAsm = hasAsm()
+var useAsm = cipherhw.AESGCMSupport()
func newCipher(key []byte) (cipher.Block, error) {
if !useAsm {
diff --git a/libgo/go/crypto/aes/const.go b/libgo/go/crypto/aes/const.go
index aee73a7c52c..cbac5ff0ea1 100644
--- a/libgo/go/crypto/aes/const.go
+++ b/libgo/go/crypto/aes/const.go
@@ -4,6 +4,13 @@
// Package aes implements AES encryption (formerly Rijndael), as defined in
// U.S. Federal Information Processing Standards Publication 197.
+//
+// The AES operations in this package are not implemented using constant-time algorithms.
+// An exception is when running on systems with enabled hardware support for AES
+// that makes these operations constant-time. Examples include amd64 systems using AES-NI
+// extensions and s390x systems using Message-Security-Assist extensions.
+// On such systems, when the result of NewCipher is passed to cipher.NewGCM,
+// the GHASH operation used by GCM is also constant-time.
package aes
// This file contains AES constants - 8720 bytes of initialized data.
diff --git a/libgo/go/crypto/aes/gcm_s390x.go b/libgo/go/crypto/aes/gcm_s390x.go
new file mode 100644
index 00000000000..ca7f6a778dc
--- /dev/null
+++ b/libgo/go/crypto/aes/gcm_s390x.go
@@ -0,0 +1,272 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package aes
+
+import (
+ "crypto/cipher"
+ "crypto/subtle"
+ "errors"
+)
+
+// gcmCount represents a 16-byte big-endian count value.
+type gcmCount [16]byte
+
+// inc increments the rightmost 32-bits of the count value by 1.
+func (x *gcmCount) inc() {
+ // The compiler should optimize this to a 32-bit addition.
+ n := uint32(x[15]) | uint32(x[14])<<8 | uint32(x[13])<<16 | uint32(x[12])<<24
+ n += 1
+ x[12] = byte(n >> 24)
+ x[13] = byte(n >> 16)
+ x[14] = byte(n >> 8)
+ x[15] = byte(n)
+}
+
+// gcmLengths writes len0 || len1 as big-endian values to a 16-byte array.
+func gcmLengths(len0, len1 uint64) [16]byte {
+ return [16]byte{
+ byte(len0 >> 56),
+ byte(len0 >> 48),
+ byte(len0 >> 40),
+ byte(len0 >> 32),
+ byte(len0 >> 24),
+ byte(len0 >> 16),
+ byte(len0 >> 8),
+ byte(len0),
+ byte(len1 >> 56),
+ byte(len1 >> 48),
+ byte(len1 >> 40),
+ byte(len1 >> 32),
+ byte(len1 >> 24),
+ byte(len1 >> 16),
+ byte(len1 >> 8),
+ byte(len1),
+ }
+}
+
+// gcmHashKey represents the 16-byte hash key required by the GHASH algorithm.
+type gcmHashKey [16]byte
+
+type gcmAsm struct {
+ block *aesCipherAsm
+ hashKey gcmHashKey
+ nonceSize int
+}
+
+const (
+ gcmBlockSize = 16
+ gcmTagSize = 16
+ gcmStandardNonceSize = 12
+)
+
+var errOpen = errors.New("cipher: message authentication failed")
+
+// Assert that aesCipherAsm implements the gcmAble interface.
+var _ gcmAble = (*aesCipherAsm)(nil)
+
+// NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only
+// called by crypto/cipher.NewGCM via the gcmAble interface.
+func (c *aesCipherAsm) NewGCM(nonceSize int) (cipher.AEAD, error) {
+ var hk gcmHashKey
+ c.Encrypt(hk[:], hk[:])
+ g := &gcmAsm{
+ block: c,
+ hashKey: hk,
+ nonceSize: nonceSize,
+ }
+ return g, nil
+}
+
+func (g *gcmAsm) NonceSize() int {
+ return g.nonceSize
+}
+
+func (*gcmAsm) Overhead() int {
+ return gcmTagSize
+}
+
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+ if total := len(in) + n; cap(in) >= total {
+ head = in[:total]
+ } else {
+ head = make([]byte, total)
+ copy(head, in)
+ }
+ tail = head[len(in):]
+ return
+}
+
+// ghash uses the GHASH algorithm to hash data with the given key. The initial
+// hash value is given by hash which will be updated with the new hash value.
+// The length of data must be a multiple of 16-bytes.
+//go:noescape
+func ghash(key *gcmHashKey, hash *[16]byte, data []byte)
+
+// paddedGHASH pads data with zeroes until its length is a multiple of
+// 16-bytes. It then calculates a new value for hash using the GHASH algorithm.
+func (g *gcmAsm) paddedGHASH(hash *[16]byte, data []byte) {
+ siz := len(data) &^ 0xf // align size to 16-bytes
+ if siz > 0 {
+ ghash(&g.hashKey, hash, data[:siz])
+ data = data[siz:]
+ }
+ if len(data) > 0 {
+ var s [16]byte
+ copy(s[:], data)
+ ghash(&g.hashKey, hash, s[:])
+ }
+}
+
+// cryptBlocksGCM encrypts src using AES in counter mode using the given
+// function code and key. The rightmost 32-bits of the counter are incremented
+// between each block as required by the GCM spec. The initial counter value
+// is given by cnt, which is updated with the value of the next counter value
+// to use.
+//
+// The lengths of both dst and buf must be greater than or equal to the length
+// of src. buf may be partially or completely overwritten during the execution
+// of the function.
+//go:noescape
+func cryptBlocksGCM(fn code, key, dst, src, buf []byte, cnt *gcmCount)
+
+// counterCrypt encrypts src using AES in counter mode and places the result
+// into dst. cnt is the initial count value and will be updated with the next
+// count value. The length of dst must be greater than or equal to the length
+// of src.
+func (g *gcmAsm) counterCrypt(dst, src []byte, cnt *gcmCount) {
+ // Copying src into a buffer improves performance on some models when
+ // src and dst point to the same underlying array. We also need a
+ // buffer for counter values.
+ var ctrbuf, srcbuf [2048]byte
+ for len(src) >= 16 {
+ siz := len(src)
+ if len(src) > len(ctrbuf) {
+ siz = len(ctrbuf)
+ }
+ siz &^= 0xf // align siz to 16-bytes
+ copy(srcbuf[:], src[:siz])
+ cryptBlocksGCM(g.block.function, g.block.key, dst[:siz], srcbuf[:siz], ctrbuf[:], cnt)
+ src = src[siz:]
+ dst = dst[siz:]
+ }
+ if len(src) > 0 {
+ var x [16]byte
+ g.block.Encrypt(x[:], cnt[:])
+ for i := range src {
+ dst[i] = src[i] ^ x[i]
+ }
+ cnt.inc()
+ }
+}
+
+// deriveCounter computes the initial GCM counter state from the given nonce.
+// See NIST SP 800-38D, section 7.1.
+func (g *gcmAsm) deriveCounter(nonce []byte) gcmCount {
+ // GCM has two modes of operation with respect to the initial counter
+ // state: a "fast path" for 96-bit (12-byte) nonces, and a "slow path"
+ // for nonces of other lengths. For a 96-bit nonce, the nonce, along
+ // with a four-byte big-endian counter starting at one, is used
+ // directly as the starting counter. For other nonce sizes, the counter
+ // is computed by passing it through the GHASH function.
+ var counter gcmCount
+ if len(nonce) == gcmStandardNonceSize {
+ copy(counter[:], nonce)
+ counter[gcmBlockSize-1] = 1
+ } else {
+ var hash [16]byte
+ g.paddedGHASH(&hash, nonce)
+ lens := gcmLengths(0, uint64(len(nonce))*8)
+ g.paddedGHASH(&hash, lens[:])
+ copy(counter[:], hash[:])
+ }
+ return counter
+}
+
+// auth calculates GHASH(ciphertext, additionalData), masks the result with
+// tagMask and writes the result to out.
+func (g *gcmAsm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]byte) {
+ var hash [16]byte
+ g.paddedGHASH(&hash, additionalData)
+ g.paddedGHASH(&hash, ciphertext)
+ lens := gcmLengths(uint64(len(additionalData))*8, uint64(len(ciphertext))*8)
+ g.paddedGHASH(&hash, lens[:])
+
+ copy(out, hash[:])
+ for i := range out {
+ out[i] ^= tagMask[i]
+ }
+}
+
+// Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for
+// details.
+func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte {
+ if len(nonce) != g.nonceSize {
+ panic("cipher: incorrect nonce length given to GCM")
+ }
+ if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize {
+ panic("cipher: message too large for GCM")
+ }
+
+ ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize)
+
+ counter := g.deriveCounter(nonce)
+
+ var tagMask [gcmBlockSize]byte
+ g.block.Encrypt(tagMask[:], counter[:])
+ counter.inc()
+
+ g.counterCrypt(out, plaintext, &counter)
+ g.auth(out[len(plaintext):], out[:len(plaintext)], data, &tagMask)
+
+ return ret
+}
+
+// Open authenticates and decrypts ciphertext. See the cipher.AEAD interface
+// for details.
+func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
+ if len(nonce) != g.nonceSize {
+ panic("cipher: incorrect nonce length given to GCM")
+ }
+ if len(ciphertext) < gcmTagSize {
+ return nil, errOpen
+ }
+ if uint64(len(ciphertext)) > ((1<<32)-2)*BlockSize+gcmTagSize {
+ return nil, errOpen
+ }
+
+ tag := ciphertext[len(ciphertext)-gcmTagSize:]
+ ciphertext = ciphertext[:len(ciphertext)-gcmTagSize]
+
+ counter := g.deriveCounter(nonce)
+
+ var tagMask [gcmBlockSize]byte
+ g.block.Encrypt(tagMask[:], counter[:])
+ counter.inc()
+
+ var expectedTag [gcmTagSize]byte
+ g.auth(expectedTag[:], ciphertext, data, &tagMask)
+
+ ret, out := sliceForAppend(dst, len(ciphertext))
+
+ if subtle.ConstantTimeCompare(expectedTag[:], tag) != 1 {
+ // The AESNI code decrypts and authenticates concurrently, and
+ // so overwrites dst in the event of a tag mismatch. That
+ // behavior is mimicked here in order to be consistent across
+ // platforms.
+ for i := range out {
+ out[i] = 0
+ }
+ return nil, errOpen
+ }
+
+ g.counterCrypt(out, ciphertext, &counter)
+ return ret, nil
+}
diff --git a/libgo/go/crypto/cipher/cipher_test.go b/libgo/go/crypto/cipher/cipher_test.go
index 1faa7b87e52..4d7cd6b5dd9 100644
--- a/libgo/go/crypto/cipher/cipher_test.go
+++ b/libgo/go/crypto/cipher/cipher_test.go
@@ -5,8 +5,10 @@
package cipher_test
import (
+ "bytes"
"crypto/aes"
"crypto/cipher"
+ "crypto/des"
"testing"
)
@@ -34,3 +36,55 @@ func mustPanic(t *testing.T, msg string, f func()) {
}()
f()
}
+
+func TestEmptyPlaintext(t *testing.T) {
+ var key [16]byte
+ a, err := aes.NewCipher(key[:16])
+ if err != nil {
+ t.Fatal(err)
+ }
+ d, err := des.NewCipher(key[:8])
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ s := 16
+ pt := make([]byte, s)
+ ct := make([]byte, s)
+ for i := 0; i < 16; i++ {
+ pt[i], ct[i] = byte(i), byte(i)
+ }
+
+ assertEqual := func(name string, got, want []byte) {
+ if !bytes.Equal(got, want) {
+ t.Fatalf("%s: got %v, want %v", name, got, want)
+ }
+ }
+
+ for _, b := range []cipher.Block{a, d} {
+ iv := make([]byte, b.BlockSize())
+ cbce := cipher.NewCBCEncrypter(b, iv)
+ cbce.CryptBlocks(ct, pt[:0])
+ assertEqual("CBC encrypt", ct, pt)
+
+ cbcd := cipher.NewCBCDecrypter(b, iv)
+ cbcd.CryptBlocks(ct, pt[:0])
+ assertEqual("CBC decrypt", ct, pt)
+
+ cfbe := cipher.NewCFBEncrypter(b, iv)
+ cfbe.XORKeyStream(ct, pt[:0])
+ assertEqual("CFB encrypt", ct, pt)
+
+ cfbd := cipher.NewCFBDecrypter(b, iv)
+ cfbd.XORKeyStream(ct, pt[:0])
+ assertEqual("CFB decrypt", ct, pt)
+
+ ctr := cipher.NewCTR(b, iv)
+ ctr.XORKeyStream(ct, pt[:0])
+ assertEqual("CTR", ct, pt)
+
+ ofb := cipher.NewOFB(b, iv)
+ ofb.XORKeyStream(ct, pt[:0])
+ assertEqual("OFB", ct, pt)
+ }
+}
diff --git a/libgo/go/crypto/cipher/example_test.go b/libgo/go/crypto/cipher/example_test.go
index 9abe782bca5..956cc2eaca6 100644
--- a/libgo/go/crypto/cipher/example_test.go
+++ b/libgo/go/crypto/cipher/example_test.go
@@ -14,7 +14,7 @@ import (
"os"
)
-func ExampleNewGCMEncrypter() {
+func ExampleNewGCM_encrypt() {
// The key argument should be the AES key, either 16 or 32 bytes
// to select AES-128 or AES-256.
key := []byte("AES256Key-32Characters1234567890")
@@ -40,7 +40,7 @@ func ExampleNewGCMEncrypter() {
fmt.Printf("%x\n", ciphertext)
}
-func ExampleNewGCMDecrypter() {
+func ExampleNewGCM_decrypt() {
// The key argument should be the AES key, either 16 or 32 bytes
// to select AES-128 or AES-256.
key := []byte("AES256Key-32Characters1234567890")
diff --git a/libgo/go/crypto/cipher/gcm.go b/libgo/go/crypto/cipher/gcm.go
index 3868d7123a1..62085aac0fe 100644
--- a/libgo/go/crypto/cipher/gcm.go
+++ b/libgo/go/crypto/cipher/gcm.go
@@ -74,6 +74,10 @@ type gcm struct {
// NewGCM returns the given 128-bit, block cipher wrapped in Galois Counter Mode
// with the standard nonce length.
+//
+// In general, the GHASH operation performed by this implementation of GCM is not constant-time.
+// An exception is when the underlying Block was created by aes.NewCipher
+// on systems with hardware support for AES. See the crypto/aes package documentation for details.
func NewGCM(cipher Block) (AEAD, error) {
return NewGCMWithNonceSize(cipher, gcmStandardNonceSize)
}
@@ -135,6 +139,10 @@ func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte {
if len(nonce) != g.nonceSize {
panic("cipher: incorrect nonce length given to GCM")
}
+ if uint64(len(plaintext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize()) {
+ panic("cipher: message too large for GCM")
+ }
+
ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize)
var counter, tagMask [gcmBlockSize]byte
@@ -159,6 +167,10 @@ func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
if len(ciphertext) < gcmTagSize {
return nil, errOpen
}
+ if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize())+gcmTagSize {
+ return nil, errOpen
+ }
+
tag := ciphertext[len(ciphertext)-gcmTagSize:]
ciphertext = ciphertext[:len(ciphertext)-gcmTagSize]
@@ -176,7 +188,7 @@ func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
if subtle.ConstantTimeCompare(expectedTag[:], tag) != 1 {
// The AESNI code decrypts and authenticates concurrently, and
// so overwrites dst in the event of a tag mismatch. That
- // behaviour is mimicked here in order to be consistent across
+ // behavior is mimicked here in order to be consistent across
// platforms.
for i := range out {
out[i] = 0
diff --git a/libgo/go/crypto/cipher/gcm_test.go b/libgo/go/crypto/cipher/gcm_test.go
index bb1ab3c0b0f..6878b4cb42b 100644
--- a/libgo/go/crypto/cipher/gcm_test.go
+++ b/libgo/go/crypto/cipher/gcm_test.go
@@ -8,7 +8,11 @@ import (
"bytes"
"crypto/aes"
"crypto/cipher"
+ "crypto/rand"
"encoding/hex"
+ "errors"
+ "io"
+ "reflect"
"testing"
)
@@ -274,3 +278,157 @@ func TestTagFailureOverwrite(t *testing.T) {
}
}
}
+
+func TestGCMCounterWrap(t *testing.T) {
+ // Test that the last 32-bits of the counter wrap correctly.
+ tests := []struct {
+ nonce, tag string
+ }{
+ {"0fa72e25", "37e1948cdfff09fbde0c40ad99fee4a7"}, // counter: 7eb59e4d961dad0dfdd75aaffffffff0
+ {"afe05cc1", "438f3aa9fee5e54903b1927bca26bbdf"}, // counter: 75d492a7e6e6bfc979ad3a8ffffffff4
+ {"9ffecbef", "7b88ca424df9703e9e8611071ec7e16e"}, // counter: c8bb108b0ecdc71747b9d57ffffffff5
+ {"ffc3e5b3", "38d49c86e0abe853ac250e66da54c01a"}, // counter: 706414d2de9b36ab3b900a9ffffffff6
+ {"cfdd729d", "e08402eaac36a1a402e09b1bd56500e8"}, // counter: cd0b96fe36b04e750584e56ffffffff7
+ {"010ae3d486", "5405bb490b1f95d01e2ba735687154bc"}, // counter: e36c18e69406c49722808104fffffff8
+ {"01b1107a9d", "939a585f342e01e17844627492d44dbf"}, // counter: e6d56eaf9127912b6d62c6dcffffffff
+ }
+ key, err := aes.NewCipher(make([]byte, 16))
+ if err != nil {
+ t.Fatal(err)
+ }
+ plaintext := make([]byte, 16*17+1)
+ for i, test := range tests {
+ nonce, _ := hex.DecodeString(test.nonce)
+ want, _ := hex.DecodeString(test.tag)
+ aead, err := cipher.NewGCMWithNonceSize(key, len(nonce))
+ if err != nil {
+ t.Fatal(err)
+ }
+ got := aead.Seal(nil, nonce, plaintext, nil)
+ if !bytes.Equal(got[len(plaintext):], want) {
+ t.Errorf("test[%v]: got: %x, want: %x", i, got[len(plaintext):], want)
+ }
+ _, err = aead.Open(nil, nonce, got, nil)
+ if err != nil {
+ t.Errorf("test[%v]: authentication failed", i)
+ }
+ }
+}
+
+var _ cipher.Block = (*wrapper)(nil)
+
+type wrapper struct {
+ block cipher.Block
+}
+
+func (w *wrapper) BlockSize() int { return w.block.BlockSize() }
+func (w *wrapper) Encrypt(dst, src []byte) { w.block.Encrypt(dst, src) }
+func (w *wrapper) Decrypt(dst, src []byte) { w.block.Decrypt(dst, src) }
+
+// wrap wraps the Block interface so that it does not fulfill
+// any optimizing interfaces such as gcmAble.
+func wrap(b cipher.Block) cipher.Block {
+ return &wrapper{b}
+}
+
+func TestGCMAsm(t *testing.T) {
+ // Create a new pair of AEADs, one using the assembly implementation
+ // and one using the generic Go implementation.
+ newAESGCM := func(key []byte) (asm, generic cipher.AEAD, err error) {
+ block, err := aes.NewCipher(key[:])
+ if err != nil {
+ return nil, nil, err
+ }
+ asm, err = cipher.NewGCM(block)
+ if err != nil {
+ return nil, nil, err
+ }
+ generic, err = cipher.NewGCM(wrap(block))
+ if err != nil {
+ return nil, nil, err
+ }
+ return asm, generic, nil
+ }
+
+ // check for assembly implementation
+ var key [16]byte
+ asm, generic, err := newAESGCM(key[:])
+ if err != nil {
+ t.Fatal(err)
+ }
+ if reflect.TypeOf(asm) == reflect.TypeOf(generic) {
+ t.Skipf("no assembly implementation of GCM")
+ }
+
+ // generate permutations
+ type pair struct{ align, length int }
+ lengths := []int{0, 8192, 8193, 8208}
+ keySizes := []int{16, 24, 32}
+ alignments := []int{0, 1, 2, 3}
+ if testing.Short() {
+ keySizes = []int{16}
+ alignments = []int{1}
+ }
+ perms := make([]pair, 0)
+ for _, l := range lengths {
+ for _, a := range alignments {
+ if a != 0 && l == 0 {
+ continue
+ }
+ perms = append(perms, pair{align: a, length: l})
+ }
+ }
+
+ // run test for all permutations
+ test := func(ks int, pt, ad []byte) error {
+ key := make([]byte, ks)
+ if _, err := io.ReadFull(rand.Reader, key); err != nil {
+ return err
+ }
+ asm, generic, err := newAESGCM(key)
+ if err != nil {
+ return err
+ }
+ if _, err := io.ReadFull(rand.Reader, pt); err != nil {
+ return err
+ }
+ if _, err := io.ReadFull(rand.Reader, ad); err != nil {
+ return err
+ }
+ nonce := make([]byte, 12)
+ if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
+ return err
+ }
+ want := generic.Seal(nil, nonce, pt, ad)
+ got := asm.Seal(nil, nonce, pt, ad)
+ if !bytes.Equal(want, got) {
+ return errors.New("incorrect Seal output")
+ }
+ got, err = asm.Open(nil, nonce, want, ad)
+ if err != nil {
+ return errors.New("authentication failed")
+ }
+ if !bytes.Equal(pt, got) {
+ return errors.New("incorrect Open output")
+ }
+ return nil
+ }
+ for _, a := range perms {
+ ad := make([]byte, a.align+a.length)
+ ad = ad[a.align:]
+ for _, p := range perms {
+ pt := make([]byte, p.align+p.length)
+ pt = pt[p.align:]
+ for _, ks := range keySizes {
+ if err := test(ks, pt, ad); err != nil {
+ t.Error(err)
+ t.Errorf(" key size: %v", ks)
+ t.Errorf(" plaintext alignment: %v", p.align)
+ t.Errorf(" plaintext length: %v", p.length)
+ t.Errorf(" additionalData alignment: %v", a.align)
+ t.Fatalf(" additionalData length: %v", a.length)
+ }
+ }
+ }
+ }
+}
diff --git a/libgo/go/crypto/dsa/dsa.go b/libgo/go/crypto/dsa/dsa.go
index e9b6a0c2532..bc0c3e34629 100644
--- a/libgo/go/crypto/dsa/dsa.go
+++ b/libgo/go/crypto/dsa/dsa.go
@@ -3,6 +3,8 @@
// license that can be found in the LICENSE file.
// Package dsa implements the Digital Signature Algorithm, as defined in FIPS 186-3.
+//
+// The DSA operations in this package are not implemented using constant-time algorithms.
package dsa
import (
@@ -189,17 +191,21 @@ func fermatInverse(k, P *big.Int) *big.Int {
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
// to the byte-length of the subgroup. This function does not perform that
// truncation itself.
+//
+// Be aware that calling Sign with an attacker-controlled PrivateKey may
+// require an arbitrary amount of CPU.
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
// FIPS 186-3, section 4.6
n := priv.Q.BitLen()
- if n&7 != 0 {
+ if priv.Q.Sign() <= 0 || priv.P.Sign() <= 0 || priv.G.Sign() <= 0 || priv.X.Sign() <= 0 || n&7 != 0 {
err = ErrInvalidPublicKey
return
}
n >>= 3
- for {
+ var attempts int
+ for attempts = 10; attempts > 0; attempts-- {
k := new(big.Int)
buf := make([]byte, n)
for {
@@ -208,6 +214,10 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
return
}
k.SetBytes(buf)
+ // priv.Q must be >= 128 because the test above
+ // requires it to be > 0 and that
+ // ceil(log_2(Q)) mod 8 = 0
+ // Thus this loop will quickly terminate.
if k.Sign() > 0 && k.Cmp(priv.Q) < 0 {
break
}
@@ -235,6 +245,12 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
}
}
+ // Only degenerate private keys will require more than a handful of
+ // attempts.
+ if attempts == 0 {
+ return nil, nil, ErrInvalidPublicKey
+ }
+
return
}
diff --git a/libgo/go/crypto/dsa/dsa_test.go b/libgo/go/crypto/dsa/dsa_test.go
index 568416d0dfb..8600059f032 100644
--- a/libgo/go/crypto/dsa/dsa_test.go
+++ b/libgo/go/crypto/dsa/dsa_test.go
@@ -73,6 +73,14 @@ func TestParameterGeneration(t *testing.T) {
testParameterGeneration(t, L3072N256, 3072, 256)
}
+func fromHex(s string) *big.Int {
+ result, ok := new(big.Int).SetString(s, 16)
+ if !ok {
+ panic(s)
+ }
+ return result
+}
+
func TestSignAndVerify(t *testing.T) {
var priv PrivateKey
priv.P, _ = new(big.Int).SetString("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF", 16)
@@ -83,3 +91,33 @@ func TestSignAndVerify(t *testing.T) {
testSignAndVerify(t, 0, &priv)
}
+
+func TestSigningWithDegenerateKeys(t *testing.T) {
+ // Signing with degenerate private keys should not cause an infinite
+ // loop.
+ badKeys := []struct {
+ p, q, g, y, x string
+ }{
+ {"00", "01", "00", "00", "00"},
+ {"01", "ff", "00", "00", "00"},
+ }
+
+ for i, test := range badKeys {
+ priv := PrivateKey{
+ PublicKey: PublicKey{
+ Parameters: Parameters{
+ P: fromHex(test.p),
+ Q: fromHex(test.q),
+ G: fromHex(test.g),
+ },
+ Y: fromHex(test.y),
+ },
+ X: fromHex(test.x),
+ }
+
+ hashed := []byte("testing")
+ if _, _, err := Sign(rand.Reader, &priv, hashed); err == nil {
+ t.Errorf("#%d: unexpected success", i)
+ }
+ }
+}
diff --git a/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go
index 72fb49934fc..02848fd5954 100644
--- a/libgo/go/crypto/ecdsa/ecdsa.go
+++ b/libgo/go/crypto/ecdsa/ecdsa.go
@@ -149,7 +149,7 @@ var errZeroParam = errors.New("zero parameter")
// returns the signature as a pair of integers. The security of the private key
// depends on the entropy of rand.
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
- // Get max(log2(q) / 2, 256) bits of entropy from rand.
+ // Get min(log2(q) / 2, 256) bits of entropy from rand.
entropylen := (priv.Curve.Params().BitSize + 7) / 16
if entropylen > 32 {
entropylen = 32
diff --git a/libgo/go/crypto/ecdsa/ecdsa_test.go b/libgo/go/crypto/ecdsa/ecdsa_test.go
index fc25fd74a78..9546f67c68b 100644
--- a/libgo/go/crypto/ecdsa/ecdsa_test.go
+++ b/libgo/go/crypto/ecdsa/ecdsa_test.go
@@ -54,6 +54,18 @@ func BenchmarkSignP256(b *testing.B) {
}
}
+func BenchmarkSignP384(b *testing.B) {
+ b.ResetTimer()
+ p384 := elliptic.P384()
+ hashed := []byte("testing")
+ priv, _ := GenerateKey(p384, rand.Reader)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ _, _, _ = Sign(rand.Reader, priv, hashed)
+ }
+}
+
func BenchmarkVerifyP256(b *testing.B) {
b.ResetTimer()
p256 := elliptic.P256()
diff --git a/libgo/go/crypto/elliptic/elliptic.go b/libgo/go/crypto/elliptic/elliptic.go
index c02df45d105..d3527243e78 100644
--- a/libgo/go/crypto/elliptic/elliptic.go
+++ b/libgo/go/crypto/elliptic/elliptic.go
@@ -367,18 +367,24 @@ func initP521() {
}
// P256 returns a Curve which implements P-256 (see FIPS 186-3, section D.2.3)
+//
+// The cryptographic operations are implemented using constant-time algorithms.
func P256() Curve {
initonce.Do(initAll)
return p256
}
// P384 returns a Curve which implements P-384 (see FIPS 186-3, section D.2.4)
+//
+// The cryptographic operations do not use constant-time algorithms.
func P384() Curve {
initonce.Do(initAll)
return p384
}
// P521 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5)
+//
+// The cryptographic operations do not use constant-time algorithms.
func P521() Curve {
initonce.Do(initAll)
return p521
diff --git a/libgo/go/crypto/elliptic/elliptic_test.go b/libgo/go/crypto/elliptic/elliptic_test.go
index 7f3f1a21187..902c4143837 100644
--- a/libgo/go/crypto/elliptic/elliptic_test.go
+++ b/libgo/go/crypto/elliptic/elliptic_test.go
@@ -28,7 +28,7 @@ func TestOffCurve(t *testing.T) {
b := Marshal(p224, x, y)
x1, y1 := Unmarshal(p224, b)
if x1 != nil || y1 != nil {
- t.Errorf("FAIL: unmarshalling a point not on the curve succeeded")
+ t.Errorf("FAIL: unmarshaling a point not on the curve succeeded")
}
}
diff --git a/libgo/go/crypto/elliptic/p224.go b/libgo/go/crypto/elliptic/p224.go
index de266ca77a7..22d0e2429cd 100644
--- a/libgo/go/crypto/elliptic/p224.go
+++ b/libgo/go/crypto/elliptic/p224.go
@@ -35,7 +35,9 @@ func initP224() {
p224FromBig(&p224.b, p224.B)
}
-// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2)
+// P224 returns a Curve which implements P-224 (see FIPS 186-3, section D.2.2).
+//
+// The cryptographic operations are implemented using constant-time algorithms.
func P224() Curve {
initonce.Do(initAll)
return p224
diff --git a/libgo/go/crypto/elliptic/p256.go b/libgo/go/crypto/elliptic/p256.go
index 688e0b412e0..a0933dc6fb1 100644
--- a/libgo/go/crypto/elliptic/p256.go
+++ b/libgo/go/crypto/elliptic/p256.go
@@ -17,7 +17,8 @@ type p256Curve struct {
}
var (
- p256 p256Curve
+ p256Params *CurveParams
+
// RInverse contains 1/R mod p - the inverse of the Montgomery constant
// (2**257).
p256RInverse *big.Int
@@ -25,15 +26,18 @@ var (
func initP256() {
// See FIPS 186-3, section D.2.3
- p256.CurveParams = &CurveParams{Name: "P-256"}
- p256.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10)
- p256.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10)
- p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
- p256.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16)
- p256.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16)
- p256.BitSize = 256
+ p256Params = &CurveParams{Name: "P-256"}
+ p256Params.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10)
+ p256Params.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10)
+ p256Params.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
+ p256Params.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16)
+ p256Params.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16)
+ p256Params.BitSize = 256
p256RInverse, _ = new(big.Int).SetString("7fffffff00000001fffffffe8000000100000000ffffffff0000000180000000", 16)
+
+ // Arch-specific initialization, i.e. let a platform dynamically pick a P256 implementation
+ initP256Arch()
}
func (curve p256Curve) Params() *CurveParams {
@@ -47,8 +51,8 @@ func p256GetScalar(out *[32]byte, in []byte) {
n := new(big.Int).SetBytes(in)
var scalarBytes []byte
- if n.Cmp(p256.N) >= 0 {
- n.Mod(n, p256.N)
+ if n.Cmp(p256Params.N) >= 0 {
+ n.Mod(n, p256Params.N)
scalarBytes = n.Bytes()
} else {
scalarBytes = in
@@ -1143,7 +1147,7 @@ func p256ScalarMult(xOut, yOut, zOut, x, y *[p256Limbs]uint32, scalar *[32]uint8
// p256FromBig sets out = R*in.
func p256FromBig(out *[p256Limbs]uint32, in *big.Int) {
tmp := new(big.Int).Lsh(in, 257)
- tmp.Mod(tmp, p256.P)
+ tmp.Mod(tmp, p256Params.P)
for i := 0; i < p256Limbs; i++ {
if bits := tmp.Bits(); len(bits) > 0 {
@@ -1183,6 +1187,6 @@ func p256ToBig(in *[p256Limbs]uint32) *big.Int {
}
result.Mul(result, p256RInverse)
- result.Mod(result, p256.P)
+ result.Mod(result, p256Params.P)
return result
}
diff --git a/libgo/go/crypto/elliptic/p256_generic.go b/libgo/go/crypto/elliptic/p256_generic.go
new file mode 100644
index 00000000000..49445c3999f
--- /dev/null
+++ b/libgo/go/crypto/elliptic/p256_generic.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// -build !amd64,!s390x
+
+package elliptic
+
+var (
+ p256 p256Curve
+)
+
+func initP256Arch() {
+ // Use pure Go implementation.
+ p256 = p256Curve{p256Params}
+}
diff --git a/libgo/go/crypto/elliptic/p256_s390x.go b/libgo/go/crypto/elliptic/p256_s390x.go
new file mode 100644
index 00000000000..a824454d7da
--- /dev/null
+++ b/libgo/go/crypto/elliptic/p256_s390x.go
@@ -0,0 +1,513 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// -build s390x
+
+package elliptic
+
+import (
+ "math/big"
+)
+
+type p256CurveFast struct {
+ *CurveParams
+}
+
+type p256Point struct {
+ x [32]byte
+ y [32]byte
+ z [32]byte
+}
+
+var (
+ p256 Curve
+ p256PreFast *[37][64]p256Point
+)
+
+// hasVectorFacility reports whether the machine has the z/Architecture
+// vector facility installed and enabled.
+func hasVectorFacility() bool
+
+var hasVX = hasVectorFacility()
+
+func initP256Arch() {
+ if hasVX {
+ p256 = p256CurveFast{p256Params}
+ initTable()
+ return
+ }
+
+ // No vector support, use pure Go implementation.
+ p256 = p256Curve{p256Params}
+ return
+}
+
+func (curve p256CurveFast) Params() *CurveParams {
+ return curve.CurveParams
+}
+
+// Functions implemented in p256_asm_s390x.s
+// Montgomery multiplication modulo P256
+func p256MulAsm(res, in1, in2 []byte)
+
+// Montgomery square modulo P256
+func p256Sqr(res, in []byte) {
+ p256MulAsm(res, in, in)
+}
+
+// Montgomery multiplication by 1
+func p256FromMont(res, in []byte)
+
+// iff cond == 1 val <- -val
+func p256NegCond(val *p256Point, cond int)
+
+// if cond == 0 res <- b; else res <- a
+func p256MovCond(res, a, b *p256Point, cond int)
+
+// Constant time table access
+func p256Select(point *p256Point, table []p256Point, idx int)
+func p256SelectBase(point *p256Point, table []p256Point, idx int)
+
+// Montgomery multiplication modulo Ord(G)
+func p256OrdMul(res, in1, in2 []byte)
+
+// Montgomery square modulo Ord(G), repeated n times
+func p256OrdSqr(res, in []byte, n int) {
+ copy(res, in)
+ for i := 0; i < n; i += 1 {
+ p256OrdMul(res, res, res)
+ }
+}
+
+// Point add with P2 being affine point
+// If sign == 1 -> P2 = -P2
+// If sel == 0 -> P3 = P1
+// if zero == 0 -> P3 = P2
+func p256PointAddAffineAsm(P3, P1, P2 *p256Point, sign, sel, zero int)
+
+// Point add
+func p256PointAddAsm(P3, P1, P2 *p256Point)
+func p256PointDoubleAsm(P3, P1 *p256Point)
+
+func (curve p256CurveFast) Inverse(k *big.Int) *big.Int {
+ if k.Cmp(p256Params.N) >= 0 {
+ // This should never happen.
+ reducedK := new(big.Int).Mod(k, p256Params.N)
+ k = reducedK
+ }
+
+ // table will store precomputed powers of x. The 32 bytes at index
+ // i store x^(i+1).
+ var table [15][32]byte
+
+ x := fromBig(k)
+ // This code operates in the Montgomery domain where R = 2^256 mod n
+ // and n is the order of the scalar field. (See initP256 for the
+ // value.) Elements in the Montgomery domain take the form a×R and
+ // multiplication of x and y in the calculates (x × y × R^-1) mod n. RR
+ // is R×R mod n thus the Montgomery multiplication x and RR gives x×R,
+ // i.e. converts x into the Montgomery domain. Stored in BigEndian form
+ RR := []byte{0x66, 0xe1, 0x2d, 0x94, 0xf3, 0xd9, 0x56, 0x20, 0x28, 0x45, 0xb2, 0x39, 0x2b, 0x6b, 0xec, 0x59,
+ 0x46, 0x99, 0x79, 0x9c, 0x49, 0xbd, 0x6f, 0xa6, 0x83, 0x24, 0x4c, 0x95, 0xbe, 0x79, 0xee, 0xa2}
+
+ p256OrdMul(table[0][:], x, RR)
+
+ // Prepare the table, no need in constant time access, because the
+ // power is not a secret. (Entry 0 is never used.)
+ for i := 2; i < 16; i += 2 {
+ p256OrdSqr(table[i-1][:], table[(i/2)-1][:], 1)
+ p256OrdMul(table[i][:], table[i-1][:], table[0][:])
+ }
+
+ copy(x, table[14][:]) // f
+
+ p256OrdSqr(x[0:32], x[0:32], 4)
+ p256OrdMul(x[0:32], x[0:32], table[14][:]) // ff
+ t := make([]byte, 32)
+ copy(t, x)
+
+ p256OrdSqr(x, x, 8)
+ p256OrdMul(x, x, t) // ffff
+ copy(t, x)
+
+ p256OrdSqr(x, x, 16)
+ p256OrdMul(x, x, t) // ffffffff
+ copy(t, x)
+
+ p256OrdSqr(x, x, 64) // ffffffff0000000000000000
+ p256OrdMul(x, x, t) // ffffffff00000000ffffffff
+ p256OrdSqr(x, x, 32) // ffffffff00000000ffffffff00000000
+ p256OrdMul(x, x, t) // ffffffff00000000ffffffffffffffff
+
+ // Remaining 32 windows
+ expLo := [32]byte{0xb, 0xc, 0xe, 0x6, 0xf, 0xa, 0xa, 0xd, 0xa, 0x7, 0x1, 0x7, 0x9, 0xe, 0x8, 0x4,
+ 0xf, 0x3, 0xb, 0x9, 0xc, 0xa, 0xc, 0x2, 0xf, 0xc, 0x6, 0x3, 0x2, 0x5, 0x4, 0xf}
+ for i := 0; i < 32; i++ {
+ p256OrdSqr(x, x, 4)
+ p256OrdMul(x, x, table[expLo[i]-1][:])
+ }
+
+ // Multiplying by one in the Montgomery domain converts a Montgomery
+ // value out of the domain.
+ one := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
+ p256OrdMul(x, x, one)
+
+ return new(big.Int).SetBytes(x)
+}
+
+// fromBig converts a *big.Int into a format used by this code.
+func fromBig(big *big.Int) []byte {
+ // This could be done a lot more efficiently...
+ res := big.Bytes()
+ if 32 == len(res) {
+ return res
+ }
+ t := make([]byte, 32)
+ offset := 32 - len(res)
+ for i := len(res) - 1; i >= 0; i-- {
+ t[i+offset] = res[i]
+ }
+ return t
+}
+
+// p256GetMultiplier makes sure byte array will have 32 byte elements, If the scalar
+// is equal or greater than the order of the group, it's reduced modulo that order.
+func p256GetMultiplier(in []byte) []byte {
+ n := new(big.Int).SetBytes(in)
+
+ if n.Cmp(p256Params.N) >= 0 {
+ n.Mod(n, p256Params.N)
+ }
+ return fromBig(n)
+}
+
+// p256MulAsm operates in a Montgomery domain with R = 2^256 mod p, where p is the
+// underlying field of the curve. (See initP256 for the value.) Thus rr here is
+// R×R mod p. See comment in Inverse about how this is used.
+var rr = []byte{0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
+ 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
+
+// (This is one, in the Montgomery domain.)
+var one = []byte{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
+
+func maybeReduceModP(in *big.Int) *big.Int {
+ if in.Cmp(p256Params.P) < 0 {
+ return in
+ }
+ return new(big.Int).Mod(in, p256Params.P)
+}
+
+func (curve p256CurveFast) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) {
+ var r1, r2 p256Point
+ r1.p256BaseMult(p256GetMultiplier(baseScalar))
+
+ copy(r2.x[:], fromBig(maybeReduceModP(bigX)))
+ copy(r2.y[:], fromBig(maybeReduceModP(bigY)))
+ copy(r2.z[:], one)
+ p256MulAsm(r2.x[:], r2.x[:], rr[:])
+ p256MulAsm(r2.y[:], r2.y[:], rr[:])
+
+ r2.p256ScalarMult(p256GetMultiplier(scalar))
+ p256PointAddAsm(&r1, &r1, &r2)
+ return r1.p256PointToAffine()
+}
+
+func (curve p256CurveFast) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
+ var r p256Point
+ r.p256BaseMult(p256GetMultiplier(scalar))
+ return r.p256PointToAffine()
+}
+
+func (curve p256CurveFast) ScalarMult(bigX, bigY *big.Int, scalar []byte) (x, y *big.Int) {
+ var r p256Point
+ copy(r.x[:], fromBig(maybeReduceModP(bigX)))
+ copy(r.y[:], fromBig(maybeReduceModP(bigY)))
+ copy(r.z[:], one)
+ p256MulAsm(r.x[:], r.x[:], rr[:])
+ p256MulAsm(r.y[:], r.y[:], rr[:])
+ r.p256ScalarMult(p256GetMultiplier(scalar))
+ return r.p256PointToAffine()
+}
+
+func (p *p256Point) p256PointToAffine() (x, y *big.Int) {
+ zInv := make([]byte, 32)
+ zInvSq := make([]byte, 32)
+
+ p256Inverse(zInv, p.z[:])
+ p256Sqr(zInvSq, zInv)
+ p256MulAsm(zInv, zInv, zInvSq)
+
+ p256MulAsm(zInvSq, p.x[:], zInvSq)
+ p256MulAsm(zInv, p.y[:], zInv)
+
+ p256FromMont(zInvSq, zInvSq)
+ p256FromMont(zInv, zInv)
+
+ return new(big.Int).SetBytes(zInvSq), new(big.Int).SetBytes(zInv)
+}
+
+// p256Inverse sets out to in^-1 mod p.
+func p256Inverse(out, in []byte) {
+ var stack [6 * 32]byte
+ p2 := stack[32*0 : 32*0+32]
+ p4 := stack[32*1 : 32*1+32]
+ p8 := stack[32*2 : 32*2+32]
+ p16 := stack[32*3 : 32*3+32]
+ p32 := stack[32*4 : 32*4+32]
+
+ p256Sqr(out, in)
+ p256MulAsm(p2, out, in) // 3*p
+
+ p256Sqr(out, p2)
+ p256Sqr(out, out)
+ p256MulAsm(p4, out, p2) // f*p
+
+ p256Sqr(out, p4)
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256MulAsm(p8, out, p4) // ff*p
+
+ p256Sqr(out, p8)
+
+ for i := 0; i < 7; i++ {
+ p256Sqr(out, out)
+ }
+ p256MulAsm(p16, out, p8) // ffff*p
+
+ p256Sqr(out, p16)
+ for i := 0; i < 15; i++ {
+ p256Sqr(out, out)
+ }
+ p256MulAsm(p32, out, p16) // ffffffff*p
+
+ p256Sqr(out, p32)
+
+ for i := 0; i < 31; i++ {
+ p256Sqr(out, out)
+ }
+ p256MulAsm(out, out, in)
+
+ for i := 0; i < 32*4; i++ {
+ p256Sqr(out, out)
+ }
+ p256MulAsm(out, out, p32)
+
+ for i := 0; i < 32; i++ {
+ p256Sqr(out, out)
+ }
+ p256MulAsm(out, out, p32)
+
+ for i := 0; i < 16; i++ {
+ p256Sqr(out, out)
+ }
+ p256MulAsm(out, out, p16)
+
+ for i := 0; i < 8; i++ {
+ p256Sqr(out, out)
+ }
+ p256MulAsm(out, out, p8)
+
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256MulAsm(out, out, p4)
+
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256MulAsm(out, out, p2)
+
+ p256Sqr(out, out)
+ p256Sqr(out, out)
+ p256MulAsm(out, out, in)
+}
+
+func boothW5(in uint) (int, int) {
+ var s uint = ^((in >> 5) - 1)
+ var d uint = (1 << 6) - in - 1
+ d = (d & s) | (in & (^s))
+ d = (d >> 1) + (d & 1)
+ return int(d), int(s & 1)
+}
+
+func boothW7(in uint) (int, int) {
+ var s uint = ^((in >> 7) - 1)
+ var d uint = (1 << 8) - in - 1
+ d = (d & s) | (in & (^s))
+ d = (d >> 1) + (d & 1)
+ return int(d), int(s & 1)
+}
+
+func initTable() {
+ p256PreFast = new([37][64]p256Point) //z coordinate not used
+ basePoint := p256Point{
+ x: [32]byte{0x18, 0x90, 0x5f, 0x76, 0xa5, 0x37, 0x55, 0xc6, 0x79, 0xfb, 0x73, 0x2b, 0x77, 0x62, 0x25, 0x10,
+ 0x75, 0xba, 0x95, 0xfc, 0x5f, 0xed, 0xb6, 0x01, 0x79, 0xe7, 0x30, 0xd4, 0x18, 0xa9, 0x14, 0x3c}, //(p256.x*2^256)%p
+ y: [32]byte{0x85, 0x71, 0xff, 0x18, 0x25, 0x88, 0x5d, 0x85, 0xd2, 0xe8, 0x86, 0x88, 0xdd, 0x21, 0xf3, 0x25,
+ 0x8b, 0x4a, 0xb8, 0xe4, 0xba, 0x19, 0xe4, 0x5c, 0xdd, 0xf2, 0x53, 0x57, 0xce, 0x95, 0x56, 0x0a}, //(p256.y*2^256)%p
+ z: [32]byte{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, //(p256.z*2^256)%p
+ }
+
+ t1 := new(p256Point)
+ t2 := new(p256Point)
+ *t2 = basePoint
+
+ zInv := make([]byte, 32)
+ zInvSq := make([]byte, 32)
+ for j := 0; j < 64; j++ {
+ *t1 = *t2
+ for i := 0; i < 37; i++ {
+ // The window size is 7 so we need to double 7 times.
+ if i != 0 {
+ for k := 0; k < 7; k++ {
+ p256PointDoubleAsm(t1, t1)
+ }
+ }
+ // Convert the point to affine form. (Its values are
+ // still in Montgomery form however.)
+ p256Inverse(zInv, t1.z[:])
+ p256Sqr(zInvSq, zInv)
+ p256MulAsm(zInv, zInv, zInvSq)
+
+ p256MulAsm(t1.x[:], t1.x[:], zInvSq)
+ p256MulAsm(t1.y[:], t1.y[:], zInv)
+
+ copy(t1.z[:], basePoint.z[:])
+ // Update the table entry
+ copy(p256PreFast[i][j].x[:], t1.x[:])
+ copy(p256PreFast[i][j].y[:], t1.y[:])
+ }
+ if j == 0 {
+ p256PointDoubleAsm(t2, &basePoint)
+ } else {
+ p256PointAddAsm(t2, t2, &basePoint)
+ }
+ }
+}
+
+func (p *p256Point) p256BaseMult(scalar []byte) {
+ wvalue := (uint(scalar[31]) << 1) & 0xff
+ sel, sign := boothW7(uint(wvalue))
+ p256SelectBase(p, p256PreFast[0][:], sel)
+ p256NegCond(p, sign)
+
+ copy(p.z[:], one[:])
+ var t0 p256Point
+
+ copy(t0.z[:], one[:])
+
+ index := uint(6)
+ zero := sel
+
+ for i := 1; i < 37; i++ {
+ if index < 247 {
+ wvalue = ((uint(scalar[31-index/8]) >> (index % 8)) + (uint(scalar[31-index/8-1]) << (8 - (index % 8)))) & 0xff
+ } else {
+ wvalue = (uint(scalar[31-index/8]) >> (index % 8)) & 0xff
+ }
+ index += 7
+ sel, sign = boothW7(uint(wvalue))
+ p256SelectBase(&t0, p256PreFast[i][:], sel)
+ p256PointAddAffineAsm(p, p, &t0, sign, sel, zero)
+ zero |= sel
+ }
+}
+
+func (p *p256Point) p256ScalarMult(scalar []byte) {
+ // precomp is a table of precomputed points that stores powers of p
+ // from p^1 to p^16.
+ var precomp [16]p256Point
+ var t0, t1, t2, t3 p256Point
+
+ // Prepare the table
+ *&precomp[0] = *p
+
+ p256PointDoubleAsm(&t0, p)
+ p256PointDoubleAsm(&t1, &t0)
+ p256PointDoubleAsm(&t2, &t1)
+ p256PointDoubleAsm(&t3, &t2)
+ *&precomp[1] = t0 // 2
+ *&precomp[3] = t1 // 4
+ *&precomp[7] = t2 // 8
+ *&precomp[15] = t3 // 16
+
+ p256PointAddAsm(&t0, &t0, p)
+ p256PointAddAsm(&t1, &t1, p)
+ p256PointAddAsm(&t2, &t2, p)
+ *&precomp[2] = t0 // 3
+ *&precomp[4] = t1 // 5
+ *&precomp[8] = t2 // 9
+
+ p256PointDoubleAsm(&t0, &t0)
+ p256PointDoubleAsm(&t1, &t1)
+ *&precomp[5] = t0 // 6
+ *&precomp[9] = t1 // 10
+
+ p256PointAddAsm(&t2, &t0, p)
+ p256PointAddAsm(&t1, &t1, p)
+ *&precomp[6] = t2 // 7
+ *&precomp[10] = t1 // 11
+
+ p256PointDoubleAsm(&t0, &t0)
+ p256PointDoubleAsm(&t2, &t2)
+ *&precomp[11] = t0 // 12
+ *&precomp[13] = t2 // 14
+
+ p256PointAddAsm(&t0, &t0, p)
+ p256PointAddAsm(&t2, &t2, p)
+ *&precomp[12] = t0 // 13
+ *&precomp[14] = t2 // 15
+
+ // Start scanning the window from top bit
+ index := uint(254)
+ var sel, sign int
+
+ wvalue := (uint(scalar[31-index/8]) >> (index % 8)) & 0x3f
+ sel, _ = boothW5(uint(wvalue))
+ p256Select(p, precomp[:], sel)
+ zero := sel
+
+ for index > 4 {
+ index -= 5
+ p256PointDoubleAsm(p, p)
+ p256PointDoubleAsm(p, p)
+ p256PointDoubleAsm(p, p)
+ p256PointDoubleAsm(p, p)
+ p256PointDoubleAsm(p, p)
+
+ if index < 247 {
+ wvalue = ((uint(scalar[31-index/8]) >> (index % 8)) + (uint(scalar[31-index/8-1]) << (8 - (index % 8)))) & 0x3f
+ } else {
+ wvalue = (uint(scalar[31-index/8]) >> (index % 8)) & 0x3f
+ }
+
+ sel, sign = boothW5(uint(wvalue))
+
+ p256Select(&t0, precomp[:], sel)
+ p256NegCond(&t0, sign)
+ p256PointAddAsm(&t1, p, &t0)
+ p256MovCond(&t1, &t1, p, sel)
+ p256MovCond(p, &t1, &t0, zero)
+ zero |= sel
+ }
+
+ p256PointDoubleAsm(p, p)
+ p256PointDoubleAsm(p, p)
+ p256PointDoubleAsm(p, p)
+ p256PointDoubleAsm(p, p)
+ p256PointDoubleAsm(p, p)
+
+ wvalue = (uint(scalar[31]) << 1) & 0x3f
+ sel, sign = boothW5(uint(wvalue))
+
+ p256Select(&t0, precomp[:], sel)
+ p256NegCond(&t0, sign)
+ p256PointAddAsm(&t1, p, &t0)
+ p256MovCond(&t1, &t1, p, sel)
+ p256MovCond(p, &t1, &t0, zero)
+}
diff --git a/libgo/go/crypto/hmac/hmac.go b/libgo/go/crypto/hmac/hmac.go
index a7481078388..9ef9c448ee2 100644
--- a/libgo/go/crypto/hmac/hmac.go
+++ b/libgo/go/crypto/hmac/hmac.go
@@ -94,5 +94,5 @@ func Equal(mac1, mac2 []byte) bool {
// We don't have to be constant time if the lengths of the MACs are
// different as that suggests that a completely different hash function
// was used.
- return len(mac1) == len(mac2) && subtle.ConstantTimeCompare(mac1, mac2) == 1
+ return subtle.ConstantTimeCompare(mac1, mac2) == 1
}
diff --git a/libgo/go/crypto/internal/cipherhw/cipherhw_amd64.go b/libgo/go/crypto/internal/cipherhw/cipherhw_amd64.go
new file mode 100644
index 00000000000..be0d490a221
--- /dev/null
+++ b/libgo/go/crypto/internal/cipherhw/cipherhw_amd64.go
@@ -0,0 +1,16 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build amd64,!gccgo,!appengine
+
+package cipherhw
+
+// defined in asm_amd64.s
+func hasAESNI() bool
+
+// AESGCMSupport returns true if the Go standard library supports AES-GCM in
+// hardware.
+func AESGCMSupport() bool {
+ return hasAESNI()
+}
diff --git a/libgo/go/crypto/internal/cipherhw/cipherhw_s390x.go b/libgo/go/crypto/internal/cipherhw/cipherhw_s390x.go
new file mode 100644
index 00000000000..9cd76795985
--- /dev/null
+++ b/libgo/go/crypto/internal/cipherhw/cipherhw_s390x.go
@@ -0,0 +1,18 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build s390x,!gccgo,!appengine
+
+package cipherhw
+
+// hasHWSupport reports whether the AES-128, AES-192 and AES-256 cipher message
+// (KM) function codes are supported. Note that this function is expensive.
+// defined in asm_s390x.s
+func hasHWSupport() bool
+
+var hwSupport = hasHWSupport()
+
+func AESGCMSupport() bool {
+ return hwSupport
+}
diff --git a/libgo/go/crypto/internal/cipherhw/doc.go b/libgo/go/crypto/internal/cipherhw/doc.go
new file mode 100644
index 00000000000..a75fcf64962
--- /dev/null
+++ b/libgo/go/crypto/internal/cipherhw/doc.go
@@ -0,0 +1,7 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package cipherhw exposes common functions for detecting whether hardware
+// support for certain ciphers and authenticators is present.
+package cipherhw
diff --git a/libgo/go/crypto/internal/cipherhw/generic.go b/libgo/go/crypto/internal/cipherhw/generic.go
new file mode 100644
index 00000000000..64d90d3b41e
--- /dev/null
+++ b/libgo/go/crypto/internal/cipherhw/generic.go
@@ -0,0 +1,11 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !amd64,!s390x gccgo appengine
+
+package cipherhw
+
+func AESGCMSupport() bool {
+ return false
+}
diff --git a/libgo/go/crypto/rand/util_test.go b/libgo/go/crypto/rand/util_test.go
index 7b076896767..48a2c3fc0cb 100644
--- a/libgo/go/crypto/rand/util_test.go
+++ b/libgo/go/crypto/rand/util_test.go
@@ -7,7 +7,9 @@ package rand_test
import (
"crypto/rand"
"math/big"
+ mathrand "math/rand"
"testing"
+ "time"
)
// https://golang.org/issue/6849.
@@ -63,3 +65,10 @@ func TestIntNegativeMaxPanics(t *testing.T) {
b := new(big.Int).SetInt64(int64(-1))
testIntPanics(t, b)
}
+
+func BenchmarkPrime(b *testing.B) {
+ r := mathrand.New(mathrand.NewSource(time.Now().UnixNano()))
+ for i := 0; i < b.N; i++ {
+ rand.Prime(r, 1024)
+ }
+}
diff --git a/libgo/go/crypto/rsa/rsa.go b/libgo/go/crypto/rsa/rsa.go
index 594305631b8..1de4fcb473e 100644
--- a/libgo/go/crypto/rsa/rsa.go
+++ b/libgo/go/crypto/rsa/rsa.go
@@ -18,6 +18,8 @@
// with v1.5/OAEP and signing/verifying with v1.5/PSS. If one needs to abstract
// over the public-key primitive, the PrivateKey struct implements the
// Decrypter and Signer interfaces from the crypto package.
+//
+// The RSA operations in this package are not implemented using constant-time algorithms.
package rsa
import (
@@ -27,6 +29,7 @@ import (
"errors"
"hash"
"io"
+ "math"
"math/big"
)
@@ -214,6 +217,21 @@ func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey
return nil, errors.New("crypto/rsa: GenerateMultiPrimeKey: nprimes must be >= 2")
}
+ if bits < 64 {
+ primeLimit := float64(uint64(1) << uint(bits/nprimes))
+ // pi approximates the number of primes less than primeLimit
+ pi := primeLimit / (math.Log(primeLimit) - 1)
+ // Generated primes start with 11 (in binary) so we can only
+ // use a quarter of them.
+ pi /= 4
+ // Use a factor of two to ensure that key generation terminates
+ // in a reasonable amount of time.
+ pi /= 2
+ if pi <= float64(nprimes) {
+ return nil, errors.New("crypto/rsa: too few primes of given length to generate an RSA key")
+ }
+ }
+
primes := make([]*big.Int, nprimes)
NextSetOfPrimes:
@@ -268,9 +286,8 @@ NextSetOfPrimes:
g := new(big.Int)
priv.D = new(big.Int)
- y := new(big.Int)
e := big.NewInt(int64(priv.E))
- g.GCD(priv.D, y, e, totient)
+ g.GCD(priv.D, nil, e, totient)
if g.Cmp(bigOne) == 0 {
if priv.D.Sign() < 0 {
@@ -347,8 +364,8 @@ func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
// values could be used to ensure that a ciphertext for one purpose cannot be
// used for another by an attacker. If not required it can be empty.
//
-// The message must be no longer than the length of the public modulus less
-// twice the hash length plus 2.
+// The message must be no longer than the length of the public modulus minus
+// twice the hash length, minus a further 2.
func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error) {
if err := checkPub(pub); err != nil {
return nil, err
diff --git a/libgo/go/crypto/rsa/rsa_test.go b/libgo/go/crypto/rsa/rsa_test.go
index 6902f9a8673..84b167455f0 100644
--- a/libgo/go/crypto/rsa/rsa_test.go
+++ b/libgo/go/crypto/rsa/rsa_test.go
@@ -73,6 +73,17 @@ func TestNPrimeKeyGeneration(t *testing.T) {
}
}
+func TestImpossibleKeyGeneration(t *testing.T) {
+ // This test ensures that trying to generate toy RSA keys doesn't enter
+ // an infinite loop.
+ for i := 0; i < 32; i++ {
+ GenerateKey(rand.Reader, i)
+ GenerateMultiPrimeKey(rand.Reader, 3, i)
+ GenerateMultiPrimeKey(rand.Reader, 4, i)
+ GenerateMultiPrimeKey(rand.Reader, 5, i)
+ }
+}
+
func TestGnuTLSKey(t *testing.T) {
// This is a key generated by `certtool --generate-privkey --bits 128`.
// It's such that de ≢ 1 mod φ(n), but is congruent mod the order of
diff --git a/libgo/go/crypto/sha1/sha1.go b/libgo/go/crypto/sha1/sha1.go
index ac593b1bf0d..fbb2f946132 100644
--- a/libgo/go/crypto/sha1/sha1.go
+++ b/libgo/go/crypto/sha1/sha1.go
@@ -90,7 +90,7 @@ func (d0 *digest) Sum(in []byte) []byte {
func (d *digest) checkSum() [Size]byte {
len := d.len
- // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
+ // Padding. Add a 1 bit and 0 bits until 56 bytes mod 64.
var tmp [64]byte
tmp[0] = 0x80
if len%64 < 56 {
@@ -121,6 +121,74 @@ func (d *digest) checkSum() [Size]byte {
return digest
}
+// ConstantTimeSum computes the same result of Sum() but in constant time
+func (d0 *digest) ConstantTimeSum(in []byte) []byte {
+ d := *d0
+ hash := d.constSum()
+ return append(in, hash[:]...)
+}
+
+func (d *digest) constSum() [Size]byte {
+ var length [8]byte
+ l := d.len << 3
+ for i := uint(0); i < 8; i++ {
+ length[i] = byte(l >> (56 - 8*i))
+ }
+
+ nx := byte(d.nx)
+ t := nx - 56 // if nx < 56 then the MSB of t is one
+ mask1b := byte(int8(t) >> 7) // mask1b is 0xFF iff one block is enough
+
+ separator := byte(0x80) // gets reset to 0x00 once used
+ for i := byte(0); i < chunk; i++ {
+ mask := byte(int8(i-nx) >> 7) // 0x00 after the end of data
+
+ // if we reached the end of the data, replace with 0x80 or 0x00
+ d.x[i] = (^mask & separator) | (mask & d.x[i])
+
+ // zero the separator once used
+ separator &= mask
+
+ if i >= 56 {
+ // we might have to write the length here if all fit in one block
+ d.x[i] |= mask1b & length[i-56]
+ }
+ }
+
+ // compress, and only keep the digest if all fit in one block
+ block(d, d.x[:])
+
+ var digest [Size]byte
+ for i, s := range d.h {
+ digest[i*4] = mask1b & byte(s>>24)
+ digest[i*4+1] = mask1b & byte(s>>16)
+ digest[i*4+2] = mask1b & byte(s>>8)
+ digest[i*4+3] = mask1b & byte(s)
+ }
+
+ for i := byte(0); i < chunk; i++ {
+ // second block, it's always past the end of data, might start with 0x80
+ if i < 56 {
+ d.x[i] = separator
+ separator = 0
+ } else {
+ d.x[i] = length[i-56]
+ }
+ }
+
+ // compress, and only keep the digest if we actually needed the second block
+ block(d, d.x[:])
+
+ for i, s := range d.h {
+ digest[i*4] |= ^mask1b & byte(s>>24)
+ digest[i*4+1] |= ^mask1b & byte(s>>16)
+ digest[i*4+2] |= ^mask1b & byte(s>>8)
+ digest[i*4+3] |= ^mask1b & byte(s)
+ }
+
+ return digest
+}
+
// Sum returns the SHA1 checksum of the data.
func Sum(data []byte) [Size]byte {
var d digest
diff --git a/libgo/go/crypto/sha1/sha1_test.go b/libgo/go/crypto/sha1/sha1_test.go
index 214afc51e1f..3e59a5defe3 100644
--- a/libgo/go/crypto/sha1/sha1_test.go
+++ b/libgo/go/crypto/sha1/sha1_test.go
@@ -61,15 +61,24 @@ func TestGolden(t *testing.T) {
t.Fatalf("Sum function: sha1(%s) = %s want %s", g.in, s, g.out)
}
c := New()
- for j := 0; j < 3; j++ {
- if j < 2 {
+ for j := 0; j < 4; j++ {
+ var sum []byte
+ switch j {
+ case 0, 1:
io.WriteString(c, g.in)
- } else {
+ sum = c.Sum(nil)
+ case 2:
io.WriteString(c, g.in[0:len(g.in)/2])
c.Sum(nil)
io.WriteString(c, g.in[len(g.in)/2:])
+ sum = c.Sum(nil)
+ case 3:
+ io.WriteString(c, g.in[0:len(g.in)/2])
+ c.(*digest).ConstantTimeSum(nil)
+ io.WriteString(c, g.in[len(g.in)/2:])
+ sum = c.(*digest).ConstantTimeSum(nil)
}
- s := fmt.Sprintf("%x", c.Sum(nil))
+ s := fmt.Sprintf("%x", sum)
if s != g.out {
t.Fatalf("sha1[%d](%s) = %s want %s", j, g.in, s, g.out)
}
diff --git a/libgo/go/crypto/sha1/sha1block_amd64.go b/libgo/go/crypto/sha1/sha1block_amd64.go
index 95d89a755f8..8ef8b1faffc 100644
--- a/libgo/go/crypto/sha1/sha1block_amd64.go
+++ b/libgo/go/crypto/sha1/sha1block_amd64.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The Go Authors. All rights reserved.
+// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/libgo/go/crypto/sha256/example_test.go b/libgo/go/crypto/sha256/example_test.go
new file mode 100644
index 00000000000..89d5c977787
--- /dev/null
+++ b/libgo/go/crypto/sha256/example_test.go
@@ -0,0 +1,43 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package sha256_test
+
+import (
+ "crypto/sha256"
+ "fmt"
+ "io"
+ "log"
+ "os"
+)
+
+func ExampleSum256() {
+ sum := sha256.Sum256([]byte("hello world\n"))
+ fmt.Printf("%x", sum)
+ // Output: a948904f2f0f479b8f8197694b30184b0d2ed1c1cd2a1ec0fb85d299a192a447
+}
+
+func ExampleNew() {
+ h := sha256.New()
+ h.Write([]byte("hello world\n"))
+ fmt.Printf("%x", h.Sum(nil))
+ // Output: a948904f2f0f479b8f8197694b30184b0d2ed1c1cd2a1ec0fb85d299a192a447
+}
+
+func ExampleNew_file() {
+ f, err := os.Open("file.txt")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer f.Close()
+
+ h := sha256.New()
+ if _, err := io.Copy(h, f); err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Printf("%x", h.Sum(nil))
+}
diff --git a/libgo/go/crypto/sha256/sha256block_decl.go b/libgo/go/crypto/sha256/sha256block_decl.go
index eca42c245d8..e283c412c18 100644
--- a/libgo/go/crypto/sha256/sha256block_decl.go
+++ b/libgo/go/crypto/sha256/sha256block_decl.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build ignore
-// +build 386 amd64 s390x
+// +build 386 amd64 s390x ppc64le
package sha256
diff --git a/libgo/go/crypto/sha256/sha256block_generic.go b/libgo/go/crypto/sha256/sha256block_generic.go
index d7d78fd51b3..5cd022d2697 100644
--- a/libgo/go/crypto/sha256/sha256block_generic.go
+++ b/libgo/go/crypto/sha256/sha256block_generic.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// -build !amd64,!386,!s390x
+// -build !amd64,!386,!s390x,!ppc64le
package sha256
diff --git a/libgo/go/crypto/sha512/sha512block_decl.go b/libgo/go/crypto/sha512/sha512block_decl.go
index 1c8f66eb96b..3859a40e328 100644
--- a/libgo/go/crypto/sha512/sha512block_decl.go
+++ b/libgo/go/crypto/sha512/sha512block_decl.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build ignore
-// -build amd64 s390x
+// +build amd64 s390x ppc64le
package sha512
diff --git a/libgo/go/crypto/sha512/sha512block_generic.go b/libgo/go/crypto/sha512/sha512block_generic.go
index 67ac94812f0..fb2e6c6bf5d 100644
--- a/libgo/go/crypto/sha512/sha512block_generic.go
+++ b/libgo/go/crypto/sha512/sha512block_generic.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// -build !amd64,!s390x
+// -build !amd64,!s390x,!ppc64le
package sha512
diff --git a/libgo/go/crypto/tls/alert.go b/libgo/go/crypto/tls/alert.go
index 9cf99224f5d..49298682574 100644
--- a/libgo/go/crypto/tls/alert.go
+++ b/libgo/go/crypto/tls/alert.go
@@ -38,6 +38,7 @@ const (
alertInappropriateFallback alert = 86
alertUserCanceled alert = 90
alertNoRenegotiation alert = 100
+ alertNoApplicationProtocol alert = 120
)
var alertText = map[alert]string{
@@ -64,6 +65,7 @@ var alertText = map[alert]string{
alertInappropriateFallback: "inappropriate fallback",
alertUserCanceled: "user canceled",
alertNoRenegotiation: "no renegotiation",
+ alertNoApplicationProtocol: "no application protocol",
}
func (e alert) String() string {
diff --git a/libgo/go/crypto/tls/cipher_suites.go b/libgo/go/crypto/tls/cipher_suites.go
index e69f5f966e3..05146743acb 100644
--- a/libgo/go/crypto/tls/cipher_suites.go
+++ b/libgo/go/crypto/tls/cipher_suites.go
@@ -11,8 +11,11 @@ import (
"crypto/hmac"
"crypto/rc4"
"crypto/sha1"
+ "crypto/sha256"
"crypto/x509"
"hash"
+
+ "golang_org/x/crypto/chacha20poly1305"
)
// a keyAgreement implements the client and server side of a TLS key agreement
@@ -73,25 +76,32 @@ type cipherSuite struct {
}
var cipherSuites = []*cipherSuite{
- // Ciphersuite order is chosen so that ECDHE comes before plain RSA
- // and RC4 comes before AES-CBC (because of the Lucky13 attack).
+ // Ciphersuite order is chosen so that ECDHE comes before plain RSA and
+ // AEADs are the top preference.
+ {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadChaCha20Poly1305},
+ {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadChaCha20Poly1305},
{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
{TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
- {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteDefaultOff, cipherRC4, macSHA1, nil},
- {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteDefaultOff, cipherRC4, macSHA1, nil},
+ {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil},
{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
+ {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, cipherAES, macSHA256, nil},
{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
{TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
{TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
- {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteDefaultOff, cipherRC4, macSHA1, nil},
+ {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
+
+ // RC4-based cipher suites are disabled by default.
+ {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteDefaultOff, cipherRC4, macSHA1, nil},
+ {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteDefaultOff, cipherRC4, macSHA1, nil},
+ {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteDefaultOff, cipherRC4, macSHA1, nil},
}
func cipherRC4(key, iv []byte, isRead bool) interface{} {
@@ -125,35 +135,84 @@ func macSHA1(version uint16, key []byte) macFunction {
copy(mac.key, key)
return mac
}
- return tls10MAC{hmac.New(sha1.New, key)}
+ return tls10MAC{hmac.New(newConstantTimeHash(sha1.New), key)}
+}
+
+// macSHA256 returns a SHA-256 based MAC. These are only supported in TLS 1.2
+// so the given version is ignored.
+func macSHA256(version uint16, key []byte) macFunction {
+ return tls10MAC{hmac.New(sha256.New, key)}
}
type macFunction interface {
Size() int
- MAC(digestBuf, seq, header, data []byte) []byte
+ MAC(digestBuf, seq, header, data, extra []byte) []byte
+}
+
+type aead interface {
+ cipher.AEAD
+
+ // explicitIVLen returns the number of bytes used by the explicit nonce
+ // that is included in the record. This is eight for older AEADs and
+ // zero for modern ones.
+ explicitNonceLen() int
}
// fixedNonceAEAD wraps an AEAD and prefixes a fixed portion of the nonce to
// each call.
type fixedNonceAEAD struct {
- // sealNonce and openNonce are buffers where the larger nonce will be
- // constructed. Since a seal and open operation may be running
- // concurrently, there is a separate buffer for each.
- sealNonce, openNonce []byte
- aead cipher.AEAD
+ // nonce contains the fixed part of the nonce in the first four bytes.
+ nonce [12]byte
+ aead cipher.AEAD
}
-func (f *fixedNonceAEAD) NonceSize() int { return 8 }
-func (f *fixedNonceAEAD) Overhead() int { return f.aead.Overhead() }
+func (f *fixedNonceAEAD) NonceSize() int { return 8 }
+func (f *fixedNonceAEAD) Overhead() int { return f.aead.Overhead() }
+func (f *fixedNonceAEAD) explicitNonceLen() int { return 8 }
func (f *fixedNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte {
- copy(f.sealNonce[len(f.sealNonce)-8:], nonce)
- return f.aead.Seal(out, f.sealNonce, plaintext, additionalData)
+ copy(f.nonce[4:], nonce)
+ return f.aead.Seal(out, f.nonce[:], plaintext, additionalData)
}
func (f *fixedNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byte, error) {
- copy(f.openNonce[len(f.openNonce)-8:], nonce)
- return f.aead.Open(out, f.openNonce, plaintext, additionalData)
+ copy(f.nonce[4:], nonce)
+ return f.aead.Open(out, f.nonce[:], plaintext, additionalData)
+}
+
+// xoredNonceAEAD wraps an AEAD by XORing in a fixed pattern to the nonce
+// before each call.
+type xorNonceAEAD struct {
+ nonceMask [12]byte
+ aead cipher.AEAD
+}
+
+func (f *xorNonceAEAD) NonceSize() int { return 8 }
+func (f *xorNonceAEAD) Overhead() int { return f.aead.Overhead() }
+func (f *xorNonceAEAD) explicitNonceLen() int { return 0 }
+
+func (f *xorNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte {
+ for i, b := range nonce {
+ f.nonceMask[4+i] ^= b
+ }
+ result := f.aead.Seal(out, f.nonceMask[:], plaintext, additionalData)
+ for i, b := range nonce {
+ f.nonceMask[4+i] ^= b
+ }
+
+ return result
+}
+
+func (f *xorNonceAEAD) Open(out, nonce, plaintext, additionalData []byte) ([]byte, error) {
+ for i, b := range nonce {
+ f.nonceMask[4+i] ^= b
+ }
+ result, err := f.aead.Open(out, f.nonceMask[:], plaintext, additionalData)
+ for i, b := range nonce {
+ f.nonceMask[4+i] ^= b
+ }
+
+ return result, err
}
func aeadAESGCM(key, fixedNonce []byte) cipher.AEAD {
@@ -166,11 +225,20 @@ func aeadAESGCM(key, fixedNonce []byte) cipher.AEAD {
panic(err)
}
- nonce1, nonce2 := make([]byte, 12), make([]byte, 12)
- copy(nonce1, fixedNonce)
- copy(nonce2, fixedNonce)
+ ret := &fixedNonceAEAD{aead: aead}
+ copy(ret.nonce[:], fixedNonce)
+ return ret
+}
+
+func aeadChaCha20Poly1305(key, fixedNonce []byte) cipher.AEAD {
+ aead, err := chacha20poly1305.New(key)
+ if err != nil {
+ panic(err)
+ }
- return &fixedNonceAEAD{nonce1, nonce2, aead}
+ ret := &xorNonceAEAD{aead: aead}
+ copy(ret.nonceMask[:], fixedNonce)
+ return ret
}
// ssl30MAC implements the SSLv3 MAC function, as defined in
@@ -188,7 +256,9 @@ var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0
var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c}
-func (s ssl30MAC) MAC(digestBuf, seq, header, data []byte) []byte {
+// MAC does not offer constant timing guarantees for SSL v3.0, since it's deemed
+// useless considering the similar, protocol-level POODLE vulnerability.
+func (s ssl30MAC) MAC(digestBuf, seq, header, data, extra []byte) []byte {
padLength := 48
if s.h.Size() == 20 {
padLength = 40
@@ -210,6 +280,29 @@ func (s ssl30MAC) MAC(digestBuf, seq, header, data []byte) []byte {
return s.h.Sum(digestBuf[:0])
}
+type constantTimeHash interface {
+ hash.Hash
+ ConstantTimeSum(b []byte) []byte
+}
+
+// cthWrapper wraps any hash.Hash that implements ConstantTimeSum, and replaces
+// with that all calls to Sum. It's used to obtain a ConstantTimeSum-based HMAC.
+type cthWrapper struct {
+ h constantTimeHash
+}
+
+func (c *cthWrapper) Size() int { return c.h.Size() }
+func (c *cthWrapper) BlockSize() int { return c.h.BlockSize() }
+func (c *cthWrapper) Reset() { c.h.Reset() }
+func (c *cthWrapper) Write(p []byte) (int, error) { return c.h.Write(p) }
+func (c *cthWrapper) Sum(b []byte) []byte { return c.h.ConstantTimeSum(b) }
+
+func newConstantTimeHash(h func() hash.Hash) func() hash.Hash {
+ return func() hash.Hash {
+ return &cthWrapper{h().(constantTimeHash)}
+ }
+}
+
// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3.
type tls10MAC struct {
h hash.Hash
@@ -219,12 +312,19 @@ func (s tls10MAC) Size() int {
return s.h.Size()
}
-func (s tls10MAC) MAC(digestBuf, seq, header, data []byte) []byte {
+// MAC is guaranteed to take constant time, as long as
+// len(seq)+len(header)+len(data)+len(extra) is constant. extra is not fed into
+// the MAC, but is only provided to make the timing profile constant.
+func (s tls10MAC) MAC(digestBuf, seq, header, data, extra []byte) []byte {
s.h.Reset()
s.h.Write(seq)
s.h.Write(header)
s.h.Write(data)
- return s.h.Sum(digestBuf[:0])
+ res := s.h.Sum(digestBuf[:0])
+ if extra != nil {
+ s.h.Write(extra)
+ }
+ return res
}
func rsaKA(version uint16) keyAgreement {
@@ -270,6 +370,7 @@ const (
TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
+ TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003c
TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c
TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007
@@ -279,10 +380,14 @@ const (
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc023
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc027
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 uint16 = 0xcca8
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 uint16 = 0xcca9
// TLS_FALLBACK_SCSV isn't a standard cipher suite but an indicator
// that the client is doing version fallback. See
diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go
index 9fc74200820..276d1761ea0 100644
--- a/libgo/go/crypto/tls/common.go
+++ b/libgo/go/crypto/tls/common.go
@@ -7,6 +7,7 @@ package tls
import (
"container/list"
"crypto"
+ "crypto/internal/cipherhw"
"crypto/rand"
"crypto/sha512"
"crypto/x509"
@@ -14,6 +15,7 @@ import (
"fmt"
"io"
"math/big"
+ "net"
"strings"
"sync"
"time"
@@ -95,6 +97,7 @@ const (
CurveP256 CurveID = 23
CurveP384 CurveID = 24
CurveP521 CurveID = 25
+ X25519 CurveID = 29
)
// TLS Elliptic Curve Point Formats
@@ -213,6 +216,25 @@ type ClientSessionCache interface {
Put(sessionKey string, cs *ClientSessionState)
}
+// SignatureScheme identifies a signature algorithm supported by TLS. See
+// https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.3.
+type SignatureScheme uint16
+
+const (
+ PKCS1WithSHA1 SignatureScheme = 0x0201
+ PKCS1WithSHA256 SignatureScheme = 0x0401
+ PKCS1WithSHA384 SignatureScheme = 0x0501
+ PKCS1WithSHA512 SignatureScheme = 0x0601
+
+ PSSWithSHA256 SignatureScheme = 0x0804
+ PSSWithSHA384 SignatureScheme = 0x0805
+ PSSWithSHA512 SignatureScheme = 0x0806
+
+ ECDSAWithP256AndSHA256 SignatureScheme = 0x0403
+ ECDSAWithP384AndSHA384 SignatureScheme = 0x0503
+ ECDSAWithP521AndSHA512 SignatureScheme = 0x0603
+)
+
// ClientHelloInfo contains information from a ClientHello message in order to
// guide certificate selection in the GetCertificate callback.
type ClientHelloInfo struct {
@@ -237,6 +259,47 @@ type ClientHelloInfo struct {
// is being used (see
// http://tools.ietf.org/html/rfc4492#section-5.1.2).
SupportedPoints []uint8
+
+ // SignatureSchemes lists the signature and hash schemes that the client
+ // is willing to verify. SignatureSchemes is set only if the Signature
+ // Algorithms Extension is being used (see
+ // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1).
+ SignatureSchemes []SignatureScheme
+
+ // SupportedProtos lists the application protocols supported by the client.
+ // SupportedProtos is set only if the Application-Layer Protocol
+ // Negotiation Extension is being used (see
+ // https://tools.ietf.org/html/rfc7301#section-3.1).
+ //
+ // Servers can select a protocol by setting Config.NextProtos in a
+ // GetConfigForClient return value.
+ SupportedProtos []string
+
+ // SupportedVersions lists the TLS versions supported by the client.
+ // For TLS versions less than 1.3, this is extrapolated from the max
+ // version advertised by the client, so values other than the greatest
+ // might be rejected if used.
+ SupportedVersions []uint16
+
+ // Conn is the underlying net.Conn for the connection. Do not read
+ // from, or write to, this connection; that will cause the TLS
+ // connection to fail.
+ Conn net.Conn
+}
+
+// CertificateRequestInfo contains information from a server's
+// CertificateRequest message, which is used to demand a certificate and proof
+// of control from a client.
+type CertificateRequestInfo struct {
+ // AcceptableCAs contains zero or more, DER-encoded, X.501
+ // Distinguished Names. These are the names of root or intermediate CAs
+ // that the server wishes the returned certificate to be signed by. An
+ // empty slice indicates that the server has no preference.
+ AcceptableCAs [][]byte
+
+ // SignatureSchemes lists the signature schemes that the server is
+ // willing to verify.
+ SignatureSchemes []SignatureScheme
}
// RenegotiationSupport enumerates the different levels of support for TLS
@@ -281,10 +344,11 @@ type Config struct {
// If Time is nil, TLS uses time.Now.
Time func() time.Time
- // Certificates contains one or more certificate chains
- // to present to the other side of the connection.
- // Server configurations must include at least one certificate
- // or else set GetCertificate.
+ // Certificates contains one or more certificate chains to present to
+ // the other side of the connection. Server configurations must include
+ // at least one certificate or else set GetCertificate. Clients doing
+ // client-authentication may set either Certificates or
+ // GetClientCertificate.
Certificates []Certificate
// NameToCertificate maps from a certificate name to an element of
@@ -302,7 +366,54 @@ type Config struct {
// 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)
+ GetCertificate func(*ClientHelloInfo) (*Certificate, error)
+
+ // GetClientCertificate, if not nil, is called when a server requests a
+ // certificate from a client. If set, the contents of Certificates will
+ // be ignored.
+ //
+ // If GetClientCertificate returns an error, the handshake will be
+ // aborted and that error will be returned. Otherwise
+ // GetClientCertificate must return a non-nil Certificate. If
+ // Certificate.Certificate is empty then no certificate will be sent to
+ // the server. If this is unacceptable to the server then it may abort
+ // the handshake.
+ //
+ // GetClientCertificate may be called multiple times for the same
+ // connection if renegotiation occurs or if TLS 1.3 is in use.
+ GetClientCertificate func(*CertificateRequestInfo) (*Certificate, error)
+
+ // GetConfigForClient, if not nil, is called after a ClientHello is
+ // received from a client. It may return a non-nil Config in order to
+ // change the Config that will be used to handle this connection. If
+ // the returned Config is nil, the original Config will be used. The
+ // Config returned by this callback may not be subsequently modified.
+ //
+ // If GetConfigForClient is nil, the Config passed to Server() will be
+ // used for all connections.
+ //
+ // Uniquely for the fields in the returned Config, session ticket keys
+ // will be duplicated from the original Config if not set.
+ // Specifically, if SetSessionTicketKeys was called on the original
+ // config but not on the returned config then the ticket keys from the
+ // original config will be copied into the new config before use.
+ // Otherwise, if SessionTicketKey was set in the original config but
+ // not in the returned config then it will be copied into the returned
+ // config before use. If neither of those cases applies then the key
+ // material from the returned config will be used for session tickets.
+ GetConfigForClient func(*ClientHelloInfo) (*Config, error)
+
+ // VerifyPeerCertificate, if not nil, is called after normal
+ // certificate verification by either a TLS client or server. It
+ // receives the raw ASN.1 certificates provided by the peer and also
+ // any verified chains that normal processing found. If it returns a
+ // non-nil error, the handshake is aborted and that error results.
+ //
+ // If normal verification fails then the handshake will abort before
+ // considering this callback. If normal verification is disabled by
+ // setting InsecureSkipVerify then this callback will be considered but
+ // the verifiedChains argument will always be nil.
+ VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
// RootCAs defines the set of root certificate authorities
// that clients use when verifying server certificates.
@@ -387,15 +498,27 @@ type Config struct {
// The default, none, is correct for the vast majority of applications.
Renegotiation RenegotiationSupport
+ // KeyLogWriter optionally specifies a destination for TLS master secrets
+ // in NSS key log format that can be used to allow external programs
+ // such as Wireshark to decrypt TLS connections.
+ // See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format.
+ // Use of KeyLogWriter compromises security and should only be
+ // used for debugging.
+ KeyLogWriter io.Writer
+
serverInitOnce sync.Once // guards calling (*Config).serverInit
- // mutex protects sessionTicketKeys
+ // mutex protects sessionTicketKeys and originalConfig.
mutex sync.RWMutex
// sessionTicketKeys contains zero or more ticket keys. If the length
// is zero, SessionTicketsDisabled must be true. The first key is used
// for new tickets and any subsequent keys can be used to decrypt old
// tickets.
sessionTicketKeys []ticketKey
+ // originalConfig is set to the Config that was passed to Server if
+ // this Config is returned by a GetConfigForClient callback. It's used
+ // by serverInit in order to copy session ticket keys if needed.
+ originalConfig *Config
}
// ticketKeyNameLen is the number of bytes of identifier that is prepended to
@@ -422,14 +545,26 @@ func ticketKeyFromBytes(b [32]byte) (key ticketKey) {
return key
}
-// clone returns a copy of c. Only the exported fields are copied.
-func (c *Config) clone() *Config {
+// Clone returns a shallow clone of c. It is safe to clone a Config that is
+// being used concurrently by a TLS client or server.
+func (c *Config) Clone() *Config {
+ // Running serverInit ensures that it's safe to read
+ // SessionTicketsDisabled.
+ c.serverInitOnce.Do(c.serverInit)
+
+ var sessionTicketKeys []ticketKey
+ c.mutex.RLock()
+ sessionTicketKeys = c.sessionTicketKeys
+ c.mutex.RUnlock()
+
return &Config{
Rand: c.Rand,
Time: c.Time,
Certificates: c.Certificates,
NameToCertificate: c.NameToCertificate,
GetCertificate: c.GetCertificate,
+ GetConfigForClient: c.GetConfigForClient,
+ VerifyPeerCertificate: c.VerifyPeerCertificate,
RootCAs: c.RootCAs,
NextProtos: c.NextProtos,
ServerName: c.ServerName,
@@ -446,14 +581,22 @@ func (c *Config) clone() *Config {
CurvePreferences: c.CurvePreferences,
DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
Renegotiation: c.Renegotiation,
+ KeyLogWriter: c.KeyLogWriter,
+ sessionTicketKeys: sessionTicketKeys,
+ // originalConfig is deliberately not duplicated.
}
}
func (c *Config) serverInit() {
- if c.SessionTicketsDisabled {
+ if c.SessionTicketsDisabled || len(c.ticketKeys()) != 0 {
return
}
+ var originalConfig *Config
+ c.mutex.Lock()
+ originalConfig, c.originalConfig = c.originalConfig, nil
+ c.mutex.Unlock()
+
alreadySet := false
for _, b := range c.SessionTicketKey {
if b != 0 {
@@ -463,13 +606,21 @@ func (c *Config) serverInit() {
}
if !alreadySet {
- if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil {
+ if originalConfig != nil {
+ copy(c.SessionTicketKey[:], originalConfig.SessionTicketKey[:])
+ } else if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil {
c.SessionTicketsDisabled = true
return
}
}
- c.sessionTicketKeys = []ticketKey{ticketKeyFromBytes(c.SessionTicketKey)}
+ if originalConfig != nil {
+ originalConfig.mutex.RLock()
+ c.sessionTicketKeys = originalConfig.sessionTicketKeys
+ originalConfig.mutex.RUnlock()
+ } else {
+ c.sessionTicketKeys = []ticketKey{ticketKeyFromBytes(c.SessionTicketKey)}
+ }
}
func (c *Config) ticketKeys() []ticketKey {
@@ -539,7 +690,7 @@ func (c *Config) maxVersion() uint16 {
return c.MaxVersion
}
-var defaultCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521}
+var defaultCurvePreferences = []CurveID{X25519, CurveP256, CurveP384, CurveP521}
func (c *Config) curvePreferences() []CurveID {
if c == nil || len(c.CurvePreferences) == 0 {
@@ -627,6 +778,26 @@ func (c *Config) BuildNameToCertificate() {
}
}
+// writeKeyLog logs client random and master secret if logging was enabled by
+// setting c.KeyLogWriter.
+func (c *Config) writeKeyLog(clientRandom, masterSecret []byte) error {
+ if c.KeyLogWriter == nil {
+ return nil
+ }
+
+ logLine := []byte(fmt.Sprintf("CLIENT_RANDOM %x %x\n", clientRandom, masterSecret))
+
+ writerMutex.Lock()
+ _, err := c.KeyLogWriter.Write(logLine)
+ writerMutex.Unlock()
+
+ return err
+}
+
+// writerMutex protects all KeyLogWriters globally. It is rarely enabled,
+// and is only for debugging, so a global mutex saves space.
+var writerMutex sync.Mutex
+
// A Certificate is a chain of one or more certificates, leaf first.
type Certificate struct {
Certificate [][]byte
@@ -749,11 +920,46 @@ func defaultCipherSuites() []uint16 {
}
func initDefaultCipherSuites() {
+ var topCipherSuites []uint16
+ if cipherhw.AESGCMSupport() {
+ // If AES-GCM hardware is provided then prioritise AES-GCM
+ // cipher suites.
+ topCipherSuites = []uint16{
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+ }
+ } else {
+ // Without AES-GCM hardware, we put the ChaCha20-Poly1305
+ // cipher suites first.
+ topCipherSuites = []uint16{
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ }
+ }
+
varDefaultCipherSuites = make([]uint16, 0, len(cipherSuites))
+ for _, topCipher := range topCipherSuites {
+ varDefaultCipherSuites = append(varDefaultCipherSuites, topCipher)
+ }
+
+NextCipherSuite:
for _, suite := range cipherSuites {
if suite.flags&suiteDefaultOff != 0 {
continue
}
+ for _, existing := range varDefaultCipherSuites {
+ if existing == suite.id {
+ continue NextCipherSuite
+ }
+ }
varDefaultCipherSuites = append(varDefaultCipherSuites, suite.id)
}
}
diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go
index 87bef23d91f..03895a723fa 100644
--- a/libgo/go/crypto/tls/conn.go
+++ b/libgo/go/crypto/tls/conn.go
@@ -29,11 +29,15 @@ 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
- // handshakeComplete is true if the connection is currently transfering
+ // handshakeCond, if not nil, indicates that a goroutine is committed
+ // to running the handshake for this Conn. Other goroutines that need
+ // to wait for the handshake can wait on this, under handshakeMutex.
+ handshakeCond *sync.Cond
+ handshakeErr error // error resulting from handshake
+ vers uint16 // TLS version
+ haveVers bool // version has been negotiated
+ config *Config // configuration passed to constructor
+ // handshakeComplete is true if the connection is currently transferring
// application data (i.e. is not currently processing a handshake).
handshakeComplete bool
// handshakes counts the number of handshakes performed on the
@@ -60,6 +64,13 @@ type Conn struct {
// the first transmitted Finished message is the tls-unique
// channel-binding value.
clientFinishedIsFirst bool
+
+ // closeNotifyErr is any error from sending the alertCloseNotify record.
+ closeNotifyErr error
+ // closeNotifySent is true if the Conn attempted to send an
+ // alertCloseNotify record.
+ closeNotifySent bool
+
// clientFinished and serverFinished contain the Finished message sent
// by the client or server in the most recent handshake. This is
// retained to support the renegotiation extension and tls-unique
@@ -189,18 +200,18 @@ func (hc *halfConn) incSeq() {
panic("TLS: sequence number wraparound")
}
-// removePadding returns an unpadded slice, in constant time, which is a prefix
-// of the input. It also returns a byte which is equal to 255 if the padding
-// was valid and 0 otherwise. See RFC 2246, section 6.2.3.2
-func removePadding(payload []byte) ([]byte, byte) {
+// extractPadding returns, in constant time, the length of the padding to remove
+// from the end of payload. It also returns a byte which is equal to 255 if the
+// padding was valid and 0 otherwise. See RFC 2246, section 6.2.3.2
+func extractPadding(payload []byte) (toRemove int, good byte) {
if len(payload) < 1 {
- return payload, 0
+ return 0, 0
}
paddingLen := payload[len(payload)-1]
t := uint(len(payload)-1) - uint(paddingLen)
// if len(payload) >= (paddingLen - 1) then the MSB of t is zero
- good := byte(int32(^t) >> 31)
+ good = byte(int32(^t) >> 31)
toCheck := 255 // the maximum possible padding length
// The length of the padded data is public, so we can use an if here
@@ -223,24 +234,24 @@ func removePadding(payload []byte) ([]byte, byte) {
good &= good << 1
good = uint8(int8(good) >> 7)
- toRemove := good&paddingLen + 1
- return payload[:len(payload)-int(toRemove)], good
+ toRemove = int(paddingLen) + 1
+ return
}
-// removePaddingSSL30 is a replacement for removePadding in the case that the
+// extractPaddingSSL30 is a replacement for extractPadding in the case that the
// protocol version is SSLv3. In this version, the contents of the padding
// are random and cannot be checked.
-func removePaddingSSL30(payload []byte) ([]byte, byte) {
+func extractPaddingSSL30(payload []byte) (toRemove int, good byte) {
if len(payload) < 1 {
- return payload, 0
+ return 0, 0
}
paddingLen := int(payload[len(payload)-1]) + 1
if paddingLen > len(payload) {
- return payload, 0
+ return 0, 0
}
- return payload[:len(payload)-paddingLen], 255
+ return paddingLen, 255
}
func roundUp(a, b int) int {
@@ -266,6 +277,7 @@ func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert)
}
paddingGood := byte(255)
+ paddingLen := 0
explicitIVLen := 0
// decrypt
@@ -273,13 +285,17 @@ func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert)
switch c := hc.cipher.(type) {
case cipher.Stream:
c.XORKeyStream(payload, payload)
- case cipher.AEAD:
- explicitIVLen = 8
+ case aead:
+ explicitIVLen = c.explicitNonceLen()
if len(payload) < explicitIVLen {
return false, 0, alertBadRecordMAC
}
- nonce := payload[:8]
- payload = payload[8:]
+ nonce := payload[:explicitIVLen]
+ payload = payload[explicitIVLen:]
+
+ if len(nonce) == 0 {
+ nonce = hc.seq[:]
+ }
copy(hc.additionalData[:], hc.seq[:])
copy(hc.additionalData[8:], b.data[:3])
@@ -308,22 +324,17 @@ func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert)
}
c.CryptBlocks(payload, payload)
if hc.version == VersionSSL30 {
- payload, paddingGood = removePaddingSSL30(payload)
+ paddingLen, paddingGood = extractPaddingSSL30(payload)
} else {
- payload, paddingGood = removePadding(payload)
+ paddingLen, paddingGood = extractPadding(payload)
+
+ // To protect against CBC padding oracles like Lucky13, the data
+ // past paddingLen (which is secret) is passed to the MAC
+ // function as extra data, to be fed into the HMAC after
+ // computing the digest. This makes the MAC constant time as
+ // long as the digest computation is constant time and does not
+ // affect the subsequent write.
}
- b.resize(recordHeaderLen + explicitIVLen + len(payload))
-
- // note that we still have a timing side-channel in the
- // MAC check, below. An attacker can align the record
- // so that a correct padding will cause one less hash
- // block to be calculated. Then they can iteratively
- // decrypt a record by breaking each byte. See
- // "Password Interception in a SSL/TLS Channel", Brice
- // Canvel et al.
- //
- // However, our behavior matches OpenSSL, so we leak
- // only as much as they do.
default:
panic("unknown cipher type")
}
@@ -336,17 +347,19 @@ func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert)
}
// strip mac off payload, b.data
- n := len(payload) - macSize
+ n := len(payload) - macSize - paddingLen
+ n = subtle.ConstantTimeSelect(int(uint32(n)>>31), 0, n) // if n < 0 { n = 0 }
b.data[3] = byte(n >> 8)
b.data[4] = byte(n)
- b.resize(recordHeaderLen + explicitIVLen + n)
- remoteMAC := payload[n:]
- localMAC := hc.mac.MAC(hc.inDigestBuf, hc.seq[0:], b.data[:recordHeaderLen], payload[:n])
+ remoteMAC := payload[n : n+macSize]
+ localMAC := hc.mac.MAC(hc.inDigestBuf, hc.seq[0:], b.data[:recordHeaderLen], payload[:n], payload[n+macSize:])
if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 {
return false, 0, alertBadRecordMAC
}
hc.inDigestBuf = localMAC
+
+ b.resize(recordHeaderLen + explicitIVLen + n)
}
hc.incSeq()
@@ -374,7 +387,7 @@ func padToBlockSize(payload []byte, blockSize int) (prefix, finalBlock []byte) {
func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
// mac
if hc.mac != nil {
- mac := hc.mac.MAC(hc.outDigestBuf, hc.seq[0:], b.data[:recordHeaderLen], b.data[recordHeaderLen+explicitIVLen:])
+ mac := hc.mac.MAC(hc.outDigestBuf, hc.seq[0:], b.data[:recordHeaderLen], b.data[recordHeaderLen+explicitIVLen:], nil)
n := len(b.data)
b.resize(n + len(mac))
@@ -389,10 +402,13 @@ func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
switch c := hc.cipher.(type) {
case cipher.Stream:
c.XORKeyStream(payload, payload)
- case cipher.AEAD:
+ case aead:
payloadLen := len(b.data) - recordHeaderLen - explicitIVLen
b.resize(len(b.data) + c.Overhead())
nonce := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
+ if len(nonce) == 0 {
+ nonce = hc.seq[:]
+ }
payload := b.data[recordHeaderLen+explicitIVLen:]
payload = payload[:payloadLen]
@@ -628,9 +644,10 @@ Again:
// Process message.
b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
- ok, off, err := c.in.decrypt(b)
+ ok, off, alertValue := c.in.decrypt(b)
if !ok {
- c.in.setErrorLocked(c.sendAlert(err))
+ c.in.freeBlock(b)
+ return c.in.setErrorLocked(c.sendAlert(alertValue))
}
b.off = off
data := b.data[b.off:]
@@ -849,15 +866,16 @@ func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) {
}
}
if explicitIVLen == 0 {
- if _, ok := c.out.cipher.(cipher.AEAD); ok {
- explicitIVLen = 8
+ if c, ok := c.out.cipher.(aead); ok {
+ explicitIVLen = c.explicitNonceLen()
+
// The AES-GCM construction in TLS has an
// explicit nonce so that the nonce can be
// random. However, the nonce is only 8 bytes
// which is too small for a secure, random
// nonce. Therefore we use the sequence number
// as the nonce.
- explicitIVIsSeq = true
+ explicitIVIsSeq = explicitIVLen > 0
}
}
m := len(data)
@@ -978,7 +996,7 @@ func (c *Conn) readHandshake() (interface{}, error) {
return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
}
- // The handshake message unmarshallers
+ // The handshake message unmarshalers
// expect to be able to keep references to data,
// so pass in a fresh copy that won't be overwritten.
data = append([]byte(nil), data...)
@@ -989,7 +1007,10 @@ func (c *Conn) readHandshake() (interface{}, error) {
return m, nil
}
-var errClosed = errors.New("tls: use of closed connection")
+var (
+ errClosed = errors.New("tls: use of closed connection")
+ errShutdown = errors.New("tls: protocol is shutdown")
+)
// Write writes data to the connection.
func (c *Conn) Write(b []byte) (int, error) {
@@ -1020,6 +1041,10 @@ func (c *Conn) Write(b []byte) (int, error) {
return 0, alertInternalError
}
+ if c.closeNotifySent {
+ return 0, errShutdown
+ }
+
// SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext
// attack when using block mode ciphers due to predictable IVs.
// This can be prevented by splitting each Application Data
@@ -1183,7 +1208,7 @@ func (c *Conn) Close() error {
c.handshakeMutex.Lock()
defer c.handshakeMutex.Unlock()
if c.handshakeComplete {
- alertErr = c.sendAlert(alertCloseNotify)
+ alertErr = c.closeNotify()
}
if err := c.conn.Close(); err != nil {
@@ -1192,6 +1217,32 @@ func (c *Conn) Close() error {
return alertErr
}
+var errEarlyCloseWrite = errors.New("tls: CloseWrite called before handshake complete")
+
+// CloseWrite shuts down the writing side of the connection. It should only be
+// called once the handshake has completed and does not call CloseWrite on the
+// underlying connection. Most callers should just use Close.
+func (c *Conn) CloseWrite() error {
+ c.handshakeMutex.Lock()
+ defer c.handshakeMutex.Unlock()
+ if !c.handshakeComplete {
+ return errEarlyCloseWrite
+ }
+
+ return c.closeNotify()
+}
+
+func (c *Conn) closeNotify() error {
+ c.out.Lock()
+ defer c.out.Unlock()
+
+ if !c.closeNotifySent {
+ c.closeNotifyErr = c.sendAlertLocked(alertCloseNotify)
+ c.closeNotifySent = true
+ }
+ return c.closeNotifyErr
+}
+
// Handshake runs the client or server handshake
// protocol if it has not yet been run.
// Most uses of this package need not call Handshake
@@ -1206,26 +1257,50 @@ func (c *Conn) Handshake() error {
// need to check whether a handshake is pending (such as Write) to
// block.
//
- // Thus we take c.handshakeMutex first and, if we find that a handshake
- // is needed, then we unlock, acquire c.in and c.handshakeMutex in the
- // correct order, and check again.
+ // Thus we first take c.handshakeMutex to check whether a handshake is
+ // needed.
+ //
+ // If so then, previously, this code would unlock handshakeMutex and
+ // then lock c.in and handshakeMutex in the correct order to run the
+ // handshake. The problem was that it was possible for a Read to
+ // complete the handshake once handshakeMutex was unlocked and then
+ // keep c.in while waiting for network data. Thus a concurrent
+ // operation could be blocked on c.in.
+ //
+ // Thus handshakeCond is used to signal that a goroutine is committed
+ // to running the handshake and other goroutines can wait on it if they
+ // need. handshakeCond is protected by handshakeMutex.
c.handshakeMutex.Lock()
defer c.handshakeMutex.Unlock()
- for i := 0; i < 2; i++ {
- if i == 1 {
- c.handshakeMutex.Unlock()
- c.in.Lock()
- defer c.in.Unlock()
- c.handshakeMutex.Lock()
- }
-
+ for {
if err := c.handshakeErr; err != nil {
return err
}
if c.handshakeComplete {
return nil
}
+ if c.handshakeCond == nil {
+ break
+ }
+
+ c.handshakeCond.Wait()
+ }
+
+ // Set handshakeCond to indicate that this goroutine is committing to
+ // running the handshake.
+ c.handshakeCond = sync.NewCond(&c.handshakeMutex)
+ c.handshakeMutex.Unlock()
+
+ c.in.Lock()
+ defer c.in.Unlock()
+
+ c.handshakeMutex.Lock()
+
+ // The handshake cannot have completed when handshakeMutex was unlocked
+ // because this goroutine set handshakeCond.
+ if c.handshakeErr != nil || c.handshakeComplete {
+ panic("handshake should not have been able to complete after handshakeCond was set")
}
if c.isClient {
@@ -1235,7 +1310,21 @@ func (c *Conn) Handshake() error {
}
if c.handshakeErr == nil {
c.handshakes++
+ } else {
+ // If an error occurred during the hadshake try to flush the
+ // alert that might be left in the buffer.
+ c.flush()
+ }
+
+ if c.handshakeErr == nil && !c.handshakeComplete {
+ panic("handshake should have had a result.")
}
+
+ // Wake any other goroutines that are waiting for this handshake to
+ // complete.
+ c.handshakeCond.Broadcast()
+ c.handshakeCond = nil
+
return c.handshakeErr
}
@@ -1246,6 +1335,8 @@ func (c *Conn) ConnectionState() ConnectionState {
var state ConnectionState
state.HandshakeComplete = c.handshakeComplete
+ state.ServerName = c.serverName
+
if c.handshakeComplete {
state.Version = c.vers
state.NegotiatedProtocol = c.clientProtocol
@@ -1254,7 +1345,6 @@ func (c *Conn) ConnectionState() ConnectionState {
state.CipherSuite = c.cipherSuite
state.PeerCertificates = c.peerCertificates
state.VerifiedChains = c.verifiedChains
- state.ServerName = c.serverName
state.SignedCertificateTimestamps = c.scts
state.OCSPResponse = c.ocspResponse
if !c.didResume {
diff --git a/libgo/go/crypto/tls/conn_test.go b/libgo/go/crypto/tls/conn_test.go
index 5cff7e7cdd4..5e5c7a2e96e 100644
--- a/libgo/go/crypto/tls/conn_test.go
+++ b/libgo/go/crypto/tls/conn_test.go
@@ -40,7 +40,7 @@ var paddingTests = []struct {
func TestRemovePadding(t *testing.T) {
for i, test := range paddingTests {
- payload, good := removePadding(test.in)
+ paddingLen, good := extractPadding(test.in)
expectedGood := byte(255)
if !test.good {
expectedGood = 0
@@ -48,19 +48,19 @@ func TestRemovePadding(t *testing.T) {
if good != expectedGood {
t.Errorf("#%d: wrong validity, want:%d got:%d", i, expectedGood, good)
}
- if good == 255 && len(payload) != test.expectedLen {
- t.Errorf("#%d: got %d, want %d", i, len(payload), test.expectedLen)
+ if good == 255 && len(test.in)-paddingLen != test.expectedLen {
+ t.Errorf("#%d: got %d, want %d", i, len(test.in)-paddingLen, test.expectedLen)
}
}
}
-var certExampleCom = `308201403081eda003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313138353835325a170d3132303933303138353835325a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31a301830160603551d11040f300d820b6578616d706c652e636f6d300b06092a864886f70d0101050341001a0b419d2c74474c6450654e5f10b32bf426ffdf55cad1c52602e7a9151513a3424c70f5960dcd682db0c33769cc1daa3fcdd3db10809d2392ed4a1bf50ced18`
+var certExampleCom = `308201713082011ba003020102021005a75ddf21014d5f417083b7a010ba2e300d06092a864886f70d01010b050030123110300e060355040a130741636d6520436f301e170d3136303831373231343135335a170d3137303831373231343135335a30123110300e060355040a130741636d6520436f305c300d06092a864886f70d0101010500034b003048024100b37f0fdd67e715bf532046ac34acbd8fdc4dabe2b598588f3f58b1f12e6219a16cbfe54d2b4b665396013589262360b6721efa27d546854f17cc9aeec6751db10203010001a34d304b300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff0402300030160603551d11040f300d820b6578616d706c652e636f6d300d06092a864886f70d01010b050003410059fc487866d3d855503c8e064ca32aac5e9babcece89ec597f8b2b24c17867f4a5d3b4ece06e795bfc5448ccbd2ffca1b3433171ebf3557a4737b020565350a0`
-var certWildcardExampleCom = `308201423081efa003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313139303034365a170d3132303933303139303034365a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31c301a30180603551d110411300f820d2a2e6578616d706c652e636f6d300b06092a864886f70d0101050341001676f0c9e7c33c1b656ed5a6476c4e2ee9ec8e62df7407accb1875272b2edd0a22096cb2c22598d11604104d604f810eb4b5987ca6bb319c7e6ce48725c54059`
+var certWildcardExampleCom = `308201743082011ea003020102021100a7aa6297c9416a4633af8bec2958c607300d06092a864886f70d01010b050030123110300e060355040a130741636d6520436f301e170d3136303831373231343231395a170d3137303831373231343231395a30123110300e060355040a130741636d6520436f305c300d06092a864886f70d0101010500034b003048024100b105afc859a711ee864114e7d2d46c2dcbe392d3506249f6c2285b0eb342cc4bf2d803677c61c0abde443f084745c1a6d62080e5664ef2cc8f50ad8a0ab8870b0203010001a34f304d300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff0402300030180603551d110411300f820d2a2e6578616d706c652e636f6d300d06092a864886f70d01010b0500034100af26088584d266e3f6566360cf862c7fecc441484b098b107439543144a2b93f20781988281e108c6d7656934e56950e1e5f2bcf38796b814ccb729445856c34`
-var certFooExampleCom = `308201443081f1a003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313139303131345a170d3132303933303139303131345a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31e301c301a0603551d1104133011820f666f6f2e6578616d706c652e636f6d300b06092a864886f70d010105034100646a2a51f2aa2477add854b462cf5207ba16d3213ffb5d3d0eed473fbf09935019192d1d5b8ca6a2407b424cf04d97c4cd9197c83ecf81f0eab9464a1109d09f`
+var certFooExampleCom = `308201753082011fa00302010202101bbdb6070b0aeffc49008cde74deef29300d06092a864886f70d01010b050030123110300e060355040a130741636d6520436f301e170d3136303831373231343234345a170d3137303831373231343234345a30123110300e060355040a130741636d6520436f305c300d06092a864886f70d0101010500034b003048024100f00ac69d8ca2829f26216c7b50f1d4bbabad58d447706476cd89a2f3e1859943748aa42c15eedc93ac7c49e40d3b05ed645cb6b81c4efba60d961f44211a54eb0203010001a351304f300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff04023000301a0603551d1104133011820f666f6f2e6578616d706c652e636f6d300d06092a864886f70d01010b0500034100a0957fca6d1e0f1ef4b247348c7a8ca092c29c9c0ecc1898ea6b8065d23af6d922a410dd2335a0ea15edd1394cef9f62c9e876a21e35250a0b4fe1ddceba0f36`
-var certDoubleWildcardExampleCom = `308201443081f1a003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313139303134315a170d3132303933303139303134315a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31e301c301a0603551d1104133011820f2a2e2a2e6578616d706c652e636f6d300b06092a864886f70d0101050341001c3de267975f56ef57771c6218ef95ecc65102e57bd1defe6f7efea90d9b26cf40de5bd7ad75e46201c7f2a92aaa3e907451e9409f65e28ddb6db80d726290f6`
+var certDoubleWildcardExampleCom = `308201753082011fa003020102021039d262d8538db8ffba30d204e02ddeb5300d06092a864886f70d01010b050030123110300e060355040a130741636d6520436f301e170d3136303831373231343331335a170d3137303831373231343331335a30123110300e060355040a130741636d6520436f305c300d06092a864886f70d0101010500034b003048024100abb6bd84b8b9be3fb9415d00f22b4ddcaec7c99855b9d818c09003e084578430e5cfd2e35faa3561f036d496aa43a9ca6e6cf23c72a763c04ae324004f6cbdbb0203010001a351304f300e0603551d0f0101ff0404030205a030130603551d25040c300a06082b06010505070301300c0603551d130101ff04023000301a0603551d1104133011820f2a2e2a2e6578616d706c652e636f6d300d06092a864886f70d01010b05000341004837521004a5b6bc7ad5d6c0dae60bb7ee0fa5e4825be35e2bb6ef07ee29396ca30ceb289431bcfd363888ba2207139933ac7c6369fa8810c819b2e2966abb4b`
func TestCertificateSelection(t *testing.T) {
config := Config{
@@ -124,7 +124,7 @@ func TestCertificateSelection(t *testing.T) {
func runDynamicRecordSizingTest(t *testing.T, config *Config) {
clientConn, serverConn := net.Pipe()
- serverConfig := config.clone()
+ serverConfig := config.Clone()
serverConfig.DynamicRecordSizingDisabled = false
tlsConn := Server(serverConn, serverConfig)
@@ -225,19 +225,19 @@ func runDynamicRecordSizingTest(t *testing.T, config *Config) {
}
func TestDynamicRecordSizingWithStreamCipher(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
runDynamicRecordSizingTest(t, config)
}
func TestDynamicRecordSizingWithCBC(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.CipherSuites = []uint16{TLS_RSA_WITH_AES_256_CBC_SHA}
runDynamicRecordSizingTest(t, config)
}
func TestDynamicRecordSizingWithAEAD(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
runDynamicRecordSizingTest(t, config)
}
diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go
index f789e6f888f..6eda18dbfce 100644
--- a/libgo/go/crypto/tls/handshake_client.go
+++ b/libgo/go/crypto/tls/handshake_client.go
@@ -115,7 +115,7 @@ NextCipherSuite:
// Session resumption is not allowed if renegotiating because
// renegotiation is primarily used to allow a client to send a client
- // certificate, which would be skipped if session resumption occured.
+ // certificate, which would be skipped if session resumption occurred.
if sessionCache != nil && c.handshakes == 0 {
// Try to resume a previously negotiated TLS session, if
// available.
@@ -199,7 +199,7 @@ NextCipherSuite:
// Otherwise, in a full handshake, if we don't have any certificates
// configured then we will never send a CertificateVerify message and
// thus no signatures are needed in that case either.
- if isResume || len(c.config.Certificates) == 0 {
+ if isResume || (len(c.config.Certificates) == 0 && c.config.GetClientCertificate == nil) {
hs.finishedHash.discardHandshakeBuffer()
}
@@ -304,6 +304,13 @@ func (hs *clientHandshakeState) doFullHandshake() error {
}
}
+ if c.config.VerifyPeerCertificate != nil {
+ if err := c.config.VerifyPeerCertificate(certMsg.certificates, c.verifiedChains); err != nil {
+ c.sendAlert(alertBadCertificate)
+ return err
+ }
+ }
+
switch certs[0].PublicKey.(type) {
case *rsa.PublicKey, *ecdsa.PublicKey:
break
@@ -370,71 +377,11 @@ func (hs *clientHandshakeState) doFullHandshake() error {
certReq, ok := msg.(*certificateRequestMsg)
if ok {
certRequested = true
-
- // RFC 4346 on the certificateAuthorities field:
- // A list of the distinguished names of acceptable certificate
- // authorities. These distinguished names may specify a desired
- // distinguished name for a root CA or for a subordinate CA;
- // thus, this message can be used to describe both known roots
- // and a desired authorization space. If the
- // certificate_authorities list is empty then the client MAY
- // send any certificate of the appropriate
- // ClientCertificateType, unless there is some external
- // arrangement to the contrary.
-
hs.finishedHash.Write(certReq.marshal())
- var rsaAvail, ecdsaAvail bool
- for _, certType := range certReq.certificateTypes {
- switch certType {
- case certTypeRSASign:
- rsaAvail = true
- case certTypeECDSASign:
- ecdsaAvail = true
- }
- }
-
- // We need to search our list of client certs for one
- // 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 {
- continue
- }
-
- for j, cert := range chain.Certificate {
- x509Cert := chain.Leaf
- // parse the certificate if this isn't the leaf
- // node, or if chain.Leaf was nil
- if j != 0 || x509Cert == nil {
- if x509Cert, err = x509.ParseCertificate(cert); err != nil {
- c.sendAlert(alertInternalError)
- return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
- }
- }
-
- switch {
- case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
- case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
- default:
- continue findCert
- }
-
- if len(certReq.certificateAuthorities) == 0 {
- // they gave us an empty list, so just take the
- // first cert from c.config.Certificates
- chainToSend = &chain
- break findCert
- }
-
- for _, ca := range certReq.certificateAuthorities {
- if bytes.Equal(x509Cert.RawIssuer, ca) {
- chainToSend = &chain
- break findCert
- }
- }
- }
+ if chainToSend, err = hs.getCertificate(certReq); err != nil {
+ c.sendAlert(alertInternalError)
+ return err
}
msg, err = c.readHandshake()
@@ -455,9 +402,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
// certificate to send.
if certRequested {
certMsg = new(certificateMsg)
- if chainToSend != nil {
- certMsg.certificates = chainToSend.Certificate
- }
+ certMsg.certificates = chainToSend.Certificate
hs.finishedHash.Write(certMsg.marshal())
if _, err := c.writeRecord(recordTypeHandshake, certMsg.marshal()); err != nil {
return err
@@ -476,7 +421,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
}
}
- if chainToSend != nil {
+ if chainToSend != nil && len(chainToSend.Certificate) > 0 {
certVerify := &certificateVerifyMsg{
hasSignatureAndHash: c.vers >= VersionTLS12,
}
@@ -521,6 +466,10 @@ func (hs *clientHandshakeState) doFullHandshake() error {
}
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
+ if err := c.config.writeKeyLog(hs.hello.random, hs.masterSecret); err != nil {
+ c.sendAlert(alertInternalError)
+ return errors.New("tls: failed to write to key log: " + err.Error())
+ }
hs.finishedHash.discardHandshakeBuffer()
@@ -716,6 +665,117 @@ func (hs *clientHandshakeState) sendFinished(out []byte) error {
return nil
}
+// tls11SignatureSchemes contains the signature schemes that we synthesise for
+// a TLS <= 1.1 connection, based on the supported certificate types.
+var tls11SignatureSchemes = []SignatureScheme{ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512, PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512, PKCS1WithSHA1}
+
+const (
+ // tls11SignatureSchemesNumECDSA is the number of initial elements of
+ // tls11SignatureSchemes that use ECDSA.
+ tls11SignatureSchemesNumECDSA = 3
+ // tls11SignatureSchemesNumRSA is the number of trailing elements of
+ // tls11SignatureSchemes that use RSA.
+ tls11SignatureSchemesNumRSA = 4
+)
+
+func (hs *clientHandshakeState) getCertificate(certReq *certificateRequestMsg) (*Certificate, error) {
+ c := hs.c
+
+ var rsaAvail, ecdsaAvail bool
+ for _, certType := range certReq.certificateTypes {
+ switch certType {
+ case certTypeRSASign:
+ rsaAvail = true
+ case certTypeECDSASign:
+ ecdsaAvail = true
+ }
+ }
+
+ if c.config.GetClientCertificate != nil {
+ var signatureSchemes []SignatureScheme
+
+ if !certReq.hasSignatureAndHash {
+ // Prior to TLS 1.2, the signature schemes were not
+ // included in the certificate request message. In this
+ // case we use a plausible list based on the acceptable
+ // certificate types.
+ signatureSchemes = tls11SignatureSchemes
+ if !ecdsaAvail {
+ signatureSchemes = signatureSchemes[tls11SignatureSchemesNumECDSA:]
+ }
+ if !rsaAvail {
+ signatureSchemes = signatureSchemes[:len(signatureSchemes)-tls11SignatureSchemesNumRSA]
+ }
+ } else {
+ signatureSchemes = make([]SignatureScheme, 0, len(certReq.signatureAndHashes))
+ for _, sah := range certReq.signatureAndHashes {
+ signatureSchemes = append(signatureSchemes, SignatureScheme(sah.hash)<<8+SignatureScheme(sah.signature))
+ }
+ }
+
+ return c.config.GetClientCertificate(&CertificateRequestInfo{
+ AcceptableCAs: certReq.certificateAuthorities,
+ SignatureSchemes: signatureSchemes,
+ })
+ }
+
+ // RFC 4346 on the certificateAuthorities field: A list of the
+ // distinguished names of acceptable certificate authorities.
+ // These distinguished names may specify a desired
+ // distinguished name for a root CA or for a subordinate CA;
+ // thus, this message can be used to describe both known roots
+ // and a desired authorization space. If the
+ // certificate_authorities list is empty then the client MAY
+ // send any certificate of the appropriate
+ // ClientCertificateType, unless there is some external
+ // arrangement to the contrary.
+
+ // We need to search our list of client certs for one
+ // 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 {
+ continue
+ }
+
+ for j, cert := range chain.Certificate {
+ x509Cert := chain.Leaf
+ // parse the certificate if this isn't the leaf
+ // node, or if chain.Leaf was nil
+ if j != 0 || x509Cert == nil {
+ var err error
+ if x509Cert, err = x509.ParseCertificate(cert); err != nil {
+ c.sendAlert(alertInternalError)
+ return nil, errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
+ }
+ }
+
+ switch {
+ case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
+ case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
+ default:
+ continue findCert
+ }
+
+ if len(certReq.certificateAuthorities) == 0 {
+ // they gave us an empty list, so just take the
+ // first cert from c.config.Certificates
+ return &chain, nil
+ }
+
+ for _, ca := range certReq.certificateAuthorities {
+ if bytes.Equal(x509Cert.RawIssuer, ca) {
+ return &chain, nil
+ }
+ }
+ }
+ }
+
+ // No acceptable certificate found. Don't send a certificate.
+ return new(Certificate), 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 {
diff --git a/libgo/go/crypto/tls/handshake_client_test.go b/libgo/go/crypto/tls/handshake_client_test.go
index ce987f11c46..5851f897f96 100644
--- a/libgo/go/crypto/tls/handshake_client_test.go
+++ b/libgo/go/crypto/tls/handshake_client_test.go
@@ -15,12 +15,14 @@ import (
"errors"
"fmt"
"io"
+ "math/big"
"net"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
+ "sync"
"testing"
"time"
)
@@ -76,7 +78,7 @@ func newOpensslOutputSink() *opensslOutputSink {
// opensslEndOfHandshake is a message that the “openssl s_server” tool will
// print when a handshake completes if run with “-state”.
-const opensslEndOfHandshake = "SSL_accept:SSLv3 write finished A"
+const opensslEndOfHandshake = "SSL_accept:SSLv3/TLS write finished"
func (o *opensslOutputSink) Write(data []byte) (n int, err error) {
o.line = append(o.line, data...)
@@ -275,6 +277,8 @@ func (test *clientTest) loadData() (flows [][]byte, err error) {
}
func (test *clientTest) run(t *testing.T, write bool) {
+ checkOpenSSLVersion(t)
+
var clientConn, serverConn net.Conn
var recordingConn *recordingConn
var childProcess *exec.Cmd
@@ -355,7 +359,7 @@ func (test *clientTest) run(t *testing.T, write bool) {
}
if expected := i + 1; client.handshakes != expected {
- t.Errorf("client should have recorded %d handshakes, but believes that %d have occured", expected, client.handshakes)
+ t.Errorf("client should have recorded %d handshakes, but believes that %d have occurred", expected, client.handshakes)
}
}()
@@ -409,7 +413,7 @@ func (test *clientTest) run(t *testing.T, write bool) {
childProcess.Process.Kill()
childProcess.Wait()
if len(recordingConn.flows) < 3 {
- childProcess.Stdout.(*bytes.Buffer).WriteTo(os.Stdout)
+ os.Stdout.Write(childProcess.Stdout.(*opensslOutputSink).all)
t.Fatalf("Client connection didn't work")
}
recordingConn.WriteTo(out)
@@ -417,7 +421,26 @@ func (test *clientTest) run(t *testing.T, write bool) {
}
}
+var (
+ didParMu sync.Mutex
+ didPar = map[*testing.T]bool{}
+)
+
+// setParallel calls t.Parallel once. If you call it twice, it would
+// panic.
+func setParallel(t *testing.T) {
+ didParMu.Lock()
+ v := didPar[t]
+ didPar[t] = true
+ didParMu.Unlock()
+ if !v {
+ t.Parallel()
+ }
+}
+
func runClientTestForVersion(t *testing.T, template *clientTest, prefix, option string) {
+ setParallel(t)
+
test := *template
test.name = prefix + test.name
if len(test.command) == 0 {
@@ -508,14 +531,81 @@ func TestHandshakeClientAES256GCMSHA384(t *testing.T) {
runClientTestTLS12(t, test)
}
+func TestHandshakeClientAES128CBCSHA256(t *testing.T) {
+ test := &clientTest{
+ name: "AES128-SHA256",
+ command: []string{"openssl", "s_server", "-cipher", "AES128-SHA256"},
+ }
+ runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientECDHERSAAES128CBCSHA256(t *testing.T) {
+ test := &clientTest{
+ name: "ECDHE-RSA-AES128-SHA256",
+ command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES128-SHA256"},
+ }
+ runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientECDHEECDSAAES128CBCSHA256(t *testing.T) {
+ test := &clientTest{
+ name: "ECDHE-ECDSA-AES128-SHA256",
+ command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-AES128-SHA256"},
+ cert: testECDSACertificate,
+ key: testECDSAPrivateKey,
+ }
+ runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientX25519(t *testing.T) {
+ config := testConfig.Clone()
+ config.CurvePreferences = []CurveID{X25519}
+
+ test := &clientTest{
+ name: "X25519-ECDHE-RSA-AES-GCM",
+ command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES128-GCM-SHA256"},
+ config: config,
+ }
+
+ runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientECDHERSAChaCha20(t *testing.T) {
+ config := testConfig.Clone()
+ config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305}
+
+ test := &clientTest{
+ name: "ECDHE-RSA-CHACHA20-POLY1305",
+ command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305"},
+ config: config,
+ }
+
+ runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientECDHEECDSAChaCha20(t *testing.T) {
+ config := testConfig.Clone()
+ config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305}
+
+ test := &clientTest{
+ name: "ECDHE-ECDSA-CHACHA20-POLY1305",
+ command: []string{"openssl", "s_server", "-cipher", "ECDHE-ECDSA-CHACHA20-POLY1305"},
+ config: config,
+ cert: testECDSACertificate,
+ key: testECDSAPrivateKey,
+ }
+
+ runClientTestTLS12(t, test)
+}
+
func TestHandshakeClientCertRSA(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
cert, _ := X509KeyPair([]byte(clientCertificatePEM), []byte(clientKeyPEM))
config.Certificates = []Certificate{cert}
test := &clientTest{
name: "ClientCert-RSA-RSA",
- command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"},
+ command: []string{"openssl", "s_server", "-cipher", "AES128", "-verify", "1"},
config: config,
}
@@ -545,13 +635,13 @@ func TestHandshakeClientCertRSA(t *testing.T) {
}
func TestHandshakeClientCertECDSA(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
cert, _ := X509KeyPair([]byte(clientECDSACertificatePEM), []byte(clientECDSAKeyPEM))
config.Certificates = []Certificate{cert}
test := &clientTest{
name: "ClientCert-ECDSA-RSA",
- command: []string{"openssl", "s_server", "-cipher", "RC4-SHA", "-verify", "1"},
+ command: []string{"openssl", "s_server", "-cipher", "AES128", "-verify", "1"},
config: config,
}
@@ -622,13 +712,14 @@ func TestClientResumption(t *testing.T) {
t.Fatal("first ticket doesn't match ticket after resumption")
}
- key2 := randomKey()
- serverConfig.SetSessionTicketKeys([][32]byte{key2})
+ key1 := randomKey()
+ serverConfig.SetSessionTicketKeys([][32]byte{key1})
testResumeState("InvalidSessionTicketKey", false)
testResumeState("ResumeAfterInvalidSessionTicketKey", true)
- serverConfig.SetSessionTicketKeys([][32]byte{randomKey(), key2})
+ key2 := randomKey()
+ serverConfig.SetSessionTicketKeys([][32]byte{key2, key1})
ticket = getTicket()
testResumeState("KeyChange", true)
if bytes.Equal(ticket, getTicket()) {
@@ -636,6 +727,16 @@ func TestClientResumption(t *testing.T) {
}
testResumeState("KeyChangeFinish", true)
+ // Reset serverConfig to ensure that calling SetSessionTicketKeys
+ // before the serverConfig is used works.
+ serverConfig = &Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+ Certificates: testConfig.Certificates,
+ }
+ serverConfig.SetSessionTicketKeys([][32]byte{key2})
+
+ testResumeState("FreshConfig", true)
+
clientConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA}
testResumeState("DifferentCipherSuite", false)
testResumeState("DifferentCipherSuiteRecovers", true)
@@ -690,8 +791,59 @@ func TestLRUClientSessionCache(t *testing.T) {
}
}
+func TestKeyLog(t *testing.T) {
+ var serverBuf, clientBuf bytes.Buffer
+
+ clientConfig := testConfig.Clone()
+ clientConfig.KeyLogWriter = &clientBuf
+
+ serverConfig := testConfig.Clone()
+ serverConfig.KeyLogWriter = &serverBuf
+
+ c, s := net.Pipe()
+ done := make(chan bool)
+
+ go func() {
+ defer close(done)
+
+ if err := Server(s, serverConfig).Handshake(); err != nil {
+ t.Errorf("server: %s", err)
+ return
+ }
+ s.Close()
+ }()
+
+ if err := Client(c, clientConfig).Handshake(); err != nil {
+ t.Fatalf("client: %s", err)
+ }
+
+ c.Close()
+ <-done
+
+ checkKeylogLine := func(side, loggedLine string) {
+ if len(loggedLine) == 0 {
+ t.Fatalf("%s: no keylog line was produced", side)
+ }
+ const expectedLen = 13 /* "CLIENT_RANDOM" */ +
+ 1 /* space */ +
+ 32*2 /* hex client nonce */ +
+ 1 /* space */ +
+ 48*2 /* hex master secret */ +
+ 1 /* new line */
+ if len(loggedLine) != expectedLen {
+ t.Fatalf("%s: keylog line has incorrect length (want %d, got %d): %q", side, expectedLen, len(loggedLine), loggedLine)
+ }
+ if !strings.HasPrefix(loggedLine, "CLIENT_RANDOM "+strings.Repeat("0", 64)+" ") {
+ t.Fatalf("%s: keylog line has incorrect structure or nonce: %q", side, loggedLine)
+ }
+ }
+
+ checkKeylogLine("client", string(clientBuf.Bytes()))
+ checkKeylogLine("server", string(serverBuf.Bytes()))
+}
+
func TestHandshakeClientALPNMatch(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.NextProtos = []string{"proto2", "proto1"}
test := &clientTest{
@@ -711,32 +863,11 @@ func TestHandshakeClientALPNMatch(t *testing.T) {
runClientTestTLS12(t, test)
}
-func TestHandshakeClientALPNNoMatch(t *testing.T) {
- config := testConfig.clone()
- 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)
-}
-
// sctsBase64 contains data from `openssl s_client -serverinfo 18 -connect ritter.vg:443`
const sctsBase64 = "ABIBaQFnAHUApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFHl5nuFgAABAMARjBEAiAcS4JdlW5nW9sElUv2zvQyPoZ6ejKrGGB03gjaBZFMLwIgc1Qbbn+hsH0RvObzhS+XZhr3iuQQJY8S9G85D9KeGPAAdgBo9pj4H2SCvjqM7rkoHUz8cVFdZ5PURNEKZ6y7T0/7xAAAAUeX4bVwAAAEAwBHMEUCIDIhFDgG2HIuADBkGuLobU5a4dlCHoJLliWJ1SYT05z6AiEAjxIoZFFPRNWMGGIjskOTMwXzQ1Wh2e7NxXE1kd1J0QsAdgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAUhcZIqHAAAEAwBHMEUCICmJ1rBT09LpkbzxtUC+Hi7nXLR0J+2PmwLp+sJMuqK+AiEAr0NkUnEVKVhAkccIFpYDqHOlZaBsuEhWWrYpg2RtKp0="
func TestHandshakClientSCTs(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
scts, err := base64.StdEncoding.DecodeString(sctsBase64)
if err != nil {
@@ -771,7 +902,7 @@ func TestHandshakClientSCTs(t *testing.T) {
}
func TestRenegotiationRejected(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
test := &clientTest{
name: "RenegotiationRejected",
command: []string{"openssl", "s_server", "-state"},
@@ -793,7 +924,7 @@ func TestRenegotiationRejected(t *testing.T) {
}
func TestRenegotiateOnce(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.Renegotiation = RenegotiateOnceAsClient
test := &clientTest{
@@ -807,7 +938,7 @@ func TestRenegotiateOnce(t *testing.T) {
}
func TestRenegotiateTwice(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.Renegotiation = RenegotiateFreelyAsClient
test := &clientTest{
@@ -821,7 +952,7 @@ func TestRenegotiateTwice(t *testing.T) {
}
func TestRenegotiateTwiceRejected(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.Renegotiation = RenegotiateOnceAsClient
test := &clientTest{
@@ -956,6 +1087,160 @@ func TestServerSelectingUnconfiguredCipherSuite(t *testing.T) {
}
}
+func TestVerifyPeerCertificate(t *testing.T) {
+ issuer, err := x509.ParseCertificate(testRSACertificateIssuer)
+ if err != nil {
+ panic(err)
+ }
+
+ rootCAs := x509.NewCertPool()
+ rootCAs.AddCert(issuer)
+
+ now := func() time.Time { return time.Unix(1476984729, 0) }
+
+ sentinelErr := errors.New("TestVerifyPeerCertificate")
+
+ verifyCallback := func(called *bool, rawCerts [][]byte, validatedChains [][]*x509.Certificate) error {
+ if l := len(rawCerts); l != 1 {
+ return fmt.Errorf("got len(rawCerts) = %d, wanted 1", l)
+ }
+ if len(validatedChains) == 0 {
+ return errors.New("got len(validatedChains) = 0, wanted non-zero")
+ }
+ *called = true
+ return nil
+ }
+
+ tests := []struct {
+ configureServer func(*Config, *bool)
+ configureClient func(*Config, *bool)
+ validate func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error)
+ }{
+ {
+ configureServer: func(config *Config, called *bool) {
+ config.InsecureSkipVerify = false
+ config.VerifyPeerCertificate = func(rawCerts [][]byte, validatedChains [][]*x509.Certificate) error {
+ return verifyCallback(called, rawCerts, validatedChains)
+ }
+ },
+ configureClient: func(config *Config, called *bool) {
+ config.InsecureSkipVerify = false
+ config.VerifyPeerCertificate = func(rawCerts [][]byte, validatedChains [][]*x509.Certificate) error {
+ return verifyCallback(called, rawCerts, validatedChains)
+ }
+ },
+ validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) {
+ if clientErr != nil {
+ t.Errorf("test[%d]: client handshake failed: %v", testNo, clientErr)
+ }
+ if serverErr != nil {
+ t.Errorf("test[%d]: server handshake failed: %v", testNo, serverErr)
+ }
+ if !clientCalled {
+ t.Errorf("test[%d]: client did not call callback", testNo)
+ }
+ if !serverCalled {
+ t.Errorf("test[%d]: server did not call callback", testNo)
+ }
+ },
+ },
+ {
+ configureServer: func(config *Config, called *bool) {
+ config.InsecureSkipVerify = false
+ config.VerifyPeerCertificate = func(rawCerts [][]byte, validatedChains [][]*x509.Certificate) error {
+ return sentinelErr
+ }
+ },
+ configureClient: func(config *Config, called *bool) {
+ config.VerifyPeerCertificate = nil
+ },
+ validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) {
+ if serverErr != sentinelErr {
+ t.Errorf("#%d: got server error %v, wanted sentinelErr", testNo, serverErr)
+ }
+ },
+ },
+ {
+ configureServer: func(config *Config, called *bool) {
+ config.InsecureSkipVerify = false
+ },
+ configureClient: func(config *Config, called *bool) {
+ config.VerifyPeerCertificate = func(rawCerts [][]byte, validatedChains [][]*x509.Certificate) error {
+ return sentinelErr
+ }
+ },
+ validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) {
+ if clientErr != sentinelErr {
+ t.Errorf("#%d: got client error %v, wanted sentinelErr", testNo, clientErr)
+ }
+ },
+ },
+ {
+ configureServer: func(config *Config, called *bool) {
+ config.InsecureSkipVerify = false
+ },
+ configureClient: func(config *Config, called *bool) {
+ config.InsecureSkipVerify = true
+ config.VerifyPeerCertificate = func(rawCerts [][]byte, validatedChains [][]*x509.Certificate) error {
+ if l := len(rawCerts); l != 1 {
+ return fmt.Errorf("got len(rawCerts) = %d, wanted 1", l)
+ }
+ // With InsecureSkipVerify set, this
+ // callback should still be called but
+ // validatedChains must be empty.
+ if l := len(validatedChains); l != 0 {
+ return errors.New("got len(validatedChains) = 0, wanted zero")
+ }
+ *called = true
+ return nil
+ }
+ },
+ validate: func(t *testing.T, testNo int, clientCalled, serverCalled bool, clientErr, serverErr error) {
+ if clientErr != nil {
+ t.Errorf("test[%d]: client handshake failed: %v", testNo, clientErr)
+ }
+ if serverErr != nil {
+ t.Errorf("test[%d]: server handshake failed: %v", testNo, serverErr)
+ }
+ if !clientCalled {
+ t.Errorf("test[%d]: client did not call callback", testNo)
+ }
+ },
+ },
+ }
+
+ for i, test := range tests {
+ c, s := net.Pipe()
+ done := make(chan error)
+
+ var clientCalled, serverCalled bool
+
+ go func() {
+ config := testConfig.Clone()
+ config.ServerName = "example.golang"
+ config.ClientAuth = RequireAndVerifyClientCert
+ config.ClientCAs = rootCAs
+ config.Time = now
+ test.configureServer(config, &serverCalled)
+
+ err = Server(s, config).Handshake()
+ s.Close()
+ done <- err
+ }()
+
+ config := testConfig.Clone()
+ config.ServerName = "example.golang"
+ config.RootCAs = rootCAs
+ config.Time = now
+ test.configureClient(config, &clientCalled)
+ clientErr := Client(c, config).Handshake()
+ c.Close()
+ serverErr := <-done
+
+ test.validate(t, i, clientCalled, serverCalled, clientErr, serverErr)
+ }
+}
+
// brokenConn wraps a net.Conn and causes all Writes after a certain number to
// fail with brokenConnErr.
type brokenConn struct {
@@ -1045,3 +1330,236 @@ func TestBuffering(t *testing.T) {
t.Errorf("expected server handshake to complete with only two writes, but saw %d", n)
}
}
+
+func TestAlertFlushing(t *testing.T) {
+ c, s := net.Pipe()
+ done := make(chan bool)
+
+ clientWCC := &writeCountingConn{Conn: c}
+ serverWCC := &writeCountingConn{Conn: s}
+
+ serverConfig := testConfig.Clone()
+
+ // Cause a signature-time error
+ brokenKey := rsa.PrivateKey{PublicKey: testRSAPrivateKey.PublicKey}
+ brokenKey.D = big.NewInt(42)
+ serverConfig.Certificates = []Certificate{{
+ Certificate: [][]byte{testRSACertificate},
+ PrivateKey: &brokenKey,
+ }}
+
+ go func() {
+ Server(serverWCC, serverConfig).Handshake()
+ serverWCC.Close()
+ done <- true
+ }()
+
+ err := Client(clientWCC, testConfig).Handshake()
+ if err == nil {
+ t.Fatal("client unexpectedly returned no error")
+ }
+
+ const expectedError = "remote error: tls: handshake failure"
+ if e := err.Error(); !strings.Contains(e, expectedError) {
+ t.Fatalf("expected to find %q in error but error was %q", expectedError, e)
+ }
+ clientWCC.Close()
+ <-done
+
+ if n := clientWCC.numWrites; n != 1 {
+ t.Errorf("expected client handshake to complete with one write, but saw %d", n)
+ }
+
+ if n := serverWCC.numWrites; n != 1 {
+ t.Errorf("expected server handshake to complete with one write, but saw %d", n)
+ }
+}
+
+func TestHandshakeRace(t *testing.T) {
+ t.Parallel()
+ // This test races a Read and Write to try and complete a handshake in
+ // order to provide some evidence that there are no races or deadlocks
+ // in the handshake locking.
+ for i := 0; i < 32; i++ {
+ c, s := net.Pipe()
+
+ go func() {
+ server := Server(s, testConfig)
+ if err := server.Handshake(); err != nil {
+ panic(err)
+ }
+
+ var request [1]byte
+ if n, err := server.Read(request[:]); err != nil || n != 1 {
+ panic(err)
+ }
+
+ server.Write(request[:])
+ server.Close()
+ }()
+
+ startWrite := make(chan struct{})
+ startRead := make(chan struct{})
+ readDone := make(chan struct{})
+
+ client := Client(c, testConfig)
+ go func() {
+ <-startWrite
+ var request [1]byte
+ client.Write(request[:])
+ }()
+
+ go func() {
+ <-startRead
+ var reply [1]byte
+ if n, err := client.Read(reply[:]); err != nil || n != 1 {
+ panic(err)
+ }
+ c.Close()
+ readDone <- struct{}{}
+ }()
+
+ if i&1 == 1 {
+ startWrite <- struct{}{}
+ startRead <- struct{}{}
+ } else {
+ startRead <- struct{}{}
+ startWrite <- struct{}{}
+ }
+ <-readDone
+ }
+}
+
+func TestTLS11SignatureSchemes(t *testing.T) {
+ expected := tls11SignatureSchemesNumECDSA + tls11SignatureSchemesNumRSA
+ if expected != len(tls11SignatureSchemes) {
+ t.Errorf("expected to find %d TLS 1.1 signature schemes, but found %d", expected, len(tls11SignatureSchemes))
+ }
+}
+
+var getClientCertificateTests = []struct {
+ setup func(*Config)
+ expectedClientError string
+ verify func(*testing.T, int, *ConnectionState)
+}{
+ {
+ func(clientConfig *Config) {
+ // Returning a Certificate with no certificate data
+ // should result in an empty message being sent to the
+ // server.
+ clientConfig.GetClientCertificate = func(cri *CertificateRequestInfo) (*Certificate, error) {
+ if len(cri.SignatureSchemes) == 0 {
+ panic("empty SignatureSchemes")
+ }
+ return new(Certificate), nil
+ }
+ },
+ "",
+ func(t *testing.T, testNum int, cs *ConnectionState) {
+ if l := len(cs.PeerCertificates); l != 0 {
+ t.Errorf("#%d: expected no certificates but got %d", testNum, l)
+ }
+ },
+ },
+ {
+ func(clientConfig *Config) {
+ // With TLS 1.1, the SignatureSchemes should be
+ // synthesised from the supported certificate types.
+ clientConfig.MaxVersion = VersionTLS11
+ clientConfig.GetClientCertificate = func(cri *CertificateRequestInfo) (*Certificate, error) {
+ if len(cri.SignatureSchemes) == 0 {
+ panic("empty SignatureSchemes")
+ }
+ return new(Certificate), nil
+ }
+ },
+ "",
+ func(t *testing.T, testNum int, cs *ConnectionState) {
+ if l := len(cs.PeerCertificates); l != 0 {
+ t.Errorf("#%d: expected no certificates but got %d", testNum, l)
+ }
+ },
+ },
+ {
+ func(clientConfig *Config) {
+ // Returning an error should abort the handshake with
+ // that error.
+ clientConfig.GetClientCertificate = func(cri *CertificateRequestInfo) (*Certificate, error) {
+ return nil, errors.New("GetClientCertificate")
+ }
+ },
+ "GetClientCertificate",
+ func(t *testing.T, testNum int, cs *ConnectionState) {
+ },
+ },
+ {
+ func(clientConfig *Config) {
+ clientConfig.GetClientCertificate = func(cri *CertificateRequestInfo) (*Certificate, error) {
+ return &testConfig.Certificates[0], nil
+ }
+ },
+ "",
+ func(t *testing.T, testNum int, cs *ConnectionState) {
+ if l := len(cs.VerifiedChains); l != 0 {
+ t.Errorf("#%d: expected some verified chains, but found none", testNum)
+ }
+ },
+ },
+}
+
+func TestGetClientCertificate(t *testing.T) {
+ issuer, err := x509.ParseCertificate(testRSACertificateIssuer)
+ if err != nil {
+ panic(err)
+ }
+
+ for i, test := range getClientCertificateTests {
+ serverConfig := testConfig.Clone()
+ serverConfig.ClientAuth = RequestClientCert
+ serverConfig.RootCAs = x509.NewCertPool()
+ serverConfig.RootCAs.AddCert(issuer)
+
+ clientConfig := testConfig.Clone()
+
+ test.setup(clientConfig)
+
+ type serverResult struct {
+ cs ConnectionState
+ err error
+ }
+
+ c, s := net.Pipe()
+ done := make(chan serverResult)
+
+ go func() {
+ defer s.Close()
+ server := Server(s, serverConfig)
+ err := server.Handshake()
+
+ var cs ConnectionState
+ if err == nil {
+ cs = server.ConnectionState()
+ }
+ done <- serverResult{cs, err}
+ }()
+
+ clientErr := Client(c, clientConfig).Handshake()
+ c.Close()
+
+ result := <-done
+
+ if clientErr != nil {
+ if len(test.expectedClientError) == 0 {
+ t.Errorf("#%d: client error: %v", i, clientErr)
+ } else if got := clientErr.Error(); got != test.expectedClientError {
+ t.Errorf("#%d: expected client error %q, but got %q", i, test.expectedClientError, got)
+ }
+ } else if len(test.expectedClientError) > 0 {
+ t.Errorf("#%d: expected client error %q, but got no error", i, test.expectedClientError)
+ } else if err := result.err; err != nil {
+ t.Errorf("#%d: server error: %v", i, err)
+ } else {
+ test.verify(t, i, &result.cs)
+ }
+ }
+}
diff --git a/libgo/go/crypto/tls/handshake_messages.go b/libgo/go/crypto/tls/handshake_messages.go
index ab8e60ae116..694bd918d85 100644
--- a/libgo/go/crypto/tls/handshake_messages.go
+++ b/libgo/go/crypto/tls/handshake_messages.go
@@ -802,12 +802,9 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
}
l := int(d[0])<<8 | int(d[1])
d = d[2:]
- if len(d) != l {
+ if len(d) != l || l == 0 {
return false
}
- if l == 0 {
- continue
- }
m.scts = make([][]byte, 0, 3)
for len(d) != 0 {
@@ -816,7 +813,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
}
sctLen := int(d[0])<<8 | int(d[1])
d = d[2:]
- if len(d) < sctLen {
+ if sctLen == 0 || len(d) < sctLen {
return false
}
m.scts = append(m.scts, d[:sctLen])
diff --git a/libgo/go/crypto/tls/handshake_messages_test.go b/libgo/go/crypto/tls/handshake_messages_test.go
index 95d825bd175..f1154d4d01d 100644
--- a/libgo/go/crypto/tls/handshake_messages_test.go
+++ b/libgo/go/crypto/tls/handshake_messages_test.go
@@ -5,6 +5,7 @@
package tls
import (
+ "bytes"
"math/rand"
"reflect"
"testing"
@@ -260,3 +261,65 @@ func (*sessionState) Generate(rand *rand.Rand, size int) reflect.Value {
}
return reflect.ValueOf(s)
}
+
+func TestRejectEmptySCTList(t *testing.T) {
+ // https://tools.ietf.org/html/rfc6962#section-3.3.1 specifies that
+ // empty SCT lists are invalid.
+
+ var random [32]byte
+ sct := []byte{0x42, 0x42, 0x42, 0x42}
+ serverHello := serverHelloMsg{
+ vers: VersionTLS12,
+ random: random[:],
+ scts: [][]byte{sct},
+ }
+ serverHelloBytes := serverHello.marshal()
+
+ var serverHelloCopy serverHelloMsg
+ if !serverHelloCopy.unmarshal(serverHelloBytes) {
+ t.Fatal("Failed to unmarshal initial message")
+ }
+
+ // Change serverHelloBytes so that the SCT list is empty
+ i := bytes.Index(serverHelloBytes, sct)
+ if i < 0 {
+ t.Fatal("Cannot find SCT in ServerHello")
+ }
+
+ var serverHelloEmptySCT []byte
+ serverHelloEmptySCT = append(serverHelloEmptySCT, serverHelloBytes[:i-6]...)
+ // Append the extension length and SCT list length for an empty list.
+ serverHelloEmptySCT = append(serverHelloEmptySCT, []byte{0, 2, 0, 0}...)
+ serverHelloEmptySCT = append(serverHelloEmptySCT, serverHelloBytes[i+4:]...)
+
+ // Update the handshake message length.
+ serverHelloEmptySCT[1] = byte((len(serverHelloEmptySCT) - 4) >> 16)
+ serverHelloEmptySCT[2] = byte((len(serverHelloEmptySCT) - 4) >> 8)
+ serverHelloEmptySCT[3] = byte(len(serverHelloEmptySCT) - 4)
+
+ // Update the extensions length
+ serverHelloEmptySCT[42] = byte((len(serverHelloEmptySCT) - 44) >> 8)
+ serverHelloEmptySCT[43] = byte((len(serverHelloEmptySCT) - 44))
+
+ if serverHelloCopy.unmarshal(serverHelloEmptySCT) {
+ t.Fatal("Unmarshaled ServerHello with empty SCT list")
+ }
+}
+
+func TestRejectEmptySCT(t *testing.T) {
+ // Not only must the SCT list be non-empty, but the SCT elements must
+ // not be zero length.
+
+ var random [32]byte
+ serverHello := serverHelloMsg{
+ vers: VersionTLS12,
+ random: random[:],
+ scts: [][]byte{nil},
+ }
+ serverHelloBytes := serverHello.marshal()
+
+ var serverHelloCopy serverHelloMsg
+ if serverHelloCopy.unmarshal(serverHelloBytes) {
+ t.Fatal("Unmarshaled ServerHello with zero-length SCT")
+ }
+}
diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go
index 1aac7295614..b786c3083a2 100644
--- a/libgo/go/crypto/tls/handshake_server.go
+++ b/libgo/go/crypto/tls/handshake_server.go
@@ -19,29 +19,28 @@ import (
// serverHandshakeState contains details of a server handshake in progress.
// It's discarded once the handshake has completed.
type serverHandshakeState struct {
- c *Conn
- clientHello *clientHelloMsg
- hello *serverHelloMsg
- suite *cipherSuite
- ellipticOk bool
- ecdsaOk bool
- rsaDecryptOk bool
- rsaSignOk bool
- sessionState *sessionState
- finishedHash finishedHash
- masterSecret []byte
- certsFromClient [][]byte
- cert *Certificate
+ c *Conn
+ clientHello *clientHelloMsg
+ hello *serverHelloMsg
+ suite *cipherSuite
+ ellipticOk bool
+ ecdsaOk bool
+ rsaDecryptOk bool
+ rsaSignOk bool
+ sessionState *sessionState
+ finishedHash finishedHash
+ masterSecret []byte
+ certsFromClient [][]byte
+ cert *Certificate
+ cachedClientHelloInfo *ClientHelloInfo
}
// serverHandshake performs a TLS handshake as a server.
// c.out.Mutex <= L; c.handshakeMutex <= L.
func (c *Conn) serverHandshake() error {
- config := c.config
-
// If this is the first server handshake, we generate a random key to
// encrypt the tickets with.
- config.serverInitOnce.Do(config.serverInit)
+ c.config.serverInitOnce.Do(c.config.serverInit)
hs := serverHandshakeState{
c: c,
@@ -112,7 +111,6 @@ func (c *Conn) serverHandshake() error {
// readClientHello reads a ClientHello message from the client and decides
// whether we will perform session resumption.
func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
- config := hs.c.config
c := hs.c
msg, err := c.readHandshake()
@@ -125,7 +123,22 @@ func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
c.sendAlert(alertUnexpectedMessage)
return false, unexpectedMessageError(hs.clientHello, msg)
}
- c.vers, ok = config.mutualVersion(hs.clientHello.vers)
+
+ if c.config.GetConfigForClient != nil {
+ if newConfig, err := c.config.GetConfigForClient(hs.clientHelloInfo()); err != nil {
+ c.sendAlert(alertInternalError)
+ return false, err
+ } else if newConfig != nil {
+ newConfig.mutex.Lock()
+ newConfig.originalConfig = c.config
+ newConfig.mutex.Unlock()
+
+ newConfig.serverInitOnce.Do(newConfig.serverInit)
+ c.config = newConfig
+ }
+ }
+
+ c.vers, ok = c.config.mutualVersion(hs.clientHello.vers)
if !ok {
c.sendAlert(alertProtocolVersion)
return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers)
@@ -135,7 +148,7 @@ func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
hs.hello = new(serverHelloMsg)
supportedCurve := false
- preferredCurves := config.curvePreferences()
+ preferredCurves := c.config.curvePreferences()
Curves:
for _, curve := range hs.clientHello.supportedCurves {
for _, supported := range preferredCurves {
@@ -171,7 +184,7 @@ Curves:
hs.hello.vers = c.vers
hs.hello.random = make([]byte, 32)
- _, err = io.ReadFull(config.rand(), hs.hello.random)
+ _, err = io.ReadFull(c.config.rand(), hs.hello.random)
if err != nil {
c.sendAlert(alertInternalError)
return false, err
@@ -196,20 +209,15 @@ Curves:
} 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
+ // c.config.NextProtos is empty. See
// https://golang.org/issue/5445.
- if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
+ if hs.clientHello.nextProtoNeg && len(c.config.NextProtos) > 0 {
hs.hello.nextProtoNeg = true
- hs.hello.nextProtos = config.NextProtos
+ hs.hello.nextProtos = c.config.NextProtos
}
}
- hs.cert, err = config.getCertificate(&ClientHelloInfo{
- CipherSuites: hs.clientHello.cipherSuites,
- ServerName: hs.clientHello.serverName,
- SupportedCurves: hs.clientHello.supportedCurves,
- SupportedPoints: hs.clientHello.supportedPoints,
- })
+ hs.cert, err = c.config.getCertificate(hs.clientHelloInfo())
if err != nil {
c.sendAlert(alertInternalError)
return false, err
@@ -354,18 +362,17 @@ func (hs *serverHandshakeState) doResumeHandshake() error {
}
func (hs *serverHandshakeState) doFullHandshake() error {
- config := hs.c.config
c := hs.c
if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
hs.hello.ocspStapling = true
}
- hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled
+ hs.hello.ticketSupported = hs.clientHello.ticketSupported && !c.config.SessionTicketsDisabled
hs.hello.cipherSuite = hs.suite.id
hs.finishedHash = newFinishedHash(hs.c.vers, hs.suite)
- if config.ClientAuth == NoClientCert {
+ if c.config.ClientAuth == NoClientCert {
// No need to keep a full record of the handshake if client
// certificates won't be used.
hs.finishedHash.discardHandshakeBuffer()
@@ -394,7 +401,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}
keyAgreement := hs.suite.ka(c.vers)
- skx, err := keyAgreement.generateServerKeyExchange(config, hs.cert, hs.clientHello, hs.hello)
+ skx, err := keyAgreement.generateServerKeyExchange(c.config, hs.cert, hs.clientHello, hs.hello)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
@@ -406,7 +413,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}
}
- if config.ClientAuth >= RequestClientCert {
+ if c.config.ClientAuth >= RequestClientCert {
// Request a client certificate
certReq := new(certificateRequestMsg)
certReq.certificateTypes = []byte{
@@ -423,8 +430,8 @@ func (hs *serverHandshakeState) doFullHandshake() error {
// to our request. When we know the CAs we trust, then
// we can send them down, so that the client can choose
// an appropriate certificate to give to us.
- if config.ClientCAs != nil {
- certReq.certificateAuthorities = config.ClientCAs.Subjects()
+ if c.config.ClientCAs != nil {
+ certReq.certificateAuthorities = c.config.ClientCAs.Subjects()
}
hs.finishedHash.Write(certReq.marshal())
if _, err := c.writeRecord(recordTypeHandshake, certReq.marshal()); err != nil {
@@ -452,7 +459,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
var ok bool
// If we requested a client certificate, then the client must send a
// certificate message, even if it's empty.
- if config.ClientAuth >= RequestClientCert {
+ if c.config.ClientAuth >= RequestClientCert {
if certMsg, ok = msg.(*certificateMsg); !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(certMsg, msg)
@@ -461,7 +468,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
if len(certMsg.certificates) == 0 {
// The client didn't actually send a certificate
- switch config.ClientAuth {
+ switch c.config.ClientAuth {
case RequireAnyClientCert, RequireAndVerifyClientCert:
c.sendAlert(alertBadCertificate)
return errors.New("tls: client didn't provide a certificate")
@@ -487,12 +494,16 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}
hs.finishedHash.Write(ckx.marshal())
- preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers)
+ preMasterSecret, err := keyAgreement.processClientKeyExchange(c.config, hs.cert, ckx, c.vers)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
}
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
+ if err := c.config.writeKeyLog(hs.clientHello.random, hs.masterSecret); err != nil {
+ c.sendAlert(alertInternalError)
+ return err
+ }
// If we received a client cert in response to our certificate request message,
// the client will send us a certificateVerifyMsg immediately after the
@@ -730,6 +741,13 @@ func (hs *serverHandshakeState) processCertsFromClient(certificates [][]byte) (c
c.verifiedChains = chains
}
+ if c.config.VerifyPeerCertificate != nil {
+ if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil {
+ c.sendAlert(alertBadCertificate)
+ return nil, err
+ }
+ }
+
if len(certs) == 0 {
return nil, nil
}
@@ -788,3 +806,37 @@ func (hs *serverHandshakeState) setCipherSuite(id uint16, supportedCipherSuites
}
return false
}
+
+// suppVersArray is the backing array of ClientHelloInfo.SupportedVersions
+var suppVersArray = [...]uint16{VersionTLS12, VersionTLS11, VersionTLS10, VersionSSL30}
+
+func (hs *serverHandshakeState) clientHelloInfo() *ClientHelloInfo {
+ if hs.cachedClientHelloInfo != nil {
+ return hs.cachedClientHelloInfo
+ }
+
+ var supportedVersions []uint16
+ if hs.clientHello.vers > VersionTLS12 {
+ supportedVersions = suppVersArray[:]
+ } else if hs.clientHello.vers >= VersionSSL30 {
+ supportedVersions = suppVersArray[VersionTLS12-hs.clientHello.vers:]
+ }
+
+ signatureSchemes := make([]SignatureScheme, 0, len(hs.clientHello.signatureAndHashes))
+ for _, sah := range hs.clientHello.signatureAndHashes {
+ signatureSchemes = append(signatureSchemes, SignatureScheme(sah.hash)<<8+SignatureScheme(sah.signature))
+ }
+
+ hs.cachedClientHelloInfo = &ClientHelloInfo{
+ CipherSuites: hs.clientHello.cipherSuites,
+ ServerName: hs.clientHello.serverName,
+ SupportedCurves: hs.clientHello.supportedCurves,
+ SupportedPoints: hs.clientHello.supportedPoints,
+ SignatureSchemes: signatureSchemes,
+ SupportedProtos: hs.clientHello.alpnProtocols,
+ SupportedVersions: supportedVersions,
+ Conn: hs.c.conn,
+ }
+
+ return hs.cachedClientHelloInfo
+}
diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go
index 9ae5d11fc18..bcd3d43ea3c 100644
--- a/libgo/go/crypto/tls/handshake_server_test.go
+++ b/libgo/go/crypto/tls/handshake_server_test.go
@@ -130,7 +130,7 @@ func TestNoRC4ByDefault(t *testing.T) {
cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
compressionMethods: []uint8{compressionNone},
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
// Reset the enabled cipher suites to nil in order to test the
// defaults.
serverConfig.CipherSuites = nil
@@ -147,7 +147,7 @@ func TestDontSelectECDSAWithRSAKey(t *testing.T) {
supportedCurves: []CurveID{CurveP256},
supportedPoints: []uint8{pointFormatUncompressed},
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
serverConfig.CipherSuites = clientHello.cipherSuites
serverConfig.Certificates = make([]Certificate, 1)
serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
@@ -172,7 +172,7 @@ func TestDontSelectRSAWithECDSAKey(t *testing.T) {
supportedCurves: []CurveID{CurveP256},
supportedPoints: []uint8{pointFormatUncompressed},
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
serverConfig.CipherSuites = clientHello.cipherSuites
// First test that it *does* work when the server's key is RSA.
testClientHello(t, serverConfig, clientHello)
@@ -206,7 +206,8 @@ func TestRenegotiationExtension(t *testing.T) {
buf = make([]byte, 1024)
n, err := c.Read(buf)
if err != nil {
- t.Fatalf("Server read returned error: %s", err)
+ t.Errorf("Server read returned error: %s", err)
+ return
}
buf = buf[:n]
c.Close()
@@ -265,7 +266,7 @@ func TestTLS12OnlyCipherSuites(t *testing.T) {
reply, clientErr = cli.readHandshake()
c.Close()
}()
- config := testConfig.clone()
+ config := testConfig.Clone()
config.CipherSuites = clientHello.cipherSuites
Server(s, config).Handshake()
s.Close()
@@ -558,6 +559,8 @@ func (test *serverTest) loadData() (flows [][]byte, err error) {
}
func (test *serverTest) run(t *testing.T, write bool) {
+ checkOpenSSLVersion(t)
+
var clientConn, serverConn net.Conn
var recordingConn *recordingConn
var childProcess *exec.Cmd
@@ -658,6 +661,7 @@ func (test *serverTest) run(t *testing.T, write bool) {
}
func runServerTestForVersion(t *testing.T, template *serverTest, prefix, option string) {
+ setParallel(t)
test := *template
test.name = prefix + test.name
if len(test.command) == 0 {
@@ -732,7 +736,7 @@ func TestHandshakeServerAES256GCMSHA384(t *testing.T) {
}
func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.Certificates = make([]Certificate, 1)
config.Certificates[0].Certificate = [][]byte{testECDSACertificate}
config.Certificates[0].PrivateKey = testECDSAPrivateKey
@@ -747,8 +751,20 @@ func TestHandshakeServerECDHEECDSAAES(t *testing.T) {
runServerTestTLS12(t, test)
}
+func TestHandshakeServerX25519(t *testing.T) {
+ config := testConfig.Clone()
+ config.CurvePreferences = []CurveID{X25519}
+
+ test := &serverTest{
+ name: "X25519-ECDHE-RSA-AES-GCM",
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "ECDHE-RSA-AES128-GCM-SHA256"},
+ config: config,
+ }
+ runServerTestTLS12(t, test)
+}
+
func TestHandshakeServerALPN(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.NextProtos = []string{"proto1", "proto2"}
test := &serverTest{
@@ -769,7 +785,7 @@ func TestHandshakeServerALPN(t *testing.T) {
}
func TestHandshakeServerALPNNoMatch(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.NextProtos = []string{"proto3"}
test := &serverTest{
@@ -804,7 +820,7 @@ func TestHandshakeServerSNI(t *testing.T) {
// TestHandshakeServerSNICertForName is similar to TestHandshakeServerSNI, but
// tests the dynamic GetCertificate method
func TestHandshakeServerSNIGetCertificate(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
// Replace the NameToCertificate map with a GetCertificate function
nameToCert := config.NameToCertificate
@@ -826,7 +842,7 @@ func TestHandshakeServerSNIGetCertificate(t *testing.T) {
// GetCertificate method doesn't return a cert, we fall back to what's in
// the NameToCertificate map.
func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
return nil, nil
@@ -844,7 +860,7 @@ func TestHandshakeServerSNIGetCertificateNotFound(t *testing.T) {
func TestHandshakeServerSNIGetCertificateError(t *testing.T) {
const errMsg = "TestHandshakeServerSNIGetCertificateError error"
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
return nil, errors.New(errMsg)
}
@@ -863,7 +879,7 @@ func TestHandshakeServerSNIGetCertificateError(t *testing.T) {
func TestHandshakeServerEmptyCertificates(t *testing.T) {
const errMsg = "TestHandshakeServerEmptyCertificates error"
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
serverConfig.GetCertificate = func(clientHello *ClientHelloInfo) (*Certificate, error) {
return nil, errors.New(errMsg)
}
@@ -891,7 +907,7 @@ func TestHandshakeServerEmptyCertificates(t *testing.T) {
// TestCipherSuiteCertPreferance ensures that we select an RSA ciphersuite with
// an RSA certificate and an ECDSA ciphersuite with an ECDSA certificate.
func TestCipherSuiteCertPreferenceECDSA(t *testing.T) {
- config := testConfig.clone()
+ config := testConfig.Clone()
config.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}
config.PreferServerCipherSuites = true
@@ -901,7 +917,7 @@ func TestCipherSuiteCertPreferenceECDSA(t *testing.T) {
}
runServerTestTLS12(t, test)
- config = testConfig.clone()
+ config = testConfig.Clone()
config.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA}
config.Certificates = []Certificate{
{
@@ -925,13 +941,13 @@ func TestResumption(t *testing.T) {
test := &serverTest{
name: "IssueTicket",
- command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_out", sessionFilePath},
+ command: []string{"openssl", "s_client", "-cipher", "AES128-SHA", "-sess_out", sessionFilePath},
}
runServerTestTLS12(t, test)
test = &serverTest{
name: "Resume",
- command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_in", sessionFilePath},
+ command: []string{"openssl", "s_client", "-cipher", "AES128-SHA", "-sess_in", sessionFilePath},
}
runServerTestTLS12(t, test)
}
@@ -940,11 +956,11 @@ func TestResumptionDisabled(t *testing.T) {
sessionFilePath := tempFile("")
defer os.Remove(sessionFilePath)
- config := testConfig.clone()
+ config := testConfig.Clone()
test := &serverTest{
name: "IssueTicketPreDisable",
- command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_out", sessionFilePath},
+ command: []string{"openssl", "s_client", "-cipher", "AES128-SHA", "-sess_out", sessionFilePath},
config: config,
}
runServerTestTLS12(t, test)
@@ -953,7 +969,7 @@ func TestResumptionDisabled(t *testing.T) {
test = &serverTest{
name: "ResumeDisabled",
- command: []string{"openssl", "s_client", "-cipher", "RC4-SHA", "-sess_in", sessionFilePath},
+ command: []string{"openssl", "s_client", "-cipher", "AES128-SHA", "-sess_in", sessionFilePath},
config: config,
}
runServerTestTLS12(t, test)
@@ -976,40 +992,40 @@ func TestFallbackSCSV(t *testing.T) {
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.
+// clientCertificatePEM and clientKeyPEM were generated with generate_cert.go
+// Thus, they have no ExtKeyUsage fields and trigger an error when verification
+// is turned on.
const clientCertificatePEM = `
-----BEGIN CERTIFICATE-----
-MIIB7TCCAVigAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD
-bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTExMTIwODA3NTUxMloXDTEyMTIwNzA4
-MDAxMlowJjEQMA4GA1UEChMHQWNtZSBDbzESMBAGA1UEAxMJMTI3LjAuMC4xMIGc
-MAsGCSqGSIb3DQEBAQOBjAAwgYgCgYBO0Hsx44Jk2VnAwoekXh6LczPHY1PfZpIG
-hPZk1Y/kNqcdK+izIDZFI7Xjla7t4PUgnI2V339aEu+H5Fto5OkOdOwEin/ekyfE
-ARl6vfLcPRSr0FTKIQzQTW6HLlzF0rtNS0/Otiz3fojsfNcCkXSmHgwa2uNKWi7e
-E5xMQIhZkwIDAQABozIwMDAOBgNVHQ8BAf8EBAMCAKAwDQYDVR0OBAYEBAECAwQw
-DwYDVR0jBAgwBoAEAQIDBDALBgkqhkiG9w0BAQUDgYEANh+zegx1yW43RmEr1b3A
-p0vMRpqBWHyFeSnIyMZn3TJWRSt1tukkqVCavh9a+hoV2cxVlXIWg7nCto/9iIw4
-hB2rXZIxE0/9gzvGnfERYraL7KtnvshksBFQRlgXa5kc0x38BvEO5ZaoDPl4ILdE
-GFGNEH5PlGffo05wc46QkYU=
+MIIB7zCCAVigAwIBAgIQXBnBiWWDVW/cC8m5k5/pvDANBgkqhkiG9w0BAQsFADAS
+MRAwDgYDVQQKEwdBY21lIENvMB4XDTE2MDgxNzIxNTIzMVoXDTE3MDgxNzIxNTIz
+MVowEjEQMA4GA1UEChMHQWNtZSBDbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAum+qhr3Pv5/y71yUYHhv6BPy0ZZvzdkybiI3zkH5yl0prOEn2mGi7oHLEMff
+NFiVhuk9GeZcJ3NgyI14AvQdpJgJoxlwaTwlYmYqqyIjxXuFOE8uCXMyp70+m63K
+hAfmDzr/d8WdQYUAirab7rCkPy1MTOZCPrtRyN1IVPQMjkcCAwEAAaNGMEQwDgYD
+VR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAw
+DwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0BAQsFAAOBgQBGq0Si+yhU+Fpn+GKU
+8ZqyGJ7ysd4dfm92lam6512oFmyc9wnTN+RLKzZ8Aa1B0jLYw9KT+RBrjpW5LBeK
+o0RIvFkTgxYEiKSBXCUNmAysEbEoVr4dzWFihAm/1oDGRY2CLLTYg5vbySK3KhIR
+e/oCO8HJ/+rJnahJ05XX1Q7lNQ==
-----END CERTIFICATE-----`
const clientKeyPEM = `
-----BEGIN RSA PRIVATE KEY-----
-MIICWgIBAAKBgE7QezHjgmTZWcDCh6ReHotzM8djU99mkgaE9mTVj+Q2px0r6LMg
-NkUjteOVru3g9SCcjZXff1oS74fkW2jk6Q507ASKf96TJ8QBGXq98tw9FKvQVMoh
-DNBNbocuXMXSu01LT862LPd+iOx81wKRdKYeDBra40paLt4TnExAiFmTAgMBAAEC
-gYBxvXd8yNteFTns8A/2yomEMC4yeosJJSpp1CsN3BJ7g8/qTnrVPxBy+RU+qr63
-t2WquaOu/cr5P8iEsa6lk20tf8pjKLNXeX0b1RTzK8rJLbS7nGzP3tvOhL096VtQ
-dAo4ROEaro0TzYpHmpciSvxVIeEIAAdFDObDJPKqcJAxyQJBAJizfYgK8Gzx9fsx
-hxp+VteCbVPg2euASH5Yv3K5LukRdKoSzHE2grUVQgN/LafC0eZibRanxHegYSr7
-7qaswKUCQQCEIWor/X4XTMdVj3Oj+vpiw75y/S9gh682+myZL+d/02IEkwnB098P
-RkKVpenBHyrGg0oeN5La7URILWKj7CPXAkBKo6F+d+phNjwIFoN1Xb/RA32w/D1I
-saG9sF+UEhRt9AxUfW/U/tIQ9V0ZHHcSg1XaCM5Nvp934brdKdvTOKnJAkBD5h/3
-Rybatlvg/fzBEaJFyq09zhngkxlZOUtBVTqzl17RVvY2orgH02U4HbCHy4phxOn7
-qTdQRYlHRftgnWK1AkANibn9PRYJ7mJyJ9Dyj2QeNcSkSTzrt0tPvUMf4+meJymN
-1Ntu5+S1DLLzfxlaljWG6ylW6DNxujCyuXIV2rvA
+MIICXQIBAAKBgQC6b6qGvc+/n/LvXJRgeG/oE/LRlm/N2TJuIjfOQfnKXSms4Sfa
+YaLugcsQx980WJWG6T0Z5lwnc2DIjXgC9B2kmAmjGXBpPCViZiqrIiPFe4U4Ty4J
+czKnvT6brcqEB+YPOv93xZ1BhQCKtpvusKQ/LUxM5kI+u1HI3UhU9AyORwIDAQAB
+AoGAEJZ03q4uuMb7b26WSQsOMeDsftdatT747LGgs3pNRkMJvTb/O7/qJjxoG+Mc
+qeSj0TAZXp+PXXc3ikCECAc+R8rVMfWdmp903XgO/qYtmZGCorxAHEmR80SrfMXv
+PJnznLQWc8U9nphQErR+tTESg7xWEzmFcPKwnZd1xg8ERYkCQQDTGtrFczlB2b/Z
+9TjNMqUlMnTLIk/a/rPE2fLLmAYhK5sHnJdvDURaH2mF4nso0EGtENnTsh6LATnY
+dkrxXGm9AkEA4hXHG2q3MnhgK1Z5hjv+Fnqd+8bcbII9WW4flFs15EKoMgS1w/PJ
+zbsySaSy5IVS8XeShmT9+3lrleed4sy+UwJBAJOOAbxhfXP5r4+5R6ql66jES75w
+jUCVJzJA5ORJrn8g64u2eGK28z/LFQbv9wXgCwfc72R468BdawFSLa/m2EECQGbZ
+rWiFla26IVXV0xcD98VWJsTBZMlgPnSOqoMdM1kSEd4fUmlAYI/dFzV1XYSkOmVr
+FhdZnklmpVDeu27P4c0CQQCuCOup0FlJSBpWY1TTfun/KMBkBatMz0VMA3d7FKIU
+csPezl677Yjo8u1r/KzeI6zLg87Z8E6r6ZWNc9wBSZK6
-----END RSA PRIVATE KEY-----`
const clientECDSACertificatePEM = `
@@ -1040,6 +1056,7 @@ FMBexFe01MNvja5oHt1vzobhfm6ySD6B5U7ixohLZNz1MLvT/2XMW/TdtWo+PtAd
-----END EC PRIVATE KEY-----`
func TestClientAuth(t *testing.T) {
+ setParallel(t)
var certPath, keyPath, ecdsaCertPath, ecdsaKeyPath string
if *update {
@@ -1053,19 +1070,19 @@ func TestClientAuth(t *testing.T) {
defer os.Remove(ecdsaKeyPath)
}
- config := testConfig.clone()
+ config := testConfig.Clone()
config.ClientAuth = RequestClientCert
test := &serverTest{
name: "ClientAuthRequestedNotGiven",
- command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA"},
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA"},
config: config,
}
runServerTestTLS12(t, test)
test = &serverTest{
name: "ClientAuthRequestedAndGiven",
- command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", certPath, "-key", keyPath},
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-cert", certPath, "-key", keyPath},
config: config,
expectedPeerCerts: []string{clientCertificatePEM},
}
@@ -1073,13 +1090,189 @@ func TestClientAuth(t *testing.T) {
test = &serverTest{
name: "ClientAuthRequestedAndECDSAGiven",
- command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "RC4-SHA", "-cert", ecdsaCertPath, "-key", ecdsaKeyPath},
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA", "-cert", ecdsaCertPath, "-key", ecdsaKeyPath},
config: config,
expectedPeerCerts: []string{clientECDSACertificatePEM},
}
runServerTestTLS12(t, test)
}
+func TestSNIGivenOnFailure(t *testing.T) {
+ const expectedServerName = "test.testing"
+
+ clientHello := &clientHelloMsg{
+ vers: VersionTLS10,
+ cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ compressionMethods: []uint8{compressionNone},
+ serverName: expectedServerName,
+ }
+
+ serverConfig := testConfig.Clone()
+ // Erase the server's cipher suites to ensure the handshake fails.
+ serverConfig.CipherSuites = nil
+
+ c, s := net.Pipe()
+ go func() {
+ cli := Client(c, testConfig)
+ cli.vers = clientHello.vers
+ cli.writeRecord(recordTypeHandshake, clientHello.marshal())
+ c.Close()
+ }()
+ hs := serverHandshakeState{
+ c: Server(s, serverConfig),
+ }
+ _, err := hs.readClientHello()
+ defer s.Close()
+
+ if err == nil {
+ t.Error("No error reported from server")
+ }
+
+ cs := hs.c.ConnectionState()
+ if cs.HandshakeComplete {
+ t.Error("Handshake registered as complete")
+ }
+
+ if cs.ServerName != expectedServerName {
+ t.Errorf("Expected ServerName of %q, but got %q", expectedServerName, cs.ServerName)
+ }
+}
+
+var getConfigForClientTests = []struct {
+ setup func(config *Config)
+ callback func(clientHello *ClientHelloInfo) (*Config, error)
+ errorSubstring string
+ verify func(config *Config) error
+}{
+ {
+ nil,
+ func(clientHello *ClientHelloInfo) (*Config, error) {
+ return nil, nil
+ },
+ "",
+ nil,
+ },
+ {
+ nil,
+ func(clientHello *ClientHelloInfo) (*Config, error) {
+ return nil, errors.New("should bubble up")
+ },
+ "should bubble up",
+ nil,
+ },
+ {
+ nil,
+ func(clientHello *ClientHelloInfo) (*Config, error) {
+ config := testConfig.Clone()
+ // Setting a maximum version of TLS 1.1 should cause
+ // the handshake to fail.
+ config.MaxVersion = VersionTLS11
+ return config, nil
+ },
+ "version 301 when expecting version 302",
+ nil,
+ },
+ {
+ func(config *Config) {
+ for i := range config.SessionTicketKey {
+ config.SessionTicketKey[i] = byte(i)
+ }
+ config.sessionTicketKeys = nil
+ },
+ func(clientHello *ClientHelloInfo) (*Config, error) {
+ config := testConfig.Clone()
+ for i := range config.SessionTicketKey {
+ config.SessionTicketKey[i] = 0
+ }
+ config.sessionTicketKeys = nil
+ return config, nil
+ },
+ "",
+ func(config *Config) error {
+ // The value of SessionTicketKey should have been
+ // duplicated into the per-connection Config.
+ for i := range config.SessionTicketKey {
+ if b := config.SessionTicketKey[i]; b != byte(i) {
+ return fmt.Errorf("SessionTicketKey was not duplicated from original Config: byte %d has value %d", i, b)
+ }
+ }
+ return nil
+ },
+ },
+ {
+ func(config *Config) {
+ var dummyKey [32]byte
+ for i := range dummyKey {
+ dummyKey[i] = byte(i)
+ }
+
+ config.SetSessionTicketKeys([][32]byte{dummyKey})
+ },
+ func(clientHello *ClientHelloInfo) (*Config, error) {
+ config := testConfig.Clone()
+ config.sessionTicketKeys = nil
+ return config, nil
+ },
+ "",
+ func(config *Config) error {
+ // The session ticket keys should have been duplicated
+ // into the per-connection Config.
+ if l := len(config.sessionTicketKeys); l != 1 {
+ return fmt.Errorf("got len(sessionTicketKeys) == %d, wanted 1", l)
+ }
+ return nil
+ },
+ },
+}
+
+func TestGetConfigForClient(t *testing.T) {
+ serverConfig := testConfig.Clone()
+ clientConfig := testConfig.Clone()
+ clientConfig.MinVersion = VersionTLS12
+
+ for i, test := range getConfigForClientTests {
+ if test.setup != nil {
+ test.setup(serverConfig)
+ }
+
+ var configReturned *Config
+ serverConfig.GetConfigForClient = func(clientHello *ClientHelloInfo) (*Config, error) {
+ config, err := test.callback(clientHello)
+ configReturned = config
+ return config, err
+ }
+ c, s := net.Pipe()
+ done := make(chan error)
+
+ go func() {
+ defer s.Close()
+ done <- Server(s, serverConfig).Handshake()
+ }()
+
+ clientErr := Client(c, clientConfig).Handshake()
+ c.Close()
+
+ serverErr := <-done
+
+ if len(test.errorSubstring) == 0 {
+ if serverErr != nil || clientErr != nil {
+ t.Errorf("test[%d]: expected no error but got serverErr: %q, clientErr: %q", i, serverErr, clientErr)
+ }
+ if test.verify != nil {
+ if err := test.verify(configReturned); err != nil {
+ t.Errorf("test[%d]: verify returned error: %v", i, err)
+ }
+ }
+ } else {
+ if serverErr == nil {
+ t.Errorf("test[%d]: expected error containing %q but got no error", i, test.errorSubstring)
+ } else if !strings.Contains(serverErr.Error(), test.errorSubstring) {
+ t.Errorf("test[%d]: expected error to contain %q but it was %q", i, test.errorSubstring, serverErr)
+ }
+ }
+ }
+}
+
func bigFromString(s string) *big.Int {
ret := new(big.Int)
ret.SetString(s, 10)
@@ -1091,23 +1284,23 @@ func fromHex(s string) []byte {
return b
}
-var testRSACertificate = fromHex("30820263308201cca003020102020900a273000c8100cbf3300d06092a864886f70d01010b0500302b31173015060355040a130e476f6f676c652054455354494e473110300e06035504031307476f20526f6f74301e170d3135303130313030303030305a170d3235303130313030303030305a302631173015060355040a130e476f6f676c652054455354494e47310b300906035504031302476f30819f300d06092a864886f70d010101050003818d0030818902818100af8788f6201b95656c14ab4405af3b4514e3b76dfd00634d957ffe6a623586c04af9187cf6aa255e7a64316600baf48e92afc76bd876d4f35f41cb6e5615971b97c13c123921663d2b16d1bcdb1cc0a7dab7caadbadacbd52150ecde8dabd16b814b8902f3c4bec16c89b14484bd21d1047d9d164df98215f6effad60947f2fb0203010001a38193308190300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d0e0412041012508d896f1bd1dc544d6ecb695e06f4301b0603551d23041430128010bf3db6a966f2b840cfeab40378481a4130190603551d1104123010820e6578616d706c652e676f6c616e67300d06092a864886f70d01010b050003818100927caf91551218965931a64840d52dd5eebb02a0f5c21e7c9bb3307d3cdc76da4f3dc0faae2d33246b037b1b67591121b511bc77b9d9e06ea82d2e35fa645f223e63106bbeff14866d0df01531a814381e3b84872ccb98ed5176b9b14fdddb9b84048640fa51ddbab48debe346de46b94f86c7f9a4c24134acccf6eab0ab3918")
+var testRSACertificate = fromHex("3082024b308201b4a003020102020900e8f09d3fe25beaa6300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301a310b3009060355040a1302476f310b300906035504031302476f30819f300d06092a864886f70d010101050003818d0030818902818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d70203010001a38193308190300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d0e041204109f91161f43433e49a6de6db680d79f60301b0603551d230414301280104813494d137e1631bba301d5acab6e7b30190603551d1104123010820e6578616d706c652e676f6c616e67300d06092a864886f70d01010b0500038181009d30cc402b5b50a061cbbae55358e1ed8328a9581aa938a495a1ac315a1a84663d43d32dd90bf297dfd320643892243a00bccf9c7db74020015faad3166109a276fd13c3cce10c5ceeb18782f16c04ed73bbb343778d0c1cf10fa1d8408361c94c722b9daedb4606064df4c1b33ec0d1bd42d4dbfe3d1360845c21d33be9fae7")
-var testRSACertificateIssuer = fromHex("3082024d308201b6a003020102020827326bd913b7c43d300d06092a864886f70d01010b0500302b31173015060355040a130e476f6f676c652054455354494e473110300e06035504031307476f20526f6f74301e170d3135303130313030303030305a170d3235303130313030303030305a302b31173015060355040a130e476f6f676c652054455354494e473110300e06035504031307476f20526f6f7430819f300d06092a864886f70d010101050003818d0030818902818100f0429a7b9f66a222c8453800452db355b34c4409fee09af2510a6589bfa35bdb4d453200d1de24338d6d5e5a91cc8301628445d6eb4e675927b9c1ea5c0f676acfb0f708ce4f19827e321c1898bf86df9823d5f0b05df2b6779888eff8abbc7f41c6e7d2667386a579b8cbaad3f6fd597cd7c4b187911a425aed1b555c1965190203010001a37a3078300e0603551d0f0101ff040403020204301d0603551d250416301406082b0601050507030106082b06010505070302300f0603551d130101ff040530030101ff30190603551d0e04120410bf3db6a966f2b840cfeab40378481a41301b0603551d23041430128010bf3db6a966f2b840cfeab40378481a41300d06092a864886f70d01010b050003818100586e68c1219ed4f5782b7cfd53cf1a55750a98781b2023f8694bb831fff6d7d4aad1f0ac782b1ec787f00a8956bdd06b4a1063444fcafe955c07d679163a730802c568886a2cf8a3c2ab41176957131c4b9e077ebd7ffbb91fdad8b08b932e9aeefac04923ffdc0aa145563f7f061995317400203578f350e3e566deb29dec5e")
+var testRSACertificateIssuer = fromHex("3082021930820182a003020102020900ca5e4e811a965964300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f7430819f300d06092a864886f70d010101050003818d0030818902818100d667b378bb22f34143b6cd2008236abefaf2852adf3ab05e01329e2c14834f5105df3f3073f99dab5442d45ee5f8f57b0111c8cb682fbb719a86944eebfffef3406206d898b8c1b1887797c9c5006547bb8f00e694b7a063f10839f269f2c34fff7a1f4b21fbcd6bfdfb13ac792d1d11f277b5c5b48600992203059f2a8f8cc50203010001a35d305b300e0603551d0f0101ff040403020204301d0603551d250416301406082b0601050507030106082b06010505070302300f0603551d130101ff040530030101ff30190603551d0e041204104813494d137e1631bba301d5acab6e7b300d06092a864886f70d01010b050003818100c1154b4bab5266221f293766ae4138899bd4c5e36b13cee670ceeaa4cbdf4f6679017e2fe649765af545749fe4249418a56bd38a04b81e261f5ce86b8d5c65413156a50d12449554748c59a30c515bc36a59d38bddf51173e899820b282e40aa78c806526fd184fb6b4cf186ec728edffa585440d2b3225325f7ab580e87dd76")
var testECDSACertificate = fromHex("3082020030820162020900b8bf2d47a0d2ebf4300906072a8648ce3d04013045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c7464301e170d3132313132323135303633325a170d3232313132303135303633325a3045310b3009060355040613024155311330110603550408130a536f6d652d53746174653121301f060355040a1318496e7465726e6574205769646769747320507479204c746430819b301006072a8648ce3d020106052b81040023038186000400c4a1edbe98f90b4873367ec316561122f23d53c33b4d213dcd6b75e6f6b0dc9adf26c1bcb287f072327cb3642f1c90bcea6823107efee325c0483a69e0286dd33700ef0462dd0da09c706283d881d36431aa9e9731bd96b068c09b23de76643f1a5c7fe9120e5858b65f70dd9bd8ead5d7f5d5ccb9b69f30665b669a20e227e5bffe3b300906072a8648ce3d040103818c0030818802420188a24febe245c5487d1bacf5ed989dae4770c05e1bb62fbdf1b64db76140d311a2ceee0b7e927eff769dc33b7ea53fcefa10e259ec472d7cacda4e970e15a06fd00242014dfcbe67139c2d050ebd3fa38c25c13313830d9406bbd4377af6ec7ac9862eddd711697f857c56defb31782be4c7780daecbbe9e4e3624317b6a0f399512078f2a")
-var testSNICertificate = fromHex("308201f23082015da003020102020100300b06092a864886f70d01010530283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d301e170d3132303431313137343033355a170d3133303431313137343533355a30283110300e060355040a130741636d6520436f311430120603550403130b736e69746573742e636f6d30819d300b06092a864886f70d01010103818d0030818902818100bb79d6f517b5e5bf4610d0dc69bee62b07435ad0032d8a7a4385b71452e7a5654c2c78b8238cb5b482e5de1f953b7e62a52ca533d6fe125c7a56fcf506bffa587b263fb5cd04d3d0c921964ac7f4549f5abfef427100fe1899077f7e887d7df10439c4a22edb51c97ce3c04c3b326601cfafb11db8719a1ddbdb896baeda2d790203010001a3323030300e0603551d0f0101ff0404030200a0300d0603551d0e0406040401020304300f0603551d2304083006800401020304300b06092a864886f70d0101050381810089c6455f1c1f5ef8eb1ab174ee2439059f5c4259bb1a8d86cdb1d056f56a717da40e95ab90f59e8deaf627c157995094db0802266eb34fc6842dea8a4b68d9c1389103ab84fb9e1f85d9b5d23ff2312c8670fbb540148245a4ebafe264d90c8a4cf4f85b0fac12ac2fc4a3154bad52462868af96c62c6525d652b6e31845bdcc")
+var testSNICertificate = fromHex("0441883421114c81480804c430820237308201a0a003020102020900e8f09d3fe25beaa6300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a3023310b3009060355040a1302476f311430120603550403130b736e69746573742e636f6d30819f300d06092a864886f70d010101050003818d0030818902818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d70203010001a3773075300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d0e041204109f91161f43433e49a6de6db680d79f60301b0603551d230414301280104813494d137e1631bba301d5acab6e7b300d06092a864886f70d01010b0500038181007beeecff0230dbb2e7a334af65430b7116e09f327c3bbf918107fc9c66cb497493207ae9b4dbb045cb63d605ec1b5dd485bb69124d68fa298dc776699b47632fd6d73cab57042acb26f083c4087459bc5a3bb3ca4d878d7fe31016b7bc9a627438666566e3389bfaeebe6becc9a0093ceed18d0f9ac79d56f3a73f18188988ed")
var testRSAPrivateKey = &rsa.PrivateKey{
PublicKey: rsa.PublicKey{
- N: bigFromString("123260960069105588390096594560395120585636206567569540256061833976822892593755073841963170165000086278069699238754008398039246547214989242849418349143232951701395321381739566687846006911427966669790845430647688107009232778985142860108863460556510585049041936029324503323373417214453307648498561956908810892027L"),
+ N: bigFromString("153980389784927331788354528594524332344709972855165340650588877572729725338415474372475094155672066328274535240275856844648695200875763869073572078279316458648124537905600131008790701752441155668003033945258023841165089852359980273279085783159654751552359397986180318708491098942831252291841441726305535546071"),
E: 65537,
},
- D: bigFromString("73196363031103823625826315929954946106043759818067219550565550066527203472294428548476778865091068522665312037075674791871635825938217363523103946045078950060973913307430314113074463630778799389010335923241901501086246276485964417618981733827707048660375428006201525399194575538037883519254056917253456403553L"),
+ D: bigFromString("7746362285745539358014631136245887418412633787074173796862711588221766398229333338511838891484974940633857861775630560092874987828057333663969469797013996401149696897591265769095952887917296740109742927689053276850469671231961384712725169432413343763989564437170644270643461665184965150423819594083121075825"),
Primes: []*big.Int{
- bigFromString("11157426355495284553529769521954035649776033703833034489026848970480272318436419662860715175517581249375929775774910501512841707465207184924996975125010787L"),
- bigFromString("11047436580963564307160117670964629323534448585520694947919342920137706075617545637058809770319843170934495909554506529982972972247390145716507031692656521L"),
+ bigFromString("13299275414352936908236095374926261633419699590839189494995965049151460173257838079863316944311313904000258169883815802963543635820059341150014695560313417"),
+ bigFromString("11578103692682951732111718237224894755352163854919244905974423810539077224889290605729035287537520656160688625383765857517518932447378594964220731750802463"),
},
}
diff --git a/libgo/go/crypto/tls/handshake_test.go b/libgo/go/crypto/tls/handshake_test.go
index f95f274ab41..8e5410a17de 100644
--- a/libgo/go/crypto/tls/handshake_test.go
+++ b/libgo/go/crypto/tls/handshake_test.go
@@ -13,9 +13,11 @@ import (
"io"
"io/ioutil"
"net"
+ "os/exec"
"strconv"
"strings"
"sync"
+ "testing"
)
// TLS reference tests run a connection against a reference implementation
@@ -35,7 +37,52 @@ import (
// generate fresh random numbers, large parts of the reference connection will
// always change.
-var update = flag.Bool("update", false, "update golden files on disk")
+var (
+ update = flag.Bool("update", false, "update golden files on disk")
+
+ opensslVersionTestOnce sync.Once
+ opensslVersionTestErr error
+)
+
+func checkOpenSSLVersion(t *testing.T) {
+ opensslVersionTestOnce.Do(testOpenSSLVersion)
+ if opensslVersionTestErr != nil {
+ t.Fatal(opensslVersionTestErr)
+ }
+}
+
+func testOpenSSLVersion() {
+ // This test ensures that the version of OpenSSL looks reasonable
+ // before updating the test data.
+
+ if !*update {
+ return
+ }
+
+ openssl := exec.Command("openssl", "version")
+ output, err := openssl.CombinedOutput()
+ if err != nil {
+ opensslVersionTestErr = err
+ return
+ }
+
+ version := string(output)
+ if strings.HasPrefix(version, "OpenSSL 1.1.0") {
+ return
+ }
+
+ println("***********************************************")
+ println("")
+ println("You need to build OpenSSL 1.1.0 from source in order")
+ println("to update the test data.")
+ println("")
+ println("Configure it with:")
+ println("./Configure enable-weak-ssl-ciphers enable-ssl3 enable-ssl3-method -static linux-x86_64")
+ println("and then add the apps/ directory at the front of your PATH.")
+ println("***********************************************")
+
+ opensslVersionTestErr = errors.New("version of OpenSSL does not appear to be suitable for updating test data")
+}
// 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
@@ -88,21 +135,33 @@ func (r *recordingConn) Write(b []byte) (n int, err error) {
}
// WriteTo writes Go source code to w that contains the recorded traffic.
-func (r *recordingConn) WriteTo(w io.Writer) {
+func (r *recordingConn) WriteTo(w io.Writer) (int64, error) {
// TLS always starts with a client to server flow.
clientToServer := true
-
+ var written int64
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)
+ n, err := fmt.Fprintf(w, ">>> Flow %d (%s to %s)\n", i+1, source, dest)
+ written += int64(n)
+ if err != nil {
+ return written, err
+ }
dumper := hex.Dumper(w)
- dumper.Write(flow)
- dumper.Close()
+ n, err = dumper.Write(flow)
+ written += int64(n)
+ if err != nil {
+ return written, err
+ }
+ err = dumper.Close()
+ if err != nil {
+ return written, err
+ }
clientToServer = !clientToServer
}
+ return written, nil
}
func parseTestData(r io.Reader) (flows [][]byte, err error) {
diff --git a/libgo/go/crypto/tls/key_agreement.go b/libgo/go/crypto/tls/key_agreement.go
index 467efb2bf5c..1b27c049ed3 100644
--- a/libgo/go/crypto/tls/key_agreement.go
+++ b/libgo/go/crypto/tls/key_agreement.go
@@ -16,6 +16,8 @@ import (
"errors"
"io"
"math/big"
+
+ "golang_org/x/crypto/curve25519"
)
var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
@@ -177,52 +179,71 @@ type ecdheKeyAgreement struct {
version uint16
sigType uint8
privateKey []byte
- curve elliptic.Curve
- x, y *big.Int
+ curveid CurveID
+
+ // publicKey is used to store the peer's public value when X25519 is
+ // being used.
+ publicKey []byte
+ // x and y are used to store the peer's public value when one of the
+ // NIST curves is being used.
+ x, y *big.Int
}
func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
- var curveid CurveID
preferredCurves := config.curvePreferences()
NextCandidate:
for _, candidate := range preferredCurves {
for _, c := range clientHello.supportedCurves {
if candidate == c {
- curveid = c
+ ka.curveid = c
break NextCandidate
}
}
}
- if curveid == 0 {
+ if ka.curveid == 0 {
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 ecdhePublic []byte
- var x, y *big.Int
- var err error
- ka.privateKey, x, y, err = elliptic.GenerateKey(ka.curve, config.rand())
- if err != nil {
- return nil, err
+ if ka.curveid == X25519 {
+ var scalar, public [32]byte
+ if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil {
+ return nil, err
+ }
+
+ curve25519.ScalarBaseMult(&public, &scalar)
+ ka.privateKey = scalar[:]
+ ecdhePublic = public[:]
+ } else {
+ curve, ok := curveForCurveID(ka.curveid)
+ if !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(curve, config.rand())
+ if err != nil {
+ return nil, err
+ }
+ ecdhePublic = elliptic.Marshal(curve, x, y)
}
- ecdhePublic := elliptic.Marshal(ka.curve, x, y)
// http://tools.ietf.org/html/rfc4492#section-5.4
serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic))
serverECDHParams[0] = 3 // named curve
- serverECDHParams[1] = byte(curveid >> 8)
- serverECDHParams[2] = byte(curveid)
+ serverECDHParams[1] = byte(ka.curveid >> 8)
+ serverECDHParams[2] = byte(ka.curveid)
serverECDHParams[3] = byte(len(ecdhePublic))
copy(serverECDHParams[4:], ecdhePublic)
sigAndHash := signatureAndHash{signature: ka.sigType}
if ka.version >= VersionTLS12 {
+ var err error
if sigAndHash.hash, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes); err != nil {
return nil, err
}
@@ -281,15 +302,32 @@ func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Cert
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
return nil, errClientKeyExchange
}
- x, y := elliptic.Unmarshal(ka.curve, ckx.ciphertext[1:])
+
+ if ka.curveid == X25519 {
+ if len(ckx.ciphertext) != 1+32 {
+ return nil, errClientKeyExchange
+ }
+
+ var theirPublic, sharedKey, scalar [32]byte
+ copy(theirPublic[:], ckx.ciphertext[1:])
+ copy(scalar[:], ka.privateKey)
+ curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic)
+ return sharedKey[:], nil
+ }
+
+ curve, ok := curveForCurveID(ka.curveid)
+ if !ok {
+ panic("internal error")
+ }
+ x, y := elliptic.Unmarshal(curve, ckx.ciphertext[1:])
if x == nil {
return nil, errClientKeyExchange
}
- if !ka.curve.IsOnCurve(x, y) {
+ if !curve.IsOnCurve(x, y) {
return nil, errClientKeyExchange
}
- x, _ = ka.curve.ScalarMult(x, y, ka.privateKey)
- preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
+ x, _ = curve.ScalarMult(x, y, ka.privateKey)
+ preMasterSecret := make([]byte, (curve.Params().BitSize+7)>>3)
xBytes := x.Bytes()
copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
@@ -303,31 +341,40 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
if skx.key[0] != 3 { // named curve
return errors.New("tls: server selected unsupported curve")
}
- curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
-
- var ok bool
- if ka.curve, ok = curveForCurveID(curveid); !ok {
- return errors.New("tls: server selected unsupported curve")
- }
+ ka.curveid = CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
publicLen := int(skx.key[3])
if publicLen+4 > len(skx.key) {
return errServerKeyExchange
}
- ka.x, ka.y = elliptic.Unmarshal(ka.curve, skx.key[4:4+publicLen])
- if ka.x == nil {
- return errServerKeyExchange
- }
- if !ka.curve.IsOnCurve(ka.x, ka.y) {
- return errServerKeyExchange
- }
serverECDHParams := skx.key[:4+publicLen]
+ publicKey := serverECDHParams[4:]
sig := skx.key[4+publicLen:]
if len(sig) < 2 {
return errServerKeyExchange
}
+ if ka.curveid == X25519 {
+ if len(publicKey) != 32 {
+ return errors.New("tls: bad X25519 public value")
+ }
+ ka.publicKey = publicKey
+ } else {
+ curve, ok := curveForCurveID(ka.curveid)
+ if !ok {
+ return errors.New("tls: server selected unsupported curve")
+ }
+
+ ka.x, ka.y = elliptic.Unmarshal(curve, publicKey)
+ if ka.x == nil {
+ return errServerKeyExchange
+ }
+ if !curve.IsOnCurve(ka.x, ka.y) {
+ return errServerKeyExchange
+ }
+ }
+
sigAndHash := signatureAndHash{signature: ka.sigType}
if ka.version >= VersionTLS12 {
// handle SignatureAndHashAlgorithm
@@ -382,19 +429,40 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
}
func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
- if ka.curve == nil {
+ if ka.curveid == 0 {
return nil, nil, errors.New("tls: missing ServerKeyExchange message")
}
- priv, mx, my, err := elliptic.GenerateKey(ka.curve, config.rand())
- if err != nil {
- return nil, nil, err
- }
- x, _ := ka.curve.ScalarMult(ka.x, ka.y, priv)
- preMasterSecret := make([]byte, (ka.curve.Params().BitSize+7)>>3)
- xBytes := x.Bytes()
- copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
- serialized := elliptic.Marshal(ka.curve, mx, my)
+ var serialized, preMasterSecret []byte
+
+ if ka.curveid == X25519 {
+ var ourPublic, theirPublic, sharedKey, scalar [32]byte
+
+ if _, err := io.ReadFull(config.rand(), scalar[:]); err != nil {
+ return nil, nil, err
+ }
+
+ copy(theirPublic[:], ka.publicKey)
+ curve25519.ScalarBaseMult(&ourPublic, &scalar)
+ curve25519.ScalarMult(&sharedKey, &scalar, &theirPublic)
+ serialized = ourPublic[:]
+ preMasterSecret = sharedKey[:]
+ } else {
+ curve, ok := curveForCurveID(ka.curveid)
+ if !ok {
+ panic("internal error")
+ }
+ priv, mx, my, err := elliptic.GenerateKey(curve, config.rand())
+ if err != nil {
+ return nil, nil, err
+ }
+ x, _ := curve.ScalarMult(ka.x, ka.y, priv)
+ preMasterSecret = make([]byte, (curve.Params().BitSize+7)>>3)
+ xBytes := x.Bytes()
+ copy(preMasterSecret[len(preMasterSecret)-len(xBytes):], xBytes)
+
+ serialized = elliptic.Marshal(curve, mx, my)
+ }
ckx := new(clientKeyExchangeMsg)
ckx.ciphertext = make([]byte, 1+len(serialized))
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA
index a62d27d5e3d..099cef4ba9a 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA
@@ -1,19 +1,20 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 59 02 00 00 55 03 01 38 1a 94 8d 84 |....Y...U..8....|
-00000010 d7 a4 29 89 50 ad 07 97 5b c0 2c 7b 8c a6 75 0e |..).P...[.,{..u.|
-00000020 97 51 62 10 07 87 c5 6f 0a 5f 86 20 1d ac 1d 05 |.Qb....o._. ....|
-00000030 ea 85 48 84 73 d9 07 8d d0 81 56 99 81 10 7b 18 |..H.s.....V...{.|
-00000040 e8 5e da a9 fe cd f9 91 88 31 9b 6e c0 09 00 00 |.^.......1.n....|
+00000000 16 03 01 00 59 02 00 00 55 03 01 4f 5d 09 43 37 |....Y...U..O].C7|
+00000010 70 c6 d9 8b 07 ca 1a f0 fb a7 05 51 53 67 7a 7e |p..........QSgz~|
+00000020 c9 c6 68 10 10 2a 69 bd 47 db 8e 20 f2 13 5b 26 |..h..*i.G.. ..[&|
+00000030 e6 8e 19 b0 bc b5 ee 1f ca 44 5d 32 11 37 b0 78 |.........D]2.7.x|
+00000040 49 16 6e c2 44 86 52 3f 9f 05 15 aa c0 09 00 00 |I.n.D.R?........|
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....|
@@ -48,21 +49,20 @@
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 01 00 d5 0c 00 00 d1 03 00 17 41 04 68 |*............A.h|
-00000280 37 18 3d 57 d2 5a 39 75 1e 7f 0a 3a 47 65 36 2e |7.=W.Z9u...:Ge6.|
-00000290 6d cb 8f aa 0f 0d 45 5e 3f 14 82 f5 8c b1 11 0a |m.....E^?.......|
-000002a0 8f e0 bc e4 07 d3 d5 bf 2d f4 82 ba cf c9 1c 88 |........-.......|
-000002b0 33 72 a8 49 39 48 40 74 c6 96 c3 30 72 31 34 00 |3r.I9H@t...0r14.|
-000002c0 8a 30 81 87 02 41 0e 43 2d 29 81 e9 c3 07 fc 5c |.0...A.C-).....\|
-000002d0 ad c0 51 9e 0f cf c5 77 e4 bf 00 b6 66 f9 0e c6 |..Q....w....f...|
-000002e0 40 c6 b5 49 a4 04 05 31 2c 7c 1f 24 38 80 1b 3f |@..I...1,|.$8..?|
-000002f0 16 5f c7 4d a8 7d 98 50 7f 7d 6d ed e9 19 1d 19 |._.M.}.P.}m.....|
-00000300 7b fd ec c5 4d 18 ab 02 42 01 00 db 37 b7 fa 39 |{...M...B...7..9|
-00000310 4b 3f 16 06 eb b8 4a 22 c6 de 00 d8 a7 eb a2 9e |K?....J"........|
-00000320 e1 6f f4 a4 32 e2 ca d0 72 3a e5 f3 14 27 a0 dd |.o..2...r:...'..|
-00000330 c4 26 34 b3 6c a3 d0 03 90 7a 2e 0e bf 0b 63 63 |.&4.l....z....cc|
-00000340 77 66 37 dd 1a 0f 7a 90 3f c8 a9 16 03 01 00 0e |wf7...z.?.......|
-00000350 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |.......@......|
+00000270 2a 16 03 01 00 b5 0c 00 00 b1 03 00 1d 20 56 b4 |*............ V.|
+00000280 39 d4 8f 18 79 87 89 d0 04 ee 12 54 20 2b be c1 |9...y......T +..|
+00000290 94 99 40 a2 73 df 1e 92 66 0b d1 f1 d6 38 00 8b |..@.s...f....8..|
+000002a0 30 81 88 02 42 01 38 12 59 bd ea 44 59 f4 6f a9 |0...B.8.Y..DY.o.|
+000002b0 8e 9e a0 85 b5 b3 55 3e 76 49 b7 75 98 6e 81 30 |......U>vI.u.n.0|
+000002c0 c4 73 bd 54 78 39 f7 e2 22 49 4c 93 0d c1 26 89 |.s.Tx9.."IL...&.|
+000002d0 08 b9 9c 8b 86 3e 81 2c a5 50 7c e9 88 ec c0 ad |.....>.,.P|.....|
+000002e0 9e e0 40 ac 4e 0a fd 02 42 01 2e 0d 37 73 6a 0d |..@.N...B...7sj.|
+000002f0 a4 60 08 a0 2b 32 0f 87 8d f8 9b c7 68 cf 50 79 |.`..+2......h.Py|
+00000300 73 f7 cf 93 aa 75 57 20 58 3d 13 c0 f3 66 7d 59 |s....uW X=...f}Y|
+00000310 15 73 d4 29 03 34 df 33 00 c0 b5 71 bc 2a 90 ef |.s.).4.3...q.*..|
+00000320 3c 02 5e ea 9d 29 93 1c 18 db 04 16 03 01 00 0a |<.^..)..........|
+00000330 0d 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e |.......@........|
+00000340 00 00 00 |...|
>>> Flow 3 (client to server)
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|
@@ -97,34 +97,32 @@
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 41 51 c5 53 a8 0f cb |.....0...AQ.S...|
-00000270 18 79 4a 59 53 62 17 bb 29 39 fa cd 56 6c 5c 29 |.yJYSb..)9..Vl\)|
-00000280 1f e3 bc df fb 9a 29 fa 38 1a 73 aa 4c 79 6b 1c |......).8.s.Lyk.|
-00000290 9f 1c 8e 95 c7 11 cc df 5d e9 c7 93 ce a3 9b e6 |........].......|
-000002a0 94 17 24 3a 8e f8 9a a9 46 01 f9 02 42 01 a1 df |..$:....F...B...|
-000002b0 c5 cc fe 8d 5b 34 fb 89 2f f5 b3 3f 75 d7 19 1b |....[4../..?u...|
-000002c0 5e 0f 1a 2e 8f 2d 62 61 73 85 2c 03 3b 22 07 2f |^....-bas.,.;"./|
-000002d0 6b f3 5c fb ba b2 87 54 1c ef d2 f8 82 f3 9e f8 |k.\....T........|
-000002e0 ce 1b fa ce b0 6d d0 85 f8 62 6e d6 ba 93 cc 14 |.....m...bn.....|
-000002f0 03 01 00 01 01 16 03 01 00 30 76 90 a8 a2 8d 25 |.........0v....%|
-00000300 c5 c2 ff ef 2b 76 83 2c 7a 0d 44 37 99 67 02 d3 |....+v.,z.D7.g..|
-00000310 6e 3b 28 83 21 cf f5 6a 71 61 2d 5b 24 57 b2 19 |n;(.!..jqa-[$W..|
-00000320 63 d4 e5 96 0c 0c e1 f3 3a 99 |c.......:.|
+00000210 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b|
+00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......|
+00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 91 0f 00 |...._X.;t.......|
+00000240 00 8d 00 8b 30 81 88 02 42 01 53 2c a8 59 57 d2 |....0...B.S,.YW.|
+00000250 fc 0b 12 27 6f 9a f7 4e a0 dd 2c af 1b 4c 81 0b |...'o..N..,..L..|
+00000260 97 79 7e 6f dd a1 cf cb e2 14 4d af 76 99 d8 06 |.y~o......M.v...|
+00000270 4f 8d 4f 86 d3 25 04 ea 80 02 ae 25 10 9d 2d 59 |O.O..%.....%..-Y|
+00000280 11 39 65 6b 83 d0 16 7d bf a8 a4 02 42 01 f2 16 |.9ek...}....B...|
+00000290 6c f1 e6 3b b1 af fb 3f 99 f0 8a e3 c8 62 ba 71 |l..;...?.....b.q|
+000002a0 12 a1 2c 1e 15 74 d5 98 b5 ae 9f 50 a2 15 9b 73 |..,..t.....P...s|
+000002b0 9a 5f 2c 90 d4 9d 20 6f 35 b6 32 3e f4 b7 dd 50 |._,... o5.2>...P|
+000002c0 64 42 e3 4e 51 f3 11 4b b4 9e a3 92 a2 10 59 14 |dB.NQ..K......Y.|
+000002d0 03 01 00 01 01 16 03 01 00 30 78 8c 7c 31 ce 16 |.........0x.|1..|
+000002e0 8f 1f 2a b9 ee cb 72 7f 1e 59 5b ad c2 58 32 77 |..*...r..Y[..X2w|
+000002f0 fa 46 83 b9 67 0c 5f 41 25 6a 38 ec 20 d2 80 e6 |.F..g._A%j8. ...|
+00000300 be 85 ce 94 b1 89 5f 8d 17 9b |......_...|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 37 f0 ad 4c 11 |..........07..L.|
-00000010 6d fb 54 90 13 d2 10 93 43 d8 be 3b d0 2b 14 a5 |m.T.....C..;.+..|
-00000020 9d fb a6 5d 38 e0 f5 e9 a6 0a 8e 3d 99 a2 ec 96 |...]8......=....|
-00000030 d8 ff 90 13 03 99 33 d7 15 29 5f |......3..)_|
+00000000 14 03 01 00 01 01 16 03 01 00 30 95 d6 f2 a2 75 |..........0....u|
+00000010 0e f8 c7 7c f9 1d 65 b4 82 08 c9 62 aa 93 24 8f |...|..e....b..$.|
+00000020 4d 11 c7 b0 17 04 f1 0a 8b be 64 06 f9 07 20 0b |M.........d... .|
+00000030 f0 3b 92 db 62 ba 63 91 a1 58 fe |.;..b.c..X.|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 20 f9 59 b0 e2 8b f9 2c dd 30 1b 8f |.... .Y....,.0..|
-00000010 df 85 0f 17 88 23 5e ca c9 d3 ca 5f 52 d4 33 e0 |.....#^...._R.3.|
-00000020 d2 62 54 17 f2 17 03 01 00 20 62 2d 28 d2 55 68 |.bT...... b-(.Uh|
-00000030 77 ab 6e c0 ac d9 cd 31 1c 38 aa 07 b3 e8 0d 89 |w.n....1.8......|
-00000040 7e e4 f3 a0 65 84 f6 b8 c8 91 15 03 01 00 20 b5 |~...e......... .|
-00000050 95 69 90 d7 32 d1 5a a5 e0 e2 6c 0a dc 00 1c 5e |.i..2.Z...l....^|
-00000060 d2 10 2b a2 3e ae a5 b2 63 9f c4 4e 62 56 db |..+.>...c..NbV.|
+00000000 17 03 01 00 20 3e a4 b5 b5 2f 4f c8 e0 08 cf 8a |.... >.../O.....|
+00000010 9c f6 69 94 a9 91 0f 5d c5 06 ee 71 e2 42 11 b4 |..i....]...q.B..|
+00000020 a8 17 54 19 3d 17 03 01 00 20 ce d2 8d 8a 78 e4 |..T.=.... ....x.|
+00000030 15 a4 ab 83 0d 9c fa 47 1c 8f 2d 87 a8 55 65 9d |.......G..-..Ue.|
+00000040 7f 03 75 11 62 83 0b 44 0b f1 15 03 01 00 20 eb |..u.b..D...... .|
+00000050 1a 46 95 1e 1b 10 b7 25 a8 c4 5b db 8b 3c 61 c9 |.F.....%..[..<a.|
+00000060 25 38 27 1e 69 11 18 16 0a 25 44 ad 9f 52 64 |%8'.i....%D..Rd|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA
index 298cbe1df53..7e9c2724abd 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA
@@ -1,60 +1,72 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 51 02 00 00 4d 03 01 4e 15 d3 06 f6 |....Q...M..N....|
-00000010 ec 13 16 c5 fa 59 cf 5e 2f ad 85 b9 38 e7 7f fb |.....Y.^/...8...|
-00000020 85 cb da eb f2 2e 17 51 a2 b0 be 20 61 e4 32 c9 |.......Q... a.2.|
-00000030 66 92 36 89 0c 0c f4 00 15 47 86 d9 e9 90 ab 2d |f.6......G.....-|
-00000040 8f a3 e2 5e f6 44 2c 6a 1d 98 88 5c 00 05 00 00 |...^.D,j...\....|
-00000050 05 ff 01 00 01 00 16 03 01 02 71 0b 00 02 6d 00 |..........q...m.|
-00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 01 00 |..A4......9.....|
-000002d0 0e 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |........@......|
+00000000 16 03 01 00 59 02 00 00 55 03 01 32 7c 5c ac bd |....Y...U..2|\..|
+00000010 77 70 c2 f8 f0 20 37 e4 e8 45 db be 97 22 e4 f3 |wp... 7..E..."..|
+00000020 24 1c c1 29 8f 02 e1 bc ba 4a 1e 20 81 6f b5 12 |$..).....J. .o..|
+00000030 c0 9d 9e de 2f b6 04 b2 74 34 da 2b 04 55 2c 4f |..../...t4.+.U,O|
+00000040 dd 01 8a 30 d9 67 45 9f f1 31 f1 78 c0 13 00 00 |...0.gE..1.x....|
+00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
+00000060 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......|
+000002c0 aa 0c 00 00 a6 03 00 1d 20 2f f7 3b 44 1a 47 85 |........ /.;D.G.|
+000002d0 d7 db 40 28 4e 6a f1 2f 1e b5 cc b0 58 0d 92 93 |..@(Nj./....X...|
+000002e0 30 41 65 08 05 f7 51 23 57 00 80 87 0d c3 22 ff |0Ae...Q#W.....".|
+000002f0 aa d1 3f 55 09 cf 98 dc 91 f8 d0 63 58 da dc 52 |..?U.......cX..R|
+00000300 03 f0 06 a6 4e 7e 5b 96 a1 3b d7 8e 1e 68 50 ef |....N~[..;...hP.|
+00000310 59 3f 78 06 eb 9a 33 c5 01 3c e0 fb c6 f1 b6 bc |Y?x...3..<......|
+00000320 5a bc 95 e8 43 d9 ab 36 05 26 13 c5 a6 68 9b e2 |Z...C..6.&...h..|
+00000330 b1 42 6e 89 60 5c b3 91 02 c5 8b ab 53 d1 d9 79 |.Bn.`\......S..y|
+00000340 d0 37 b5 5e 2c 16 72 29 f8 9c d0 4a 46 87 46 f4 |.7.^,.r)...JF.F.|
+00000350 01 2b e8 6a 4f 59 d1 2d 3d de 4b 3b 0e c7 cd 42 |.+.jOY.-=.K;...B|
+00000360 ae d2 94 e9 a6 6b 65 ad 3f 77 57 16 03 01 00 0a |.....ke.?wW.....|
+00000370 0d 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e |.......@........|
+00000380 00 00 00 |...|
>>> Flow 3 (client to server)
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|
@@ -89,33 +101,32 @@
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 73 bd 73 65 92 86 |..........s.se..|
-00000220 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 87 |#A.y......M.....|
-00000230 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 53 |.2R.k..-.......S|
-00000240 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 fe |.m.....o..#87...|
-00000250 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 65 |...U...`}p&..T.e|
-00000260 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 ff |...S_..:.3{.L...|
-00000270 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b 52 |Z.6*G.....1x..kR|
-00000280 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 4d |..........+.8..M|
-00000290 e5 78 13 4e a4 38 46 42 dc 16 16 03 01 00 91 0f |.x.N.8FB........|
-000002a0 00 00 8d 00 8b 30 81 88 02 42 01 45 b9 8f b1 1f |.....0...B.E....|
-000002b0 72 80 2c 4f 2c 65 58 db 40 7e f1 d5 14 0b cc 4c |r.,O,eX.@~.....L|
-000002c0 8b 50 5c ee 93 45 95 3d fe 00 5e 5e ca 13 56 8d |.P\..E.=..^^..V.|
-000002d0 2b b3 1a 22 70 3f d2 41 cf 74 8f c3 0f 37 ba 97 |+.."p?.A.t...7..|
-000002e0 cb 29 16 77 92 df 19 35 f9 8a a0 8e 02 42 01 00 |.).w...5.....B..|
-000002f0 3f 8b ce b1 2a 01 43 e8 2c b5 27 d1 19 bc 04 b3 |?...*.C.,.'.....|
-00000300 c3 ad bf e8 12 37 57 6f c9 01 7c 8e f4 4d 88 39 |.....7Wo..|..M.9|
-00000310 4b 00 f6 ff fd 38 39 f8 3e 7f 49 d4 6a 82 94 6a |K....89.>.I.j..j|
-00000320 d3 f4 17 f2 a9 e0 ef 85 1e 01 85 b6 ca 89 91 ee |................|
-00000330 14 03 01 00 01 01 16 03 01 00 24 8d 82 24 82 55 |..........$..$.U|
-00000340 c4 0e 45 8c f0 f3 e3 29 4e ff 6c ee 43 4b ca 68 |..E....)N.l.CK.h|
-00000350 2e 12 98 cf ce b6 7e fa 73 07 e1 0f aa 7f 80 |......~.s......|
+00000210 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b|
+00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......|
+00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 91 0f 00 |...._X.;t.......|
+00000240 00 8d 00 8b 30 81 88 02 42 01 b3 df 59 06 71 e6 |....0...B...Y.q.|
+00000250 74 c9 9d d5 2c b0 a7 f8 1e ac bc f3 5a e2 ed 0b |t...,.......Z...|
+00000260 f2 e9 37 82 c6 fe 7c 23 b9 63 6e 88 1d 63 31 ad |..7...|#.cn..c1.|
+00000270 d3 29 48 eb f3 5d 52 f5 76 ab fc 16 9e 09 4f 49 |.)H..]R.v.....OI|
+00000280 cf b4 03 6a ed db e5 13 ea 67 74 02 42 01 8e 2f |...j.....gt.B../|
+00000290 b8 12 38 c9 a6 8c 77 40 85 89 ef d8 ac 08 00 c0 |..8...w@........|
+000002a0 ee 70 68 a6 88 1f d1 67 0d 1b 7b 1f be e0 a7 b9 |.ph....g..{.....|
+000002b0 c3 7d ff 6a 39 3c b9 aa f6 78 ac 9a ca 67 55 0c |.}.j9<...x...gU.|
+000002c0 38 23 cc ab 18 c0 b9 ea 9c 84 61 32 0a 0d f3 14 |8#........a2....|
+000002d0 03 01 00 01 01 16 03 01 00 30 73 12 76 94 30 37 |.........0s.v.07|
+000002e0 e5 e3 30 59 88 2f 5f e9 f2 7b 3d 02 88 65 09 14 |..0Y./_..{=..e..|
+000002f0 68 23 02 d0 ae e5 7f 7f 8d 95 3b 1c 75 f5 1f 24 |h#........;.u..$|
+00000300 43 60 29 bb 0e 69 88 36 a9 68 |C`)..i.6.h|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 24 21 a3 eb a6 f5 |..........$!....|
-00000010 d0 17 38 9b 89 ec f3 39 23 33 f6 49 51 41 97 92 |..8....9#3.IQA..|
-00000020 a6 64 bd 60 68 9d 0e 45 06 2f dd ff 79 b6 50 |.d.`h..E./..y.P|
+00000000 14 03 01 00 01 01 16 03 01 00 30 a0 5f 7f 59 e0 |..........0._.Y.|
+00000010 b1 7e ed ad de 6a 47 94 21 e5 1b 77 a7 d0 88 fd |.~...jG.!..w....|
+00000020 9e 4e 48 87 1d cf 40 e4 b9 38 a3 2e e4 00 c3 94 |.NH...@..8......|
+00000030 95 20 1c 97 d2 a9 3a 11 86 30 5f |. ....:..0_|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 1a d2 72 d5 91 9d fc 6c 22 02 cc 32 |......r....l"..2|
-00000010 58 5c 8a f6 75 11 48 e1 3f e4 e5 81 29 63 62 15 |X\..u.H.?...)cb.|
-00000020 03 01 00 16 b6 9a 1f 43 d4 ae b7 16 25 ce ae b7 |.......C....%...|
-00000030 6c 37 f7 35 0a 26 7d ea 1f 80 |l7.5.&}...|
+00000000 17 03 01 00 20 ca 4c f5 cb 81 66 2f 97 e3 5d 8b |.... .L...f/..].|
+00000010 dd 7d dd fa fe 8c 98 45 3f 3d 16 17 98 4d b5 15 |.}.....E?=...M..|
+00000020 6c 91 8a 79 7a 17 03 01 00 20 96 ec 30 cb d3 78 |l..yz.... ..0..x|
+00000030 b9 0a a1 ab fd 12 25 d5 82 7b 7a 3c 17 56 7b b7 |......%..{z<.V{.|
+00000040 c4 6e ea a2 5b d7 6b b6 22 a9 15 03 01 00 20 ba |.n..[.k."..... .|
+00000050 ff fe 2b 60 83 34 ad 45 75 15 d5 95 b3 27 92 46 |..+`.4.Eu....'.F|
+00000060 47 ae f1 d4 a4 9d 63 ef db d9 b5 37 0f f1 74 |G.....c....7..t|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA
index ba4976df3b6..67772e174aa 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA
@@ -1,19 +1,20 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 59 02 00 00 55 03 01 eb ed 76 6a 07 |....Y...U....vj.|
-00000010 65 02 ec 6f 93 a0 38 21 09 0d d7 bf 11 20 51 eb |e..o..8!..... Q.|
-00000020 cc 00 08 9b 7a 98 c4 c5 02 ff c1 20 f9 1b c7 66 |....z...... ...f|
-00000030 35 40 8c 67 8d 7f d5 c8 28 f0 cb d2 f9 da af 7a |5@.g....(......z|
-00000040 ea 4e 42 f2 5d 44 1c cc 92 36 b1 10 c0 09 00 00 |.NB.]D...6......|
+00000000 16 03 01 00 59 02 00 00 55 03 01 ed 13 de 15 cc |....Y...U.......|
+00000010 90 4f f3 72 5a d4 7a 01 26 fa 7a ae 38 92 a0 d6 |.O.rZ.z.&.z.8...|
+00000020 70 4a 20 f6 7e 11 f7 ac e6 94 87 20 9f 37 0f 8f |pJ .~...... .7..|
+00000030 55 a6 6a 97 b8 0f 56 aa 2d 69 c5 79 01 d5 c0 01 |U.j...V.-i.y....|
+00000040 2c 2b 0e 16 d8 79 a3 f3 44 99 7c 01 c0 09 00 00 |,+...y..D.|.....|
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....|
@@ -48,82 +49,79 @@
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 34 |*............A.4|
-00000280 47 57 64 b3 20 6d eb 17 9c 36 d4 aa 78 8b 20 26 |GWd. m...6..x. &|
-00000290 6f 22 10 79 5f 96 69 62 1d ae 9f c7 40 17 1e 30 |o".y_.ib....@..0|
-000002a0 10 db d1 13 51 d8 63 61 ef 8e fb 34 d6 02 95 ac |....Q.ca...4....|
-000002b0 fb 33 72 a9 46 ff 27 b1 15 ca dd 81 8f 5a 58 00 |.3r.F.'......ZX.|
-000002c0 8a 30 81 87 02 41 5c 09 1a 87 40 f3 1a 87 84 31 |.0...A\...@....1|
-000002d0 62 6c e5 a5 c0 3c cc ba 5d 4a 5e 65 ea e0 60 83 |bl...<..]J^e..`.|
-000002e0 fe fe 99 1d 66 4a bb 6c 0d 5e 25 64 e3 92 ce eb |....fJ.l.^%d....|
-000002f0 15 39 42 a6 b0 98 a1 d3 79 65 c7 fc e7 c7 64 c7 |.9B.....ye....d.|
-00000300 69 9c 2f 7e 00 c1 a3 02 42 01 f2 61 91 ae 8e f6 |i./~....B..a....|
-00000310 88 99 70 55 32 4a fe 08 31 f0 8d d6 e6 1d fa a1 |..pU2J..1.......|
-00000320 76 b6 16 98 58 8e 46 30 b1 00 b6 dd 5d 70 bb e1 |v...X.F0....]p..|
-00000330 81 89 bd aa ac b5 7f 9b d3 c0 8b 4b c3 36 00 87 |...........K.6..|
-00000340 47 0c 34 92 27 c3 aa bd 0d 7c 36 16 03 01 00 0e |G.4.'....|6.....|
-00000350 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |.......@......|
+00000270 2a 16 03 01 00 b4 0c 00 00 b0 03 00 1d 20 ca e8 |*............ ..|
+00000280 ef 79 56 cd aa eb 12 8f e1 89 d1 3c 63 1f c8 54 |.yV........<c..T|
+00000290 5f 4e cf 6b 72 7d 1c bb f6 80 ae 17 33 69 00 8a |_N.kr}......3i..|
+000002a0 30 81 87 02 42 01 d1 45 df fc 46 21 5b 9b 49 f0 |0...B..E..F![.I.|
+000002b0 3c f2 16 65 1e 33 90 d8 be 1d 65 12 2f 46 93 5b |<..e.3....e./F.[|
+000002c0 e2 14 67 b8 67 9b c1 10 31 a1 96 b8 86 c3 8b 26 |..g.g...1......&|
+000002d0 3f da 5e 86 e7 b1 f9 3f f1 04 57 ed e6 6f a5 86 |?.^....?..W..o..|
+000002e0 f7 58 38 6e 0d ae 42 02 41 05 1b 07 9b 4c 4d 39 |.X8n..B.A....LM9|
+000002f0 2d 0c 4e d7 94 d6 86 c9 6c b9 4d 54 a2 56 87 12 |-.N.....l.MT.V..|
+00000300 08 ec 4e f1 a4 19 5e 52 69 ed 9f 6c 59 5f 31 0f |..N...^Ri..lY_1.|
+00000310 8d 33 1f a7 42 e5 56 9d 54 f4 18 9b 33 31 97 b9 |.3..B.V.T...31..|
+00000320 57 55 c9 9f ea 7d f2 9e 24 e0 16 03 01 00 0a 0d |WU...}..$.......|
+00000330 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e 00 |......@.........|
+00000340 00 00 |..|
>>> Flow 3 (client to server)
-00000000 16 03 01 01 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 1e 4d 89 4e e2 82 ca 5d 31 8a |.......M.N...]1.|
-00000260 66 c7 c2 d6 00 4d 2e 1e 94 34 61 6b 86 3d 78 60 |f....M...4ak.=x`|
-00000270 70 e1 71 93 22 df 5d 81 d3 d7 33 10 f5 01 f9 1d |p.q.".]...3.....|
-00000280 e2 4a 91 22 67 ae 5b 2f 4c d9 43 31 35 c6 01 ad |.J."g.[/L.C15...|
-00000290 59 86 03 a1 9b c5 ea a5 2d aa ef 46 5a a8 70 57 |Y.......-..FZ.pW|
-000002a0 50 59 ea 7a 07 32 bb a6 a1 11 33 05 d8 88 2e 42 |PY.z.2....3....B|
-000002b0 d8 7b f7 34 be 5e 5f 42 9f 6a 90 ed d7 4b c4 7e |.{.4.^_B.j...K.~|
-000002c0 f9 5c a5 ff 28 f8 a1 f1 8f 1c e0 7a 37 a0 49 e5 |.\..(......z7.I.|
-000002d0 ce 11 46 ef 5f 06 14 03 01 00 01 01 16 03 01 00 |..F._...........|
-000002e0 30 cb 08 f0 3c d4 21 f2 3a 7d db 59 75 80 48 24 |0...<.!.:}.Yu.H$|
-000002f0 27 6f 2c 26 50 a4 7d 6c 91 d5 5d f7 c9 b4 bd 15 |'o,&P.}l..].....|
-00000300 a8 8a 12 d5 40 8c 9a 0f 56 67 66 89 dd 12 36 d8 |....@...Vgf...6.|
-00000310 d3 |.|
+00000000 16 03 01 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0|
+00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.|
+00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.|
+00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1|
+00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C|
+00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523|
+00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231|
+00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac|
+00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.|
+00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....|
+000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x|
+000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.|
+000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4|
+000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..|
+000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#|
+000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....|
+00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......|
+00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..|
+00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U|
+00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U|
+00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......|
+00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.|
+00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0|
+00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........|
+00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..|
+00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]|
+000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A|
+000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...|
+000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...|
+000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......|
+000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{|
+000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....|
+00000200 e5 35 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.|
+00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...|
+00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 |......._X.;t....|
+00000230 86 0f 00 00 82 00 80 8f 6f 77 5d d5 99 28 0c 7a |........ow]..(.z|
+00000240 36 f2 50 ec 9a e6 eb 88 ac 45 f7 9b 6f 98 84 ba |6.P......E..o...|
+00000250 fb 3c b8 d6 54 61 b8 87 25 50 3c 31 5a d2 c1 54 |.<..Ta..%P<1Z..T|
+00000260 e8 ed c3 93 cc 98 b1 c3 d4 84 11 d8 a0 c7 ae 67 |...............g|
+00000270 67 35 6a 0f 93 18 bb 18 52 f8 25 88 1f d2 19 4d |g5j.....R.%....M|
+00000280 3b 4c f2 0f f7 06 68 57 cf 45 20 e0 57 75 37 e9 |;L....hW.E .Wu7.|
+00000290 cd 86 1f e5 d2 90 1e cf 3a 18 fd 45 bc a1 84 63 |........:..E...c|
+000002a0 36 d8 ac 6b 09 41 da 0a 87 7f ab ce 8e 49 e6 c8 |6..k.A.......I..|
+000002b0 bf fb 2c 3b 7b e9 ae 14 03 01 00 01 01 16 03 01 |..,;{...........|
+000002c0 00 30 7d 65 9c c1 25 e4 85 d7 39 d4 67 cf eb f1 |.0}e..%...9.g...|
+000002d0 b7 c2 4d e6 5d bd 13 74 55 22 f0 8a 7e a6 a2 eb |..M.]..tU"..~...|
+000002e0 93 cc b7 fa 86 b1 b5 e0 a3 ef ee 56 f0 cd f7 a5 |...........V....|
+000002f0 d8 9e |..|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 02 e3 be 9d 2d |..........0....-|
-00000010 6f 2c 9a b7 b4 f1 a5 30 ec 3e ae 05 e6 02 19 2f |o,.....0.>...../|
-00000020 a4 ac d1 6e ac de 75 4e cc 14 e6 78 5a ea 27 7f |...n..uN...xZ.'.|
-00000030 4e 45 c4 9d b2 da a6 ea b7 d2 7e |NE........~|
+00000000 14 03 01 00 01 01 16 03 01 00 30 ff 13 14 c5 ad |..........0.....|
+00000010 88 ec a1 cf cc 0d 3f 7b ec 50 4a 25 69 1f 18 dc |......?{.PJ%i...|
+00000020 b1 99 1f 3b 78 60 e0 83 c0 cd 9a b3 0d 59 0b f8 |...;x`.......Y..|
+00000030 8a b7 7c 2c b4 2c e4 d0 49 82 82 |..|,.,..I..|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 20 e0 71 e9 54 11 6e 48 4b be a2 2a |.... .q.T.nHK..*|
-00000010 b1 70 d2 2c 74 c0 f4 74 05 f1 d3 d6 84 29 58 f7 |.p.,t..t.....)X.|
-00000020 87 90 84 2b c8 17 03 01 00 20 b6 a2 e9 e0 f0 0d |...+..... ......|
-00000030 d5 ef d7 32 6d cb 99 5d a6 37 c2 6e f9 c3 8e 6f |...2m..].7.n...o|
-00000040 76 71 d8 a6 c5 ae 4e 04 77 06 15 03 01 00 20 f2 |vq....N.w..... .|
-00000050 09 ab dc 37 90 78 3a 2a 41 ab 9b a9 c1 78 2a 64 |...7.x:*A....x*d|
-00000060 a8 3f 21 c4 bb af 76 b3 c6 2f e1 20 a3 b1 1e |.?!...v../. ...|
+00000000 17 03 01 00 20 51 91 74 f6 31 07 15 6b 9e 0b 28 |.... Q.t.1..k..(|
+00000010 02 b8 ec 9d c6 e3 15 24 d3 ea 4b 27 d0 fa 9f c2 |.......$..K'....|
+00000020 c4 8d 37 b3 d9 17 03 01 00 20 7d 97 75 fe de 3f |..7...... }.u..?|
+00000030 ae ab e6 a8 1d 76 1c 06 9c 02 61 cc f5 1d fe c8 |.....v....a.....|
+00000040 a2 dc ae 97 7f 1c 05 19 e5 14 15 03 01 00 20 4a |.............. J|
+00000050 bc 45 97 6b 09 8e 47 5f d5 a0 97 78 79 67 09 8d |.E.k..G_...xyg..|
+00000060 d3 80 38 58 5c cc ae 8e d4 67 1d 93 2b 20 79 |..8X\....g..+ y|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA
index e00787037ab..e585894db7e 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA
@@ -1,120 +1,131 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 51 02 00 00 4d 03 01 e5 d7 4b 56 7b |....Q...M....KV{|
-00000010 a8 2c 07 33 fc 66 d7 79 e9 26 91 56 7d 9d 99 1d |.,.3.f.y.&.V}...|
-00000020 b2 24 36 2c f6 78 3a e7 63 15 f6 20 9f e1 d4 07 |.$6,.x:.c.. ....|
-00000030 a9 75 3d b9 3b 8c 46 cb a7 37 36 56 af 4e 99 cf |.u=.;.F..76V.N..|
-00000040 90 49 e1 e9 69 25 81 0f fd 22 48 e6 00 05 00 00 |.I..i%..."H.....|
-00000050 05 ff 01 00 01 00 16 03 01 02 71 0b 00 02 6d 00 |..........q...m.|
-00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 01 00 |..A4......9.....|
-000002d0 0e 0d 00 00 06 03 01 02 40 00 00 0e 00 00 00 |........@......|
+00000000 16 03 01 00 59 02 00 00 55 03 01 61 6b 2e 41 7f |....Y...U..ak.A.|
+00000010 af 26 6f a2 8b 63 ee e4 b1 76 19 3a 6d a3 c2 30 |.&o..c...v.:m..0|
+00000020 37 e8 47 c2 90 10 7e e8 c5 b2 eb 20 00 1c 8f 70 |7.G...~.... ...p|
+00000030 0d 15 4a c7 7d ab ca 79 a7 d8 c2 01 62 6e 6f aa |..J.}..y....bno.|
+00000040 df a2 1c 8f 7c 27 d9 e6 fe e9 c8 ab c0 13 00 00 |....|'..........|
+00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
+00000060 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......|
+000002c0 aa 0c 00 00 a6 03 00 1d 20 29 0b ca 37 f3 a1 52 |........ )..7..R|
+000002d0 49 1c 84 9a e4 74 6b 4b 2d 1f e6 e9 83 1d 5d 59 |I....tkK-.....]Y|
+000002e0 5a 2f 09 9f bc a4 30 af 71 00 80 d9 bb 6d 09 a7 |Z/....0.q....m..|
+000002f0 ab 47 6f e8 a6 1a da fb 66 7d a5 f0 c9 c3 24 4c |.Go.....f}....$L|
+00000300 99 56 c6 29 71 27 08 0b c1 60 44 cc 6d 42 1b 5e |.V.)q'...`D.mB.^|
+00000310 cd 9f 82 24 38 23 ec d9 fa 32 49 2f 16 5d d2 9d |...$8#...2I/.]..|
+00000320 e9 13 4e 66 3d f8 bf 30 2e 8c eb 35 4c e8 81 86 |..Nf=..0...5L...|
+00000330 c0 de c7 0d a9 60 7e 7c 4a c4 1d a0 89 70 de 82 |.....`~|J....p..|
+00000340 1b 37 a0 ea 7f 20 a5 fe d4 20 1d 6f 1a 84 dd a4 |.7... ... .o....|
+00000350 13 46 18 c6 31 14 81 4b a4 bb 43 5c c4 49 1c 5a |.F..1..K..C\.I.Z|
+00000360 8d 12 57 e0 1d 9a b6 cd f1 39 ff 16 03 01 00 0a |..W......9......|
+00000370 0d 00 00 06 03 01 02 40 00 00 16 03 01 00 04 0e |.......@........|
+00000380 00 00 00 |...|
>>> Flow 3 (client to server)
-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 73 bd 73 65 92 |...........s.se.|
-00000210 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
-00000220 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
-00000230 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
-00000240 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
-00000250 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
-00000260 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
-00000270 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
-00000280 4d e5 78 13 4e a4 38 46 42 dc 16 16 03 01 00 86 |M.x.N.8FB.......|
-00000290 0f 00 00 82 00 80 3d f7 ff c1 72 82 b8 90 42 a3 |......=...r...B.|
-000002a0 10 24 b5 01 44 60 98 39 e4 36 86 56 09 55 e5 73 |.$..D`.9.6.V.U.s|
-000002b0 3a d9 9d 00 ae 05 23 6f 78 4e 49 28 c1 cc 7a ff |:.....#oxNI(..z.|
-000002c0 8f 67 92 cd 94 c0 d2 68 7f 48 ec 10 83 48 9e 02 |.g.....h.H...H..|
-000002d0 b8 10 b2 1b f0 ba 8f 5a c8 85 d9 19 53 c2 8d 37 |.......Z....S..7|
-000002e0 8e 86 4c ca ee 0f c4 97 20 f9 a5 4e 94 b8 c5 c5 |..L..... ..N....|
-000002f0 53 0c c1 b6 e5 a1 4e d6 15 b3 6b 08 c2 25 c3 de |S.....N...k..%..|
-00000300 e7 69 85 85 56 31 16 ad 68 7e 00 8f 1b fc f8 9f |.i..V1..h~......|
-00000310 d7 50 87 08 0d c5 14 03 01 00 01 01 16 03 01 00 |.P..............|
-00000320 24 eb 0c f3 4f 56 04 e3 54 b0 a8 e4 bb af 3a 44 |$...OV..T.....:D|
-00000330 c7 d6 f0 24 2f fc e6 79 93 f4 4e ec c5 1f 5b 99 |...$/..y..N...[.|
-00000340 32 37 c2 f1 ad |27...|
+00000000 16 03 01 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0|
+00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.|
+00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.|
+00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1|
+00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C|
+00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523|
+00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231|
+00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac|
+00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.|
+00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....|
+000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x|
+000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.|
+000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4|
+000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..|
+000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#|
+000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....|
+00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......|
+00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..|
+00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U|
+00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U|
+00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......|
+00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.|
+00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0|
+00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........|
+00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..|
+00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]|
+000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A|
+000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...|
+000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...|
+000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......|
+000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{|
+000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....|
+00000200 e5 35 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.|
+00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...|
+00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 01 00 |......._X.;t....|
+00000230 86 0f 00 00 82 00 80 12 76 af 25 e4 e7 ff d6 e4 |........v.%.....|
+00000240 27 58 31 0f 6b 1e 84 13 2f d0 60 80 18 c3 f8 c1 |'X1.k.../.`.....|
+00000250 f8 04 39 d4 07 05 d3 96 e2 b2 10 de 1f 68 88 67 |..9..........h.g|
+00000260 1d dd 0a 11 52 9d 16 0e af 07 de cb f1 7c f4 b4 |....R........|..|
+00000270 5d 0f 4f 43 5b 3c 25 07 32 13 f2 ab 9b 2d d0 a8 |].OC[<%.2....-..|
+00000280 28 90 cb 04 48 c3 43 bd 2b b4 ef b9 7b cd bd d5 |(...H.C.+...{...|
+00000290 bc d1 cc 00 17 46 fa 9b 1f 44 58 b7 6c de 1b 7a |.....F...DX.l..z|
+000002a0 e0 d7 12 38 a3 09 f8 7a 9b 26 0b ee 37 bc 79 1b |...8...z.&..7.y.|
+000002b0 51 9f 9a 1f f9 a9 51 14 03 01 00 01 01 16 03 01 |Q.....Q.........|
+000002c0 00 30 97 df fb 79 78 a8 27 fd 2b 68 6b ec 4d 29 |.0...yx.'.+hk.M)|
+000002d0 a1 02 59 ae 18 0b 46 62 af 61 53 2f 95 50 f2 ac |..Y...Fb.aS/.P..|
+000002e0 c8 c3 5e 78 ca b0 e2 5d ff d7 1b 9b 00 30 f6 da |..^x...].....0..|
+000002f0 d7 91 |..|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 24 75 ac 09 a6 28 |..........$u...(|
-00000010 60 ce 7f 81 a2 75 86 af 84 95 dc 3f e1 07 1c 02 |`....u.....?....|
-00000020 bc 3c 90 db 1e 1a 35 06 93 60 22 69 b9 05 bb |.<....5..`"i...|
+00000000 14 03 01 00 01 01 16 03 01 00 30 f9 e9 d7 8c 4a |..........0....J|
+00000010 6b f4 c9 88 d6 98 70 53 13 fc 51 9c 81 14 cf 71 |k.....pS..Q....q|
+00000020 d9 30 7a d9 2c 34 96 00 a4 a0 2b 1e 7d ff d0 f2 |.0z.,4....+.}...|
+00000030 b7 81 ed 86 c5 e1 09 16 82 47 20 |.........G |
>>> Flow 5 (client to server)
-00000000 17 03 01 00 1a f4 67 a7 d8 0a 67 8d 3a 11 53 7e |......g...g.:.S~|
-00000010 49 91 bf 92 85 e0 35 24 25 72 92 26 63 9b 09 15 |I.....5$%r.&c...|
-00000020 03 01 00 16 98 bb a0 ca 40 70 26 6f 2d 73 35 3d |........@p&o-s5=|
-00000030 90 8c ff 01 e0 b1 50 52 e3 57 |......PR.W|
+00000000 17 03 01 00 20 db b5 66 4e fb b1 47 8a 8e 6b a8 |.... ..fN..G..k.|
+00000010 03 53 1a 51 22 8e 47 a3 3a 74 ed a4 6a aa 79 fd |.S.Q".G.:t..j.y.|
+00000020 55 0f ac 35 a9 17 03 01 00 20 3e 0b 39 f5 5a 03 |U..5..... >.9.Z.|
+00000030 43 d9 e2 7d 1c dc 3b 42 82 2a 2d d4 04 0a 76 97 |C..}..;B.*-...v.|
+00000040 70 ed ee 99 58 15 40 c1 3a d5 15 03 01 00 20 bf |p...X.@.:..... .|
+00000050 ea e8 93 67 a4 91 1a b5 f5 03 a5 94 50 95 41 16 |...g........P.A.|
+00000060 b0 2a 74 d9 32 65 94 35 45 b9 0f 2e 80 87 fd |.*t.2e.5E......|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES
index 929e1c6b12b..529b7cef48b 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES
@@ -1,19 +1,20 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 59 02 00 00 55 03 01 78 09 57 86 09 |....Y...U..x.W..|
-00000010 64 7e 35 c7 c7 b9 44 9c 09 ae f0 49 cb 1c 1f 58 |d~5...D....I...X|
-00000020 89 ef 65 16 9e 32 73 cd 4d 1b 8f 20 10 4d 5b cf |..e..2s.M.. .M[.|
-00000030 d0 24 59 dd e8 47 c9 a2 ad 9c 98 b5 eb 16 46 6b |.$Y..G........Fk|
-00000040 7d 33 6e 53 0a 3d 81 71 a1 bc 43 7a c0 09 00 00 |}3nS.=.q..Cz....|
+00000000 16 03 01 00 59 02 00 00 55 03 01 b0 ec 4b 2e 9e |....Y...U....K..|
+00000010 19 7d 7b 7e 7c 52 8a d2 2e 8a 97 05 8a c6 ae aa |.}{~|R..........|
+00000020 c5 62 bd 6f bd 7e fe 6b c6 9f d4 20 74 db 02 b1 |.b.o.~.k... t...|
+00000030 65 88 41 bb 9a 55 22 f3 01 c4 5c ca 39 86 b1 77 |e.A..U"...\.9..w|
+00000040 c4 b3 45 16 eb 55 d8 15 b8 4d ac 12 c0 09 00 00 |..E..U...M......|
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....|
@@ -48,41 +49,37 @@
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 01 00 d6 0c 00 00 d2 03 00 17 41 04 51 |*............A.Q|
-00000280 39 70 43 9c 01 de 29 df 3c d0 f8 31 54 70 34 53 |9pC...).<..1Tp4S|
-00000290 0e ab e8 e0 b0 8b 21 66 63 ac a9 68 7c 92 6f f8 |......!fc..h|.o.|
-000002a0 cf a3 ba cb 6d 39 f4 5c f5 2e ff 1d d7 1b b9 e7 |....m9.\........|
-000002b0 08 13 59 f8 64 7e 23 e0 1d 04 cf 37 47 d6 b7 00 |..Y.d~#....7G...|
-000002c0 8b 30 81 88 02 42 01 cd 1d 01 46 68 da 4c b6 0d |.0...B....Fh.L..|
-000002d0 67 05 39 0d aa 6c c5 40 e4 5d bf 4f 2a 92 78 8d |g.9..l.@.].O*.x.|
-000002e0 08 0e c0 07 8c 68 cc 55 4e 54 a9 9d 22 f9 a6 4a |.....h.UNT.."..J|
-000002f0 e4 38 9f 53 4a 60 e8 eb 81 02 50 75 7e 13 31 2a |.8.SJ`....Pu~.1*|
-00000300 ff 3e 17 cd b4 d1 d4 75 02 42 01 95 ba b6 a0 12 |.>.....u.B......|
-00000310 23 59 9f ae 1c c0 60 d2 8f 59 6b 35 ee b3 3f ac |#Y....`..Yk5..?.|
-00000320 e4 42 9a 23 d0 f4 fd a1 3c 36 1b 31 33 76 8d f0 |.B.#....<6.13v..|
-00000330 b6 66 fd 92 9a 2a 27 8b 06 11 72 41 09 bd 27 55 |.f...*'...rA..'U|
-00000340 c7 1b a9 d1 49 5e 8f 85 dc aa 9d be 16 03 01 00 |....I^..........|
-00000350 04 0e 00 00 00 |.....|
+00000270 2a 16 03 01 00 b5 0c 00 00 b1 03 00 1d 20 7d 74 |*............ }t|
+00000280 bf aa a8 b6 c0 1f 78 0c 1a ee c5 b7 56 ff 5c aa |......x.....V.\.|
+00000290 f4 e3 a5 0c f7 64 31 eb 85 8a c9 bd 05 1b 00 8b |.....d1.........|
+000002a0 30 81 88 02 42 00 f8 5d e5 bf 2e 70 79 f4 36 90 |0...B..]...py.6.|
+000002b0 fc 6e 9a cc f1 c4 01 50 8c b9 92 4e bd e0 82 2d |.n.....P...N...-|
+000002c0 1b ab 30 71 d1 db 76 af 50 75 08 fb cb 50 5b 00 |..0q..v.Pu...P[.|
+000002d0 49 72 f5 d7 d9 44 48 94 ac 1d 8d 2e 50 90 ad a3 |Ir...DH.....P...|
+000002e0 42 2b 5f 57 48 5e 9e 02 42 00 bb 0b 9a d7 25 53 |B+_WH^..B.....%S|
+000002f0 04 5c 58 01 07 8e 3d ee f5 4f 0b 80 bd 02 07 3e |.\X...=..O.....>|
+00000300 ff b9 01 ac 7a 49 be 94 fa cf 58 5c 59 91 b5 5d |....zI....X\Y..]|
+00000310 cc 61 b9 e3 2f 53 7d 3c 3f 41 c5 31 1a 90 fc fa |.a../S}<?A.1....|
+00000320 f7 0b eb e9 01 17 ab 23 ab 28 63 16 03 01 00 04 |.......#.(c.....|
+00000330 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 64 61 7f ea 98 8e e7 c9 0f ea |.....0da........|
-00000060 0a b3 52 ba 3d 01 36 a4 47 24 7b 2d 19 b5 7e 92 |..R.=.6.G${-..~.|
-00000070 04 b7 8c 4f fc 02 5d 79 15 3e 50 72 05 3c df d2 |...O..]y.>Pr.<..|
-00000080 c6 a3 b3 c8 7c 48 |....|H|
+00000000 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 01 00 01 01 |....._X.;t......|
+00000030 16 03 01 00 30 f5 d0 86 ef 96 7e b9 94 cc 19 62 |....0.....~....b|
+00000040 cc 3a 14 f1 74 a2 0d c8 b9 4c 5d 8a c5 80 60 23 |.:..t....L]...`#|
+00000050 d5 f5 04 06 16 e2 69 ca 4d 99 1b a0 b5 3b 7d 62 |......i.M....;}b|
+00000060 51 62 ee d9 60 |Qb..`|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 7d 49 8d e9 da |..........0}I...|
-00000010 87 77 18 4d 10 63 17 ed 1f 34 7a d4 be e3 dd b6 |.w.M.c...4z.....|
-00000020 8b f3 a7 06 bc de 76 8e 04 be 8a 95 5b 24 19 ec |......v.....[$..|
-00000030 66 55 8a 1b e0 df 0b a1 57 cb 67 |fU......W.g|
+00000000 14 03 01 00 01 01 16 03 01 00 30 4d f9 c2 63 4f |..........0M..cO|
+00000010 98 1b 02 ce df ca d1 15 a2 4f 6f 4c 2c b8 1a 88 |.........OoL,...|
+00000020 11 c9 b3 45 e6 1d cf e8 6b dd 8c 89 c6 1d 0b 66 |...E....k......f|
+00000030 82 d5 1d c6 55 14 1c 56 59 3e 69 |....U..VY>i|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 20 2d a3 e5 55 13 3f 73 8e ba 41 79 |.... -..U.?s..Ay|
-00000010 65 e0 83 d5 3a ea cd e9 a8 b4 4b 3c d0 0c bf 06 |e...:.....K<....|
-00000020 75 2a 67 f2 f7 17 03 01 00 20 a0 8d 3c a2 ca b3 |u*g...... ..<...|
-00000030 f3 e5 36 dc 44 a4 3b ad cd 03 be a9 70 a8 75 51 |..6.D.;.....p.uQ|
-00000040 0f 8e 9f 7c a7 3c 03 84 38 88 15 03 01 00 20 75 |...|.<..8..... u|
-00000050 0f db fe 48 b4 7e 04 3b f5 5b 47 5b 0a ab 69 18 |...H.~.;.[G[..i.|
-00000060 37 bb 89 d3 a8 40 ba 53 3b 5f 6d 8b 06 ff ae |7....@.S;_m....|
+00000000 17 03 01 00 20 12 be 42 b4 31 07 55 8e f9 a1 64 |.... ..B.1.U...d|
+00000010 96 70 46 68 3e fd 4e 4f 9c af b3 11 de fc 80 f1 |.pFh>.NO........|
+00000020 c8 11 84 ba ae 17 03 01 00 20 2f f9 ec dd 50 97 |......... /...P.|
+00000030 1e a4 f1 66 fe 28 e3 c1 51 8d c0 f6 c3 d8 b3 ad |...f.(..Q.......|
+00000040 7d dc a5 98 87 90 34 71 b4 73 15 03 01 00 20 d1 |}.....4q.s.... .|
+00000050 6f 91 91 01 68 c4 11 6a e5 a2 ed 20 3f 3a 3d b7 |o...h..j... ?:=.|
+00000060 d9 7f c3 b3 29 c3 df 3e 17 69 76 9f 04 f8 58 |....)..>.iv...X|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES
index 0b481ea5ecb..78947ace0e8 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES
@@ -1,93 +1,89 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 59 02 00 00 55 03 01 90 3d f6 98 16 |....Y...U...=...|
-00000010 55 0f 73 94 05 96 4c ab ad f4 98 7a db c5 ca 26 |U.s...L....z...&|
-00000020 1b c8 d9 15 a8 79 8e 2b 10 67 54 20 b2 8e 45 24 |.....y.+.gT ..E$|
-00000030 6d 82 ec f5 30 41 2e 32 10 fa c0 76 3f 84 81 39 |m...0A.2...v?..9|
-00000040 1e 5d 98 c1 33 d9 0d 4f 21 e1 0d 47 c0 13 00 00 |.]..3..O!..G....|
+00000000 16 03 01 00 59 02 00 00 55 03 01 45 04 14 a2 70 |....Y...U..E...p|
+00000010 3e 1e d9 2c d4 bd f3 e8 9c f3 e0 08 d8 0f 7f 82 |>..,............|
+00000020 2b 07 a0 bd 47 56 a0 e1 06 0d 36 20 fc 0f 5b 85 |+...GV....6 ..[.|
+00000030 8e 17 20 f1 f6 1e 80 c3 79 1a e1 86 c3 ed e9 24 |.. .....y......$|
+00000040 6d bb 24 3c 0c 8d 2c 79 f2 03 27 b0 c0 13 00 00 |m.$<..,y..'.....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 01 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
-00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
-00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
-000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
-000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
-000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
-000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
-000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
-000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
-00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
-00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
-00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
-00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
-00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
-00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
-00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
-00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
-00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
-00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
-000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
-000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
-000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
-000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
-000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
-000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
-00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
-00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
-00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
-00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
-00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
-00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
-00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
-00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
-00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
-00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
-000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
-000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
-000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
-000002d0 b0 ab 39 18 16 03 01 00 cb 0c 00 00 c7 03 00 17 |..9.............|
-000002e0 41 04 d9 ae 3f 05 64 d3 77 d9 1d b8 37 8a d4 ac |A...?.d.w...7...|
-000002f0 51 f4 af 65 70 da c0 64 76 00 53 50 a2 d4 6c bc |Q..ep..dv.SP..l.|
-00000300 9c 62 ab 2f 7b 02 48 fe b2 0d 0b bb be 8f 34 55 |.b./{.H.......4U|
-00000310 fb ce ee 93 43 76 d5 ce 3b b5 79 ab 3d 74 6e 19 |....Cv..;.y.=tn.|
-00000320 a9 7d 00 80 05 cf 57 f2 f7 e0 ad 71 f1 75 d0 8b |.}....W....q.u..|
-00000330 f5 9d 83 1a 7e 0a 71 10 d7 9e fe bd 9d 47 62 45 |....~.q......GbE|
-00000340 8d 1b 9c 33 fa 2c 5c aa ce 9e 62 dc ad 56 ac 87 |...3.,\...b..V..|
-00000350 84 54 f5 32 87 d1 bb 8b d9 d7 6d 3c 6c 6d b7 79 |.T.2......m<lm.y|
-00000360 05 4d 55 f1 7c ef b1 fc e7 35 5d 41 66 60 44 4f |.MU.|....5]Af`DO|
-00000370 f3 dd de 25 f4 73 12 c2 b6 cc 61 d5 14 5a ff 88 |...%.s....a..Z..|
-00000380 ae f5 04 62 ac 2d 10 a0 95 c1 8e fa e6 db fe 41 |...b.-.........A|
-00000390 46 98 f1 3d 2e e3 2a 5a ea 87 26 6e 7a 4f 38 6c |F..=..*Z..&nzO8l|
-000003a0 4b 1f 1b 56 16 03 01 00 04 0e 00 00 00 |K..V.........|
+00000060 01 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 01 00 |.=.`.\!.;.......|
+000002c0 aa 0c 00 00 a6 03 00 1d 20 85 05 5f e3 a2 b2 12 |........ .._....|
+000002d0 c8 82 53 2b c2 38 e1 a8 08 87 a7 d5 b3 98 6f 81 |..S+.8........o.|
+000002e0 ce 81 6b 78 3e 3a b7 1d 71 00 80 43 81 fb 47 5e |..kx>:..q..C..G^|
+000002f0 08 16 39 35 d3 c2 f3 ea bb 2c 7d bc 01 9b 35 5d |..95.....,}...5]|
+00000300 63 7e c3 38 f3 04 96 eb d7 3f d1 df 71 97 ec 22 |c~.8.....?..q.."|
+00000310 1b 4a 89 14 4d e5 44 08 87 52 69 ea 28 f8 6a ea |.J..M.D..Ri.(.j.|
+00000320 3e ff 17 de 4d 20 95 e3 6e 3f af 05 20 9b a3 ac |>...M ..n?.. ...|
+00000330 70 1b 1c bf f9 52 d6 11 6d d9 85 90 08 4d 64 1f |p....R..m....Md.|
+00000340 c5 35 34 37 11 b8 44 a3 ef 93 a6 b6 87 58 0b c4 |.547..D......X..|
+00000350 8e 94 d8 67 4d 09 7a 2a aa 95 db e6 af 29 21 a2 |...gM.z*.....)!.|
+00000360 ee c3 90 ef c6 53 46 12 fb 87 06 16 03 01 00 04 |.....SF.........|
+00000370 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 73 96 2d 54 e3 9a bc 54 f5 9e |.....0s.-T...T..|
-00000060 e5 c7 46 35 b8 e1 d6 f6 14 95 92 f1 95 81 5a 9d |..F5..........Z.|
-00000070 4b df cc 96 77 f2 39 60 5d 5d da 94 b0 bf a0 80 |K...w.9`]]......|
-00000080 bd 28 55 b1 6a c3 |.(U.j.|
+00000000 16 03 01 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 01 00 01 01 |....._X.;t......|
+00000030 16 03 01 00 30 50 f5 a9 34 25 ed a2 fb c8 7f 35 |....0P..4%.....5|
+00000040 08 57 59 da 54 c1 8d 92 ec 23 73 af f3 92 8d 19 |.WY.T....#s.....|
+00000050 03 ce ab 5b eb dc 5b 81 3f 51 a1 20 31 3f 33 da |...[..[.?Q. 1?3.|
+00000060 27 c5 c3 9c fd |'....|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 c9 46 7a 8b be |..........0.Fz..|
-00000010 cd eb 5c 83 13 9c 9b 9f 70 84 38 3b 48 8c f4 11 |..\.....p.8;H...|
-00000020 b3 ca 10 09 38 d0 8e c8 9f 66 db b9 8a 95 15 6b |....8....f.....k|
-00000030 5e f8 1d 39 25 75 3d f1 b9 32 a3 |^..9%u=..2.|
+00000000 14 03 01 00 01 01 16 03 01 00 30 b1 61 9b 63 4e |..........0.a.cN|
+00000010 43 96 80 49 ac 2d 93 7d b9 f2 bb 81 79 5e 94 bf |C..I.-.}....y^..|
+00000020 06 d0 a6 14 46 91 cd 90 b0 8a 85 ee fe 41 a7 4d |....F........A.M|
+00000030 97 d7 4d 40 5e f4 5b bd d3 0c db |..M@^.[....|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 20 04 69 a9 01 42 f4 1a fd 5a 4e 12 |.... .i..B...ZN.|
-00000010 2b 6d cd 68 6b 94 70 b2 80 07 cf 79 a4 43 69 bf |+m.hk.p....y.Ci.|
-00000020 27 25 b5 ae e7 17 03 01 00 20 bf 1e cd 83 64 af |'%....... ....d.|
-00000030 6f cc 89 21 bf 16 e7 e8 86 29 f3 0a 36 ab a4 e3 |o..!.....)..6...|
-00000040 fa c0 7e 7a 78 ca 29 17 11 9c 15 03 01 00 20 94 |..~zx.)....... .|
-00000050 7a dd 17 eb fd 67 b1 cc 58 c9 c3 ae db b6 b0 a4 |z....g..X.......|
-00000060 68 15 36 ca 33 22 ec 03 fb cf 2f f5 70 d6 9d |h.6.3"..../.p..|
+00000000 17 03 01 00 20 49 21 bc a5 4c 96 41 3f 22 87 0a |.... I!..L.A?"..|
+00000010 c0 4e 0e 54 cb c2 27 8a 4f b0 37 fb b4 1f c1 4e |.N.T..'.O.7....N|
+00000020 77 e1 09 57 23 17 03 01 00 20 f0 f0 3b 78 a8 ae |w..W#.... ..;x..|
+00000030 ef b1 e0 f4 29 0f 90 4a 0f e5 48 34 84 5e 4f d8 |....)..J..H4.^O.|
+00000040 53 46 f8 29 64 2b 8e 87 79 0a 15 03 01 00 20 71 |SF.)d+..y..... q|
+00000050 32 6c 08 2a f7 18 c8 d5 48 a8 c7 d1 68 7a 65 ec |2l.*....H...hze.|
+00000060 3e fa 4b fe ff 76 1a 57 64 22 61 27 a0 5d b6 |>.K..v.Wd"a'.].|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4 b/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4
index 57eb930d092..7ecfbde86a4 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-RSA-RC4
@@ -1,79 +1,78 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 01 00 51 02 00 00 4d 03 01 1c 0e e9 7a c6 |....Q...M.....z.|
-00000010 91 fe 7e 8c 6f 0b 8e cf 23 f5 07 29 10 de 05 a6 |..~.o...#..)....|
-00000020 20 72 11 65 4f 2b 45 95 96 02 62 20 43 a8 93 34 | r.eO+E...b C..4|
-00000030 e7 c0 29 d5 fb 26 f9 c2 59 37 94 dc e6 b5 c4 ed |..)..&..Y7......|
-00000040 ae 7a d7 94 d1 f4 d8 0b 02 ad 20 1b 00 05 00 00 |.z........ .....|
-00000050 05 ff 01 00 01 00 16 03 01 02 71 0b 00 02 6d 00 |..........q...m.|
-00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 01 00 |..A4......9.....|
-000002d0 04 0e 00 00 00 |.....|
+00000000 16 03 01 00 51 02 00 00 4d 03 01 4c 98 ce a5 80 |....Q...M..L....|
+00000010 84 dc d3 70 de 75 bf 26 5c 15 8b b7 2c 78 30 a7 |...p.u.&\...,x0.|
+00000020 65 1a 0c f7 1a e5 51 91 7c cb ca 20 83 2c 90 3b |e.....Q.|.. .,.;|
+00000030 cf dd 4e 51 8b 27 98 95 aa d9 1d da 4d 3d e1 18 |..NQ.'......M=..|
+00000040 f5 58 fd 85 c5 ed c9 5f 12 2f 4b b3 00 05 00 00 |.X....._./K.....|
+00000050 05 ff 01 00 01 00 16 03 01 02 59 0b 00 02 55 00 |..........Y...U.|
+00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000090 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+000000a0 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+000000b0 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000c0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000d0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000e0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000f0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+00000100 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+00000110 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000120 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000130 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000140 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000150 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000160 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000170 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000180 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000190 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+000001a0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+000001b0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001c0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001d0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001e0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001f0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+00000200 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+00000210 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000220 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000230 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000240 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000250 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000260 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000270 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000280 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000290 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+000002a0 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+000002b0 3b e9 fa e7 16 03 01 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 01 00 86 10 00 00 82 00 80 73 bd 73 65 92 |...........s.se.|
-00000010 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
-00000020 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
-00000030 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
-00000040 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
-00000050 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
-00000060 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
-00000070 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
-00000080 4d e5 78 13 4e a4 38 46 42 dc 16 14 03 01 00 01 |M.x.N.8FB.......|
-00000090 01 16 03 01 00 24 ae a9 da 45 6b 5e 76 57 02 62 |.....$...Ek^vW.b|
-000000a0 63 d4 1f 40 bf c9 47 27 a9 7a 24 c0 f0 e9 c2 c4 |c..@..G'.z$.....|
-000000b0 9c 07 84 df ae c7 66 40 d2 b0 |......f@..|
+00000000 16 03 01 00 86 10 00 00 82 00 80 b9 65 8d bf a7 |............e...|
+00000010 c8 4b 79 ce 6f cb 8b 13 1c ac b9 7d 66 5e e9 ba |.Ky.o......}f^..|
+00000020 1d 71 4e a9 e9 34 ae f6 64 65 90 3b d8 16 52 a2 |.qN..4..de.;..R.|
+00000030 6f f4 cb 8a 13 74 a2 ee b7 27 69 b4 41 c0 90 68 |o....t...'i.A..h|
+00000040 bc 02 69 e1 c6 48 4f 39 36 30 25 ca 4c 17 ce 83 |..i..HO960%.L...|
+00000050 9e 08 56 e3 05 49 93 9e 2e c4 fb e6 c8 01 f1 0f |..V..I..........|
+00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..|
+00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..|
+00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 01 00 01 |.Y(.....ia5.....|
+00000090 01 16 03 01 00 24 0e 4d ff 2c 39 80 ba a5 96 18 |.....$.M.,9.....|
+000000a0 56 15 94 9f e2 1e 7d 13 62 51 d5 e1 05 f8 d8 b3 |V.....}.bQ......|
+000000b0 bd 77 58 38 95 b4 7d 37 66 8a |.wX8..}7f.|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 24 e9 84 92 41 c5 |..........$...A.|
-00000010 31 e1 3c a9 78 18 d1 7b e1 b1 0b 0a ef 18 54 19 |1.<.x..{......T.|
-00000020 7c ba c7 59 ca c8 7b 4d c9 f4 ad d6 7b 77 fb ||..Y..{M....{w.|
+00000000 14 03 01 00 01 01 16 03 01 00 24 dc 6f da 57 0d |..........$.o.W.|
+00000010 f8 b8 aa d5 e5 0a 2e 81 ed 2a b7 f8 0e 2a f1 05 |.........*...*..|
+00000020 76 8d 4f b0 0e db 16 c5 d7 c8 5e f9 fb 9e e0 |v.O.......^....|
>>> Flow 5 (client to server)
-00000000 17 03 01 00 1a 1a dc 95 e2 4f ec f1 f6 68 9d 15 |.........O...h..|
-00000010 56 d5 7b 06 1a f5 be bb b1 ca b2 a6 d3 9e 28 15 |V.{...........(.|
-00000020 03 01 00 16 64 fe 4a 37 d3 32 a8 55 38 9e 0f 76 |....d.J7.2.U8..v|
-00000030 50 de e2 2e aa 77 15 2b e5 21 |P....w.+.!|
+00000000 17 03 01 00 1a 47 97 4d e6 59 d4 2f bb 60 56 69 |.....G.M.Y./.`Vi|
+00000010 d8 bc 8d 91 44 7c cd 85 7e c5 18 5f 57 8e 08 15 |....D|..~.._W...|
+00000020 03 01 00 16 f7 79 56 72 e6 77 8d af 94 55 d7 0e |.....yVr.w...U..|
+00000030 96 c8 3b 35 52 ea f7 e7 b8 d6 |..;5R.....|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES
index 87fbe3f4051..5232ad57df8 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES
@@ -1,19 +1,20 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 02 00 59 02 00 00 55 03 02 07 ae a6 e4 1a |....Y...U.......|
-00000010 f7 7a 0c bc ea 21 0e 86 e3 d0 b4 2c fc d9 97 a3 |.z...!.....,....|
-00000020 8b 29 5f 59 3e a9 06 fb ca d9 57 20 cd 45 e7 cd |.)_Y>.....W .E..|
-00000030 6c 4c 56 cd 7c 4c 51 2c 8f 8c 67 a2 05 51 26 f5 |lLV.|LQ,..g..Q&.|
-00000040 17 cc 18 c2 a1 29 94 4b e2 02 cc 1c c0 09 00 00 |.....).K........|
+00000000 16 03 02 00 59 02 00 00 55 03 02 30 f8 f6 b2 af |....Y...U..0....|
+00000010 99 b0 e0 f6 9a eb 47 6f 2f ad 2f 45 18 56 b3 dd |......Go/./E.V..|
+00000020 b6 b9 20 fb af 97 43 1f 0e 51 c0 20 fe 6c 12 64 |.. ...C..Q. .l.d|
+00000030 8e cc a4 24 d6 e6 80 cf f2 9e 74 3f a7 1e 8b da |...$......t?....|
+00000040 0e 3c 58 74 f4 8f be 1f 60 86 57 c6 c0 09 00 00 |.<Xt....`.W.....|
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....|
@@ -48,43 +49,39 @@
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 02 00 d6 0c 00 00 d2 03 00 17 41 04 cd |*............A..|
-00000280 9d 30 75 8d 98 17 b5 1b 2f 4e af ea 69 52 a1 c1 |.0u...../N..iR..|
-00000290 86 73 6a 56 54 f8 ed b6 35 e5 4e 34 a0 6f b1 85 |.sjVT...5.N4.o..|
-000002a0 95 8e be 77 c5 1a 56 9a 59 d1 69 79 ea d6 2b c7 |...w..V.Y.iy..+.|
-000002b0 c1 4a fb bc f8 98 c3 49 1c f3 ce 33 ef 98 20 00 |.J.....I...3.. .|
-000002c0 8b 30 81 88 02 42 00 8b 15 7e 3b 4f 73 b0 8e ca |.0...B...~;Os...|
-000002d0 67 e0 7c d8 89 70 f1 b2 6b 9c 19 84 fa aa 6e 15 |g.|..p..k.....n.|
-000002e0 8b 46 95 57 d5 ac 79 f3 e8 2a e5 7a a8 1e c3 d7 |.F.W..y..*.z....|
-000002f0 0a b2 02 cd d6 32 34 2f 37 65 41 c8 61 c6 ed e5 |.....24/7eA.a...|
-00000300 d2 6f 0f e8 1a 49 b6 c7 02 42 00 d1 00 f4 05 65 |.o...I...B.....e|
-00000310 dd 43 42 db 8b 0b 95 9d f5 62 51 e6 58 60 20 9b |.CB......bQ.X` .|
-00000320 46 84 e6 1f 76 4a 92 42 e4 4d 77 5b 76 a5 78 a0 |F...vJ.B.Mw[v.x.|
-00000330 b0 f0 50 7d f9 4f ca 43 9d c2 50 cb 20 1c 40 52 |..P}.O.C..P. .@R|
-00000340 0f a8 c4 43 7a 9d d5 61 de 26 30 b5 16 03 02 00 |...Cz..a.&0.....|
-00000350 04 0e 00 00 00 |.....|
+00000270 2a 16 03 02 00 b3 0c 00 00 af 03 00 1d 20 4b 2d |*............ K-|
+00000280 60 48 54 b4 48 42 10 de e1 98 f0 fb 73 d9 49 16 |`HT.HB......s.I.|
+00000290 3e a2 11 b3 84 50 de 26 00 09 d8 36 34 04 00 89 |>....P.&...64...|
+000002a0 30 81 86 02 41 24 90 6f 3e 1a 2c a5 7f 08 dc b2 |0...A$.o>.,.....|
+000002b0 d3 46 27 5e cb 1f 2a 6d 92 ba 1b fe e3 c5 64 79 |.F'^..*m......dy|
+000002c0 31 50 8c 43 4b b1 ee 0d 6f 53 ad 6f e9 db 86 e7 |1P.CK...oS.o....|
+000002d0 1f e3 77 f1 8d a8 ab 81 2a d6 fa e7 98 d5 bc 0d |..w.....*.......|
+000002e0 ec af ea 84 c4 f8 02 41 6a d2 66 32 e1 d7 46 1a |.......Aj.f2..F.|
+000002f0 95 5a 91 c3 76 82 20 c2 a3 a2 32 f5 fd eb a2 0e |.Z..v. ...2.....|
+00000300 0f d8 a9 31 7a ef a8 05 6c 5d bf 27 d0 2d 94 ca |...1z...l].'.-..|
+00000310 fb d6 62 7a 1c 6a 46 20 fe ed a6 60 a3 db b1 bd |..bz.jF ...`....|
+00000320 11 82 05 c3 db 0c 4a 2d 6c 16 03 02 00 04 0e 00 |......J-l.......|
+00000330 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 c0 81 e7 e8 40 f3 24 45 ed 74 |..........@.$E.t|
-00000070 86 31 7b 39 d1 3c a2 67 99 28 06 b1 34 b6 3c a6 |.1{9.<.g.(..4.<.|
-00000080 1d ce 39 aa 56 c9 72 0d f1 e0 c1 5a 51 a0 5d f2 |..9.V.r....ZQ.].|
-00000090 44 4d e6 d7 0e 84 |DM....|
+00000000 16 03 02 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 02 00 01 01 |....._X.;t......|
+00000030 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........|
+00000040 00 00 00 00 00 22 71 28 3d 07 73 61 5e 84 72 36 |....."q(=.sa^.r6|
+00000050 c0 87 37 4a 5b c2 d9 40 96 a2 01 20 b2 04 23 2f |..7J[..@... ..#/|
+00000060 c1 6f 1e 7c a1 77 20 0f 87 46 98 a2 5c aa 35 37 |.o.|.w ..F..\.57|
+00000070 37 87 5a 75 33 |7.Zu3|
>>> Flow 4 (server to client)
-00000000 14 03 02 00 01 01 16 03 02 00 40 82 8d c7 e3 7b |..........@....{|
-00000010 f8 9d 33 a1 c2 08 8c 24 d9 af 66 64 6e e8 61 8e |..3....$..fdn.a.|
-00000020 3c 03 65 2d c3 64 a2 26 23 a5 25 3f a2 a4 f9 40 |<.e-.d.&#.%?...@|
-00000030 ec 9f 0e b8 57 b1 5f 84 ea 94 72 1a 3e 60 f1 dd |....W._...r.>`..|
-00000040 af 2e 81 f7 16 de 43 85 21 51 49 |......C.!QI|
+00000000 14 03 02 00 01 01 16 03 02 00 40 21 b5 1f 8d 4b |..........@!...K|
+00000010 1c a7 28 4e 73 3e d7 c5 75 6e eb e4 b3 95 02 4e |..(Ns>..un.....N|
+00000020 a3 47 03 44 97 69 c9 89 f5 ac e2 29 5e 22 e7 2c |.G.D.i.....)^".,|
+00000030 a2 2d e3 ac 64 45 ae 9d 07 9e fe f8 c6 85 47 4d |.-..dE........GM|
+00000040 59 be 72 8d e6 50 da c7 83 91 14 |Y.r..P.....|
>>> 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 43 8f 88 82 c8 e1 55 37 76 d7 a5 |.....C.....U7v..|
-00000020 83 c6 d2 94 26 fe 30 1f e2 24 ca d7 27 22 33 47 |....&.0..$..'"3G|
-00000030 5f a9 74 9d ad 15 03 02 00 30 00 00 00 00 00 00 |_.t......0......|
-00000040 00 00 00 00 00 00 00 00 00 00 49 8e ee 5c ec 86 |..........I..\..|
-00000050 e7 64 a7 ac 0d 5c c4 43 a6 45 a4 22 b7 3d 21 06 |.d...\.C.E.".=!.|
-00000060 11 67 08 99 9a 08 a1 7c e0 1e |.g.....|..|
+00000010 00 00 00 00 00 57 45 25 4c 1b 90 d3 28 e1 69 43 |.....WE%L...(.iC|
+00000020 c5 28 d9 d5 15 35 cf 41 bb 38 f2 12 c6 18 a5 a2 |.(...5.A.8......|
+00000030 f5 e4 64 1d 59 15 03 02 00 30 00 00 00 00 00 00 |..d.Y....0......|
+00000040 00 00 00 00 00 00 00 00 00 00 35 06 5f e3 ff e7 |..........5._...|
+00000050 f0 f1 0c d5 b1 59 42 80 19 8d 67 1b 18 18 5c 18 |.....YB...g...\.|
+00000060 42 38 67 85 c3 ab e2 dc 60 d4 |B8g.....`.|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES
index 75816429d1a..48ff7bce320 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES
@@ -1,95 +1,91 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 02 00 59 02 00 00 55 03 02 0c 74 28 d1 02 |....Y...U...t(..|
-00000010 15 8f 15 9c ec 8c 4e 34 97 d8 14 ab 0c ed 1b 38 |......N4.......8|
-00000020 af 7f e6 d3 41 db fd ad a0 8d 4f 20 03 71 4a d6 |....A.....O .qJ.|
-00000030 32 23 57 6c e1 55 34 1d 48 6f 9d e0 9a db 15 9d |2#Wl.U4.Ho......|
-00000040 5b 45 a7 3e 4e 98 31 7d f5 d4 b6 36 c0 13 00 00 |[E.>N.1}...6....|
+00000000 16 03 02 00 59 02 00 00 55 03 02 10 ca d9 1b 83 |....Y...U.......|
+00000010 59 c8 a5 a5 6a 89 65 6e 1c 0a 49 98 69 05 49 27 |Y...j.en..I.i.I'|
+00000020 96 72 74 5f 6e 5b 66 26 3b fd f8 20 23 b5 d6 c5 |.rt_n[f&;.. #...|
+00000030 09 f1 66 02 27 5c 5a 15 17 83 c5 11 a4 32 cf d8 |..f.'\Z......2..|
+00000040 1e a0 e7 93 83 35 6e aa 61 ae 97 77 c0 13 00 00 |.....5n.a..w....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 02 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
-00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
-00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
-000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
-000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
-000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
-000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
-000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
-000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
-00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
-00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
-00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
-00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
-00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
-00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
-00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
-00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
-00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
-00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
-000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
-000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
-000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
-000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
-000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
-000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
-00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
-00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
-00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
-00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
-00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
-00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
-00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
-00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
-00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
-00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
-000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
-000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
-000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
-000002d0 b0 ab 39 18 16 03 02 00 cb 0c 00 00 c7 03 00 17 |..9.............|
-000002e0 41 04 2c e8 55 b8 19 d6 cd e5 c7 96 a4 aa 61 af |A.,.U.........a.|
-000002f0 aa b2 f1 fc b3 ac 9a 90 02 d0 0a 86 61 9a c1 2e |............a...|
-00000300 3e fd 42 0b ba 07 95 77 2b 92 a2 5b 1f 44 ad 6b |>.B....w+..[.D.k|
-00000310 78 7a f4 b3 4b 04 d3 d5 2d eb 20 2d 73 02 4c db |xz..K...-. -s.L.|
-00000320 7e ac 00 80 79 b0 c6 b9 a8 50 e4 bf de 97 c6 1f |~...y....P......|
-00000330 ae 5f 89 77 6e e4 23 8c 8d 1a 49 f8 d4 92 cf 0d |._.wn.#...I.....|
-00000340 f0 08 bd 3a 88 9c 55 46 fc be 9e 7c 70 ff 6f 70 |...:..UF...|p.op|
-00000350 7b 94 b3 7b 82 c3 58 53 f7 20 13 3c 83 6e 10 55 |{..{..XS. .<.n.U|
-00000360 9d 51 cb 53 8c 93 dc 0e 02 06 40 d4 df ce 57 e4 |.Q.S......@...W.|
-00000370 e0 9a ba e2 b3 9b 01 98 0e 12 ca e9 96 5b 7a f2 |.............[z.|
-00000380 b1 ac 9c 44 e7 6e 2e c6 51 63 99 68 26 93 ca e2 |...D.n..Qc.h&...|
-00000390 40 31 e5 9a 80 ce 83 8f ca 80 90 c4 e8 ab 89 b2 |@1..............|
-000003a0 ca d6 30 a5 16 03 02 00 04 0e 00 00 00 |..0..........|
+00000060 02 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 02 00 |.=.`.\!.;.......|
+000002c0 aa 0c 00 00 a6 03 00 1d 20 97 a4 91 6b cd ca 44 |........ ...k..D|
+000002d0 7e ac fd a5 b1 c0 ce 88 07 f3 a2 d9 93 2b a8 d9 |~............+..|
+000002e0 0b 65 0b 47 c0 2e 4f 3b 26 00 80 00 18 01 a1 29 |.e.G..O;&......)|
+000002f0 0b 84 c9 09 5e 8c 58 5f 62 b6 22 8b 94 6e 72 26 |....^.X_b."..nr&|
+00000300 44 27 32 b9 22 12 67 58 34 a1 ce 6f 87 19 a0 5c |D'2.".gX4..o...\|
+00000310 5d 58 dc 91 fb c7 e6 31 33 76 6d 1f 8e 4f 46 55 |]X.....13vm..OFU|
+00000320 f1 08 57 9b bb fe 8d c7 6c 0b cd 8b ad b7 51 28 |..W.....l.....Q(|
+00000330 f8 5b 75 97 fe a0 d4 a1 2e 9a d3 d5 45 62 f8 19 |.[u.........Eb..|
+00000340 f6 73 d0 f6 6d e8 43 49 a2 f5 71 66 c5 29 1a 99 |.s..m.CI..qf.)..|
+00000350 e6 c0 cc f9 a5 cd a5 b7 58 08 4d cc 17 46 91 4c |........X.M..F.L|
+00000360 29 99 b4 05 78 af e7 b0 d1 2d 38 16 03 02 00 04 |)...x....-8.....|
+00000370 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 7d 87 6f 44 8f b9 92 51 5a b7 |......}.oD...QZ.|
-00000070 d2 6c 22 7f 62 a1 4e 30 61 f8 42 cd b0 05 c0 24 |.l".b.N0a.B....$|
-00000080 1f e0 49 a8 36 ce 8a 68 94 b7 37 c7 e8 d9 d8 05 |..I.6..h..7.....|
-00000090 be fb 5e 48 ba d1 |..^H..|
+00000000 16 03 02 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 02 00 01 01 |....._X.;t......|
+00000030 16 03 02 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........|
+00000040 00 00 00 00 00 f2 fb 8f ab ae 46 f2 6a 18 1b 77 |..........F.j..w|
+00000050 f3 ce 0c b6 83 9c d6 34 54 82 76 db 5c 79 5d cf |.......4T.v.\y].|
+00000060 24 f3 26 6d 9d f0 af d3 fc e0 96 69 0a 04 f7 ba |$.&m.......i....|
+00000070 78 54 af 37 a5 |xT.7.|
>>> Flow 4 (server to client)
-00000000 14 03 02 00 01 01 16 03 02 00 40 7d ed 01 b9 5a |..........@}...Z|
-00000010 34 f4 e1 63 70 84 13 86 e6 4d 90 92 da 3c 9b 35 |4..cp....M...<.5|
-00000020 77 92 7f 0a fd 69 09 75 30 5b c3 2c 6e 8e d0 59 |w....i.u0[.,n..Y|
-00000030 08 08 5c c9 eb 53 45 f3 a6 12 16 f2 95 06 27 82 |..\..SE.......'.|
-00000040 6d 9b 9e 6a bb 52 79 65 ca 94 9b |m..j.Rye...|
+00000000 14 03 02 00 01 01 16 03 02 00 40 e7 d9 0e af 0c |..........@.....|
+00000010 06 55 85 ab b0 0a 5e d9 11 81 7a 53 c0 f6 3f 84 |.U....^...zS..?.|
+00000020 06 7d 9c 20 05 e9 0d 1d df 9b 48 11 d9 df 0c e6 |.}. ......H.....|
+00000030 6b c2 a8 8f f4 d9 e8 8e f6 1a 3e db 7c e5 97 ac |k.........>.|...|
+00000040 5d 63 08 b2 3a 54 91 62 fc 2e a5 |]c..:T.b...|
>>> 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 bb 2d 28 50 1f a4 8f be 94 b9 99 |......-(P.......|
-00000020 e6 0b dd cf 50 fc 72 92 ec 1d 72 9b 27 9a 36 18 |....P.r...r.'.6.|
-00000030 3e e3 d7 cc 69 15 03 02 00 30 00 00 00 00 00 00 |>...i....0......|
-00000040 00 00 00 00 00 00 00 00 00 00 61 ca 39 3c 7e 9f |..........a.9<~.|
-00000050 1c c8 c2 2a 42 4a d0 c4 f3 80 41 04 b4 35 d0 41 |...*BJ....A..5.A|
-00000060 3d 47 1b 16 2c 71 27 04 7c 81 |=G..,q'.|.|
+00000010 00 00 00 00 00 3f ef e9 bc 10 07 75 99 67 8f 99 |.....?.....u.g..|
+00000020 bb c0 15 94 86 a2 80 cc 15 97 54 f8 4e 1a d1 9a |..........T.N...|
+00000030 33 80 aa da ec 15 03 02 00 30 00 00 00 00 00 00 |3........0......|
+00000040 00 00 00 00 00 00 00 00 00 00 6f 78 7b d2 80 62 |..........ox{..b|
+00000050 5c cf 34 d6 5a 72 d8 63 95 24 c6 ff 69 d0 6d 90 |\.4.Zr.c.$..i.m.|
+00000060 8d a2 9f 37 e8 7b b1 d4 68 04 |...7.{..h.|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4 b/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4
index e5e315e255a..2e9c49e27ad 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv11-RSA-RC4
@@ -1,79 +1,78 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 02 00 51 02 00 00 4d 03 02 59 22 be 64 85 |....Q...M..Y".d.|
-00000010 71 af 54 70 5f a8 50 ff 68 52 a0 9e a7 79 4d 90 |q.Tp_.P.hR...yM.|
-00000020 cd bc c7 9c 4f 62 bc 4d a6 b9 0c 20 e1 94 8f 01 |....Ob.M... ....|
-00000030 fa 7f 9e 6f 01 72 82 ef cc 41 ed 4d 7e 76 ee e1 |...o.r...A.M~v..|
-00000040 21 34 f3 5c e0 b4 4b e2 73 37 a8 40 00 05 00 00 |!4.\..K.s7.@....|
-00000050 05 ff 01 00 01 00 16 03 02 02 71 0b 00 02 6d 00 |..........q...m.|
-00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 02 00 |..A4......9.....|
-000002d0 04 0e 00 00 00 |.....|
+00000000 16 03 02 00 51 02 00 00 4d 03 02 36 8f 18 79 0f |....Q...M..6..y.|
+00000010 99 6b 3d 1d f4 19 aa ff 79 7c 50 15 52 db 9d c5 |.k=.....y|P.R...|
+00000020 62 40 2d 5b de 45 0c 66 b1 cb be 20 9e 00 c3 00 |b@-[.E.f... ....|
+00000030 22 2f b5 c6 79 c1 f7 72 8f 4b 94 f4 ac fe a9 53 |"/..y..r.K.....S|
+00000040 97 4e fb 00 df 34 b6 24 8f ff 89 db 00 05 00 00 |.N...4.$........|
+00000050 05 ff 01 00 01 00 16 03 02 02 59 0b 00 02 55 00 |..........Y...U.|
+00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000090 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+000000a0 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+000000b0 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000c0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000d0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000e0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000f0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+00000100 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+00000110 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000120 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000130 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000140 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000150 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000160 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000170 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000180 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000190 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+000001a0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+000001b0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001c0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001d0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001e0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001f0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+00000200 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+00000210 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000220 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000230 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000240 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000250 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000260 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000270 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000280 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000290 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+000002a0 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+000002b0 3b e9 fa e7 16 03 02 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 02 00 86 10 00 00 82 00 80 73 bd 73 65 92 |...........s.se.|
-00000010 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
-00000020 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
-00000030 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
-00000040 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
-00000050 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
-00000060 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
-00000070 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
-00000080 4d e5 78 13 4e a4 38 46 42 dc 16 14 03 02 00 01 |M.x.N.8FB.......|
-00000090 01 16 03 02 00 24 0b 7b 3e 32 fb 94 95 66 26 a9 |.....$.{>2...f&.|
-000000a0 4c 21 5e 18 59 cb 80 57 1b 9a 89 c8 91 c5 30 1f |L!^.Y..W......0.|
-000000b0 1a e2 80 9a 0f 03 8e 7b 4c 7d |.......{L}|
+00000000 16 03 02 00 86 10 00 00 82 00 80 b9 65 8d bf a7 |............e...|
+00000010 c8 4b 79 ce 6f cb 8b 13 1c ac b9 7d 66 5e e9 ba |.Ky.o......}f^..|
+00000020 1d 71 4e a9 e9 34 ae f6 64 65 90 3b d8 16 52 a2 |.qN..4..de.;..R.|
+00000030 6f f4 cb 8a 13 74 a2 ee b7 27 69 b4 41 c0 90 68 |o....t...'i.A..h|
+00000040 bc 02 69 e1 c6 48 4f 39 36 30 25 ca 4c 17 ce 83 |..i..HO960%.L...|
+00000050 9e 08 56 e3 05 49 93 9e 2e c4 fb e6 c8 01 f1 0f |..V..I..........|
+00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..|
+00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..|
+00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 02 00 01 |.Y(.....ia5.....|
+00000090 01 16 03 02 00 24 92 fa 9a bb 9b a3 39 3f 6b 0c |.....$......9?k.|
+000000a0 70 b5 48 4a fc cf 79 86 c7 90 e8 db ca 6a ff 95 |p.HJ..y......j..|
+000000b0 11 9b 65 b2 07 61 00 a8 dc 14 |..e..a....|
>>> Flow 4 (server to client)
-00000000 14 03 02 00 01 01 16 03 02 00 24 06 7f be 82 45 |..........$....E|
-00000010 79 c6 67 fb d3 1e 3f ca d9 0f 8f 81 36 cc 80 77 |y.g...?.....6..w|
-00000020 b8 48 f3 88 29 fa f1 3a b2 d4 fd 10 e5 8c 43 |.H..)..:......C|
+00000000 14 03 02 00 01 01 16 03 02 00 24 47 d5 78 31 32 |..........$G.x12|
+00000010 db db 2b f4 2f e6 a4 fa fa 04 31 ba c0 bc 86 38 |..+./.....1....8|
+00000020 29 70 53 c6 8c 28 e5 75 90 ed 0f 4f 3e cb 06 |)pS..(.u...O>..|
>>> Flow 5 (client to server)
-00000000 17 03 02 00 1a 29 4d a2 80 38 2c 9e 96 bb 29 8b |.....)M..8,...).|
-00000010 22 69 ea 85 3e d8 a9 66 39 b8 58 12 ae 67 db 15 |"i..>..f9.X..g..|
-00000020 03 02 00 16 8c b2 f4 c1 35 5d 28 dc 5c bc 30 95 |........5](.\.0.|
-00000030 99 3e f6 c6 ff 4f 5c f4 85 1a |.>...O\...|
+00000000 17 03 02 00 1a f3 e7 6c 01 c5 70 c6 69 dd 4f 40 |.......l..p.i.O@|
+00000010 38 c1 b2 d2 28 69 2f 99 b1 bd 71 d0 c2 00 08 15 |8...(i/...q.....|
+00000020 03 02 00 16 4c 44 14 02 8e 46 f8 84 40 f1 3d 6d |....LD...F..@.=m|
+00000030 f2 01 f6 9d 7a 0b 18 ee 9d 41 |....z....A|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 b/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256
index 9e41089e824..c20dcc658f3 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256
@@ -1,81 +1,80 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 51 02 00 00 4d 03 03 e7 18 39 61 14 |....Q...M....9a.|
-00000010 47 69 40 34 ae 4e 58 4b 32 2d ed 2a 52 09 c5 2f |Gi@4.NXK2-.*R../|
-00000020 07 f6 44 0b 2b 9c 43 4b bb 79 b6 20 48 f4 ff f1 |..D.+.CK.y. H...|
-00000030 c6 72 77 e5 3a e0 8d 08 b9 cd 8b bf e3 9b ec 41 |.rw.:..........A|
-00000040 1d d9 86 1b 35 7b 8c 04 e0 83 0d d3 00 9c 00 00 |....5{..........|
-00000050 05 ff 01 00 01 00 16 03 03 02 71 0b 00 02 6d 00 |..........q...m.|
-00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002d0 04 0e 00 00 00 |.....|
+00000000 16 03 03 00 51 02 00 00 4d 03 03 65 9c b1 7a 5c |....Q...M..e..z\|
+00000010 84 e5 a5 12 ba 54 1f 4c ec 95 0b 8f ea 5c cc 3b |.....T.L.....\.;|
+00000020 de b8 18 23 8e c4 95 59 d7 7f 8f 20 36 fe ec 27 |...#...Y... 6..'|
+00000030 10 85 43 fb 9c 68 3f 69 d0 08 a6 57 10 a6 29 a4 |..C..h?i...W..).|
+00000040 f6 0c 2e 05 6e 0d e5 44 61 e1 2e 07 00 9c 00 00 |....n..Da.......|
+00000050 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000090 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+000000a0 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+000000b0 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000c0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000d0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000e0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000f0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+00000100 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+00000110 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000120 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000130 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000140 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000150 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000160 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000170 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000180 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000190 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+000001a0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+000001b0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001c0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001d0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001e0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001f0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+00000200 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+00000210 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000220 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000230 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000240 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000250 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000260 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000270 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000280 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000290 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+000002a0 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+000002b0 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 73 bd 73 65 92 |...........s.se.|
-00000010 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
-00000020 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
-00000030 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
-00000040 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
-00000050 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
-00000060 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
-00000070 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
-00000080 4d e5 78 13 4e a4 38 46 42 dc 16 14 03 03 00 01 |M.x.N.8FB.......|
-00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 8a 9b |.....(..........|
-000000a0 29 1d 64 2e ee 0d 39 d9 c5 86 b9 02 9d c3 bd 74 |).d...9........t|
-000000b0 39 9d 53 9f 1a ee 84 64 82 82 41 81 f8 2f |9.S....d..A../|
+00000000 16 03 03 00 86 10 00 00 82 00 80 b9 65 8d bf a7 |............e...|
+00000010 c8 4b 79 ce 6f cb 8b 13 1c ac b9 7d 66 5e e9 ba |.Ky.o......}f^..|
+00000020 1d 71 4e a9 e9 34 ae f6 64 65 90 3b d8 16 52 a2 |.qN..4..de.;..R.|
+00000030 6f f4 cb 8a 13 74 a2 ee b7 27 69 b4 41 c0 90 68 |o....t...'i.A..h|
+00000040 bc 02 69 e1 c6 48 4f 39 36 30 25 ca 4c 17 ce 83 |..i..HO960%.L...|
+00000050 9e 08 56 e3 05 49 93 9e 2e c4 fb e6 c8 01 f1 0f |..V..I..........|
+00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..|
+00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..|
+00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....|
+00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 97 f1 |.....(..........|
+000000a0 fe 34 f7 de 76 9b 56 27 e6 9f 36 48 30 a6 de 78 |.4..v.V'..6H0..x|
+000000b0 10 6a ef bf 92 8a 6e 99 21 2f 1b 7b 48 80 |.j....n.!/.{H.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 60 71 25 f9 f9 |..........(`q%..|
-00000010 89 cd f8 6f 00 a6 0e 92 f8 3e 84 08 79 6f 91 cd |...o.....>..yo..|
-00000020 e2 62 d5 da 96 79 c3 0d f4 34 26 bd 47 9c 30 aa |.b...y...4&.G.0.|
-00000030 1b 5f 24 |._$|
+00000000 14 03 03 00 01 01 16 03 03 00 28 23 9d a2 ae a1 |..........(#....|
+00000010 7d dd 92 1f 42 18 68 f6 fb 31 56 7b e4 58 a4 e9 |}...B.h..1V{.X..|
+00000020 c2 1c e7 67 1b 40 b1 b9 63 9d 05 fb c7 44 9e f6 |...g.@..c....D..|
+00000030 7a 14 bb |z..|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 44 05 c9 |.............D..|
-00000010 2b 82 55 26 ab 4b 65 b1 94 e5 8a 81 bf 44 a5 cb |+.U&.Ke......D..|
-00000020 22 f0 0a 15 03 03 00 1a 00 00 00 00 00 00 00 02 |"...............|
-00000030 59 8d 6f 5d 30 47 4d 3e ed aa 87 5f ca 39 44 a4 |Y.o]0GM>..._.9D.|
-00000040 9b fc |..|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 d7 31 70 |..............1p|
+00000010 c8 11 3f bd 83 fc 6e f8 3b e0 ee 45 c5 1a c8 41 |..?...n.;..E...A|
+00000020 80 22 d4 15 03 03 00 1a 00 00 00 00 00 00 00 02 |."..............|
+00000030 7a fe 3a 11 7c c0 26 30 55 24 85 0b 43 cb 7c ac |z.:.|.&0U$..C.|.|
+00000040 ef 2c |.,|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-SHA256 b/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-SHA256
new file mode 100644
index 00000000000..774481e84a7
--- /dev/null
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-AES128-SHA256
@@ -0,0 +1,89 @@
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 91 01 00 00 8d 03 03 00 00 00 00 00 |................|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
+>>> Flow 2 (server to client)
+00000000 16 03 03 00 51 02 00 00 4d 03 03 26 31 ba 4a 56 |....Q...M..&1.JV|
+00000010 16 83 15 47 b9 c4 7e 10 ca 92 31 4d 77 af cc cd |...G..~...1Mw...|
+00000020 70 f4 cc 82 6e b9 ac 1b 0d 17 25 20 e9 08 ec 95 |p...n.....% ....|
+00000030 ea 84 a4 bd 8f 9d 8e d3 58 a7 5e 72 42 e4 19 8f |........X.^rB...|
+00000040 46 c3 d9 be 16 3c d4 53 5a 02 8f a1 00 3c 00 00 |F....<.SZ....<..|
+00000050 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000090 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+000000a0 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+000000b0 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000c0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000d0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000e0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000f0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+00000100 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+00000110 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000120 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000130 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000140 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000150 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000160 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000170 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000180 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000190 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+000001a0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+000001b0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001c0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001d0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001e0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001f0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+00000200 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+00000210 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000220 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000230 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000240 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000250 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000260 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000270 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000280 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000290 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+000002a0 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+000002b0 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............|
+>>> Flow 3 (client to server)
+00000000 16 03 03 00 86 10 00 00 82 00 80 b9 65 8d bf a7 |............e...|
+00000010 c8 4b 79 ce 6f cb 8b 13 1c ac b9 7d 66 5e e9 ba |.Ky.o......}f^..|
+00000020 1d 71 4e a9 e9 34 ae f6 64 65 90 3b d8 16 52 a2 |.qN..4..de.;..R.|
+00000030 6f f4 cb 8a 13 74 a2 ee b7 27 69 b4 41 c0 90 68 |o....t...'i.A..h|
+00000040 bc 02 69 e1 c6 48 4f 39 36 30 25 ca 4c 17 ce 83 |..i..HO960%.L...|
+00000050 9e 08 56 e3 05 49 93 9e 2e c4 fb e6 c8 01 f1 0f |..V..I..........|
+00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..|
+00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..|
+00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....|
+00000090 01 16 03 03 00 50 00 00 00 00 00 00 00 00 00 00 |.....P..........|
+000000a0 00 00 00 00 00 00 46 91 40 e2 65 40 fe 42 c3 34 |......F.@.e@.B.4|
+000000b0 98 65 89 d0 96 7e 7b 67 8e c4 d5 e6 37 f5 96 04 |.e...~{g....7...|
+000000c0 b7 c8 63 83 76 5c ca 9d 89 18 d4 97 8b 3f f6 75 |..c.v\.......?.u|
+000000d0 1d 51 0b b9 90 1c 85 8f 83 20 9e 9a 21 d9 db 14 |.Q....... ..!...|
+000000e0 1e 02 d4 ab aa c4 |......|
+>>> Flow 4 (server to client)
+00000000 14 03 03 00 01 01 16 03 03 00 50 6d 34 72 de 79 |..........Pm4r.y|
+00000010 ad 96 d0 92 5f d7 01 de 90 f4 5d 0f de 02 ae 19 |...._.....].....|
+00000020 61 a3 ee 29 ab 18 f1 09 2e 5b bc e0 73 9a 68 19 |a..).....[..s.h.|
+00000030 17 dd c8 d9 63 b4 28 c8 da 1a 81 40 ca d3 5a 99 |....c.(....@..Z.|
+00000040 17 67 fe e9 dd 1a 52 c4 6e 70 0a 0e cf e8 c0 f8 |.g....R.np......|
+00000050 6c 1f ee d2 70 97 dc ee b8 95 35 |l...p.....5|
+>>> Flow 5 (client to server)
+00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........|
+00000010 00 00 00 00 00 ee 03 cc 04 97 17 f0 04 85 02 b7 |................|
+00000020 5c 24 ca 9f c2 25 e0 76 f4 72 e5 71 2b ac f4 a5 |\$...%.v.r.q+...|
+00000030 c4 62 08 9a da b7 ab 30 2f 34 b0 70 20 a3 b9 b3 |.b.....0/4.p ...|
+00000040 df 90 9b 01 0b 15 03 03 00 40 00 00 00 00 00 00 |.........@......|
+00000050 00 00 00 00 00 00 00 00 00 00 3b ca fc 0e 08 f2 |..........;.....|
+00000060 c8 b7 22 61 43 24 b3 54 1b ca 58 c6 bd 27 f3 3d |.."aC$.T..X..'.=|
+00000070 ac a0 d8 fe 0e b5 15 7c 1f 98 32 f0 6b 28 bc 61 |.......|..2.k(.a|
+00000080 6c c7 ba 66 54 19 92 a9 6f 43 |l..fT...oC|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384 b/libgo/go/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384
index 33fb70871ee..6d2674639a2 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384
@@ -1,81 +1,80 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 51 02 00 00 4d 03 03 08 e2 40 1b 1a |....Q...M....@..|
-00000010 54 dc 66 60 e1 e0 8d 94 c6 dd 2c eb 95 e0 e9 2f |T.f`......,..../|
-00000020 fb 49 17 d8 34 d7 a2 7a 1b e1 60 20 26 a3 4b 7c |.I..4..z..` &.K||
-00000030 40 cc df 4b 9c 72 a9 e6 61 89 1e 20 b2 e5 e3 1e |@..K.r..a.. ....|
-00000040 4e a3 b6 32 ce fc 94 0d ab 13 74 f8 00 9d 00 00 |N..2......t.....|
-00000050 05 ff 01 00 01 00 16 03 03 02 71 0b 00 02 6d 00 |..........q...m.|
-00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002d0 04 0e 00 00 00 |.....|
+00000000 16 03 03 00 51 02 00 00 4d 03 03 98 b0 4a 9a c8 |....Q...M....J..|
+00000010 8f f9 1f f9 70 03 d9 1a ee 7c 29 30 6a 71 7c 6c |....p....|)0jq|l|
+00000020 ea 2c de 84 f9 ee 4d 2c d7 58 12 20 a4 e2 1b f3 |.,....M,.X. ....|
+00000030 42 b8 9a 0b 71 8c 27 57 61 98 c5 c5 1b 04 01 5b |B...q.'Wa......[|
+00000040 a0 bc 88 64 d9 ce 5a a1 b2 7b 6c 4e 00 9d 00 00 |...d..Z..{lN....|
+00000050 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000090 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+000000a0 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+000000b0 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000c0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000d0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000e0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000f0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+00000100 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+00000110 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000120 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000130 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000140 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000150 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000160 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000170 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000180 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000190 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+000001a0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+000001b0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001c0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001d0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001e0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001f0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+00000200 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+00000210 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000220 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000230 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000240 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000250 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000260 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000270 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000280 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000290 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+000002a0 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+000002b0 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 73 bd 73 65 92 |...........s.se.|
-00000010 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
-00000020 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
-00000030 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
-00000040 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
-00000050 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
-00000060 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
-00000070 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
-00000080 4d e5 78 13 4e a4 38 46 42 dc 16 14 03 03 00 01 |M.x.N.8FB.......|
-00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 28 9a |.....(........(.|
-000000a0 46 23 21 fa a9 ec 6d 57 d1 27 2f 53 58 a9 00 48 |F#!...mW.'/SX..H|
-000000b0 7e 82 82 b8 23 f3 c4 a8 d3 2c a3 99 76 2e |~...#....,..v.|
+00000000 16 03 03 00 86 10 00 00 82 00 80 b9 65 8d bf a7 |............e...|
+00000010 c8 4b 79 ce 6f cb 8b 13 1c ac b9 7d 66 5e e9 ba |.Ky.o......}f^..|
+00000020 1d 71 4e a9 e9 34 ae f6 64 65 90 3b d8 16 52 a2 |.qN..4..de.;..R.|
+00000030 6f f4 cb 8a 13 74 a2 ee b7 27 69 b4 41 c0 90 68 |o....t...'i.A..h|
+00000040 bc 02 69 e1 c6 48 4f 39 36 30 25 ca 4c 17 ce 83 |..i..HO960%.L...|
+00000050 9e 08 56 e3 05 49 93 9e 2e c4 fb e6 c8 01 f1 0f |..V..I..........|
+00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..|
+00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..|
+00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....|
+00000090 01 16 03 03 00 28 00 00 00 00 00 00 00 00 57 97 |.....(........W.|
+000000a0 64 ef 80 07 b0 31 02 c8 2a a2 b7 1f d6 a3 7c 7a |d....1..*.....|z|
+000000b0 e9 c4 e1 55 9f 0a ef 0d 8f 0a 57 13 f5 a4 |...U......W...|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 0c c8 0a e1 b8 |..........(.....|
-00000010 95 b9 84 bc 0f 48 eb d4 4a a5 63 c2 92 58 8a 91 |.....H..J.c..X..|
-00000020 27 30 36 28 23 f5 50 bd d6 a9 e9 61 54 10 f9 72 |'06(#.P....aT..r|
-00000030 98 d1 0e |...|
+00000000 14 03 03 00 01 01 16 03 03 00 28 42 49 9c 67 4f |..........(BI.gO|
+00000010 36 75 b8 34 0e ee 00 98 1a ba 52 d5 96 7b 91 d7 |6u.4......R..{..|
+00000020 ba ec e4 5e 2e 42 e3 72 a0 ea 60 24 31 30 3d a2 |...^.B.r..`$10=.|
+00000030 c5 6c 8f |.l.|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 b9 55 ce |..............U.|
-00000010 5a ab 7e 7e 58 4f c9 5a bc 0e 93 98 4f 87 86 98 |Z.~~XO.Z....O...|
-00000020 a6 40 7e 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.@~.............|
-00000030 57 0c 6f d9 28 87 d4 a6 de 14 91 a7 79 cc 19 e5 |W.o.(.......y...|
-00000040 28 66 |(f|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 42 9f da |.............B..|
+00000010 a1 e6 98 48 a8 6c 78 a0 f7 fd e7 0f bc df 97 ef |...H.lx.........|
+00000020 b8 62 4c 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.bL.............|
+00000030 99 ac 35 a4 d9 1f 58 26 51 c6 6a b9 1f 53 ec 19 |..5...X&Q.j..S..|
+00000040 90 78 |.x|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN b/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN
index d7745dc295c..9f90ff269ad 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN
@@ -1,93 +1,86 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 9d 01 00 00 99 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 a9 01 00 00 a5 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 4e 33 74 00 00 00 05 00 05 01 00 00 00 |...N3t..........|
-00000060 00 00 0a 00 08 00 06 00 17 00 18 00 19 00 0b 00 |................|
-00000070 02 01 00 00 0d 00 0e 00 0c 04 01 04 03 05 01 05 |................|
-00000080 03 02 01 02 03 ff 01 00 01 00 00 10 00 10 00 0e |................|
-00000090 06 70 72 6f 74 6f 32 06 70 72 6f 74 6f 31 00 12 |.proto2.proto1..|
-000000a0 00 00 |..|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 50 33 74 |.............P3t|
+00000060 00 00 00 05 00 05 01 00 00 00 00 00 0a 00 0a 00 |................|
+00000070 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
+00000080 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
+00000090 03 ff 01 00 01 00 00 10 00 10 00 0e 06 70 72 6f |.............pro|
+000000a0 74 6f 32 06 70 72 6f 74 6f 31 00 12 00 00 |to2.proto1....|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 66 02 00 00 62 03 03 a2 7d b9 7c f9 |....f...b...}.|.|
-00000010 bf fb cb b2 d5 11 c0 99 19 73 3d b4 eb 6b 39 f8 |.........s=..k9.|
-00000020 1b 7c 1d 6b 17 4d 66 a3 ed 20 5b 20 ee 87 d7 1f |.|.k.Mf.. [ ....|
-00000030 cf 60 6c 75 12 8b de 56 f6 ca da 4a 92 76 49 43 |.`lu...V...J.vIC|
-00000040 70 18 0a e7 7b 2a 0c f3 44 a6 d8 dd c0 2f 00 00 |p...{*..D..../..|
+00000000 16 03 03 00 66 02 00 00 62 03 03 8d 70 c6 03 ad |....f...b...p...|
+00000010 2f 20 b3 c2 ab e0 fc 80 74 c4 23 9e 82 65 61 a1 |/ ......t.#..ea.|
+00000020 26 97 14 a0 9b 9c d5 e0 92 43 ee 20 ec 84 cf 78 |&........C. ...x|
+00000030 44 16 7d f3 ad 94 a9 f8 c3 e0 c6 e1 b6 c5 e3 3d |D.}............=|
+00000040 77 ea 76 1d 58 cc 94 3a ad 1a 1a 6c cc a8 00 00 |w.v.X..:...l....|
00000050 1a ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 10 |................|
-00000060 00 09 00 07 06 70 72 6f 74 6f 31 16 03 03 02 71 |.....proto1....q|
-00000070 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 63 30 82 |...m..j..g0..c0.|
-00000080 01 cc a0 03 02 01 02 02 09 00 a2 73 00 0c 81 00 |...........s....|
-00000090 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 |..0...*.H.......|
-000000a0 00 30 2b 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |.0+1.0...U....Go|
-000000b0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 10 30 0e |ogle TESTING1.0.|
-000000c0 06 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e |..U....Go Root0.|
-000000d0 17 0d 31 35 30 31 30 31 30 30 30 30 30 30 5a 17 |..150101000000Z.|
-000000e0 0d 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 26 |.250101000000Z0&|
-000000f0 31 17 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c |1.0...U....Googl|
-00000100 65 20 54 45 53 54 49 4e 47 31 0b 30 09 06 03 55 |e TESTING1.0...U|
-00000110 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 |....Go0..0...*.H|
-00000120 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 |............0...|
-00000130 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 ab 44 05 |....... ..el..D.|
-00000140 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f fe 6a 62 |.;E...m..cM...jb|
-00000150 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 31 66 00 |5..J..|..%^zd1f.|
-00000160 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 cb 6e 56 |......k.v.._A.nV|
-00000170 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 d1 bc db |.....<.9!f=+....|
-00000180 1c c0 a7 da b7 ca ad ba da cb d5 21 50 ec de 8d |...........!P...|
-00000190 ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 b1 44 84 |..k.K......l..D.|
-000001a0 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef fa d6 09 |.!..}..M........|
-000001b0 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 90 30 0e |G..........0..0.|
-000001c0 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d |..U...........0.|
-000001d0 06 03 55 1d 25 04 16 30 14 06 08 2b 06 01 05 05 |..U.%..0...+....|
-000001e0 07 03 01 06 08 2b 06 01 05 05 07 03 02 30 0c 06 |.....+.......0..|
-000001f0 03 55 1d 13 01 01 ff 04 02 30 00 30 19 06 03 55 |.U.......0.0...U|
-00000200 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 dc 54 4d |.......P..o...TM|
-00000210 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 04 14 30 |n.i^..0...U.#..0|
-00000220 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea b4 03 78 |....=..f..@....x|
-00000230 48 1a 41 30 19 06 03 55 1d 11 04 12 30 10 82 0e |H.A0...U....0...|
-00000240 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d |example.golang0.|
-00000250 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 |..*.H...........|
-00000260 00 92 7c af 91 55 12 18 96 59 31 a6 48 40 d5 2d |..|..U...Y1.H@.-|
-00000270 d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 |........|..0}<.v|
-00000280 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b 67 59 11 |.O=...-3$k.{.gY.|
-00000290 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f |!...w...n.-.5.d_|
-000002a0 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 31 a8 14 |">c.k....m...1..|
-000002b0 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 4f dd db |8.;..,...Qv..O..|
-000002c0 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 46 de 46 |....@.Q......F.F|
-000002d0 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea b0 ab 39 |.O.....A4......9|
-000002e0 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 41 |.............A.A|
-000002f0 a4 1f 6f ea 6d 59 68 72 1a 6d 47 c7 b4 a0 08 01 |..o.mYhr.mG.....|
-00000300 b9 b3 d8 7a 95 75 c0 58 2a d9 29 91 e7 d9 78 b2 |...z.u.X*.)...x.|
-00000310 97 1d 52 72 2d 18 cb ce 83 8a 07 f4 bd dd 7e a1 |..Rr-.........~.|
-00000320 d2 45 51 9d bf f1 bf 01 33 3a 10 94 6c 2b 99 04 |.EQ.....3:..l+..|
-00000330 01 00 80 63 8f 03 6d b4 4d f7 27 d0 1f f2 0f ff |...c..m.M.'.....|
-00000340 af 27 c2 97 21 68 8c 32 8b 14 67 0e b5 75 3a 5b |.'..!h.2..g..u:[|
-00000350 73 08 9a c7 fd ad 8d 50 2a de e7 d6 c5 87 7a b2 |s......P*.....z.|
-00000360 06 29 0a 09 dd d4 81 d5 a7 2b 4d 20 50 72 6f be |.).......+M Pro.|
-00000370 35 9b c6 2d b0 1e 8f a2 cf 10 33 d4 53 0b 33 95 |5..-......3.S.3.|
-00000380 b8 a5 34 38 1b db 1e 45 07 36 3a 86 c7 f1 b1 3a |..48...E.6:....:|
-00000390 2e 5d 82 b2 1d 3e e1 27 8f f2 f4 2c 8c c3 27 e9 |.]...>.'...,..'.|
-000003a0 f0 9a 8f 6d 20 b1 19 8e 23 d5 04 69 e4 eb 0d eb |...m ...#..i....|
-000003b0 97 fb 71 16 03 03 00 04 0e 00 00 00 |..q.........|
+00000060 00 09 00 07 06 70 72 6f 74 6f 31 16 03 03 02 59 |.....proto1....Y|
+00000070 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 |...U..R..O0..K0.|
+00000080 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b |.............?.[|
+00000090 ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 |..0...*.H.......|
+000000a0 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |.0.1.0...U....Go|
+000000b0 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f |1.0...U....Go Ro|
+000000c0 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 |ot0...1601010000|
+000000d0 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 |00Z..25010100000|
+000000e0 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 |0Z0.1.0...U....G|
+000000f0 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 |o1.0...U....Go0.|
+00000100 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 |.0...*.H........|
+00000110 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e |....0.......F}..|
+00000120 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e |.'.H..(!.~...]..|
+00000130 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be |RE.z6G....B[....|
+00000140 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 |.y.@.Om..+.....g|
+00000150 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 |....."8.J.ts+.4.|
+00000160 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 |.....t{.X.la<..A|
+00000170 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 |..++$#w[.;.u]. T|
+00000180 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 |..c...$....P....|
+00000190 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 |C...ub...R......|
+000001a0 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff |...0..0...U.....|
+000001b0 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 |......0...U.%..0|
+000001c0 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 |...+.........+..|
+000001d0 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 |.....0...U......|
+000001e0 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 |.0.0...U........|
+000001f0 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b |..CC>I..m....`0.|
+00000200 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 |..U.#..0...H.IM.|
+00000210 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 |~.1......n{0...U|
+00000220 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e |....0...example.|
+00000230 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d |golang0...*.H...|
+00000240 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 |..........0.@+[P|
+00000250 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 |.a...SX...(.X..8|
+00000260 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 |....1Z..f=C.-...|
+00000270 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 |... d8.$:....}.@|
+00000280 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c | ._...a..v......|
+00000290 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c |\.....l..s..Cw..|
+000002a0 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 |.....@.a.Lr+...F|
+000002b0 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 |..M...>...B...=.|
+000002c0 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c 00 |`.\!.;..........|
+000002d0 00 a8 03 00 1d 20 84 de 31 92 b6 a5 d8 a4 88 a2 |..... ..1.......|
+000002e0 54 67 e6 61 40 f2 5a 87 0f ce 15 b1 d6 af f3 5d |Tg.a@.Z........]|
+000002f0 99 71 d6 04 f5 52 04 01 00 80 a8 1d 8b 8c e9 a3 |.q...R..........|
+00000300 af 2d 31 e4 0f f0 26 74 c2 e5 1b ae ac 47 9c 6e |.-1...&t.....G.n|
+00000310 6c 5f 45 7d b1 b3 2a af 36 68 42 13 95 0d 33 1c |l_E}..*.6hB...3.|
+00000320 8d 6c 72 48 4a 94 f0 fb 82 20 cc 76 21 7f 62 e7 |.lrHJ.... .v!.b.|
+00000330 23 a3 c8 4e 3a ce f1 5c c3 60 73 26 59 4c 94 f3 |#..N:..\.`s&YL..|
+00000340 07 36 f6 a0 b3 60 03 d5 72 1e bf c8 d9 1d 61 01 |.6...`..r.....a.|
+00000350 9a 18 57 a3 b4 de 36 1f e1 7d dc 69 c0 fb c0 71 |..W...6..}.i...q|
+00000360 45 1f 73 0d 50 69 d3 18 97 23 60 1c 5a 9a 93 b4 |E.s.Pi...#`.Z...|
+00000370 67 cc e5 80 3b 25 d0 6c 50 c8 16 03 03 00 04 0e |g...;%.lP.......|
+00000380 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 15 94 |.....(..........|
-00000060 6f 5b 35 9d eb 14 c8 be 23 a7 05 8c 14 86 35 a7 |o[5.....#.....5.|
-00000070 5c 91 76 4f 85 b1 09 f8 0f 58 9f ec d2 a9 |\.vO.....X....|
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 20 5c c5 3e 7a 14 97 1b 55 88 25 08 |.... \.>z...U.%.|
+00000040 ad 86 48 ac f0 43 8c 17 5b 58 93 6c 7a 95 69 a8 |..H..C..[X.lz.i.|
+00000050 ad 0c b3 61 4d |...aM|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 e7 7f 99 c9 fa |..........(.....|
-00000010 e0 a3 e3 77 68 74 37 62 26 90 d6 be ec a1 ae 5a |...wht7b&......Z|
-00000020 de af 10 f1 2e a0 42 f0 88 ed 89 54 04 b2 b9 eb |......B....T....|
-00000030 b0 91 b8 |...|
+00000000 14 03 03 00 01 01 16 03 03 00 20 dd 1b 80 da d9 |.......... .....|
+00000010 73 da 7d 15 9b 92 82 01 a7 8f fe 4a 75 97 8f f4 |s.}........Ju...|
+00000020 64 1b bf cf c3 40 78 f2 52 f5 7a |d....@x.R.z|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 be e7 77 |...............w|
-00000010 f9 92 ac 51 d0 34 25 34 e6 35 9e ea f0 d3 89 45 |...Q.4%4.5.....E|
-00000020 84 1b 93 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................|
-00000030 1a 27 54 01 c9 7c 86 4b 61 c8 98 1b d3 15 1f 93 |.'T..|.Ka.......|
-00000040 f9 42 |.B|
+00000000 17 03 03 00 16 4e fa 7c 37 80 48 19 a6 03 25 7c |.....N.|7.H...%||
+00000010 65 56 43 af 9a e8 e2 aa e5 79 98 15 03 03 00 12 |eVC......y......|
+00000020 f9 b7 01 e8 2e 85 33 89 60 44 84 93 26 4c ec ac |......3.`D..&L..|
+00000030 2e 6f |.o|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch b/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch
index 9a34e4a78bb..62e7d11bb8d 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch
@@ -1,91 +1,91 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 96 01 00 00 92 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 9c 01 00 00 98 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 47 33 74 00 00 00 05 00 05 01 00 00 00 |...G3t..........|
-00000060 00 00 0a 00 08 00 06 00 17 00 18 00 19 00 0b 00 |................|
-00000070 02 01 00 00 0d 00 0e 00 0c 04 01 04 03 05 01 05 |................|
-00000080 03 02 01 02 03 ff 01 00 01 00 00 10 00 09 00 07 |................|
-00000090 06 70 72 6f 74 6f 33 00 12 00 00 |.proto3....|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 28 c0 2f |.............(./|
+00000030 c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 c0 09 c0 14 |.+.0.,.'...#....|
+00000040 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 c0 12 00 0a |.......<./.5....|
+00000050 00 05 c0 11 c0 07 01 00 00 47 33 74 00 00 00 05 |.........G3t....|
+00000060 00 05 01 00 00 00 00 00 0a 00 08 00 06 00 17 00 |................|
+00000070 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 0c 04 |................|
+00000080 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 01 00 |................|
+00000090 00 10 00 09 00 07 06 70 72 6f 74 6f 33 00 12 00 |.......proto3...|
+000000a0 00 |.|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 18 3d 15 59 fb |....Y...U...=.Y.|
-00000010 0a a4 93 d7 43 50 59 7f 6c f9 64 db b5 47 cc 17 |....CPY.l.d..G..|
-00000020 8c cd 91 b5 04 02 3f c0 5d 60 b7 20 75 ed d2 e9 |......?.]`. u...|
-00000030 b6 72 2d f7 66 34 2e 2f d2 b9 80 66 eb c3 36 f6 |.r-.f4./...f..6.|
-00000040 b2 61 77 79 a9 c2 db cd 57 5a b2 6b c0 2f 00 00 |.awy....WZ.k./..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 36 0e 9f 51 42 |....Y...U..6..QB|
+00000010 82 65 fa b5 17 7a 86 d6 40 33 a9 67 d3 3d aa 2f |.e...z..@3.g.=./|
+00000020 89 a0 39 82 af 16 30 8e 64 80 d4 20 23 a6 d0 12 |..9...0.d.. #...|
+00000030 ff 8c fc b4 b5 47 ec 10 fe ba 73 fb 0f ab e8 1c |.....G....s.....|
+00000040 15 c1 fb 11 c1 b2 e1 8a f7 5d 5b ad c0 2f 00 00 |.........][../..|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
-00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
-00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
-000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
-000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
-000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
-000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
-000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
-000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
-00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
-00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
-00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
-00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
-00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
-00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
-00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
-00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
-00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
-00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
-000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
-000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
-000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
-000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
-000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
-000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
-00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
-00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
-00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
-00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
-00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
-00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
-00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
-00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
-00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
-00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
-000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
-000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
-000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
-000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............|
-000002e0 41 04 62 52 78 76 89 36 e7 b9 a6 cc df 8e f8 c3 |A.bRxv.6........|
-000002f0 52 54 b6 42 9b 68 65 65 27 91 bf 1b 0f 21 ab a9 |RT.B.hee'....!..|
-00000300 f4 00 62 dd 70 25 b8 ec d0 3d 9b 0c 53 16 6e eb |..b.p%...=..S.n.|
-00000310 a8 c3 1a ad a9 de ec 27 64 07 e8 9b b8 bf 5a 6c |.......'d.....Zl|
-00000320 87 f4 04 01 00 80 05 ec 2b f7 2e a4 5e 79 85 6f |........+...^y.o|
-00000330 64 7a b5 fb 9a e9 f1 12 ae 28 93 4b 6d 8e a0 2f |dz.......(.Km../|
-00000340 94 bc 38 26 01 64 ab fb 03 c8 3d 17 bc b4 43 09 |..8&.d....=...C.|
-00000350 19 c8 e9 ac 60 40 67 57 71 e3 72 22 cf b1 a7 38 |....`@gWq.r"...8|
-00000360 ac 86 88 9d 47 6f 70 c9 43 82 75 b6 bf 42 4e 72 |....Gop.C.u..BNr|
-00000370 12 48 d1 2b ce 74 02 5d 30 56 66 6f 71 8f 9b 82 |.H.+.t.]0Vfoq...|
-00000380 70 3b 92 5d fb 37 d3 cf d3 23 27 d2 d5 8d 72 22 |p;.].7...#'...r"|
-00000390 d4 b4 92 6d 64 06 d9 0b e0 bb 34 eb bf 42 ec 6a |...md.....4..B.j|
-000003a0 ea e3 56 68 85 a0 16 03 03 00 04 0e 00 00 00 |..Vh...........|
+00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
+000002c0 cd 0c 00 00 c9 03 00 17 41 04 11 b4 a9 10 7e 5c |........A.....~\|
+000002d0 41 5e 39 12 15 a3 ed 5b 3e 5d 68 c8 ad 48 39 ef |A^9....[>]h..H9.|
+000002e0 09 8b b1 a7 bf db 5f 54 49 cd d5 de 4d b3 47 4c |......_TI...M.GL|
+000002f0 18 02 84 7c ec 75 4e d0 3e 8a d1 6c 80 83 98 64 |...|.uN.>..l...d|
+00000300 4a 81 bc 8f 84 c7 e5 b4 2d fa 04 01 00 80 72 ee |J.......-.....r.|
+00000310 41 38 f2 b8 a1 56 81 d8 04 78 75 05 f4 78 5f f2 |A8...V...xu..x_.|
+00000320 2b 5d a2 46 23 9d 48 c8 63 a9 1d de a8 78 6e 99 |+].F#.H.c....xn.|
+00000330 cd 59 6b 19 20 f5 b1 11 e1 f8 1c 5b 40 c3 b8 cd |.Yk. ......[@...|
+00000340 66 a3 98 37 c5 c2 5c b7 d6 cc 61 b4 5e 97 fa dd |f..7..\...a.^...|
+00000350 b7 85 5d b6 34 8c 39 4a 60 5a 03 20 47 7f e3 65 |..].4.9J`Z. G..e|
+00000360 01 18 00 2c c3 eb be d4 aa 58 57 a9 5e 69 fb 3c |...,.....XW.^i.<|
+00000370 fa c6 28 1a 5c f7 00 d5 21 e5 c1 30 db 84 38 c3 |..(.\...!..0..8.|
+00000380 08 aa 08 5f c9 fd a0 b7 8e d0 66 77 bf 13 16 03 |..._......fw....|
+00000390 03 00 04 0e 00 00 00 |.......|
>>> Flow 3 (client to server)
00000000 16 03 03 00 46 10 00 00 42 41 04 1e 18 37 ef 0d |....F...BA...7..|
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 97 34 |.....(.........4|
-00000060 d5 c2 64 97 f6 a9 f5 60 bc 17 f3 d3 02 3f 42 a8 |..d....`.....?B.|
-00000070 2f ba eb c6 50 3c ec 9b 8d 3b 22 ed ec 35 |/...P<...;"..5|
+00000050 01 16 03 03 00 28 00 00 00 00 00 00 00 00 4f 7e |.....(........O~|
+00000060 9a 3a cc 74 a4 91 77 01 0b 0e 28 0a c5 bd 55 b7 |.:.t..w...(...U.|
+00000070 9a 4c 40 4e e9 c9 46 d5 5f c5 e1 77 c3 f2 |.L@N..F._..w..|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 9a e5 f5 51 5c |..........(...Q\|
-00000010 cb be 5d a1 67 cc 55 aa ba db e7 0a ab 96 3b 33 |..].g.U.......;3|
-00000020 5f 2c 8c 61 20 f1 0d 6e ce 90 d8 39 27 d7 fb 68 |_,.a ..n...9'..h|
-00000030 d9 dd da |...|
+00000000 14 03 03 00 01 01 16 03 03 00 28 62 4b 13 ef 22 |..........(bK.."|
+00000010 f9 a8 8d ec 42 3a 36 80 5d a8 5b e9 60 d1 ba 65 |....B:6.].[.`..e|
+00000020 2b d8 37 64 e5 12 b2 ef 84 75 87 0c 0f 3d 35 6e |+.7d.....u...=5n|
+00000030 59 7c 51 |Y|Q|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 a8 be 7c |...............||
-00000010 05 48 ea df 62 4a 7a 45 68 e4 dc e6 42 ff 06 f2 |.H..bJzEh...B...|
-00000020 02 33 1a 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.3..............|
-00000030 66 68 f4 de da 69 b4 f9 80 9c 80 c6 46 e5 2b ae |fh...i......F.+.|
-00000040 0e d1 |..|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 5f cd 4d |............._.M|
+00000010 7b a7 c0 f9 6c 1f 80 93 cf 55 3b 12 c7 21 12 86 |{...l....U;..!..|
+00000020 f6 b1 52 15 03 03 00 1a 00 00 00 00 00 00 00 02 |..R.............|
+00000030 fd 31 a4 4b d1 e9 f0 e0 18 b5 96 28 f7 b4 0c 29 |.1.K.......(...)|
+00000040 8c 0c |..|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA
index 4b88acff71d..336e10da83a 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA
@@ -1,19 +1,20 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 f0 5c 85 c8 ff |....Y...U...\...|
-00000010 c5 57 76 99 3d 75 e6 2e db 31 26 c0 0c 81 c5 6b |.Wv.=u...1&....k|
-00000020 30 79 e6 72 86 77 48 01 ec 43 1a 20 f8 fd ad b5 |0y.r.wH..C. ....|
-00000030 a0 7b f3 35 27 df ad 95 f9 56 f9 79 6c a2 6c 23 |.{.5'....V.yl.l#|
-00000040 51 4c ef fc 92 fb fa 59 97 e9 63 27 c0 09 00 00 |QL.....Y..c'....|
+00000000 16 03 03 00 59 02 00 00 55 03 03 cf 28 2c 3e 4f |....Y...U...(,>O|
+00000010 da 6b ae 24 74 a9 91 c3 c5 55 4b ab ec 07 f8 cd |.k.$t....UK.....|
+00000020 65 f8 fe 08 f6 9a 23 da 99 6c 5d 20 af 4a 1e 32 |e.....#..l] .J.2|
+00000030 7b bd 3c 0b b1 14 66 a3 b7 2f a4 2a c3 43 c4 e0 |{.<...f../.*.C..|
+00000040 c2 ad 78 b1 28 ab 51 06 1b 87 d2 75 c0 09 00 00 |..x.(.Q....u....|
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....|
@@ -48,24 +49,22 @@
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 51 |*............A.Q|
-00000280 1e 2e 40 c5 a1 13 15 f0 bc 8a 04 e1 9a 57 74 10 |..@..........Wt.|
-00000290 7e b3 17 bf 0c c9 85 9b 5f bd 6b 39 c7 a6 c0 50 |~......._.k9...P|
-000002a0 0e 5e 9b b1 8c cc 57 39 e8 0f 94 02 be 28 19 16 |.^....W9.....(..|
-000002b0 94 73 2b c1 3c a7 0f c9 e7 b0 89 ac 13 53 f9 04 |.s+.<........S..|
-000002c0 03 00 8b 30 81 88 02 42 01 1b e0 ab 94 02 aa 27 |...0...B.......'|
-000002d0 fa 7b 99 9c 68 36 d8 2d 2e e0 92 84 c7 7b 37 74 |.{..h6.-.....{7t|
-000002e0 6a ad a8 f5 50 3f 74 d5 e8 8e 5a db 31 43 c8 98 |j...P?t...Z.1C..|
-000002f0 d3 ee 61 43 80 9a 72 eb 2d 2b 21 b8 33 aa 61 0a |..aC..r.-+!.3.a.|
-00000300 cd dc 85 88 29 26 83 ee 3c b2 02 42 00 b6 ea 34 |....)&..<..B...4|
-00000310 30 71 5c 0a 9a 6d a2 25 62 1c 3e 13 90 9c a3 b8 |0q\..m.%b.>.....|
-00000320 0d 97 a8 06 26 9e 31 50 88 9a b9 ff 12 63 a8 14 |....&.1P.....c..|
-00000330 18 f3 c2 b0 af d1 27 25 a9 ec ef 69 85 7a 72 c6 |......'%...i.zr.|
-00000340 b0 88 d2 c1 41 43 f4 69 62 25 13 eb f9 f8 16 03 |....AC.ib%......|
-00000350 03 00 2e 0d 00 00 26 03 01 02 40 00 1e 06 01 06 |......&...@.....|
-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 00 00 0e 00 00 |................|
-00000380 00 |.|
+00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 18 6f |*............ .o|
+00000280 77 a5 2b 27 2c 52 fc 6c 8a 34 41 1c a8 c6 4f 90 |w.+',R.l.4A...O.|
+00000290 a9 4b b7 e0 39 8b b1 f5 a6 15 4b 94 e8 2c 04 03 |.K..9.....K..,..|
+000002a0 00 8b 30 81 88 02 42 00 dc 3a 14 a2 38 32 c1 40 |..0...B..:..82.@|
+000002b0 98 83 17 94 e9 2a 0d 95 c3 59 d6 76 94 c2 3e a0 |.....*...Y.v..>.|
+000002c0 f7 e0 5d 64 47 5a d1 d9 ed d2 1c 6b 13 3e e7 83 |..]dGZ.....k.>..|
+000002d0 6e bb 53 33 03 7d 69 c6 8f 9d 98 d7 96 9c 73 e3 |n.S3.}i.......s.|
+000002e0 12 bd 69 1f b1 d3 f4 25 d7 02 42 01 11 6d c8 53 |..i....%..B..m.S|
+000002f0 9b bf f4 db ff 8a 00 82 93 f7 b5 bf c9 bb cd ec |................|
+00000300 64 f8 d9 6d 36 0d f8 db ce 9d 65 a0 5e 5a e0 13 |d..m6.....e.^Z..|
+00000310 ec 08 73 2c 3f 8c c6 5b 08 cc 0f 4a 7d 6b 5e 89 |..s,?..[...J}k^.|
+00000320 bf 4a 4e db 51 5a 9f 51 3e 9d 9a c5 84 16 03 03 |.JN.QZ.Q>.......|
+00000330 00 2a 0d 00 00 26 03 01 02 40 00 1e 06 01 06 02 |.*...&...@......|
+00000340 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
+00000350 03 02 03 03 02 01 02 02 02 03 00 00 16 03 03 00 |................|
+00000360 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|
@@ -100,36 +99,34 @@
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 93 0f |.h.A.Vk.Z.......|
-00000260 00 00 8f 05 03 00 8b 30 81 88 02 42 00 8a 82 c2 |.......0...B....|
-00000270 c0 30 8c a1 12 c4 4a ed d1 00 3f 2d ee bd 8e 9c |.0....J...?-....|
-00000280 a5 a0 d9 6f 44 27 49 60 e9 75 01 ee b4 0d 87 25 |...oD'I`.u.....%|
-00000290 2a 8d 67 f1 e3 d9 49 6f a0 34 90 76 93 52 f9 17 |*.g...Io.4.v.R..|
-000002a0 fb 1b cc d0 5a f4 50 37 9c 4c 44 b6 61 5f 02 42 |....Z.P7.LD.a_.B|
-000002b0 01 ad 85 38 e9 3a 69 35 ea 74 76 2c 09 6b ab d4 |...8.:i5.tv,.k..|
-000002c0 e0 dc d1 d5 03 41 22 8e 8b 53 98 b7 f1 b6 e9 29 |.....A"..S.....)|
-000002d0 d2 57 34 dc e0 b6 71 77 79 bd 57 61 7c 30 77 00 |.W4...qwy.Wa|0w.|
-000002e0 7a 42 2d 1f ed e8 14 da 16 33 c6 31 e4 3d 53 3a |zB-......3.1.=S:|
-000002f0 9a 37 14 03 03 00 01 01 16 03 03 00 40 00 00 00 |.7..........@...|
-00000300 00 00 00 00 00 00 00 00 00 00 00 00 00 d4 fe c1 |................|
-00000310 a6 fb 21 78 21 80 af 0d da a1 80 68 e2 9c ec 0b |..!x!......h....|
-00000320 57 8c 2a 7e f1 11 3b 52 ea 17 00 d1 d4 14 78 c5 |W.*~..;R......x.|
-00000330 81 39 12 ad 30 98 93 1b 29 77 45 7d 00 |.9..0...)wE}.|
+00000210 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b|
+00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......|
+00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 93 0f 00 |...._X.;t.......|
+00000240 00 8f 05 03 00 8b 30 81 88 02 42 01 32 6d 32 38 |......0...B.2m28|
+00000250 d6 bd 1b b6 c5 80 f2 ea 60 b8 bf 3f b6 76 68 1b |........`..?.vh.|
+00000260 66 fb 5d 69 0b 25 09 7f 2d 73 ad 7e cd 98 cb b5 |f.]i.%..-s.~....|
+00000270 93 4e 4f 1c 4e 3f a1 39 cf a0 70 a6 3d 29 36 27 |.NO.N?.9..p.=)6'|
+00000280 51 e0 55 95 11 df 00 88 6c 38 d6 de 36 02 42 01 |Q.U.....l8..6.B.|
+00000290 67 50 81 90 a7 ae b5 e2 34 75 81 41 c2 71 8d 0c |gP......4u.A.q..|
+000002a0 9a 20 e7 33 af 0e 61 48 85 51 a1 f7 90 17 d1 ad |. .3..aH.Q......|
+000002b0 b3 e1 cf 3e 12 fc ce 39 16 a8 78 3b 69 0d 79 76 |...>...9..x;i.yv|
+000002c0 03 17 75 c2 a0 63 5e dc 0a a7 c9 aa 15 2a 83 65 |..u..c^......*.e|
+000002d0 df 14 03 03 00 01 01 16 03 03 00 40 00 00 00 00 |...........@....|
+000002e0 00 00 00 00 00 00 00 00 00 00 00 00 27 da 48 f6 |............'.H.|
+000002f0 d3 00 98 b9 a6 b7 41 0b eb e6 d1 d7 82 9a 0c 59 |......A........Y|
+00000300 8a 42 1c 99 59 af da a7 5b 88 ab b6 7d 01 bc 0f |.B..Y...[...}...|
+00000310 45 08 c4 05 0d 2a 4a 83 bf eb b1 b6 |E....*J.....|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 40 f7 0a 50 d0 87 |..........@..P..|
-00000010 fb f9 be b0 6b 8d 9b a5 8b d2 56 27 67 7d 3c 51 |....k.....V'g}<Q|
-00000020 af 53 8c 7d 61 9f 12 a5 54 5d ec 56 36 31 01 73 |.S.}a...T].V61.s|
-00000030 37 cb 5f ff 36 3c 1c 4a e3 db ec 99 bc 86 15 e4 |7._.6<.J........|
-00000040 cd 5d 87 bd d7 80 c7 b1 fe 42 9f |.].......B.|
+00000000 14 03 03 00 01 01 16 03 03 00 40 73 7c e6 43 b9 |..........@s|.C.|
+00000010 47 85 1c 50 f1 cb a1 29 79 02 dd 13 85 2a d9 a2 |G..P...)y....*..|
+00000020 07 50 e4 80 c4 7e 66 ee f2 1a 21 1d cd e4 ff 4a |.P...~f...!....J|
+00000030 a4 61 9d b4 a1 26 88 72 20 2b 06 77 c3 8b 3b 21 |.a...&.r +.w..;!|
+00000040 53 33 02 3d a2 06 77 3b a5 a6 0b |S3.=..w;...|
>>> 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 ef 81 cf 63 f1 b5 6b b2 30 6f 00 |........c..k.0o.|
-00000020 0e c0 0c 5d d4 85 76 d2 30 db 6b 14 06 e4 75 0b |...]..v.0.k...u.|
-00000030 cf fc 72 aa 64 15 03 03 00 30 00 00 00 00 00 00 |..r.d....0......|
-00000040 00 00 00 00 00 00 00 00 00 00 ef 28 8a e7 15 51 |...........(...Q|
-00000050 0d 0d 27 4f 36 35 f6 43 28 d2 16 dc a3 35 33 3e |..'O65.C(....53>|
-00000060 be 80 db 31 a9 89 3d 17 c2 58 |...1..=..X|
+00000010 00 00 00 00 00 1a 45 68 03 9b f0 42 e4 21 5e d8 |......Eh...B.!^.|
+00000020 98 d6 46 67 2b 93 80 92 1f 91 60 a3 05 04 1c a0 |..Fg+.....`.....|
+00000030 1b a9 ce 45 03 15 03 03 00 30 00 00 00 00 00 00 |...E.....0......|
+00000040 00 00 00 00 00 00 00 00 00 00 6b 23 42 c8 5c 29 |..........k#B.\)|
+00000050 f5 1f 7c d5 80 c4 9f 6f 12 77 95 71 8f 82 f9 63 |..|....o.w.q...c|
+00000060 07 2c 6d ed 6d c6 4f 90 50 a3 |.,m.m.O.P.|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA
index 53f2f8645ee..fb6c940a5f9 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA
@@ -1,62 +1,74 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 51 02 00 00 4d 03 03 e8 b5 19 bd df |....Q...M.......|
-00000010 e5 18 78 4b 01 f1 3f 7f ab 91 05 78 98 77 50 bf |..xK..?....x.wP.|
-00000020 60 f5 a4 76 7b 3c 40 9f 54 56 68 20 a1 99 57 a7 |`..v{<@.TVh ..W.|
-00000030 a8 46 ca 26 22 d8 bb 8d 93 12 48 ff be 8e d3 d4 |.F.&".....H.....|
-00000040 e0 fd cd ce f5 d9 a9 2e fe d4 cd 85 00 05 00 00 |................|
-00000050 05 ff 01 00 01 00 16 03 03 02 71 0b 00 02 6d 00 |..........q...m.|
-00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002d0 2e 0d 00 00 26 03 01 02 40 00 1e 06 01 06 02 06 |....&...@.......|
-000002e0 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 |................|
-000002f0 02 03 03 02 01 02 02 02 03 00 00 0e 00 00 00 |...............|
+00000000 16 03 03 00 59 02 00 00 55 03 03 2e d2 1c 3f f8 |....Y...U.....?.|
+00000010 3a dc be 78 0b fa 03 00 e0 9a b9 62 34 45 f8 34 |:..x.......b4E.4|
+00000020 54 21 4c c0 76 a6 e1 5a a1 67 c2 20 1b 98 25 34 |T!L.v..Z.g. ..%4|
+00000030 79 ac 59 b5 39 c8 93 10 a9 ea 9d 25 3d 2c d8 69 |y.Y.9......%=,.i|
+00000040 da d8 33 75 ef 44 4c 76 92 2b 3b b4 c0 2f 00 00 |..3u.DLv.+;../..|
+00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
+00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
+000002c0 ac 0c 00 00 a8 03 00 1d 20 06 be 1b 0b d8 95 59 |........ ......Y|
+000002d0 b2 13 1c 4a 06 b8 36 3e 4f 98 3f 81 11 3e 7d 21 |...J..6>O.?..>}!|
+000002e0 fa d9 f0 db 1b 41 4a d0 14 04 01 00 80 ca 57 f5 |.....AJ.......W.|
+000002f0 e7 b6 72 7e 3f b0 67 f2 a2 d0 84 d5 7f 7d 83 ff |..r~?.g......}..|
+00000300 92 73 4f 19 f7 94 b6 d7 95 f4 1b 56 2a fc fa 24 |.sO........V*..$|
+00000310 3e fe 00 65 52 76 c8 30 8a bf ae fe b5 c9 f2 47 |>..eRv.0.......G|
+00000320 0a 71 ad c1 6a 61 8c b5 ab 59 09 12 92 b2 b4 ad |.q..ja...Y......|
+00000330 cb cc ac c4 30 e9 a4 8a 82 4e 2e d6 1d 16 46 dd |....0....N....F.|
+00000340 60 37 50 b8 ae 83 c1 e6 1d ba 8c c7 18 f7 5e d7 |`7P...........^.|
+00000350 23 e5 8a 14 ba e4 8e a1 77 8a b6 41 03 61 8a 25 |#.......w..A.a.%|
+00000360 8a 27 f8 cb 2e 4a e0 07 aa bf 03 32 98 16 03 03 |.'...J.....2....|
+00000370 00 2a 0d 00 00 26 03 01 02 40 00 1e 06 01 06 02 |.*...&...@......|
+00000380 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
+00000390 03 02 03 03 02 01 02 02 02 03 00 00 16 03 03 00 |................|
+000003a0 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|
@@ -91,33 +103,30 @@
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 73 bd 73 65 92 86 |..........s.se..|
-00000220 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 87 |#A.y......M.....|
-00000230 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 53 |.2R.k..-.......S|
-00000240 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 fe |.m.....o..#87...|
-00000250 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 65 |...U...`}p&..T.e|
-00000260 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 ff |...S_..:.3{.L...|
-00000270 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b 52 |Z.6*G.....1x..kR|
-00000280 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 4d |..........+.8..M|
-00000290 e5 78 13 4e a4 38 46 42 dc 16 16 03 03 00 92 0f |.x.N.8FB........|
-000002a0 00 00 8e 05 03 00 8a 30 81 87 02 42 01 4c f6 31 |.......0...B.L.1|
-000002b0 4f ec 64 bb ce d0 96 4d 66 f3 8d 64 78 c9 2d 47 |O.d....Mf..dx.-G|
-000002c0 39 02 88 31 49 84 7f cc a8 af c1 17 35 fb 46 b1 |9..1I.......5.F.|
-000002d0 dc 07 58 71 13 6b 8e 71 2b 94 fd 41 7c 26 45 39 |..Xq.k.q+..A|&E9|
-000002e0 28 b1 aa f7 5b 89 04 de 84 d1 b5 d9 9f f3 02 41 |(...[..........A|
-000002f0 4e f6 2a ed 39 ee 63 68 da f5 ae 1b 4d f5 01 0f |N.*.9.ch....M...|
-00000300 bc f7 05 d2 96 42 67 e3 8f ff 27 d5 bf c4 53 bf |.....Bg...'...S.|
-00000310 8a d7 46 58 05 54 94 d8 73 a9 d9 38 40 5f cb 8c |..FX.T..s..8@_..|
-00000320 c7 d1 94 56 2a e1 61 32 29 f7 c9 c1 e8 95 30 e3 |...V*.a2).....0.|
-00000330 33 14 03 03 00 01 01 16 03 03 00 24 b1 86 d2 50 |3..........$...P|
-00000340 fc ea 68 b1 d9 3d b7 2c fd 2c 87 f0 d4 44 2b 22 |..h..=.,.,...D+"|
-00000350 b8 47 74 77 46 14 6d 18 b3 08 9c 3a d4 a1 ba cb |.GtwF.m....:....|
+00000210 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd 62 |...%...! /.}.G.b|
+00000220 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 cf |C.(.._.).0......|
+00000230 c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 92 0f 00 |...._X.;t.......|
+00000240 00 8e 05 03 00 8a 30 81 87 02 41 19 c6 1e f0 f4 |......0...A.....|
+00000250 ca 79 d7 8c 36 0f 56 9a 9d 07 55 31 fe 63 f1 ec |.y..6.V...U1.c..|
+00000260 20 80 6f 12 ed 7f bb c0 87 0a 0d 68 81 89 bd 8b | .o........h....|
+00000270 19 04 5e c0 19 8a d2 0f 6d 71 83 59 ee a7 be be |..^.....mq.Y....|
+00000280 1d bb 2f 12 53 9b ca 58 0e a6 8d ae 02 42 00 d0 |../.S..X.....B..|
+00000290 4c 69 75 30 86 d1 da 73 1b 8e 3e e1 82 9b f3 58 |Liu0...s..>....X|
+000002a0 8f 6d 0a 10 86 72 5f 90 17 d1 ac 34 8a b5 60 d0 |.m...r_....4..`.|
+000002b0 b8 54 0f 05 7f cd 6a c0 62 b5 04 d9 3a 98 95 b6 |.T....j.b...:...|
+000002c0 b3 00 1d 94 6e 79 35 57 d2 78 a4 7a 4a 45 89 d1 |....ny5W.x.zJE..|
+000002d0 14 03 03 00 01 01 16 03 03 00 28 00 00 00 00 00 |..........(.....|
+000002e0 00 00 00 cf b5 3c cf 0a b7 6b 51 cb fe 06 4c df |.....<...kQ...L.|
+000002f0 2c 79 a6 5e a8 75 8b 4c 44 7b ae ff 64 d7 67 dc |,y.^.u.LD{..d.g.|
+00000300 af ef 54 |..T|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 70 c7 ee d4 d3 |..........$p....|
-00000010 d3 ad dc 5a d1 a3 01 89 4d ae 0f b9 7b 97 91 4a |...Z....M...{..J|
-00000020 c0 5b e2 94 ef 5f 2f e0 90 1a 18 8a e8 50 9d |.[..._/......P.|
+00000000 14 03 03 00 01 01 16 03 03 00 28 1c 12 5e 29 ba |..........(..^).|
+00000010 34 b3 d8 ae f7 2a 83 0d 3e 21 ec 91 c9 fa 7f d1 |4....*..>!......|
+00000020 42 7e 8d d9 e5 ed 4e f9 ae 95 66 27 85 cc 44 2d |B~....N...f'..D-|
+00000030 cd a3 26 |..&|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1a e8 e8 00 30 71 09 61 65 55 90 c8 |........0q.aeU..|
-00000010 d6 fd 8d 5d a9 fb e6 2b d4 45 a9 8c ea 2f 0b 15 |...]...+.E.../..|
-00000020 03 03 00 16 f2 d3 36 ce 26 42 59 1b d7 15 c5 c4 |......6.&BY.....|
-00000030 8b 0b 06 0a d0 fd 78 62 3d 39 |......xb=9|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 8b 4c 36 |..............L6|
+00000010 6f b8 69 16 0a 40 67 05 5e a8 e6 48 cc ad 7b 29 |o.i..@g.^..H..{)|
+00000020 95 3d 02 15 03 03 00 1a 00 00 00 00 00 00 00 02 |.=..............|
+00000030 58 e3 b5 8e 30 e7 5d 02 cd e5 c0 11 95 3a ef a9 |X...0.]......:..|
+00000040 d7 86 |..|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384
index 9ba51f5ac62..17fc8f8e118 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384
@@ -1,134 +1,130 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 f5 6d a6 9a 3d |....Y...U...m..=|
-00000010 b4 32 c7 59 b9 f7 09 bb 56 7e 06 26 02 ac eb dd |.2.Y....V~.&....|
-00000020 78 91 e4 cd f9 f4 e7 98 7f 13 f0 20 6d d5 42 4a |x.......... m.BJ|
-00000030 85 ac 86 9a a6 78 6d 5c d7 ef 9d 16 dc ff 5a 41 |.....xm\......ZA|
-00000040 91 5a 54 ff ba f6 90 f4 2a 4f fd 37 c0 30 00 00 |.ZT.....*O.7.0..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 31 df 35 e4 36 |....Y...U..1.5.6|
+00000010 c5 f1 b4 9f e7 5d fa e1 e0 23 04 54 bd 2b fb ab |.....]...#.T.+..|
+00000020 a2 37 8f 35 eb 79 47 e6 f8 2b cb 20 ba d8 db 26 |.7.5.yG..+. ...&|
+00000030 ce 6b 4a e9 1e 0c 46 9f 4d 85 cb d7 b0 e2 3d 20 |.kJ...F.M.....= |
+00000040 58 43 83 37 e1 53 ac 3b d9 b3 fd 0a c0 30 00 00 |XC.7.S.;.....0..|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
-00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
-00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
-000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
-000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
-000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
-000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
-000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
-000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
-00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
-00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
-00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
-00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
-00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
-00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
-00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
-00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
-00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
-00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
-000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
-000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
-000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
-000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
-000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
-000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
-00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
-00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
-00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
-00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
-00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
-00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
-00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
-00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
-00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
-00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
-000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
-000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
-000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
-000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............|
-000002e0 41 04 2a 2a b7 63 a8 8e 34 67 32 18 57 6e fe 2a |A.**.c..4g2.Wn.*|
-000002f0 51 41 41 5f 65 a3 a7 e9 d6 0b 42 7f 77 fb 40 09 |QAA_e.....B.w.@.|
-00000300 c8 7a a2 9b fd 5f 6e 2b ce 85 f6 24 c2 8d e8 bb |.z..._n+...$....|
-00000310 69 3e dc 51 15 6f a8 db a4 fb 11 10 70 04 82 6a |i>.Q.o......p..j|
-00000320 7b 81 04 01 00 80 7a a3 c9 1b e6 02 33 39 55 36 |{.....z.....39U6|
-00000330 dc f9 2d f7 00 5b 8d f4 de 7a f7 3b 1b 4c 9a 27 |..-..[...z.;.L.'|
-00000340 f6 db 3c d1 6b f8 d6 7a 20 53 33 5f 88 9f f6 73 |..<.k..z S3_...s|
-00000350 90 2f 35 9e f6 05 b5 80 96 4f c8 85 e6 72 95 ba |./5......O...r..|
-00000360 3b 42 43 94 c3 0b db 91 ff 6b 24 c6 b1 78 de 18 |;BC......k$..x..|
-00000370 9f d5 3b 33 53 22 45 bf cb b2 d2 77 ce 03 56 7b |..;3S"E....w..V{|
-00000380 b7 56 b6 ec 04 64 62 04 f7 f8 52 1a 47 49 01 71 |.V...db...R.GI.q|
-00000390 29 9e ee 68 1f e9 c6 36 fb 77 4c 9a 14 90 e1 70 |)..h...6.wL....p|
-000003a0 7d 7e 77 92 a6 18 16 03 03 00 2e 0d 00 00 26 03 |}~w...........&.|
-000003b0 01 02 40 00 1e 06 01 06 02 06 03 05 01 05 02 05 |..@.............|
-000003c0 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 02 |................|
-000003d0 02 02 03 00 00 0e 00 00 00 |.........|
+00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
+000002c0 ac 0c 00 00 a8 03 00 1d 20 9a 18 f9 2e 33 f7 bb |........ ....3..|
+000002d0 ca 60 0b 51 ad 5c 01 e2 61 82 0b 3f 09 8f 78 9d |.`.Q.\..a..?..x.|
+000002e0 3b 11 8b e0 4a 35 2e d5 54 04 01 00 80 90 94 0e |;...J5..T.......|
+000002f0 bf 3a b7 95 d3 58 cc 65 c3 79 5e 1e bb d9 21 56 |.:...X.e.y^...!V|
+00000300 06 93 6c 2b 6e 26 55 ee 26 c3 02 44 7e db 35 9b |..l+n&U.&..D~.5.|
+00000310 d4 d4 1a a0 65 35 41 a4 6c ce de 1f 94 ff b4 1b |....e5A.l.......|
+00000320 1e 9c 28 0b 4c 8d 55 d0 d8 be f1 df e0 d1 1a b5 |..(.L.U.........|
+00000330 c8 be 2c 5a 2c c3 3f ea 4f e6 d5 b4 6b e1 ff eb |..,Z,.?.O...k...|
+00000340 f3 f3 40 54 d5 62 1f a0 fc b2 34 66 ee c5 27 a6 |..@T.b....4f..'.|
+00000350 2b 2a b9 5d 3f 36 28 eb 39 99 25 e5 04 d2 18 13 |+*.]?6(.9.%.....|
+00000360 3c 23 93 d0 04 37 85 b0 4d 6e 9b 32 9a 16 03 03 |<#...7..Mn.2....|
+00000370 00 2a 0d 00 00 26 03 01 02 40 00 1e 06 01 06 02 |.*...&...@......|
+00000380 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
+00000390 03 02 03 03 02 01 02 02 02 03 00 00 16 03 03 00 |................|
+000003a0 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 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 05 01 00 80 45 11 dc 3c 2a fc 5f aa |........E..<*._.|
-00000260 60 09 59 47 45 cc a7 74 e3 9d 0c c3 a4 08 b0 2a |`.YGE..t.......*|
-00000270 44 47 cd 66 ed 94 54 8f d7 74 fd 47 a3 90 56 69 |DG.f..T..t.G..Vi|
-00000280 5a b6 c5 b0 bd c2 16 a2 1e af 58 37 88 cb d1 4b |Z.........X7...K|
-00000290 5c ee e6 0f 16 9b e0 d7 43 b3 e6 0a b2 90 fa 21 |\.......C......!|
-000002a0 78 95 3e 7f fc c1 b3 df a1 bf fc eb bc e8 37 63 |x.>...........7c|
-000002b0 87 33 3e c3 9a e4 6c 0f 3d 0d 9f e8 db 2d 82 ad |.3>...l.=....-..|
-000002c0 3c 6d f7 4a 5e 81 21 4f 19 0e 60 2d ef c1 40 8d |<m.J^.!O..`-..@.|
-000002d0 cb 97 4f 08 1c c0 66 e7 14 03 03 00 01 01 16 03 |..O...f.........|
-000002e0 03 00 28 00 00 00 00 00 00 00 00 8c ce 5e 94 90 |..(..........^..|
-000002f0 22 2c 8d 64 be 29 99 62 1f 95 6e 3b 51 22 9c eb |",.d.).b..n;Q"..|
-00000300 f3 0f 24 b8 a5 84 58 70 82 71 a1 |..$...Xp.q.|
+00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0|
+00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.|
+00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.|
+00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1|
+00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C|
+00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523|
+00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231|
+00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac|
+00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.|
+00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....|
+000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x|
+000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.|
+000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4|
+000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..|
+000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#|
+000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....|
+00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......|
+00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..|
+00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U|
+00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U|
+00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......|
+00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.|
+00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0|
+00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........|
+00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..|
+00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]|
+000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A|
+000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...|
+000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...|
+000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......|
+000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{|
+000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....|
+00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.|
+00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...|
+00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....|
+00000230 88 0f 00 00 84 05 01 00 80 ad f7 ff a0 cb d0 6e |...............n|
+00000240 8f 19 0c 40 2a 1f bb dd 11 52 81 84 f1 7b 3f cf |...@*....R...{?.|
+00000250 75 72 83 a4 4c 0a 9c 70 95 98 d5 51 a2 28 0c 8c |ur..L..p...Q.(..|
+00000260 20 08 d7 2a a5 3e 0c cf 6c a2 1d 32 bd cc a1 b4 | ..*.>..l..2....|
+00000270 61 e0 6d 9a 61 16 03 5c 7a b8 fa 15 ea cd e4 de |a.m.a..\z.......|
+00000280 d6 16 93 b2 e0 d2 55 b9 03 e0 67 04 27 64 8c e2 |......U...g.'d..|
+00000290 01 ee 8f f7 59 3e 12 16 51 f2 07 20 fe 03 e2 3e |....Y>..Q.. ...>|
+000002a0 09 1f 96 24 c5 73 0e 69 ac 57 ff 43 2b 6a c6 20 |...$.s.i.W.C+j. |
+000002b0 2f e4 ef 7e bc b3 38 57 06 14 03 03 00 01 01 16 |/..~..8W........|
+000002c0 03 03 00 28 00 00 00 00 00 00 00 00 fd 71 f5 ca |...(.........q..|
+000002d0 91 26 67 54 a5 e6 f3 06 c8 40 24 9d a9 bd b1 9a |.&gT.....@$.....|
+000002e0 63 c4 c2 53 56 ba af c0 16 bc 06 5c |c..SV......\|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 b1 23 11 48 69 |..........(.#.Hi|
-00000010 52 44 34 f1 9a 69 2b 79 fb 68 b4 53 d5 d7 08 08 |RD4..i+y.h.S....|
-00000020 34 95 5f 56 b2 57 eb 91 31 6c 32 25 b5 68 8a 8e |4._V.W..1l2%.h..|
-00000030 f1 68 6e |.hn|
+00000000 14 03 03 00 01 01 16 03 03 00 28 92 8f bd c5 97 |..........(.....|
+00000010 94 76 70 f4 0a f9 9a 79 69 31 27 0e c0 c5 0b 3c |.vp....yi1'....<|
+00000020 9f 4f c2 2f cb 6c 56 62 80 3b e5 72 6a 05 9e 4b |.O./.lVb.;.rj..K|
+00000030 34 b9 66 |4.f|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 03 ab 9e |................|
-00000010 f0 a6 6c f1 ea 23 20 63 42 a3 9d c6 5d 41 96 c1 |..l..# cB...]A..|
-00000020 44 b2 8b 15 03 03 00 1a 00 00 00 00 00 00 00 02 |D...............|
-00000030 e9 73 41 50 28 b0 d3 00 46 81 d6 c9 1a ca ab cd |.sAP(...F.......|
-00000040 44 9b |D.|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 43 fb 43 |.............C.C|
+00000010 3d 96 63 dd 25 94 9d 7a fb 9e 15 6f 62 5e ed 34 |=.c.%..z...ob^.4|
+00000020 19 89 b8 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................|
+00000030 53 c2 2d 6c b7 91 6c 62 84 09 a2 1c 9b 3d 9e 89 |S.-l..lb.....=..|
+00000040 6a 3d |j=|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA
index 4fa5e20e93a..1ff91986d28 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA
@@ -1,19 +1,20 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 2a 01 f8 3e d1 |....Y...U..*..>.|
-00000010 52 41 2e 9a 8d 56 ff 52 3d 6a fe 65 ab 91 bb b7 |RA...V.R=j.e....|
-00000020 82 be f1 60 40 3b 80 a1 f8 dc 95 20 48 87 41 46 |...`@;..... H.AF|
-00000030 6a d2 f3 b8 d8 68 20 40 45 b7 fe 19 21 bc 84 00 |j....h @E...!...|
-00000040 5d 40 40 21 58 3e 7d fb a7 e3 30 37 c0 09 00 00 |]@@!X>}...07....|
+00000000 16 03 03 00 59 02 00 00 55 03 03 84 4b ff a4 2a |....Y...U...K..*|
+00000010 a4 76 c0 26 f6 05 72 94 01 15 44 f2 c6 7d b0 4b |.v.&..r...D..}.K|
+00000020 1b fa da 51 54 45 78 66 e6 0a dd 20 17 df d2 0c |...QTExf... ....|
+00000030 2f d6 55 b9 ae 82 ce 2f 2f 07 67 54 5e 02 bd 2f |/.U....//.gT^../|
+00000040 48 f6 fb 3d 9c fa 4f a8 66 15 08 da c0 09 00 00 |H..=..O.f.......|
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....|
@@ -48,87 +49,83 @@
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 00 |*............A..|
-00000280 9e 90 3a 3d 00 37 0a c0 43 92 6e bf b4 23 d9 64 |..:=.7..C.n..#.d|
-00000290 99 d2 90 9e eb 88 b6 d6 6f 15 4a 22 72 f0 bf 5e |........o.J"r..^|
-000002a0 72 80 93 90 aa f1 d1 9c 45 c6 6e 3a f8 a9 6f fe |r.......E.n:..o.|
-000002b0 fb 24 dc b1 4d 52 39 91 f5 48 36 06 f6 15 0e 04 |.$..MR9..H6.....|
-000002c0 03 00 8b 30 81 88 02 42 00 a9 54 74 a7 a8 d0 04 |...0...B..Tt....|
-000002d0 ae ef e4 64 38 74 21 e6 18 f0 79 b2 d7 7e 7b 0e |...d8t!...y..~{.|
-000002e0 f6 74 75 52 f0 b8 15 3c 3d 15 52 75 9f 60 03 63 |.tuR...<=.Ru.`.c|
-000002f0 15 b8 1e b8 0e 5c 58 c7 e7 2f 6d 76 c7 c8 42 7a |.....\X../mv..Bz|
-00000300 df 15 26 4b dc 9c 3b 4d b3 b6 02 42 00 a5 fd bf |..&K..;M...B....|
-00000310 a9 5d fc 87 42 24 f9 0b 7a 17 97 7c ee 45 1c 29 |.]..B$..z..|.E.)|
-00000320 3a 07 5f df 4d f2 d3 cb fc a6 fd 84 34 2c 40 84 |:._.M.......4,@.|
-00000330 06 76 bf 43 35 d2 f6 9a 7c d6 1b 5e d8 fd 08 35 |.v.C5...|..^...5|
-00000340 1b 90 0e 24 a7 48 9d 71 ab 4a 11 92 d3 6e 16 03 |...$.H.q.J...n..|
-00000350 03 00 2e 0d 00 00 26 03 01 02 40 00 1e 06 01 06 |......&...@.....|
-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 00 00 0e 00 00 |................|
-00000380 00 |.|
+00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 5d 4e |*............ ]N|
+00000280 0c 9e ad 7b f1 48 0c db 03 96 26 2e 16 87 2c e2 |...{.H....&...,.|
+00000290 ce a2 47 5a 57 30 e8 e1 7e b2 53 5b c6 7b 04 03 |..GZW0..~.S[.{..|
+000002a0 00 8b 30 81 88 02 42 00 e8 8e 68 a8 e3 b5 b4 fe |..0...B...h.....|
+000002b0 b9 91 aa 4f 96 3d 97 8d b2 ef 23 a4 3d 16 db 2b |...O.=....#.=..+|
+000002c0 50 6d 52 cd a5 e7 79 ae 65 10 d6 36 e0 ba c3 6b |PmR...y.e..6...k|
+000002d0 53 61 14 bb 05 47 5a df 26 2f cb 3a 95 c6 6b dc |Sa...GZ.&/.:..k.|
+000002e0 88 fd 2e 22 b5 ef ff 31 0e 02 42 01 be ce 6e 53 |..."...1..B...nS|
+000002f0 42 43 1c 1c d8 83 7f 45 c4 16 ee d2 7b 66 a0 f4 |BC.....E....{f..|
+00000300 f3 14 da 5c 14 e8 fc bc 86 7d 18 43 b9 7b 90 8c |...\.....}.C.{..|
+00000310 af f1 05 95 c6 53 0b 0b 0d 10 a1 e9 bb 89 35 c2 |.....S........5.|
+00000320 b2 e1 d7 dd 99 7c bf 85 19 3c 4e 8e 8f 16 03 03 |.....|...<N.....|
+00000330 00 2a 0d 00 00 26 03 01 02 40 00 1e 06 01 06 02 |.*...&...@......|
+00000340 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
+00000350 03 02 03 03 02 01 02 02 02 03 00 00 16 03 03 00 |................|
+00000360 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 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 05 01 00 80 20 ef 4b 1c d7 67 37 6e |........ .K..g7n|
-00000260 24 12 9e e9 59 b1 6d da e5 3e 6b 11 03 f4 96 e4 |$...Y.m..>k.....|
-00000270 2e fb 03 e1 13 af 73 4d 15 11 c1 80 e2 ed 11 c6 |......sM........|
-00000280 73 6a 96 ce d1 26 e4 bc fe 71 c9 48 32 fd d8 70 |sj...&...q.H2..p|
-00000290 01 9d 18 7b ed a3 bd 6a 68 df 45 a0 d5 77 79 d2 |...{...jh.E..wy.|
-000002a0 5b e2 8c 96 68 95 46 8d 7d e6 b6 26 fa e1 c4 05 |[...h.F.}..&....|
-000002b0 4c d1 39 4e 35 e3 0c 1b 26 37 2e 0b 9b 0b cf f7 |L.9N5...&7......|
-000002c0 25 c3 da 27 18 70 83 18 49 ff ee ba e3 f8 70 75 |%..'.p..I.....pu|
-000002d0 e8 9b 2d 89 d7 b2 00 a5 14 03 03 00 01 01 16 03 |..-.............|
-000002e0 03 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 |..@.............|
-000002f0 00 00 00 d3 33 79 85 64 14 07 a6 93 74 f8 f8 55 |....3y.d....t..U|
-00000300 0f fb fc 8e 1b 4c 38 21 b6 61 c5 4b b2 d4 17 b2 |.....L8!.a.K....|
-00000310 c4 be a6 4b d6 3f a3 5f 3c ff 5f 1d 93 a2 c4 82 |...K.?._<._.....|
-00000320 96 90 eb |...|
+00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0|
+00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.|
+00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.|
+00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1|
+00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C|
+00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523|
+00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231|
+00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac|
+00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.|
+00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....|
+000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x|
+000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.|
+000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4|
+000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..|
+000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#|
+000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....|
+00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......|
+00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..|
+00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U|
+00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U|
+00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......|
+00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.|
+00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0|
+00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........|
+00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..|
+00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]|
+000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A|
+000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...|
+000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...|
+000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......|
+000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{|
+000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....|
+00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.|
+00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...|
+00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....|
+00000230 88 0f 00 00 84 05 01 00 80 98 58 a8 77 3d db 0b |..........X.w=..|
+00000240 04 36 78 51 8b 23 48 fc 70 2b c9 94 1f ee 32 ae |.6xQ.#H.p+....2.|
+00000250 41 c0 42 20 19 51 67 e7 fa c0 fd 15 a1 5f 55 4f |A.B .Qg......_UO|
+00000260 aa be 29 77 f5 47 71 b9 6c 51 89 18 df 25 98 fd |..)w.Gq.lQ...%..|
+00000270 c8 6e ae e3 fd 99 63 ca 2c d2 fb ca bc 57 b7 7f |.n....c.,....W..|
+00000280 a2 90 a6 6f b7 2e b7 2a 52 29 e6 75 57 86 cc b1 |...o...*R).uW...|
+00000290 d8 6c f3 4e 49 ab 4b 66 0a 72 aa ec c2 f7 6e 57 |.l.NI.Kf.r....nW|
+000002a0 15 26 79 1a a4 24 c2 ba 76 9e dd b9 f9 d4 da 1b |.&y..$..v.......|
+000002b0 c9 29 66 eb 64 1b 68 66 66 14 03 03 00 01 01 16 |.)f.d.hff.......|
+000002c0 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 00 |...@............|
+000002d0 00 00 00 00 70 2b 69 27 05 9a 96 e6 e8 52 ea 0f |....p+i'.....R..|
+000002e0 3a d6 40 b5 e2 89 5b bf aa 95 6c c1 7d 53 09 89 |:.@...[...l.}S..|
+000002f0 23 38 6b 83 85 84 fa f4 2e fb cd b3 57 4e 79 8a |#8k.........WNy.|
+00000300 92 74 03 22 |.t."|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 40 80 b0 df ff b3 |..........@.....|
-00000010 34 11 03 f5 2d fb c7 c2 38 15 df 41 97 55 0e 1d |4...-...8..A.U..|
-00000020 36 f7 a5 35 5b 63 d7 c5 a6 fd fc a1 91 32 9d cd |6..5[c.......2..|
-00000030 34 66 75 4c 5d 27 ee 89 ed d4 4a ec 67 b0 da e7 |4fuL]'....J.g...|
-00000040 f0 e7 36 eb db b9 22 97 74 30 cd |..6...".t0.|
+00000000 14 03 03 00 01 01 16 03 03 00 40 8f 91 f1 f5 6b |..........@....k|
+00000010 cc 52 9d db 35 1f db b4 64 fe 33 a5 83 08 24 2f |.R..5...d.3...$/|
+00000020 57 18 0e 60 4e 18 54 bb 80 31 37 fe 26 14 b8 c8 |W..`N.T..17.&...|
+00000030 dd c4 8c 07 42 0b 80 0b 41 82 40 f6 9b b8 60 4f |....B...A.@...`O|
+00000040 cb 7b 43 ea 1a 6e 31 8d 9f 82 f7 |.{C..n1....|
>>> 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 62 24 32 e9 40 38 c8 c3 dd 07 42 |.....b$2.@8....B|
-00000020 05 c8 7c 3d d1 27 68 00 e4 91 6c 2d 08 c1 a1 b6 |..|=.'h...l-....|
-00000030 8a 89 3d 1d c1 15 03 03 00 30 00 00 00 00 00 00 |..=......0......|
-00000040 00 00 00 00 00 00 00 00 00 00 d1 c8 bc cb cb a5 |................|
-00000050 24 1e ad c5 bf 23 92 4b 81 a6 c0 77 19 e0 46 30 |$....#.K...w..F0|
-00000060 48 51 0c cc 39 cd 4b 8d e5 a7 |HQ..9.K...|
+00000010 00 00 00 00 00 70 e7 c8 03 9c e2 58 73 68 ab 9b |.....p.....Xsh..|
+00000020 5c bf 32 57 f8 f1 13 97 02 59 de 99 d3 3e 16 3d |\.2W.....Y...>.=|
+00000030 87 11 d4 b4 63 15 03 03 00 30 00 00 00 00 00 00 |....c....0......|
+00000040 00 00 00 00 00 00 00 00 00 00 9b 99 45 f3 0d f1 |............E...|
+00000050 c5 36 07 8c 81 94 b7 0a dc 7c ee 0c 22 1b 36 fd |.6.......|..".6.|
+00000060 d4 fc 7d f1 98 8b 87 be 5f c6 |..}....._.|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA
index a0a96400314..76f0c2511ba 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA
@@ -1,122 +1,130 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 51 02 00 00 4d 03 03 60 8e 1c c9 6d |....Q...M..`...m|
-00000010 de 9d 2a dc 6a a6 82 71 9a 3f 8f 5b 18 52 44 4e |..*.j..q.?.[.RDN|
-00000020 4d 72 0d e7 c8 a1 b0 81 64 8c 1f 20 06 a8 17 35 |Mr......d.. ...5|
-00000030 b8 0b 96 52 30 f7 b3 d4 2a 25 94 c0 ba a8 a2 f7 |...R0...*%......|
-00000040 86 5c 18 18 3c 68 3a 71 0f bc 3f 12 00 05 00 00 |.\..<h:q..?.....|
-00000050 05 ff 01 00 01 00 16 03 03 02 71 0b 00 02 6d 00 |..........q...m.|
-00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002d0 2e 0d 00 00 26 03 01 02 40 00 1e 06 01 06 02 06 |....&...@.......|
-000002e0 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 |................|
-000002f0 02 03 03 02 01 02 02 02 03 00 00 0e 00 00 00 |...............|
+00000000 16 03 03 00 59 02 00 00 55 03 03 92 93 45 4c f9 |....Y...U....EL.|
+00000010 93 bf ee 78 58 e0 42 b6 df 32 c2 63 6d ec 89 66 |...xX.B..2.cm..f|
+00000020 5a 11 7c 0d 31 2f b5 90 22 ab 3d 20 65 f3 40 c4 |Z.|.1/..".= e.@.|
+00000030 f8 31 fa 80 f3 fb a7 f6 9e dc 0c 94 67 48 d9 2b |.1..........gH.+|
+00000040 cb 94 82 5f 4e 8b 41 5e c6 63 27 da c0 2f 00 00 |..._N.A^.c'../..|
+00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
+00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
+000002c0 ac 0c 00 00 a8 03 00 1d 20 66 49 44 2b 04 fe f5 |........ fID+...|
+000002d0 41 68 60 09 81 0e 24 c4 46 68 33 87 41 dd 48 69 |Ah`...$.Fh3.A.Hi|
+000002e0 4c be c8 22 2d 4e ff 80 20 04 01 00 80 30 85 40 |L.."-N.. ....0.@|
+000002f0 30 56 d5 1d 41 14 9d e8 27 39 a2 18 d5 eb 92 27 |0V..A...'9.....'|
+00000300 63 4b 05 85 1a 9e 5f 60 2c 80 a3 20 9f 9c 57 29 |cK...._`,.. ..W)|
+00000310 ba 5f ac 0a aa 89 98 fc ca 8e 37 6b 44 bc 0f 33 |._........7kD..3|
+00000320 5d 47 91 46 55 d4 f9 4f 76 73 51 c4 f6 a9 90 e4 |]G.FU..OvsQ.....|
+00000330 95 10 92 94 f1 33 11 3d 83 0a eb 5d ff e6 9d 9c |.....3.=...]....|
+00000340 19 ec e1 65 11 ad d7 7b 6a a4 f9 d8 b6 0c 53 8a |...e...{j.....S.|
+00000350 16 d5 1f a7 0b 80 6f c5 d8 6a 57 11 2f b1 84 65 |......o..jW./..e|
+00000360 24 8a 02 de aa 10 40 bd 9b 68 a2 b7 b6 16 03 03 |$.....@..h......|
+00000370 00 2a 0d 00 00 26 03 01 02 40 00 1e 06 01 06 02 |.*...&...@......|
+00000380 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 |................|
+00000390 03 02 03 03 02 01 02 02 02 03 00 00 16 03 03 00 |................|
+000003a0 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 73 bd 73 65 92 |...........s.se.|
-00000210 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
-00000220 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
-00000230 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
-00000240 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
-00000250 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
-00000260 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
-00000270 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
-00000280 4d e5 78 13 4e a4 38 46 42 dc 16 16 03 03 00 88 |M.x.N.8FB.......|
-00000290 0f 00 00 84 05 01 00 80 21 58 47 70 c2 2e 1c 4a |........!XGp...J|
-000002a0 fa 97 b2 cf 8d f8 93 f4 b0 8c b3 e0 e7 33 a6 ea |.............3..|
-000002b0 d7 fe 8e 25 e7 f3 f5 a1 8d 09 b7 0b 01 ec a1 15 |...%............|
-000002c0 5b 67 06 53 2a 7d 31 e5 a8 16 bc e3 1d ed 5a 77 |[g.S*}1.......Zw|
-000002d0 0b 78 78 c5 fc c5 62 8e 41 49 d3 ea cd 69 10 3f |.xx...b.AI...i.?|
-000002e0 34 9e 86 df f9 9f f6 02 0c 29 c4 66 a0 45 cf 7b |4........).f.E.{|
-000002f0 ce 51 ec 0a 26 b4 9d 3d 9e 63 5d 40 1a e8 84 4e |.Q..&..=.c]@...N|
-00000300 24 f5 42 48 b5 3e f8 92 c4 f2 e6 5d f4 ad 67 01 |$.BH.>.....]..g.|
-00000310 f8 a7 a7 2b b5 fc be e8 14 03 03 00 01 01 16 03 |...+............|
-00000320 03 00 24 f0 ec 1d f5 39 1c d2 d2 c7 f4 1f 3b 0c |..$....9......;.|
-00000330 cd 25 e4 8e ed c4 bb 02 9d 38 e5 a7 91 e0 ea 00 |.%.......8......|
-00000340 73 a8 9a 63 c9 e7 7d |s..c..}|
+00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0|
+00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.|
+00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.|
+00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1|
+00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C|
+00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523|
+00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231|
+00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac|
+00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.|
+00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....|
+000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x|
+000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.|
+000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4|
+000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..|
+000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#|
+000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....|
+00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......|
+00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..|
+00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U|
+00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U|
+00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......|
+00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.|
+00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0|
+00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........|
+00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..|
+00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]|
+000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A|
+000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...|
+000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...|
+000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......|
+000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{|
+000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....|
+00000200 e5 35 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 |.5....%...! /.}.|
+00000210 47 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 |G.bC.(.._.).0...|
+00000220 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 16 03 03 00 |......._X.;t....|
+00000230 88 0f 00 00 84 05 01 00 80 05 9b 97 90 30 0b 21 |.............0.!|
+00000240 ed 52 16 19 e0 54 7d 59 42 17 94 81 9b 2c b6 5b |.R...T}YB....,.[|
+00000250 7f 7c 8e a5 bf 27 a9 25 14 74 f0 37 fa 6e 2b 84 |.|...'.%.t.7.n+.|
+00000260 80 a4 cd ae a6 8a 1b 62 2d 5e 03 ff 70 55 d7 99 |.......b-^..pU..|
+00000270 68 3c b3 0e 03 41 ae af c6 3e 09 d4 16 8e 06 71 |h<...A...>.....q|
+00000280 14 f8 90 97 cd f6 eb 7d 90 3c d1 f3 95 db 35 3c |.......}.<....5<|
+00000290 c9 7d dc 30 55 e1 a0 66 8e 26 20 4f 43 89 08 6f |.}.0U..f.& OC..o|
+000002a0 95 58 42 ae e8 6c b6 77 45 c6 8c c7 ad e5 ed ff |.XB..l.wE.......|
+000002b0 09 6f 2e 7e b0 e4 5c f2 db 14 03 03 00 01 01 16 |.o.~..\.........|
+000002c0 03 03 00 28 00 00 00 00 00 00 00 00 c0 2c cc 32 |...(.........,.2|
+000002d0 78 5e 6c 3e e9 a3 83 65 b4 bb 4e 79 b2 04 08 30 |x^l>...e..Ny...0|
+000002e0 09 e9 04 99 70 48 44 95 26 b0 37 c9 |....pHD.&.7.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 0b c5 7d ca a6 |..........$..}..|
-00000010 87 7f 50 7b 88 9c d9 8e ea 78 a0 40 6b 8e 92 0b |..P{.....x.@k...|
-00000020 78 88 97 46 ec 7c 20 5b 1f fc da 49 d8 6a be |x..F.| [...I.j.|
+00000000 14 03 03 00 01 01 16 03 03 00 28 5f 80 e2 f1 78 |..........(_...x|
+00000010 0f cb 58 5c 3c 50 4c 1e 33 8a 1f b7 89 92 37 11 |..X\<PL.3.....7.|
+00000020 a3 8a 76 39 4a 3d b0 1f a3 e9 ba 52 f8 2b e5 a3 |..v9J=.....R.+..|
+00000030 59 7c ac |Y|.|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1a 16 25 97 df 98 e4 d6 8e d1 2c 0c |......%.......,.|
-00000010 27 74 67 e5 b7 f1 c7 58 41 5f 04 f5 e4 74 dc 15 |'tg....XA_...t..|
-00000020 03 03 00 16 df 55 01 0d 53 5b b4 36 c7 88 8d b0 |.....U..S[.6....|
-00000030 22 53 ec 87 1b 07 c7 9d af 89 |"S........|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 75 dc 54 |.............u.T|
+00000010 d9 c5 b1 c2 c9 64 9a ea 20 e5 76 61 6c 05 af 33 |.....d.. .val..3|
+00000020 6b bc d7 15 03 03 00 1a 00 00 00 00 00 00 00 02 |k...............|
+00000030 24 6b 03 76 d3 da d0 ee a6 32 c3 58 a1 5e a5 21 |$k.v.....2.X.^.!|
+00000040 b8 3a |.:|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES
index c9b5351f45c..5d795e791f0 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES
@@ -1,19 +1,20 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 8a ae 27 5b 39 |....Y...U....'[9|
-00000010 8b c4 a6 d5 fa 9e 67 9e 6c fe 53 ed ab ec e0 04 |......g.l.S.....|
-00000020 8d 7c f8 1f d0 db 2e cb 22 4d a1 20 ee 80 5f fc |.|......"M. .._.|
-00000030 f8 77 8a 23 23 c5 95 81 7f a6 12 f5 e0 19 91 50 |.w.##..........P|
-00000040 da 75 42 c2 eb 45 bf e2 a5 54 ed 6e c0 09 00 00 |.uB..E...T.n....|
+00000000 16 03 03 00 59 02 00 00 55 03 03 c3 2f 08 30 ba |....Y...U.../.0.|
+00000010 5d 9e 55 ef 23 f9 8a 0d 2f b4 25 02 5f c0 d2 c2 |].U.#.../.%._...|
+00000020 50 7c da db a4 ee 7c 18 df af aa 20 f3 a5 02 de |P|....|.... ....|
+00000030 54 9f ce b9 6d 69 66 5d 57 76 ff 18 91 d3 93 ab |T...mif]Wv......|
+00000040 39 13 29 4c b9 a7 3c db 7f 4d 97 fc c0 09 00 00 |9.)L..<..M......|
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....|
@@ -48,43 +49,39 @@
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 03 00 d7 0c 00 00 d3 03 00 17 41 04 3e |*............A.>|
-00000280 e3 d6 d6 7b d7 ec 6f 4b 88 50 53 26 5a 2b a6 69 |...{..oK.PS&Z+.i|
-00000290 25 6f 30 a7 c3 a5 39 5c e2 ca b6 35 a5 30 35 9a |%o0...9\...5.05.|
-000002a0 35 8f e3 65 bd 4c 47 30 72 9a 4b 32 c4 6d 01 c9 |5..e.LG0r.K2.m..|
-000002b0 a5 91 d1 cd 0b 79 e2 04 0f a9 9c c2 72 cd 58 04 |.....y......r.X.|
-000002c0 03 00 8a 30 81 87 02 41 70 01 8c dd 0a 32 db e3 |...0...Ap....2..|
-000002d0 0b 04 9c d0 64 a1 08 06 b1 cf e3 66 79 1f c0 c1 |....d......fy...|
-000002e0 14 34 87 a6 e5 52 11 20 12 24 a5 b6 c2 50 63 86 |.4...R. .$...Pc.|
-000002f0 31 6a e3 85 7d 19 2d 3b 68 bf b7 64 20 37 c7 f9 |1j..}.-;h..d 7..|
-00000300 76 38 b5 32 84 0b f9 b6 71 02 42 01 89 e3 93 85 |v8.2....q.B.....|
-00000310 d6 16 8e 44 66 72 d6 9f b3 b1 e9 22 ad 2e f8 49 |...Dfr....."...I|
-00000320 41 8f 80 f9 0e d4 fd de 35 67 cf 09 ba 65 f7 a1 |A.......5g...e..|
-00000330 17 a8 c0 b5 a3 cc c0 17 83 af 68 92 5b 5c a9 ce |..........h.[\..|
-00000340 ce 11 92 93 fe 39 b9 80 19 20 f2 b6 3b 16 03 03 |.....9... ..;...|
-00000350 00 04 0e 00 00 00 |......|
+00000270 2a 16 03 03 00 b6 0c 00 00 b2 03 00 1d 20 46 07 |*............ F.|
+00000280 78 fd 3b 0c e0 2c 96 f8 44 b9 e9 06 e9 66 17 35 |x.;..,..D....f.5|
+00000290 c0 92 87 51 f6 e3 d7 f5 09 50 56 c6 e9 3b 04 03 |...Q.....PV..;..|
+000002a0 00 8a 30 81 87 02 41 5d 88 4b fe eb 45 ee 5e 9f |..0...A].K..E.^.|
+000002b0 ec 20 90 1f 41 aa 47 87 f7 ae 46 71 dc 55 8b 2c |. ..A.G...Fq.U.,|
+000002c0 ce 70 5f ad 3e fa 3c c3 cb 77 d2 69 67 25 27 08 |.p_.>.<..w.ig%'.|
+000002d0 23 de 52 3c 0e 6c ca 8f 86 8f 61 cd 5b cf d8 42 |#.R<.l....a.[..B|
+000002e0 aa 5a 95 aa 4b d4 d9 f3 02 42 01 81 78 53 9c bd |.Z..K....B..xS..|
+000002f0 af 7e d9 be 26 07 24 11 ca 4b 1d dd 2b 49 ec 35 |.~..&.$..K..+I.5|
+00000300 25 8d 58 87 ad 80 4f 90 c7 f8 a4 b9 c2 75 b5 12 |%.X...O......u..|
+00000310 a7 2c 49 82 76 e8 ce c4 a7 23 68 75 fc 88 82 13 |.,I.v....#hu....|
+00000320 27 55 a7 50 3c d6 d0 ae e3 88 94 b4 16 03 03 00 |'U.P<...........|
+00000330 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 39 19 e6 fb c7 28 b4 c9 f5 ba |......9....(....|
-00000070 a2 44 0a 74 70 18 86 1f 5f c2 3d 99 f5 d7 17 04 |.D.tp..._.=.....|
-00000080 88 07 a5 06 01 6a 2c 13 55 0b fc 82 75 b5 24 54 |.....j,.U...u.$T|
-00000090 a0 63 9e f0 ce 92 |.c....|
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........|
+00000040 00 00 00 00 00 04 f4 cc a8 9f 48 44 ca 19 e6 4c |..........HD...L|
+00000050 3d 51 f2 29 40 0b 70 06 09 f0 69 5c 51 78 51 1e |=Q.)@.p...i\QxQ.|
+00000060 2b d1 47 22 8d d6 fb f5 41 bd e4 fd 3d f4 1b 48 |+.G"....A...=..H|
+00000070 44 96 2d 97 b9 |D.-..|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 40 15 37 89 e6 1f |..........@.7...|
-00000010 20 f6 91 b9 1f fb 29 e9 3e 07 ab c2 09 96 06 89 | .....).>.......|
-00000020 69 c2 dd 63 e1 24 5d cd af 08 e2 ed df 46 45 6b |i..c.$]......FEk|
-00000030 1e 9f 62 b6 89 27 04 3f fc f2 77 71 23 04 24 37 |..b..'.?..wq#.$7|
-00000040 74 8a 0a 64 a8 10 e3 1c dc 53 64 |t..d.....Sd|
+00000000 14 03 03 00 01 01 16 03 03 00 40 f1 a2 70 ba 50 |..........@..p.P|
+00000010 9d 7a 9f 8f c6 fb 7e 83 75 bd 94 cf e6 c1 4a f0 |.z....~.u.....J.|
+00000020 e6 54 e9 2c 30 23 a2 5c c2 09 32 d4 06 f7 54 e7 |.T.,0#.\..2...T.|
+00000030 ab 27 a6 66 ab 86 e6 2c 20 12 cf 61 4d ef 12 20 |.'.f..., ..aM.. |
+00000040 ba b6 42 39 b7 76 b9 1b fc f4 44 |..B9.v....D|
>>> Flow 5 (client to server)
00000000 17 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-00000010 00 00 00 00 00 ae 4e e7 3a 25 9d 8f fa 06 99 49 |......N.:%.....I|
-00000020 2e b8 0f 49 d0 54 2d 06 b4 d7 4c 60 51 f1 13 11 |...I.T-...L`Q...|
-00000030 c1 b3 f5 d0 bc 15 03 03 00 30 00 00 00 00 00 00 |.........0......|
-00000040 00 00 00 00 00 00 00 00 00 00 80 de bf db 10 74 |...............t|
-00000050 da 3f d8 77 ca 37 cc f3 96 bd d3 e1 34 9c f2 0a |.?.w.7......4...|
-00000060 70 60 5e 7c a4 7e c9 bd 89 5f |p`^|.~..._|
+00000010 00 00 00 00 00 0b 5b d0 ab 14 3f ae 1f 4b 12 25 |......[...?..K.%|
+00000020 05 2a 67 11 0c 17 42 1b b6 d2 af 16 40 26 fd 7b |.*g...B.....@&.{|
+00000030 d7 57 10 2a f8 15 03 03 00 30 00 00 00 00 00 00 |.W.*.....0......|
+00000040 00 00 00 00 00 00 00 00 00 00 83 54 64 d6 31 32 |...........Td.12|
+00000050 55 62 32 49 b9 54 7b e3 34 02 1c 75 e3 1b 5a 41 |Ub2I.T{.4..u..ZA|
+00000060 a2 cd 47 26 f0 ed c2 d5 41 34 |..G&....A4|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM
index 48d822a39c9..28a9ef7c659 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM
@@ -1,19 +1,20 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 42 ab c5 81 f5 |....Y...U..B....|
-00000010 c0 5b 73 64 f6 1b e0 59 30 b0 fd c5 e6 b3 57 f2 |.[sd...Y0.....W.|
-00000020 28 3f 5c d2 e8 05 7d a8 29 84 2e 20 8e 18 6b 52 |(?\...}.).. ..kR|
-00000030 1b ee 03 02 64 52 fb 24 44 4f 39 f2 d3 0f e6 9d |....dR.$DO9.....|
-00000040 50 31 31 b3 39 9e c1 3a b3 67 41 a0 c0 2b 00 00 |P11.9..:.gA..+..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 72 81 c3 91 37 |....Y...U..r...7|
+00000010 54 37 fb 0f 2b 16 3b 7b bc a6 d9 2e e2 83 23 83 |T7..+.;{......#.|
+00000020 b3 67 cf 36 dc 65 8d a6 3d cb 72 20 ac b9 b9 48 |.g.6.e..=.r ...H|
+00000030 30 9d fe 67 09 39 f5 47 d2 9a c8 3e 22 02 50 5e |0..g.9.G...>".P^|
+00000040 fd 02 c9 ff c1 84 2e 2e ab 78 ef c6 c0 2b 00 00 |.........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....|
@@ -48,38 +49,34 @@
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 03 00 d8 0c 00 00 d4 03 00 17 41 04 7a |*............A.z|
-00000280 01 b4 2c 50 85 34 6e 2c 2c 52 bc fa cf 71 82 e5 |..,P.4n,,R...q..|
-00000290 98 8d b0 f1 65 5f 7d bc c8 1b 7c 84 3e 46 45 c5 |....e_}...|.>FE.|
-000002a0 43 0e 72 e1 90 63 40 26 1c 22 dc 9a 3b b8 12 26 |C.r..c@&."..;..&|
-000002b0 a9 d6 1c e1 44 cf c7 38 db 9e 1b d0 b9 bb 06 04 |....D..8........|
-000002c0 03 00 8b 30 81 88 02 42 01 6b af f8 34 ae 89 50 |...0...B.k..4..P|
-000002d0 df 44 20 16 0b f9 ef a9 99 63 39 48 39 08 69 2d |.D ......c9H9.i-|
-000002e0 2d 9d 8b 3a e8 8a 9c 2f e9 d2 85 f2 d3 54 53 ec |-..:.../.....TS.|
-000002f0 b7 18 5b b0 76 3c 38 02 85 cc 00 20 45 9d e7 ba |..[.v<8.... E...|
-00000300 c0 3f c0 b5 1f df 64 42 fd 34 02 42 00 fa e5 dd |.?....dB.4.B....|
-00000310 04 c4 60 60 ff 9b 95 a2 a4 b4 80 87 9f 59 b4 8e |..``.........Y..|
-00000320 72 bf 53 8e 61 b6 df 99 9d 81 05 c5 71 a2 00 cb |r.S.a.......q...|
-00000330 80 bd e5 2a c3 51 d0 45 2f a3 8b 6d 21 6e 6c 80 |...*.Q.E/..m!nl.|
-00000340 4e f1 28 23 6d 76 df 55 77 69 a1 be 39 05 16 03 |N.(#mv.Uwi..9...|
-00000350 03 00 04 0e 00 00 00 |.......|
+00000270 2a 16 03 03 00 b6 0c 00 00 b2 03 00 1d 20 b7 1c |*............ ..|
+00000280 2f 05 5e c8 ae 68 6b 54 c5 88 19 cf 7c 04 b2 ed |/.^..hkT....|...|
+00000290 8d 5a e9 7e 6b 50 8a ee 12 66 2d 6f e4 7a 04 03 |.Z.~kP...f-o.z..|
+000002a0 00 8a 30 81 87 02 42 01 8d 7e 23 bc d7 a7 ad 73 |..0...B..~#....s|
+000002b0 5f 45 9e 04 da 6e c0 34 a8 09 59 e3 bc ab 80 e1 |_E...n.4..Y.....|
+000002c0 d4 84 79 7d de 90 c1 f2 ea 95 ed fc 7e d3 f0 31 |..y}........~..1|
+000002d0 4c 9b da 82 a0 97 ed e6 c9 f2 b9 2a 0a 1e 0a 2c |L..........*...,|
+000002e0 7f 1d 62 ea 11 a9 77 5e 2f 02 41 09 88 2b eb 84 |..b...w^/.A..+..|
+000002f0 4f 62 9a c9 8a 0b a2 c6 88 0e 3e d9 29 f0 2b ba |Ob........>.).+.|
+00000300 08 40 b0 9c 17 70 d9 84 1e d3 39 ad 70 fc df 63 |.@...p....9.p..c|
+00000310 a0 f6 69 3c 19 ce 0b a5 95 d2 6a b1 46 b1 e5 ba |..i<......j.F...|
+00000320 fd d2 67 4b 76 e3 eb b9 21 d0 7c 85 16 03 03 00 |..gKv...!.|.....|
+00000330 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 94 ba |.....(..........|
-00000060 0a c6 38 6b 65 60 95 5e df fc 42 7e ac 9f 5a 25 |..8ke`.^..B~..Z%|
-00000070 39 0e a9 7a 61 b3 17 80 77 82 e5 80 0a af |9..za...w.....|
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 32 49 7e |....(........2I~|
+00000040 8f d6 2e 81 d7 03 a6 61 a3 04 98 81 95 84 58 d1 |.......a......X.|
+00000050 a2 33 fe 4a 5d cd 96 76 64 1e 1a 62 03 |.3.J]..vd..b.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 ef 8d ac 17 6f |..........(....o|
-00000010 88 03 88 8f f3 d5 a0 60 28 a9 4d e8 20 ae 0c 21 |.......`(.M. ..!|
-00000020 fd d1 50 9b c3 d1 e9 cd 27 ed d7 8b 92 60 49 47 |..P.....'....`IG|
-00000030 ed 9a 74 |..t|
+00000000 14 03 03 00 01 01 16 03 03 00 28 28 14 2d ae 7c |..........((.-.||
+00000010 b8 7d dc 27 b2 18 39 57 c8 be 5c 3d a3 ab fa 5a |.}.'..9W..\=...Z|
+00000020 3d 55 1b 3d 31 77 95 af 42 86 af 2b e7 5a 98 40 |=U.=1w..B..+.Z.@|
+00000030 18 77 d1 |.w.|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 1d 4f 3c |..............O<|
-00000010 c5 d1 39 01 46 ab 7d d1 75 59 e7 f5 cd fa 02 0b |..9.F.}.uY......|
-00000020 dd 02 17 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................|
-00000030 e9 a5 d5 0c 05 2a 82 fe a5 6c 03 6e d0 c4 7d cb |.....*...l.n..}.|
-00000040 32 f3 |2.|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 30 50 2f |.............0P/|
+00000010 36 4a 7c ee e6 f0 b9 b8 bf 4d e3 63 4d 5e 58 08 |6J|......M.cM^X.|
+00000020 ac ac 82 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................|
+00000030 80 e2 42 ca 91 65 04 4e ca a8 6f 81 7c 30 c0 1f |..B..e.N..o.|0..|
+00000040 aa 7b |.{|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256
new file mode 100644
index 00000000000..831fa2101fe
--- /dev/null
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES128-SHA256
@@ -0,0 +1,91 @@
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 91 01 00 00 8d 03 03 00 00 00 00 00 |................|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
+>>> Flow 2 (server to client)
+00000000 16 03 03 00 59 02 00 00 55 03 03 be c0 b6 d7 fe |....Y...U.......|
+00000010 43 9d 21 1f 89 27 bd db 0a 9a 5a 44 dd 79 d1 f2 |C.!..'....ZD.y..|
+00000020 18 9a 2a 04 8c eb e6 a9 93 ef ee 20 35 48 44 08 |..*........ 5HD.|
+00000030 8c 7a 3e f6 0f d7 5f 33 54 60 0b c9 65 4e 17 8d |.z>..._3T`..eN..|
+00000040 d2 69 b7 20 0b c5 ba 9a d4 b7 40 39 c0 23 00 00 |.i. ......@9.#..|
+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 b7 0c 00 00 b3 03 00 1d 20 0e 53 |*............ .S|
+00000280 82 54 1a ba f8 a4 52 1d 6d b8 70 18 41 e8 67 f9 |.T....R.m.p.A.g.|
+00000290 38 1e fb fa b8 89 2d d6 4d 1b ae 67 fe 75 04 03 |8.....-.M..g.u..|
+000002a0 00 8b 30 81 88 02 42 01 68 0e d4 92 a6 1a d9 66 |..0...B.h......f|
+000002b0 ff 0e ca 4c 32 b8 78 d3 52 d1 ad a2 32 83 f0 3c |...L2.x.R...2..<|
+000002c0 43 e0 7e 92 94 e9 c6 99 00 d9 f7 06 c0 2c 72 c0 |C.~..........,r.|
+000002d0 9b f7 c0 ec 1f 23 8f b5 e5 74 9d ff 89 17 12 b4 |.....#...t......|
+000002e0 f1 f5 25 f7 2e 0d 78 f6 1c 02 42 01 fc da dd c8 |..%...x...B.....|
+000002f0 65 30 67 a3 ff 42 e3 37 19 ba 7c 04 6b a1 b3 97 |e0g..B.7..|.k...|
+00000300 b0 ca 8c 2d fc b0 40 1c a1 d8 c9 64 fe df 48 3b |...-..@....d..H;|
+00000310 07 57 1f 81 a2 3e a4 84 96 00 fb 55 29 1c 94 9d |.W...>.....U)...|
+00000320 f9 0d a4 71 4f 5f fd c3 22 e2 88 07 21 16 03 03 |...qO_.."...!...|
+00000330 00 04 0e 00 00 00 |......|
+>>> Flow 3 (client to server)
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 50 00 00 00 00 00 00 00 00 00 00 00 |....P...........|
+00000040 00 00 00 00 00 7c e9 97 4b 98 8a 4c 59 95 3e 31 |.....|..K..LY.>1|
+00000050 c4 b6 e2 79 10 de bc 8e aa 1e 52 07 b2 e1 52 bc |...y......R...R.|
+00000060 3b da 8d 5f 12 6a 18 d1 0a 5d 93 1c ad bb f9 b7 |;.._.j...]......|
+00000070 6b 58 49 39 ea 3a 9e 20 47 69 43 b4 b4 d8 16 d0 |kXI9.:. GiC.....|
+00000080 f0 9d 36 74 04 |..6t.|
+>>> Flow 4 (server to client)
+00000000 14 03 03 00 01 01 16 03 03 00 50 60 d5 ac 39 b6 |..........P`..9.|
+00000010 58 50 03 90 9f c9 78 f1 45 43 b1 34 bd c8 29 65 |XP....x.EC.4..)e|
+00000020 54 38 7a 88 46 15 e8 a4 fb 9d 80 4e d6 45 e1 8d |T8z.F......N.E..|
+00000030 27 d6 09 66 1d ee 46 6d dd 8e 89 34 0f 4a fb fd |'..f..Fm...4.J..|
+00000040 bc 85 08 07 f0 5b 1c 24 e2 11 1b e2 a4 94 f5 80 |.....[.$........|
+00000050 fa 47 f4 62 0e b9 1c 31 cb 7b bf |.G.b...1.{.|
+>>> Flow 5 (client to server)
+00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........|
+00000010 00 00 00 00 00 37 b7 23 a2 06 97 f3 60 9a f0 7e |.....7.#....`..~|
+00000020 b7 11 6d 0d 66 0e db 38 1a eb cd 72 80 c8 54 ef |..m.f..8...r..T.|
+00000030 cf 90 6d 22 68 41 63 03 46 b9 28 4f 2f d6 fe fa |..m"hAc.F.(O/...|
+00000040 b2 91 07 36 71 15 03 03 00 40 00 00 00 00 00 00 |...6q....@......|
+00000050 00 00 00 00 00 00 00 00 00 00 ca 17 d9 fd 1a 0e |................|
+00000060 21 db a4 92 dc 92 e8 89 9d 14 6b 8a d3 ee a7 95 |!.........k.....|
+00000070 c0 91 8d 3c af 5a 48 d5 c6 2f 66 b8 b8 d4 ce f9 |...<.ZH../f.....|
+00000080 59 e5 e0 e2 df e5 7e ea 94 03 |Y.....~...|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384
index 2a16651136c..c22edd05e00 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384
@@ -1,19 +1,20 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 ed 6d 5a 1c 89 |....Y...U...mZ..|
-00000010 a4 f3 35 0b e4 74 7e e2 05 a5 36 4d 4a 55 b3 7c |..5..t~...6MJU.||
-00000020 a1 a6 42 a3 fc 35 8c e0 97 5b 4b 20 a1 4a 06 28 |..B..5...[K .J.(|
-00000030 4d 40 0b fc 47 d5 4d 9b d5 43 b0 0d 0d c6 ae 30 |M@..G.M..C.....0|
-00000040 79 59 00 d4 90 96 98 92 d2 3a 57 07 c0 2c 00 00 |yY.......:W..,..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 e6 0e 27 a7 58 |....Y...U....'.X|
+00000010 1d a3 1d 1d 21 64 31 f6 1e bc 28 b4 46 7e 26 be |....!d1...(.F~&.|
+00000020 de 0a 65 eb f0 18 dc 7f 3e 1b 55 20 fe 66 50 20 |..e.....>.U .fP |
+00000030 f0 f0 48 a8 db 0a ff ee 60 ea 3d 7f 07 5e b9 65 |..H.....`.=..^.e|
+00000040 c3 e4 2a 19 9c bd 57 36 ca e3 a7 2d c0 2c 00 00 |..*...W6...-.,..|
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....|
@@ -48,38 +49,34 @@
00000240 13 83 0d 94 06 bb d4 37 7a f6 ec 7a c9 86 2e dd |.......7z..z....|
00000250 d7 11 69 7f 85 7c 56 de fb 31 78 2b e4 c7 78 0d |..i..|V..1x+..x.|
00000260 ae cb be 9e 4e 36 24 31 7b 6a 0f 39 95 12 07 8f |....N6$1{j.9....|
-00000270 2a 16 03 03 00 d7 0c 00 00 d3 03 00 17 41 04 89 |*............A..|
-00000280 e6 6d 6a 56 3e e5 4e 72 df 2b 41 11 de a0 c0 3e |.mjV>.Nr.+A....>|
-00000290 22 04 9a b5 a8 d6 22 30 2a e5 bd 83 1c 7a 8e 6c |"....."0*....z.l|
-000002a0 93 ab 8f d7 64 9e fe 89 c0 da 9a 45 7d 76 91 69 |....d......E}v.i|
-000002b0 0a 11 c5 59 26 49 ec 69 99 b3 91 a5 4b 2b 89 04 |...Y&I.i....K+..|
-000002c0 03 00 8a 30 81 87 02 42 01 17 1d ff 9a 99 76 20 |...0...B......v |
-000002d0 13 8a e1 5a a8 04 8a 1e 84 57 fd b0 95 c1 6c af |...Z.....W....l.|
-000002e0 b2 66 13 b5 75 36 ce 86 69 67 3d dc 82 2f 06 57 |.f..u6..ig=../.W|
-000002f0 19 14 56 54 0e 8e 04 74 0b 73 49 61 92 8e d1 9a |..VT...t.sIa....|
-00000300 b5 60 7f 65 a8 f8 99 eb ac 56 02 41 57 a3 78 57 |.`.e.....V.AW.xW|
-00000310 8a dd fa 9c 3d 24 a0 f2 0a 74 1a 8a 8f 6c 82 55 |....=$...t...l.U|
-00000320 4c cd d8 5d 79 99 87 93 41 e7 78 f4 28 0d ef 63 |L..]y...A.x.(..c|
-00000330 fb da 8e 93 86 31 6e 3e ca 6f 6b 1b fd 7a a3 86 |.....1n>.ok..z..|
-00000340 6e bb 17 35 90 d9 a4 df 12 d0 54 5e 25 16 03 03 |n..5......T^%...|
-00000350 00 04 0e 00 00 00 |......|
+00000270 2a 16 03 03 00 b7 0c 00 00 b3 03 00 1d 20 17 21 |*............ .!|
+00000280 a9 b8 65 8b aa 41 d2 d1 45 45 e5 ce 39 60 54 b6 |..e..A..EE..9`T.|
+00000290 43 9f c4 19 a4 aa ec 71 08 b0 d1 22 f7 46 04 03 |C......q...".F..|
+000002a0 00 8b 30 81 88 02 42 00 8b a5 d9 d3 8f a1 72 48 |..0...B.......rH|
+000002b0 06 42 25 c3 f6 c8 46 8d 88 30 36 7d d8 18 a9 cc |.B%...F..06}....|
+000002c0 de e4 c8 3f e9 d2 f0 88 18 cc c6 fb 14 e0 05 b1 |...?............|
+000002d0 ec 50 3d 57 b4 e9 83 57 55 4b 0d 2c 89 69 ff b1 |.P=W...WUK.,.i..|
+000002e0 58 0b 01 89 48 97 ee 88 7e 02 42 01 e1 6f 9c 36 |X...H...~.B..o.6|
+000002f0 6a 6c 86 24 d6 b3 45 f1 6c 03 d8 fd da d8 cc 52 |jl.$..E.l......R|
+00000300 04 41 7a c5 f9 b5 91 a5 6c d8 5a 03 ad de e3 da |.Az.....l.Z.....|
+00000310 de f8 db b0 bc 75 38 03 ab 84 ac 3f b2 c2 7e 6d |.....u8....?..~m|
+00000320 a7 2e c0 d9 bd 85 e2 7b 36 11 2b 12 14 16 03 03 |.......{6.+.....|
+00000330 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 9d e7 |.....(..........|
-00000060 31 2a 0a 46 84 fd d9 18 c2 b0 b1 31 eb 63 4d 2d |1*.F.......1.cM-|
-00000070 ee 17 59 e6 b4 0f c6 d8 3d 8c e9 57 83 a8 |..Y.....=..W..|
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 4b a3 cc |....(........K..|
+00000040 a1 5b 04 d4 1e 6c 2c 26 56 23 62 50 bc d6 90 0b |.[...l,&V#bP....|
+00000050 67 41 d9 7c 79 a5 53 54 73 0a 93 e2 73 |gA.|y.STs...s|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 e0 85 25 02 b4 |..........(..%..|
-00000010 86 32 57 70 3c 7e 6b e5 75 e0 3a 43 c8 c2 fe f8 |.2Wp<~k.u.:C....|
-00000020 2e 04 fe 73 e4 7b 2c 9a e0 65 2e d6 53 ae f1 19 |...s.{,..e..S...|
-00000030 dd 6f 1a |.o.|
+00000000 14 03 03 00 01 01 16 03 03 00 28 e3 19 7b 8c 8a |..........(..{..|
+00000010 52 35 82 cc 70 50 83 22 88 8b 0a 54 bc eb ff 57 |R5..pP."...T...W|
+00000020 2c df 0d 50 d6 21 2f d2 d9 e8 15 27 b9 d7 01 a3 |,..P.!/....'....|
+00000030 f2 62 0b |.b.|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 29 b2 e6 |.............)..|
-00000010 c3 2e 72 ba cc ac d9 3b c7 0c 1d 53 b2 30 39 71 |..r....;...S.09q|
-00000020 6e dd 79 15 03 03 00 1a 00 00 00 00 00 00 00 02 |n.y.............|
-00000030 88 c9 92 fe 6c 1f 6c fd bd 7b fb 0a 8a b5 cc c9 |....l.l..{......|
-00000040 94 90 |..|
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 cc cf 92 |................|
+00000010 4d 25 58 96 1d dc df fb d9 1f a5 49 87 45 dd 73 |M%X........I.E.s|
+00000020 1a 17 ae 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................|
+00000030 fb b5 c5 e4 aa ea e7 7e ff dd f7 11 63 c0 e4 a3 |.......~....c...|
+00000040 86 fc |..|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305
new file mode 100644
index 00000000000..61e665721a2
--- /dev/null
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-CHACHA20-POLY1305
@@ -0,0 +1,77 @@
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 67 01 00 00 63 03 03 00 00 00 00 00 |....g...c.......|
+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 02 cc a9 |................|
+00000030 01 00 00 38 00 05 00 05 01 00 00 00 00 00 0a 00 |...8............|
+00000040 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................|
+00000050 00 00 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 |................|
+00000060 01 02 03 ff 01 00 01 00 00 12 00 00 |............|
+>>> Flow 2 (server to client)
+00000000 16 03 03 00 59 02 00 00 55 03 03 d6 47 27 38 fc |....Y...U...G'8.|
+00000010 16 92 2c 1f a6 53 a9 31 85 65 a7 83 0a 8f cb 4d |..,..S.1.e.....M|
+00000020 7d 5b df c1 2e b9 b1 08 e3 b9 96 20 16 0c e5 07 |}[......... ....|
+00000030 27 cc 4f 7d 11 ef 1a 14 c6 42 bf e9 c1 b7 a5 89 |'.O}.....B......|
+00000040 ca 2b 4c 30 4f c7 c8 10 13 b0 b1 6b cc a9 00 00 |.+L0O......k....|
+00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
+00000060 03 02 0e 0b 00 02 0a 00 02 07 00 02 04 30 82 02 |.............0..|
+00000070 00 30 82 01 62 02 09 00 b8 bf 2d 47 a0 d2 eb f4 |.0..b.....-G....|
+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 b7 0c 00 00 b3 03 00 1d 20 69 78 |*............ ix|
+00000280 7b e5 14 95 c8 d1 3c 7e c2 d7 38 33 c3 9f 8f dc |{.....<~..83....|
+00000290 25 8d 89 8a 99 a4 e4 8b 40 17 fc 80 43 67 04 03 |%.......@...Cg..|
+000002a0 00 8b 30 81 88 02 42 01 32 a8 dd d9 ec 11 d2 f2 |..0...B.2.......|
+000002b0 6d 86 da 31 00 8c bf ed 81 1d 8c c8 23 87 98 f7 |m..1........#...|
+000002c0 25 0c 1b 3d 9f 07 80 11 bc 07 b1 15 5f 3a 81 0e |%..=........_:..|
+000002d0 59 04 e8 09 be ea 21 97 34 a9 8a 2f ef 3a 47 ad |Y.....!.4../.:G.|
+000002e0 3b f9 9d f3 b8 b8 9a 93 03 02 42 01 bc 88 6b 99 |;.........B...k.|
+000002f0 d7 7a df de 5a 75 53 b0 3c 4c 1d 8b 15 c5 a7 9d |.z..ZuS.<L......|
+00000300 3d 00 c0 f7 19 47 88 30 00 29 24 80 23 45 88 2e |=....G.0.)$.#E..|
+00000310 11 60 3e 4b 6a 41 ad dc 3d 7d 3f 59 a0 0e fd d6 |.`>KjA..=}?Y....|
+00000320 f7 c7 7f 63 49 2f e4 4e d9 8f 2d e5 98 16 03 03 |...cI/.N..-.....|
+00000330 00 04 0e 00 00 00 |......|
+>>> Flow 3 (client to server)
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 20 7c 89 36 36 77 8c 09 31 e4 48 01 |.... |.66w..1.H.|
+00000040 6f 08 27 a8 bb 1b 1c a6 0c 09 ec 0b f6 a3 be bd |o.'.............|
+00000050 76 70 fb f8 e5 |vp...|
+>>> Flow 4 (server to client)
+00000000 14 03 03 00 01 01 16 03 03 00 20 a0 db 6c df b1 |.......... ..l..|
+00000010 87 77 78 ad 22 b2 98 77 e8 57 aa 13 a8 98 35 63 |.wx."..w.W....5c|
+00000020 00 c5 13 b9 88 5d ca bf bc c5 c3 |.....].....|
+>>> Flow 5 (client to server)
+00000000 17 03 03 00 16 16 00 c8 c6 25 ae 11 9d a5 10 75 |.........%.....u|
+00000010 e4 4c e3 69 12 2b d9 9e 8e 40 88 15 03 03 00 12 |.L.i.+...@......|
+00000020 cf ab ac d4 c4 8e 9c 92 c4 2f 1f c6 96 0b 36 c9 |........./....6.|
+00000030 f5 22 |."|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES
index 29767b7b936..45728cfbe73 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES
@@ -1,95 +1,91 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 2a 6a a8 b3 97 |....Y...U..*j...|
-00000010 d5 c8 5e b4 22 7e d0 a5 c7 46 af 89 60 44 77 5e |..^."~...F..`Dw^|
-00000020 1a f8 3a 30 08 6d 5f 4c 61 36 c5 20 57 79 91 3e |..:0.m_La6. Wy.>|
-00000030 1f 40 d1 f1 33 d7 a9 fb 93 eb 16 0d e1 39 e3 a3 |.@..3........9..|
-00000040 80 e3 4f 58 a6 f8 a4 be 19 dd ef ee c0 13 00 00 |..OX............|
+00000000 16 03 03 00 59 02 00 00 55 03 03 2f 51 e0 81 eb |....Y...U../Q...|
+00000010 d2 db 4f 22 fa 11 d2 56 f3 06 d6 a0 97 d2 f3 74 |..O"...V.......t|
+00000020 fc a9 a7 73 ba a8 ee f2 05 89 15 20 0f 96 70 60 |...s....... ..p`|
+00000030 6f 78 aa 56 fa 92 5e e3 bc e7 f0 40 00 48 8b 84 |ox.V..^....@.H..|
+00000040 57 b8 49 e9 f9 00 99 ff 73 29 f6 e7 c0 13 00 00 |W.I.....s)......|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
-00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
-00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
-000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
-000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
-000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
-000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
-000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
-000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
-00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
-00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
-00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
-00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
-00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
-00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
-00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
-00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
-00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
-00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
-000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
-000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
-000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
-000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
-000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
-000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
-00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
-00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
-00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
-00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
-00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
-00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
-00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
-00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
-00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
-00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
-000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
-000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
-000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
-000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............|
-000002e0 41 04 8e c8 e8 42 7c 8a 01 c2 ff 01 cb 0b e1 20 |A....B|........ |
-000002f0 50 42 d4 3a 1b 34 ff 74 59 81 2f a2 0e 29 b2 f9 |PB.:.4.tY./..)..|
-00000300 47 cf 0d 08 97 cf aa 9f fe f0 7f e8 f4 fd 3a fa |G.............:.|
-00000310 a6 b6 47 32 d3 25 78 87 bf 77 cc 12 37 02 6a ad |..G2.%x..w..7.j.|
-00000320 cf 2c 04 01 00 80 13 a1 95 17 7b 21 86 7f f2 02 |.,........{!....|
-00000330 9f ed 88 2d 1f 2c 38 96 bc fa 5a 39 85 4b 9f ff |...-.,8...Z9.K..|
-00000340 5c 7a 02 1e 5f c9 4a 69 51 d3 83 34 9f dc 8c 39 |\z.._.JiQ..4...9|
-00000350 fe 81 76 fc c3 59 ff e2 a8 81 ca 6f f6 52 c9 44 |..v..Y.....o.R.D|
-00000360 a0 3f 5e 5e 92 20 db d9 2e 0b e3 ab 75 e7 79 f6 |.?^^. ......u.y.|
-00000370 b2 73 17 e1 94 1e 12 62 e9 b0 0f 04 e7 5d 83 ac |.s.....b.....]..|
-00000380 71 ca a5 62 40 dd 69 b1 3f cf bb 3d c7 3e 51 6c |q..b@.i.?..=.>Ql|
-00000390 11 f2 cf 39 f1 b5 72 bd 52 d4 3d 3c c0 90 34 c8 |...9..r.R.=<..4.|
-000003a0 4b 22 55 39 1c 2b 16 03 03 00 04 0e 00 00 00 |K"U9.+.........|
+00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
+000002c0 ac 0c 00 00 a8 03 00 1d 20 48 77 87 3e 04 c9 14 |........ Hw.>...|
+000002d0 56 9d 1b 41 4b d0 eb 65 8d 56 56 97 fd 73 97 cd |V..AK..e.VV..s..|
+000002e0 c6 88 8f 8e 79 99 09 65 53 04 01 00 80 98 c2 ff |....y..eS.......|
+000002f0 49 aa 41 ce 0e 7b 03 99 39 c0 b5 ac 72 16 1c 5e |I.A..{..9...r..^|
+00000300 a0 92 f1 07 0c 93 dc f6 25 2b 5c be e3 65 41 a9 |........%+\..eA.|
+00000310 1e 57 6d 9f 28 50 ca 87 2f c7 b0 15 2e 15 d2 cc |.Wm.(P../.......|
+00000320 4d 0e 42 4c 0a 01 4d 1b 9c d1 17 e7 22 9a 6a a9 |M.BL..M.....".j.|
+00000330 27 0b 7a a7 32 e3 c7 5a d1 7f f2 1c 45 61 91 a8 |'.z.2..Z....Ea..|
+00000340 e0 e0 49 de b7 2f a6 89 63 94 ed 0e 63 15 6b 4f |..I../..c...c.kO|
+00000350 fb 62 c4 35 cb 98 89 c2 d1 bc f6 e2 2d 8f 9f 72 |.b.5........-..r|
+00000360 56 79 50 5f cd 73 00 f1 65 bf a4 3f 87 16 03 03 |VyP_.s..e..?....|
+00000370 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 a2 6e de ea 78 0c 4d 20 ad 1f |.......n..x.M ..|
-00000070 1a f5 6b 15 09 f1 50 bb cd 40 0e c7 d9 ed 7f e1 |..k...P..@......|
-00000080 4b bc d3 26 5d 89 b7 26 c5 6c 0e 59 6f 84 51 5d |K..&]..&.l.Yo.Q]|
-00000090 2f 75 d8 0f 2e e8 |/u....|
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........|
+00000040 00 00 00 00 00 93 4b 37 8d 57 43 52 77 56 d2 af |......K7.WCRwV..|
+00000050 7c 56 d0 bf 1e 7b 29 55 3e b7 d0 1c 02 2e 0d de ||V...{)U>.......|
+00000060 09 66 f2 98 21 57 ab d2 d2 4a 73 c1 c5 fe f1 b8 |.f..!W...Js.....|
+00000070 95 d3 fc 70 ce |...p.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 40 dd d8 e7 63 89 |..........@...c.|
-00000010 8e cc 3e e0 df 6d 5a 42 b3 49 1b 66 e8 79 e9 f0 |..>..mZB.I.f.y..|
-00000020 8a c3 0e 5e d7 01 ac 04 81 6a e1 60 14 60 b9 a6 |...^.....j.`.`..|
-00000030 4c a5 46 43 74 df 30 1e f8 74 77 4c b5 42 e5 25 |L.FCt.0..twL.B.%|
-00000040 81 9d b1 04 bc 02 46 bd b1 55 d0 |......F..U.|
+00000000 14 03 03 00 01 01 16 03 03 00 40 b3 e1 81 3e 0a |..........@...>.|
+00000010 f8 f3 c6 05 c1 09 f5 73 01 eb 18 1a 05 fa 2f 9b |.......s....../.|
+00000020 b2 bc c7 44 23 38 ed b9 99 a0 56 7d 8b e4 a5 4b |...D#8....V}...K|
+00000030 f1 89 45 bc 95 ea 06 a8 48 de 07 bf d5 cb 53 bc |..E.....H.....S.|
+00000040 50 fa 25 fb d5 79 17 ec 4d be 3d |P.%..y..M.=|
>>> 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 35 49 6d a7 3f a1 39 5d 37 8d 2e |.....5Im.?.9]7..|
-00000020 c5 1e 90 3b f9 60 58 d3 47 e3 db 73 8b aa 6c 9e |...;.`X.G..s..l.|
-00000030 b5 82 55 09 62 15 03 03 00 30 00 00 00 00 00 00 |..U.b....0......|
-00000040 00 00 00 00 00 00 00 00 00 00 71 b3 7b c7 d4 27 |..........q.{..'|
-00000050 f9 77 7f d0 80 25 1b 43 d0 0e 92 38 8c f3 2f 50 |.w...%.C...8../P|
-00000060 eb 96 22 fb e6 09 45 ec 7f 16 |.."...E...|
+00000010 00 00 00 00 00 3e 90 61 a4 f1 53 ac 7b b2 9f 4e |.....>.a..S.{..N|
+00000020 2c 16 5a 77 8b da 5d 68 5c 8b a8 6d 44 52 f3 ad |,.Zw..]h\..mDR..|
+00000030 8e ba c8 89 2f 15 03 03 00 30 00 00 00 00 00 00 |..../....0......|
+00000040 00 00 00 00 00 00 00 00 00 00 e5 01 5d ef 4c 0c |............].L.|
+00000050 07 8f 21 99 60 83 ee 36 13 8e 25 15 32 85 a5 96 |..!.`..6..%.2...|
+00000060 36 90 60 49 4f c7 54 99 dd 76 |6.`IO.T..v|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256
new file mode 100644
index 00000000000..6b02249f3fc
--- /dev/null
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES128-SHA256
@@ -0,0 +1,95 @@
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 91 01 00 00 8d 03 03 00 00 00 00 00 |................|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
+>>> Flow 2 (server to client)
+00000000 16 03 03 00 59 02 00 00 55 03 03 ab d3 05 5e d0 |....Y...U.....^.|
+00000010 80 0b 87 e9 43 26 e2 c9 28 04 3f eb 68 05 54 3d |....C&..(.?.h.T=|
+00000020 9b 28 d0 4e d4 d9 25 e5 b0 27 2b 20 89 27 da d5 |.(.N..%..'+ .'..|
+00000030 3d 19 38 63 01 34 f6 43 1b a9 f7 09 12 7d 27 e1 |=.8c.4.C.....}'.|
+00000040 f6 23 b8 39 24 8b 1e c7 a3 2f 07 16 c0 27 00 00 |.#.9$..../...'..|
+00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
+00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
+000002c0 ac 0c 00 00 a8 03 00 1d 20 ec 71 cc fb 07 bd 0f |........ .q.....|
+000002d0 6b e0 e1 27 7f 62 59 06 09 3c 09 bc b1 c9 09 93 |k..'.bY..<......|
+000002e0 e9 b0 a4 5b f3 be 14 d1 3c 04 01 00 80 a9 c7 98 |...[....<.......|
+000002f0 ea ac 6a 9b 49 7c 72 45 4d 5c c8 4c d6 56 64 1b |..j.I|rEM\.L.Vd.|
+00000300 44 7f 13 4f 2a ed e9 6b c7 c0 a2 25 3b 7a 99 f4 |D..O*..k...%;z..|
+00000310 93 84 35 78 72 21 ca f6 29 1b 60 d7 f6 bd 31 5b |..5xr!..).`...1[|
+00000320 7a fb 57 20 30 cc e6 90 07 b2 0e 08 82 86 56 a7 |z.W 0.........V.|
+00000330 55 00 fd f4 ce f4 b1 74 27 e9 0a 28 1c bc 56 47 |U......t'..(..VG|
+00000340 f7 18 3e 9e 9c 45 2d 1d 82 a8 66 51 27 25 be ec |..>..E-...fQ'%..|
+00000350 cd 9e 83 89 7e e0 e3 0f 3b 7b 32 f2 26 7b 30 c8 |....~...;{2.&{0.|
+00000360 c1 e3 7b 4c f4 14 d5 51 ea b7 45 7a 59 16 03 03 |..{L...Q..EzY...|
+00000370 00 04 0e 00 00 00 |......|
+>>> Flow 3 (client to server)
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 50 00 00 00 00 00 00 00 00 00 00 00 |....P...........|
+00000040 00 00 00 00 00 76 d8 c4 58 a1 94 11 ab 19 4c 7b |.....v..X.....L{|
+00000050 7c 34 d1 b6 8b 7f a2 96 41 e6 e9 98 d8 55 62 2b ||4......A....Ub+|
+00000060 56 54 2a 65 25 f0 fa 15 ac cb b7 cc 3b 59 8b 99 |VT*e%.......;Y..|
+00000070 e9 be 9e fe 56 97 07 ae 39 38 a7 f4 f0 d0 e9 f5 |....V...98......|
+00000080 33 de 20 a6 04 |3. ..|
+>>> Flow 4 (server to client)
+00000000 14 03 03 00 01 01 16 03 03 00 50 8c 0f 2a be cd |..........P..*..|
+00000010 30 f7 46 cf 58 5b 38 88 86 5e d1 33 b1 61 d6 95 |0.F.X[8..^.3.a..|
+00000020 13 c7 e7 f2 fb bc 37 e5 a3 db ac a7 74 49 00 89 |......7.....tI..|
+00000030 db 94 25 aa 00 b6 b2 34 0a dd 97 bf fa cf 33 6e |..%....4......3n|
+00000040 6e f7 ab bf 70 a6 85 91 9b 4f f2 86 15 83 60 0d |n...p....O....`.|
+00000050 79 9e 11 51 17 a6 6f 06 2f 98 bc |y..Q..o./..|
+>>> Flow 5 (client to server)
+00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........|
+00000010 00 00 00 00 00 c3 c9 23 7b bd 57 1a 29 5f ac f6 |.......#{.W.)_..|
+00000020 8d bb 90 bb 48 8a 9a 75 65 3b 5b 52 c0 ee 0e 24 |....H..ue;[R...$|
+00000030 43 f6 62 1f 1e 51 36 4e 3e a3 e4 96 d8 2b d8 a7 |C.b..Q6N>....+..|
+00000040 d0 18 97 d7 1e 15 03 03 00 40 00 00 00 00 00 00 |.........@......|
+00000050 00 00 00 00 00 00 00 00 00 00 c0 c8 9f 7d df b1 |.............}..|
+00000060 78 72 b5 3d 0d 3e d9 88 38 c2 42 eb 2b 4d e0 b3 |xr.=.>..8.B.+M..|
+00000070 d7 69 19 31 57 16 7c 0a bb 24 5b 9c 9b c2 4b b9 |.i.1W.|..$[...K.|
+00000080 55 ef ad 2c c1 eb 9b 59 06 5a |U..,...Y.Z|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305 b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305
new file mode 100644
index 00000000000..64f999a05ad
--- /dev/null
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-CHACHA20-POLY1305
@@ -0,0 +1,81 @@
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 67 01 00 00 63 03 03 00 00 00 00 00 |....g...c.......|
+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 02 cc a8 |................|
+00000030 01 00 00 38 00 05 00 05 01 00 00 00 00 00 0a 00 |...8............|
+00000040 0a 00 08 00 1d 00 17 00 18 00 19 00 0b 00 02 01 |................|
+00000050 00 00 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 |................|
+00000060 01 02 03 ff 01 00 01 00 00 12 00 00 |............|
+>>> Flow 2 (server to client)
+00000000 16 03 03 00 59 02 00 00 55 03 03 45 f5 61 06 a8 |....Y...U..E.a..|
+00000010 4e ce c0 32 d6 af fb 12 5e c8 6c 06 ac c9 d7 e4 |N..2....^.l.....|
+00000020 02 49 09 b9 42 ee ae fa e4 52 18 20 12 3a 53 7d |.I..B....R. .:S}|
+00000030 11 cf 13 13 a3 f8 42 c3 98 bb bc a6 10 3e f4 13 |......B......>..|
+00000040 a5 a2 fd ef aa b3 01 3c cb 8a 3a 2c cc a8 00 00 |.......<..:,....|
+00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
+00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
+000002c0 ac 0c 00 00 a8 03 00 1d 20 57 53 06 53 e5 14 06 |........ WS.S...|
+000002d0 df 26 9d 3a 06 dc a9 d5 49 d3 3f 5f 7b c2 ab 77 |.&.:....I.?_{..w|
+000002e0 fd a1 fe 28 dc 54 36 06 22 04 01 00 80 da 23 f5 |...(.T6.".....#.|
+000002f0 19 de e8 d2 a9 79 b8 37 3d c0 8c ae f6 7c d5 d9 |.....y.7=....|..|
+00000300 87 ab 6b 3f 76 7c 5f 94 be 11 55 a3 78 66 1e e3 |..k?v|_...U.xf..|
+00000310 f3 11 3d 1a f7 02 26 a4 a6 cd 7c fe 87 0d 68 a1 |..=...&...|...h.|
+00000320 50 e8 7e 94 41 bd 5b 74 d0 6d 3b 6c ef ee 88 2d |P.~.A.[t.m;l...-|
+00000330 60 0a a9 53 cf 1f f4 03 a3 54 e5 91 36 50 62 54 |`..S.....T..6PbT|
+00000340 5f e6 e5 36 63 58 ba 7b bb 3a 79 59 58 08 a8 f2 |_..6cX.{.:yYX...|
+00000350 f5 1e 35 f8 f5 0f 7f 19 e7 7f 5f 56 e2 50 6d 8c |..5......._V.Pm.|
+00000360 da 45 70 60 0d 58 32 94 e7 a0 f7 da 93 16 03 03 |.Ep`.X2.........|
+00000370 00 04 0e 00 00 00 |......|
+>>> Flow 3 (client to server)
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 20 9d 2f a6 b7 21 56 ad 38 a8 31 20 |.... ./..!V.8.1 |
+00000040 0b 2e dc 3f 8a 34 64 de 81 0e d3 a5 b1 c1 fc 05 |...?.4d.........|
+00000050 18 d9 3e 77 35 |..>w5|
+>>> Flow 4 (server to client)
+00000000 14 03 03 00 01 01 16 03 03 00 20 a8 82 60 8a ef |.......... ..`..|
+00000010 31 55 42 e9 1d 33 0e d8 a9 b1 43 85 1c 04 7b 20 |1UB..3....C...{ |
+00000020 81 df 03 e9 fd c0 f7 32 b9 b3 31 |.......2..1|
+>>> Flow 5 (client to server)
+00000000 17 03 03 00 16 ef 72 f7 1b 26 1a 47 99 f9 4c e7 |......r..&.G..L.|
+00000010 be 8e ab c5 8e ea 8c c6 60 6c 10 15 03 03 00 12 |........`l......|
+00000020 2c f4 39 e3 3a 74 a4 3c 72 63 77 e8 82 cf a9 e2 |,.9.:t.<rcw.....|
+00000030 2b 04 |+.|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4 b/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4
index ffdc3284b84..74282d4b1a5 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RSA-RC4
@@ -1,79 +1,78 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 51 02 00 00 4d 03 03 79 8f 56 ac 75 |....Q...M..y.V.u|
-00000010 4f a9 fc 2c b9 53 82 a6 b4 c8 0d 4e 50 9a 9e aa |O..,.S.....NP...|
-00000020 8d ed 21 21 91 5d a2 cc 99 1b 68 20 0c e7 35 50 |..!!.]....h ..5P|
-00000030 67 02 70 2a 45 0d 6c 4c 46 df 75 dc 5f 6e 2f 79 |g.p*E.lLF.u._n/y|
-00000040 03 26 da 45 53 25 50 23 c0 85 3b 8c 00 05 00 00 |.&.ES%P#..;.....|
-00000050 05 ff 01 00 01 00 16 03 03 02 71 0b 00 02 6d 00 |..........q...m.|
-00000060 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000070 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000090 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-000000a0 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-000000b0 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000c0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000d0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000e0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000f0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-00000100 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-00000110 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000120 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000130 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000140 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000150 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000160 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000170 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000180 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000190 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-000001a0 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-000001b0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001c0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001d0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001e0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001f0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-00000200 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-00000210 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000220 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000230 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000240 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000250 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000260 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000270 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000280 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000290 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-000002a0 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-000002b0 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002c0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002d0 04 0e 00 00 00 |.....|
+00000000 16 03 03 00 51 02 00 00 4d 03 03 ac bf 85 b8 5f |....Q...M......_|
+00000010 56 44 a0 c5 3b 20 77 71 af de 34 bc 79 a0 a4 a7 |VD..; wq..4.y...|
+00000020 fa 2e cf b5 ee c5 a7 a2 5e 11 48 20 05 89 5e a6 |........^.H ..^.|
+00000030 cd ad 91 e4 be c3 c3 6c 6a 0e 1d ab 27 03 5e 0f |.......lj...'.^.|
+00000040 05 9d ef b0 63 8d 2d b6 29 08 66 e3 00 05 00 00 |....c.-.).f.....|
+00000050 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000060 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000070 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000080 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000090 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+000000a0 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+000000b0 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000c0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000d0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000e0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000f0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+00000100 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+00000110 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000120 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000130 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000140 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000150 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000160 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000170 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000180 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000190 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+000001a0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+000001b0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001c0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001d0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001e0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001f0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+00000200 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+00000210 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000220 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000230 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000240 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000250 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000260 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000270 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000280 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000290 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+000002a0 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+000002b0 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 73 bd 73 65 92 |...........s.se.|
-00000010 86 23 41 14 79 7f d5 c1 10 ce 94 4d ad 9c c3 a9 |.#A.y......M....|
-00000020 87 b5 32 52 f8 6b 11 93 2d 9b 98 0b 8b 1d c0 f6 |..2R.k..-.......|
-00000030 53 17 6d c7 9c 2e ae c9 6f cc 99 23 38 37 1a 10 |S.m.....o..#87..|
-00000040 fe 05 0b b5 55 0a 14 e9 60 7d 70 26 98 e2 54 d9 |....U...`}p&..T.|
-00000050 65 cf 2e f4 53 5f 1d aa 3a f6 33 7b eb 4c 0e b3 |e...S_..:.3{.L..|
-00000060 ff 5a db 36 2a 47 f3 df f9 fc f5 31 78 83 aa 6b |.Z.6*G.....1x..k|
-00000070 52 b7 ba 1a 96 bc fa c1 a1 a9 bb 2b f5 38 89 00 |R..........+.8..|
-00000080 4d e5 78 13 4e a4 38 46 42 dc 16 14 03 03 00 01 |M.x.N.8FB.......|
-00000090 01 16 03 03 00 24 72 bd b1 13 05 73 26 c0 0b ec |.....$r....s&...|
-000000a0 e6 39 08 6a 2d 87 00 51 58 9d e3 8d da be 60 98 |.9.j-..QX.....`.|
-000000b0 0a ee 0c 96 13 f4 e5 30 90 85 |.......0..|
+00000000 16 03 03 00 86 10 00 00 82 00 80 b9 65 8d bf a7 |............e...|
+00000010 c8 4b 79 ce 6f cb 8b 13 1c ac b9 7d 66 5e e9 ba |.Ky.o......}f^..|
+00000020 1d 71 4e a9 e9 34 ae f6 64 65 90 3b d8 16 52 a2 |.qN..4..de.;..R.|
+00000030 6f f4 cb 8a 13 74 a2 ee b7 27 69 b4 41 c0 90 68 |o....t...'i.A..h|
+00000040 bc 02 69 e1 c6 48 4f 39 36 30 25 ca 4c 17 ce 83 |..i..HO960%.L...|
+00000050 9e 08 56 e3 05 49 93 9e 2e c4 fb e6 c8 01 f1 0f |..V..I..........|
+00000060 c5 70 0f 08 83 48 e9 48 ef 6e 50 8b 05 7e e5 84 |.p...H.H.nP..~..|
+00000070 25 fa 55 c7 ae 31 02 27 00 ef 3f 98 86 20 12 89 |%.U..1.'..?.. ..|
+00000080 91 59 28 b4 f7 d7 af d2 69 61 35 14 03 03 00 01 |.Y(.....ia5.....|
+00000090 01 16 03 03 00 24 e1 ef 77 60 cf 7a 44 79 74 59 |.....$..w`.zDytY|
+000000a0 ff 81 72 b9 b5 f5 97 af 60 59 78 f5 01 49 2d bb |..r.....`Yx..I-.|
+000000b0 4a ec 98 1f f5 31 f4 00 a2 f3 |J....1....|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 d4 ad ab a0 01 |..........$.....|
-00000010 1b 87 9c aa c4 27 08 b5 8c 4a 7f fc 03 df a6 d6 |.....'...J......|
-00000020 f8 6c d1 61 7c d3 1f 6d 18 c3 8d 88 5c 7b cf |.l.a|..m....\{.|
+00000000 14 03 03 00 01 01 16 03 03 00 24 52 fd a3 51 aa |..........$R..Q.|
+00000010 ee 9d 4d be 8c 08 32 f6 f7 4a a5 26 26 6c b2 5a |..M...2..J.&&l.Z|
+00000020 49 7f 31 7d 44 b1 83 67 19 4a e3 07 7d 59 34 |I.1}D..g.J..}Y4|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1a 33 a8 7a 61 46 09 7b 64 e6 aa f8 |.....3.zaF.{d...|
-00000010 8a 43 d3 a9 0c e9 2e c0 89 7c 72 fb 75 50 50 15 |.C.......|r.uPP.|
-00000020 03 03 00 16 2b b9 b5 eb f8 bd 53 20 ea 67 bc 47 |....+.....S .g.G|
-00000030 83 cf c5 6e f9 4f 9e 12 f5 1a |...n.O....|
+00000000 17 03 03 00 1a 61 73 4d 86 b2 a1 36 b2 3e b0 1d |.....asM...6.>..|
+00000010 6a b9 8a 8b 00 e0 3a d9 7e 23 c7 83 72 97 28 15 |j.....:.~#..r.(.|
+00000020 03 03 00 16 4a 8a 04 00 0a b2 75 80 20 ad 76 2a |....J.....u. .v*|
+00000030 88 16 56 e6 4a a5 c0 ea c7 0c |..V.J.....|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce
index 00d35f42905..8a9ac360582 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateOnce
@@ -1,251 +1,231 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 fa 71 0e 3c 35 |....Y...U...q.<5|
-00000010 33 cc 51 25 19 cf fe c4 ef c8 2d ec 88 75 a9 1c |3.Q%......-..u..|
-00000020 6a e4 f3 b4 3d fd 74 cc e1 71 71 20 de 14 e5 21 |j...=.t..qq ...!|
-00000030 84 17 62 62 4f 44 e7 c2 d6 00 07 d2 63 f8 b0 32 |..bbOD......c..2|
-00000040 e0 12 d3 cb 69 1f d8 ed 5d 43 89 86 c0 2f 00 00 |....i...]C.../..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 16 d2 11 2e d6 |....Y...U.......|
+00000010 62 0c 5e 5c 9b 1f d2 31 87 b3 43 3e cd 47 4f f1 |b.^\...1..C>.GO.|
+00000020 0b a9 d1 4f f1 2a 42 5d 35 e0 ce 20 f2 f3 45 4b |...O.*B]5.. ..EK|
+00000030 98 2f 80 06 49 9a c3 4f 3f 70 0d e5 9a 2a 2e ff |./..I..O?p...*..|
+00000040 34 1b 0e 30 2c 85 52 e1 84 8c 3c dc cc a8 00 00 |4..0,.R...<.....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
-00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
-00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
-000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
-000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
-000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
-000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
-000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
-000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
-00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
-00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
-00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
-00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
-00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
-00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
-00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
-00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
-00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
-00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
-000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
-000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
-000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
-000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
-000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
-000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
-00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
-00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
-00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
-00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
-00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
-00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
-00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
-00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
-00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
-00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
-000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
-000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
-000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
-000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............|
-000002e0 41 04 71 a0 a9 f0 31 52 0b a2 5f 44 b1 48 a6 dc |A.q...1R.._D.H..|
-000002f0 b7 b8 bb a3 59 13 06 46 73 37 b1 9d f6 5a 42 49 |....Y..Fs7...ZBI|
-00000300 a7 e4 3c 26 64 ed 26 41 f9 76 d5 88 ad b5 2f 12 |..<&d.&A.v..../.|
-00000310 ce 02 34 b8 85 36 ee cd a1 dc d9 d7 4b ed d2 81 |..4..6......K...|
-00000320 82 1e 04 01 00 80 86 91 0e 05 48 de 2b 45 0a 9d |..........H.+E..|
-00000330 72 33 44 73 98 f3 0e 0f 4c 0b aa c0 6b 02 34 83 |r3Ds....L...k.4.|
-00000340 0c e1 53 04 89 47 21 22 de 09 5e d0 b3 d9 8b 53 |..S..G!"..^....S|
-00000350 62 b0 bf c6 dd fe d3 ed d6 2e ac a0 64 9d a4 07 |b...........d...|
-00000360 1f a9 d5 89 5f 62 7f e0 b1 9b e2 ef 3e 36 89 70 |...._b......>6.p|
-00000370 3e 7c 0a e7 8c cb c3 a8 e0 91 d9 bd 6e 3d be 0e |>|..........n=..|
-00000380 a2 8c ab 46 1b 07 24 40 da a5 e3 0b b1 6a 9f 28 |...F..$@.....j.(|
-00000390 c7 4f e8 d0 a3 57 e1 5c f2 34 07 aa 77 28 91 a0 |.O...W.\.4..w(..|
-000003a0 7e d6 36 2c c3 1a 16 03 03 00 04 0e 00 00 00 |~.6,...........|
+00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
+000002c0 ac 0c 00 00 a8 03 00 1d 20 63 85 d4 43 2a d6 9f |........ c..C*..|
+000002d0 2f 1f 0c 73 fe dc 96 1e 51 50 a5 0d 5e fd b0 5b |/..s....QP..^..[|
+000002e0 a5 88 2a cd 1e bf c1 ec 4d 04 01 00 80 90 fc 48 |..*.....M......H|
+000002f0 53 eb 1b bc ec 39 be ae 60 4d c9 d1 49 eb 97 cf |S....9..`M..I...|
+00000300 94 53 75 30 84 35 ff 0c f6 ad 9f 24 98 70 2b d3 |.Su0.5.....$.p+.|
+00000310 45 0a 7f 25 ca a3 eb 37 5a a5 97 f1 78 8b b6 02 |E..%...7Z...x...|
+00000320 92 f9 12 9e 90 52 36 0e 40 15 76 de 37 02 c5 22 |.....R6.@.v.7.."|
+00000330 44 8f a4 fc f9 ac 88 88 ad 0c 9b f6 0e d6 9f f3 |D...............|
+00000340 68 cb f1 41 dd 2d c2 71 b6 43 36 12 d2 35 1c 9a |h..A.-.q.C6..5..|
+00000350 a9 72 ea af a9 9e 77 19 16 86 be 3e ec 5f 5a 53 |.r....w....>._ZS|
+00000360 f8 38 27 7f 08 2a ae 68 e0 17 31 df 9b 16 03 03 |.8'..*.h..1.....|
+00000370 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 53 c5 |.....(........S.|
-00000060 60 30 29 1d 8a 38 57 f3 6d d1 f4 e1 ec 3e 79 d1 |`0)..8W.m....>y.|
-00000070 79 d3 b8 7f 4e 71 41 d6 72 fa c0 cd 53 92 |y...NqA.r...S.|
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 20 b1 f2 9a ca 02 d3 ac 26 f5 32 03 |.... .......&.2.|
+00000040 4c b6 de cb f2 a3 11 19 eb c3 e0 e9 3b 8e 99 7d |L...........;..}|
+00000050 c2 f3 d0 6d 4d |...mM|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 86 be df d2 27 |..........(....'|
-00000010 8b 37 77 eb 0b e4 6e 38 5c 27 56 48 bb b5 f2 be |.7w...n8\'VH....|
-00000020 43 e5 f7 32 d2 d3 a1 d7 4e 6a 3c 76 17 94 c1 b0 |C..2....Nj<v....|
-00000030 06 af 67 |..g|
+00000000 14 03 03 00 01 01 16 03 03 00 20 c5 d4 b1 e2 0f |.......... .....|
+00000010 37 ad d5 c1 1a 6c 7f da 5f 25 e3 bd 20 1d 6e 58 |7....l.._%.. .nX|
+00000020 27 7a 07 55 76 11 76 72 1b 28 9e |'z.Uv.vr.(.|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 17 22 06 |..............".|
-00000010 f7 50 b5 6f 65 e0 dd f9 b6 bc 50 b7 91 c9 54 5c |.P.oe.....P...T\|
-00000020 4e 2f cc |N/.|
+00000000 17 03 03 00 16 3d 89 e4 a6 38 75 31 c2 08 3d 86 |.....=...8u1..=.|
+00000010 45 ed 8d c4 49 c4 da 54 3b 8f e3 |E...I..T;..|
>>> Flow 6 (server to client)
-00000000 16 03 03 00 1c 86 be df d2 27 8b 37 78 c8 e7 d6 |.........'.7x...|
-00000010 4b e4 60 9e 4c b0 28 79 d9 7a 78 58 d8 27 76 18 |K.`.L.(y.zxX.'v.|
-00000020 a3 |.|
+00000000 16 03 03 00 14 aa 85 e4 64 46 2f 8e dc 89 3e ef |........dF/...>.|
+00000010 6d 9e 1a af 53 3b a0 81 c2 |m...S;...|
>>> Flow 7 (client to server)
-00000000 16 03 03 00 a9 00 00 00 00 00 00 00 02 a7 17 56 |...............V|
-00000010 8e ea 2e fc 76 06 40 b2 fa 10 71 62 68 b9 14 e6 |....v.@...qbh...|
-00000020 09 6d 63 86 d1 6b 87 3a c4 84 15 77 68 f8 85 ec |.mc..k.:...wh...|
-00000030 55 49 3c c5 c1 be 24 85 0c 38 4b 66 a8 5f 33 f9 |UI<...$..8Kf._3.|
-00000040 a3 e5 d1 36 fd 25 ba 9d 54 1f 4c df 66 09 a7 08 |...6.%..T.L.f...|
-00000050 8d 7c a4 7e d4 5d c2 11 77 7b 48 7a 32 f7 88 0a |.|.~.]..w{Hz2...|
-00000060 51 5f 6a 26 e2 11 88 01 5b b6 8e 6a aa 18 79 85 |Q_j&....[..j..y.|
-00000070 6a 0e 31 1f 33 5e 34 fd e9 1c 84 7c ea 6c 78 5d |j.1.3^4....|.lx]|
-00000080 0e d2 df c0 8c 92 3d 48 fc 9e 47 18 2a a7 1e e3 |......=H..G.*...|
-00000090 9b 89 6f 30 d0 fd 0a cd 4c b9 d9 89 b6 72 53 54 |..o0....L....rST|
-000000a0 3e 02 c3 d0 68 b0 4e 40 06 86 cd 8e 87 53 |>...h.N@.....S|
+00000000 16 03 03 00 ad c3 12 d1 1a b2 88 da c1 0b 5a 32 |..............Z2|
+00000010 cf 05 35 53 ce 5d d8 42 cd 99 7e e7 9f 62 b8 35 |..5S.].B..~..b.5|
+00000020 9e f5 b5 a6 15 fd 82 26 9b 6a fe 3b 8e c0 43 27 |.......&.j.;..C'|
+00000030 1c 56 37 d1 6f d9 2c a6 a8 e8 b4 50 64 80 ae 5c |.V7.o.,....Pd..\|
+00000040 ed eb a6 58 58 52 cf 32 de 1d be 80 69 63 38 a6 |...XXR.2....ic8.|
+00000050 12 4e 11 9b 50 aa 4b 10 f7 ad 6f 5b 08 c6 cc bd |.N..P.K...o[....|
+00000060 94 42 64 90 c7 33 58 65 18 c5 a7 66 ce dd 83 8b |.Bd..3Xe...f....|
+00000070 b0 15 8a 61 26 c7 eb 15 4b 6c 0b 15 45 33 2a 01 |...a&...Kl..E3*.|
+00000080 ea 13 5a 20 52 16 15 a0 70 8f 86 dc 28 50 bb e4 |..Z R...p...(P..|
+00000090 9d 01 f4 c9 7f 27 5a 54 3f 42 34 c9 5c 04 3f a3 |.....'ZT?B4.\.?.|
+000000a0 6a 5c a1 3f 03 7c fc 57 94 9b 3e 76 65 bf 78 40 |j\.?.|.W..>ve.x@|
+000000b0 b1 4f |.O|
>>> Flow 8 (server to client)
-00000000 16 03 03 00 89 86 be df d2 27 8b 37 79 29 01 95 |.........'.7y)..|
-00000010 8c 13 0f f0 6e 8b 00 0c 1e 1a 36 73 b6 96 ad e1 |....n.....6s....|
-00000020 40 80 6d 68 f3 41 a9 a1 85 ca 86 81 73 6c fc 49 |@.mh.A......sl.I|
-00000030 b4 61 76 27 0f cd 22 5f 7e a7 c1 e3 13 f6 2e da |.av'.."_~.......|
-00000040 1a 15 57 1a f1 b0 be 6d 55 44 78 95 62 82 ff 6e |..W....mUDx.b..n|
-00000050 bb 70 ea 24 2c bf e2 14 48 3a 07 9a 30 3a a8 88 |.p.$,...H:..0:..|
-00000060 8b d6 b4 62 28 cb 30 94 54 f6 9c 15 34 e9 c4 d2 |...b(.0.T...4...|
-00000070 e3 42 cf 79 1f 96 34 f3 4c 9f f2 df 6e 70 4f cd |.B.y..4.L...npO.|
-00000080 68 ae e2 2c d5 b7 f3 37 86 0a f5 7c af 32 16 03 |h..,...7...|.2..|
-00000090 03 02 89 86 be df d2 27 8b 37 7a 66 a9 20 cf 95 |.......'.7zf. ..|
-000000a0 d1 c9 3c c6 bc 53 16 01 e2 78 7e 2b 4d 45 20 d8 |..<..S...x~+ME .|
-000000b0 be da 93 9f 61 0b 34 25 f8 42 aa 0e b7 c5 a7 7a |....a.4%.B.....z|
-000000c0 99 23 b5 a5 0b 39 37 48 2d 66 21 8a bd 41 11 e5 |.#...97H-f!..A..|
-000000d0 79 5f 5d c1 9b 4f c2 0c fc a4 b9 ad 82 7e 7e 5b |y_]..O.......~~[|
-000000e0 f6 95 46 eb b2 9e 9c 2d 58 7e c7 90 2c c4 7f 1c |..F....-X~..,...|
-000000f0 cf 32 86 37 ec ab 60 71 ee 82 2b a2 95 61 8f 31 |.2.7..`q..+..a.1|
-00000100 99 2d c7 f4 5f 29 e8 b6 c3 f4 81 4f 2c b6 2c 67 |.-.._).....O,.,g|
-00000110 70 e5 cf d1 00 77 34 28 dc 61 cf e1 78 10 5e 64 |p....w4(.a..x.^d|
-00000120 17 f7 2b 3e 74 2c 8f 42 d5 a8 c2 4e 11 48 0f 0a |..+>t,.B...N.H..|
-00000130 3f 8a ea 0f 37 f5 da 8f 7f 7c 61 b3 98 d9 69 80 |?...7....|a...i.|
-00000140 b5 1e c6 5c 01 ff e3 8e 45 a1 7a cb ee ea 12 d3 |...\....E.z.....|
-00000150 d7 56 2e 33 8c 55 a5 94 84 f7 a1 a4 fa f3 71 f4 |.V.3.U........q.|
-00000160 a3 15 f0 7e 44 c7 32 65 86 39 93 b7 df ab 6b 94 |...~D.2e.9....k.|
-00000170 df 6d d8 31 72 ba d9 7b b6 8a 68 b1 c8 da e1 a0 |.m.1r..{..h.....|
-00000180 4f 0f 06 6a 52 78 6e a1 57 2f 2b 6b 10 5b c1 57 |O..jRxn.W/+k.[.W|
-00000190 d0 92 23 bf dc 95 f1 83 66 ce 6f ef c5 22 22 24 |..#.....f.o..""$|
-000001a0 80 bd 2f 38 ff de ec 86 8b ad 81 4e fe 31 65 54 |../8.......N.1eT|
-000001b0 19 94 ce 99 0f 6d 5b 1b 53 ba ad 65 a6 6a f6 27 |.....m[.S..e.j.'|
-000001c0 ba e0 b7 a9 8b 80 18 71 67 f7 6c 35 5f 69 c2 19 |.......qg.l5_i..|
-000001d0 08 27 03 45 5a 58 49 27 cf ec bf 18 e7 60 64 2b |.'.EZXI'.....`d+|
-000001e0 47 9e 07 1a 49 ef 90 20 c7 f7 69 5c 46 92 ae 65 |G...I.. ..i\F..e|
-000001f0 fa 45 9f 3b a3 4e ed cb d9 1f d9 26 18 1e bb 58 |.E.;.N.....&...X|
-00000200 16 cd a5 00 df 65 73 39 82 fd 98 29 de 45 8f 70 |.....es9...).E.p|
-00000210 56 e3 c6 0b 18 71 09 92 0e 69 4e b8 e7 23 4f 70 |V....q...iN..#Op|
-00000220 7a 89 06 c7 78 05 04 31 7f 77 5c 68 74 f0 45 76 |z...x..1.w\ht.Ev|
-00000230 e2 56 b2 de 34 e6 79 64 49 9a a8 3a b7 5b 4a d3 |.V..4.ydI..:.[J.|
-00000240 5e 6d 0b f3 fb 6d 0c 2f 61 d0 71 f4 0d ed 60 2f |^m...m./a.q...`/|
-00000250 61 80 c9 9b b9 e5 89 f2 64 88 52 d6 d3 aa 72 6b |a.......d.R...rk|
-00000260 66 18 ae e9 df 20 40 15 b5 73 ba ac 50 b1 27 99 |f.... @..s..P.'.|
-00000270 b3 17 97 56 0b 7d 25 8a 64 80 42 5c c8 b8 d5 98 |...V.}%.d.B\....|
-00000280 28 16 2b ce 45 65 3d fc d8 c6 91 31 c2 d4 09 a3 |(.+.Ee=....1....|
-00000290 cf 92 85 63 36 cb e2 da a3 66 fb 08 c9 bc 12 23 |...c6....f.....#|
-000002a0 c8 88 7d 46 22 98 40 01 bf fb 58 84 f2 8f ad 83 |..}F".@...X.....|
-000002b0 ed 79 b4 a8 3d e5 92 b7 b8 e1 d0 50 aa be 22 9c |.y..=......P..".|
-000002c0 9c cb dc bd 65 59 41 3e 6f 53 89 02 30 b1 88 ca |....eYA>oS..0...|
-000002d0 06 6d 8e b2 a6 75 6a d8 5a 19 65 de 27 c3 bf 70 |.m...uj.Z.e.'..p|
-000002e0 49 64 13 2d 19 5d 7a ec 91 a7 f6 82 92 7d e3 7e |Id.-.]z......}.~|
-000002f0 d6 65 5b d4 eb ed 58 d7 cd 41 a2 b9 d3 9e e4 a0 |.e[...X..A......|
-00000300 92 bf 88 4f 0e 59 74 66 86 db 72 11 18 ad 81 24 |...O.Ytf..r....$|
-00000310 6e 43 38 24 23 fb db af 92 d8 1a 2d 16 03 03 00 |nC8$#......-....|
-00000320 e5 86 be df d2 27 8b 37 7b ce 01 b6 78 47 7d 3a |.....'.7{...xG}:|
-00000330 ad 2e 03 8e 78 03 61 da 55 0e d4 fa 87 9d 20 25 |....x.a.U..... %|
-00000340 73 1f 3b 87 7b 02 c1 a3 af ce d5 b9 9e 29 91 1b |s.;.{........)..|
-00000350 58 13 c9 bc 96 95 88 f8 67 43 03 25 a3 be 5e a6 |X.......gC.%..^.|
-00000360 1d ee 6e 70 4c b5 66 48 3d 7d 1a 58 8e 10 c0 68 |..npL.fH=}.X...h|
-00000370 6b d8 f1 dd 83 c5 d3 c8 81 c5 6d 72 68 50 41 6f |k.........mrhPAo|
-00000380 f6 20 13 f8 72 fa 82 9a 25 e4 07 10 df b7 39 90 |. ..r...%.....9.|
-00000390 6a d7 d2 d7 a1 1c 31 4e b6 7c 00 bc 4d b1 a1 ff |j.....1N.|..M...|
-000003a0 d0 ae 42 b1 2d 3e 8b c9 43 f4 fa fc d4 71 8f 74 |..B.->..C....q.t|
-000003b0 37 23 1b bb 34 4e b6 e4 fe f1 1b ea da 08 e4 12 |7#..4N..........|
-000003c0 fd 50 23 f9 8a 2d 92 eb f5 2b fc b4 e1 35 87 74 |.P#..-...+...5.t|
-000003d0 44 79 0b df 6a 14 eb 20 17 ab 5b 12 a7 19 a4 4e |Dy..j.. ..[....N|
-000003e0 94 70 93 57 2d bd c2 54 88 fb 19 b7 82 28 ab db |.p.W-..T.....(..|
-000003f0 ca a9 19 5d 36 1b d6 fc 7d 41 2c 5b 76 ec 90 72 |...]6...}A,[v..r|
-00000400 47 5b c4 ae 59 a6 16 03 03 00 46 86 be df d2 27 |G[..Y.....F....'|
-00000410 8b 37 7c ed db 59 c6 0b 4e 52 c9 bc 7a 81 ed 20 |.7|..Y..NR..z.. |
-00000420 00 55 02 76 15 49 9b 0b f2 81 c2 f7 25 51 61 9d |.U.v.I......%Qa.|
-00000430 48 e3 d2 6f 08 ea 0c 9b 26 cc 3b 52 58 ef a0 1f |H..o....&.;RX...|
-00000440 09 c3 ca e8 c2 6c 13 86 b1 94 04 f1 65 e2 de 4c |.....l......e..L|
-00000450 7c |||
+00000000 16 03 03 00 81 33 ef 78 c8 2d 94 4b e3 b8 ea eb |.....3.x.-.K....|
+00000010 67 1e 6c 10 98 25 5f df ce 46 4c 13 77 ec d1 b1 |g.l..%_..FL.w...|
+00000020 e9 e2 c9 b0 de 9c ce 40 d0 d9 6f a5 fb a6 69 1f |.......@..o...i.|
+00000030 9f 53 68 6c ab f8 f0 10 4a c9 43 f0 ad 61 59 01 |.Shl....J.C..aY.|
+00000040 b2 90 97 9e cf 62 64 a5 46 b2 27 2f 1e b8 33 24 |.....bd.F.'/..3$|
+00000050 ed 7e 6b 5a dd 45 4d 00 61 a3 7e 22 5e bc 02 af |.~kZ.EM.a.~"^...|
+00000060 5a a0 73 fb c5 1c 0f 11 f6 70 5f cc 9e 1c fa 3c |Z.s......p_....<|
+00000070 13 0d 8b 03 4c 3b d5 5a 02 7b 95 64 ae cb 2f 50 |....L;.Z.{.d../P|
+00000080 e7 e1 32 13 72 96 16 03 03 02 69 f0 60 6a b8 fb |..2.r.....i.`j..|
+00000090 50 6e f9 f2 65 d0 73 90 f7 55 0d bc 3a 66 72 32 |Pn..e.s..U..:fr2|
+000000a0 b7 32 ad 1d de 18 04 90 55 70 2d b8 c9 3f 4b 2f |.2......Up-..?K/|
+000000b0 37 98 1c 4e c1 78 c1 ed 1f e2 bf 50 78 40 04 10 |7..N.x.....Px@..|
+000000c0 b8 55 48 29 26 b0 a4 4d ea aa 45 65 b4 21 93 ed |.UH)&..M..Ee.!..|
+000000d0 49 4c 1d d9 77 33 38 2e 14 92 b4 e3 06 ce fe 51 |IL..w38........Q|
+000000e0 6a 19 1c aa e9 a6 7d fa 45 86 66 1a 6e bb 01 01 |j.....}.E.f.n...|
+000000f0 82 86 89 86 81 ce 0a 93 1a b2 f1 90 71 7a 43 fa |............qzC.|
+00000100 b1 03 24 75 a1 48 f8 ee a0 b4 c0 18 ff 81 95 2a |..$u.H.........*|
+00000110 aa 74 87 39 da 23 ba ab 33 6b 63 ee df 2b f1 d1 |.t.9.#..3kc..+..|
+00000120 1a 9a 4a 0d ef de 68 13 28 81 49 d5 c6 08 57 a9 |..J...h.(.I...W.|
+00000130 d7 5e 56 a4 ec 81 42 de 28 39 51 7d 3a 66 cf a7 |.^V...B.(9Q}:f..|
+00000140 f7 81 7a b2 a7 09 b3 24 a6 b0 a5 cc 96 24 30 b2 |..z....$.....$0.|
+00000150 5b 94 1b ef 70 dd 7f bc 63 2f 7b bc 80 70 9e 9f |[...p...c/{..p..|
+00000160 01 c9 20 ab 35 53 7c 3b d6 70 d9 1d 9a f6 e8 76 |.. .5S|;.p.....v|
+00000170 f5 46 f8 b1 10 46 a9 eb da 7b 80 cc 74 18 f9 30 |.F...F...{..t..0|
+00000180 56 1a cb 4e 60 2a b3 9f 35 fe a9 b8 b8 76 02 a7 |V..N`*..5....v..|
+00000190 4e f9 43 c9 52 70 6a fd 9c 3e dd c4 3f 28 08 19 |N.C.Rpj..>..?(..|
+000001a0 28 ed f9 44 e3 d1 b9 53 7e b7 cd 1b e9 11 c8 9f |(..D...S~.......|
+000001b0 35 ed ab e3 5e 26 e8 49 7a 13 5c 20 9a b7 a0 95 |5...^&.Iz.\ ....|
+000001c0 60 0f 54 68 5c a8 c9 1d 37 0b 9f f6 61 3b fe 4c |`.Th\...7...a;.L|
+000001d0 dc 4f 11 98 0c 7a b7 32 0b 50 e2 cd a7 59 bf 05 |.O...z.2.P...Y..|
+000001e0 a2 8a 51 33 23 ab 99 49 23 97 42 3b 0f 1c 39 b1 |..Q3#..I#.B;..9.|
+000001f0 43 c4 01 aa f9 f8 54 d7 2c b4 ef 33 f3 05 13 d0 |C.....T.,..3....|
+00000200 8d 81 06 23 d3 38 cb 3a 6b 37 f0 4d 1f be ed 0c |...#.8.:k7.M....|
+00000210 b7 58 00 3a bd 74 02 a4 f4 b4 fc fd b8 fa 89 15 |.X.:.t..........|
+00000220 01 46 49 52 47 f1 4c 94 ee de 00 a1 25 aa b4 9b |.FIRG.L.....%...|
+00000230 f6 b4 23 a1 0d fd 00 5a de 45 38 ee 69 17 6f c3 |..#....Z.E8.i.o.|
+00000240 0b ed c5 3b b1 7d b1 2c a4 8f ed 30 44 9a 0b 51 |...;.}.,...0D..Q|
+00000250 34 12 cc 6a 09 e4 74 ec 11 94 4b ba ce 72 93 64 |4..j..t...K..r.d|
+00000260 07 c8 ff 78 6e 1a bd 5e 26 15 a7 e8 72 90 71 a9 |...xn..^&...r.q.|
+00000270 0a bb cf 25 40 1d 20 a7 d7 b3 46 4b 53 6c c2 50 |...%@. ...FKSl.P|
+00000280 c7 7b 58 e1 3c df 6d db 28 71 15 f9 84 b7 ad b0 |.{X.<.m.(q......|
+00000290 9f e9 7a 08 5d 85 7a dd bc c0 62 2e 6a d0 63 6a |..z.].z...b.j.cj|
+000002a0 e2 46 6b 80 68 cf e5 a7 9e 60 42 8a 17 54 9c ec |.Fk.h....`B..T..|
+000002b0 80 9b 81 80 7e 6f 33 8c d1 be 95 30 f2 a9 19 f8 |....~o3....0....|
+000002c0 36 2c 8e 89 c2 5a b4 04 2e 12 05 21 3b 4f 42 26 |6,...Z.....!;OB&|
+000002d0 d1 98 11 f4 17 c2 a3 06 54 37 31 8e ca 9b 07 62 |........T71....b|
+000002e0 79 95 b8 fd 49 aa 60 5b 03 7d 60 50 b6 2f 3b 0a |y...I.`[.}`P./;.|
+000002f0 5d c2 9f 92 16 03 03 00 bc ba f6 73 85 34 20 c4 |]..........s.4 .|
+00000300 b3 a4 15 01 fe 37 b3 b4 57 a5 b5 26 0c 64 2b 3e |.....7..W..&.d+>|
+00000310 07 d3 e4 59 a8 64 3f fd 15 24 24 70 61 77 9b 96 |...Y.d?..$$paw..|
+00000320 c6 4b 79 2e a8 a7 c4 ac 5e cd 6e 8f 30 e5 3f f8 |.Ky.....^.n.0.?.|
+00000330 08 22 cb de 5f 8c b8 dc 07 4b 79 ec 41 41 20 20 |.".._....Ky.AA |
+00000340 02 f6 4e 98 a3 5e 38 e2 5a d9 4a 2d 2e 3b 29 13 |..N..^8.Z.J-.;).|
+00000350 26 dc 4e eb a5 5e a3 b6 6f 16 75 b3 9e 63 4e 8e |&.N..^..o.u..cN.|
+00000360 00 c1 46 30 fc 25 f9 05 86 ed 00 87 f2 6b 5c 18 |..F0.%.......k\.|
+00000370 69 e5 5c 32 9e 15 d2 47 9e 0e d8 c1 7a 9d 45 7a |i.\2...G....z.Ez|
+00000380 76 4a ef 8d b5 60 7d 4d fa 99 8f c5 58 18 ad a2 |vJ...`}M....X...|
+00000390 93 c1 36 85 39 73 e1 7b 46 be 69 de 88 fa 68 8e |..6.9s.{F.i...h.|
+000003a0 be d1 48 bc 7b 29 2a 21 ba 60 60 58 51 c2 03 66 |..H.{)*!.``XQ..f|
+000003b0 51 9a 4e 70 06 16 03 03 00 3a c5 ed 8d 5d b9 c0 |Q.Np.....:...]..|
+000003c0 a2 07 15 c3 ef 76 ff fb ca f6 b6 4b ab a5 7a 80 |.....v.....K..z.|
+000003d0 a9 2e 43 d0 d2 f1 d9 96 61 ff 43 59 3d d1 82 57 |..C.....a.CY=..W|
+000003e0 68 d7 c8 3a 5f 86 4a 2e 00 8f 3d 0e 73 49 c6 4a |h..:_.J...=.sI.J|
+000003f0 81 4e ec e2 16 03 03 00 14 d5 5f c3 d2 9c 13 36 |.N........_....6|
+00000400 cb 22 23 3d e4 03 5b b9 26 66 cf 79 7c |."#=..[.&f.y||
>>> Flow 9 (client to server)
-00000000 16 03 03 02 89 00 00 00 00 00 00 00 03 3c 0f 09 |.............<..|
-00000010 9e dc 39 b8 be ab ca 53 74 05 93 12 a4 e7 bb 56 |..9....St......V|
-00000020 9f e1 9f 2a 09 7d e1 74 89 ee b3 99 3c 91 c6 38 |...*.}.t....<..8|
-00000030 7e 0c 5e 2d 1f 7d bd cd 1a d1 16 ab af 94 08 c6 |~.^-.}..........|
-00000040 74 e3 16 12 0e 9b bc 91 95 6d 01 fd 10 00 12 c6 |t........m......|
-00000050 03 96 92 08 df 50 89 ba 5c 25 ce 31 d8 b1 84 8a |.....P..\%.1....|
-00000060 7d 6c cf 7f e6 9a e4 08 17 cc b8 f2 c9 8f e8 4b |}l.............K|
-00000070 ab 44 4f e9 63 8c 93 71 b1 70 4a f4 29 5f ef 45 |.DO.c..q.pJ.)_.E|
-00000080 68 e1 0e 31 a0 4c 96 8c 65 03 f3 48 24 48 d4 d7 |h..1.L..e..H$H..|
-00000090 93 d1 17 39 8d 97 e8 d8 59 08 4b 46 82 cf a3 99 |...9....Y.KF....|
-000000a0 55 36 65 a9 d8 df db d5 65 78 52 38 c2 2a 1e ec |U6e.....exR8.*..|
-000000b0 65 6a f5 d5 4c 81 0c f6 e6 77 b2 68 d4 6c 32 05 |ej..L....w.h.l2.|
-000000c0 ef f4 ee 0b e1 83 d0 3a cf a0 06 f2 cc 61 62 5e |.......:.....ab^|
-000000d0 fa b4 19 c7 e2 99 c1 cf 02 a1 01 3d 6a e0 be 9f |...........=j...|
-000000e0 82 cd e5 c8 ac e2 3e 6d 0f 60 a4 e9 9b ca cf c9 |......>m.`......|
-000000f0 c1 fe 2d ef 29 ed f9 c3 11 03 9f 76 66 71 ef 24 |..-.)......vfq.$|
-00000100 5f d3 29 aa 6a e1 0c b1 58 7a f3 df 92 e8 61 e2 |_.).j...Xz....a.|
-00000110 41 43 ad 9d 55 a0 b0 a3 20 8d 2c 8f 34 e6 ab d3 |AC..U... .,.4...|
-00000120 37 80 9e cb 27 91 69 0a ba 33 05 a1 7f 4d 7f 63 |7...'.i..3...M.c|
-00000130 ed 6a c1 72 43 ec 6a 6c ac b7 87 bb 81 6e 06 fa |.j.rC.jl.....n..|
-00000140 68 7a c9 33 28 59 ed 74 87 a1 6a 24 06 02 c0 21 |hz.3(Y.t..j$...!|
-00000150 71 b0 27 f9 6e b3 7e 30 e9 e0 df c2 5d 63 2a dd |q.'.n.~0....]c*.|
-00000160 9d e9 9c 4f 47 66 68 7e e4 8c 87 b7 f0 a8 3d b8 |...OGfh~......=.|
-00000170 36 39 3e 4c 9f 55 e7 bb c7 3e 34 36 54 19 41 33 |69>L.U...>46T.A3|
-00000180 61 e6 9a ae c6 91 1d fa 2d 8c 45 95 5f 95 36 79 |a.......-.E._.6y|
-00000190 e9 59 7e 81 cd 7e 9e 01 fe 85 eb c8 ed 4e 93 c6 |.Y~..~.......N..|
-000001a0 53 76 2d 5c 72 50 22 16 04 15 c2 cf 19 07 e6 73 |Sv-\rP"........s|
-000001b0 74 d0 7b bb 68 c3 29 39 bc ab 1b 4c c9 5a 36 73 |t.{.h.)9...L.Z6s|
-000001c0 55 47 7a c8 4a a7 45 fe f3 a9 94 6e ea ea cc 7d |UGz.J.E....n...}|
-000001d0 d1 de f4 82 4c 14 84 f0 58 09 56 25 83 7a 23 71 |....L...X.V%.z#q|
-000001e0 a1 63 e3 4e 13 78 68 41 a1 9a 55 ec 9e 37 ee c2 |.c.N.xhA..U..7..|
-000001f0 7d 3f 8f 91 00 30 f2 ca 7b 13 b7 e7 fe 85 c5 aa |}?...0..{.......|
-00000200 5e e3 97 2c cb d5 13 1e 83 3d c9 2a b1 21 f1 58 |^..,.....=.*.!.X|
-00000210 7d 09 32 31 d6 fd 89 26 ff 72 3c f7 c4 fe 99 33 |}.21...&.r<....3|
-00000220 41 82 76 05 b9 14 b1 b0 3c 41 02 74 a8 1d dd 80 |A.v.....<A.t....|
-00000230 38 67 25 01 39 f7 36 fa e4 1c 7d 2f c9 7e 21 0a |8g%.9.6...}/.~!.|
-00000240 30 77 1e ff fc 8a 31 ac ee 91 f0 2c b1 9a b7 5e |0w....1....,...^|
-00000250 26 d0 7a 9d b4 9e 53 6b dd a6 5e 7b f0 45 99 9b |&.z...Sk..^{.E..|
-00000260 2b 69 90 d4 dd 1a d0 b5 13 90 11 ac 01 f0 2f 94 |+i............/.|
-00000270 5b 59 7e 7a 40 22 3a b0 d4 24 92 7d 94 bf 34 91 |[Y~z@":..$.}..4.|
-00000280 f6 b9 cc c9 e5 de d3 67 6d 83 97 ee 8f 48 16 03 |.......gm....H..|
-00000290 03 00 5e 00 00 00 00 00 00 00 04 dc 6f 41 98 23 |..^.........oA.#|
-000002a0 d7 70 80 24 74 46 c8 45 e1 2f 43 1d b8 66 4d 0a |.p.$tF.E./C..fM.|
-000002b0 03 0e d6 01 8b 92 f7 76 c1 2c 32 6c 65 60 da ab |.......v.,2le`..|
-000002c0 0b 12 6d 30 1c cf de e7 ec a7 12 f9 df 6c b4 42 |..m0.........l.B|
-000002d0 e7 d9 6e 6e f3 1c 10 ee 39 47 7f ec 7c ec 68 68 |..nn....9G..|.hh|
-000002e0 e8 b2 70 a2 67 61 e0 b3 68 b5 91 9f 1a e0 c5 af |..p.ga..h.......|
-000002f0 e3 16 03 03 00 a0 00 00 00 00 00 00 00 05 6b 56 |..............kV|
-00000300 3d 5e 4e f1 2c 30 e2 91 24 5c b1 5f d3 7d 3e dc |=^N.,0..$\._.}>.|
-00000310 ba 98 e1 9f 72 98 2b 0e 11 07 d1 ea 14 d5 73 25 |....r.+.......s%|
-00000320 d2 cf 8e bc a5 ea 93 a7 32 ab 94 83 1e ea c5 62 |........2......b|
-00000330 06 79 bb ab 4c a0 cf fb 51 3b 7b f0 11 5e ae 50 |.y..L...Q;{..^.P|
-00000340 23 cb ff 86 03 3d a5 66 b9 c4 35 c2 12 f2 98 85 |#....=.f..5.....|
-00000350 77 ba af 3b d5 dd f2 cd 58 09 29 26 08 cd 4a ed |w..;....X.)&..J.|
-00000360 ac af 57 ab 27 1a 40 ef 10 57 d1 ad 06 34 be ed |..W.'.@..W...4..|
-00000370 fe 88 1d 09 4a 81 8a da e7 ef fa 27 71 ab 2b 3f |....J......'q.+?|
-00000380 21 91 5f 1a dc 50 a4 f0 58 bd aa af 75 4e 25 2a |!._..P..X...uN%*|
-00000390 2c 55 e5 57 c6 ab 14 03 03 00 19 00 00 00 00 00 |,U.W............|
-000003a0 00 00 06 5d 8a 3e 8e 55 e4 9d c0 6a de 91 c6 96 |...].>.U...j....|
-000003b0 6e 17 54 a5 16 03 03 00 28 00 00 00 00 00 00 00 |n.T.....(.......|
-000003c0 00 d5 45 5d 11 af e2 b6 f1 a8 e5 ed 58 80 54 ce |..E]........X.T.|
-000003d0 b3 db dc 97 b3 86 c0 83 f9 3b 7c b5 ad 21 f8 cf |.........;|..!..|
-000003e0 9a |.|
+00000000 16 03 03 02 69 15 0b 29 0e 27 a9 4b 52 4d 0a 77 |....i..).'.KRM.w|
+00000010 b8 3a 40 95 84 a7 7a 8d b1 6b 90 61 94 3a e4 06 |.:@...z..k.a.:..|
+00000020 20 6f 88 40 8a 8c c2 4e dc 3a 01 39 c2 11 5a 9b | o.@...N.:.9..Z.|
+00000030 28 92 bc 72 04 a3 60 c3 42 c0 b8 dd f3 41 40 be |(..r..`.B....A@.|
+00000040 6d 51 5b b8 db 75 63 3d 4f 2a cf f5 04 3d 53 be |mQ[..uc=O*...=S.|
+00000050 47 f1 ae be 0a 97 5d 2c df 55 5d dd 9a f6 0e 40 |G.....],.U]....@|
+00000060 59 02 91 d8 55 c9 3b e6 84 9c 8d 40 af 29 77 59 |Y...U.;....@.)wY|
+00000070 15 0c 83 dd ec c7 e2 16 85 d8 6e e7 4e c5 a5 b1 |..........n.N...|
+00000080 8b 4b 46 3e 62 7c ff 27 1b 37 b7 5c 05 32 30 fb |.KF>b|.'.7.\.20.|
+00000090 c1 cc 1d 13 1f 09 db 57 6a 70 2b 9f a7 25 9b 75 |.......Wjp+..%.u|
+000000a0 d3 62 20 45 d1 2f 28 c0 d7 84 d6 2e b3 6d 4a c3 |.b E./(......mJ.|
+000000b0 46 0d 92 32 87 65 dd b8 98 68 1a 52 0a df be b3 |F..2.e...h.R....|
+000000c0 09 bc 63 bb a3 da f7 52 5a 81 53 9a e0 ff bb 06 |..c....RZ.S.....|
+000000d0 7f 81 f8 ea 02 bb 3b 96 7b 0f 84 a5 4d 17 3a 2a |......;.{...M.:*|
+000000e0 20 e9 21 70 b2 ab 8a 55 31 4b 1b 60 52 7f a8 39 | .!p...U1K.`R..9|
+000000f0 5a 0f 0b 00 4e eb 01 0c a6 d8 f0 30 2b a3 6f 7b |Z...N......0+.o{|
+00000100 99 82 90 9e 4c c8 03 1c 0e 85 55 bc 2d 42 28 66 |....L.....U.-B(f|
+00000110 35 c3 1e 08 70 d0 45 05 5b 2e 00 fc 9a f1 44 0e |5...p.E.[.....D.|
+00000120 cb 91 ce b8 0f 2a 9f 5a 18 a8 ca 38 ff 2a ab 11 |.....*.Z...8.*..|
+00000130 57 a5 03 2f 3e 92 21 77 df dc 85 e7 fd d4 7e d0 |W../>.!w......~.|
+00000140 d9 6e ef 99 66 5d a8 f5 9a d3 c3 0f 0c 98 cd fe |.n..f]..........|
+00000150 5a 46 79 77 c9 28 fb 5e 3e c0 d5 b3 db 98 79 9d |ZFyw.(.^>.....y.|
+00000160 d4 20 a5 ad 25 d8 3b 39 35 60 fd 21 e0 eb 86 be |. ..%.;95`.!....|
+00000170 8f 65 72 a2 d3 91 4c 25 70 31 b1 02 29 17 da e0 |.er...L%p1..)...|
+00000180 9f 7d 4e 5f 1a 7b 93 09 4c 84 5b 40 f8 3c 98 36 |.}N_.{..L.[@.<.6|
+00000190 9b 14 43 db 43 11 0a e2 9a 8b 73 96 a3 7b 4d 67 |..C.C.....s..{Mg|
+000001a0 d7 35 a6 85 40 6d 45 0e 9d 47 43 96 b8 64 d4 d7 |.5..@mE..GC..d..|
+000001b0 d1 28 c8 32 7e ab d5 11 ad b4 a7 9c c9 ab c5 96 |.(.2~...........|
+000001c0 72 69 1a db 42 06 8e 03 d0 70 f9 7a 75 56 53 49 |ri..B....p.zuVSI|
+000001d0 29 e1 60 16 86 99 da 9e d6 c3 95 94 e3 e4 6c 9c |).`...........l.|
+000001e0 4f d0 5d e7 a6 23 e1 49 a5 b8 3d 41 a4 e0 8c a2 |O.]..#.I..=A....|
+000001f0 f8 35 40 4d 12 f1 0b 70 06 f5 b5 29 f8 5d 74 73 |.5@M...p...).]ts|
+00000200 32 35 11 7f 50 a3 22 5b d6 db a5 a8 9f ca db 47 |25..P."[.......G|
+00000210 b9 a8 c7 fc 16 40 ae 94 6e 6c 40 30 7a d6 9c 89 |.....@..nl@0z...|
+00000220 d7 e9 1b 6b 26 72 1f d7 c9 bc ce 6f 84 03 3d 65 |...k&r.....o..=e|
+00000230 34 f9 7b 32 54 e4 b4 72 8c e1 31 9e e5 13 50 2f |4.{2T..r..1...P/|
+00000240 ea 16 27 15 cb ec 0f 1b 21 aa dd cb 25 74 b9 4d |..'.....!...%t.M|
+00000250 36 c0 0d fe a4 99 2f 86 50 52 d0 83 e2 3f fa e7 |6...../.PR...?..|
+00000260 2d 24 b6 7a ca 7f 69 3e 7d 0b 61 df 29 3b 16 03 |-$.z..i>}.a.);..|
+00000270 03 00 35 8e 89 3d 7b 39 aa d2 21 01 6a 3d fe 4f |..5..={9..!.j=.O|
+00000280 e2 d9 e6 6d 5d 1e d3 a5 1d 3f f8 8e fb 97 3d 06 |...m]....?....=.|
+00000290 9b 68 67 45 15 3b a1 e8 e8 39 77 1a 41 77 2b c5 |.hgE.;...9w.Aw+.|
+000002a0 8c fe bd 28 7a 85 eb 7a 16 03 03 00 98 f0 ed 3c |...(z..z.......<|
+000002b0 37 3f 34 3b 35 e4 15 a8 f3 b4 b6 76 49 65 e8 26 |7?4;5......vIe.&|
+000002c0 93 4b cc b1 31 7a 4c e7 7d 80 63 60 65 9a ff 11 |.K..1zL.}.c`e...|
+000002d0 a8 c5 c4 4e c2 7a ca 95 cb 08 21 77 42 ce 70 1e |...N.z....!wB.p.|
+000002e0 bf d9 b5 6d de dc 03 67 2e 11 b5 47 c1 c0 74 6b |...m...g...G..tk|
+000002f0 b4 9d c4 de 8c d4 80 e4 99 92 31 68 09 85 00 34 |..........1h...4|
+00000300 43 cc 06 09 bc a8 6e 83 a0 fa df 6e a0 04 e9 37 |C.....n....n...7|
+00000310 b3 05 69 b9 f1 85 7f 48 27 73 d0 64 2c 33 48 1f |..i....H's.d,3H.|
+00000320 f9 7c 0a 21 1f cb 0f 4c c2 28 b0 3b 8c 9b 23 21 |.|.!...L.(.;..#!|
+00000330 f4 8c 69 b2 1d 55 35 20 b9 92 09 36 01 aa e1 e3 |..i..U5 ...6....|
+00000340 ee b7 3d 83 7b 14 03 03 00 11 40 bb bb 2e 3d 48 |..=.{.....@...=H|
+00000350 9f fa c6 0c d8 4f 45 cb 11 b3 a5 16 03 03 00 20 |.....OE........ |
+00000360 39 b7 46 30 00 68 12 c5 f5 d7 a0 85 7f ce 49 70 |9.F0.h........Ip|
+00000370 05 83 64 26 7a 0c 43 fb a9 4d bb 61 3a c3 8a 91 |..d&z.C..M.a:...|
>>> Flow 10 (server to client)
-00000000 14 03 03 00 19 86 be df d2 27 8b 37 7d 85 70 b7 |.........'.7}.p.|
-00000010 a7 98 89 36 01 b4 a8 6f cb 14 0f dd ac 08 16 03 |...6...o........|
-00000020 03 00 28 75 41 a9 ef 1c 88 59 4e 84 15 29 a4 75 |..(uA....YN..).u|
-00000030 e6 66 01 3f a1 b7 ff 69 04 b6 08 99 c9 5e 57 60 |.f.?...i.....^W`|
-00000040 ea 76 21 94 06 e4 32 95 e1 4c d7 17 03 03 00 21 |.v!...2..L.....!|
-00000050 75 41 a9 ef 1c 88 59 4f c8 5d 4e bd 42 52 ec 50 |uA....YO.]N.BR.P|
-00000060 2f 28 4f 87 da bc f0 df a8 93 14 b7 6f a0 7f a2 |/(O.........o...|
-00000070 c5 |.|
+00000000 14 03 03 00 11 d1 d7 7e 3c 5f 01 cb f8 eb af d5 |.......~<_......|
+00000010 ba 09 32 68 4b cf 16 03 03 00 20 02 f1 23 45 32 |..2hK..... ..#E2|
+00000020 60 9b 49 db 2f 3a cb 5c e4 f3 64 b1 cb ca 09 b0 |`.I./:.\..d.....|
+00000030 b3 34 a3 75 7d a5 a0 80 44 fd b7 17 03 03 00 19 |.4.u}...D.......|
+00000040 d7 c3 c4 33 e6 f2 73 d2 2c 0b 7e 0e 40 d3 8b f6 |...3..s.,.~.@...|
+00000050 47 57 13 88 be 4b 12 43 57 |GW...K.CW|
>>> Flow 11 (client to server)
-00000000 15 03 03 00 1a 00 00 00 00 00 00 00 01 92 8a f2 |................|
-00000010 9a d1 c9 1e 68 15 2d 6b 9a a7 f8 21 78 87 89 |....h.-k...!x..|
+00000000 15 03 03 00 12 3a 90 85 e8 ce 53 d1 2a 3b d6 9a |.....:....S.*;..|
+00000010 f3 61 c1 72 81 c0 03 |.a.r...|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice
index 185dc6528c9..c2f4e4aca90 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwice
@@ -1,409 +1,376 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 bb b7 b5 ee 8b |....Y...U.......|
-00000010 b7 92 40 96 01 65 93 09 a0 63 77 b3 35 74 0a 73 |..@..e...cw.5t.s|
-00000020 db e8 4a 9c d4 95 4b 2a f9 43 1e 20 d6 5a ed d1 |..J...K*.C. .Z..|
-00000030 05 f0 61 aa 45 ae 0e 92 03 87 1b a6 0a 1a 83 a1 |..a.E...........|
-00000040 bd 4f c3 81 79 e8 56 10 5d 08 7b 6d c0 2f 00 00 |.O..y.V.].{m./..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 30 5b 03 80 cf |....Y...U..0[...|
+00000010 ad 5e 69 9b da 4a de 2f 07 f3 6c 42 d7 50 99 10 |.^i..J./..lB.P..|
+00000020 80 15 dc dd d2 ef 3d 20 b9 eb bd 20 51 63 fd 9d |......= ... Qc..|
+00000030 3d b7 3e ea 4e 18 45 90 40 50 f2 f3 2b b8 00 42 |=.>.N.E.@P..+..B|
+00000040 bf 77 ae d1 ff 29 2d ca d8 c2 4e c7 cc a8 00 00 |.w...)-...N.....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
-00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
-00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
-000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
-000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
-000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
-000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
-000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
-000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
-00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
-00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
-00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
-00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
-00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
-00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
-00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
-00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
-00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
-00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
-000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
-000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
-000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
-000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
-000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
-000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
-00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
-00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
-00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
-00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
-00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
-00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
-00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
-00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
-00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
-00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
-000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
-000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
-000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
-000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............|
-000002e0 41 04 b5 fe 7d 68 cd 5a b7 bf 61 10 81 dc 92 23 |A...}h.Z..a....#|
-000002f0 d0 82 13 fb 71 6f 39 48 f9 87 f8 f7 a0 3a cd 18 |....qo9H.....:..|
-00000300 85 d7 4d 66 88 9d 39 8d 6d 53 a1 a3 0d 00 b0 0f |..Mf..9.mS......|
-00000310 14 64 1b 72 2d 89 5c 93 6f 3c ed c9 82 20 3d 2f |.d.r-.\.o<... =/|
-00000320 d0 7f 04 01 00 80 42 24 14 6e cf 78 ea 30 90 1e |......B$.n.x.0..|
-00000330 4e 99 bf ca 98 9c 2f 24 98 c2 a2 b3 f8 34 49 22 |N...../$.....4I"|
-00000340 35 16 11 03 79 3b a8 10 a3 fa d8 5e 17 9d f9 50 |5...y;.....^...P|
-00000350 0a 3b 0b b5 b2 0f 90 18 c1 f5 6f 89 84 04 e2 f0 |.;........o.....|
-00000360 b0 04 2f 3e 78 d3 de 31 9e 6e 3b b8 c7 f5 cc 4f |../>x..1.n;....O|
-00000370 4e ad fe 76 d2 6d 23 31 94 56 b1 d8 df 0d 9b c5 |N..v.m#1.V......|
-00000380 f7 9e 9c a7 2a 47 e4 c8 20 08 fc 6c d5 29 cd 36 |....*G.. ..l.).6|
-00000390 88 83 c5 59 33 6d 1f 0b f9 98 65 fa cb f7 89 2d |...Y3m....e....-|
-000003a0 90 3a 40 8a 31 7e 16 03 03 00 04 0e 00 00 00 |.:@.1~.........|
+00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
+000002c0 ac 0c 00 00 a8 03 00 1d 20 6b cd 37 6d a7 76 7a |........ k.7m.vz|
+000002d0 04 0e 8c 93 db b0 62 67 14 65 26 5e 91 b3 8d 66 |......bg.e&^...f|
+000002e0 20 40 31 c1 84 3c ef d8 67 04 01 00 80 ce 3a f2 | @1..<..g.....:.|
+000002f0 16 01 b2 8a cd d6 1c b3 c4 46 a5 e8 1f 17 85 d9 |.........F......|
+00000300 5b 97 fb dd 43 65 52 82 e3 49 99 e8 49 d9 09 13 |[...CeR..I..I...|
+00000310 05 73 19 d0 d9 66 54 03 de 4b fa 43 2d f1 f8 98 |.s...fT..K.C-...|
+00000320 79 21 3b fa a9 ea 29 78 fa 87 59 8e 9b 2f f2 99 |y!;...)x..Y../..|
+00000330 14 85 21 9c 7e 59 5b 4b 2f e3 33 c4 7c 2c ac 35 |..!.~Y[K/.3.|,.5|
+00000340 4f 68 c8 a3 0b f5 43 7e 72 9a e6 4f 9c 10 4d 4a |Oh....C~r..O..MJ|
+00000350 d4 b5 84 62 61 4e f4 0f 3f a5 b5 23 89 d9 33 e2 |...baN..?..#..3.|
+00000360 06 22 02 c5 fe db 27 fb 40 87 8c e7 6e 16 03 03 |."....'.@...n...|
+00000370 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 fa e7 |.....(..........|
-00000060 ff 47 50 7a 68 0d 20 f6 9f 2a b5 bc f4 21 c1 72 |.GPzh. ..*...!.r|
-00000070 07 4c e5 07 2c 07 e5 1e d7 fa 07 01 83 68 |.L..,........h|
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 20 5a b9 f7 81 81 7f 65 84 c9 87 40 |.... Z.....e...@|
+00000040 a4 66 07 85 38 3b 85 8d ff c4 7e b7 f6 16 1d c1 |.f..8;....~.....|
+00000050 36 4f 53 1a bb |6OS..|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 b7 93 18 5b 36 |..........(...[6|
-00000010 18 ce 97 17 75 40 15 17 1f 0e 0d 99 fd 66 fa 89 |....u@.......f..|
-00000020 db b7 97 95 a9 45 90 07 6e 82 0e 67 4f 01 58 ec |.....E..n..gO.X.|
-00000030 94 d7 ad |...|
+00000000 14 03 03 00 01 01 16 03 03 00 20 ff b2 f4 3b af |.......... ...;.|
+00000010 ba 44 66 0b f9 31 09 18 df 9d d0 04 82 38 11 dd |.Df..1.......8..|
+00000020 a7 ee 83 ef 03 51 21 08 f9 c4 8a |.....Q!....|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 21 2b 7b |.............!+{|
-00000010 62 ac e4 37 d6 77 19 89 77 1c 6a ce 40 c1 9d 71 |b..7.w..w.j.@..q|
-00000020 5a 23 f0 |Z#.|
+00000000 17 03 03 00 16 b6 45 4e 35 df 21 f4 c7 24 ba e6 |......EN5.!..$..|
+00000010 18 65 1c 75 ba 72 5d 5b 4a fd 78 |.e.u.r][J.x|
>>> Flow 6 (server to client)
-00000000 16 03 03 00 1c b7 93 18 5b 36 18 ce 98 4a 49 69 |........[6...JIi|
-00000010 f4 dd 35 f2 93 3b c6 4e d5 25 51 34 38 23 ea 74 |..5..;.N.%Q48#.t|
-00000020 84 |.|
+00000000 16 03 03 00 14 1a ec 37 ab 36 23 80 76 1c 0b d0 |.......7.6#.v...|
+00000010 54 9a 8f 7e 7a c0 bd 09 9a |T..~z....|
>>> Flow 7 (client to server)
-00000000 16 03 03 00 a9 00 00 00 00 00 00 00 02 65 09 7a |.............e.z|
-00000010 d5 9b 32 0b cd 10 ea 2c b6 d8 be ce db 3f a4 38 |..2....,.....?.8|
-00000020 a7 37 a3 95 ed 05 a7 c1 28 69 7a 13 50 07 ab 19 |.7......(iz.P...|
-00000030 52 d7 29 fe 49 80 f0 ef ea 17 ac 20 f9 62 51 72 |R.).I...... .bQr|
-00000040 8d c0 17 62 03 cf bb 80 f8 6f 1b 74 f1 85 45 96 |...b.....o.t..E.|
-00000050 49 55 56 b0 7a dd 9b 5a f1 3f 1a e7 96 cd 21 ec |IUV.z..Z.?....!.|
-00000060 85 6f b9 9d 0f e3 f6 55 9b b8 a7 e1 77 ad 53 0b |.o.....U....w.S.|
-00000070 98 90 ac 5d cf 31 0f 86 69 04 d8 e9 5e fc ea a8 |...].1..i...^...|
-00000080 a8 b7 a2 d8 0f ea 4f e5 ac f2 b2 c0 59 29 ba 53 |......O.....Y).S|
-00000090 af 1e 81 08 be 02 46 a7 b8 6f 2a b4 86 47 5d 8e |......F..o*..G].|
-000000a0 72 a6 64 84 7e 76 31 9c 31 fb 59 b7 da 15 |r.d.~v1.1.Y...|
+00000000 16 03 03 00 ad 7a d4 bf 4d bf 48 0a 0f 2c d1 38 |.....z..M.H..,.8|
+00000010 9f 20 f7 c7 36 27 82 d9 5e f4 21 44 0e 75 46 ca |. ..6'..^.!D.uF.|
+00000020 67 f8 87 6c 4f 1e c7 1e 5f 8d f2 88 58 1b 92 12 |g..lO..._...X...|
+00000030 e0 f6 d5 5c d7 4b 21 b9 8c 93 a8 bc a4 e6 e5 cb |...\.K!.........|
+00000040 d0 33 eb d5 10 ad 53 50 58 e0 94 f0 b8 52 20 8c |.3....SPX....R .|
+00000050 c2 69 7a c3 43 73 3f 2e 4a 42 2c c1 8d c1 ff 1e |.iz.Cs?.JB,.....|
+00000060 57 ba 7d 99 9c a2 10 99 19 d6 72 38 96 ba 2b ff |W.}.......r8..+.|
+00000070 7b a8 42 c0 c0 c4 d4 50 20 39 39 b8 18 23 a1 d3 |{.B....P 99..#..|
+00000080 38 d3 9d 41 81 c2 4b ba 4c 28 c0 14 22 71 df d9 |8..A..K.L(.."q..|
+00000090 e1 57 fc 9c 4f 0e 28 9a 13 c6 a1 e2 de f0 81 3b |.W..O.(........;|
+000000a0 5f c1 7b 61 f5 fc 74 93 f1 06 7d 9b 67 56 45 a4 |_.{a..t...}.gVE.|
+000000b0 f8 83 |..|
>>> Flow 8 (server to client)
-00000000 16 03 03 00 89 b7 93 18 5b 36 18 ce 99 4a 72 26 |........[6...Jr&|
-00000010 ab cb a4 70 60 0f 7a 02 62 28 f3 10 54 77 a7 33 |...p`.z.b(..Tw.3|
-00000020 32 a6 29 c8 8d 18 48 8f 9d 45 6e 7e 06 07 ca b3 |2.)...H..En~....|
-00000030 b6 45 eb ac f2 41 f1 d9 19 9e 30 1f c0 18 40 1c |.E...A....0...@.|
-00000040 55 09 4d f2 23 75 2f 2f c8 b7 46 63 05 d1 73 c0 |U.M.#u//..Fc..s.|
-00000050 02 71 de 5e 4a 84 92 3d 9a b9 68 62 31 91 7d 23 |.q.^J..=..hb1.}#|
-00000060 43 e3 4b 00 98 2e 01 12 f4 1f fa 4c aa 91 a0 ca |C.K........L....|
-00000070 9c a0 d9 6b 7f 5c b3 f4 8d e2 3a 54 eb e9 82 44 |...k.\....:T...D|
-00000080 21 54 ac 85 86 39 b8 df 23 64 2a 0c 3e 1d 16 03 |!T...9..#d*.>...|
-00000090 03 02 89 b7 93 18 5b 36 18 ce 9a 1c ae 99 12 58 |......[6.......X|
-000000a0 12 fa ef da 77 04 7f b5 42 68 b1 59 64 50 92 2b |....w...Bh.YdP.+|
-000000b0 a0 21 b7 b3 4c f8 c2 cc 75 5a d0 85 50 95 f4 1b |.!..L...uZ..P...|
-000000c0 c9 b2 1f 53 94 4c fd 6d 18 ad 1a 0d 24 9f fb 4c |...S.L.m....$..L|
-000000d0 19 13 5a 74 f2 e2 59 dd 1b d8 67 bc d9 d0 da ab |..Zt..Y...g.....|
-000000e0 a7 7f 8e ca e0 09 28 59 18 8d a1 8a c9 c3 2e 76 |......(Y.......v|
-000000f0 b9 0d 2f 56 5f c4 77 07 17 ac 62 26 a1 91 50 ee |../V_.w...b&..P.|
-00000100 60 45 aa a0 8a d9 1a 13 65 68 c8 cf ca 0c 50 3e |`E......eh....P>|
-00000110 9f 39 62 02 12 ea b4 ed e2 6c 0e 28 32 d7 fb ec |.9b......l.(2...|
-00000120 fc 6d e4 0a 14 1d 88 00 a8 c0 57 1e be 78 fd 18 |.m........W..x..|
-00000130 6e 40 70 37 2e f5 3b 52 59 03 02 bf 27 18 c8 00 |n@p7..;RY...'...|
-00000140 58 8f 5e d8 a8 7c 4c 54 83 4a fe f3 dc f8 19 2a |X.^..|LT.J.....*|
-00000150 00 ed 96 93 0e e4 45 58 8f 41 99 0d 93 f5 6c a4 |......EX.A....l.|
-00000160 4e 62 f2 4b 9a cb 69 30 5a 4b 36 45 f2 d2 c1 62 |Nb.K..i0ZK6E...b|
-00000170 f9 1c c4 c3 b2 94 b3 17 1a ed d8 57 ba b7 79 a1 |...........W..y.|
-00000180 a2 2e 5a 18 79 36 0b 54 ee 2c 2c 3b 62 96 5d e5 |..Z.y6.T.,,;b.].|
-00000190 3c 74 0e be 52 6f 06 7c 93 05 86 0f d6 1d d0 ee |<t..Ro.|........|
-000001a0 f9 ac 67 50 a6 d3 36 f7 5f 0b 3f 44 3b fc 4b 79 |..gP..6._.?D;.Ky|
-000001b0 b7 29 04 6c 37 18 2a 04 bf f4 3e 1a 53 f3 93 e5 |.).l7.*...>.S...|
-000001c0 f2 b7 b1 4b ed 19 5a 2f 40 d1 f2 91 49 0b 8b f6 |...K..Z/@...I...|
-000001d0 21 0b 20 01 ce 0f a8 f1 44 3f 5e b1 89 1a 15 9f |!. .....D?^.....|
-000001e0 4c c5 93 6b 68 93 ab 67 b5 1d 10 fa 22 53 e3 0f |L..kh..g...."S..|
-000001f0 c7 63 d0 32 b7 52 c6 2e b7 47 a4 1a b4 ab 35 a9 |.c.2.R...G....5.|
-00000200 b0 0e cd f6 8c e7 54 6c 77 7b 5c 6c c2 b3 02 89 |......Tlw{\l....|
-00000210 74 f7 b1 61 91 dc 01 3a 68 d9 81 78 21 95 b1 67 |t..a...:h..x!..g|
-00000220 36 2d 2a d6 c4 96 0d 7b e0 44 83 cd 52 e4 05 36 |6-*....{.D..R..6|
-00000230 a4 1d 2a 24 e8 cc 76 d7 66 2f 32 ef 8f 70 ef 26 |..*$..v.f/2..p.&|
-00000240 90 73 2e e6 b4 53 91 13 5b 5e 15 51 15 56 e9 43 |.s...S..[^.Q.V.C|
-00000250 22 9a b6 55 3d 94 00 35 73 41 12 fc 8a 0b fd 89 |"..U=..5sA......|
-00000260 7c 00 14 0d b8 f6 76 d0 ac 33 1d e4 73 49 e9 a2 ||.....v..3..sI..|
-00000270 09 69 e1 f1 a7 92 48 ee 2e fc ef 13 09 7c a7 72 |.i....H......|.r|
-00000280 eb 4c 15 39 17 6e cd 71 c0 e9 48 06 43 09 19 39 |.L.9.n.q..H.C..9|
-00000290 72 b0 9c f8 0e 75 af a8 eb 25 96 36 75 68 16 8f |r....u...%.6uh..|
-000002a0 e8 f6 66 56 66 63 b0 52 47 74 55 af c8 7a 07 dc |..fVfc.RGtU..z..|
-000002b0 d0 8b bf 51 6e bc 77 fa 8a 03 43 0c 5a 47 fb c7 |...Qn.w...C.ZG..|
-000002c0 be b3 ef b5 ad 24 48 40 6c 4b 03 41 dd 7c 3e 6e |.....$H@lK.A.|>n|
-000002d0 25 01 4b 45 ce ad d7 23 3a 6c 33 0b f1 7a 44 07 |%.KE...#:l3..zD.|
-000002e0 7e c8 bd 52 a5 a8 30 91 95 3e 4d 42 07 67 57 fb |~..R..0..>MB.gW.|
-000002f0 c0 4a ed 9f 76 21 8e df fb f6 a4 0a 08 1e 5b c6 |.J..v!........[.|
-00000300 3e a3 8c 47 a4 4d 41 2b e6 8f 42 43 cd ef a8 f1 |>..G.MA+..BC....|
-00000310 88 f2 b3 46 eb 8a 24 a3 98 a2 d7 d2 16 03 03 00 |...F..$.........|
-00000320 e5 b7 93 18 5b 36 18 ce 9b 62 57 ae 22 62 34 88 |....[6...bW."b4.|
-00000330 41 e1 7e 2a 4a 07 b4 b8 aa 80 32 f5 93 4c 58 79 |A.~*J.....2..LXy|
-00000340 82 51 d4 b8 c8 5b d2 99 a3 18 43 aa c2 14 bf 65 |.Q...[....C....e|
-00000350 e8 90 8d 46 69 d5 fa 34 e4 1a 47 06 dc 1a ae e9 |...Fi..4..G.....|
-00000360 40 b2 2e 7e 5e 74 f7 72 4d a9 e2 b7 52 b4 bb dc |@..~^t.rM...R...|
-00000370 06 e6 50 7e ef 42 8f 72 08 63 f9 ec 9e 13 36 0f |..P~.B.r.c....6.|
-00000380 d4 95 72 2b ff a5 6d 4b 1b db d6 b3 25 50 f0 dd |..r+..mK....%P..|
-00000390 e3 89 f5 c1 c0 3f aa 6c f0 a7 30 5d 56 76 77 b6 |.....?.l..0]Vvw.|
-000003a0 24 8f 93 fd 49 8c 73 1e f7 5c 5c 3a f3 0d 5e 89 |$...I.s..\\:..^.|
-000003b0 a4 bb 48 8a 82 ed 01 a6 2d eb b1 fe d2 6e 4e 88 |..H.....-....nN.|
-000003c0 1d 06 b6 f5 d8 41 86 40 fe 45 3e ef 35 9b 88 df |.....A.@.E>.5...|
-000003d0 48 af e0 05 33 4e 13 15 8b b6 5a 8e 5c f8 2a 59 |H...3N....Z.\.*Y|
-000003e0 14 6d 4a 79 75 48 e4 9d 16 4f 6f 65 9c c3 40 1e |.mJyuH...Ooe..@.|
-000003f0 7c 72 60 ce b9 f8 61 3b ff 34 81 94 01 aa b3 59 ||r`...a;.4.....Y|
-00000400 72 d2 1e 5f fe 7f 16 03 03 00 46 b7 93 18 5b 36 |r.._......F...[6|
-00000410 18 ce 9c c8 c9 b2 10 f1 39 bb f0 80 a9 0b 68 76 |........9.....hv|
-00000420 2b 60 0b c5 f3 eb 16 72 b5 4c c9 42 96 39 bf c1 |+`.....r.L.B.9..|
-00000430 94 87 f0 47 80 34 11 e2 1c 4c fc 26 d6 4b 00 49 |...G.4...L.&.K.I|
-00000440 ef 73 00 4e ab 61 d6 1f 89 2c 7e f2 5c ea 6b 5c |.s.N.a...,~.\.k\|
-00000450 50 |P|
+00000000 16 03 03 00 81 ec 0e 7c 60 5b ed 0f 29 e6 cd 3a |.......|`[..)..:|
+00000010 ca ff f7 68 3e 22 30 cf 43 b2 29 71 ca 3a 06 db |...h>"0.C.)q.:..|
+00000020 e0 df bc 87 51 62 df 37 37 7a 9d b4 2d 35 ab bb |....Qb.77z..-5..|
+00000030 d2 ed d1 50 e7 61 a4 27 18 43 23 74 4b 1d 14 46 |...P.a.'.C#tK..F|
+00000040 80 5c 10 99 10 47 b2 51 92 11 1f aa f1 5a c3 cf |.\...G.Q.....Z..|
+00000050 f5 30 69 96 26 f6 0e 7c e9 e1 7c 4b d5 2f 46 1c |.0i.&..|..|K./F.|
+00000060 7d 18 a5 20 f1 ff 40 9e c7 d5 d4 54 33 c4 99 9c |}.. ..@....T3...|
+00000070 26 95 d9 ca 82 fc e7 27 37 fc 33 9f f8 c7 cb 0a |&......'7.3.....|
+00000080 9d 4e bc 66 ca fc 16 03 03 02 69 ab be 55 39 99 |.N.f......i..U9.|
+00000090 ac 66 a6 86 03 51 70 d8 fa 7d e7 89 09 fc eb b5 |.f...Qp..}......|
+000000a0 25 f6 95 0c 40 3d b8 ea b6 78 41 db a4 f3 92 83 |%...@=...xA.....|
+000000b0 00 c8 8d 1f 19 0c ec ec e5 60 07 d9 31 2d 3b 91 |.........`..1-;.|
+000000c0 ba ad b3 c1 fb b5 57 52 73 37 43 89 22 e0 45 7c |......WRs7C.".E||
+000000d0 b0 da 1f 69 76 d3 af fc ba f0 98 ec d2 7f be f0 |...iv...........|
+000000e0 a4 76 f0 d9 30 1b 78 22 bb 43 fd 45 64 07 e4 64 |.v..0.x".C.Ed..d|
+000000f0 c5 74 2f ed ba 23 8d 3a 5a ff 7f 35 de 25 53 0d |.t/..#.:Z..5.%S.|
+00000100 ac ae 5b da b1 7d 86 fe da c8 9e 79 58 6c 4c 9c |..[..}.....yXlL.|
+00000110 6d f9 e9 1d 31 ff aa fb 8e 2e 98 f4 3a 67 33 9b |m...1.......:g3.|
+00000120 a3 63 5e fc 74 f5 c5 28 76 30 e6 22 8a 85 79 56 |.c^.t..(v0."..yV|
+00000130 4e cf 94 38 92 61 09 22 00 95 d4 16 b4 e0 80 05 |N..8.a."........|
+00000140 28 35 30 6f 56 7d f8 b9 ed 49 72 b0 9f 47 9f 07 |(50oV}...Ir..G..|
+00000150 7f 1d b9 3b 6d ce c9 09 72 2f 65 b0 88 b4 ec 24 |...;m...r/e....$|
+00000160 29 8d 57 93 a7 51 85 32 26 4c 31 21 24 b1 ab 97 |).W..Q.2&L1!$...|
+00000170 c6 3c 38 44 d4 8f d0 3b ea 62 39 48 90 ca c4 5c |.<8D...;.b9H...\|
+00000180 9c 72 08 a4 3f d0 1e 3e 9f 23 02 0e 94 b4 14 cc |.r..?..>.#......|
+00000190 96 bc 23 22 2f af c5 ed 81 da 49 ca 26 f4 55 6a |..#"/.....I.&.Uj|
+000001a0 b3 24 3f 13 a5 f7 d6 82 70 04 37 63 dc 92 63 0f |.$?.....p.7c..c.|
+000001b0 3d f7 4e 42 7c 5a 42 df 53 17 48 25 cb da 31 e1 |=.NB|ZB.S.H%..1.|
+000001c0 67 a7 22 8c ca db 2d 33 49 86 62 b5 ba 38 53 4c |g."...-3I.b..8SL|
+000001d0 12 f3 c3 f6 b6 01 53 b1 11 43 e1 e8 ba 3f 68 7a |......S..C...?hz|
+000001e0 9c 10 09 82 d1 90 cd 9e 52 2e 29 15 0b 13 c3 e3 |........R.).....|
+000001f0 34 ef 76 8a 0d f9 f6 17 76 57 c2 55 cb 7d 45 e0 |4.v.....vW.U.}E.|
+00000200 d5 e6 53 93 75 57 c2 ab 26 5a 13 02 05 7a 60 2b |..S.uW..&Z...z`+|
+00000210 b6 92 1a 88 0c 34 59 81 40 42 70 d5 4e 7b d3 14 |.....4Y.@Bp.N{..|
+00000220 3c e6 70 81 90 ff 53 79 c5 f3 7c d9 02 6f 35 6b |<.p...Sy..|..o5k|
+00000230 d4 81 ff 32 a2 71 28 a0 4b 22 75 9f 3b 50 c8 03 |...2.q(.K"u.;P..|
+00000240 22 e7 4f 1f c5 c5 99 67 f3 2c 97 5e 43 89 84 39 |".O....g.,.^C..9|
+00000250 04 c9 4c 1e e0 da 39 8f 78 8f 95 3a 64 74 d3 63 |..L...9.x..:dt.c|
+00000260 13 d4 14 9d 98 6c bb 27 81 1e 12 88 8c d4 11 1c |.....l.'........|
+00000270 4a 71 2f 10 dc 5b 9a 8e 70 e6 bf 0b a2 50 4c d1 |Jq/..[..p....PL.|
+00000280 c4 29 b7 85 9e 0f 86 33 7c 38 e4 ae d4 53 5e 81 |.).....3|8...S^.|
+00000290 95 cf 6c 1a 15 7d af 20 53 21 f4 84 5c 46 5f 10 |..l..}. S!..\F_.|
+000002a0 1f 68 7d 9a 20 0d a8 1f 90 2f ae b8 c0 57 e0 4b |.h}. ..../...W.K|
+000002b0 ad ec 9d ae 51 52 78 5d 3f bb de 54 54 d4 18 ff |....QRx]?..TT...|
+000002c0 e6 b4 c9 52 f8 66 63 e3 bf 7a f3 5e c6 3f d9 27 |...R.fc..z.^.?.'|
+000002d0 71 07 e7 69 6d cb 60 24 55 4e f9 34 e7 5f a3 37 |q..im.`$UN.4._.7|
+000002e0 76 90 ec b5 eb ff 49 38 15 71 23 fd 77 30 80 c8 |v.....I8.q#.w0..|
+000002f0 ca 0e 38 3c 16 03 03 00 bc 89 27 c8 13 dd 05 8b |..8<......'.....|
+00000300 46 97 5f 19 76 db 29 8d b1 24 52 fe 7a 2e 2c 4d |F._.v.)..$R.z.,M|
+00000310 e2 f9 59 89 48 82 f5 d7 87 af 99 4b 98 c5 7c 1d |..Y.H......K..|.|
+00000320 1a e1 4d fd 0c 37 d0 d3 d8 e2 f8 0f 04 d5 15 21 |..M..7.........!|
+00000330 60 09 47 0c d6 bf 09 bf 55 c1 ae 33 11 35 94 29 |`.G.....U..3.5.)|
+00000340 80 96 3a 53 ae a8 29 c4 84 37 e2 80 f9 da 79 18 |..:S..)..7....y.|
+00000350 77 50 26 32 bf f6 b2 6d 3a 73 25 e7 cd 34 6d ea |wP&2...m:s%..4m.|
+00000360 a0 92 40 7e f8 eb d0 82 06 b3 a1 f5 1c 8e b2 ef |..@~............|
+00000370 b2 4f 0c bb 04 1b c7 cf bc dd 42 19 00 3e 45 93 |.O........B..>E.|
+00000380 e6 72 57 ed eb d9 1d b3 71 b7 fe 84 03 57 e4 9c |.rW.....q....W..|
+00000390 71 78 35 39 63 b1 cf 36 b9 5a d6 95 13 ee 4d 2f |qx59c..6.Z....M/|
+000003a0 22 ef ed 2e fc 69 7c 12 c2 0e 32 ed 05 17 42 5c |"....i|...2...B\|
+000003b0 a7 62 ab 6b 46 16 03 03 00 3a b9 af 3d 25 e4 6a |.b.kF....:..=%.j|
+000003c0 a9 b5 b4 00 79 21 aa 3c f3 56 50 bd 32 a4 a8 ab |....y!.<.VP.2...|
+000003d0 8a 60 77 5d b7 3e 89 d3 60 a2 b8 5c a8 99 27 bb |.`w].>..`..\..'.|
+000003e0 0e dd 93 af 3e 2b 66 8e 56 19 03 29 44 6a 63 a1 |....>+f.V..)Djc.|
+000003f0 c7 17 f3 1e 16 03 03 00 14 1c bd e4 7b c3 88 d9 |............{...|
+00000400 be ba c3 c3 fb b7 07 9d f1 58 3e b0 61 |.........X>.a|
>>> Flow 9 (client to server)
-00000000 16 03 03 02 89 00 00 00 00 00 00 00 03 c2 d4 9b |................|
-00000010 19 c8 b6 76 fb ef e4 b2 f7 97 c7 80 f5 e2 b4 3c |...v...........<|
-00000020 bd b7 b8 25 da 54 52 a7 f8 38 0d 48 c0 13 19 82 |...%.TR..8.H....|
-00000030 17 3c ff d2 c0 8f bd 76 5d 16 39 db a7 51 3f b1 |.<.....v].9..Q?.|
-00000040 72 b6 59 e4 8c 6c f5 33 de 78 15 8d 64 cf 55 c6 |r.Y..l.3.x..d.U.|
-00000050 47 e3 0b 30 06 e1 6c 2d e1 e0 7a e1 0a da dd 0d |G..0..l-..z.....|
-00000060 60 5b 06 28 a8 94 14 a3 cc 91 96 8d 2b 71 af ff |`[.(........+q..|
-00000070 c2 32 e2 19 77 96 f3 5b 53 3a d3 29 51 c2 54 98 |.2..w..[S:.)Q.T.|
-00000080 f3 00 8e 9a fe ef bb ea 06 27 58 54 3c c8 67 dc |.........'XT<.g.|
-00000090 f3 41 01 77 de 25 b4 54 53 67 64 41 b3 ae 2b c2 |.A.w.%.TSgdA..+.|
-000000a0 57 cd 74 14 3c 46 a7 70 ec a8 bc 0e 05 46 ce fc |W.t.<F.p.....F..|
-000000b0 c8 54 4d 23 25 b9 e0 45 fa 1e 1b 2c f1 d0 da 66 |.TM#%..E...,...f|
-000000c0 3c 00 e5 b3 f5 f9 ff 64 75 82 f9 dd c2 3f 42 46 |<......du....?BF|
-000000d0 27 ca 72 a2 f7 6c 4e bf 98 05 e6 99 b5 7b 60 33 |'.r..lN......{`3|
-000000e0 99 e8 7a 7c 91 41 64 cd 96 60 f2 f6 c8 bd 4f 35 |..z|.Ad..`....O5|
-000000f0 5f 6f 43 11 b0 94 3c 98 bc 58 15 7e 52 01 ba cf |_oC...<..X.~R...|
-00000100 71 f4 0a fb 85 0a 24 13 0c 4a 53 55 77 92 91 cd |q.....$..JSUw...|
-00000110 ce 39 7e 07 2f 4f ba 47 ca bd 67 5b ce 5a 04 03 |.9~./O.G..g[.Z..|
-00000120 ff 86 0a 82 80 b9 42 b8 4c e3 ce 73 b2 4a 5a 4b |......B.L..s.JZK|
-00000130 f5 f2 44 d8 e5 01 30 c8 2e ce 4f 62 2d 34 9c d6 |..D...0...Ob-4..|
-00000140 57 20 db 37 20 66 03 b6 4d a7 0f 75 30 d8 ad 2f |W .7 f..M..u0../|
-00000150 63 f7 4e 24 ec 68 e0 a2 a9 b1 3d 68 e5 c1 8b d8 |c.N$.h....=h....|
-00000160 19 dd 40 33 c6 5c 57 3b 22 5a 9c 24 fe 2f 92 54 |..@3.\W;"Z.$./.T|
-00000170 0f e8 85 74 06 72 59 ab 1d b8 5d 31 91 ed 05 51 |...t.rY...]1...Q|
-00000180 61 c6 43 3d 81 f4 47 c3 80 17 4d 1b 08 c4 85 1b |a.C=..G...M.....|
-00000190 b7 37 b0 cf 5c 73 5f 56 0f 5a b5 21 21 46 e3 df |.7..\s_V.Z.!!F..|
-000001a0 e6 cb 9d ac ab 16 c0 b1 b8 2a 4a 5b a7 2d 7a 00 |.........*J[.-z.|
-000001b0 9f 9d 76 57 ab 20 ea 80 8a 7a ca 14 45 d7 4e 1b |..vW. ...z..E.N.|
-000001c0 c8 7c b8 c6 82 fc 40 b2 b4 7d f1 74 7d b5 2a 90 |.|....@..}.t}.*.|
-000001d0 01 83 d4 d1 26 63 d7 39 69 b1 33 5f 7e 54 de f7 |....&c.9i.3_~T..|
-000001e0 08 3d 62 3b da 57 0d d4 48 99 9a 3e 99 e5 b0 6b |.=b;.W..H..>...k|
-000001f0 25 45 38 36 aa 7a bb 81 7d 0b dd 1d 50 c4 17 68 |%E86.z..}...P..h|
-00000200 4b a7 f7 2f d8 cd 97 a6 ea 24 9b 34 69 9e 7d ad |K../.....$.4i.}.|
-00000210 6a 17 23 d8 36 61 cf 85 74 47 18 5b fd cd 72 ac |j.#.6a..tG.[..r.|
-00000220 c2 a2 b4 53 e3 5d 25 f7 bb b6 95 99 a0 e5 05 38 |...S.]%........8|
-00000230 0a 52 32 f6 7d a6 30 5c 11 6b 8a 7b af ec a2 9b |.R2.}.0\.k.{....|
-00000240 b8 f1 85 6d a8 b7 79 61 42 60 4a 35 73 fb d5 2c |...m..yaB`J5s..,|
-00000250 1f 84 5c d9 c9 23 10 e8 a4 2c 56 fd f4 22 1a 7a |..\..#...,V..".z|
-00000260 f3 b2 c5 69 8b c9 d1 d5 45 c8 65 59 fc ab d9 d3 |...i....E.eY....|
-00000270 7d ab c3 fe bc da 6d a3 cd 0c 83 32 70 65 c7 7f |}.....m....2pe..|
-00000280 8c 83 c8 97 3e 7f 89 fc 11 7d 1c a5 fd 99 16 03 |....>....}......|
-00000290 03 00 5e 00 00 00 00 00 00 00 04 64 60 91 c0 fd |..^........d`...|
-000002a0 3a 96 5a ac 5a 13 a9 9a 41 eb a0 6d 51 98 ee a8 |:.Z.Z...A..mQ...|
-000002b0 4d ee 90 c9 3e a5 15 ac f3 6a c8 56 f3 20 c3 10 |M...>....j.V. ..|
-000002c0 e3 3a d1 ea b0 7d a7 21 ae 2c b1 fa 5c b8 c1 fa |.:...}.!.,..\...|
-000002d0 d7 97 6e ea fd 09 53 46 db aa e4 39 31 00 c2 bb |..n...SF...91...|
-000002e0 ad 36 10 cd e9 cb 46 31 7b 66 ee ce 0c a8 f9 c2 |.6....F1{f......|
-000002f0 0a 16 03 03 00 a0 00 00 00 00 00 00 00 05 6d a0 |..............m.|
-00000300 03 60 12 bb 06 89 0c 03 ad f7 36 f3 5c e4 c1 65 |.`........6.\..e|
-00000310 b2 26 c9 f5 87 85 f9 8f 2d 05 43 35 32 d7 0a a0 |.&......-.C52...|
-00000320 e5 16 7a 94 62 15 ed cc 8e 9f e3 10 8d e7 83 a2 |..z.b...........|
-00000330 ea e4 07 49 c9 df 1d 2b 6f b8 0f 67 31 22 44 9b |...I...+o..g1"D.|
-00000340 65 77 99 78 f9 3e 14 67 3a 90 e5 5a c2 b5 1b ee |ew.x.>.g:..Z....|
-00000350 db 20 73 8d 85 22 4d 79 6e e9 17 d0 b1 03 58 f3 |. s.."Myn.....X.|
-00000360 cf 1b f5 03 9a 75 1f 7a 3b 49 ee 67 04 da c4 fc |.....u.z;I.g....|
-00000370 7a 62 a9 ff 26 4f 71 b2 7e e9 c7 78 96 74 1e 63 |zb..&Oq.~..x.t.c|
-00000380 eb 2b 2f 18 1f 19 cf 1e 89 73 39 9e f6 02 3d 31 |.+/......s9...=1|
-00000390 50 65 1f 80 19 26 14 03 03 00 19 00 00 00 00 00 |Pe...&..........|
-000003a0 00 00 06 82 62 df fd 51 9e be 21 0b 22 b6 c1 6d |....b..Q..!."..m|
-000003b0 5c 90 ea c5 16 03 03 00 28 00 00 00 00 00 00 00 |\.......(.......|
-000003c0 00 d6 5f a7 05 2b 99 cc 7d fb d7 38 5e e3 31 a7 |.._..+..}..8^.1.|
-000003d0 c9 1c bd 7b c7 89 d0 e5 b5 93 78 d1 63 57 d2 76 |...{......x.cW.v|
-000003e0 38 |8|
+00000000 16 03 03 02 69 d3 b2 83 ca 08 61 36 6f fa 66 de |....i.....a6o.f.|
+00000010 5c 42 5f 35 17 f4 4c b3 5e 17 94 07 c5 2a 89 90 |\B_5..L.^....*..|
+00000020 b8 31 50 af 55 91 b1 28 bc 00 00 da 57 85 cc d5 |.1P.U..(....W...|
+00000030 a5 a7 ec ba 52 d5 1f ab b5 4f a3 53 9c af 59 20 |....R....O.S..Y |
+00000040 be 13 f6 c5 70 b0 cc f7 59 69 d1 db 80 7f 60 29 |....p...Yi....`)|
+00000050 e1 e8 7a 1e 97 a6 e1 a2 11 70 4f b4 7b 53 7c 9a |..z......pO.{S|.|
+00000060 dd fa 58 5d 12 a4 fb 3e 46 dd d3 4d ac e3 b6 73 |..X]...>F..M...s|
+00000070 05 42 03 f3 37 79 a0 10 34 ef 01 6f c6 27 52 4b |.B..7y..4..o.'RK|
+00000080 75 4c b2 86 1b d6 ca 13 b4 31 41 db 93 2f a3 35 |uL.......1A../.5|
+00000090 e1 e9 bc 65 85 c8 1a e2 7b 6e 36 49 e8 ed 04 a9 |...e....{n6I....|
+000000a0 cb a9 70 32 c0 4d e5 f5 94 d8 af 7d 41 b6 dc e5 |..p2.M.....}A...|
+000000b0 fc ff db 9f 91 50 df c6 b2 4a 0c bb 86 4e 50 a5 |.....P...J...NP.|
+000000c0 2a 3b 69 e2 3d fa 10 eb cc 48 21 9d 98 78 02 0b |*;i.=....H!..x..|
+000000d0 e7 4d 83 63 9e e5 ad 2c 7b 46 d1 09 28 35 07 6c |.M.c...,{F..(5.l|
+000000e0 12 c9 ae f0 4c 7c 00 aa 54 ba 7b e8 42 be e0 18 |....L|..T.{.B...|
+000000f0 f4 df a0 9d eb 8f a2 3a d0 00 b6 e0 eb 90 65 38 |.......:......e8|
+00000100 b2 cc 21 87 57 b7 50 07 41 e2 5a 9b c8 2b ae 64 |..!.W.P.A.Z..+.d|
+00000110 55 6a d7 b5 0d 5d f0 ac da 0b f0 80 75 8d 6a 0a |Uj...]......u.j.|
+00000120 5b c5 2a 20 f2 ab 75 76 a3 33 f1 43 24 06 45 75 |[.* ..uv.3.C$.Eu|
+00000130 63 58 60 57 ca 7f d2 8f e8 a5 b8 e3 72 37 39 bd |cX`W........r79.|
+00000140 9c dd 10 b0 f8 b5 e8 46 4a 39 ac 94 69 08 51 29 |.......FJ9..i.Q)|
+00000150 27 2d 28 0f 15 8a 91 00 3b cc 99 77 ea 82 0d e1 |'-(.....;..w....|
+00000160 66 ed 34 da 6e 88 47 e5 f4 1b 28 28 cd 38 9f e5 |f.4.n.G...((.8..|
+00000170 1c 26 67 3d 83 d0 b1 88 a3 08 9c 2e 08 a5 b7 af |.&g=............|
+00000180 15 28 d5 1e aa c9 58 17 48 85 f7 13 17 6f 55 c3 |.(....X.H....oU.|
+00000190 dc 9d 2e 7e 67 45 7a cb 80 a7 e5 77 86 96 36 4d |...~gEz....w..6M|
+000001a0 f7 df 27 7d f4 5d 53 9b be e6 b2 b9 44 b9 86 e9 |..'}.]S.....D...|
+000001b0 8f 33 26 4e 20 97 e4 34 66 58 6d d5 28 be e8 84 |.3&N ..4fXm.(...|
+000001c0 de 2f 19 f2 46 52 80 84 e9 ef 0e 6c 55 5c 43 8c |./..FR.....lU\C.|
+000001d0 51 19 8b 22 30 b7 b3 eb 9f ed 35 a1 fe 09 aa 6a |Q.."0.....5....j|
+000001e0 f8 b6 37 7e 20 4c e5 76 ae 10 4c dd 67 7c 07 e2 |..7~ L.v..L.g|..|
+000001f0 0c dc 78 77 a1 8e c1 d1 aa fa d3 36 8b 9c 74 ed |..xw.......6..t.|
+00000200 e2 fe 84 98 40 95 f2 1a a6 fd 77 cf 47 d3 c3 d6 |....@.....w.G...|
+00000210 bc 38 45 a9 94 63 13 52 2d 7b 3f 3d 06 1e 0a 31 |.8E..c.R-{?=...1|
+00000220 cb 98 1d 18 fa a7 86 21 65 c7 58 dd 78 13 2d 4d |.......!e.X.x.-M|
+00000230 76 57 9d 65 15 a3 2d be 7f c9 58 78 b7 89 3c d6 |vW.e..-...Xx..<.|
+00000240 dc 7e 5b c5 1b 93 78 04 7b ca ef 61 77 6c 27 6b |.~[...x.{..awl'k|
+00000250 a5 30 67 43 64 a7 30 f0 dd 5c 63 92 76 9a e3 a2 |.0gCd.0..\c.v...|
+00000260 31 12 49 8e c4 7e 80 ce 1e ce 94 66 2f 6f 16 03 |1.I..~.....f/o..|
+00000270 03 00 35 39 86 a0 5a 88 07 66 5f 43 59 ed fb b5 |..59..Z..f_CY...|
+00000280 0c 0b ee ff 76 62 28 ea 62 7e 53 72 3d d9 26 9f |....vb(.b~Sr=.&.|
+00000290 06 64 99 83 a5 3c 59 45 84 4d 79 86 1d b4 21 14 |.d...<YE.My...!.|
+000002a0 29 df f1 99 aa 6a 64 91 16 03 03 00 98 22 32 c2 |)....jd......"2.|
+000002b0 63 2c 82 b9 47 02 65 97 6b 14 fc 35 b8 20 ce 3c |c,..G.e.k..5. .<|
+000002c0 1b 16 fd 51 55 e8 31 b5 58 e6 64 a8 2b b0 f2 ab |...QU.1.X.d.+...|
+000002d0 31 7a cd 3e 32 43 64 eb 08 b0 52 d4 81 56 e3 04 |1z.>2Cd...R..V..|
+000002e0 4e d2 1a b8 f6 ae 64 d2 c0 05 9b 18 84 71 a7 ad |N.....d......q..|
+000002f0 ea 49 f6 b5 ae 91 ad 66 6f cb fa 56 de 1e 40 22 |.I.....fo..V..@"|
+00000300 7f d3 44 c4 a7 bf b1 7b 61 e3 09 1f fe 3b 4b 7b |..D....{a....;K{|
+00000310 5a 3f ae 4e c4 5c a8 ac a4 c2 fc 0e 1f 12 4f 9b |Z?.N.\........O.|
+00000320 f9 e0 a2 89 ab a0 bb e8 f9 97 5a 7c 8d e8 58 87 |..........Z|..X.|
+00000330 3f 4c 1c f3 ff 6e b9 a0 e6 f7 e4 c2 43 cc af 9e |?L...n......C...|
+00000340 06 3a 1c ee ef 14 03 03 00 11 8b 6d c3 12 83 c4 |.:.........m....|
+00000350 2f e7 67 81 db 18 9a 33 e6 fa 82 16 03 03 00 20 |/.g....3....... |
+00000360 ef c9 6f 3f b7 9d 9d 2d a0 05 b6 fd 74 8e ff de |..o?...-....t...|
+00000370 cc 4b ca 4c 5b 4d 61 30 76 b5 f3 7a d1 46 d6 6a |.K.L[Ma0v..z.F.j|
>>> Flow 10 (server to client)
-00000000 14 03 03 00 19 b7 93 18 5b 36 18 ce 9d 68 22 e1 |........[6...h".|
-00000010 d0 06 aa e5 87 f8 49 bc 38 d7 b9 38 85 97 16 03 |......I.8..8....|
-00000020 03 00 28 24 71 bf 67 14 d6 5e 29 1b de e6 f4 e0 |..($q.g..^).....|
-00000030 33 76 dc 66 c6 95 c0 3a 15 49 99 09 2f cf 6b 6b |3v.f...:.I../.kk|
-00000040 a1 8f 1a e4 af 8d 1e 7f 02 b1 87 17 03 03 00 21 |...............!|
-00000050 24 71 bf 67 14 d6 5e 2a 61 7b 98 dd e8 52 b0 1e |$q.g..^*a{...R..|
-00000060 28 46 28 de e2 22 65 6c 66 85 3a 1d bb 9e 76 a2 |(F(.."elf.:...v.|
-00000070 55 16 03 03 00 1c 24 71 bf 67 14 d6 5e 2b bb 84 |U.....$q.g..^+..|
-00000080 6d f0 1c d0 46 89 bb b2 09 96 dd 95 53 bf ac d7 |m...F.......S...|
-00000090 80 f1 |..|
+00000000 14 03 03 00 11 2e d9 0e 1b 6b 4b 9a 60 96 e9 38 |.........kK.`..8|
+00000010 35 a3 72 3d c4 5b 16 03 03 00 20 62 1f 2b 02 e8 |5.r=.[.... b.+..|
+00000020 22 0a 89 a2 f6 60 8a da f2 09 52 5a 92 12 a8 f6 |"....`....RZ....|
+00000030 c3 ee 25 17 6b 91 25 3e 2b 75 ba 17 03 03 00 19 |..%.k.%>+u......|
+00000040 b9 4e 6b c3 74 30 39 f9 3f a2 aa af 80 49 6b 8a |.Nk.t09.?....Ik.|
+00000050 f2 a1 9b f5 c7 34 f7 1b 2f 16 03 03 00 14 2d 25 |.....4../.....-%|
+00000060 74 c2 c7 80 a8 5f 65 ff 65 b0 c2 50 c8 bc fe 8c |t...._e.e..P....|
+00000070 d4 9e |..|
>>> Flow 11 (client to server)
-00000000 16 03 03 00 a9 00 00 00 00 00 00 00 01 61 12 ee |.............a..|
-00000010 0a f2 5e e2 3d 3d 36 4c 14 10 20 aa 4d 8a 91 e4 |..^.==6L.. .M...|
-00000020 c2 b0 63 68 9e f5 71 b7 a4 ee 75 27 20 8c 2e 21 |..ch..q...u' ..!|
-00000030 f5 57 3d e9 9a 05 da 7b a5 af 6a 17 10 8b eb 25 |.W=....{..j....%|
-00000040 8a 79 75 07 dc fe f5 7f a5 e2 63 31 ee 55 ba c0 |.yu.......c1.U..|
-00000050 e6 3d de 03 36 2b 64 19 b1 1a b8 80 09 25 8c dd |.=..6+d......%..|
-00000060 dd 59 c7 1d e7 40 20 ae ca a9 b5 14 a7 57 f0 62 |.Y...@ ......W.b|
-00000070 71 88 a3 2c fc a4 50 dc 8b 85 22 20 38 c5 74 ea |q..,..P..." 8.t.|
-00000080 ac 33 1d a3 c5 5c cc 10 62 fd c5 70 22 fa e3 73 |.3...\..b..p"..s|
-00000090 f3 bf 24 14 0d cb 7c 25 e4 74 6c fe c0 70 5e a0 |..$...|%.tl..p^.|
-000000a0 63 a7 e5 f2 6e d8 71 bd 7d b9 f0 b6 0b 70 |c...n.q.}....p|
+00000000 16 03 03 00 ad d0 25 9a 38 60 d3 94 8e b8 23 45 |......%.8`....#E|
+00000010 44 67 95 20 79 1a 27 5f cf bb dc 72 8c 95 2a 02 |Dg. y.'_...r..*.|
+00000020 1d d9 80 c6 61 12 c2 5c ae d5 62 a9 aa b0 4a d0 |....a..\..b...J.|
+00000030 13 ad 6d ae df c9 63 e2 6b 27 bb ca 88 c3 dc 8b |..m...c.k'......|
+00000040 e9 bc 0b fb 32 d6 0f 99 b6 d1 03 7e c9 8d 72 ee |....2......~..r.|
+00000050 09 7b 82 f1 79 11 a7 23 43 8b 77 b8 a9 bd 9e 67 |.{..y..#C.w....g|
+00000060 43 03 79 88 34 ab c2 6b d1 2a cf c7 c9 b6 14 ee |C.y.4..k.*......|
+00000070 ee 32 01 10 fb 85 dc 5a 04 cf 9a ea 8d 8c fc f8 |.2.....Z........|
+00000080 b3 b2 49 c0 93 37 93 09 24 1c 26 97 43 5f dd 09 |..I..7..$.&.C_..|
+00000090 7a 0d c0 6c bd 17 df 78 37 3d 23 6b 9d 27 d2 f7 |z..l...x7=#k.'..|
+000000a0 1c 2e 82 5c ba 95 1c 0f b3 40 af 9f 2f 5e 42 40 |...\.....@../^B@|
+000000b0 cc b9 |..|
>>> Flow 12 (server to client)
-00000000 16 03 03 00 89 24 71 bf 67 14 d6 5e 2c 55 62 31 |.....$q.g..^,Ub1|
-00000010 5c a3 53 1a c3 2f 89 47 62 33 7e 24 cd ad a9 5b |\.S../.Gb3~$...[|
-00000020 51 79 d8 08 08 ff 09 3c 41 c7 80 ed ec 5a 7a e4 |Qy.....<A....Zz.|
-00000030 71 e1 17 91 5e c1 80 58 35 c7 27 ca 62 74 cc d8 |q...^..X5.'.bt..|
-00000040 e8 35 86 97 bf 05 73 b9 3f ae 5b af 9a 14 88 4b |.5....s.?.[....K|
-00000050 f9 6f a4 de 3d 45 c8 7b 0a b1 7a 81 3e 7c 02 b5 |.o..=E.{..z.>|..|
-00000060 e9 43 a5 64 88 59 f6 55 20 d1 09 39 cd 01 46 0f |.C.d.Y.U ..9..F.|
-00000070 a2 06 f3 2b 45 14 b2 57 21 2c 2f a0 e5 db 02 99 |...+E..W!,/.....|
-00000080 e4 6b 1e 22 99 c9 ae 93 e4 67 89 d1 c6 6d 16 03 |.k.".....g...m..|
-00000090 03 02 89 24 71 bf 67 14 d6 5e 2d ce 6a 42 6b ce |...$q.g..^-.jBk.|
-000000a0 07 4e ff 40 39 4b 00 c8 14 4c 76 e0 4d 09 41 c3 |.N.@9K...Lv.M.A.|
-000000b0 41 3a ca ac 28 06 01 80 e4 b8 73 a2 fc ea 8d 92 |A:..(.....s.....|
-000000c0 44 0e 43 3e d8 cb 8a 0c a0 c1 5e 88 6d 6d 80 be |D.C>......^.mm..|
-000000d0 9c 9f cc 20 7c fa 6f e4 1a a1 39 c2 a8 7d 04 85 |... |.o...9..}..|
-000000e0 75 5d c4 d3 6f df d7 3a 9d 83 c3 74 aa 49 df 34 |u]..o..:...t.I.4|
-000000f0 e0 41 ad a3 80 80 c3 29 44 b9 5f a1 7b 67 89 30 |.A.....)D._.{g.0|
-00000100 04 b0 90 78 6b 82 fe ae 0c eb e1 5a 64 e2 6f de |...xk......Zd.o.|
-00000110 de 12 db 4f 1f eb 1d a9 66 a1 62 11 ab 54 1f 5d |...O....f.b..T.]|
-00000120 c2 ce 1e a8 b3 8b 29 08 76 13 a0 67 5b e6 1b 2c |......).v..g[..,|
-00000130 bd 1b 42 80 a5 09 b0 03 28 df 77 6f a7 d5 2f 85 |..B.....(.wo../.|
-00000140 2b b1 69 81 5c a0 16 16 1c eb b4 61 f1 f7 70 55 |+.i.\......a..pU|
-00000150 ee 64 9d 8f 1a 0b af af 18 f5 da e6 32 ab b2 28 |.d..........2..(|
-00000160 0d a0 ea b4 44 3d a9 f7 1a 84 c1 8f 30 09 41 13 |....D=......0.A.|
-00000170 a3 34 79 a7 6f da 76 59 62 9f d6 82 0f 48 21 64 |.4y.o.vYb....H!d|
-00000180 11 49 53 cd 3a 44 5a dc 8b 97 8a 84 d2 f9 12 77 |.IS.:DZ........w|
-00000190 b3 5b b0 37 58 7a a3 5a 47 9d c7 e4 83 f5 0a 32 |.[.7Xz.ZG......2|
-000001a0 10 39 aa d6 7c 8e 44 eb a9 fd 0f c0 6a 80 82 21 |.9..|.D.....j..!|
-000001b0 30 d1 36 31 73 38 c5 bd 16 99 71 b5 49 8e 7f df |0.61s8....q.I...|
-000001c0 f9 64 7f ff 16 3b 68 7c b5 7c 1f 41 19 36 dd ef |.d...;h|.|.A.6..|
-000001d0 65 11 b9 91 c4 d4 40 eb 37 94 69 8b 3b 10 56 45 |e.....@.7.i.;.VE|
-000001e0 ee 56 a8 a7 3d 94 17 5c fe f2 88 c7 fb 78 8e 51 |.V..=..\.....x.Q|
-000001f0 53 a8 bc b3 88 ee 75 42 1d 41 b8 c5 34 d5 9e bc |S.....uB.A..4...|
-00000200 b4 b7 1c 97 8b 83 d6 3d 97 4b 43 7a 40 3d 63 6e |.......=.KCz@=cn|
-00000210 cf 57 9a d3 71 6d 54 fe 38 ec 6f d7 c3 aa 1c a8 |.W..qmT.8.o.....|
-00000220 2b f6 34 96 cb 16 da 3e 2d 74 dd f6 1c 33 3c 4e |+.4....>-t...3<N|
-00000230 25 d9 e3 c5 85 52 c3 ea 22 ea 86 16 84 31 05 a4 |%....R.."....1..|
-00000240 7d 41 00 bd 4a b3 79 93 18 1c a1 e4 78 1c 90 49 |}A..J.y.....x..I|
-00000250 b4 9f bc d3 2d d0 f9 46 da 13 7c f6 88 5e e1 b2 |....-..F..|..^..|
-00000260 5c 41 12 bf 2f 1f b4 c3 13 8c 2f a6 83 c5 86 ba |\A../...../.....|
-00000270 20 42 21 57 e1 78 82 0e 4b 55 32 c1 f2 6e 4c a2 | B!W.x..KU2..nL.|
-00000280 a7 c7 63 b3 b5 30 49 9d 7a 51 5e 67 38 52 89 ee |..c..0I.zQ^g8R..|
-00000290 51 16 34 5c f6 b1 04 30 7b f4 b0 f8 88 6c 9d bc |Q.4\...0{....l..|
-000002a0 32 5d 8b 73 b0 df f6 a2 dd e7 62 94 d7 b7 68 92 |2].s......b...h.|
-000002b0 d6 a6 6a b2 53 75 d8 a7 43 1f 1e a2 c0 4e 6a 84 |..j.Su..C....Nj.|
-000002c0 e7 6d ae 81 82 dc 43 bd 8c 44 6a db ec 37 34 70 |.m....C..Dj..74p|
-000002d0 a0 e3 39 a1 17 d2 b7 53 bc 06 0e 33 3f 91 b3 a6 |..9....S...3?...|
-000002e0 0a d1 43 b0 94 54 bc b9 07 52 40 6e 49 99 ab 09 |..C..T...R@nI...|
-000002f0 3f dc 5d 5f c9 33 59 03 3f cf 7b 47 54 2d 05 4b |?.]_.3Y.?.{GT-.K|
-00000300 c2 e6 81 f5 2f 58 5d 84 ad 9d 72 cc 3b 09 70 50 |..../X]...r.;.pP|
-00000310 75 f8 c8 b7 9a 3f b7 3e aa 6a 75 5d 16 03 03 00 |u....?.>.ju]....|
-00000320 e5 24 71 bf 67 14 d6 5e 2e 0b f5 20 45 e5 51 07 |.$q.g..^... E.Q.|
-00000330 98 f0 75 3c 5c f3 16 88 ba e7 76 fe 10 18 41 38 |..u<\.....v...A8|
-00000340 d5 df 7f 8b d3 2e 1c 0a 4c 83 57 fc e5 63 35 68 |........L.W..c5h|
-00000350 6e 23 5b c3 0c 9d f9 ab f8 3c 86 b6 ec 54 ec 52 |n#[......<...T.R|
-00000360 a4 45 cf 7b 31 a7 04 ef 5b 0b b1 11 50 8c 95 25 |.E.{1...[...P..%|
-00000370 9a 17 9b 4d 65 9c 0b d3 bb 0d 98 10 d9 34 52 7a |...Me........4Rz|
-00000380 f8 1e 9e 78 cb 41 27 47 31 cb 25 42 90 e9 3c 02 |...x.A'G1.%B..<.|
-00000390 49 17 01 5f 06 d2 f4 58 35 75 d5 9d 54 65 15 0d |I.._...X5u..Te..|
-000003a0 02 7e 94 fd c8 ac b8 c4 97 1c 9a 1c 9a 23 d5 d3 |.~...........#..|
-000003b0 44 c6 9a dd f9 b4 d1 48 e9 3d a0 5b d4 66 b3 d9 |D......H.=.[.f..|
-000003c0 11 0c d5 6d 0e 06 9c 00 90 30 d7 97 06 dc 0e e2 |...m.....0......|
-000003d0 59 51 7f b5 2e b8 f7 eb be 66 56 fa 9d a4 92 db |YQ.......fV.....|
-000003e0 82 3a d9 fc bd da c5 23 f6 2c 7b 36 2f a8 57 8e |.:.....#.,{6/.W.|
-000003f0 c6 0a 48 50 e3 f4 e7 07 95 48 9b 45 a9 ba cb e0 |..HP.....H.E....|
-00000400 3e ee 10 f9 0e cc 16 03 03 00 46 24 71 bf 67 14 |>.........F$q.g.|
-00000410 d6 5e 2f 97 87 ae b8 b4 fb f1 67 2b e7 0f f4 be |.^/.......g+....|
-00000420 24 0a f8 4a c0 42 4b 40 d3 ea e7 e0 f7 2a 9b 80 |$..J.BK@.....*..|
-00000430 bb 62 c0 2d d5 f8 52 19 49 d4 4c 45 1d c2 28 e7 |.b.-..R.I.LE..(.|
-00000440 8f fd b2 47 0e 22 d1 e1 b1 33 c1 26 6a fd 3f 9f |...G."...3.&j.?.|
-00000450 d8 |.|
+00000000 16 03 03 00 81 39 20 22 4a e1 4e 21 2e 78 35 50 |.....9 "J.N!.x5P|
+00000010 8a d4 c4 c6 a9 20 74 8e 10 4b fd 31 4c ba c4 7f |..... t..K.1L...|
+00000020 14 91 ab 4b 7a b2 7a 86 56 cc 61 ed 12 63 4a d5 |...Kz.z.V.a..cJ.|
+00000030 b5 c9 48 6e ae 10 71 fc 30 f5 e5 36 8b e2 7d 9d |..Hn..q.0..6..}.|
+00000040 93 e2 34 cd 8e a0 72 c4 19 9b 62 eb 9b c4 5e c3 |..4...r...b...^.|
+00000050 df 22 d4 16 4d 88 b1 d5 e5 74 ac 9d 38 40 7d 1f |."..M....t..8@}.|
+00000060 40 bd 86 e5 fc 19 88 bb 67 cf 3f 22 0f 39 1f 8f |@.......g.?".9..|
+00000070 40 5c ee 29 48 00 c1 bf 6a f1 85 51 03 c0 e8 7a |@\.)H...j..Q...z|
+00000080 2e f4 2a f9 b6 fb 16 03 03 02 69 59 b1 5a b9 98 |..*.......iY.Z..|
+00000090 86 77 af 76 a7 4c 69 0d 83 79 3c 9a b9 3c dd 49 |.w.v.Li..y<..<.I|
+000000a0 f2 0f ef d2 38 ac 31 b0 9b 5d 57 ed a7 ca f9 79 |....8.1..]W....y|
+000000b0 7c ef 58 f7 ca 7e 0c 60 1c 53 09 c5 06 dd b8 31 ||.X..~.`.S.....1|
+000000c0 09 88 af 50 9f c2 2a 2c 24 89 9e 57 ae c8 e6 49 |...P..*,$..W...I|
+000000d0 f4 6f 46 e9 dd 38 f1 52 e9 06 50 38 69 b3 e1 69 |.oF..8.R..P8i..i|
+000000e0 f5 33 28 54 39 43 05 b9 04 04 c2 d9 3d 34 da 48 |.3(T9C......=4.H|
+000000f0 99 7e 8a b2 59 d1 d3 20 da 34 c8 ab 91 f7 66 69 |.~..Y.. .4....fi|
+00000100 3a 4f fc 6d ee e6 ef f5 c0 b0 08 bf 59 c0 f8 e5 |:O.m........Y...|
+00000110 dc c6 dc c6 49 a7 d5 3c 22 0f e3 9f 39 0b 2a 09 |....I..<"...9.*.|
+00000120 7a 56 f8 90 33 05 06 09 21 6f 6a 53 0d 89 63 2a |zV..3...!ojS..c*|
+00000130 76 28 19 33 73 e5 a0 2a fa d2 82 bf 4c 43 84 f9 |v(.3s..*....LC..|
+00000140 e1 bb 7f 31 62 04 c5 26 ed 16 40 f5 6a 04 e0 c5 |...1b..&..@.j...|
+00000150 4e fe bd e3 4c 57 e2 61 41 2f 9a 95 7f 8a e1 34 |N...LW.aA/.....4|
+00000160 64 f4 fc ce 13 e5 0c 68 c1 e5 29 df e7 b1 56 0b |d......h..)...V.|
+00000170 42 6b fc d6 5d 63 0b 3c 0c ca ce 38 11 50 f2 64 |Bk..]c.<...8.P.d|
+00000180 1a 6e 16 da 3e 69 cf 82 ba a0 03 0f 9d 72 ed 10 |.n..>i.......r..|
+00000190 78 b2 54 c0 be 9c 16 fa 15 4b 88 db dd 85 dd 08 |x.T......K......|
+000001a0 bd f4 50 a0 50 01 77 7a cf 20 c1 3e 50 55 5f bd |..P.P.wz. .>PU_.|
+000001b0 4a ba b4 d5 6d 51 38 b2 6d 4f fc b5 af b9 92 ff |J...mQ8.mO......|
+000001c0 c4 44 f1 0e db 4d 71 09 15 b3 c3 37 47 57 03 35 |.D...Mq....7GW.5|
+000001d0 95 de da 33 31 8c 60 bc 8a 97 2d f8 27 9b 4e dc |...31.`...-.'.N.|
+000001e0 2a 6d aa 3e 4d eb 8f 97 b8 fa d4 ef f6 27 d9 da |*m.>M........'..|
+000001f0 a6 fe 38 91 4b 96 ff 75 4b 71 52 9f 37 e4 d9 85 |..8.K..uKqR.7...|
+00000200 a8 d8 ac 21 e9 b2 c0 4f c0 c0 e3 3a 9f ab e0 93 |...!...O...:....|
+00000210 dc 03 18 30 92 55 33 67 58 f3 47 f3 0a 95 bc 33 |...0.U3gX.G....3|
+00000220 70 73 e1 5b 9d 63 cf f7 c7 9b da 9e 5d 2e 7a 66 |ps.[.c......].zf|
+00000230 03 b1 b8 5c fa b9 f4 fb 4e 0b 38 9a 97 f0 c9 e5 |...\....N.8.....|
+00000240 ce 18 33 ea 66 1c 59 cd 41 3e af 71 7c bf 00 a0 |..3.f.Y.A>.q|...|
+00000250 d9 ee 20 d7 80 a9 5d 55 b8 f8 92 7b 7e 4f bc 66 |.. ...]U...{~O.f|
+00000260 92 98 6a c6 15 5b e3 1d 59 14 d9 d0 5a 30 c0 4d |..j..[..Y...Z0.M|
+00000270 37 f5 d9 40 a4 f9 f4 ad b6 cf 55 98 03 1e e7 13 |7..@......U.....|
+00000280 5a 23 49 69 36 fa ae 9d c2 cb 90 16 cc 36 f4 41 |Z#Ii6........6.A|
+00000290 3a c7 56 9f 05 23 be 1d 3f 8f 90 41 09 6b 88 9a |:.V..#..?..A.k..|
+000002a0 70 91 76 e1 6d f0 5c 86 de 77 a4 83 c7 d5 3c c4 |p.v.m.\..w....<.|
+000002b0 67 ff b1 a2 e2 f5 61 4f 3b 4d 38 5d c9 c2 8c 97 |g.....aO;M8]....|
+000002c0 e2 a7 c0 72 3b 5e 4c d9 0f 18 a8 b9 77 8d 31 8f |...r;^L.....w.1.|
+000002d0 d9 73 ac 33 a6 7a b5 bd 5e 58 b4 51 22 be d8 d4 |.s.3.z..^X.Q"...|
+000002e0 f5 e1 bc 37 80 d3 cf 3b 58 be 3e ce 33 83 1c 46 |...7...;X.>.3..F|
+000002f0 8b f3 f3 56 16 03 03 00 bc 30 f0 e1 0b eb 80 fe |...V.....0......|
+00000300 5f fb 94 c9 5a 04 08 82 0f 0b b5 9b f7 f6 f6 d3 |_...Z...........|
+00000310 7e 68 e7 e5 2e cf a0 56 e6 b7 70 0a 63 5e 53 42 |~h.....V..p.c^SB|
+00000320 7f 27 ec 82 a0 5d e3 e8 77 27 40 3c 6d 47 ce dd |.'...]..w'@<mG..|
+00000330 89 6e ac 0c 48 ab 25 d1 8e 4e 4e b8 99 69 a5 94 |.n..H.%..NN..i..|
+00000340 8d 19 ab f9 82 6b 28 e3 b8 5f f7 75 a8 dd 1f b5 |.....k(.._.u....|
+00000350 0a ff d1 72 4f 82 9b 9e 8e b3 3f f9 73 d6 cd ea |...rO.....?.s...|
+00000360 c8 5b 51 4e 7f 16 a5 4b 81 5e 9a d7 a3 f2 64 35 |.[QN...K.^....d5|
+00000370 fd 2e dc 11 07 10 04 63 80 77 eb 0d d2 ba 9f 7c |.......c.w.....||
+00000380 ad 66 eb 0a 2e f7 f2 3d d3 a4 04 7b 83 8f 84 94 |.f.....=...{....|
+00000390 93 8e 8c 74 2a b0 3a 3e e1 33 92 f9 59 e5 0a 56 |...t*.:>.3..Y..V|
+000003a0 95 3a 8b dc 1f 24 6c 08 07 c0 f1 20 6d 96 43 71 |.:...$l.... m.Cq|
+000003b0 bf c6 92 81 e3 16 03 03 00 3a 91 c1 13 a0 26 c9 |.........:....&.|
+000003c0 12 6a 09 23 5b 8b e8 da 10 cc 4d 00 ed 9e a6 09 |.j.#[.....M.....|
+000003d0 d8 d4 c0 b7 f0 cd 5f 7a 6e 4d 31 21 f6 6a 22 e7 |......_znM1!.j".|
+000003e0 6e 25 11 94 4a f2 b1 f1 b2 c9 30 4b e4 cd f3 f5 |n%..J.....0K....|
+000003f0 ce 86 e7 5d 16 03 03 00 14 20 c5 91 f0 6e 21 b8 |...]..... ...n!.|
+00000400 e8 a1 bb cf 62 ed 4b 5a fa 19 40 ea 54 |....b.KZ..@.T|
>>> Flow 13 (client to server)
-00000000 16 03 03 02 89 00 00 00 00 00 00 00 02 32 20 c7 |.............2 .|
-00000010 66 2d 3f e5 9b f9 e0 1c 7c 1f 3e 21 d9 51 af 9a |f-?.....|.>!.Q..|
-00000020 60 65 99 c7 3e 0b 48 f2 a3 8f eb ea 75 da af 60 |`e..>.H.....u..`|
-00000030 2e 5b ac 7f 9f d1 1f 69 86 18 49 3b 18 a2 e5 c5 |.[.....i..I;....|
-00000040 d0 c7 fe 3e c6 15 3d 5d 04 4d aa 7e 28 e3 20 d3 |...>..=].M.~(. .|
-00000050 55 c2 ed 4f 61 5f cc f9 39 5f 7d 3a 0f f2 81 5d |U..Oa_..9_}:...]|
-00000060 fd 4e 86 92 12 cd 2b b7 e6 46 49 b7 b8 5f 8f e5 |.N....+..FI.._..|
-00000070 b7 5e 64 2f 13 33 65 1c c8 c4 38 bd 70 94 23 e9 |.^d/.3e...8.p.#.|
-00000080 b6 57 81 c8 23 d1 57 85 91 c5 bc 5b 33 55 eb f5 |.W..#.W....[3U..|
-00000090 2d b3 76 53 44 e2 e8 66 fe 42 de f8 6f 03 37 d4 |-.vSD..f.B..o.7.|
-000000a0 a0 a4 75 7a 03 7f 00 92 eb 45 2f b8 5d 01 d3 4b |..uz.....E/.]..K|
-000000b0 e7 ca 2f 5b 3b 20 67 dc 32 2a 4c 06 1b 03 97 c1 |../[; g.2*L.....|
-000000c0 38 40 35 79 31 25 b0 fe d8 f3 b7 ee 6c ad 62 3e |8@5y1%......l.b>|
-000000d0 60 d6 96 6a 10 2b 14 8a 9e 72 f4 c9 63 6a 63 14 |`..j.+...r..cjc.|
-000000e0 d1 b0 e4 1f e9 3d 85 9d ed 11 3f 85 eb fa ca 46 |.....=....?....F|
-000000f0 17 f8 45 d5 65 28 79 8d 63 8e d7 22 40 9f c7 25 |..E.e(y.c.."@..%|
-00000100 ae e0 72 9f 60 70 95 59 99 25 41 1a e6 e9 45 cb |..r.`p.Y.%A...E.|
-00000110 3d 5a 2e 2d 4d c2 3c f2 3a 01 61 1f 96 d7 78 1a |=Z.-M.<.:.a...x.|
-00000120 cd 14 bd 87 75 23 10 7f 67 e4 8e fa 0a 9d 5d e9 |....u#..g.....].|
-00000130 12 f8 c7 35 c1 37 4c a4 91 a1 a5 de 79 9a a7 9c |...5.7L.....y...|
-00000140 ce d2 c9 72 a8 fa a3 27 24 8d 14 4e d7 11 f3 e9 |...r...'$..N....|
-00000150 07 4d 6d 47 92 4d e2 75 9a 71 d0 1e dd 09 61 0e |.MmG.M.u.q....a.|
-00000160 16 36 84 3a b1 dd 9b f8 09 dd 73 78 ed f7 29 4e |.6.:......sx..)N|
-00000170 a6 29 b0 31 54 72 ac 4b 7a 49 13 ba 9b ef b6 8b |.).1Tr.KzI......|
-00000180 48 dd a1 a7 9d 25 0e b7 37 42 5f 70 27 a7 59 40 |H....%..7B_p'.Y@|
-00000190 fe 72 1a 23 3e 71 b7 56 ef ff 02 c0 c9 07 99 20 |.r.#>q.V....... |
-000001a0 19 d2 9e 65 a5 5e f1 15 d3 ec 6e bb b1 c4 bf c0 |...e.^....n.....|
-000001b0 f8 71 19 bc 77 30 93 72 33 eb 1b c0 62 07 5e ca |.q..w0.r3...b.^.|
-000001c0 4a bf 89 5d 5d 44 23 fb 58 8e 71 b4 58 41 b9 97 |J..]]D#.X.q.XA..|
-000001d0 8b da b6 a0 b6 40 54 46 01 b9 47 79 21 bc 7c f3 |.....@TF..Gy!.|.|
-000001e0 4c 46 a3 92 ce d6 ec ac 3b 5d 6f 19 65 d1 b0 cd |LF......;]o.e...|
-000001f0 19 cd 2e 9d 6e 7d d3 57 44 c2 dd c6 56 dd e6 2b |....n}.WD...V..+|
-00000200 06 c6 f1 46 f1 ba ce e6 d9 c8 1e 03 5d b5 15 37 |...F........]..7|
-00000210 9d 8a d2 01 e7 28 33 30 a2 2b a3 42 d1 05 2f e9 |.....(30.+.B../.|
-00000220 7f 50 bf c8 7f 7b f8 c7 7e 12 3f 97 5e d5 1c 34 |.P...{..~.?.^..4|
-00000230 eb bf 2e c2 f0 6b 36 4e 09 c9 73 0e bb 3a cd f8 |.....k6N..s..:..|
-00000240 5f 2a 13 4d f2 92 b3 ae 4f dd 0e 82 a0 58 a9 be |_*.M....O....X..|
-00000250 2f c1 20 5c 64 48 11 e3 66 18 22 4d ea aa 76 21 |/. \dH..f."M..v!|
-00000260 07 ac 5a f2 14 38 a7 d8 9a 58 f8 92 62 77 3c 59 |..Z..8...X..bw<Y|
-00000270 1a 31 4e 3f 56 55 2b 9f 87 96 9c 7e c5 f0 10 fa |.1N?VU+....~....|
-00000280 90 a1 0b 9e e4 66 74 99 80 da 58 85 3d bd 16 03 |.....ft...X.=...|
-00000290 03 00 5e 00 00 00 00 00 00 00 03 42 d9 1d 19 27 |..^........B...'|
-000002a0 98 c0 29 9e bc 35 99 e9 e9 de f5 7c b7 2f ce a1 |..)..5.....|./..|
-000002b0 48 fe a9 79 26 c3 f1 74 63 73 3b 8d b7 4c 47 11 |H..y&..tcs;..LG.|
-000002c0 7c ea 6d 09 4c 1c 10 1d c9 b4 63 d4 5e c4 f1 34 ||.m.L.....c.^..4|
-000002d0 94 63 1c 04 a1 5f d0 65 7c b6 dd 2b a3 1c 1b 5f |.c..._.e|..+..._|
-000002e0 5c d6 dc 7f e7 df c4 75 ad df cc ae 71 47 64 cc |\......u....qGd.|
-000002f0 96 16 03 03 00 a0 00 00 00 00 00 00 00 04 61 37 |..............a7|
-00000300 a3 98 54 d1 7c 5d 14 b9 04 72 6e 02 ab 1a 15 2c |..T.|]...rn....,|
-00000310 93 07 15 ab 56 b1 ac d5 75 75 2e 25 ae 5e 3f fa |....V...uu.%.^?.|
-00000320 d0 20 ff 9d e0 ef fd 25 ed 4d 60 56 c7 33 07 d0 |. .....%.M`V.3..|
-00000330 57 09 e4 12 bd aa f0 d2 cc de 0d 45 23 ab b6 67 |W..........E#..g|
-00000340 ea d3 bc e1 4d 3a 75 9f 2d bb 53 b4 70 67 ce 63 |....M:u.-.S.pg.c|
-00000350 83 29 fa 27 2b db ea a3 19 be 79 77 cd 75 fb bf |.).'+.....yw.u..|
-00000360 c1 27 86 a6 a9 27 06 49 e1 77 13 0d e4 78 0c 07 |.'...'.I.w...x..|
-00000370 d4 1c af 76 f4 7b 05 04 5f 0f ec 66 f9 03 3e 81 |...v.{.._..f..>.|
-00000380 41 be 24 5f 43 2a 99 56 06 a9 d7 be ca 62 46 a2 |A.$_C*.V.....bF.|
-00000390 ba e1 a6 8b 1b 0a 14 03 03 00 19 00 00 00 00 00 |................|
-000003a0 00 00 05 f9 8f d4 80 bf ed b3 38 3a 12 d9 91 b6 |..........8:....|
-000003b0 cf 87 1a 1b 16 03 03 00 28 00 00 00 00 00 00 00 |........(.......|
-000003c0 00 fb 80 da 9a 59 82 9d d2 35 57 57 dd 76 a1 b1 |.....Y...5WW.v..|
-000003d0 4a dc a5 cb f6 81 3f e3 4d cc 0e 7f 3a 96 85 f3 |J.....?.M...:...|
-000003e0 ea |.|
+00000000 16 03 03 02 69 1a b5 80 9c c6 42 be a6 d9 d1 c8 |....i.....B.....|
+00000010 0b 2c f7 f8 2a 1a 02 f6 db 48 8b 5c 45 fc 28 41 |.,..*....H.\E.(A|
+00000020 a4 db 35 fb a7 a9 72 07 19 86 9e e9 dc 53 48 fb |..5...r......SH.|
+00000030 97 94 f3 a0 0d 8d 46 69 cf eb d9 ea de 21 a3 f4 |......Fi.....!..|
+00000040 b9 94 4f 8f 09 c3 de 66 fa 20 83 34 fc 50 ae c6 |..O....f. .4.P..|
+00000050 13 f6 7c c5 80 45 17 51 af a9 da bd 24 dd f6 15 |..|..E.Q....$...|
+00000060 8e c4 b4 e6 10 54 85 23 9d fe 72 b1 4c 2f ab ec |.....T.#..r.L/..|
+00000070 78 9a 06 60 03 96 f7 d0 af dd 94 26 c9 67 1d e5 |x..`.......&.g..|
+00000080 9f 87 22 c4 11 82 f1 4c f5 68 a7 fd d8 f3 dc ac |.."....L.h......|
+00000090 35 90 6b c2 97 1c 78 54 d9 b2 3c d8 9d 13 66 42 |5.k...xT..<...fB|
+000000a0 6e 3b 1b 8f 32 4e 8f b5 a0 60 6e e4 35 fd d5 b4 |n;..2N...`n.5...|
+000000b0 f8 fb a6 a9 c7 b7 31 39 8e 90 0c 42 bc 1a 4f 67 |......19...B..Og|
+000000c0 fa b3 10 a8 45 01 88 8a dd 41 43 c6 6c 41 9d 28 |....E....AC.lA.(|
+000000d0 bd 4c 43 85 4c 3b 7c 03 c4 55 70 f1 49 a0 d6 52 |.LC.L;|..Up.I..R|
+000000e0 5c 49 3e 2b d7 e8 a9 75 5e 92 bf f3 4c 1c c3 7e |\I>+...u^...L..~|
+000000f0 69 ca 52 25 07 bb 54 e0 58 2d 28 ba 50 30 81 e8 |i.R%..T.X-(.P0..|
+00000100 93 0d 9d 78 3d c0 f1 c3 34 72 29 f1 da 60 de 84 |...x=...4r)..`..|
+00000110 aa fc d3 0f 2b 1e 1a 9c 7c af 6f 6a 4c cc 88 36 |....+...|.ojL..6|
+00000120 03 03 34 79 f9 89 6d 41 bb 19 61 6a 60 75 d7 0f |..4y..mA..aj`u..|
+00000130 dc 22 7a e4 36 91 32 2b 99 24 36 19 4b 4c c4 ae |."z.6.2+.$6.KL..|
+00000140 4f 98 6d f0 97 ce bc b4 ee 97 30 97 0b 54 8c 14 |O.m.......0..T..|
+00000150 8f d5 9d 44 ae 0a a6 07 9f 39 f6 66 80 cb fa 27 |...D.....9.f...'|
+00000160 bb 2f 26 bb c3 1a a4 9b a0 d3 e8 75 13 49 da 0a |./&........u.I..|
+00000170 8f cc e8 15 77 f8 05 c2 17 a0 ff e7 2a 59 bc c8 |....w.......*Y..|
+00000180 67 b5 7e b8 78 1e 32 81 22 3e 57 28 ee 51 96 b7 |g.~.x.2.">W(.Q..|
+00000190 0e dc 3f d1 00 16 a5 eb 01 cb c3 e3 5b 01 ad a9 |..?.........[...|
+000001a0 d5 1b ac 9b e2 0d 9a 6f 7a 2f f1 7d 05 57 6d 2d |.......oz/.}.Wm-|
+000001b0 9d 35 68 88 e7 c5 e0 fb 9d 87 a7 ef 71 d8 47 b8 |.5h.........q.G.|
+000001c0 19 8e 87 d8 b1 36 0f 52 ab 98 8b 97 43 53 86 be |.....6.R....CS..|
+000001d0 9d 86 2a cd 7c b0 46 c4 48 89 5b 6c 1e 93 9e a2 |..*.|.F.H.[l....|
+000001e0 15 af 60 8f 84 75 99 97 53 11 23 f9 0d ba 78 12 |..`..u..S.#...x.|
+000001f0 9b a9 04 91 d0 3a b3 4d 7b 67 a0 fa 78 5c 19 d6 |.....:.M{g..x\..|
+00000200 88 d2 21 f6 8d e4 91 d1 76 95 67 9d 4e 3b a1 d2 |..!.....v.g.N;..|
+00000210 61 c3 d2 a6 53 fd 82 93 20 7e f6 07 a0 49 3a ea |a...S... ~...I:.|
+00000220 bc 73 03 0b f2 df 51 ac 35 d8 e4 35 9d 13 56 b5 |.s....Q.5..5..V.|
+00000230 be fc 7c 36 8b 37 a0 71 57 62 bd 89 38 18 90 1e |..|6.7.qWb..8...|
+00000240 7a 1f b3 8f 73 55 32 94 5a 3a 31 91 b3 95 bd 61 |z...sU2.Z:1....a|
+00000250 ea 93 9d f0 38 33 fb 5b 28 3d a7 29 a4 91 de 85 |....83.[(=.)....|
+00000260 9c 16 63 10 81 c6 e0 11 92 3d 53 db 69 95 16 03 |..c......=S.i...|
+00000270 03 00 35 f7 3a b7 d1 20 aa f7 ed b1 c7 46 52 cb |..5.:.. .....FR.|
+00000280 6e dd e2 f4 ae 83 20 cd 6c 59 b5 26 f9 81 7e 6c |n..... .lY.&..~l|
+00000290 ed e9 0b 2a f1 3a dc f8 d6 ed e5 6d 89 14 3d 79 |...*.:.....m..=y|
+000002a0 e7 c8 af 89 30 eb 98 3d 16 03 03 00 98 a0 59 2f |....0..=......Y/|
+000002b0 cd d9 f6 63 e3 53 47 77 e5 c4 fc 2e 12 d7 24 8a |...c.SGw......$.|
+000002c0 4c c7 d8 c9 77 4f bc 3c af 93 6f 57 3d 6f 5d 1c |L...wO.<..oW=o].|
+000002d0 6a 5a 2c 42 1c e0 92 d5 5e 34 c8 a5 9e 11 21 16 |jZ,B....^4....!.|
+000002e0 01 1a 08 af 4e f6 a1 e3 19 a6 81 41 3d 7a f3 d1 |....N......A=z..|
+000002f0 e0 9e 55 90 42 4b d9 5c 46 b7 eb c8 fb 83 1c 97 |..U.BK.\F.......|
+00000300 9e d9 74 bb 7f 2f 4d 61 89 46 db 32 da 1a 76 95 |..t../Ma.F.2..v.|
+00000310 88 f8 ca 62 14 88 dc 97 b8 58 82 74 16 78 be c5 |...b.....X.t.x..|
+00000320 f9 78 a4 88 c1 d4 6b 36 6e 54 60 a5 21 30 47 07 |.x....k6nT`.!0G.|
+00000330 e8 2d 22 ce a5 17 fb 43 10 9d 74 c9 64 a3 db ac |.-"....C..t.d...|
+00000340 d9 24 7a a7 5d 14 03 03 00 11 68 20 87 e9 9b 91 |.$z.].....h ....|
+00000350 81 67 2b 31 c4 47 e8 9b 2e 7c c4 16 03 03 00 20 |.g+1.G...|..... |
+00000360 ef 6f 3d 0f 23 fa 77 8c a9 46 d9 0d b0 d9 f8 16 |.o=.#.w..F......|
+00000370 62 e2 07 21 ec b6 a7 78 ce a6 ea b3 68 c1 c7 af |b..!...x....h...|
>>> Flow 14 (server to client)
-00000000 14 03 03 00 19 24 71 bf 67 14 d6 5e 30 cc 1c 3f |.....$q.g..^0..?|
-00000010 3c 20 07 b3 c3 79 d0 6e fd 59 e6 0d 47 fd 16 03 |< ...y.n.Y..G...|
-00000020 03 00 28 54 db a5 f7 3d b3 18 49 39 e5 59 93 bb |..(T...=..I9.Y..|
-00000030 64 93 1c ed 46 d6 f8 89 94 45 ba 4a 9e 73 2e cb |d...F....E.J.s..|
-00000040 03 18 e4 26 6d 33 e3 34 73 d6 fc 17 03 03 00 21 |...&m3.4s......!|
-00000050 54 db a5 f7 3d b3 18 4a aa 45 38 3b 50 02 44 37 |T...=..J.E8;P.D7|
-00000060 6a d1 3e f9 d3 3b 33 33 d5 84 2d 52 33 7d 68 84 |j.>..;33..-R3}h.|
-00000070 ef |.|
+00000000 14 03 03 00 11 bb 45 96 9e 08 cb e4 24 c2 e3 71 |......E.....$..q|
+00000010 40 d1 ef a1 5e 2f 16 03 03 00 20 1b 3f 69 fb ae |@...^/.... .?i..|
+00000020 cd 98 15 59 16 14 cf a5 16 af 36 6d 6d 3a 49 06 |...Y......6mm:I.|
+00000030 a6 f9 cf 53 ea 9a b7 3b 48 d2 e3 17 03 03 00 19 |...S...;H.......|
+00000040 72 2c 82 a0 8c 6c 8b c3 78 e4 41 1b ff ba 92 6d |r,...l..x.A....m|
+00000050 3c 4d 9c c3 95 e3 27 b9 82 |<M....'..|
>>> Flow 15 (client to server)
-00000000 15 03 03 00 1a 00 00 00 00 00 00 00 01 55 5f 94 |.............U_.|
-00000010 25 d0 89 86 cb 8f 33 6f b7 b6 35 ec 0f 6a 87 |%.....3o..5..j.|
+00000000 15 03 03 00 12 3d f9 72 53 84 b5 a4 ec 27 39 cc |.....=.rS....'9.|
+00000010 72 29 c0 e6 37 7b 0f |r)..7{.|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected
index fe2fa88a90e..737ccc61baa 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiateTwiceRejected
@@ -1,255 +1,234 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 51 0e b9 8f 73 |....Y...U..Q...s|
-00000010 ec 20 17 90 80 3a 43 7a bc 19 19 f5 75 c3 76 a6 |. ...:Cz....u.v.|
-00000020 53 53 4b 77 ce dd ca 4b 1b 1e ed 20 8d e5 a7 6f |SSKw...K... ...o|
-00000030 53 e9 a4 06 4b 01 a6 08 a1 90 e5 da c9 e3 74 b0 |S...K.........t.|
-00000040 87 1f 17 1a 68 d3 f7 ae 39 b8 3e 80 c0 2f 00 00 |....h...9.>../..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 75 f6 1b 17 2f |....Y...U..u.../|
+00000010 e0 d4 19 06 0d 93 90 51 46 d9 c3 a0 cd 45 6c 85 |.......QF....El.|
+00000020 94 87 01 21 3e 92 62 1d e7 d1 39 20 07 26 a1 5b |...!>.b...9 .&.[|
+00000030 d2 4a 61 40 ba 58 c0 23 0c 3f c3 08 5d 28 04 94 |.Ja@.X.#.?..](..|
+00000040 a9 34 37 28 64 75 6f 9c ae fa 1f 24 cc a8 00 00 |.47(duo....$....|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
-00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
-00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
-000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
-000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
-000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
-000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
-000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
-000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
-00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
-00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
-00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
-00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
-00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
-00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
-00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
-00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
-00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
-00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
-000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
-000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
-000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
-000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
-000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
-000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
-00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
-00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
-00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
-00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
-00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
-00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
-00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
-00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
-00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
-00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
-000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
-000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
-000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
-000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............|
-000002e0 41 04 5e 2e 43 b7 c2 0f e8 4a 33 aa b8 d6 04 7f |A.^.C....J3.....|
-000002f0 2b be a2 e3 6f fa 05 1a d1 64 a7 d1 ec 45 f9 16 |+...o....d...E..|
-00000300 b7 75 ad f2 52 3e a3 60 67 f8 fb 87 a0 c0 d4 2f |.u..R>.`g....../|
-00000310 f4 66 c9 dd 38 40 79 5b 16 75 0b 16 6a d8 e5 ad |.f..8@y[.u..j...|
-00000320 63 f3 04 01 00 80 5e 89 b3 6b f4 a1 35 b3 27 be |c.....^..k..5.'.|
-00000330 6a d4 39 42 7c ac e2 d4 9f a0 a0 a3 95 22 b5 09 |j.9B|........"..|
-00000340 70 4a 0c 6f cf 7f 69 f9 7d 27 c4 0d e7 b8 9c 82 |pJ.o..i.}'......|
-00000350 c9 0d 1d bb 5c 23 20 eb ca 09 ca 02 a0 56 27 10 |....\# ......V'.|
-00000360 c5 d6 13 7d cd 05 64 cc 53 20 5d df ac 00 90 7f |...}..d.S ].....|
-00000370 d7 cd f2 a1 07 9c 06 c2 e6 d1 94 60 d3 c6 97 a6 |...........`....|
-00000380 3c e5 89 67 e7 cc b7 c1 ba 75 dc 17 2b 47 ce 23 |<..g.....u..+G.#|
-00000390 a3 37 3b 3f 32 39 ae 4a 64 17 d2 64 d1 75 23 8a |.7;?29.Jd..d.u#.|
-000003a0 e3 b4 fa 75 17 72 16 03 03 00 04 0e 00 00 00 |...u.r.........|
+00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
+000002c0 ac 0c 00 00 a8 03 00 1d 20 84 74 e5 bc 24 39 39 |........ .t..$99|
+000002d0 e0 6e 35 fb 34 87 76 0d 78 89 35 5c 85 e7 92 da |.n5.4.v.x.5\....|
+000002e0 e1 39 f4 b2 e7 ec d5 cd 58 04 01 00 80 cf 3a 57 |.9......X.....:W|
+000002f0 6a 8b b7 72 d8 a2 6b 47 87 77 8b 7a bf 63 6c e8 |j..r..kG.w.z.cl.|
+00000300 d4 20 6a 6a 9c 62 b6 ef 4b 9f a7 89 8c a6 fd 02 |. jj.b..K.......|
+00000310 92 2f 8d 07 44 09 f6 d9 03 99 39 49 1d 8d 1b 7f |./..D.....9I....|
+00000320 eb eb 4b a6 fb 9f 83 3b 3d d3 61 3e e4 d3 22 24 |..K....;=.a>.."$|
+00000330 c1 44 76 e8 75 c7 aa 31 96 e3 50 bb 76 3e 87 02 |.Dv.u..1..P.v>..|
+00000340 b9 1d 82 dd 55 ee 05 b9 b5 1e 65 90 2c 50 c9 87 |....U.....e.,P..|
+00000350 49 dd 35 c8 84 67 6e 52 3a 3b ec 3c 63 f4 0f 95 |I.5..gnR:;.<c...|
+00000360 87 05 8e ec bd d7 97 9f 9a 14 78 d7 97 16 03 03 |..........x.....|
+00000370 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 4f ef |.....(........O.|
-00000060 08 7c a7 de 53 70 7e 78 fb 08 79 97 1f bd 33 92 |.|..Sp~x..y...3.|
-00000070 c5 46 4d 64 32 bb 94 f0 07 ad 7d 00 86 9e |.FMd2.....}...|
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 20 3e a2 12 3b a4 83 4a c2 0e 93 d5 |.... >..;..J....|
+00000040 98 d5 2e 11 9e 60 60 23 78 5a 63 49 f1 7a ee c4 |.....``#xZcI.z..|
+00000050 47 00 6c 4e fb |G.lN.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 59 c3 19 1f ed |..........(Y....|
-00000010 d1 1b 54 5b 66 81 47 29 9a 77 84 87 a0 bd c5 d4 |..T[f.G).w......|
-00000020 f0 4e e2 11 d3 1d 26 dd 87 7a 55 11 48 37 7f 3a |.N....&..zU.H7.:|
-00000030 2c fc 62 |,.b|
+00000000 14 03 03 00 01 01 16 03 03 00 20 6d 78 5b 5f 1b |.......... mx[_.|
+00000010 2c 05 ba 92 46 e2 f0 04 48 fa a1 da be 93 ed fd |,...F...H.......|
+00000020 f5 f8 b8 dd 00 60 09 a6 36 3c c4 |.....`..6<.|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 02 12 57 |...............W|
-00000010 9d 64 c5 47 13 95 13 7b 2b 3e e0 f7 ae 49 0f c7 |.d.G...{+>...I..|
-00000020 0e 3a 67 |.:g|
+00000000 17 03 03 00 16 a4 db 13 bc c1 6e 06 9e 6d 1a c9 |..........n..m..|
+00000010 85 a7 e9 28 b8 27 74 19 8f 1a bc |...(.'t....|
>>> Flow 6 (server to client)
-00000000 16 03 03 00 1c 59 c3 19 1f ed d1 1b 55 ac 23 dc |.....Y......U.#.|
-00000010 0c 35 65 1e 7a 65 4f 47 13 46 a0 d0 d0 4d 0a 1f |.5e.zeOG.F...M..|
-00000020 5c |\|
+00000000 16 03 03 00 14 fa a3 77 3c 76 11 5d be 12 4f 6a |.......w<v.]..Oj|
+00000010 f7 0d 26 73 ab 7c bd 4b 19 |..&s.|.K.|
>>> Flow 7 (client to server)
-00000000 16 03 03 00 a9 00 00 00 00 00 00 00 02 c0 05 0c |................|
-00000010 76 0a 46 19 16 17 a6 75 af 11 bb 73 37 74 a4 26 |v.F....u...s7t.&|
-00000020 d9 16 93 b8 19 5e 2f 17 52 d1 12 9e 36 90 4e c9 |.....^/.R...6.N.|
-00000030 7a f9 89 75 3b d9 d4 e1 2e cf a0 5d 03 7d cc f6 |z..u;......].}..|
-00000040 73 aa a9 52 c7 65 78 d0 89 6f b1 15 6e f9 9e 55 |s..R.ex..o..n..U|
-00000050 42 9e 22 09 df 97 00 31 b8 73 57 1b 93 ff 0c e7 |B."....1.sW.....|
-00000060 46 29 40 79 a7 c0 de b9 44 93 7b 4d 35 a0 35 65 |F)@y....D.{M5.5e|
-00000070 6e 58 07 90 2b 11 49 26 10 f7 c7 32 f7 8e 6e a7 |nX..+.I&...2..n.|
-00000080 9b 75 ba cb 4a ce f7 f0 f1 31 ca 04 a6 02 d0 62 |.u..J....1.....b|
-00000090 da 9b 8b 27 8e 04 b8 4a 49 0d d6 31 10 93 30 37 |...'...JI..1..07|
-000000a0 ad ea d7 c4 49 98 90 f3 a1 45 f4 69 2e 59 |....I....E.i.Y|
+00000000 16 03 03 00 ad 59 80 a4 91 95 56 2a 01 ee 04 84 |.....Y....V*....|
+00000010 f9 d2 dd a5 2c a6 46 a8 69 a3 c7 47 7e eb 54 da |....,.F.i..G~.T.|
+00000020 ec cc 9d aa e1 0a b1 7c e9 cf 9f c9 c8 12 62 35 |.......|......b5|
+00000030 d2 4a eb 28 0d 9b aa a4 d5 79 66 f7 72 4c 26 10 |.J.(.....yf.rL&.|
+00000040 b6 71 db 4a 68 8b 47 f9 47 e3 6d a6 4e 99 d5 0b |.q.Jh.G.G.m.N...|
+00000050 27 b2 2c 23 9b 58 60 8a 37 a1 8e 26 09 26 2a 46 |'.,#.X`.7..&.&*F|
+00000060 e6 24 7f 9b cb 6b d1 9d b1 c0 48 c9 50 8b ab 06 |.$...k....H.P...|
+00000070 05 57 ef 1a e0 bd ce db ca 3d e1 59 df 24 4c 02 |.W.......=.Y.$L.|
+00000080 bf 1b 9e 48 52 42 6c dd 8f fa 82 68 56 52 a6 be |...HRBl....hVR..|
+00000090 d0 93 cb 43 74 e1 2f 86 cc e1 4c fa ba fc 1d f0 |...Ct./...L.....|
+000000a0 d5 20 3a 79 b3 b8 b7 24 b5 cf 4c dd a5 d0 4d 18 |. :y...$..L...M.|
+000000b0 15 55 |.U|
>>> Flow 8 (server to client)
-00000000 16 03 03 00 89 59 c3 19 1f ed d1 1b 56 c8 38 86 |.....Y......V.8.|
-00000010 22 b6 5f 55 cb 0c e1 40 e6 12 f2 71 d5 09 bc 47 |"._U...@...q...G|
-00000020 ea 83 38 3a 58 f4 34 da ae 7f 64 fb 8c bc 71 64 |..8:X.4...d...qd|
-00000030 1b aa 84 e4 3e c1 cc c4 a9 05 36 13 5a 9b 1e c0 |....>.....6.Z...|
-00000040 44 cc 86 54 f0 75 b7 d0 aa b0 f0 3a b5 c7 f1 cc |D..T.u.....:....|
-00000050 1f cd 8e 9e 9e bb 24 23 c3 05 0b a5 1d f3 0b 41 |......$#.......A|
-00000060 41 19 89 1e ee 51 fc b3 e8 e2 6e a8 3f c4 8b ab |A....Q....n.?...|
-00000070 cb af d9 a1 7e 1c db e7 6c f6 23 71 c6 31 db 40 |....~...l.#q.1.@|
-00000080 a8 a7 08 fb 1a ff 8d 94 53 88 9a 11 73 6a 16 03 |........S...sj..|
-00000090 03 02 89 59 c3 19 1f ed d1 1b 57 17 dd 9c b5 a5 |...Y......W.....|
-000000a0 89 12 3a 14 61 34 e0 1d 0b 35 d6 3a 6c 09 93 2b |..:.a4...5.:l..+|
-000000b0 6c 69 ee f4 f3 be fb 42 33 99 fd 9a e6 21 38 68 |li.....B3....!8h|
-000000c0 a6 19 37 43 24 81 ba 35 12 fe ab ed 49 0b 03 54 |..7C$..5....I..T|
-000000d0 11 a7 74 4d bb ba e7 b9 f3 ee 6a 4e 1a 84 2f 03 |..tM......jN../.|
-000000e0 0c d1 28 21 49 84 f4 3c 5b 15 92 07 5c 6a 24 89 |..(!I..<[...\j$.|
-000000f0 00 cf 78 31 76 23 0f 9d 45 3b 93 a5 68 ee 9c 73 |..x1v#..E;..h..s|
-00000100 14 3f 08 30 37 40 4e 8b a4 02 03 3c 4b 52 74 99 |.?.07@N....<KRt.|
-00000110 0e 9a ec 40 c6 74 16 ef c5 48 68 33 86 d7 06 57 |...@.t...Hh3...W|
-00000120 bf 8a 6f 3f 41 fe 4d f2 37 0a 1b fd fb 66 55 bd |..o?A.M.7....fU.|
-00000130 70 4d b0 8c 4f 78 24 eb 1f 8f 22 c7 aa 07 89 04 |pM..Ox$...".....|
-00000140 6a b3 07 15 37 25 21 63 97 39 b1 c1 9b fa 81 5e |j...7%!c.9.....^|
-00000150 69 c9 c7 4a 9c 5d b3 6a 41 d0 5e b9 f4 d5 5c a1 |i..J.].jA.^...\.|
-00000160 8e 8a ad 58 6e 5c 4f 73 62 38 1c 5f 8d b1 67 63 |...Xn\Osb8._..gc|
-00000170 49 da 4b 4e 83 54 34 8f 8d 12 de 4e 43 4d dc b9 |I.KN.T4....NCM..|
-00000180 02 ab 08 59 db 0b 45 7e f5 b8 e2 33 f1 04 de 16 |...Y..E~...3....|
-00000190 05 bf b4 2b 07 a1 11 e4 9e 48 f7 52 ab 20 89 04 |...+.....H.R. ..|
-000001a0 a7 44 28 7a 12 6c 19 ab 2f 68 1a d9 26 ec 72 a0 |.D(z.l../h..&.r.|
-000001b0 62 83 48 6f 4b 70 7d 74 3a 43 4f a6 38 37 fe 59 |b.HoKp}t:CO.87.Y|
-000001c0 6e 72 5d 81 7d 2c c7 e1 6b 06 47 41 56 17 2c 25 |nr].},..k.GAV.,%|
-000001d0 06 b1 7f f5 10 0a 31 a3 12 b1 5c 01 2f e0 a6 e4 |......1...\./...|
-000001e0 fa ab d2 0b 02 77 ad ac f8 54 db 70 20 0a 1f 04 |.....w...T.p ...|
-000001f0 86 a8 32 05 26 ee 7d e0 e9 03 19 cc 8f 67 f5 b6 |..2.&.}......g..|
-00000200 97 fe 06 5e c1 d5 df 25 f5 39 70 64 57 a8 c9 84 |...^...%.9pdW...|
-00000210 8f 0f 25 f8 c8 f9 17 70 e5 00 3c 4a 9f 4b c1 d9 |..%....p..<J.K..|
-00000220 6e b8 1a e4 6d 85 a4 e2 42 44 71 ba 43 9b 03 70 |n...m...BDq.C..p|
-00000230 14 ff 72 5e 5c 69 24 2e 52 0c 73 8b df 50 99 68 |..r^\i$.R.s..P.h|
-00000240 57 81 c1 ed b6 33 fc 74 15 45 fd a2 c4 8c f8 95 |W....3.t.E......|
-00000250 bf 8d 0e 92 91 42 72 77 03 ec c6 f6 9a 02 ca 7d |.....Brw.......}|
-00000260 3c 87 72 eb 8d 30 3a 5c b4 03 4a 6d 2e 83 22 c5 |<.r..0:\..Jm..".|
-00000270 e2 4a 95 83 7a 72 72 f2 2a 11 25 4a bd 04 16 ab |.J..zrr.*.%J....|
-00000280 6a 48 44 2b 99 fb 6f 61 9a 14 4a 42 1e bf d1 82 |jHD+..oa..JB....|
-00000290 db 62 5f ac 1e 6d 1d 1b 0d 4b 9d 8d 3a 84 94 b4 |.b_..m...K..:...|
-000002a0 aa 08 5b 90 7f d2 46 b0 a7 40 f4 55 76 6b 0d 4c |..[...F..@.Uvk.L|
-000002b0 8e e3 8c fd ed 33 7d 93 f8 d8 c3 db 26 2d db a1 |.....3}.....&-..|
-000002c0 24 bc b0 fb 26 5f ec 13 5f 97 05 bb 5c 3c cc a3 |$...&_.._...\<..|
-000002d0 c2 57 58 cd 2e 70 0c a7 77 c5 e5 e8 0c 42 f2 e0 |.WX..p..w....B..|
-000002e0 1c 11 0f 62 4b 84 49 c2 b7 10 83 2e 16 1c 38 d4 |...bK.I.......8.|
-000002f0 10 f7 ca 71 7a 87 c5 a3 66 d2 98 1e c8 f2 c0 37 |...qz...f......7|
-00000300 0e 28 31 fe 8e 3e f4 03 74 6e 91 42 22 cb 5d 7f |.(1..>..tn.B".].|
-00000310 d2 22 da 3c f2 a0 2d 09 a9 a5 2d 14 16 03 03 00 |.".<..-...-.....|
-00000320 e5 59 c3 19 1f ed d1 1b 58 3f 19 93 55 cb 19 f8 |.Y......X?..U...|
-00000330 02 1a 43 b3 b2 6c 4e 3e ee 99 b3 df fd 45 24 ac |..C..lN>.....E$.|
-00000340 63 e7 45 cc a4 44 ca cf 3a e1 81 88 01 9a b3 64 |c.E..D..:......d|
-00000350 fe 6b 36 57 9f 81 fc 40 8d ef 21 af 00 be 43 f7 |.k6W...@..!...C.|
-00000360 a3 3b a3 fa f0 01 f2 b4 ab 8a d1 a8 14 58 1b 6f |.;...........X.o|
-00000370 75 01 35 92 54 a7 a6 c1 99 1e 92 d8 87 53 7b 42 |u.5.T........S{B|
-00000380 4a 76 96 5e e9 db bb 4e f1 d9 bb e6 d2 b0 34 10 |Jv.^...N......4.|
-00000390 1b 4c d5 2c ca af 19 0d 3e 77 ee 77 0e 5f ff e2 |.L.,....>w.w._..|
-000003a0 02 c5 4a f2 ec 0b 7d cf d1 e7 3c 72 d2 17 4d 6c |..J...}...<r..Ml|
-000003b0 a7 ca 3a 1b 00 2b 69 17 e5 a9 82 69 49 c2 ff 8a |..:..+i....iI...|
-000003c0 f1 e8 ab 1b c3 8d da f1 31 ba a6 f4 7c 3c 01 6f |........1...|<.o|
-000003d0 ed a8 6f e2 4f a3 68 77 b7 54 b5 87 1b 5c 5c fb |..o.O.hw.T...\\.|
-000003e0 83 bf 48 4d 36 43 d6 f7 0a 48 74 f3 44 9d 43 53 |..HM6C...Ht.D.CS|
-000003f0 f8 54 1b 57 97 24 53 5a 93 e2 e9 33 f0 35 5f 0a |.T.W.$SZ...3.5_.|
-00000400 0d 4c ce 92 4d c9 16 03 03 00 46 59 c3 19 1f ed |.L..M.....FY....|
-00000410 d1 1b 59 80 50 fc 3a 56 e0 0b 06 b4 58 39 0c d8 |..Y.P.:V....X9..|
-00000420 4b b1 11 7a bd cf 1c 78 41 62 ee 22 74 61 7d 61 |K..z...xAb."ta}a|
-00000430 91 3d 0a 74 a4 b0 cd 25 70 19 a5 de d8 1b df 12 |.=.t...%p.......|
-00000440 4e b8 71 db ac bc 48 ea 89 32 ec 27 69 02 0d 8b |N.q...H..2.'i...|
-00000450 83 |.|
+00000000 16 03 03 00 81 10 b8 d9 9a 82 21 14 86 6d ef e4 |..........!..m..|
+00000010 b6 bc 10 84 80 a6 72 7b dc 24 ba e1 e5 d2 bb d2 |......r{.$......|
+00000020 9f 09 d3 d7 37 20 ec 7d bd 13 e0 bd 40 44 8a 6e |....7 .}....@D.n|
+00000030 7f f6 d5 42 03 4b 00 b5 87 99 ac 6d 11 03 38 46 |...B.K.....m..8F|
+00000040 33 71 c4 10 ce da 36 d6 c1 41 9f 96 8e eb 4b 99 |3q....6..A....K.|
+00000050 24 07 8c 6b 88 2c f1 dd 31 35 ba 43 0f 60 bf b0 |$..k.,..15.C.`..|
+00000060 74 77 a9 d4 a7 65 f6 68 e2 70 4a 7e fe db ab 13 |tw...e.h.pJ~....|
+00000070 7f 51 c3 0f b4 93 42 12 d6 29 5d 44 5c df 17 6e |.Q....B..)]D\..n|
+00000080 73 1d b8 95 fc 8b 16 03 03 02 69 64 5d 4f b4 3a |s.........id]O.:|
+00000090 23 98 07 51 63 18 09 07 9a 8c dd 8e 51 a8 ca 23 |#..Qc.......Q..#|
+000000a0 37 21 f4 d5 e0 8f 03 1c 6f 6d c4 60 dd 99 8f 4b |7!......om.`...K|
+000000b0 4c 11 f7 78 f8 aa f6 29 87 cf 4d ba 89 87 2a c9 |L..x...)..M...*.|
+000000c0 48 66 48 d3 a6 19 8a 84 f6 db 17 b4 59 5b e4 8e |HfH.........Y[..|
+000000d0 8e ef fc 32 10 aa 0d 57 47 68 82 07 72 95 03 f6 |...2...WGh..r...|
+000000e0 e5 c1 c3 01 00 f9 85 4f 0f 85 37 73 f7 c5 af a2 |.......O..7s....|
+000000f0 37 96 ba 06 49 6a 2d a2 23 39 2e 9b f1 fc 01 de |7...Ij-.#9......|
+00000100 53 75 ee 34 ae 27 ea 49 6a d8 d0 cd 9b e8 60 b7 |Su.4.'.Ij.....`.|
+00000110 f6 b1 8e 26 ec 6c 36 87 d6 70 49 07 e0 96 2a bd |...&.l6..pI...*.|
+00000120 45 a3 b1 f5 dc b0 a3 4f dc d8 c3 fd 4f fb 98 13 |E......O....O...|
+00000130 67 55 99 39 b5 16 19 72 9d f1 5a cf 6e 53 d9 03 |gU.9...r..Z.nS..|
+00000140 05 f5 81 07 a1 38 a1 e5 4c 76 51 1a ae f6 4b f6 |.....8..LvQ...K.|
+00000150 b2 a7 84 1e 2a 31 b0 b8 9f 41 e8 e5 32 18 44 4c |....*1...A..2.DL|
+00000160 0b fb e3 d9 4c dd 45 c5 c4 c4 57 bf f7 5a dc f6 |....L.E...W..Z..|
+00000170 73 98 d4 ea 2f c0 cb 35 97 c1 45 94 37 87 d3 8c |s.../..5..E.7...|
+00000180 65 3f ee a8 67 a6 00 80 92 02 76 e8 0a 04 ce 7a |e?..g.....v....z|
+00000190 79 4f cd 70 1a 31 5a 03 83 01 de 1f 4a 46 39 4e |yO.p.1Z.....JF9N|
+000001a0 d0 80 6e 67 d7 e6 fc ba 74 4b 57 d2 3c 19 7b 03 |..ng....tKW.<.{.|
+000001b0 ab 9a e2 f7 db 58 c2 b7 58 96 55 88 e6 e2 e2 f8 |.....X..X.U.....|
+000001c0 ab e9 b0 12 ef ff e6 53 7b 4e 01 2f 65 0d 05 f0 |.......S{N./e...|
+000001d0 95 9f 46 d2 ae e7 33 5c 37 56 ab 67 95 87 81 59 |..F...3\7V.g...Y|
+000001e0 f2 35 76 78 ed 13 63 a3 58 52 af 46 e6 aa c3 99 |.5vx..c.XR.F....|
+000001f0 37 9d 10 25 cc 7f 7e 63 e1 96 6d 7a 8e ac 9e 00 |7..%..~c..mz....|
+00000200 d1 0e 7a 48 b6 82 77 6a a0 17 d1 77 70 f8 40 4a |..zH..wj...wp.@J|
+00000210 c4 90 da b0 3f 25 68 f5 9f dd 5e ec 95 02 19 53 |....?%h...^....S|
+00000220 08 6a 13 11 88 9e 2b 25 b8 28 cd 58 36 d7 d3 95 |.j....+%.(.X6...|
+00000230 f5 91 63 92 ff 3b d2 4f 75 ae 47 6c 64 8a a4 76 |..c..;.Ou.Gld..v|
+00000240 48 96 a7 35 d6 35 22 96 4d 4f ee 45 fb 88 52 68 |H..5.5".MO.E..Rh|
+00000250 4e 38 93 e8 08 6a e6 f3 00 a7 f7 b0 0b 68 41 ab |N8...j.......hA.|
+00000260 9b 3a 92 2b fd b2 71 14 77 91 48 e7 70 62 b5 b0 |.:.+..q.w.H.pb..|
+00000270 45 90 35 d2 b3 22 f5 70 6c 62 7f 55 6b 56 42 f8 |E.5..".plb.UkVB.|
+00000280 6c 87 a7 60 45 37 f0 41 41 ec 73 f5 f1 d9 d2 84 |l..`E7.AA.s.....|
+00000290 bd 88 bc 9b 43 ec 8b b3 c4 3a 59 2c 30 61 30 98 |....C....:Y,0a0.|
+000002a0 78 d3 e7 85 dd 7e 80 b8 fb b3 bf 7e 11 79 e8 20 |x....~.....~.y. |
+000002b0 aa b8 81 94 10 5c f8 ba 70 4c 1e 7c 35 8f 48 30 |.....\..pL.|5.H0|
+000002c0 17 38 d6 1c 91 ed 00 2c f7 af 29 d3 cb 9b ab 6b |.8.....,..)....k|
+000002d0 b3 fa 6e 1a 9b a8 cf 08 8e 03 a5 f7 76 17 74 3a |..n.........v.t:|
+000002e0 9e 36 ae 19 fd 2c 44 14 f3 2b 1d 01 db e1 96 22 |.6...,D..+....."|
+000002f0 25 14 5b d8 16 03 03 00 bc bb 8c bb cf f9 d7 76 |%.[............v|
+00000300 7a a7 d6 e0 29 cb 45 21 8d 57 0b 81 0c e0 96 05 |z...).E!.W......|
+00000310 c7 96 67 43 0f 41 11 e9 c2 07 2d 62 17 b4 64 01 |..gC.A....-b..d.|
+00000320 c5 75 79 dc 9c 36 3f ea 42 ea 09 a7 bc 0f 6b b1 |.uy..6?.B.....k.|
+00000330 b4 4d ae 38 0a ca 51 d0 97 46 b6 55 12 7c 24 28 |.M.8..Q..F.U.|$(|
+00000340 77 16 64 42 53 70 c4 52 ed e5 aa 20 3a 00 7e d0 |w.dBSp.R... :.~.|
+00000350 9e 99 e4 56 5f ef 30 56 00 8b e7 31 6d 66 6d dc |...V_.0V...1mfm.|
+00000360 58 8a b0 60 6f 16 a7 b0 14 a5 9d 3d 38 94 6e 16 |X..`o......=8.n.|
+00000370 a3 22 76 e9 59 d8 90 cd 32 83 bb 8c c5 23 cb c2 |."v.Y...2....#..|
+00000380 c5 03 02 de 13 97 ac 4e 99 9f 4d 6d aa ed 72 b7 |.......N..Mm..r.|
+00000390 76 db 8b c9 31 17 b9 1c 4a fa 87 2c 6b dc 07 82 |v...1...J..,k...|
+000003a0 a2 39 e0 09 32 a2 8e 1c 6e 68 e1 14 ba ab 3a d4 |.9..2...nh....:.|
+000003b0 1e 4f f4 39 c7 16 03 03 00 3a cf b2 61 5f 7e ef |.O.9.....:..a_~.|
+000003c0 04 51 64 f6 3d b3 54 44 bd 8a d0 87 48 64 76 a6 |.Qd.=.TD....Hdv.|
+000003d0 0d bc 7f b7 99 d4 67 8b cd e3 c4 5d df c5 c8 fc |......g....]....|
+000003e0 be d1 c4 03 6d 61 2d 10 58 b1 7a 7c 9e 1c 6b 16 |....ma-.X.z|..k.|
+000003f0 ff 31 a8 87 16 03 03 00 14 85 99 57 4b a1 19 33 |.1.........WK..3|
+00000400 bd 9a 86 ed be 5d 24 f0 02 9d ca 1e 26 |.....]$.....&|
>>> Flow 9 (client to server)
-00000000 16 03 03 02 89 00 00 00 00 00 00 00 03 be 8d 55 |...............U|
-00000010 8a 5b 24 10 db e3 f2 11 28 0d 26 cc 1b bc 38 fa |.[$.....(.&...8.|
-00000020 1c 8c f8 c9 64 55 ec 43 16 f7 ca af 12 a8 1c 09 |....dU.C........|
-00000030 0d b0 47 bc 9f 19 02 91 ab 9d 33 b4 bc 45 f7 4d |..G.......3..E.M|
-00000040 53 85 4a 91 7e d3 2d dc d6 02 6e 4a 34 51 99 db |S.J.~.-...nJ4Q..|
-00000050 f2 a1 8d 34 60 6f 15 6a f9 4d 7a 03 0b dc f7 c1 |...4`o.j.Mz.....|
-00000060 99 c2 2c b8 4c a1 63 ce a2 fb 33 0d d6 dd d4 0a |..,.L.c...3.....|
-00000070 88 0c 1d 5c ea 06 00 33 3a 06 6e 3d 63 b4 d5 0c |...\...3:.n=c...|
-00000080 9b 69 f0 86 72 db 47 52 3d 61 0b 66 57 8d 7b 67 |.i..r.GR=a.fW.{g|
-00000090 1e 42 aa b8 ca e6 d3 07 56 cf f5 09 14 25 a2 1d |.B......V....%..|
-000000a0 3b 3e dd 0c 41 ac 66 05 3b db 59 85 9d e2 9f 8b |;>..A.f.;.Y.....|
-000000b0 21 c0 9a 3b 0b 8e 5b 4b af ac 73 87 d3 b4 34 b7 |!..;..[K..s...4.|
-000000c0 2e 26 b0 5d 10 3a 2e 00 cc ac 40 b5 72 40 69 fa |.&.].:....@.r@i.|
-000000d0 11 04 b6 37 38 84 59 76 29 08 f0 0f 0f 79 40 7c |...78.Yv)....y@||
-000000e0 e4 08 15 b7 58 cd 6c f4 d6 77 d6 f8 cb 1d ca 5c |....X.l..w.....\|
-000000f0 41 d7 f8 64 63 14 a5 a5 3a 13 ce 55 b4 0a d9 b5 |A..dc...:..U....|
-00000100 34 f9 5e 69 f2 9a 62 88 b9 69 2f 93 08 2c 55 c4 |4.^i..b..i/..,U.|
-00000110 5d 0d cb 92 ac 2c 30 27 83 11 68 9f 74 35 5d 3a |]....,0'..h.t5]:|
-00000120 96 4c 57 91 95 a8 e7 03 fa b7 ae 8b 94 e3 39 38 |.LW...........98|
-00000130 6d e1 ad b1 f7 26 2c 90 d4 3c eb a5 5e df e4 29 |m....&,..<..^..)|
-00000140 39 ff ba d2 04 f4 b4 9c fa c2 da 34 bc 04 32 07 |9..........4..2.|
-00000150 db 52 38 fd 92 89 4c e9 50 13 e5 90 e7 f1 88 5e |.R8...L.P......^|
-00000160 c1 7a 9b fa 6e 1f 99 ce 52 77 0c 03 d8 a6 5d 64 |.z..n...Rw....]d|
-00000170 ab 58 82 93 10 a1 4f 35 ea a3 6d af a9 64 17 3d |.X....O5..m..d.=|
-00000180 fc a8 d8 9e 7e d7 44 af 2a c1 d6 a8 4d 78 b3 0b |....~.D.*...Mx..|
-00000190 d1 0b 3d 54 e2 c8 df 84 61 cb 92 1a d8 ce 23 a3 |..=T....a.....#.|
-000001a0 68 f7 af 40 53 09 f0 cc 00 7d 39 83 2c 6d f4 44 |h..@S....}9.,m.D|
-000001b0 d6 95 59 06 0a ef 9c 74 39 b3 70 cb 0a 0c 13 cd |..Y....t9.p.....|
-000001c0 ec 1f bf 75 93 01 1a 35 68 75 8b 80 15 80 7d a9 |...u...5hu....}.|
-000001d0 d0 25 9a 52 bc 02 bf 71 eb 60 76 2a 74 90 c8 16 |.%.R...q.`v*t...|
-000001e0 80 03 c2 a8 0c be 94 7c 12 b0 ee 45 3a 38 09 5a |.......|...E:8.Z|
-000001f0 bf 8b ca 78 f3 9e 79 8a 9f 65 57 84 f8 33 79 2a |...x..y..eW..3y*|
-00000200 f8 8c e0 c8 4b 9e 12 19 b1 3f ba cf 9d db 48 13 |....K....?....H.|
-00000210 b4 b0 53 0e 7a 6b 1d 21 13 45 37 8d 90 75 88 f9 |..S.zk.!.E7..u..|
-00000220 b5 9d 41 d0 ee 95 5f 6a e5 96 b6 48 ce 3b 43 20 |..A..._j...H.;C |
-00000230 47 15 db eb ba af 6d bf 38 26 e7 ad 86 ba 1e 91 |G.....m.8&......|
-00000240 be 8b df ba 5c 30 6e 3c 13 6a 96 68 13 24 bf 06 |....\0n<.j.h.$..|
-00000250 f1 d2 b0 05 8f 8e 21 7f 6a 09 5f b8 be 0b c5 5f |......!.j._...._|
-00000260 67 60 94 ec 78 65 6f 70 94 9b 15 82 07 f4 88 fb |g`..xeop........|
-00000270 a2 94 68 f7 57 0a 9c ec ab 3f 8f d5 83 ec 6a 24 |..h.W....?....j$|
-00000280 6f 88 4f 22 7f a1 82 cb ef ec 4c 33 b9 c1 16 03 |o.O"......L3....|
-00000290 03 00 5e 00 00 00 00 00 00 00 04 34 f9 69 a5 83 |..^........4.i..|
-000002a0 c5 86 34 51 f0 07 5b 44 51 36 c1 0d f7 71 c7 1b |..4Q..[DQ6...q..|
-000002b0 70 27 aa 35 cd c7 10 76 fd 96 27 dc bc 6f 39 ff |p'.5...v..'..o9.|
-000002c0 f1 a7 de e3 c5 21 70 e9 70 b1 52 d2 f0 be c0 72 |.....!p.p.R....r|
-000002d0 e5 aa 2b 1a 1d a8 8f 10 37 b5 2f c7 b9 32 c8 3c |..+.....7./..2.<|
-000002e0 7c c8 11 a5 dc aa 84 12 57 f1 ff 3b f9 04 a4 29 ||.......W..;...)|
-000002f0 24 16 03 03 00 a0 00 00 00 00 00 00 00 05 1a 86 |$...............|
-00000300 c7 35 6f 23 c5 38 85 85 0e 31 df 33 1a 42 6e f8 |.5o#.8...1.3.Bn.|
-00000310 c3 f7 81 29 aa 03 85 8c 5a 8a e1 9b 1c d3 6f 7d |...)....Z.....o}|
-00000320 36 41 45 30 06 2b dd 19 dc 22 9e 9e d4 bc 0e 51 |6AE0.+...".....Q|
-00000330 65 59 e9 7e 1b a1 d1 54 4b 3c 9a 41 de b9 43 98 |eY.~...TK<.A..C.|
-00000340 a5 ef 7a b8 77 69 f7 a5 80 02 d6 46 73 96 89 46 |..z.wi.....Fs..F|
-00000350 43 3a d7 ae 21 64 db 05 b5 7d fc 83 a3 75 ba ad |C:..!d...}...u..|
-00000360 0d d2 d6 9b 51 3b cb 37 85 46 92 b5 57 eb 2c dc |....Q;.7.F..W.,.|
-00000370 b2 8f e2 c0 7f 29 bf 5e bd f0 26 dd 31 e4 31 af |.....).^..&.1.1.|
-00000380 09 51 e4 26 09 56 a2 f4 5d fc c5 cb c8 da 51 ee |.Q.&.V..].....Q.|
-00000390 35 2e bb 3e ee bb 14 03 03 00 19 00 00 00 00 00 |5..>............|
-000003a0 00 00 06 b5 3d 07 af c9 3f ad f0 25 b4 5e b9 0f |....=...?..%.^..|
-000003b0 fa f0 16 48 16 03 03 00 28 00 00 00 00 00 00 00 |...H....(.......|
-000003c0 00 43 54 67 b4 f1 0e 1d 9d 7f ab f7 4c b6 77 3f |.CTg........L.w?|
-000003d0 d0 17 da 6a 61 75 a8 c8 42 47 fb 2a f7 22 85 02 |...jau..BG.*."..|
-000003e0 b0 |.|
+00000000 16 03 03 02 69 8c c7 01 da 38 a5 36 3d 2c 21 1c |....i....8.6=,!.|
+00000010 64 1b b8 e7 c2 cd 17 06 b6 51 0e e6 d9 d9 18 c5 |d........Q......|
+00000020 a9 c9 ac 5d 2d 23 f8 15 92 b2 e1 62 6e d7 8d 58 |...]-#.....bn..X|
+00000030 5b d9 b8 26 e5 ec 0f 61 15 3e 12 70 89 0d 3f 4e |[..&...a.>.p..?N|
+00000040 e3 2e 18 42 7c c7 59 7b e1 48 d9 a8 cf b1 cd 38 |...B|.Y{.H.....8|
+00000050 17 90 97 89 2e 4f 4b df 58 b0 9f 4e 95 d2 e9 70 |.....OK.X..N...p|
+00000060 6d 0b 82 af b7 05 be 11 26 d8 f9 89 e6 d6 44 f5 |m.......&.....D.|
+00000070 db 7c 8c 91 61 78 dc 68 98 9b 10 17 5b 85 42 93 |.|..ax.h....[.B.|
+00000080 31 a2 16 97 72 c5 f2 d0 81 76 a6 9b b7 9c 14 ab |1...r....v......|
+00000090 a7 bf 19 f7 34 e3 8f 3f a5 aa 23 c8 49 07 1b 6f |....4..?..#.I..o|
+000000a0 e5 5d 65 66 a1 dc d2 e7 bb c2 4b 9e a7 9a dc d6 |.]ef......K.....|
+000000b0 72 42 d3 71 d3 51 a4 3a 82 f7 cd 2a 15 34 da 6d |rB.q.Q.:...*.4.m|
+000000c0 44 3a a9 7d 6e 4c ce a5 ba 6b 5b 3b 88 8c e1 29 |D:.}nL...k[;...)|
+000000d0 ee a8 17 1b 02 36 8f 68 c9 9e e6 f1 bf e3 e3 e0 |.....6.h........|
+000000e0 cd 6d 7f ff c2 4d 3f 88 c7 9b 75 20 e5 cd fa fa |.m...M?...u ....|
+000000f0 a0 d7 10 6a c1 00 73 f9 df bd 22 60 8c 82 71 e6 |...j..s..."`..q.|
+00000100 56 aa 90 bf c7 a8 82 51 e7 23 42 ec 99 f5 b9 aa |V......Q.#B.....|
+00000110 3c cc c6 32 11 29 1f a6 ae 89 03 04 e8 de 9f f4 |<..2.)..........|
+00000120 bd 87 ae af 91 ee a2 f3 e2 6d 7b 87 ad 67 16 2d |.........m{..g.-|
+00000130 ad 92 34 38 52 ed 7c 38 92 45 16 26 9f 65 d2 67 |..48R.|8.E.&.e.g|
+00000140 3e 33 a1 bd b2 f6 d3 c8 76 96 52 11 0d 8d ac a6 |>3......v.R.....|
+00000150 27 10 6a 43 63 5f 82 41 e7 fe 91 24 68 70 bd 2c |'.jCc_.A...$hp.,|
+00000160 35 fd 0e 49 ec 3a dd f3 c0 af 5c f4 61 9a 2a 00 |5..I.:....\.a.*.|
+00000170 59 b5 28 24 f0 cf d3 25 bc 77 65 74 04 ee 4b 5e |Y.($...%.wet..K^|
+00000180 2b 9f 1d 27 e2 dd 1a ed ab e5 ff d6 1a 55 d7 4d |+..'.........U.M|
+00000190 5c da 14 96 21 43 f6 c3 2d 78 e5 75 60 69 26 ce |\...!C..-x.u`i&.|
+000001a0 7a 66 5e 42 91 0e ef 41 c2 c4 e6 15 8a 9a 17 a1 |zf^B...A........|
+000001b0 d9 23 2c cc c7 81 00 71 b0 52 ec 4e ea eb f9 75 |.#,....q.R.N...u|
+000001c0 2e 87 16 b4 ba 25 8c 09 f1 23 f9 ee ea db 0e b5 |.....%...#......|
+000001d0 d0 dd 47 9b b6 06 a3 f3 5e 0d 34 5a ba 76 cd 0a |..G.....^.4Z.v..|
+000001e0 b1 9f 8a 99 aa d3 02 2e b6 04 7b c5 d3 2f dc d7 |..........{../..|
+000001f0 68 af 6b 88 90 0a 94 a4 29 65 0b ba b3 da f2 cd |h.k.....)e......|
+00000200 51 93 4f ea b4 f8 54 c7 28 e3 2d 63 d0 62 54 d9 |Q.O...T.(.-c.bT.|
+00000210 27 a0 85 57 7b a2 f2 f5 a5 25 83 1b e2 36 15 06 |'..W{....%...6..|
+00000220 41 ae e1 f9 ca a5 c6 59 2d da 4a ed 10 7b 80 01 |A......Y-.J..{..|
+00000230 06 39 f2 a8 4b 22 37 4d aa 84 79 85 71 29 1b 4e |.9..K"7M..y.q).N|
+00000240 c3 79 af 13 f5 4e 3c 6d fa 8c d7 55 13 2b 48 3d |.y...N<m...U.+H=|
+00000250 9a 79 e2 b4 3f 59 f8 f9 6c d2 39 51 e0 6e c2 c3 |.y..?Y..l.9Q.n..|
+00000260 09 06 d4 e0 4f 76 a6 54 b8 9d ef 30 ba 80 16 03 |....Ov.T...0....|
+00000270 03 00 35 df a1 cc 0f 77 42 24 fe 38 ac ec 25 cf |..5....wB$.8..%.|
+00000280 13 85 03 87 73 b4 c0 d9 97 d0 a8 8e 12 f4 13 61 |....s..........a|
+00000290 42 40 03 a6 b6 6c d3 dd d9 92 f0 e9 bc bc a7 22 |B@...l........."|
+000002a0 64 cf 4b 00 97 71 ac 3b 16 03 03 00 98 f7 61 85 |d.K..q.;......a.|
+000002b0 47 fc 23 b5 34 4b 1f 10 c7 12 51 07 a2 40 40 48 |G.#.4K....Q..@@H|
+000002c0 1c 79 52 3a a7 9d ca 45 62 a2 53 71 bd 23 0a 77 |.yR:...Eb.Sq.#.w|
+000002d0 0b 7f 8c ff f2 51 da 91 07 d7 67 71 bb ec 02 8d |.....Q....gq....|
+000002e0 3f 79 dc d9 af f4 4c 78 3e ac 8d 30 ed eb c9 19 |?y....Lx>..0....|
+000002f0 96 89 a7 0f 7c fb 96 18 84 86 e7 bd e2 35 31 0c |....|........51.|
+00000300 7a 51 d7 94 6b 61 62 7a 6a d8 56 62 e6 cf bf 60 |zQ..kabzj.Vb...`|
+00000310 df 7a c5 ce d3 87 ea 2f 5a ad 90 d4 39 f7 47 8e |.z...../Z...9.G.|
+00000320 8b d3 6b 8e e0 3f 2f 59 71 e4 e6 bf 3f 4a 29 a8 |..k..?/Yq...?J).|
+00000330 60 df 1b 5c 2d 21 ab 0a a5 9f 5a a2 a3 d6 08 3c |`..\-!....Z....<|
+00000340 4a 4b f9 d6 a0 14 03 03 00 11 44 a4 62 7e c1 4a |JK........D.b~.J|
+00000350 4e 56 dd 08 65 b2 ab 12 cd fa 8d 16 03 03 00 20 |NV..e.......... |
+00000360 b4 52 5a e8 33 b6 23 b1 b4 e6 59 da b0 84 52 94 |.RZ.3.#...Y...R.|
+00000370 70 de dc 02 f6 41 e3 27 7c 27 56 6a 7c 92 e3 48 |p....A.'|'Vj|..H|
>>> Flow 10 (server to client)
-00000000 14 03 03 00 19 59 c3 19 1f ed d1 1b 5a 9d 51 67 |.....Y......Z.Qg|
-00000010 ff ed 61 fd 01 85 c2 46 f1 26 e1 08 c3 5b 16 03 |..a....F.&...[..|
-00000020 03 00 28 02 08 83 98 20 78 eb a5 8e f5 d3 31 b6 |..(.... x.....1.|
-00000030 6d 4b 3a 9c cd 76 30 ca 92 4b 6c 17 2c d8 c5 d5 |mK:..v0..Kl.,...|
-00000040 7d 59 76 f8 ff 0c 8f f4 f6 fb 81 17 03 03 00 21 |}Yv............!|
-00000050 02 08 83 98 20 78 eb a6 9b c6 07 33 3b 43 e4 5b |.... x.....3;C.[|
-00000060 c6 d4 31 6e 2b 5b 4a 65 c2 0a df 27 02 a2 3e 3b |..1n+[Je...'..>;|
-00000070 04 16 03 03 00 1c 02 08 83 98 20 78 eb a7 43 45 |.......... x..CE|
-00000080 df 9b 74 94 81 17 21 b1 7d d5 c0 7a 2b cc 38 a1 |..t...!.}..z+.8.|
-00000090 30 1d |0.|
+00000000 14 03 03 00 11 c7 92 b3 aa a0 91 21 4f 42 96 0c |...........!OB..|
+00000010 3a 92 c3 53 55 d1 16 03 03 00 20 4b da e5 1c 08 |:..SU..... K....|
+00000020 ce a7 33 f1 a6 c7 47 52 19 68 b4 f5 1d 66 a7 38 |..3...GR.h...f.8|
+00000030 97 45 43 9f ca b5 db 2c 14 fc f4 17 03 03 00 19 |.EC....,........|
+00000040 28 f4 bb bf c1 5a 2d 1e b8 fc c7 fc 55 16 e9 cc |(....Z-.....U...|
+00000050 43 a3 63 58 7e 2c 60 77 23 16 03 03 00 14 2c e6 |C.cX~,`w#.....,.|
+00000060 25 0a b7 26 7b 13 55 62 f1 fe 6e fe 0e 57 53 57 |%..&{.Ub..n..WSW|
+00000070 19 1b |..|
>>> Flow 11 (client to server)
-00000000 15 03 03 00 1a 00 00 00 00 00 00 00 01 d6 2b 5a |..............+Z|
-00000010 7d c9 ba d3 94 cc 45 26 1c 1e 1e 70 39 6c 4e 15 |}.....E&...p9lN.|
-00000020 03 03 00 1a 00 00 00 00 00 00 00 02 fd 76 21 e8 |.............v!.|
-00000030 b5 16 14 43 36 9f 61 14 6d 40 76 e3 14 11 |...C6.a.m@v...|
+00000000 15 03 03 00 12 dd 2b 00 09 fd 8c 7d 21 3d 7c 06 |......+....}!=|.|
+00000010 93 ca c9 21 b2 3e 20 15 03 03 00 12 90 32 4b 3b |...!.> ......2K;|
+00000020 33 4d fd 69 55 81 aa 42 16 ae 47 b9 4c 06 |3M.iU..B..G.L.|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected
index 90adc18fe92..cb964324fd2 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-RenegotiationRejected
@@ -1,97 +1,89 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 00 59 02 00 00 55 03 03 b1 7d c5 82 a4 |....Y...U...}...|
-00000010 f7 1d 3a b9 c0 da 13 7c 2f 75 22 a4 5f 2e 58 2a |..:....|/u"._.X*|
-00000020 39 eb 18 7c bb 0d 98 ba 51 2e 4a 20 41 40 2f 53 |9..|....Q.J A@/S|
-00000030 bc 16 e0 a4 44 07 f0 5e 8f 43 a3 69 87 0b 94 dd |....D..^.C.i....|
-00000040 60 a0 20 d0 25 e1 a1 a0 b8 0d d8 00 c0 2f 00 00 |`. .%......../..|
+00000000 16 03 03 00 59 02 00 00 55 03 03 91 a6 bc 02 ab |....Y...U.......|
+00000010 19 62 2c de 45 57 ba 71 c0 b0 4d 78 5e f4 c2 b9 |.b,.EW.q..Mx^...|
+00000020 81 ba 8b d6 b1 9b c8 fb 0c 7c 40 20 dc 66 80 5b |.........|@ .f.[|
+00000030 20 3c 60 65 7f 9e 0c 67 a8 f3 22 c9 c5 48 80 fa | <`e...g.."..H..|
+00000040 02 a1 1a 48 6d 1c 46 07 db 6c 8e 85 cc a8 00 00 |...Hm.F..l......|
00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
-00000060 03 02 71 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 |..q...m..j..g0..|
-00000070 63 30 82 01 cc a0 03 02 01 02 02 09 00 a2 73 00 |c0............s.|
-00000080 0c 81 00 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 |.....0...*.H....|
-00000090 01 0b 05 00 30 2b 31 17 30 15 06 03 55 04 0a 13 |....0+1.0...U...|
-000000a0 0e 47 6f 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 |.Google TESTING1|
-000000b0 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
-000000c0 74 30 1e 17 0d 31 35 30 31 30 31 30 30 30 30 30 |t0...15010100000|
-000000d0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
-000000e0 5a 30 26 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |Z0&1.0...U....Go|
-000000f0 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 0b 30 09 |ogle TESTING1.0.|
-00000100 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
-00000110 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
-00000120 81 89 02 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 |.......... ..el.|
-00000130 ab 44 05 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f |.D..;E...m..cM..|
-00000140 fe 6a 62 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 |.jb5..J..|..%^zd|
-00000150 31 66 00 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 |1f.......k.v.._A|
-00000160 cb 6e 56 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 |.nV.....<.9!f=+.|
-00000170 d1 bc db 1c c0 a7 da b7 ca ad ba da cb d5 21 50 |..............!P|
-00000180 ec de 8d ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 |.....k.K......l.|
-00000190 b1 44 84 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef |.D..!..}..M.....|
-000001a0 fa d6 09 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 |...G..........0.|
-000001b0 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
-000001c0 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
-000001d0 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
-000001e0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
-000001f0 06 03 55 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 |..U.......P..o..|
-00000200 dc 54 4d 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 |.TMn.i^..0...U.#|
-00000210 04 14 30 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea |..0....=..f..@..|
-00000220 b4 03 78 48 1a 41 30 19 06 03 55 1d 11 04 12 30 |..xH.A0...U....0|
-00000230 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
-00000240 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
-00000250 03 81 81 00 92 7c af 91 55 12 18 96 59 31 a6 48 |.....|..U...Y1.H|
-00000260 40 d5 2d d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d |@.-........|..0}|
-00000270 3c dc 76 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b |<.v.O=...-3$k.{.|
-00000280 67 59 11 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 |gY.!...w...n.-.5|
-00000290 fa 64 5f 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 |.d_">c.k....m...|
-000002a0 31 a8 14 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 |1..8.;..,...Qv..|
-000002b0 4f dd db 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 |O......@.Q......|
-000002c0 46 de 46 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea |F.F.O.....A4....|
-000002d0 b0 ab 39 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 |..9.............|
-000002e0 41 04 62 2a a7 2d 1f 7a 8d 7e 8a 9e 84 db df e2 |A.b*.-.z.~......|
-000002f0 7c 35 d8 a1 9f ec 23 ef c7 c2 9a c5 45 02 6f eb ||5....#.....E.o.|
-00000300 24 ed 77 e1 ca fe 9a be 06 1e ea 30 5a e7 13 00 |$.w........0Z...|
-00000310 47 52 a4 a2 d8 ee 9d 4e 87 f5 48 83 6f 5d 8e 02 |GR.....N..H.o]..|
-00000320 ff f5 04 01 00 80 19 f6 63 a1 47 d1 cf 4d 28 73 |........c.G..M(s|
-00000330 4e 31 03 78 b5 17 ba 53 64 d0 b8 3f 04 77 9d 6b |N1.x...Sd..?.w.k|
-00000340 85 d0 d4 1e 02 90 b9 ab 10 dc d7 b1 79 1b 12 80 |............y...|
-00000350 e1 5a 4b 69 80 2d 2a 37 4c fd 72 a9 c3 8e 2a 1f |.ZKi.-*7L.r...*.|
-00000360 1a 3f 74 49 c6 49 ce 2f 02 58 3f 68 f0 f6 b5 8a |.?tI.I./.X?h....|
-00000370 16 11 8b 63 15 6a f2 91 f1 74 a8 f0 6d dc 91 0a |...c.j...t..m...|
-00000380 b4 e2 4e 10 14 1d b9 da 05 29 bf 31 30 ee 7d a5 |..N......).10.}.|
-00000390 75 4e da ff db 43 04 a7 55 4b dd 93 4c 5f 32 be |uN...C..UK..L_2.|
-000003a0 e9 23 c9 a1 23 86 16 03 03 00 04 0e 00 00 00 |.#..#..........|
+00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
+000002c0 ac 0c 00 00 a8 03 00 1d 20 f5 fd 54 ea 3e bb 70 |........ ..T.>.p|
+000002d0 fb 8e fb e4 8a 25 1f 9d 3d 9a fb fb 9d ff d1 52 |.....%..=......R|
+000002e0 81 9d b0 ea a1 e6 b0 87 2f 04 01 00 80 77 54 16 |......../....wT.|
+000002f0 98 5d 22 c4 7f 9b 2a 44 dd e4 0d 78 c2 60 6a ad |.]"...*D...x.`j.|
+00000300 91 9d d9 ed 93 0b 4e b4 c6 26 f1 94 6d e0 cc f4 |......N..&..m...|
+00000310 8d fa 9c ec 70 f5 5b ac 80 d7 5e 4f 49 04 bc 24 |....p.[...^OI..$|
+00000320 8e 0a 7d 44 e1 7e 47 1e a8 68 d1 fe 6f 41 0d 4a |..}D.~G..h..oA.J|
+00000330 e5 5b f6 f6 a3 af 76 21 56 1a 25 d2 03 3c f4 dd |.[....v!V.%..<..|
+00000340 0c 13 ce 56 8a 61 6f 5b 8c a1 04 43 82 87 64 20 |...V.ao[...C..d |
+00000350 4a 3b ec 90 d7 59 aa ca 08 3a 39 57 f1 56 57 6a |J;...Y...:9W.VWj|
+00000360 18 c9 14 7f e3 8d 83 0f e2 0b 4d 24 01 16 03 03 |..........M$....|
+00000370 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 d4 cb |.....(..........|
-00000060 e2 c0 1e fe cb b0 d6 fe da 7c 8f 8c b2 2f f7 c1 |.........|.../..|
-00000070 3d e9 52 6e 70 c1 13 13 87 ff 12 85 6c 2c |=.Rnp.......l,|
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 20 6b ce 5c 2f df 85 e7 5e fa 51 48 |.... k.\/...^.QH|
+00000040 f9 31 a5 02 64 c7 1e b1 2e f2 6b 86 30 43 23 91 |.1..d.....k.0C#.|
+00000050 76 6b 40 74 2b |vk@t+|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 0a 86 ff b2 73 |..........(....s|
-00000010 35 40 a1 89 9f 21 1f 0b 2f 79 50 70 eb 74 e1 2f |5@...!../yPp.t./|
-00000020 4d bc 5c 3c 85 0b 60 cc 73 36 e4 08 01 0a 4c 75 |M.\<..`.s6....Lu|
-00000030 0f a2 9c |...|
+00000000 14 03 03 00 01 01 16 03 03 00 20 e7 1e 88 10 2d |.......... ....-|
+00000010 dc 35 6d 2b 4a 91 39 5d 5c 46 ed 2e 45 6f 41 38 |.5m+J.9]\F..EoA8|
+00000020 66 0f 15 58 f8 af d8 a6 6c 99 61 |f..X....l.a|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 c9 78 b7 |..............x.|
-00000010 07 d1 a9 95 fc b4 aa 57 16 77 86 fb c7 a9 c6 12 |.......W.w......|
-00000020 bc bd 09 |...|
+00000000 17 03 03 00 16 ab 2a df 2f 3c 07 6a 24 98 55 0b |......*./<.j$.U.|
+00000010 67 20 2d 92 cd 9a 44 74 da fd 6a |g -...Dt..j|
>>> Flow 6 (server to client)
-00000000 16 03 03 00 1c 0a 86 ff b2 73 35 40 a2 4d b1 9b |.........s5@.M..|
-00000010 eb 51 76 71 6b b8 88 fe 21 60 bb 8b 2a cc e3 3e |.Qvqk...!`..*..>|
-00000020 d5 |.|
+00000000 16 03 03 00 14 d6 fb e7 9a 76 2a 6f e1 e9 33 1a |.........v*o..3.|
+00000010 77 07 fd 7f 98 af 1e 04 43 |w.......C|
>>> Flow 7 (client to server)
-00000000 15 03 03 00 1a 00 00 00 00 00 00 00 02 0e da c6 |................|
-00000010 01 09 cc 0f bb 7d de c9 41 8d 30 b5 d5 b7 f2 15 |.....}..A.0.....|
-00000020 03 03 00 1a 00 00 00 00 00 00 00 03 a7 0e 24 98 |..............$.|
-00000030 32 62 1b a9 98 17 b6 b3 71 af 88 7a a3 6b |2b......q..z.k|
+00000000 15 03 03 00 12 7e e3 20 96 03 31 8c 6a 31 f8 62 |.....~. ..1.j1.b|
+00000010 02 a7 a4 ce 77 83 c1 15 03 03 00 12 b9 91 75 45 |....w.........uE|
+00000020 a5 4a f9 c6 6d b2 5c c3 0a 1a 26 63 00 04 |.J..m.\...&c..|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-SCT b/libgo/go/crypto/tls/testdata/Client-TLSv12-SCT
index e6187baa3f4..a0f6a090af2 100644
--- a/libgo/go/crypto/tls/testdata/Client-TLSv12-SCT
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-SCT
@@ -1,19 +1,20 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 85 01 00 00 81 03 03 00 00 00 00 00 |................|
+00000000 16 03 01 00 91 01 00 00 8d 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 22 c0 2f |............."./|
-00000030 c0 2b c0 30 c0 2c c0 11 c0 07 c0 13 c0 09 c0 14 |.+.0.,..........|
-00000040 c0 0a 00 9c 00 9d 00 05 00 2f 00 35 c0 12 00 0a |........./.5....|
-00000050 01 00 00 36 00 05 00 05 01 00 00 00 00 00 0a 00 |...6............|
-00000060 08 00 06 00 17 00 18 00 19 00 0b 00 02 01 00 00 |................|
-00000070 0d 00 0e 00 0c 04 01 04 03 05 01 05 03 02 01 02 |................|
-00000080 03 ff 01 00 01 00 00 12 00 00 |..........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 38 00 05 |.............8..|
+00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................|
+00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 0e 00 |................|
+00000080 0c 04 01 04 03 05 01 05 03 02 01 02 03 ff 01 00 |................|
+00000090 01 00 00 12 00 00 |......|
>>> Flow 2 (server to client)
-00000000 16 03 03 01 c6 02 00 01 c2 03 03 5d d8 84 38 51 |...........]..8Q|
-00000010 c6 51 9e 6c d3 e0 b2 d7 81 2a 9b 1c 06 0b 11 c8 |.Q.l.....*......|
-00000020 54 90 f3 d1 66 83 7a 68 2f 65 8b 20 ac 8b 35 9a |T...f.zh/e. ..5.|
-00000030 31 25 04 c9 89 31 27 80 8f 10 74 8e 3c 4f 20 bc |1%...1'...t.<O .|
-00000040 3b 46 9d d0 91 f3 ca 7e 0e 59 b7 72 c0 2f 00 01 |;F.....~.Y.r./..|
+00000000 16 03 03 01 c6 02 00 01 c2 03 03 08 db 5c c4 da |.............\..|
+00000010 fe 2c a2 21 0d c4 9e c4 14 b9 e3 15 d7 c5 2c 84 |.,.!..........,.|
+00000020 f2 b8 0e 32 67 9e 72 08 9c 17 6b 20 86 09 60 52 |...2g.r...k ..`R|
+00000030 9d 53 ba c8 8a c3 1a 11 c0 e5 c6 a0 59 49 ed cb |.S..........YI..|
+00000040 e0 6f 0a 56 e9 4f bf 02 2f 23 10 b8 cc a8 00 01 |.o.V.O../#......|
00000050 7a ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 12 |z...............|
00000060 01 69 01 67 00 75 00 a4 b9 09 90 b4 18 58 14 87 |.i.g.u.......X..|
00000070 bb 13 a2 cc 67 70 0a 3c 35 98 04 f9 1b df b8 e3 |....gp.<5.......|
@@ -37,77 +38,70 @@
00000190 91 bc f1 b5 40 be 1e 2e e7 5c b4 74 27 ed 8f 9b |....@....\.t'...|
000001a0 02 e9 fa c2 4c ba a2 be 02 21 00 af 43 64 52 71 |....L....!..CdRq|
000001b0 15 29 58 40 91 c7 08 16 96 03 a8 73 a5 65 a0 6c |.)X@.......s.e.l|
-000001c0 b8 48 56 5a b6 29 83 64 6d 2a 9d 16 03 03 02 71 |.HVZ.).dm*.....q|
-000001d0 0b 00 02 6d 00 02 6a 00 02 67 30 82 02 63 30 82 |...m..j..g0..c0.|
-000001e0 01 cc a0 03 02 01 02 02 09 00 a2 73 00 0c 81 00 |...........s....|
-000001f0 cb f3 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 |..0...*.H.......|
-00000200 00 30 2b 31 17 30 15 06 03 55 04 0a 13 0e 47 6f |.0+1.0...U....Go|
-00000210 6f 67 6c 65 20 54 45 53 54 49 4e 47 31 10 30 0e |ogle TESTING1.0.|
-00000220 06 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e |..U....Go Root0.|
-00000230 17 0d 31 35 30 31 30 31 30 30 30 30 30 30 5a 17 |..150101000000Z.|
-00000240 0d 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 26 |.250101000000Z0&|
-00000250 31 17 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c |1.0...U....Googl|
-00000260 65 20 54 45 53 54 49 4e 47 31 0b 30 09 06 03 55 |e TESTING1.0...U|
-00000270 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 |....Go0..0...*.H|
-00000280 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 |............0...|
-00000290 81 81 00 af 87 88 f6 20 1b 95 65 6c 14 ab 44 05 |....... ..el..D.|
-000002a0 af 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f fe 6a 62 |.;E...m..cM...jb|
-000002b0 35 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 31 66 00 |5..J..|..%^zd1f.|
-000002c0 ba f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 cb 6e 56 |......k.v.._A.nV|
-000002d0 15 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 d1 bc db |.....<.9!f=+....|
-000002e0 1c c0 a7 da b7 ca ad ba da cb d5 21 50 ec de 8d |...........!P...|
-000002f0 ab d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 b1 44 84 |..k.K......l..D.|
-00000300 bd 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef fa d6 09 |.!..}..M........|
-00000310 47 f2 fb 02 03 01 00 01 a3 81 93 30 81 90 30 0e |G..........0..0.|
-00000320 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d |..U...........0.|
-00000330 06 03 55 1d 25 04 16 30 14 06 08 2b 06 01 05 05 |..U.%..0...+....|
-00000340 07 03 01 06 08 2b 06 01 05 05 07 03 02 30 0c 06 |.....+.......0..|
-00000350 03 55 1d 13 01 01 ff 04 02 30 00 30 19 06 03 55 |.U.......0.0...U|
-00000360 1d 0e 04 12 04 10 12 50 8d 89 6f 1b d1 dc 54 4d |.......P..o...TM|
-00000370 6e cb 69 5e 06 f4 30 1b 06 03 55 1d 23 04 14 30 |n.i^..0...U.#..0|
-00000380 12 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea b4 03 78 |....=..f..@....x|
-00000390 48 1a 41 30 19 06 03 55 1d 11 04 12 30 10 82 0e |H.A0...U....0...|
-000003a0 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d |example.golang0.|
-000003b0 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 |..*.H...........|
-000003c0 00 92 7c af 91 55 12 18 96 59 31 a6 48 40 d5 2d |..|..U...Y1.H@.-|
-000003d0 d5 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 |........|..0}<.v|
-000003e0 da 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b 67 59 11 |.O=...-3$k.{.gY.|
-000003f0 21 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f |!...w...n.-.5.d_|
-00000400 22 3e 63 10 6b be ff 14 86 6d 0d f0 15 31 a8 14 |">c.k....m...1..|
-00000410 38 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 4f dd db |8.;..,...Qv..O..|
-00000420 9b 84 04 86 40 fa 51 dd ba b4 8d eb e3 46 de 46 |....@.Q......F.F|
-00000430 b9 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea b0 ab 39 |.O.....A4......9|
-00000440 18 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 1e |.............A..|
-00000450 d1 1c 5c d3 00 41 84 cd f7 e2 78 ad b5 7d 5b f2 |..\..A....x..}[.|
-00000460 23 5b 1a 18 44 3f 86 8e 3e 52 f2 4b b6 7d 84 b4 |#[..D?..>R.K.}..|
-00000470 1d 98 83 8f 2f 58 07 92 1f 58 2a 8d 8c e3 fa b7 |..../X...X*.....|
-00000480 aa 78 7e 33 9a 64 b9 b6 cb 78 94 be 2b c3 ac 04 |.x~3.d...x..+...|
-00000490 01 00 80 65 9f 42 e3 24 5c cd 18 aa 08 8e 6b bf |...e.B.$\.....k.|
-000004a0 39 15 2a a3 e6 42 1c 9d 6b 34 39 a2 2c 58 f5 5f |9.*..B..k49.,X._|
-000004b0 3e fb 2a 4c 01 2b e5 20 4e f5 69 77 c1 62 8f 68 |>.*L.+. N.iw.b.h|
-000004c0 be b4 c4 77 27 c9 4a 97 6d 18 7f 45 fd c9 9e 24 |...w'.J.m..E...$|
-000004d0 19 6b d9 00 c5 52 1a 34 a3 c9 cb eb 92 fc f6 48 |.k...R.4.......H|
-000004e0 3d 89 8a ff 82 be 55 c9 92 e2 24 86 b0 99 c6 e8 |=.....U...$.....|
-000004f0 a5 4c b7 bc 5a e5 f3 81 94 ee 15 47 e7 5e 8c 66 |.L..Z......G.^.f|
-00000500 32 72 7d 81 78 61 fe 25 98 dd 07 a2 92 4c eb ed |2r}.xa.%.....L..|
-00000510 f1 a7 17 16 03 03 00 04 0e 00 00 00 |............|
+000001c0 b8 48 56 5a b6 29 83 64 6d 2a 9d 16 03 03 02 59 |.HVZ.).dm*.....Y|
+000001d0 0b 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 |...U..R..O0..K0.|
+000001e0 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b |.............?.[|
+000001f0 ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 |..0...*.H.......|
+00000200 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |.0.1.0...U....Go|
+00000210 31 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f |1.0...U....Go Ro|
+00000220 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 |ot0...1601010000|
+00000230 30 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 |00Z..25010100000|
+00000240 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 |0Z0.1.0...U....G|
+00000250 6f 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 |o1.0...U....Go0.|
+00000260 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 |.0...*.H........|
+00000270 03 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e |....0.......F}..|
+00000280 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e |.'.H..(!.~...]..|
+00000290 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be |RE.z6G....B[....|
+000002a0 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 |.y.@.Om..+.....g|
+000002b0 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 |....."8.J.ts+.4.|
+000002c0 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 |.....t{.X.la<..A|
+000002d0 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 |..++$#w[.;.u]. T|
+000002e0 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 |..c...$....P....|
+000002f0 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 |C...ub...R......|
+00000300 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff |...0..0...U.....|
+00000310 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 |......0...U.%..0|
+00000320 14 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 |...+.........+..|
+00000330 05 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 |.....0...U......|
+00000340 02 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 |.0.0...U........|
+00000350 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b |..CC>I..m....`0.|
+00000360 06 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 |..U.#..0...H.IM.|
+00000370 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 |~.1......n{0...U|
+00000380 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e |....0...example.|
+00000390 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d |golang0...*.H...|
+000003a0 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 |..........0.@+[P|
+000003b0 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 |.a...SX...(.X..8|
+000003c0 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 |....1Z..f=C.-...|
+000003d0 97 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 |... d8.$:....}.@|
+000003e0 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c | ._...a..v......|
+000003f0 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c |\.....l..s..Cw..|
+00000400 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 |.....@.a.Lr+...F|
+00000410 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 |..M...>...B...=.|
+00000420 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c 00 |`.\!.;..........|
+00000430 00 a8 03 00 1d 20 27 94 d8 62 00 f3 3f 21 e6 e1 |..... '..b..?!..|
+00000440 0f 1f 2d 9b 37 4d cf 72 34 48 72 2e 85 46 dd b6 |..-.7M.r4Hr..F..|
+00000450 32 23 64 b3 4b 63 04 01 00 80 82 34 e5 7f 70 51 |2#d.Kc.....4..pQ|
+00000460 42 3b ab 51 61 73 1f 2c 64 04 1d 66 96 ff f9 95 |B;.Qas.,d..f....|
+00000470 86 09 a8 75 11 16 34 05 17 fb 96 9c fb 78 40 4c |...u..4......x@L|
+00000480 10 5b ee 0d 31 a0 77 32 a8 0f 19 ef a4 30 cd 08 |.[..1.w2.....0..|
+00000490 cb f5 ec 36 fa 24 0a ca 0b d8 16 02 d1 34 86 a7 |...6.$.......4..|
+000004a0 f8 e3 cb e6 62 1c cd 40 d6 4f 0c 2f 5b 66 12 6f |....b..@.O./[f.o|
+000004b0 8a 2f c4 ef ac 46 86 44 90 e0 65 38 94 4d 5e df |./...F.D..e8.M^.|
+000004c0 51 a3 40 6e 64 b6 00 6b 88 97 7b 43 78 d9 df 70 |Q.@nd..k..{Cx..p|
+000004d0 fe 66 66 56 82 14 ed ab 08 cd 16 03 03 00 04 0e |.ffV............|
+000004e0 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 f0 4f |.....(.........O|
-00000060 fe 22 53 9e e1 61 f4 45 4e 41 ff 5e e4 63 25 f7 |."S..a.ENA.^.c%.|
-00000070 b2 f6 0a ea 89 75 7f d4 e7 3a cc e8 c2 2c |.....u...:...,|
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 20 7a 58 e1 33 d4 ce ca 57 ef ea b9 |.... zX.3...W...|
+00000040 9d f2 4d ec ce 86 4b e9 c2 b5 64 dd 0f 32 f0 66 |..M...K...d..2.f|
+00000050 65 42 74 d8 59 |eBt.Y|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 28 ad 49 0a 66 16 |..........(.I.f.|
-00000010 6d 64 42 c2 ab 38 bf 81 3d d9 14 13 d6 69 27 81 |mdB..8..=....i'.|
-00000020 ea 5c 53 fd 6c bf 81 6c 06 81 a5 67 f2 cd ed a3 |.\S.l..l...g....|
-00000030 d4 c2 08 |...|
+00000000 14 03 03 00 01 01 16 03 03 00 20 27 df 9b 14 a1 |.......... '....|
+00000010 cd a5 83 5b 6b 30 60 a3 ae 8d 64 56 fe 8e 87 a2 |...[k0`...dV....|
+00000020 ff 1b 54 72 c8 7c b2 85 9d 8a de |..Tr.|.....|
>>> Flow 5 (client to server)
-00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 5c ab e3 |.............\..|
-00000010 f9 61 72 9e 44 46 1a 05 e9 00 eb 5b e0 73 22 03 |.ar.DF.....[.s".|
-00000020 9f 90 f9 15 03 03 00 1a 00 00 00 00 00 00 00 02 |................|
-00000030 04 28 a4 9d 07 79 95 40 0f f0 eb b9 5d 97 bf 87 |.(...y.@....]...|
-00000040 4a b6 |J.|
+00000000 17 03 03 00 16 c7 bf a9 7a 72 07 27 88 9a ec 1b |........zr.'....|
+00000010 d3 44 f2 20 88 e4 c2 8b 61 86 5c 15 03 03 00 12 |.D. ....a.\.....|
+00000020 35 ab f5 f6 92 f9 db 23 bf f1 8e e8 65 62 cf 48 |5......#....eb.H|
+00000030 91 9d |..|
diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE-RSA-AES-GCM b/libgo/go/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE-RSA-AES-GCM
new file mode 100644
index 00000000000..90541fd16e0
--- /dev/null
+++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-X25519-ECDHE-RSA-AES-GCM
@@ -0,0 +1,85 @@
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 8b 01 00 00 87 03 03 00 00 00 00 00 |................|
+00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2c cc a8 |.............,..|
+00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#|
+00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5|
+00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 32 00 05 |.............2..|
+00000060 00 05 01 00 00 00 00 00 0a 00 04 00 02 00 1d 00 |................|
+00000070 0b 00 02 01 00 00 0d 00 0e 00 0c 04 01 04 03 05 |................|
+00000080 01 05 03 02 01 02 03 ff 01 00 01 00 00 12 00 00 |................|
+>>> Flow 2 (server to client)
+00000000 16 03 03 00 59 02 00 00 55 03 03 07 42 b0 44 05 |....Y...U...B.D.|
+00000010 b1 6d 3c f0 60 fe 6a f2 1f 8f 1d 88 de 4b 6a 1b |.m<.`.j......Kj.|
+00000020 4f 72 60 4d 42 a5 f7 77 eb 86 c2 20 99 35 47 07 |Or`MB..w... .5G.|
+00000030 64 60 32 52 2e 1d 54 d5 b7 e2 26 85 72 c1 ec 8d |d`2R..T...&.r...|
+00000040 fb 59 86 91 46 7d ad 16 bd b7 38 94 c0 2f 00 00 |.Y..F}....8../..|
+00000050 0d ff 01 00 01 00 00 0b 00 04 03 00 01 02 16 03 |................|
+00000060 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 82 02 |..Y...U..R..O0..|
+00000070 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 f0 9d |K0..............|
+00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....|
+00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...|
+000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go|
+000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010|
+000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100|
+000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..|
+000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G|
+000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
+00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F|
+00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...|
+00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.|
+00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...|
+00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+|
+00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<|
+00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]|
+00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.|
+00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...|
+00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
+000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
+000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
+000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
+000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
+000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....|
+000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.|
+00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.|
+00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
+00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
+00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@|
+00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X|
+00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-|
+00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....|
+00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...|
+00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C|
+00000290 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d |w.......@.a.Lr+.|
+000002a0 ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db |..F..M...>...B..|
+000002b0 fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 03 00 |.=.`.\!.;.......|
+000002c0 ac 0c 00 00 a8 03 00 1d 20 cc f6 2e 98 6c e0 8b |........ ....l..|
+000002d0 15 17 63 6f 97 5e 37 6a a7 3c 4b f2 d4 91 e0 87 |..co.^7j.<K.....|
+000002e0 53 1d d3 9e f3 43 a9 21 40 04 01 00 80 3c 35 db |S....C.!@....<5.|
+000002f0 b1 ef 58 96 b4 3f eb 6b d5 0d b7 ab cd 51 8d 57 |..X..?.k.....Q.W|
+00000300 2b fe 3a 7f 72 42 a0 a7 7d 1d db c1 6c cd df de |+.:.rB..}...l...|
+00000310 7f 98 69 b0 0b c1 56 07 34 51 79 dc 1a 52 d1 11 |..i...V.4Qy..R..|
+00000320 ea b4 dd 0f 9d 9a 8c a3 4f 23 da 0e aa dc 2a e1 |........O#....*.|
+00000330 16 51 a4 33 e2 4f f8 34 2d b0 ba f5 f5 ed 3e 24 |.Q.3.O.4-.....>$|
+00000340 04 f0 b9 ab 81 b8 4e 39 88 8f b7 46 2c 60 b8 5c |......N9...F,`.\|
+00000350 6f 4d d4 5d 7a 04 f7 1d 82 98 a2 b1 f9 7e f0 1f |oM.]z........~..|
+00000360 cf a5 e5 28 25 d4 3d b0 32 ea eb 21 c6 16 03 03 |...(%.=.2..!....|
+00000370 00 04 0e 00 00 00 |......|
+>>> Flow 3 (client to server)
+00000000 16 03 03 00 25 10 00 00 21 20 2f e5 7d a3 47 cd |....%...! /.}.G.|
+00000010 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af c4 |bC.(.._.).0.....|
+00000020 cf c2 ed 90 99 5f 58 cb 3b 74 14 03 03 00 01 01 |....._X.;t......|
+00000030 16 03 03 00 28 00 00 00 00 00 00 00 00 75 70 c8 |....(........up.|
+00000040 c5 ef ae 60 b5 8d ba 98 1a 7d 8d c3 e4 32 fc 33 |...`.....}...2.3|
+00000050 5e 15 cc e2 d7 5d d5 76 52 1a fe ac 1e |^....].vR....|
+>>> Flow 4 (server to client)
+00000000 14 03 03 00 01 01 16 03 03 00 28 7f 2b fe 0d 9f |..........(.+...|
+00000010 93 07 fd ee 48 76 09 fb 8d 4c dd 7b b5 b5 26 36 |....Hv...L.{..&6|
+00000020 3e 05 e1 1b a7 dc 0b 4a c0 69 a8 22 33 0b 17 fc |>......J.i."3...|
+00000030 6f ab b8 |o..|
+>>> Flow 5 (client to server)
+00000000 17 03 03 00 1e 00 00 00 00 00 00 00 01 49 61 5c |.............Ia\|
+00000010 db f2 e5 63 23 3a f1 dd 12 3e 61 ed d9 4b 5f b5 |...c#:...>a..K_.|
+00000020 d3 f7 38 15 03 03 00 1a 00 00 00 00 00 00 00 02 |..8.............|
+00000030 af 09 a7 f1 e1 d9 1f 54 d1 35 19 16 b7 23 ce 4e |.......T.5...#.N|
+00000040 3a b1 |:.|
diff --git a/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES b/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES
index 10b7f52bce2..11a8a1c8cb2 100644
--- a/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES
+++ b/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-3DES
@@ -1,78 +1,76 @@
>>> Flow 1 (client to server)
-00000000 16 03 00 00 30 01 00 00 2c 03 00 50 32 2f f9 d5 |....0...,..P2/..|
-00000010 8f 83 ac 79 0e 0b e5 65 2c 87 79 01 7d 15 73 00 |...y...e,.y.}.s.|
-00000020 46 7c dc c6 6d 70 0b f3 d2 dc de 00 00 04 00 0a |F|..mp..........|
-00000030 00 ff 02 01 00 |.....|
+00000000 16 03 00 00 2f 01 00 00 2b 03 00 47 b4 bd 36 64 |..../...+..G..6d|
+00000010 0a 7d 37 1d 99 ac fd 1c 7a 3f d5 0f 9d 90 e3 59 |.}7.....z?.....Y|
+00000020 64 e4 fb 59 3a 4a 5f 53 d2 af 88 00 00 04 00 0a |d..Y:J_S........|
+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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 00 00 |..A4......9.....|
-000002b0 04 0e 00 00 00 |.....|
+00000030 05 ff 01 00 01 00 16 03 00 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 00 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 00 00 84 10 00 00 80 48 96 89 e9 d2 e6 c6 |.........H......|
-00000010 eb 9d f8 46 dd c7 d8 01 95 57 76 1a 59 1c 79 21 |...F.....Wv.Y.y!|
-00000020 94 0b 83 b2 c9 5e c1 5f 4f 12 00 10 63 12 d3 f9 |.....^._O...c...|
-00000030 ae ae 31 18 fa b4 33 37 eb b9 23 15 55 7e cf 62 |..1...37..#.U~.b|
-00000040 20 a7 cb eb 69 35 e0 35 32 e4 0a 4c c0 33 e9 7d | ...i5.52..L.3.}|
-00000050 f2 a8 4b e2 fe 90 62 7a 09 df c5 46 03 0c 52 7a |..K...bz...F..Rz|
-00000060 fb 96 dd fd 55 aa e5 be 3c 35 65 03 be e1 51 0f |....U...<5e...Q.|
-00000070 7b b3 05 6b e9 af 9b 0e e4 ea d9 34 69 a5 c2 9a |{..k.......4i...|
-00000080 71 a8 cc 0a 94 ef 91 14 88 14 03 00 00 01 01 16 |q...............|
-00000090 03 00 00 40 0c 34 26 4c cf f0 d4 a0 08 b9 b7 6b |...@.4&L.......k|
-000000a0 0a 69 55 48 91 2c 92 4c 9b e7 66 d0 b8 da 2d e7 |.iUH.,.L..f...-.|
-000000b0 89 ca f5 a4 3d 11 ff 87 22 07 c0 ed 72 9c ad 19 |....=..."...r...|
-000000c0 7d 63 2b 67 43 e3 33 76 a1 ac 69 77 55 bb 60 ba |}c+gC.3v..iwU.`.|
-000000d0 57 00 4e 2a |W.N*|
+00000000 16 03 00 00 84 10 00 00 80 43 4d 76 6b 7f b3 e6 |.........CMvk...|
+00000010 82 18 f9 8a a5 cd 45 ab 8f 1a 1d d4 9a 0a 1d 50 |......E........P|
+00000020 96 f2 08 14 a7 6b e3 ef d1 31 6b 18 d2 f5 ee e3 |.....k...1k.....|
+00000030 cd df 67 23 3d ec 70 09 07 df 32 c2 cd 60 6c 2b |..g#=.p...2..`l+|
+00000040 7f 04 cd b3 77 87 78 e5 90 60 41 0c fc 22 1a 3a |....w.x..`A..".:|
+00000050 82 29 28 92 9c f8 33 3a 72 ee 08 58 55 d5 ea 9c |.)(...3:r..XU...|
+00000060 37 96 a4 92 75 e0 29 8a 18 ad 5a c1 1f 4c aa c7 |7...u.)...Z..L..|
+00000070 49 89 6e ff 29 32 a3 c8 51 e8 50 3f 41 10 36 27 |I.n.)2..Q.P?A.6'|
+00000080 0b 60 a2 96 4b 82 a9 c6 52 14 03 00 00 01 01 16 |.`..K...R.......|
+00000090 03 00 00 40 b3 59 d0 de d1 47 8e 9e 1a 27 16 41 |...@.Y...G...'.A|
+000000a0 f7 38 4e 91 12 a0 71 89 1c 68 29 dc 60 7e 2c 39 |.8N...q..h).`~,9|
+000000b0 45 cb e6 98 8d 43 5e 76 34 ca 5b 86 24 9d 77 0a |E....C^v4.[.$.w.|
+000000c0 90 60 19 75 67 74 3d 95 1d e7 82 ee a8 9f 3a 60 |.`.ugt=.......:`|
+000000d0 8e ac 28 74 |..(t|
>>> Flow 4 (server to client)
-00000000 14 03 00 00 01 01 16 03 00 00 40 dd e1 34 c5 4a |..........@..4.J|
-00000010 96 76 81 49 df 1b 3d 48 cc 6c b0 3b ee 77 a9 62 |.v.I..=H.l.;.w.b|
-00000020 91 b3 16 b0 e1 79 4b 2a 95 d8 54 98 7b 5e ac 0f |.....yK*..T.{^..|
-00000030 07 3b 06 36 e1 38 dc 75 6a af f7 ce a4 b2 3f 9e |.;.6.8.uj.....?.|
-00000040 36 b1 44 ce e9 6c 34 ba ce 97 02 17 03 00 00 18 |6.D..l4.........|
-00000050 5b be 71 2f a1 15 2f e9 9b 83 8e f1 9b e7 5b 4a |[.q/../.......[J|
-00000060 a1 85 13 03 c0 f2 30 0c 17 03 00 00 28 2c d9 9e |......0.....(,..|
-00000070 f4 d2 70 2a 37 76 66 e7 f4 5c c7 55 be d8 82 49 |..p*7vf..\.U...I|
-00000080 77 e0 4f 0f 87 4b c0 b1 f3 d2 a3 63 df 62 bc ee |w.O..K.....c.b..|
-00000090 5c c2 50 2a 96 15 03 00 00 18 8b 0a 68 8a d8 64 |\.P*........h..d|
-000000a0 4e 3f f9 ee c6 b2 21 51 03 10 6b 73 3b 8c a4 bb |N?....!Q..ks;...|
-000000b0 6d f2 |m.|
+00000000 14 03 00 00 01 01 16 03 00 00 40 e8 3e 89 b5 10 |..........@.>...|
+00000010 e4 c9 eb f7 3f 83 e5 6a 7c 04 fd e6 96 69 25 fb |....?..j|....i%.|
+00000020 0b 0b 0e f7 13 4e 99 45 d2 0e 13 22 6b d1 0e 32 |.....N.E..."k..2|
+00000030 30 b5 c4 a2 03 cf 22 59 68 5c cc 63 96 f5 01 f3 |0....."Yh\.c....|
+00000040 2c b3 b5 13 e1 9d 19 45 c0 4f 28 17 03 00 00 18 |,......E.O(.....|
+00000050 2e cb 8c b3 d4 d5 c2 18 fd 6e dc 72 7b b3 4b b8 |.........n.r{.K.|
+00000060 10 56 0a 01 af 55 e8 5a 17 03 00 00 28 3f df 74 |.V...U.Z....(?.t|
+00000070 2f b9 5b a4 43 ec 24 68 ad ff 6c 52 b5 6a 91 0c |/.[.C.$h..lR.j..|
+00000080 be 3b 25 c9 e4 40 59 66 17 cb f0 e7 6b 6e cd 43 |.;%..@Yf....kn.C|
+00000090 ac be b7 62 d0 15 03 00 00 18 43 4d 3c fd 83 6e |...b......CM<..n|
+000000a0 e0 3f ae 40 0c 8a a1 08 d2 74 e2 60 7b d0 97 d5 |.?.@.....t.`{...|
+000000b0 e8 a5 |..|
diff --git a/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES b/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES
index e73381950eb..771373c27fb 100644
--- a/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES
+++ b/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-AES
@@ -1,79 +1,77 @@
>>> Flow 1 (client to server)
-00000000 16 03 00 00 30 01 00 00 2c 03 00 36 b0 f3 52 13 |....0...,..6..R.|
-00000010 00 17 16 8f 6e 44 24 06 84 05 5b 03 e6 8a 55 ee |....nD$...[...U.|
-00000020 75 9c a8 77 9e e0 7b 15 f9 60 6e 00 00 04 00 2f |u..w..{..`n..../|
-00000030 00 ff 02 01 00 |.....|
+00000000 16 03 00 00 2f 01 00 00 2b 03 00 26 1e 06 cd 27 |..../...+..&...'|
+00000010 f5 2a b4 8d 00 07 47 16 02 23 aa 5e 92 02 95 4a |.*....G..#.^...J|
+00000020 1a 0b a8 51 8a 6f 4a 31 3c e9 a2 00 00 04 00 2f |...Q.oJ1<....../|
+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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 00 00 |..A4......9.....|
-000002b0 04 0e 00 00 00 |.....|
+00000030 05 ff 01 00 01 00 16 03 00 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 00 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 00 00 84 10 00 00 80 2d 0b b1 1c 96 72 65 |.........-....re|
-00000010 e5 3b 5b 48 35 91 b8 2e 18 b5 6c 36 a4 91 10 0e |.;[H5.....l6....|
-00000020 15 63 de fb 7e ea 44 cd 2e 2f 37 2c 88 96 30 d4 |.c..~.D../7,..0.|
-00000030 07 ff 02 9b af 84 2c 43 6c 3a 1f 75 17 4c 5e 8b |......,Cl:.u.L^.|
-00000040 4a d9 df 68 fe ad 72 c9 0c f7 a5 0c a1 70 8b 9f |J..h..r......p..|
-00000050 e7 8e 1d 32 61 8e 80 e5 3a 3a 61 ea 22 1a 67 e5 |...2a...::a.".g.|
-00000060 06 6a 5e 0c 65 bd c7 32 9c 13 c1 53 ad 8e f1 be |.j^.e..2...S....|
-00000070 4d 6c 53 89 8f 9c 49 d2 85 58 04 b5 e8 53 b4 82 |MlS...I..X...S..|
-00000080 84 46 9d 70 fa 0a 34 15 1d 14 03 00 00 01 01 16 |.F.p..4.........|
-00000090 03 00 00 40 71 c7 4b ef 6b 7a f4 a2 29 dd c0 4b |...@q.K.kz..)..K|
-000000a0 ef 04 7d ea 1c 31 16 38 ae 85 f9 89 db 2f a8 04 |..}..1.8...../..|
-000000b0 ad 61 b7 33 73 8c 31 9b 72 5a f6 8b 10 71 0c af |.a.3s.1.rZ...q..|
-000000c0 99 89 14 63 b8 19 f8 0e 2c 0f 14 c6 d6 0a bd 4f |...c....,......O|
-000000d0 96 59 0d 60 |.Y.`|
+00000000 16 03 00 00 84 10 00 00 80 66 67 59 2f 21 b9 e3 |.........fgY/!..|
+00000010 0d a9 78 0c 6b fc dc 6f 69 4e f9 00 8b 40 a2 0f |..x.k..oiN...@..|
+00000020 5a d8 8c d2 59 ab 33 78 f6 42 2f fa cf d6 48 7a |Z...Y.3x.B/...Hz|
+00000030 59 30 94 1c 10 49 30 69 4a 6c a2 e5 ce 59 6d e3 |Y0...I0iJl...Ym.|
+00000040 49 0c a7 0a ab 17 8b c6 48 82 71 44 d5 7d 80 e5 |I.......H.qD.}..|
+00000050 6d 45 6c 10 12 01 85 71 ee dc c5 e3 19 41 ed 22 |mEl....q.....A."|
+00000060 11 5c c4 25 c6 90 ad c8 4c 48 45 8d ad 6c f4 ef |.\.%....LHE..l..|
+00000070 fb b4 2b 53 90 cc 78 b0 9e 22 e7 2c 1a 64 0e 8b |..+S..x..".,.d..|
+00000080 d8 57 54 74 c5 33 20 3f 42 14 03 00 00 01 01 16 |.WTt.3 ?B.......|
+00000090 03 00 00 40 18 b6 0a d4 9e 4d fa 8a 67 ce 8e d5 |...@.....M..g...|
+000000a0 51 31 75 65 f1 ff 54 a2 1b 80 c5 c3 a0 fc d2 78 |Q1ue..T........x|
+000000b0 0b 99 3b 65 6c 1d 52 6d a9 9f 64 13 97 d5 2e b1 |..;el.Rm..d.....|
+000000c0 76 0b a0 fb f6 16 f7 72 28 a5 8a 11 a7 46 d5 59 |v......r(....F.Y|
+000000d0 e1 f4 f3 6f |...o|
>>> Flow 4 (server to client)
-00000000 14 03 00 00 01 01 16 03 00 00 40 28 76 de 29 3b |..........@(v.);|
-00000010 48 77 56 f1 e5 97 21 20 88 9c 7d 5e 02 3d bb c9 |HwV...! ..}^.=..|
-00000020 2f b1 ce 2e 65 ac 53 ea a2 06 0e fb cf 53 28 1d |/...e.S......S(.|
-00000030 df b3 24 48 52 7a 28 d6 9e 50 83 64 da 34 c1 f4 |..$HRz(..P.d.4..|
-00000040 c9 bf ec 42 33 c4 8a 6f 89 aa 1c 17 03 00 00 20 |...B3..o....... |
-00000050 f2 af bb 38 4f 37 58 0e c4 2b 28 45 01 45 89 e9 |...8O7X..+(E.E..|
-00000060 31 5a 6d 8d 4d 1b 49 bd 7d 87 8a 62 e6 c8 03 43 |1Zm.M.I.}..b...C|
-00000070 17 03 00 00 30 60 ec e4 6f ec 88 33 d8 89 49 73 |....0`..o..3..Is|
-00000080 3a aa 67 ab 45 9f de c7 3f 0e 39 3d 9a 30 99 9c |:.g.E...?.9=.0..|
-00000090 2d 10 5f f0 7d 70 10 d5 8e ca 18 91 25 e8 9d d1 |-._.}p......%...|
-000000a0 36 b0 a7 90 9b 15 03 00 00 20 63 e9 92 98 7d b1 |6........ c...}.|
-000000b0 9a 88 07 37 b2 27 99 95 b9 16 17 74 c2 42 9c dc |...7.'.....t.B..|
-000000c0 80 32 de f4 f6 87 cb f1 87 d8 |.2........|
+00000000 14 03 00 00 01 01 16 03 00 00 40 6c 5b 64 b5 f9 |..........@l[d..|
+00000010 76 cc 7e 51 72 46 ab 21 17 b3 fb 2b 48 c5 5a 9f |v.~QrF.!...+H.Z.|
+00000020 e6 35 14 ff df c7 a7 4b 5e 5a 9b 82 57 b5 bf 4d |.5.....K^Z..W..M|
+00000030 5f 7c a5 be 67 96 71 3a 63 ad 76 86 66 06 e9 a2 |_|..g.q:c.v.f...|
+00000040 35 39 6f 79 13 21 4b 19 c1 83 0e 17 03 00 00 20 |59oy.!K........ |
+00000050 1a 80 c5 d1 8b 33 79 89 39 fc 11 44 80 33 1a f7 |.....3y.9..D.3..|
+00000060 9f 63 96 5d c9 1a d4 56 2a ee 68 24 68 83 5d ca |.c.]...V*.h$h.].|
+00000070 17 03 00 00 30 7c d4 88 17 d0 10 66 6a b3 61 ed |....0|.....fj.a.|
+00000080 0a b5 72 55 ca fb c4 ec e2 f2 e2 bf 67 dd 3d c9 |..rU........g.=.|
+00000090 01 3b 50 5c 35 ce 28 2d e6 9c 1f 5c 70 14 46 2a |.;P\5.(-...\p.F*|
+000000a0 d8 9e ef 6a 66 15 03 00 00 20 c7 af e1 86 10 30 |...jf.... .....0|
+000000b0 41 73 88 b2 86 02 a8 60 38 61 92 32 11 22 2d 47 |As.....`8a.2."-G|
+000000c0 76 fe 22 9c 76 c2 00 ee e9 03 |v.".v.....|
diff --git a/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4 b/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4
index dce3ebe9cd3..f5674ccd670 100644
--- a/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4
+++ b/libgo/go/crypto/tls/testdata/Server-SSLv3-RSA-RC4
@@ -1,74 +1,72 @@
>>> Flow 1 (client to server)
-00000000 16 03 00 00 30 01 00 00 2c 03 00 3c 64 40 96 81 |....0...,..<d@..|
-00000010 b4 90 3d a5 bb 90 8a ba 39 73 4c cd 2d f9 4c 12 |..=.....9sL.-.L.|
-00000020 4c 6e d6 09 43 e3 eb 07 2e 52 1a 00 00 04 00 05 |Ln..C....R......|
-00000030 00 ff 02 01 00 |.....|
+00000000 16 03 00 00 2f 01 00 00 2b 03 00 3f cc 8d 3f f0 |..../...+..?..?.|
+00000010 c9 36 6f 43 43 c1 46 45 cd bf e5 ba 02 e6 55 2c |.6oCC.FE......U,|
+00000020 3a 24 4a db cb a8 f2 1d 26 3e ef 00 00 04 00 05 |:$J.....&>......|
+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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 00 00 |..A4......9.....|
-000002b0 04 0e 00 00 00 |.....|
+00000030 05 ff 01 00 01 00 16 03 00 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 00 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 00 00 84 10 00 00 80 00 e0 40 dd e4 0f 54 |...........@...T|
-00000010 40 66 62 06 72 2a 7a 06 2d a9 0f 16 3b 5c 63 9b |@fb.r*z.-...;\c.|
-00000020 95 82 9c d4 95 57 c0 37 d1 30 6a 33 e1 5a ec 93 |.....W.7.0j3.Z..|
-00000030 12 ec 2a 94 c6 9c b3 6c a3 4f ef cd f1 80 25 a7 |..*....l.O....%.|
-00000040 54 ca 6a 6e b9 80 0b fc f1 e9 60 a0 f5 33 24 3b |T.jn......`..3$;|
-00000050 13 04 9a f1 8a 37 cd 11 cf 95 ae 71 ba 73 8e 00 |.....7.....q.s..|
-00000060 86 17 6a 3b d5 9e a9 04 87 fd 62 ed 4c b5 01 55 |..j;......b.L..U|
-00000070 65 a2 fb e8 1d 86 a5 58 2a ad e7 fd d3 44 2f 7d |e......X*....D/}|
-00000080 25 b7 3b c7 75 39 5c 45 f6 14 03 00 00 01 01 16 |%.;.u9\E........|
-00000090 03 00 00 3c e6 58 15 b2 fb 0d 44 ed 43 d5 ff a8 |...<.X....D.C...|
-000000a0 41 25 83 41 46 da f6 8e 70 34 39 c6 6c 2c ea 1b |A%.AF...p49.l,..|
-000000b0 2a 02 5c 4b e4 87 58 33 6c d0 22 2e ce 85 df 31 |*.\K..X3l."....1|
-000000c0 0d 71 4c 1a f9 9c 64 d7 87 53 eb c9 1a 0a 16 dc |.qL...d..S......|
+00000000 16 03 00 00 84 10 00 00 80 13 5d 75 f0 6d 24 54 |..........]u.m$T|
+00000010 f5 a1 f0 13 86 61 ce ea 66 86 06 eb c8 27 78 9f |.....a..f....'x.|
+00000020 10 0d ef 94 3f 1b fb 8c 11 14 67 2a 0e 2a 1b cf |....?.....g*.*..|
+00000030 ae 5a cb ac b8 b2 ea a8 70 85 ee fd 88 a9 61 a4 |.Z......p.....a.|
+00000040 75 66 86 a5 88 96 a0 0d 6f 77 fe 63 5e 88 60 4d |uf......ow.c^.`M|
+00000050 f6 b7 93 28 99 72 e8 60 ed 64 9a 3f e6 12 ea ee |...(.r.`.d.?....|
+00000060 83 58 d4 0c 19 e0 2b ce b0 b4 fa 73 9f 78 d9 09 |.X....+....s.x..|
+00000070 8c 17 b8 f5 04 e1 de c4 fe a9 1a aa ba 0d be f3 |................|
+00000080 c8 e1 e4 e8 cc 39 4c f0 b9 14 03 00 00 01 01 16 |.....9L.........|
+00000090 03 00 00 3c 1b 70 07 7f ad 8f a7 78 fd e8 eb b2 |...<.p.....x....|
+000000a0 9a 54 86 a2 dd bc fa b6 0a 52 48 24 79 6a 04 f6 |.T.......RH$yj..|
+000000b0 28 80 1f b7 b1 c6 4e 07 a3 52 60 5a 5a 81 14 11 |(.....N..R`ZZ...|
+000000c0 d2 ee 33 71 e7 d3 ba 3e 4b 31 81 f2 f0 49 ee e4 |..3q...>K1...I..|
>>> Flow 4 (server to client)
-00000000 14 03 00 00 01 01 16 03 00 00 3c 17 a2 5b 4a 06 |..........<..[J.|
-00000010 63 6a 4b f9 ef 66 ed 31 f6 87 75 20 8b 08 8d 5d |cjK..f.1..u ...]|
-00000020 0f 72 87 dd 8d db 99 d5 06 42 2b a3 84 77 35 f2 |.r.......B+..w5.|
-00000030 1d 11 ae 0b 0c df ed 10 6e 23 27 93 29 65 25 f6 |........n#'.)e%.|
-00000040 60 b9 76 c8 95 2b 0c 17 03 00 00 21 df 08 e8 1f |`.v..+.....!....|
-00000050 2f ea 5a 61 d6 d4 4a c0 c1 b5 59 bc e1 89 6e 88 |/.Za..J...Y...n.|
-00000060 bb 8d 16 db 64 87 31 6c 2d d6 c7 d2 ed 15 03 00 |....d.1l-.......|
-00000070 00 16 a9 53 32 af 7a a4 88 02 93 6b aa 95 84 4f |...S2.z....k...O|
-00000080 17 5a 97 93 67 87 3b 07 |.Z..g.;.|
+00000000 14 03 00 00 01 01 16 03 00 00 3c 47 20 7c b9 0d |..........<G |..|
+00000010 f8 59 c0 79 25 ae 8a f3 f5 7d 0c f5 62 d4 a5 5b |.Y.y%....}..b..[|
+00000020 f6 08 36 cc 99 21 ac 80 04 48 49 2c 04 7c 87 08 |..6..!...HI,.|..|
+00000030 d3 10 43 a9 6a ec 99 96 99 0a fa cb db 95 6f fe |..C.j.........o.|
+00000040 b1 75 77 1e b7 a9 9d 17 03 00 00 21 1a 2f bc 70 |.uw........!./.p|
+00000050 2c 00 6b 55 e1 e5 81 17 1c b7 a1 11 d7 21 c1 2f |,.kU.........!./|
+00000060 3e 95 f8 48 74 a4 97 0a 9d a2 0b bc d4 15 03 00 |>..Ht...........|
+00000070 00 16 67 0d 6d 69 53 87 92 23 21 51 72 f6 31 73 |..g.miS..#!Qr.1s|
+00000080 db bd 3c e6 f4 12 4c 69 |..<...Li|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES
index 9314b909241..3e170818a05 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES
@@ -1,11 +1,10 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5f 01 00 00 5b 03 01 ad 87 94 6b 8a |...._...[.....k.|
-00000010 38 9e 70 d6 94 8a 73 a9 39 d8 d7 25 ab 47 92 4c |8.p...s.9..%.G.L|
-00000020 b1 20 8e 4d f3 7b cd 84 5e 13 c1 00 00 04 c0 0a |. .M.{..^.......|
-00000030 00 ff 02 01 00 00 2d 00 0b 00 04 03 00 01 02 00 |......-.........|
-00000040 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 18 00 |................|
-00000050 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 0a 00 |................|
-00000060 0f 00 01 01 |....|
+00000000 16 03 01 00 4f 01 00 00 4b 03 01 f1 86 d0 c8 69 |....O...K......i|
+00000010 46 0b 0b 89 08 c0 82 c0 f7 f1 9a b6 d2 2b e1 46 |F............+.F|
+00000020 e6 e1 44 65 de 39 0a 68 a8 d5 1c 00 00 04 c0 0a |..De.9.h........|
+00000030 00 ff 01 00 00 1e 00 0b 00 04 03 00 01 02 00 0a |................|
+00000040 00 0a 00 08 00 1d 00 17 00 19 00 18 00 16 00 00 |................|
+00000050 00 17 00 00 |....|
>>> 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 |................|
@@ -43,41 +42,37 @@
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 8b |A.Vk.Z...0...B..|
-000002a0 48 d5 a3 a0 35 5c 31 f5 0b e8 72 7c 87 31 79 af |H...5\1...r|.1y.|
-000002b0 7f 12 93 9a f9 df d5 44 bf 08 5a 6b 1c 68 dd 73 |.......D..Zk.h.s|
-000002c0 67 0f 32 41 45 53 bf 74 cf 91 54 e7 7a 88 41 7a |g.2AES.t..T.z.Az|
-000002d0 15 ea 3d e3 b8 93 c0 3f 24 4c fb ee 25 f1 20 80 |..=....?$L..%. .|
-000002e0 02 42 01 ab 97 5f 8b 8d 22 71 f9 f5 a3 59 69 42 |.B..._.."q...YiB|
-000002f0 06 bd 12 f5 61 53 cb c8 a1 b4 90 87 12 94 9b f8 |....aS..........|
-00000300 b3 1d 34 d9 cd 64 20 9c 92 ec b5 72 35 01 44 3a |..4..d ....r5.D:|
-00000310 86 e4 54 46 0d 74 1d 4e d8 41 16 eb ac c3 8a 2f |..TF.t.N.A...../|
-00000320 20 11 ad bc 16 03 01 00 04 0e 00 00 00 | ............|
+00000240 7b 6a 0f 39 95 12 07 8f 2a 16 03 01 00 b5 0c 00 |{j.9....*.......|
+00000250 00 b1 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 28 |..... /.}.G.bC.(|
+00000260 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 |.._.).0.........|
+00000270 99 5f 58 cb 3b 74 00 8b 30 81 88 02 42 00 ad 93 |._X.;t..0...B...|
+00000280 e2 c2 3d 7e 95 63 17 5d 45 cf cd 27 af d2 db b3 |..=~.c.]E..'....|
+00000290 d0 bc 13 1e 6f 0a 61 3a fb 3c b3 03 61 2c 36 ae |....o.a:.<..a,6.|
+000002a0 4f be 27 e9 43 3c cf 57 9b 82 5e 7d 54 36 ed 7e |O.'.C<.W..^}T6.~|
+000002b0 0b 34 68 26 90 00 20 02 0f c1 18 bc 79 1b 90 02 |.4h&.. .....y...|
+000002c0 42 01 6b 66 9d 56 48 8e 5e 38 93 48 03 6b b9 d7 |B.kf.VH.^8.H.k..|
+000002d0 bd 14 a0 3e 8a 27 81 7f fe 4d e5 8a 12 4d 95 16 |...>.'...M...M..|
+000002e0 ef c7 8d 60 07 1d 22 f8 5d 72 0d cc be c3 51 69 |...`..".]r....Qi|
+000002f0 7a 04 e3 84 e5 ba dd 04 1d d4 4c 6f 9f 6b 12 e0 |z.........Lo.k..|
+00000300 2f 83 3c 16 03 01 00 04 0e 00 00 00 |/.<.........|
>>> Flow 3 (client to server)
-00000000 16 03 01 00 46 10 00 00 42 41 04 38 ca 59 61 cd |....F...BA.8.Ya.|
-00000010 17 4a cf a8 0b 81 c6 b7 7f 52 dd 95 d7 57 9d 24 |.J.......R...W.$|
-00000020 bb b1 02 af 57 ee b9 f9 c5 a0 c3 20 44 e1 9a e4 |....W...... D...|
-00000030 83 64 7d a1 fa 9d 2e 3b 5e be 0f af ed 96 f3 09 |.d}....;^.......|
-00000040 62 a2 22 21 72 f8 84 89 8a fd 10 14 03 01 00 01 |b."!r...........|
-00000050 01 16 03 01 00 30 bd e6 23 e0 32 b8 4c ef ce 9e |.....0..#.2.L...|
-00000060 22 a5 77 2c f1 7e 2f 8d 8b 9e a5 92 42 f9 0f 02 |".w,.~/.....B...|
-00000070 eb 2e 94 f1 6d a3 24 3f c0 ae bb c0 c4 99 08 51 |....m.$?.......Q|
-00000080 47 28 8b 4e f9 02 |G(.N..|
+00000000 16 03 01 00 25 10 00 00 21 20 18 40 ea d1 e1 17 |....%...! .@....|
+00000010 b6 a2 a5 db 20 13 70 81 90 fc ac e8 96 7c b1 e1 |.... .p......|..|
+00000020 ff 6f 57 1f c1 64 72 94 f7 05 14 03 01 00 01 01 |.oW..dr.........|
+00000030 16 03 01 00 30 05 33 48 f0 2a 3a df df 1d c4 3d |....0.3H.*:....=|
+00000040 87 ea 9d 04 04 eb 84 bf a0 ed bc 56 2f ab 36 52 |...........V/.6R|
+00000050 d5 b2 2c 6f 8c 58 49 51 33 d5 fc df 5d 09 df e9 |..,o.XIQ3...]...|
+00000060 be 20 30 9a 37 |. 0.7|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 11 a9 f0 95 27 |..........0....'|
-00000010 ac 0a b7 8e 0d 42 0a 2a f8 f8 e2 4f 4f 4a 79 d1 |.....B.*...OOJy.|
-00000020 73 e6 4d 42 90 3c 06 f8 7b da 26 cc 58 be 97 f6 |s.MB.<..{.&.X...|
-00000030 41 32 fb 39 2f fa e1 bc 59 2b 45 17 03 01 00 20 |A2.9/...Y+E.... |
-00000040 93 6a a1 a6 a2 e6 be bb be 2f 8f 0c 52 39 1c 6a |.j......./..R9.j|
-00000050 6d 4c af 38 f7 60 8b ad 0e c7 62 0c 8b a4 42 14 |mL.8.`....b...B.|
-00000060 17 03 01 00 30 da b0 1b ef cf 45 86 09 e9 be aa |....0.....E.....|
-00000070 0f 71 af a3 86 d0 0f 2d e8 76 39 9a c4 1f f5 c2 |.q.....-.v9.....|
-00000080 82 0a ee 34 0e a6 3b 19 b8 2c 10 ad fc 03 33 31 |...4..;..,....31|
-00000090 10 42 9b 6e 7b 15 03 01 00 20 ac 73 4d 4b 92 30 |.B.n{.... .sMK.0|
-000000a0 bf 4c bc 77 c1 87 d7 20 ad 82 bd 75 31 82 0d 34 |.L.w... ...u1..4|
-000000b0 cb b2 86 fd 4f 9c 84 a3 80 af |....O.....|
+00000000 14 03 01 00 01 01 16 03 01 00 30 8c b6 5b 83 03 |..........0..[..|
+00000010 c0 d8 83 f7 1d 24 2e ec 39 68 00 91 73 d2 5a 15 |.....$..9h..s.Z.|
+00000020 3f 83 aa e3 6d fd cc 31 58 90 e9 a9 e3 e4 78 5d |?...m..1X.....x]|
+00000030 ce 8e b3 ba cd 71 aa a2 fd f4 7c 17 03 01 00 20 |.....q....|.... |
+00000040 62 98 34 9d 01 13 13 2d 1b 27 3a 4f 10 28 48 d6 |b.4....-.':O.(H.|
+00000050 32 8c 99 2a c8 64 14 6e dc f5 7c 6d 16 59 45 8e |2..*.d.n..|m.YE.|
+00000060 17 03 01 00 30 1e ed f9 40 ad 5c 5d f6 94 c9 fd |....0...@.\]....|
+00000070 a1 ac fc 00 7b 48 9a 59 6d f5 b7 06 a4 66 25 04 |....{H.Ym....f%.|
+00000080 61 33 08 f3 66 86 21 00 fb f3 03 78 83 4c b6 c8 |a3..f.!....x.L..|
+00000090 9d 5e ea f5 7e 15 03 01 00 20 98 d8 f6 2a 79 60 |.^..~.... ...*y`|
+000000a0 8d fb c9 45 2f 27 59 17 a9 79 eb e7 b9 46 f1 57 |...E/'Y..y...F.W|
+000000b0 a6 fa ea e1 d0 23 8c 03 4f 72 |.....#..Or|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-3DES b/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-3DES
index 33e8063ba60..9590b0daa1e 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-3DES
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-3DES
@@ -1,74 +1,72 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 37 01 00 00 33 03 01 8d f4 8c 3d bd |....7...3.....=.|
-00000010 d8 81 53 bb f5 bc 18 69 07 09 0d 05 93 4f 6f eb |..S....i.....Oo.|
-00000020 fa fb 03 65 d4 49 a3 df 9f c3 a5 00 00 04 00 0a |...e.I..........|
-00000030 00 ff 02 01 00 00 05 00 0f 00 01 01 |............|
+00000000 16 03 01 00 39 01 00 00 35 03 01 58 71 a3 0c c4 |....9...5..Xq...|
+00000010 b6 b0 33 0a 66 3c eb c6 f4 d9 0e 99 75 d4 9e b6 |..3.f<......u...|
+00000020 03 b4 ae ae ad bc a8 ab 64 a0 27 00 00 04 00 0a |........d.'.....|
+00000030 00 ff 01 00 00 08 00 16 00 00 00 17 00 00 |..............|
>>> 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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 01 00 |..A4......9.....|
-000002b0 04 0e 00 00 00 |.....|
+00000030 05 ff 01 00 01 00 16 03 01 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 01 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 01 00 86 10 00 00 82 00 80 6b 00 e3 47 e3 |...........k..G.|
-00000010 0d 22 44 53 7a b9 d1 14 4e e4 47 17 a1 e2 f5 d2 |."DSz...N.G.....|
-00000020 f7 82 2f 1b e2 3a 60 aa 79 36 fa 74 05 72 66 88 |../..:`.y6.t.rf.|
-00000030 3f 6a 57 8d 10 8a a1 80 3c 74 5b 29 c3 a1 b8 57 |?jW.....<t[)...W|
-00000040 20 cc 75 fc 0e 3c 09 06 46 52 b2 ca b2 cd bf 4c | .u..<..FR.....L|
-00000050 b3 12 2b 59 f1 41 a2 c7 4c 62 c7 61 26 2b 89 fe |..+Y.A..Lb.a&+..|
-00000060 01 9a b6 2b b4 15 75 05 4b f8 5b 04 9a 64 cc 06 |...+..u.K.[..d..|
-00000070 6b 8c 98 6d 51 37 50 b4 69 03 5c 9a ed e3 9a 23 |k..mQ7P.i.\....#|
-00000080 a9 68 e0 56 58 f7 f4 a0 d6 b4 55 14 03 01 00 01 |.h.VX.....U.....|
-00000090 01 16 03 01 00 28 9f ac be d9 6f ab cb 0e 45 8a |.....(....o...E.|
-000000a0 96 71 fd 23 39 b0 02 cc a6 5a 7a 64 e2 29 9f 18 |.q.#9....Zzd.)..|
-000000b0 dc 25 84 ee 76 56 3c cc d9 15 34 16 67 7e |.%..vV<...4.g~|
+00000000 16 03 01 00 86 10 00 00 82 00 80 ab 50 cd 04 9e |............P...|
+00000010 db 19 e4 18 26 ff 59 41 20 02 a5 a2 20 a3 1c 44 |....&.YA ... ..D|
+00000020 02 bc 9a 1c d9 d7 5d 5b 55 fc 2a 4d 2b 03 22 b1 |......][U.*M+.".|
+00000030 de 96 10 84 6f e3 f2 22 2d 6f cb 29 07 43 a6 6e |....o.."-o.).C.n|
+00000040 ce 23 64 f7 72 2b dc 9b c0 6f 7f bd 8e cf e2 7f |.#d.r+...o......|
+00000050 75 12 24 72 23 6b 26 08 69 76 17 c0 21 91 c0 7d |u.$r#k&.iv..!..}|
+00000060 8c 8f 20 83 08 02 0d 73 27 23 91 35 5f 3f e6 56 |.. ....s'#.5_?.V|
+00000070 1d 69 d3 1d 3b 0e fa 60 86 8b 40 ad c0 48 59 60 |.i..;..`..@..HY`|
+00000080 45 eb b0 77 2c 91 94 75 fd 6a d3 14 03 01 00 01 |E..w,..u.j......|
+00000090 01 16 03 01 00 28 8b 25 c1 8f 25 32 b5 cb 74 6d |.....(.%..%2..tm|
+000000a0 08 67 59 a3 ae ae 16 f9 fa 03 f6 54 42 f4 56 3f |.gY........TB.V?|
+000000b0 c4 12 66 f3 1a b0 48 95 24 79 fe 41 a5 d1 |..f...H.$y.A..|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 28 f4 cf 23 f8 86 |..........(..#..|
-00000010 83 df 44 af 1c 25 b1 51 84 5b 6a f3 0e 6b 47 5c |..D..%.Q.[j..kG\|
-00000020 2a 59 67 db 42 11 f9 53 58 4e db 6f 00 b2 20 5b |*Yg.B..SXN.o.. [|
-00000030 ae a3 43 17 03 01 00 18 df e0 22 d6 05 ab 79 c7 |..C......."...y.|
-00000040 87 8a 82 83 01 bc 06 45 36 74 4d 1c 40 96 97 5f |.......E6tM.@.._|
-00000050 17 03 01 00 28 49 bd b7 e9 41 6b eb b1 aa 89 60 |....(I...Ak....`|
-00000060 21 91 df bf f4 7a 49 9d 54 04 4a 16 1a d1 44 9a |!....zI.T.J...D.|
-00000070 09 6c 4f 01 3d c0 2f d5 a3 72 a3 b2 fe 15 03 01 |.lO.=./..r......|
-00000080 00 18 5c 7a de a0 ef ed 56 99 99 01 5f b4 32 b3 |..\z....V..._.2.|
-00000090 00 be c6 cc 7e bb 6f 82 7d f7 |....~.o.}.|
+00000000 14 03 01 00 01 01 16 03 01 00 28 ff 69 ed 0f 20 |..........(.i.. |
+00000010 ff e1 42 78 b9 bc a8 61 48 82 08 a0 01 a5 98 91 |..Bx...aH.......|
+00000020 3e 39 d4 6d 17 38 a2 04 18 ed 90 3c f0 cf 6a 9a |>9.m.8.....<..j.|
+00000030 ea c5 45 17 03 01 00 18 b5 76 2c 0e f1 34 51 e5 |..E......v,..4Q.|
+00000040 f5 38 d3 9f c9 c5 d5 19 35 c3 2e ec 18 df 8e c8 |.8......5.......|
+00000050 17 03 01 00 28 47 6f e9 c0 fa b3 21 ec 6c 16 e7 |....(Go....!.l..|
+00000060 71 a8 09 15 17 86 68 1c cf fa ea 37 68 d3 33 ef |q.....h....7h.3.|
+00000070 4a b1 95 46 5b 16 d7 95 f8 13 65 2f 93 15 03 01 |J..F[.....e/....|
+00000080 00 18 1b 0c 09 81 ff fc 6d 82 84 ab 83 98 fc 72 |........m......r|
+00000090 f5 4a a0 eb 08 96 79 01 76 26 |.J....y.v&|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES b/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES
index e51bc17ee75..c1750292d73 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-AES
@@ -1,77 +1,75 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 37 01 00 00 33 03 01 39 72 8e 06 ed |....7...3..9r...|
-00000010 d2 74 5c 02 74 0e 2b 7a bd 54 ce be 17 a0 4f 1a |.t\.t.+z.T....O.|
-00000020 c5 72 b1 e8 3e 2e 90 68 ff fc 6e 00 00 04 00 2f |.r..>..h..n..../|
-00000030 00 ff 02 01 00 00 05 00 0f 00 01 01 |............|
+00000000 16 03 01 00 39 01 00 00 35 03 01 82 f3 04 d5 71 |....9...5......q|
+00000010 d8 65 69 36 46 cb 45 77 b2 ef 00 75 98 e4 16 d2 |.ei6F.Ew...u....|
+00000020 70 f7 3c 97 84 49 ef da 5d cd 64 00 00 04 00 2f |p.<..I..].d..../|
+00000030 00 ff 01 00 00 08 00 16 00 00 00 17 00 00 |..............|
>>> 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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 01 00 |..A4......9.....|
-000002b0 04 0e 00 00 00 |.....|
+00000030 05 ff 01 00 01 00 16 03 01 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 01 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 01 00 86 10 00 00 82 00 80 0e a2 23 fe 89 |.............#..|
-00000010 46 08 20 98 da 4d 91 a4 48 40 ab 03 df 1f 00 67 |F. ..M..H@.....g|
-00000020 f3 fb fb 22 f7 8e d6 65 2c 43 a7 f4 9c 0e 25 cc |..."...e,C....%.|
-00000030 d9 3b b5 58 df bd 93 27 1c df 69 37 27 01 cb 0d |.;.X...'..i7'...|
-00000040 b4 f4 a6 8d 91 fe ef dc 9a e2 09 7c 53 1a 73 6d |...........|S.sm|
-00000050 b9 f6 89 0a 1f 94 f0 26 25 ef 73 54 20 d5 8d 77 |.......&%.sT ..w|
-00000060 36 2e e7 4c 9a f1 4a be ae 6e b6 be 16 10 31 42 |6..L..J..n....1B|
-00000070 9e d2 49 41 2c 32 52 11 bc 85 2d fa 39 80 9b f9 |..IA,2R...-.9...|
-00000080 95 fe e8 88 2a a2 57 65 7e 38 b2 14 03 01 00 01 |....*.We~8......|
-00000090 01 16 03 01 00 30 1c 6f 91 45 16 ed 25 82 ee 5f |.....0.o.E..%.._|
-000000a0 f9 f0 09 0c a4 ad 56 61 e5 b7 a2 05 50 02 b8 80 |......Va....P...|
-000000b0 ef 73 d1 11 3c 25 50 44 0d ba b5 7c fd 5d 7a df |.s..<%PD...|.]z.|
-000000c0 14 62 1b 29 be 29 |.b.).)|
+00000000 16 03 01 00 86 10 00 00 82 00 80 9c a1 18 77 22 |..............w"|
+00000010 f5 a1 cf 4d cc df 27 7c c5 7e 98 24 24 be 2f b2 |...M..'|.~.$$./.|
+00000020 1d d7 b8 2f fe 90 73 d0 fc f6 88 3c 91 a4 bc dc |.../..s....<....|
+00000030 b9 0b 48 0d 55 e5 9f c1 8a 6c 1c 7d 4d a9 12 d5 |..H.U....l.}M...|
+00000040 87 4b 9a 77 74 3d 33 8c c7 17 fb 32 09 df 86 f1 |.K.wt=3....2....|
+00000050 93 cc 17 f9 08 bd bc 0e 38 df 9d 82 ad cc 70 0c |........8.....p.|
+00000060 f5 8b 8d 99 e8 5f 3e e5 a6 c7 c2 6a 67 02 90 82 |....._>....jg...|
+00000070 28 9a 72 e1 3e 77 51 10 84 29 21 09 56 36 f2 6a |(.r.>wQ..)!.V6.j|
+00000080 1d 15 08 7b 44 41 43 59 55 8d 52 14 03 01 00 01 |...{DACYU.R.....|
+00000090 01 16 03 01 00 30 06 5b 20 42 7e 7b 1f 4b 7c 36 |.....0.[ B~{.K|6|
+000000a0 99 bb c6 b4 ea a1 19 3e 02 0c 3b 3a 38 be 80 11 |.......>..;:8...|
+000000b0 29 72 a8 12 92 ad 24 9d bf 01 3e ef 9a f1 db 33 |)r....$...>....3|
+000000c0 3e c1 dc d2 51 b1 |>...Q.|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 30 5e 8c b1 dc 1f |..........0^....|
-00000010 b3 18 85 4a 46 02 fb 34 e4 05 56 78 4c e3 34 63 |...JF..4..VxL.4c|
-00000020 06 08 b4 ee 36 e2 28 ab c9 98 ee 26 4e 5b 5d 42 |....6.(....&N[]B|
-00000030 5f f8 e1 d1 2f 8b c8 ef 5a 65 40 17 03 01 00 20 |_.../...Ze@.... |
-00000040 e7 92 6e b1 60 b9 f8 cd 53 d3 37 5b 44 74 1c af |..n.`...S.7[Dt..|
-00000050 90 93 13 8e 55 25 cc 9f 57 8c f3 06 f7 ba e0 f9 |....U%..W.......|
-00000060 17 03 01 00 30 fc 83 e6 4e 8c 65 8f d1 7c c7 f4 |....0...N.e..|..|
-00000070 8b 68 0d 5d da 8e 49 45 68 ea 4c e3 7f 7d 84 87 |.h.]..IEh.L..}..|
-00000080 2f 63 e0 fb 43 24 04 cd e2 38 32 50 0a 4c 43 ce |/c..C$...82P.LC.|
-00000090 3b 12 a5 6b 99 15 03 01 00 20 2a 42 d8 57 26 79 |;..k..... *B.W&y|
-000000a0 51 ee 79 9d b2 83 b8 49 a4 e9 a2 08 34 73 c4 f5 |Q.y....I....4s..|
-000000b0 53 21 4b 78 ec 5b ce b4 4e a0 |S!Kx.[..N.|
+00000000 14 03 01 00 01 01 16 03 01 00 30 2e d5 04 91 6d |..........0....m|
+00000010 32 12 8b 41 4a 46 2c f3 7f d4 16 0a 21 c2 ac 88 |2..AJF,.....!...|
+00000020 09 a0 b5 0d 65 4e 44 e1 92 5a ae b8 3f 61 1f 35 |....eND..Z..?a.5|
+00000030 ab 3a fe bd f8 3c 2c 42 dd 68 0f 17 03 01 00 20 |.:...<,B.h..... |
+00000040 6e d4 08 98 bf b7 18 84 ee 68 f8 17 88 c5 13 7a |n........h.....z|
+00000050 73 e0 c6 ca 0d 21 4d 6b 44 dc 94 36 6c e4 a0 2f |s....!MkD..6l../|
+00000060 17 03 01 00 30 a0 45 d0 88 5d 96 48 26 46 37 33 |....0.E..].H&F73|
+00000070 f6 48 f3 38 2e 38 d7 b6 ef d5 25 bf f3 1b b6 78 |.H.8.8....%....x|
+00000080 32 a7 9c fe be 55 35 f2 07 5b b7 14 87 89 80 f2 |2....U5..[......|
+00000090 cc d5 cb c8 57 15 03 01 00 20 80 2a 8e 6c b8 5a |....W.... .*.l.Z|
+000000a0 41 b4 ae 56 ca 3f 8b a2 e1 ea a0 55 64 b5 60 44 |A..V.?.....Ud.`D|
+000000b0 8f de 33 c6 37 f7 df b5 d9 c3 |..3.7.....|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4 b/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4
index 8d5446341ba..3d788c35d23 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv10-RSA-RC4
@@ -1,71 +1,69 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 37 01 00 00 33 03 01 b3 82 99 50 b0 |....7...3.....P.|
-00000010 1e 7a 46 48 9d 8e 93 32 3b 01 bc 50 e9 5c eb 91 |.zFH...2;..P.\..|
-00000020 25 4b c1 ea 0a 91 c9 b3 2b 54 90 00 00 04 00 05 |%K......+T......|
-00000030 00 ff 02 01 00 00 05 00 0f 00 01 01 |............|
+00000000 16 03 01 00 39 01 00 00 35 03 01 71 34 00 f7 c4 |....9...5..q4...|
+00000010 e6 94 b4 ca f2 af d5 0a 82 ce d4 f6 b7 4a a7 d1 |.............J..|
+00000020 1a 88 65 b2 3c b2 6c ec f7 eb 4a 00 00 04 00 05 |..e.<.l...J.....|
+00000030 00 ff 01 00 00 08 00 16 00 00 00 17 00 00 |..............|
>>> 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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 01 00 |..A4......9.....|
-000002b0 04 0e 00 00 00 |.....|
+00000030 05 ff 01 00 01 00 16 03 01 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 01 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 01 00 86 10 00 00 82 00 80 05 1c 93 2a 69 |..............*i|
-00000010 f7 0b 1d 59 ea ca c2 4a b1 7c ef 22 4c 7b 31 5f |...Y...J.|."L{1_|
-00000020 18 8d 32 b6 db 75 8c f8 45 07 27 e1 9f 3f 9d 0b |..2..u..E.'..?..|
-00000030 02 ac 2c 3f aa bf 79 fb d4 af 98 0c b2 c0 03 4b |..,?..y........K|
-00000040 86 26 c3 30 f3 ea 2b 1a ab 70 90 8d 01 2b 0e ff |.&.0..+..p...+..|
-00000050 4c 10 9a 29 75 cb 14 bb 85 80 98 35 fb 82 e8 b5 |L..)u......5....|
-00000060 80 6f 9d e6 3b b6 14 36 bb 61 8e 18 f2 6b da 09 |.o..;..6.a...k..|
-00000070 71 9c 6d 1e c3 60 a9 c5 8b 4e 77 41 db ec 12 49 |q.m..`...NwA...I|
-00000080 a4 c2 e2 10 ce 7f 18 05 b9 74 aa 14 03 01 00 01 |.........t......|
-00000090 01 16 03 01 00 24 3d 90 d0 f6 6f 15 94 05 a0 fb |.....$=...o.....|
-000000a0 43 83 55 b5 b1 ef e5 fd fc 00 d3 d5 25 b4 7c 9f |C.U.........%.|.|
-000000b0 e0 82 99 2a 6d 5a 26 7c 05 21 |...*mZ&|.!|
+00000000 16 03 01 00 86 10 00 00 82 00 80 a5 75 5a 20 2c |............uZ ,|
+00000010 31 f7 61 dc 73 c7 f6 4c 06 d2 b9 c0 e8 5f cc 0c |1.a.s..L....._..|
+00000020 51 70 0a 30 b2 8a bb 3b 4c 37 f6 d3 38 da 13 48 |Qp.0...;L7..8..H|
+00000030 90 4f fe 41 ec 53 3c fb 07 26 77 68 07 a0 fb 71 |.O.A.S<..&wh...q|
+00000040 b6 cc 3c cd b4 64 03 08 3a 76 97 6e 6c f1 b4 a9 |..<..d..:v.nl...|
+00000050 af f4 e0 ce bf 36 b9 8e 37 12 de 5b ac 24 06 63 |.....6..7..[.$.c|
+00000060 e2 fb 13 33 be 3b 8d 93 e3 10 95 29 21 b2 22 77 |...3.;.....)!."w|
+00000070 cb 95 b2 13 b3 76 47 98 13 1b a8 cc 50 47 ed 50 |.....vG.....PG.P|
+00000080 f0 cc ca 5a c6 a0 1e c9 9c 97 58 14 03 01 00 01 |...Z......X.....|
+00000090 01 16 03 01 00 24 e7 fd a2 7e fd 6f 53 da 29 68 |.....$...~.oS.)h|
+000000a0 c3 49 2e e9 69 a1 94 b9 e4 a0 cb a2 94 14 a6 42 |.I..i..........B|
+000000b0 df 75 1e da 95 e5 60 e3 35 f1 |.u....`.5.|
>>> Flow 4 (server to client)
-00000000 14 03 01 00 01 01 16 03 01 00 24 28 d0 1f ec 1d |..........$(....|
-00000010 9e 1d e3 80 6b 6d 3e 8b c5 f7 9c 14 a9 0b c3 53 |....km>........S|
-00000020 fd 48 d0 b3 eb d1 49 97 97 71 e9 36 b9 e6 3a 17 |.H....I..q.6..:.|
-00000030 03 01 00 21 c3 b6 2e 02 05 86 0f 57 04 dd 88 33 |...!.......W...3|
-00000040 0a ed 1d d5 a8 0f 55 54 c5 8c 87 5b 11 b7 80 7f |......UT...[....|
-00000050 30 79 e0 64 ee 15 03 01 00 16 b1 50 de 3d 18 05 |0y.d.......P.=..|
-00000060 2f db 37 4c db 62 f1 c8 d5 19 ca c2 fb a5 8a 37 |/.7L.b.........7|
+00000000 14 03 01 00 01 01 16 03 01 00 24 44 a6 c8 7b 5f |..........$D..{_|
+00000010 b9 4e c2 62 2d e0 c3 9f 76 0f b3 e5 f5 07 b7 c0 |.N.b-...v.......|
+00000020 93 cd 1f 32 3c 0a 7a 83 57 4a 24 59 ac 95 f9 17 |...2<.z.WJ$Y....|
+00000030 03 01 00 21 6f 02 76 2e 70 82 a0 6c 11 ce 3c b8 |...!o.v.p..l..<.|
+00000040 dd d3 9e 2a ee ce d7 7f 63 1a 5b 35 d0 46 68 7d |...*....c.[5.Fh}|
+00000050 21 6e 5b 64 fc 15 03 01 00 16 81 56 32 7d 51 e4 |!n[d.......V2}Q.|
+00000060 08 53 85 45 65 c3 87 ac b0 58 70 4f 6f f7 64 4e |.S.Ee....XpOo.dN|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv11-FallbackSCSV b/libgo/go/crypto/tls/testdata/Server-TLSv11-FallbackSCSV
index a6e2137e504..209e6216cfd 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv11-FallbackSCSV
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv11-FallbackSCSV
@@ -1,17 +1,10 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 cf 01 00 00 cb 03 02 ee 33 c1 3f a6 |............3.?.|
-00000010 62 ba a6 4f c7 32 25 0f 15 66 f7 35 a2 cf c0 cd |b..O.2%..f.5....|
-00000020 48 93 77 1c 04 1f fb 65 41 37 ca 00 00 70 c0 14 |H.w....eA7...p..|
-00000030 c0 0a 00 39 00 38 00 37 00 36 00 88 00 87 00 86 |...9.8.7.6......|
-00000040 00 85 c0 0f c0 05 00 35 00 84 c0 13 c0 09 00 33 |.......5.......3|
-00000050 00 32 00 31 00 30 00 9a 00 99 00 98 00 97 00 45 |.2.1.0.........E|
-00000060 00 44 00 43 00 42 c0 0e c0 04 00 2f 00 96 00 41 |.D.C.B...../...A|
-00000070 00 07 c0 11 c0 07 c0 0c c0 02 00 05 00 04 c0 12 |................|
-00000080 c0 08 00 16 00 13 00 10 00 0d c0 0d c0 03 00 0a |................|
-00000090 00 15 00 12 00 0f 00 0c 00 09 00 ff 56 00 02 01 |............V...|
-000000a0 00 00 31 00 0b 00 04 03 00 01 02 00 0a 00 1c 00 |..1.............|
-000000b0 1a 00 17 00 19 00 1c 00 1b 00 18 00 1a 00 16 00 |................|
-000000c0 0e 00 0d 00 0b 00 0c 00 09 00 0a 00 23 00 00 00 |............#...|
-000000d0 0f 00 01 01 |....|
+00000000 16 03 01 00 63 01 00 00 5f 03 02 6e 78 cc 6a ea |....c..._..nx.j.|
+00000010 13 aa a8 20 76 7d 32 ca c7 3f be 88 36 ae fb c3 |... v}2..?..6...|
+00000020 ca 95 35 70 54 20 3b 18 3b ba 82 00 00 14 c0 0a |..5pT ;.;.......|
+00000030 c0 14 00 39 c0 09 c0 13 00 33 00 35 00 2f 00 ff |...9.....3.5./..|
+00000040 56 00 01 00 00 22 00 0b 00 04 03 00 01 02 00 0a |V...."..........|
+00000050 00 0a 00 08 00 1d 00 17 00 19 00 18 00 23 00 00 |.............#..|
+00000060 00 16 00 00 00 17 00 00 |........|
>>> 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
index b3916f9fd1c..18debc470ce 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv11-RSA-RC4
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv11-RSA-RC4
@@ -1,71 +1,69 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 37 01 00 00 33 03 02 95 4a cf f5 14 |....7...3...J...|
-00000010 56 9b d6 be 0c ba 0d b2 ad 65 47 d2 c6 ce 84 c9 |V........eG.....|
-00000020 f4 80 2a 4e 75 df ff 48 cf 48 9b 00 00 04 00 05 |..*Nu..H.H......|
-00000030 00 ff 02 01 00 00 05 00 0f 00 01 01 |............|
+00000000 16 03 01 00 39 01 00 00 35 03 02 15 67 73 bf 3f |....9...5...gs.?|
+00000010 6f 15 30 c2 34 2e c6 1b 23 3a 42 45 4d d9 87 a2 |o.0.4...#:BEM...|
+00000020 e7 b8 de 1c b8 2b cc 21 7a 0b a1 00 00 04 00 05 |.....+.!z.......|
+00000030 00 ff 01 00 00 08 00 16 00 00 00 17 00 00 |..............|
>>> 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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 02 00 |..A4......9.....|
-000002b0 04 0e 00 00 00 |.....|
+00000030 05 ff 01 00 01 00 16 03 02 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 02 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 02 00 86 10 00 00 82 00 80 19 c3 d4 f2 e4 |................|
-00000010 bf 4a 52 90 a4 65 f6 e7 29 1a 7f ef 0e a4 1e b4 |.JR..e..).......|
-00000020 c2 df b2 83 43 4a 1a f4 b6 cd 51 a5 24 62 3f e1 |....CJ....Q.$b?.|
-00000030 fb 5f 7e b1 10 08 3b 8a ab eb 3a a3 72 ba 31 1c |._~...;...:.r.1.|
-00000040 23 bd ef 2e 3d 13 dc 61 88 a6 af ca 80 82 5d e4 |#...=..a......].|
-00000050 d6 a2 d3 13 80 87 c6 ad a5 13 4e f1 b6 a0 5d fa |..........N...].|
-00000060 ed a7 0d 37 58 f1 54 38 18 f5 be db 90 9f 07 4a |...7X.T8.......J|
-00000070 67 25 c9 8d 9d 5e 07 62 ca db 72 74 b5 bd a0 ed |g%...^.b..rt....|
-00000080 d0 95 9f 3e cd 37 b8 96 df df 3b 14 03 02 00 01 |...>.7....;.....|
-00000090 01 16 03 02 00 24 80 53 7a 8f 23 06 a7 6b e6 be |.....$.Sz.#..k..|
-000000a0 61 c2 1a c8 35 30 6b e2 2f 82 f3 46 ff e3 1d bd |a...50k./..F....|
-000000b0 68 e9 a2 78 49 33 05 ca d9 41 |h..xI3...A|
+00000000 16 03 02 00 86 10 00 00 82 00 80 75 8e 85 93 be |...........u....|
+00000010 53 df e0 4f 65 92 ed 3d 58 34 f8 06 fd 36 e4 5a |S..Oe..=X4...6.Z|
+00000020 f7 7a 59 88 f6 ac bd de 21 ed c4 04 0d 35 19 cd |.zY.....!....5..|
+00000030 ff 3b 9f c4 bc 93 4f 21 2a 36 a3 99 a4 6f eb 1e |.;....O!*6...o..|
+00000040 7b b4 a8 a7 6d 69 a5 93 b6 e3 d2 2d be 7a c8 f3 |{...mi.....-.z..|
+00000050 9f 25 9e f9 51 75 d9 4f 05 41 0e 17 56 31 4e 3f |.%..Qu.O.A..V1N?|
+00000060 c0 15 d8 c4 29 4d e5 92 f9 ed 50 b6 88 f1 41 ea |....)M....P...A.|
+00000070 cb 5a 8c 50 12 78 16 e7 21 b6 11 ca 2c 49 cf b6 |.Z.P.x..!...,I..|
+00000080 d2 1a 16 28 f7 08 b5 c9 61 e0 18 14 03 02 00 01 |...(....a.......|
+00000090 01 16 03 02 00 24 a1 cf 1b 5d dc 4c 9c 2c d7 39 |.....$...].L.,.9|
+000000a0 af 13 e9 04 48 c0 2a aa 6f 3a 9c fb 9e 0a 25 55 |....H.*.o:....%U|
+000000b0 7e 82 3d 1b 78 d1 e3 e0 f5 30 |~.=.x....0|
>>> Flow 4 (server to client)
-00000000 14 03 02 00 01 01 16 03 02 00 24 8f 06 3e 7b 8c |..........$..>{.|
-00000010 fb f2 3d 9e 5c a9 46 56 79 2a 3a ba ad 25 30 57 |..=.\.FVy*:..%0W|
-00000020 f9 f1 16 70 51 5d 73 7e 47 74 8d c0 84 b0 31 17 |...pQ]s~Gt....1.|
-00000030 03 02 00 21 76 09 88 df 7e f7 2f c9 3d 86 b9 30 |...!v...~./.=..0|
-00000040 b0 5c ac ea db c6 d0 d5 69 55 91 7b a1 72 0b 4d |.\......iU.{.r.M|
-00000050 7d ae 6f aa 50 15 03 02 00 16 8c 31 73 86 1a c7 |}.o.P......1s...|
-00000060 ef 08 52 8a 7d 30 b8 00 3b 62 4d 21 7b 81 2c 76 |..R.}0..;bM!{.,v|
+00000000 14 03 02 00 01 01 16 03 02 00 24 7b 68 71 56 0f |..........${hqV.|
+00000010 a5 46 1c 13 34 81 b5 b6 ba 29 fb 41 46 dc fe 78 |.F..4....).AF..x|
+00000020 cc 0b 2d 75 bd fe c1 55 45 b1 fc 04 28 5e b1 17 |..-u...UE...(^..|
+00000030 03 02 00 21 0b fa a9 2f 9e 82 5b 77 30 c2 27 88 |...!.../..[w0.'.|
+00000040 f5 f3 50 47 7b 62 4c 7a d4 07 71 74 46 da 24 de |..PG{bLz..qtF.$.|
+00000050 bf 3f 56 a7 9b 15 03 02 00 16 85 26 8a 89 33 21 |.?V........&..3!|
+00000060 36 ce 69 83 84 50 fc 8f 99 b3 43 ad 6b 14 1e b2 |6.i..P....C.k...|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN
index df832d7dea7..3e90ebd90f8 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN
@@ -1,109 +1,94 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 01 4d 01 00 01 49 03 03 ac 76 61 d8 20 |....M...I...va. |
-00000010 b3 c3 1d c2 3d c2 a4 b9 e2 46 a2 a1 0a 5e 08 56 |....=....F...^.V|
-00000020 4a aa 59 43 42 d6 21 9c 46 0c 21 00 00 b6 c0 30 |J.YCB.!.F.!....0|
-00000030 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 |.,.(.$..........|
-00000040 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 |...k.j.i.h.9.8.7|
-00000050 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a |.6.........2...*|
-00000060 c0 26 c0 0f c0 05 00 9d 00 3d 00 35 00 84 c0 2f |.&.......=.5.../|
-00000070 c0 2b c0 27 c0 23 c0 13 c0 09 00 a4 00 a2 00 a0 |.+.'.#..........|
-00000080 00 9e 00 67 00 40 00 3f 00 3e 00 33 00 32 00 31 |...g.@.?.>.3.2.1|
-00000090 00 30 00 9a 00 99 00 98 00 97 00 45 00 44 00 43 |.0.........E.D.C|
-000000a0 00 42 c0 31 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c |.B.1.-.).%......|
-000000b0 00 3c 00 2f 00 96 00 41 00 07 c0 11 c0 07 c0 0c |.<./...A........|
-000000c0 c0 02 00 05 00 04 c0 12 c0 08 00 16 00 13 00 10 |................|
-000000d0 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f 00 0c |................|
-000000e0 00 09 00 ff 02 01 00 00 69 00 0b 00 04 03 00 01 |........i.......|
-000000f0 02 00 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 |................|
-00000100 18 00 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 |................|
-00000110 0a 00 23 00 00 00 0d 00 20 00 1e 06 01 06 02 06 |..#..... .......|
-00000120 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 |................|
-00000130 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 00 10 |................|
-00000140 00 10 00 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 |.....proto2.prot|
-00000150 6f 31 |o1|
+00000000 16 03 01 00 bf 01 00 00 bb 03 03 18 c9 32 10 f3 |.............2..|
+00000010 be ff a8 60 c5 2a 03 cb 25 8a b3 54 8d 70 27 90 |...`.*..%..T.p'.|
+00000020 74 1e 15 3e 61 48 9b be f0 77 1f 00 00 38 c0 2c |t..>aH...w...8.,|
+00000030 c0 30 00 9f cc a9 cc a8 cc aa c0 2b c0 2f 00 9e |.0.........+./..|
+00000040 c0 24 c0 28 00 6b c0 23 c0 27 00 67 c0 0a c0 14 |.$.(.k.#.'.g....|
+00000050 00 39 c0 09 c0 13 00 33 00 9d 00 9c 00 3d 00 3c |.9.....3.....=.<|
+00000060 00 35 00 2f 00 ff 01 00 00 5a 00 0b 00 04 03 00 |.5./.....Z......|
+00000070 01 02 00 0a 00 0a 00 08 00 1d 00 17 00 19 00 18 |................|
+00000080 00 23 00 00 00 0d 00 20 00 1e 06 01 06 02 06 03 |.#..... ........|
+00000090 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 |................|
+000000a0 03 03 02 01 02 02 02 03 00 10 00 10 00 0e 06 70 |...............p|
+000000b0 72 6f 74 6f 32 06 70 72 6f 74 6f 31 00 16 00 00 |roto2.proto1....|
+000000c0 00 17 00 00 |....|
>>> 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 30 00 00 |.............0..|
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 71 0b 00 02 6d |.proto1....q...m|
-00000050 00 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 |..j..g0..c0.....|
-00000060 02 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d |.......s......0.|
-00000070 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 |..*.H........0+1|
-00000080 17 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 |.0...U....Google|
-00000090 20 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 | TESTING1.0...U.|
-000000a0 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 |...Go Root0...15|
-000000b0 30 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 |0101000000Z..250|
-000000c0 31 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 |101000000Z0&1.0.|
-000000d0 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 |..U....Google TE|
-000000e0 53 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 |STING1.0...U....|
-000000f0 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 |Go0..0...*.H....|
-00000100 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af |........0.......|
-00000110 87 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 |... ..el..D..;E.|
-00000120 e3 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a |..m..cM...jb5..J|
-00000130 f9 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 |..|..%^zd1f.....|
-00000140 af c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 |..k.v.._A.nV....|
-00000150 c1 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da |.<.9!f=+........|
-00000160 b7 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 |.......!P.....k.|
-00000170 4b 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 |K......l..D..!..|
-00000180 7d 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 |}..M........G...|
-00000190 03 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d |.......0..0...U.|
-000001a0 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d |..........0...U.|
-000001b0 25 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 |%..0...+........|
-000001c0 08 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 |.+.......0...U..|
-000001d0 01 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 |.....0.0...U....|
-000001e0 04 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e |...P..o...TMn.i^|
-000001f0 06 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf |..0...U.#..0....|
-00000200 3d b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 |=..f..@....xH.A0|
-00000210 19 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d |...U....0...exam|
-00000220 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 |ple.golang0...*.|
-00000230 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af |H.............|.|
-00000240 91 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 |.U...Y1.H@.-....|
-00000250 a0 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 |....|..0}<.v.O=.|
-00000260 fa ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc |..-3$k.{.gY.!...|
-00000270 77 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 |w...n.-.5.d_">c.|
-00000280 6b be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 |k....m...1..8.;.|
-00000290 87 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 |.,...Qv..O......|
-000002a0 40 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 |@.Q......F.F.O..|
-000002b0 f9 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 |...A4......9....|
-000002c0 00 cd 0c 00 00 c9 03 00 17 41 04 1e 18 37 ef 0d |.........A...7..|
-000002d0 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd |.Q.5uq..T[....g.|
-000002e0 a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e |.$ >.V...(^.+-O.|
-000002f0 f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 |...lK[.V.2B.X..I|
-00000300 a6 b5 68 1a 41 03 56 6b dc 5a 89 05 01 00 80 aa |..h.A.Vk.Z......|
-00000310 8c a6 e1 51 65 fc 99 37 cf 63 d8 fd 04 52 d5 50 |...Qe..7.c...R.P|
-00000320 1f 0a f5 90 58 48 19 8d d8 0b 64 23 e4 24 56 b4 |....XH....d#.$V.|
-00000330 e5 87 0f 88 a1 7a 29 fa 88 79 99 75 6d 53 a9 50 |.....z)..y.umS.P|
-00000340 a4 9c b9 47 c2 51 87 10 b9 a5 e3 6f a9 38 b8 83 |...G.Q.....o.8..|
-00000350 0d 39 b5 28 27 5f ec 9d a3 2d 1c 53 6b da 93 0d |.9.('_...-.Sk...|
-00000360 cc cf 0c 27 7e d2 f0 05 d5 c0 04 dc 6d d4 2e 03 |...'~.......m...|
-00000370 a7 16 98 58 e4 8d fd 14 6b bb 0c 09 b0 16 35 9e |...X....k.....5.|
-00000380 78 3a 29 21 b5 2f 13 37 94 ae f7 fe 54 89 c0 16 |x:)!./.7....T...|
-00000390 03 03 00 04 0e 00 00 00 |........|
+00000040 06 70 72 6f 74 6f 31 16 03 03 02 59 0b 00 02 55 |.proto1....Y...U|
+00000050 00 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 |..R..O0..K0.....|
+00000060 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d |.........?.[..0.|
+00000070 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 |..*.H........0.1|
+00000080 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e |.0...U....Go1.0.|
+00000090 06 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e |..U....Go Root0.|
+000000a0 17 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 |..160101000000Z.|
+000000b0 0d 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a |.250101000000Z0.|
+000000c0 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 |1.0...U....Go1.0|
+000000d0 09 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 |...U....Go0..0..|
+000000e0 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 |.*.H............|
+000000f0 30 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 |0.......F}...'.H|
+00000100 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a |..(!.~...]..RE.z|
+00000110 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 |6G....B[.....y.@|
+00000120 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e |.Om..+.....g....|
+00000130 d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 |."8.J.ts+.4.....|
+00000140 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b |.t{.X.la<..A..++|
+00000150 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 |$#w[.;.u]. T..c.|
+00000160 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 |..$....P....C...|
+00000170 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 |ub...R.........0|
+00000180 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 |..0...U.........|
+00000190 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b |..0...U.%..0...+|
+000001a0 06 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 |.........+......|
+000001b0 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 |.0...U.......0.0|
+000001c0 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 |...U..........CC|
+000001d0 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d |>I..m....`0...U.|
+000001e0 23 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb |#..0...H.IM.~.1.|
+000001f0 a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 |.....n{0...U....|
+00000200 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 |0...example.gola|
+00000210 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 |ng0...*.H.......|
+00000220 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba |......0.@+[P.a..|
+00000230 e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac |.SX...(.X..8....|
+00000240 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 |1Z..f=C.-...... |
+00000250 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa |d8.$:....}.@ ._.|
+00000260 d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 |..a..v......\...|
+00000270 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 |..l..s..Cw......|
+00000280 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 |.@.a.Lr+...F..M.|
+00000290 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 |..>...B...=.`.\!|
+000002a0 d3 3b e9 fa e7 16 03 03 00 ac 0c 00 00 a8 03 00 |.;..............|
+000002b0 1d 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f bb |. /.}.G.bC.(.._.|
+000002c0 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb |).0.........._X.|
+000002d0 3b 74 05 01 00 80 2e c1 51 a1 e8 92 a6 bb ad 1e |;t......Q.......|
+000002e0 4d f1 22 c5 e7 10 e6 31 1d 78 61 8a 22 a3 93 84 |M."....1.xa."...|
+000002f0 58 d6 5a c6 94 d0 da 6c 6a 35 d1 31 ea 1b 7e 55 |X.Z....lj5.1..~U|
+00000300 d6 35 a3 b7 42 e4 04 f8 31 15 15 88 5f 91 a8 7e |.5..B...1..._..~|
+00000310 3e 73 52 8f 32 50 2e ad 95 44 83 b6 88 d6 18 99 |>sR.2P...D......|
+00000320 cf 86 57 97 c0 b2 a0 91 ee a7 ac f8 38 4b 1c 8e |..W.........8K..|
+00000330 a4 58 59 4a f6 fc 88 a4 02 ed c8 04 1a 8b 7b 9e |.XYJ..........{.|
+00000340 83 91 72 ca 1e 1c e0 76 58 73 89 3a 7d 12 c5 ef |..r....vXs.:}...|
+00000350 f8 f7 45 dc ca c4 16 03 03 00 04 0e 00 00 00 |..E............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 35 ca 56 91 15 |....F...BA.5.V..|
-00000010 4f dd af 97 f2 2d fb df 54 2b 80 98 18 bb 33 54 |O....-..T+....3T|
-00000020 3f 7e 66 21 d3 81 38 f9 a4 b5 b9 a6 46 9a 52 8b |?~f!..8.....F.R.|
-00000030 98 f7 81 1f 77 81 78 38 01 c5 3b fb 7a b7 53 e7 |....w.x8..;.z.S.|
-00000040 ae c3 4c 2e 73 f4 8e 3a 36 0d 43 14 03 03 00 01 |..L.s..:6.C.....|
-00000050 01 16 03 03 00 28 38 26 8e 03 ad 81 9b a0 41 d9 |.....(8&......A.|
-00000060 c0 11 3f 36 dc 6b ab 6c 29 dc df 02 a3 fe b0 0f |..?6.k.l).......|
-00000070 2e b1 c6 44 39 42 d5 ef 29 30 d8 e0 f1 f9 |...D9B..)0....|
+00000000 16 03 03 00 25 10 00 00 21 20 be 4e 0d d5 31 aa |....%...! .N..1.|
+00000010 27 13 df 73 d3 8d 17 8c b3 5f 44 61 7b 01 b6 99 |'..s....._Da{...|
+00000020 7b ba b3 5d bf d4 be 3c 87 26 14 03 03 00 01 01 |{..]...<.&......|
+00000030 16 03 03 00 28 9c 86 e0 30 d4 a5 ec 0c 9e a6 08 |....(...0.......|
+00000040 ce 8a 7a ff ef be 52 0c 56 86 62 de 49 09 a1 18 |..z...R.V.b.I...|
+00000050 aa 62 e5 e3 d3 2e 4a 24 c9 ef 44 c9 67 |.b....J$..D.g|
>>> Flow 4 (server to client)
00000000 16 03 03 00 82 04 00 00 7e 00 00 00 00 00 78 50 |........~.....xP|
00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................|
-00000030 6f ec 80 83 61 fb fb 41 b1 31 e9 71 75 43 c3 74 |o...a..A.1.quC.t|
-00000040 a1 a0 ac fb 97 b7 69 ee a6 2f e3 a3 dd 9f de e4 |......i../......|
-00000050 80 9d d7 69 1a 2c 0b b4 02 bd ef e2 6a c1 ca 30 |...i.,......j..0|
-00000060 8b 9d 60 f9 fe 33 94 53 3a 14 a3 1a aa 5a ba ff |..`..3.S:....Z..|
-00000070 1e 94 fd 4f e7 90 0b 09 ee 80 f3 d6 d5 c0 48 83 |...O..........H.|
-00000080 98 20 d7 a4 07 99 e0 14 03 03 00 01 01 16 03 03 |. ..............|
-00000090 00 28 00 00 00 00 00 00 00 00 0d 66 de 91 4a 97 |.(.........f..J.|
-000000a0 21 c6 d2 d7 df 68 9b 7e f6 43 73 02 66 b3 5a d6 |!....h.~.Cs.f.Z.|
-000000b0 92 48 c2 c1 11 fc cd 1e 2e 4b 17 03 03 00 25 00 |.H.......K....%.|
-000000c0 00 00 00 00 00 00 01 72 0c 48 75 fa b2 8b 23 09 |.......r.Hu...#.|
-000000d0 be 76 36 a4 bc e0 62 ef bd 79 8e de 6b 39 4b 55 |.v6...b..y..k9KU|
-000000e0 8d 3c ca 14 15 03 03 00 1a 00 00 00 00 00 00 00 |.<..............|
-000000f0 02 74 5f 79 31 41 4f f5 4d 02 96 bc c3 9a 85 92 |.t_y1AO.M.......|
-00000100 44 e1 76 |D.v|
+00000030 6f ec 80 83 61 da 3d a1 df 0d 11 25 4b 66 55 09 |o...a.=....%KfU.|
+00000040 af 7a c1 82 b9 ea 2f 9f 5c f4 0a 62 15 62 c2 32 |.z..../.\..b.b.2|
+00000050 c6 37 51 5b bb 19 14 f8 73 f8 fb 82 00 ef 19 21 |.7Q[....s......!|
+00000060 e2 52 7d ab 0a 33 94 df 78 54 ba 6c 5e 94 eb 16 |.R}..3..xT.l^...|
+00000070 ad 85 01 ca d5 98 8f 8e b7 04 7e 9a 3c 35 c0 e5 |..........~.<5..|
+00000080 8f cf 27 6d b4 12 c2 14 03 03 00 01 01 16 03 03 |..'m............|
+00000090 00 28 00 00 00 00 00 00 00 00 75 da b5 10 2e 7c |.(........u....||
+000000a0 39 ec 3d 98 12 fb 5d 15 81 79 f3 c7 b1 e4 e0 54 |9.=...]..y.....T|
+000000b0 ed 27 6e bc c3 81 a0 74 7e 38 17 03 03 00 25 00 |.'n....t~8....%.|
+000000c0 00 00 00 00 00 00 01 bf 81 cc 93 49 4f b2 59 8b |...........IO.Y.|
+000000d0 53 4a 61 96 04 00 4b ac 34 d5 bd 5a 94 44 18 5b |SJa...K.4..Z.D.[|
+000000e0 7d 81 dc 05 15 03 03 00 1a 00 00 00 00 00 00 00 |}...............|
+000000f0 02 bd 32 d5 cf 4d 13 61 6a 77 8b 3e 51 b3 13 84 |..2..M.ajw.>Q...|
+00000100 e6 1a 23 |..#|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch
index 35bfdc10620..d40300e8395 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch
@@ -1,108 +1,94 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 01 4d 01 00 01 49 03 03 73 f2 f2 44 4f |....M...I..s..DO|
-00000010 87 05 77 e2 e7 07 ca c7 d4 36 37 4e d9 17 ba ff |..w......67N....|
-00000020 b0 e1 47 65 f8 7f fd 7a b4 85 39 00 00 b6 c0 30 |..Ge...z..9....0|
-00000030 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 |.,.(.$..........|
-00000040 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 |...k.j.i.h.9.8.7|
-00000050 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a |.6.........2...*|
-00000060 c0 26 c0 0f c0 05 00 9d 00 3d 00 35 00 84 c0 2f |.&.......=.5.../|
-00000070 c0 2b c0 27 c0 23 c0 13 c0 09 00 a4 00 a2 00 a0 |.+.'.#..........|
-00000080 00 9e 00 67 00 40 00 3f 00 3e 00 33 00 32 00 31 |...g.@.?.>.3.2.1|
-00000090 00 30 00 9a 00 99 00 98 00 97 00 45 00 44 00 43 |.0.........E.D.C|
-000000a0 00 42 c0 31 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c |.B.1.-.).%......|
-000000b0 00 3c 00 2f 00 96 00 41 00 07 c0 11 c0 07 c0 0c |.<./...A........|
-000000c0 c0 02 00 05 00 04 c0 12 c0 08 00 16 00 13 00 10 |................|
-000000d0 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f 00 0c |................|
-000000e0 00 09 00 ff 02 01 00 00 69 00 0b 00 04 03 00 01 |........i.......|
-000000f0 02 00 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 |................|
-00000100 18 00 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 |................|
-00000110 0a 00 23 00 00 00 0d 00 20 00 1e 06 01 06 02 06 |..#..... .......|
-00000120 03 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 |................|
-00000130 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 00 10 |................|
-00000140 00 10 00 0e 06 70 72 6f 74 6f 32 06 70 72 6f 74 |.....proto2.prot|
-00000150 6f 31 |o1|
+00000000 16 03 01 00 bf 01 00 00 bb 03 03 82 57 14 fc ab |............W...|
+00000010 56 21 ff 72 39 72 3f fe f1 9b 0f 22 00 ff ef 44 |V!.r9r?...."...D|
+00000020 da db e0 83 d2 c0 a7 1c fb f0 6c 00 00 38 c0 2c |..........l..8.,|
+00000030 c0 30 00 9f cc a9 cc a8 cc aa c0 2b c0 2f 00 9e |.0.........+./..|
+00000040 c0 24 c0 28 00 6b c0 23 c0 27 00 67 c0 0a c0 14 |.$.(.k.#.'.g....|
+00000050 00 39 c0 09 c0 13 00 33 00 9d 00 9c 00 3d 00 3c |.9.....3.....=.<|
+00000060 00 35 00 2f 00 ff 01 00 00 5a 00 0b 00 04 03 00 |.5./.....Z......|
+00000070 01 02 00 0a 00 0a 00 08 00 1d 00 17 00 19 00 18 |................|
+00000080 00 23 00 00 00 0d 00 20 00 1e 06 01 06 02 06 03 |.#..... ........|
+00000090 05 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 |................|
+000000a0 03 03 02 01 02 02 02 03 00 10 00 10 00 0e 06 70 |...............p|
+000000b0 72 6f 74 6f 32 06 70 72 6f 74 6f 31 00 16 00 00 |roto2.proto1....|
+000000c0 00 17 00 00 |....|
>>> Flow 2 (server to client)
00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 c0 30 00 00 |.............0..|
-00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 71 0b |..#...........q.|
-00000040 00 02 6d 00 02 6a 00 02 67 30 82 02 63 30 82 01 |..m..j..g0..c0..|
-00000050 cc a0 03 02 01 02 02 09 00 a2 73 00 0c 81 00 cb |..........s.....|
-00000060 f3 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........|
-00000070 30 2b 31 17 30 15 06 03 55 04 0a 13 0e 47 6f 6f |0+1.0...U....Goo|
-00000080 67 6c 65 20 54 45 53 54 49 4e 47 31 10 30 0e 06 |gle TESTING1.0..|
-00000090 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
-000000a0 0d 31 35 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.150101000000Z..|
-000000b0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 26 31 |250101000000Z0&1|
-000000c0 17 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 |.0...U....Google|
-000000d0 20 54 45 53 54 49 4e 47 31 0b 30 09 06 03 55 04 | TESTING1.0...U.|
-000000e0 03 13 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |...Go0..0...*.H.|
-000000f0 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....|
-00000100 81 00 af 87 88 f6 20 1b 95 65 6c 14 ab 44 05 af |...... ..el..D..|
-00000110 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 |;E...m..cM...jb5|
-00000120 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 31 66 00 ba |..J..|..%^zd1f..|
-00000130 f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 |.....k.v.._A.nV.|
-00000140 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 d1 bc db 1c |....<.9!f=+.....|
-00000150 c0 a7 da b7 ca ad ba da cb d5 21 50 ec de 8d ab |..........!P....|
-00000160 d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 b1 44 84 bd |.k.K......l..D..|
-00000170 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef fa d6 09 47 |!..}..M........G|
-00000180 f2 fb 02 03 01 00 01 a3 81 93 30 81 90 30 0e 06 |..........0..0..|
-00000190 03 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 |.U...........0..|
-000001a0 03 55 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 |.U.%..0...+.....|
-000001b0 03 01 06 08 2b 06 01 05 05 07 03 02 30 0c 06 03 |....+.......0...|
-000001c0 55 1d 13 01 01 ff 04 02 30 00 30 19 06 03 55 1d |U.......0.0...U.|
-000001d0 0e 04 12 04 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e |......P..o...TMn|
-000001e0 cb 69 5e 06 f4 30 1b 06 03 55 1d 23 04 14 30 12 |.i^..0...U.#..0.|
-000001f0 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea b4 03 78 48 |...=..f..@....xH|
-00000200 1a 41 30 19 06 03 55 1d 11 04 12 30 10 82 0e 65 |.A0...U....0...e|
-00000210 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 |xample.golang0..|
-00000220 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 |.*.H............|
-00000230 92 7c af 91 55 12 18 96 59 31 a6 48 40 d5 2d d5 |.|..U...Y1.H@.-.|
-00000240 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da |.......|..0}<.v.|
-00000250 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b 67 59 11 21 |O=...-3$k.{.gY.!|
-00000260 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 |...w...n.-.5.d_"|
-00000270 3e 63 10 6b be ff 14 86 6d 0d f0 15 31 a8 14 38 |>c.k....m...1..8|
-00000280 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 4f dd db 9b |.;..,...Qv..O...|
-00000290 84 04 86 40 fa 51 dd ba b4 8d eb e3 46 de 46 b9 |...@.Q......F.F.|
-000002a0 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 |O.....A4......9.|
-000002b0 16 03 03 00 cd 0c 00 00 c9 03 00 17 41 04 1e 18 |............A...|
-000002c0 37 ef 0d 19 51 88 35 75 71 b5 e5 54 5b 12 2e 8f |7...Q.5uq..T[...|
-000002d0 09 67 fd a7 24 20 3e b2 56 1c ce 97 28 5e f8 2b |.g..$ >.V...(^.+|
-000002e0 2d 4f 9e f1 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 |-O....lK[.V.2B.X|
-000002f0 b6 d7 49 a6 b5 68 1a 41 03 56 6b dc 5a 89 05 01 |..I..h.A.Vk.Z...|
-00000300 00 80 97 89 a3 7f 30 d1 7b 70 26 3d a4 d5 66 2e |......0.{p&=..f.|
-00000310 cd fc 02 f5 37 a5 cd 09 69 7a c6 2f b2 62 e8 a6 |....7...iz./.b..|
-00000320 88 e2 3a c4 0a 8c 77 ad d3 c9 29 49 84 81 9c cd |..:...w...)I....|
-00000330 33 44 59 2d b5 2e e7 ce 12 c5 3b 46 13 6d 4a c8 |3DY-......;F.mJ.|
-00000340 6d f6 1f e7 f1 99 13 01 ca 43 79 fa b5 78 c7 1a |m........Cy..x..|
-00000350 7d 8f 85 dd 3b ca 56 22 c3 d0 41 11 1b 13 8c 07 |}...;.V"..A.....|
-00000360 02 75 87 7a ea 68 43 30 0b 2a 38 52 b2 8f cc ea |.u.z.hC0.*8R....|
-00000370 a3 a3 cb 71 fb 97 cd 3e 74 d0 5b 9b bd 17 13 f0 |...q...>t.[.....|
-00000380 d9 fe 16 03 03 00 04 0e 00 00 00 |...........|
+00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 59 0b |..#...........Y.|
+00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..|
+00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.|
+00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........|
+00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1|
+00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
+00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000|
+000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
+000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go|
+000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..|
+000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........|
+000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...|
+000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R|
+00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....|
+00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.|
+00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..|
+00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.|
+00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.|
+00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C|
+00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......|
+00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......|
+00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.|
+00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...|
+000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......|
+000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........|
+000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..|
+000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~|
+000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.|
+000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g|
+00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....|
+00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.|
+00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.|
+00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....|
+00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ |
+00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\|
+00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...|
+00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.|
+00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`|
+00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c 00 00 |.\!.;...........|
+000002a0 a8 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 28 da |.... /.}.G.bC.(.|
+000002b0 ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 |._.).0..........|
+000002c0 5f 58 cb 3b 74 05 01 00 80 bf 6d 57 f5 0c 78 c4 |_X.;t.....mW..x.|
+000002d0 77 48 0e 60 67 7a 3a 1b 3e 9e d2 88 a4 89 07 ef |wH.`gz:.>.......|
+000002e0 d1 45 1a 66 7e 8c ec cb da 71 ea ec ba ed 81 9e |.E.f~....q......|
+000002f0 21 4d 2e ba d4 8f c2 0a 67 ea 3a a1 d1 67 09 66 |!M......g.:..g.f|
+00000300 dc a8 ad 16 a2 23 2a db 4f 31 65 b1 54 13 73 d1 |.....#*.O1e.T.s.|
+00000310 f6 7b 75 d9 f1 07 19 b8 67 21 87 d2 3b cf a5 6c |.{u.....g!..;..l|
+00000320 61 8e af ed 60 7f f2 56 9f 0d 0f 19 88 98 30 3a |a...`..V......0:|
+00000330 61 8c 21 e7 8b 5d ab 6f cf 93 73 33 63 cd 50 bb |a.!..].o..s3c.P.|
+00000340 dd 0e ab 4f 6a fb a3 f9 68 16 03 03 00 04 0e 00 |...Oj...h.......|
+00000350 00 00 |..|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 ba 5b 0f e7 ec |....F...BA..[...|
-00000010 8e c8 ad 51 8c c0 50 f1 8a 2a 68 32 74 d0 95 03 |...Q..P..*h2t...|
-00000020 0c 61 f1 1c 89 ed 95 5d 9a 4a 14 ee cc 14 9a 73 |.a.....].J.....s|
-00000030 f6 db 46 dd b7 47 8a 82 3d 7a b8 9f 45 d1 a2 3f |..F..G..=z..E..?|
-00000040 f4 34 9b b6 6d 7d 41 87 c9 d5 cd 14 03 03 00 01 |.4..m}A.........|
-00000050 01 16 03 03 00 28 1e ae f6 90 a9 91 eb 4b ca 23 |.....(.......K.#|
-00000060 6e bf 9e 67 5b 38 ab f6 d6 ee 12 aa b9 b6 d0 6e |n..g[8.........n|
-00000070 a7 dd 45 91 34 45 78 a0 04 9e d8 85 48 48 |..E.4Ex.....HH|
+00000000 16 03 03 00 25 10 00 00 21 20 05 0c 3b 8b 22 36 |....%...! ..;."6|
+00000010 61 79 58 28 b0 82 65 44 39 67 93 c5 2c 3b d1 40 |ayX(..eD9g..,;.@|
+00000020 88 af 9f 38 c1 fa e0 81 a0 19 14 03 03 00 01 01 |...8............|
+00000030 16 03 03 00 28 87 2e d2 c2 ce 65 6d e8 d9 da a0 |....(.....em....|
+00000040 9d dc f5 51 b0 84 88 8d c6 a3 0a 5d 08 10 ca c6 |...Q.......]....|
+00000050 e3 83 0c 0a cb 6d ec 09 b8 9f a5 45 99 |.....m.....E.|
>>> Flow 4 (server to client)
00000000 16 03 03 00 82 04 00 00 7e 00 00 00 00 00 78 50 |........~.....xP|
00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................|
-00000030 6f ec 80 83 61 4f 7f 09 64 32 96 26 b5 71 46 6a |o...aO..d2.&.qFj|
-00000040 29 7d fd 0b bb 49 13 0e c8 c5 de 06 ed 47 e8 cb |)}...I.......G..|
-00000050 d8 9f 18 82 69 af ab 24 d2 78 90 ba 9a c8 24 95 |....i..$.x....$.|
-00000060 46 53 19 2e e8 33 94 3c 22 73 26 d6 86 4e 01 a4 |FS...3.<"s&..N..|
-00000070 34 ea a8 bf f2 ca b5 0d fc f6 08 b9 31 b3 42 e7 |4...........1.B.|
-00000080 c1 92 96 f9 bf 9a 00 14 03 03 00 01 01 16 03 03 |................|
-00000090 00 28 00 00 00 00 00 00 00 00 bd 51 1d 0e bd 51 |.(.........Q...Q|
-000000a0 a3 b1 03 f2 df f4 ba 9b 1e a5 a8 22 e7 ce 7c 19 |..........."..|.|
-000000b0 1a bf 37 3d 42 f4 4d 6f 63 75 17 03 03 00 25 00 |..7=B.Mocu....%.|
-000000c0 00 00 00 00 00 00 01 52 8a d2 34 52 70 f1 cf 87 |.......R..4Rp...|
-000000d0 54 4e fd e6 11 a7 76 1a f4 7b 70 e8 34 ef 01 c8 |TN....v..{p.4...|
-000000e0 6c 4a f8 6d 15 03 03 00 1a 00 00 00 00 00 00 00 |lJ.m............|
-000000f0 02 8a 4c f9 7c d1 61 a6 cd 2a e6 3a 5b b0 cb aa |..L.|.a..*.:[...|
-00000100 91 2e 8b |...|
+00000030 6f ec 80 83 61 34 53 e2 a4 e2 ff 73 4f 1b 15 8f |o...a4S....sO...|
+00000040 3b 43 47 ac 20 c6 2d 5e 52 7a 61 6f af 40 c3 5a |;CG. .-^Rzao.@.Z|
+00000050 cb 3f 7d 10 a9 90 ca cf 8d c4 c4 d4 a3 b8 1d 62 |.?}............b|
+00000060 7d a9 68 32 01 33 94 65 8b 67 73 aa 51 d4 08 1d |}.h2.3.e.gs.Q...|
+00000070 ce 76 6b ef 3d e6 ce d3 42 fe 24 cf f3 82 5b 17 |.vk.=...B.$...[.|
+00000080 5c 03 e9 50 94 8e 8b 14 03 03 00 01 01 16 03 03 |\..P............|
+00000090 00 28 00 00 00 00 00 00 00 00 c2 7c e6 69 c9 ec |.(.........|.i..|
+000000a0 b5 55 57 34 8e 86 38 e6 28 85 b0 c8 2e c8 0f a6 |.UW4..8.(.......|
+000000b0 a9 07 f4 91 47 46 dd fe c8 57 17 03 03 00 25 00 |....GF...W....%.|
+000000c0 00 00 00 00 00 00 01 39 9a a2 da d8 3d 7f 25 0e |.......9....=.%.|
+000000d0 83 a8 cd 57 d8 a4 7e 9f e1 e2 fe 3f 5a ed b9 99 |...W..~....?Z...|
+000000e0 b6 4d 97 3a 15 03 03 00 1a 00 00 00 00 00 00 00 |.M.:............|
+000000f0 02 d5 2a aa 1e 7a 60 b8 79 56 c6 56 75 11 b7 4c |..*..z`.yV.Vu..L|
+00000100 83 19 9c |...|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA b/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA
index ae3748f49bf..e2864070a4a 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA
@@ -1,24 +1,15 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 01 35 01 00 01 31 03 03 00 02 67 8e 1d |....5...1....g..|
-00000010 3b d2 26 20 63 c5 6a b6 68 25 02 72 ce 86 6b c7 |;.& c.j.h%.r..k.|
-00000020 97 1a 9f 4d be 02 98 ac 24 5e 82 00 00 b6 c0 30 |...M....$^.....0|
-00000030 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 |.,.(.$..........|
-00000040 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 |...k.j.i.h.9.8.7|
-00000050 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a |.6.........2...*|
-00000060 c0 26 c0 0f c0 05 00 9d 00 3d 00 35 00 84 c0 2f |.&.......=.5.../|
-00000070 c0 2b c0 27 c0 23 c0 13 c0 09 00 a4 00 a2 00 a0 |.+.'.#..........|
-00000080 00 9e 00 67 00 40 00 3f 00 3e 00 33 00 32 00 31 |...g.@.?.>.3.2.1|
-00000090 00 30 00 9a 00 99 00 98 00 97 00 45 00 44 00 43 |.0.........E.D.C|
-000000a0 00 42 c0 31 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c |.B.1.-.).%......|
-000000b0 00 3c 00 2f 00 96 00 41 00 07 c0 11 c0 07 c0 0c |.<./...A........|
-000000c0 c0 02 00 05 00 04 c0 12 c0 08 00 16 00 13 00 10 |................|
-000000d0 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f 00 0c |................|
-000000e0 00 09 00 ff 02 01 00 00 51 00 0b 00 04 03 00 01 |........Q.......|
-000000f0 02 00 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 |................|
-00000100 18 00 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 |................|
-00000110 0a 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 |.... ...........|
-00000120 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 02 |................|
-00000130 01 02 02 02 03 00 0f 00 01 01 |..........|
+00000000 16 03 01 00 a7 01 00 00 a3 03 03 27 01 f3 21 98 |...........'..!.|
+00000010 ff 55 7f 78 32 44 b7 9d 88 6b 82 43 26 52 00 74 |.U.x2D...k.C&R.t|
+00000020 fb 05 ca be 23 1f d0 18 1f 74 c2 00 00 38 c0 2c |....#....t...8.,|
+00000030 c0 30 00 9f cc a9 cc a8 cc aa c0 2b c0 2f 00 9e |.0.........+./..|
+00000040 c0 24 c0 28 00 6b c0 23 c0 27 00 67 c0 0a c0 14 |.$.(.k.#.'.g....|
+00000050 00 39 c0 09 c0 13 00 33 00 9d 00 9c 00 3d 00 3c |.9.....3.....=.<|
+00000060 00 35 00 2f 00 ff 01 00 00 42 00 0b 00 04 03 00 |.5./.....B......|
+00000070 01 02 00 0a 00 0a 00 08 00 1d 00 17 00 19 00 18 |................|
+00000080 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 |... ............|
+00000090 05 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 |................|
+000000a0 02 02 02 03 00 16 00 00 00 17 00 00 |............|
>>> 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 |................|
@@ -56,43 +47,39 @@
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 05 03 00 8b 30 81 88 02 42 |A.Vk.Z.....0...B|
-000002a0 01 bc 56 16 22 ad fd e7 ac ba c8 f5 3f c0 d7 f8 |..V.".......?...|
-000002b0 8c 64 e0 ba 09 30 c3 66 49 90 7e d2 68 86 07 72 |.d...0.fI.~.h..r|
-000002c0 20 87 a1 e1 36 92 a7 68 e2 c3 6e 34 93 a9 ca e8 | ...6..h..n4....|
-000002d0 68 3d 9e 42 c4 1e 8e 2d 95 05 ee a6 a4 2c 8d be |h=.B...-.....,..|
-000002e0 e3 88 02 42 01 16 18 77 b9 99 0e f8 46 90 46 07 |...B...w....F.F.|
-000002f0 f9 67 a9 26 68 d7 da c8 a1 d9 67 55 ec 37 11 2d |.g.&h.....gU.7.-|
-00000300 4b f3 52 f4 96 6a 0e 8a 6a 14 21 94 63 ea f9 70 |K.R..j..j.!.c..p|
-00000310 2d 57 05 8a 72 29 6e d2 60 a1 97 af 08 5b c3 cf |-W..r)n.`....[..|
-00000320 3a 82 a3 81 11 cf 16 03 03 00 04 0e 00 00 00 |:..............|
+00000240 7b 6a 0f 39 95 12 07 8f 2a 16 03 03 00 b7 0c 00 |{j.9....*.......|
+00000250 00 b3 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 28 |..... /.}.G.bC.(|
+00000260 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 |.._.).0.........|
+00000270 99 5f 58 cb 3b 74 05 03 00 8b 30 81 88 02 42 01 |._X.;t....0...B.|
+00000280 4f 30 aa d0 4d e5 61 db ba fc 95 15 52 ef 2a 41 |O0..M.a.....R.*A|
+00000290 b4 d6 59 ac 39 61 b6 38 08 1e 87 b3 ca 9b 49 d3 |..Y.9a.8......I.|
+000002a0 95 5a c5 29 84 cd 10 73 4a cc 09 df 1a b0 54 6d |.Z.)...sJ.....Tm|
+000002b0 b8 61 28 80 2e ec cf 95 9d 6f c3 d9 ed 80 53 63 |.a(......o....Sc|
+000002c0 d9 02 42 00 af 71 2f 91 80 ff a1 79 82 c7 d9 79 |..B..q/....y...y|
+000002d0 fa 12 a9 88 7b 93 47 be 6a dc 80 42 17 9d 85 7a |....{.G.j..B...z|
+000002e0 b8 1b fe 85 7f 5c 10 9c 9e 0e e1 71 a7 b0 12 02 |.....\.....q....|
+000002f0 e2 a4 79 c4 8d d8 02 09 01 9c 6f 7a 27 7c 1f f4 |..y.......oz'|..|
+00000300 38 46 59 46 94 16 03 03 00 04 0e 00 00 00 |8FYF..........|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 8c 80 0c da 24 |....F...BA.....$|
-00000010 d6 66 ff cc 1b 26 d5 3f 37 37 16 8f 16 ee 0d 5f |.f...&.?77....._|
-00000020 c3 0e 62 7c e4 52 2d 43 29 e9 6b da 49 bc 99 16 |..b|.R-C).k.I...|
-00000030 28 46 8e 43 20 7f 12 66 1c 94 1c 03 55 6f 05 53 |(F.C ..f....Uo.S|
-00000040 6f b7 dc 8b 70 9d 9d c5 1f da 5b 14 03 03 00 01 |o...p.....[.....|
-00000050 01 16 03 03 00 40 17 60 dd e5 b2 58 fd 74 10 38 |.....@.`...X.t.8|
-00000060 95 b1 73 7e 8f 7a 2b d0 f5 65 80 0c dc b1 ca 29 |..s~.z+..e.....)|
-00000070 06 25 e1 f9 c3 c0 7c 88 e4 ad d3 16 0a 8a dd 1f |.%....|.........|
-00000080 a7 86 86 0f ac c7 ea f5 0f 1f 2b 97 85 b3 81 f7 |..........+.....|
-00000090 5d 42 2f 3b 72 80 |]B/;r.|
+00000000 16 03 03 00 25 10 00 00 21 20 8c 80 e4 c7 bd d7 |....%...! ......|
+00000010 ea ea 42 f7 53 24 50 28 6a e9 f3 ff 4f 4a 28 22 |..B.S$P(j...OJ("|
+00000020 a2 95 09 fc f0 d9 3e fc cc 6e 14 03 03 00 01 01 |......>..n......|
+00000030 16 03 03 00 40 79 56 60 f5 45 e7 48 9e 97 1d 49 |....@yV`.E.H...I|
+00000040 de 59 dd b0 f0 0a d2 cc 10 f0 98 3c c2 d5 67 d6 |.Y.........<..g.|
+00000050 2c 18 2b 21 ae a3 2f ea 2d 0b ff fd e6 c2 73 25 |,.+!../.-.....s%|
+00000060 1c 01 3e 94 3a cc 1d 58 6b fb 7f 85 e4 50 ec 10 |..>.:..Xk....P..|
+00000070 b9 d7 71 cb be |..q..|
>>> 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 82 01 fd 38 ae |..............8.|
-00000020 a4 07 8f bd 72 0a a2 b5 c5 78 09 89 65 1b 6d 1e |....r....x..e.m.|
-00000030 56 52 9d 4f de 02 15 2d 93 d8 8f d7 1f bb 07 3b |VR.O...-.......;|
-00000040 e9 62 3c 19 3e 19 65 ac 10 aa e5 17 03 03 00 40 |.b<.>.e........@|
+00000010 00 00 00 00 00 00 00 00 00 00 00 83 5c 5c e3 c0 |............\\..|
+00000020 20 56 8c 92 4b 75 f0 30 bd 67 74 52 f1 af 9c 14 | V..Ku.0.gtR....|
+00000030 29 1e e4 b2 5b c0 2c e6 48 6f 94 42 7b 21 92 96 |)...[.,.Ho.B{!..|
+00000040 0a 83 ce 1c 91 36 95 8c 14 38 57 17 03 03 00 40 |.....6...8W....@|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000060 18 61 1d 26 f3 b9 34 20 00 6c 27 75 fc 35 f5 c2 |.a.&..4 .l'u.5..|
-00000070 6f 71 ca 9b 0d 70 30 46 57 7c 07 86 7d 52 a9 d6 |oq...p0FW|..}R..|
-00000080 ab fc 89 a5 48 79 ae 60 03 05 4b 17 b2 d9 6b 39 |....Hy.`..K...k9|
+00000060 73 a4 40 cf ad 86 cc 05 9e 47 5f 83 50 ae 68 d5 |s.@......G_.P.h.|
+00000070 d1 6a a9 8c ba 74 fe c0 cc 4a 1a e3 b0 14 0d 31 |.j...t...J.....1|
+00000080 9f 06 54 e3 95 3a 89 6d 34 54 0c e4 b4 34 38 21 |..T..:.m4T...48!|
00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-000000a0 00 00 00 00 00 8f 8d 88 88 c5 1e f5 bf 06 f2 45 |...............E|
-000000b0 e7 fe f0 24 c7 4c 92 5a 80 a7 89 c8 2b ac 49 d9 |...$.L.Z....+.I.|
-000000c0 39 00 ca 57 ec |9..W.|
+000000a0 00 00 00 00 00 e6 dd b2 11 ab a7 34 61 00 d4 09 |...........4a...|
+000000b0 bc ea c1 5f c4 e2 52 60 63 96 f0 fd 44 4e f9 0e |..._..R`c...DN..|
+000000c0 af 32 99 e4 12 |.2...|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA b/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA
index 144ef4288a3..1f9fbc1abb8 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA
@@ -1,104 +1,89 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 01 35 01 00 01 31 03 03 ed 84 e2 1a c1 |....5...1.......|
-00000010 d9 3f a5 ba 70 0b 5f 3f 3b 87 79 18 27 03 92 ee |.?..p._?;.y.'...|
-00000020 b1 9f c7 36 26 e3 0b 6d fc d5 ed 00 00 b6 c0 30 |...6&..m.......0|
-00000030 c0 2c c0 28 c0 24 c0 14 c0 0a 00 a5 00 a3 00 a1 |.,.(.$..........|
-00000040 00 9f 00 6b 00 6a 00 69 00 68 00 39 00 38 00 37 |...k.j.i.h.9.8.7|
-00000050 00 36 00 88 00 87 00 86 00 85 c0 32 c0 2e c0 2a |.6.........2...*|
-00000060 c0 26 c0 0f c0 05 00 9d 00 3d 00 35 00 84 c0 2f |.&.......=.5.../|
-00000070 c0 2b c0 27 c0 23 c0 13 c0 09 00 a4 00 a2 00 a0 |.+.'.#..........|
-00000080 00 9e 00 67 00 40 00 3f 00 3e 00 33 00 32 00 31 |...g.@.?.>.3.2.1|
-00000090 00 30 00 9a 00 99 00 98 00 97 00 45 00 44 00 43 |.0.........E.D.C|
-000000a0 00 42 c0 31 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c |.B.1.-.).%......|
-000000b0 00 3c 00 2f 00 96 00 41 00 07 c0 11 c0 07 c0 0c |.<./...A........|
-000000c0 c0 02 00 05 00 04 c0 12 c0 08 00 16 00 13 00 10 |................|
-000000d0 00 0d c0 0d c0 03 00 0a 00 15 00 12 00 0f 00 0c |................|
-000000e0 00 09 00 ff 02 01 00 00 51 00 0b 00 04 03 00 01 |........Q.......|
-000000f0 02 00 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 |................|
-00000100 18 00 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 |................|
-00000110 0a 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 |.... ...........|
-00000120 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 02 |................|
-00000130 01 02 02 02 03 00 0f 00 01 01 |..........|
+00000000 16 03 01 00 a7 01 00 00 a3 03 03 1d 39 c9 33 73 |............9.3s|
+00000010 c2 b9 71 d8 66 23 63 a7 5c 9e 50 b6 3e a5 f9 bb |..q.f#c.\.P.>...|
+00000020 34 1b 71 e1 09 4f ae d5 53 8a e8 00 00 38 c0 2c |4.q..O..S....8.,|
+00000030 c0 30 00 9f cc a9 cc a8 cc aa c0 2b c0 2f 00 9e |.0.........+./..|
+00000040 c0 24 c0 28 00 6b c0 23 c0 27 00 67 c0 0a c0 14 |.$.(.k.#.'.g....|
+00000050 00 39 c0 09 c0 13 00 33 00 9d 00 9c 00 3d 00 3c |.9.....3.....=.<|
+00000060 00 35 00 2f 00 ff 01 00 00 42 00 0b 00 04 03 00 |.5./.....B......|
+00000070 01 02 00 0a 00 0a 00 08 00 1d 00 17 00 19 00 18 |................|
+00000080 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 |... ............|
+00000090 05 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 |................|
+000000a0 02 02 02 03 00 16 00 00 00 17 00 00 |............|
>>> 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 14 00 00 |................|
-00000030 05 ff 01 00 01 00 16 03 03 02 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002b0 cd 0c 00 00 c9 03 00 17 41 04 1e 18 37 ef 0d 19 |........A...7...|
-000002c0 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..|
-000002d0 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..|
-000002e0 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.|
-000002f0 b5 68 1a 41 03 56 6b dc 5a 89 05 01 00 80 7c 5c |.h.A.Vk.Z.....|\|
-00000300 f6 68 cc 07 f0 bd ec 30 07 d0 70 1b c6 95 a4 14 |.h.....0..p.....|
-00000310 67 3a 83 a1 43 ff 0a c3 f0 b7 ee 59 f8 c7 09 65 |g:..C......Y...e|
-00000320 08 ac 18 34 d4 8f 46 c4 2c 91 7b 57 95 e0 54 03 |...4..F.,.{W..T.|
-00000330 d8 8e b6 53 61 74 77 8b a3 5f 23 f0 06 dc 3a 56 |...Satw.._#...:V|
-00000340 61 80 5e 31 d5 75 c3 05 9f d0 06 1f c5 32 ba 79 |a.^1.u.......2.y|
-00000350 fd 14 a9 54 5a 18 b4 2b 09 0e 19 ab 76 0b 12 5d |...TZ..+....v..]|
-00000360 52 27 ce b8 dd 4c f8 f2 d2 70 56 43 19 53 b3 13 |R'...L...pVC.S..|
-00000370 b9 b7 65 ce cd 50 ed 4a 9f 42 96 c7 3c b9 16 03 |..e..P.J.B..<...|
-00000380 03 00 04 0e 00 00 00 |.......|
+00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 ac 0c 00 00 a8 03 00 1d |;...............|
+000002a0 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 | /.}.G.bC.(.._.)|
+000002b0 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b |.0.........._X.;|
+000002c0 74 05 01 00 80 06 d4 bd e4 7b 10 77 89 d7 d4 d6 |t........{.w....|
+000002d0 4e f6 3e 46 49 db ee 5c 4e bc ee fe cb 8b a6 9b |N.>FI..\N.......|
+000002e0 5c f6 99 fb 31 96 60 a8 23 09 f6 31 65 53 f0 6e |\...1.`.#..1eS.n|
+000002f0 07 5c 32 f9 59 5d 8b c0 b4 74 c8 01 85 8a b7 19 |.\2.Y]...t......|
+00000300 ab 19 08 68 6a e8 2f 81 bd 04 9b 38 ab d9 27 66 |...hj./....8..'f|
+00000310 d7 a5 3f 75 9c 4f 81 5b 9e 69 10 20 2b f2 1d a2 |..?u.O.[.i. +...|
+00000320 8f fc 7f ba ee 5b 76 8b 19 3f 46 60 01 25 99 72 |.....[v..?F`.%.r|
+00000330 78 24 02 8e 28 d5 24 f1 2e 6b 70 53 75 ec e2 8d |x$..(.$..kpSu...|
+00000340 76 ab e0 8e e8 16 03 03 00 04 0e 00 00 00 |v.............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 36 1c 6c f5 0a |....F...BA.6.l..|
-00000010 7f 52 84 ac 5a 27 45 76 79 a6 89 f1 1d d9 30 30 |.R..Z'Evy.....00|
-00000020 b6 64 af c7 34 11 12 b3 b9 72 83 e6 78 bc 06 74 |.d..4....r..x..t|
-00000030 a7 a4 10 01 34 77 5c 05 88 82 0f a9 cf 8d e8 68 |....4w\........h|
-00000040 09 80 c7 79 b6 e9 5a 2a 5f 80 5e 14 03 03 00 01 |...y..Z*_.^.....|
-00000050 01 16 03 03 00 40 ef f9 3c 34 cd 26 70 c9 7b 60 |.....@..<4.&p.{`|
-00000060 a7 27 0a 2b 86 18 2f 10 ad 48 3f 2e 9e 88 13 d6 |.'.+../..H?.....|
-00000070 d8 c6 fd 35 99 be 09 e6 dd ae 02 06 ea df 60 62 |...5..........`b|
-00000080 e0 f8 67 ea 9d c8 8c 11 d8 5a e7 6a a6 b2 eb 62 |..g......Z.j...b|
-00000090 23 b2 d2 be 75 58 |#...uX|
+00000000 16 03 03 00 25 10 00 00 21 20 21 75 22 84 bc b7 |....%...! !u"...|
+00000010 82 b3 03 d2 42 ff b6 ce 76 26 88 bf 8f 72 fc dd |....B...v&...r..|
+00000020 63 9b f1 4c 22 6d 12 cc d3 57 14 03 03 00 01 01 |c..L"m...W......|
+00000030 16 03 03 00 40 20 2b 26 bd 60 1b 27 a1 32 cb ab |....@ +&.`.'.2..|
+00000040 30 83 9c 47 59 7d f5 bb d9 45 8a d9 3e 29 86 4d |0..GY}...E..>).M|
+00000050 54 86 48 38 25 d9 b9 af 36 7c 7a f0 ae f6 b6 4e |T.H8%...6|z....N|
+00000060 a1 76 93 91 26 f3 c9 49 b5 6d 49 cf 22 97 bf c7 |.v..&..I.mI."...|
+00000070 db 44 c8 7a e3 |.D.z.|
>>> 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 a6 52 02 4f 20 |............R.O |
-00000020 f6 d7 2d 2d 7c 65 4e 7b 43 33 32 50 9b c6 68 2c |..--|eN{C32P..h,|
-00000030 c0 6a 02 6f c6 bc 38 d8 06 c0 42 ba c1 41 ce 5c |.j.o..8...B..A.\|
-00000040 d0 a0 5f fc 8a 31 33 26 a2 79 9a 17 03 03 00 40 |.._..13&.y.....@|
+00000010 00 00 00 00 00 00 00 00 00 00 00 43 7c 61 f2 30 |...........C|a.0|
+00000020 c6 4a c2 76 da 7d 84 c6 ed 5d ee 2e 9c 33 e4 3b |.J.v.}...]...3.;|
+00000030 e3 a1 ea ee 44 02 4b f7 90 f6 0c 8b 45 d7 26 2e |....D.K.....E.&.|
+00000040 4a 37 43 1d 93 44 79 e6 5d c5 8c 17 03 03 00 40 |J7C..Dy.]......@|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000060 f2 42 8f e8 79 0d f3 c0 a0 b7 8a 5e de b8 52 c4 |.B..y......^..R.|
-00000070 b6 9d b2 10 00 e8 a3 19 27 12 ac 38 e7 d8 ec 89 |........'..8....|
-00000080 af 7d 68 15 03 e8 c4 c8 08 34 ad ad 15 7b 69 bb |.}h......4...{i.|
+00000060 b2 e4 62 17 e2 d4 d8 73 2b ea 77 39 78 51 1a 86 |..b....s+.w9xQ..|
+00000070 64 54 1f 36 9a cc a1 c0 d2 6d df b7 8a 2e 68 b0 |dT.6.....m....h.|
+00000080 79 9a 9f a1 15 b1 78 fa db 2e 5a 43 0d fe 45 71 |y.....x...ZC..Eq|
00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-000000a0 00 00 00 00 00 a0 a5 02 ff b1 77 9a 8f e0 fc ca |..........w.....|
-000000b0 86 ee ca 9c 7c 3b ca 61 33 7f f9 12 54 79 41 97 |....|;.a3...TyA.|
-000000c0 b0 7d bd 9b 93 |.}...|
+000000a0 00 00 00 00 00 04 8c d0 bf 15 9f b4 55 22 b8 8e |............U"..|
+000000b0 a5 a7 df ed bd b2 ab 88 71 38 bd b2 5d b4 5e 8e |........q8..].^.|
+000000c0 54 fc e4 63 5a |T..cZ|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven b/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven
index 626024cb2bc..7a950db0ac9 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven
@@ -1,57 +1,56 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5b 01 00 00 57 03 03 55 46 9e 3b 51 |....[...W..UF.;Q|
-00000010 e7 cd bf df bc fe 0d 5a 5a de a6 09 6c 72 cb ea |.......ZZ...lr..|
-00000020 ab f8 a6 fd 9a 5b be 77 7d 25 20 00 00 04 00 05 |.....[.w}% .....|
-00000030 00 ff 02 01 00 00 29 00 0d 00 20 00 1e 06 01 06 |......)... .....|
-00000040 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
-00000050 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |................|
+00000000 16 03 01 00 5d 01 00 00 59 03 03 8e 50 ff 02 c4 |....]...Y...P...|
+00000010 3b 5e dd ee 59 d1 3a e1 db f1 30 f4 bb a7 8a 8c |;^..Y.:...0.....|
+00000020 b2 d2 1a fd f8 a4 c9 e4 5f 41 e1 00 00 04 00 2f |........_A...../|
+00000030 00 ff 01 00 00 2c 00 0d 00 20 00 1e 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 00 16 00 00 00 17 |................|
+00000060 00 00 |..|
>>> 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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002b0 17 0d 00 00 13 02 01 40 00 0c 04 01 04 03 05 01 |.......@........|
-000002c0 05 03 02 01 02 03 00 00 16 03 03 00 04 0e 00 00 |................|
-000002d0 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 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 17 0d 00 00 13 02 01 40 |;..............@|
+000002a0 00 0c 04 01 04 03 05 01 05 03 02 01 02 03 00 00 |................|
+000002b0 16 03 03 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|
@@ -86,32 +85,40 @@
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 03 64 6f 74 1b 0e |...........dot..|
-00000220 df 6b a4 8e f8 ec b5 02 c2 d6 7a 9a f3 bf 3e 32 |.k........z...>2|
-00000230 ba 41 dd 61 33 8a 63 fb 71 e6 87 68 32 9c 41 d5 |.A.a3.c.q..h2.A.|
-00000240 59 ee 93 55 16 e9 0a 01 72 14 93 23 82 73 91 3a |Y..U....r..#.s.:|
-00000250 6d 3c e6 e0 a8 33 34 84 80 59 65 6b c1 6d 01 19 |m<...34..Yek.m..|
-00000260 cc d5 4f 1d f6 88 4f cc b5 c6 3c 9c 68 4a be 47 |..O...O...<.hJ.G|
-00000270 c2 67 61 a4 e3 c3 00 c0 9c d4 83 ed b5 65 25 a4 |.ga..........e%.|
-00000280 2e 1c 8d 47 3f 80 b8 1d 5b 74 a2 bf fa b9 b7 e2 |...G?...[t......|
-00000290 58 94 ba ec a9 cf 1c 56 ef 0a 16 03 03 00 92 0f |X......V........|
-000002a0 00 00 8e 04 03 00 8a 30 81 87 02 41 75 cf 19 3a |.......0...Au..:|
-000002b0 a1 9e e9 69 c7 f3 63 0b 46 c2 60 35 e1 cc 95 0d |...i..c.F.`5....|
-000002c0 ee 0f ad 28 17 b4 b2 09 ea 38 18 c7 08 84 b6 ac |...(.....8......|
-000002d0 65 03 b9 49 c3 ea ff e4 45 d3 15 14 3a 94 14 0c |e..I....E...:...|
-000002e0 cb 48 ce 75 c2 a4 4a 0e 7d d8 f0 c5 5f 02 42 01 |.H.u..J.}..._.B.|
-000002f0 99 dd c7 54 ce ee 38 bb 18 16 eb 92 0a 53 0b 92 |...T..8......S..|
-00000300 d8 73 73 48 b3 0a 3b ea 12 ea 62 d3 88 99 00 54 |.ssH..;...b....T|
-00000310 bc 92 28 7d 66 b3 17 7f e7 5f 69 50 d1 a1 4c 6a |..(}f...._iP..Lj|
-00000320 99 60 00 59 0a 4d 6c 97 05 54 ee 82 5a e1 c5 88 |.`.Y.Ml..T..Z...|
-00000330 1b 14 03 03 00 01 01 16 03 03 00 24 80 64 11 aa |...........$.d..|
-00000340 cc 9d 1c 83 b6 2f 56 dc 48 cb 33 e5 0f 25 a2 42 |...../V.H.3..%.B|
-00000350 df b8 a6 cc 64 93 10 63 ad 76 91 27 3f c7 8f d4 |....d..c.v.'?...|
+00000210 03 03 00 86 10 00 00 82 00 80 2b 80 6e 49 b8 ec |..........+.nI..|
+00000220 12 7a 7c f3 2a d3 7e 16 a0 39 e5 77 61 7a 56 15 |.z|.*.~..9.wazV.|
+00000230 97 c6 64 63 13 cf 09 d0 1b f5 b6 78 1d cb 86 4f |..dc.......x...O|
+00000240 14 84 c9 e6 5d 3c 6b 61 5e 46 83 7e ef 1d 74 d4 |....]<ka^F.~..t.|
+00000250 3b 8c 78 be 26 92 24 04 b4 6f 21 88 03 8d 92 a8 |;.x.&.$..o!.....|
+00000260 60 c6 08 b5 75 5d 2f 2c 71 60 5f 54 27 a0 fa 83 |`...u]/,q`_T'...|
+00000270 4d 39 1e 22 1e 1e 60 92 51 ac 2d 35 c7 cf fc 5e |M9."..`.Q.-5...^|
+00000280 db e3 60 37 6b 4e 7c d8 04 f3 09 54 de 38 af 57 |..`7kN|....T.8.W|
+00000290 20 d0 f5 08 5a a8 6f 65 03 55 16 03 03 00 93 0f | ...Z.oe.U......|
+000002a0 00 00 8f 04 03 00 8b 30 81 88 02 42 00 97 84 ac |.......0...B....|
+000002b0 cf 9b df b0 3a c8 9d a6 da 8c 11 87 35 2a d7 d0 |....:.......5*..|
+000002c0 15 df e1 02 ca 85 3f 1c a5 21 17 8c 8a 73 1b 76 |......?..!...s.v|
+000002d0 8d 0f af 26 ea b5 7f 87 a6 b6 c8 61 32 27 fc f4 |...&.......a2'..|
+000002e0 b7 c5 c3 2c 53 61 59 5a 5d 12 c6 dd 9e 54 02 42 |...,SaYZ]....T.B|
+000002f0 01 04 3f 82 bb a4 5c ea ea c9 9c 2a 75 96 c2 88 |..?...\....*u...|
+00000300 5a ae f8 2e 29 01 cf 7b a4 20 83 df ec c8 9d 37 |Z...)..{. .....7|
+00000310 0c 33 fb 20 73 51 47 6d 81 d0 75 b1 19 ed 02 00 |.3. sQGm..u.....|
+00000320 b8 40 67 75 b9 72 63 9c 1e e1 c9 44 93 d6 ec e7 |.@gu.rc....D....|
+00000330 16 5c 14 03 03 00 01 01 16 03 03 00 40 43 51 cf |.\..........@CQ.|
+00000340 07 b2 de 6e 40 10 eb dd 3f 84 6a 54 a3 7f b2 48 |...n@...?.jT...H|
+00000350 b3 aa 3c d4 e7 69 32 7c 77 ba e9 0b 99 b3 c9 e8 |..<..i2|w.......|
+00000360 c5 53 29 9a 6b 82 ee 7d 5e a9 ae 63 fa a9 af 21 |.S).k..}^..c...!|
+00000370 f2 04 b1 a1 bf f1 10 4c 65 6c 49 34 a0 |.......LelI4.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 24 8d e5 5f d9 |..........$$.._.|
-00000010 99 7d d4 f2 5f f4 4b e3 b4 8e 33 84 7a c3 cb bf |.}.._.K...3.z...|
-00000020 21 00 94 db 7b 7f 6c fa a0 f2 9f 0e e9 3b 27 17 |!...{.l......;'.|
-00000030 03 03 00 21 67 f8 3a ff c1 3b cb de 04 bf 49 a6 |...!g.:..;....I.|
-00000040 9a 45 56 ab 64 99 06 7e 40 cc a7 f6 4e 1e ca cb |.EV.d..~@...N...|
-00000050 11 87 da 58 b7 15 03 03 00 16 10 1b 62 97 25 bf |...X........b.%.|
-00000060 84 c1 23 d6 76 4a a1 da 07 c7 25 68 f6 6e 63 55 |..#.vJ....%h.ncU|
+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 93 a2 18 a9 e2 |................|
+00000020 51 be f7 bd c0 05 64 51 0a 17 9d 58 11 d1 a6 b9 |Q.....dQ...X....|
+00000030 6d 1e 42 16 e4 bc bf 09 f2 b9 29 20 74 8a cd 8a |m.B.......) t...|
+00000040 b6 31 04 64 fb 5b 1f 83 c3 19 78 17 03 03 00 40 |.1.d.[....x....@|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 ee c4 d0 5d 69 37 2b fc dc 9c f1 77 df 44 6f da |...]i7+....w.Do.|
+00000070 4e 22 05 05 3a 6c 32 a8 6c c2 fb ce ca a7 1b 54 |N"..:l2.l......T|
+00000080 2a 25 ae cf 77 e4 47 21 33 b6 29 54 62 00 dd 30 |*%..w.G!3.)Tb..0|
+00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
+000000a0 00 00 00 00 00 cf e1 fd e3 5f d3 19 cd 05 70 79 |........._....py|
+000000b0 be 16 a5 26 18 f1 92 bc 73 bd 6f 4d 33 3d 6f 8a |...&....s.oM3=o.|
+000000c0 13 51 7c 57 c7 |.Q|W.|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven b/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven
index 819825ca897..c81acc8992f 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven
@@ -1,116 +1,123 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5b 01 00 00 57 03 03 87 41 6f c5 67 |....[...W...Ao.g|
-00000010 07 3b 12 46 ad aa d2 be 0d 08 98 e3 c7 4b ac 48 |.;.F.........K.H|
-00000020 67 02 6b 3b dc 84 79 c5 57 e9 89 00 00 04 00 05 |g.k;..y.W.......|
-00000030 00 ff 02 01 00 00 29 00 0d 00 20 00 1e 06 01 06 |......)... .....|
-00000040 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
-00000050 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |................|
+00000000 16 03 01 00 5d 01 00 00 59 03 03 f3 3a db 98 ff |....]...Y...:...|
+00000010 29 a2 30 75 53 87 b3 5f 00 b5 9f 77 4d 88 38 ea |).0uS.._...wM.8.|
+00000020 e9 87 f4 a4 e4 da dd 73 00 47 d1 00 00 04 00 2f |.......s.G...../|
+00000030 00 ff 01 00 00 2c 00 0d 00 20 00 1e 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 00 16 00 00 00 17 |................|
+00000060 00 00 |..|
>>> 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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002b0 17 0d 00 00 13 02 01 40 00 0c 04 01 04 03 05 01 |.......@........|
-000002c0 05 03 02 01 02 03 00 00 16 03 03 00 04 0e 00 00 |................|
-000002d0 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 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 17 0d 00 00 13 02 01 40 |;..............@|
+000002a0 00 0c 04 01 04 03 05 01 05 03 02 01 02 03 00 00 |................|
+000002b0 16 03 03 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 79 a7 23 10 fc |...........y.#..|
-00000210 64 a7 ab 17 ce d6 8b ab ff c2 44 40 3b ba b4 c6 |d.........D@;...|
-00000220 86 b7 66 7d be 9b fa 66 f9 f6 bb e4 f7 02 16 ea |..f}...f........|
-00000230 0f 13 9c 8a 98 3a 34 e6 58 82 dc dc 27 3a 3d 5c |.....:4.X...':=\|
-00000240 99 09 db 48 54 a5 5a a2 16 7f ba 99 d9 0d ca fb |...HT.Z.........|
-00000250 4a 9e b7 f6 3a ab 26 ef f9 df a2 0c 4c 45 19 3b |J...:.&.....LE.;|
-00000260 b2 9f 21 cd ff fc cc c7 fb 91 fa 54 93 a9 42 a9 |..!........T..B.|
-00000270 4c 48 4a 8c 7b 9a d7 90 97 f6 21 89 03 f6 a5 86 |LHJ.{.....!.....|
-00000280 83 6f 21 19 2f 5b f8 ec a6 36 e9 16 03 03 00 88 |.o!./[...6......|
-00000290 0f 00 00 84 04 01 00 80 0f 9d 15 cc c0 0b 71 8a |..............q.|
-000002a0 b9 95 ca 9a 86 ff bf 93 8d da 64 ce 99 28 e2 6e |..........d..(.n|
-000002b0 6d 6f 34 c9 03 fa 87 96 b0 1d 4f b2 3c 9e 4d 2c |mo4.......O.<.M,|
-000002c0 df be 7d fb 53 fe 90 6f 45 f3 f0 d9 ab 70 d4 df |..}.S..oE....p..|
-000002d0 5a 95 a4 53 12 02 c1 45 15 c2 2b 69 7e 5f 6f cd |Z..S...E..+i~_o.|
-000002e0 b3 eb 5d ff 48 36 94 ad 28 29 fe 47 40 ab 9c eb |..].H6..().G@...|
-000002f0 02 f9 ca 7d e0 48 9f 6e a4 9f 1e c2 d7 fd 16 18 |...}.H.n........|
-00000300 db ad d9 35 27 89 96 c8 c4 70 10 be a4 5d 6b b4 |...5'....p...]k.|
-00000310 d8 61 70 93 08 00 0f c9 14 03 03 00 01 01 16 03 |.ap.............|
-00000320 03 00 24 7b ee b7 23 12 63 f0 80 ca b3 6f d3 b8 |..${..#.c....o..|
-00000330 ca cc 4a 54 06 ea e5 3e 73 f2 de 1d d6 16 7e 61 |..JT...>s.....~a|
-00000340 32 76 eb f8 8a 66 74 |2v...ft|
+00000000 16 03 03 01 fd 0b 00 01 f9 00 01 f6 00 01 f3 30 |...............0|
+00000010 82 01 ef 30 82 01 58 a0 03 02 01 02 02 10 5c 19 |...0..X.......\.|
+00000020 c1 89 65 83 55 6f dc 0b c9 b9 93 9f e9 bc 30 0d |..e.Uo........0.|
+00000030 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 12 31 |..*.H........0.1|
+00000040 10 30 0e 06 03 55 04 0a 13 07 41 63 6d 65 20 43 |.0...U....Acme C|
+00000050 6f 30 1e 17 0d 31 36 30 38 31 37 32 31 35 32 33 |o0...16081721523|
+00000060 31 5a 17 0d 31 37 30 38 31 37 32 31 35 32 33 31 |1Z..170817215231|
+00000070 5a 30 12 31 10 30 0e 06 03 55 04 0a 13 07 41 63 |Z0.1.0...U....Ac|
+00000080 6d 65 20 43 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |me Co0..0...*.H.|
+00000090 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....|
+000000a0 81 00 ba 6f aa 86 bd cf bf 9f f2 ef 5c 94 60 78 |...o........\.`x|
+000000b0 6f e8 13 f2 d1 96 6f cd d9 32 6e 22 37 ce 41 f9 |o.....o..2n"7.A.|
+000000c0 ca 5d 29 ac e1 27 da 61 a2 ee 81 cb 10 c7 df 34 |.])..'.a.......4|
+000000d0 58 95 86 e9 3d 19 e6 5c 27 73 60 c8 8d 78 02 f4 |X...=..\'s`..x..|
+000000e0 1d a4 98 09 a3 19 70 69 3c 25 62 66 2a ab 22 23 |......pi<%bf*."#|
+000000f0 c5 7b 85 38 4f 2e 09 73 32 a7 bd 3e 9b ad ca 84 |.{.8O..s2..>....|
+00000100 07 e6 0f 3a ff 77 c5 9d 41 85 00 8a b6 9b ee b0 |...:.w..A.......|
+00000110 a4 3f 2d 4c 4c e6 42 3e bb 51 c8 dd 48 54 f4 0c |.?-LL.B>.Q..HT..|
+00000120 8e 47 02 03 01 00 01 a3 46 30 44 30 0e 06 03 55 |.G......F0D0...U|
+00000130 1d 0f 01 01 ff 04 04 03 02 05 a0 30 13 06 03 55 |...........0...U|
+00000140 1d 25 04 0c 30 0a 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......|
+00000150 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 0f |0...U.......0.0.|
+00000160 06 03 55 1d 11 04 08 30 06 87 04 7f 00 00 01 30 |..U....0.......0|
+00000170 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 |...*.H..........|
+00000180 81 00 46 ab 44 a2 fb 28 54 f8 5a 67 f8 62 94 f1 |..F.D..(T.Zg.b..|
+00000190 9a b2 18 9e f2 b1 de 1d 7e 6f 76 95 a9 ba e7 5d |........~ov....]|
+000001a0 a8 16 6c 9c f7 09 d3 37 e4 4b 2b 36 7c 01 ad 41 |..l....7.K+6|..A|
+000001b0 d2 32 d8 c3 d2 93 f9 10 6b 8e 95 b9 2c 17 8a a3 |.2......k...,...|
+000001c0 44 48 bc 59 13 83 16 04 88 a4 81 5c 25 0d 98 0c |DH.Y.......\%...|
+000001d0 ac 11 b1 28 56 be 1d cd 61 62 84 09 bf d6 80 c6 |...(V...ab......|
+000001e0 45 8d 82 2c b4 d8 83 9b db c9 22 b7 2a 12 11 7b |E..,......".*..{|
+000001f0 fa 02 3b c1 c9 ff ea c9 9d a8 49 d3 95 d7 d5 0e |..;.......I.....|
+00000200 e5 35 16 03 03 00 86 10 00 00 82 00 80 47 31 82 |.5...........G1.|
+00000210 ae c1 d2 74 3f a4 74 5a 57 16 ae e2 d0 46 72 53 |...t?.tZW....FrS|
+00000220 e1 5e 6a e8 e4 d5 8c 84 2b d9 82 c1 4a da 9e 1d |.^j.....+...J...|
+00000230 a0 da 60 08 0d 35 0c 55 6d 6a 68 04 09 ee 94 39 |..`..5.Umjh....9|
+00000240 c7 a3 49 7f 2c ee 6a cf 09 01 bd 08 d3 59 0a bd |..I.,.j......Y..|
+00000250 7f 6c d3 26 eb be 7b fd 9b 17 fd e2 6e 82 d1 c7 |.l.&..{.....n...|
+00000260 dd c3 64 8c 87 f0 41 f2 71 75 f1 0a 01 26 5b 97 |..d...A.qu...&[.|
+00000270 94 ba ac 50 df 19 32 39 80 ae 14 ea 4a d2 e5 9f |...P..29....J...|
+00000280 5d 07 9f 2d 89 ac 83 33 40 aa 8e cc 2c 16 03 03 |]..-...3@...,...|
+00000290 00 88 0f 00 00 84 04 01 00 80 7d 37 8b 6f be e9 |..........}7.o..|
+000002a0 e7 fa 4c 28 cf 16 0d 28 40 e9 f2 9a 11 22 fc 8a |..L(...(@...."..|
+000002b0 2c 52 f7 36 af 1a cf d7 8a f8 17 19 9f ed 9d 1d |,R.6............|
+000002c0 43 f9 e2 fb 0f dd ca d6 1d 4c 03 4e 25 8d 5c 4c |C........L.N%.\L|
+000002d0 95 98 02 db cf ea 44 2a ad 36 74 e3 08 07 e3 9a |......D*.6t.....|
+000002e0 50 6c dc 46 a1 f5 84 9b 65 7f 48 94 b5 de cc a9 |Pl.F....e.H.....|
+000002f0 cf ee 0e 31 f2 f8 6f 8f 19 4b 29 14 b4 32 1d 21 |...1..o..K)..2.!|
+00000300 02 d2 da 64 68 e8 a1 72 cc ee 64 48 d8 74 e5 64 |...dh..r..dH.t.d|
+00000310 90 b3 50 cc 3e 25 0e b1 88 53 14 03 03 00 01 01 |..P.>%...S......|
+00000320 16 03 03 00 40 6a 61 6b 3e ea 63 2c b8 26 95 e2 |....@jak>.c,.&..|
+00000330 5f 83 e3 c3 cd c3 b7 a8 0b 76 81 8a 5b 46 ff 41 |_........v..[F.A|
+00000340 c2 02 eb 21 85 31 b9 ba 2e 30 e7 6e 8d 1c 49 15 |...!.1...0.n..I.|
+00000350 af a0 a7 67 62 b7 42 8c fa a8 04 8c 23 7a 3d 39 |...gb.B.....#z=9|
+00000360 74 18 70 2b 99 |t.p+.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 64 d5 a4 78 e9 |..........$d..x.|
-00000010 f1 1d d1 34 f7 b3 95 87 18 f6 cf 65 c6 f0 02 08 |...4.......e....|
-00000020 69 f5 6d aa f2 da fc 2c ac fc aa f8 25 aa 50 17 |i.m....,....%.P.|
-00000030 03 03 00 21 9f 94 f8 78 46 58 2c 21 0d 30 04 89 |...!...xFX,!.0..|
-00000040 bd 35 03 dc 04 b6 0f 6f 22 65 db 3d 8d 96 00 0c |.5.....o"e.=....|
-00000050 db bf e5 b3 59 15 03 03 00 16 a6 35 f2 07 5e 32 |....Y......5..^2|
-00000060 4e 09 e4 31 3a f6 4a 83 c2 03 db b9 bf b0 eb 6d |N..1:.J........m|
+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 a6 5b 7c b0 91 |............[|..|
+00000020 53 f6 d5 e4 34 71 4f 64 2a 03 9d 75 62 d9 8d a8 |S...4qOd*..ub...|
+00000030 39 7b e1 d8 31 80 26 db 14 f3 3a 52 66 7d 12 31 |9{..1.&...:Rf}.1|
+00000040 29 14 7f a1 39 b6 1c e0 c9 55 6e 17 03 03 00 40 |)...9....Un....@|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 5e 00 64 9b 25 cd 74 94 b7 65 6e 83 8e 5b 68 e8 |^.d.%.t..en..[h.|
+00000070 59 4c f0 31 8b f2 0c 59 2a ff 11 8e 43 d4 73 fd |YL.1...Y*...C.s.|
+00000080 b3 2a 76 59 25 52 32 76 bd 2e 1d 4d 0a 53 d7 c2 |.*vY%R2v...M.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 23 96 6e 7d 41 bb 51 4f 40 52 07 |.....#.n}A.QO@R.|
+000000b0 90 cc 6c bd c0 bb 99 d4 8a 91 7b 8a f3 24 ef 71 |..l.......{..$.q|
+000000c0 20 d4 98 b0 14 | ....|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven b/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven
index 903272b6442..091de9081eb 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven
@@ -1,76 +1,83 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5b 01 00 00 57 03 03 9a 56 e0 d9 b8 |....[...W...V...|
-00000010 ac d5 88 c7 2f d1 87 1b 44 c6 ff 7b 4f 6f f0 2a |..../...D..{Oo.*|
-00000020 56 a1 9e 46 86 4b 6f 91 29 29 3b 00 00 04 00 05 |V..F.Ko.));.....|
-00000030 00 ff 02 01 00 00 29 00 0d 00 20 00 1e 06 01 06 |......)... .....|
-00000040 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
-00000050 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |................|
+00000000 16 03 01 00 5d 01 00 00 59 03 03 41 24 db 27 37 |....]...Y..A$.'7|
+00000010 2e 1e a8 61 b7 7f 08 f1 83 84 fb d5 a2 96 e0 53 |...a...........S|
+00000020 1a 2b cd 8e 50 38 7b a5 64 d8 92 00 00 04 00 2f |.+..P8{.d....../|
+00000030 00 ff 01 00 00 2c 00 0d 00 20 00 1e 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 00 16 00 00 00 17 |................|
+00000060 00 00 |..|
>>> 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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002b0 17 0d 00 00 13 02 01 40 00 0c 04 01 04 03 05 01 |.......@........|
-000002c0 05 03 02 01 02 03 00 00 16 03 03 00 04 0e 00 00 |................|
-000002d0 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 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 17 0d 00 00 13 02 01 40 |;..............@|
+000002a0 00 0c 04 01 04 03 05 01 05 03 02 01 02 03 00 00 |................|
+000002b0 16 03 03 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 3a 72 91 a2 c3 ba 83 75 1b |.......:r.....u.|
-00000020 d3 f6 1c 07 7f 92 a8 b0 1f 47 42 cc 8d 4e 7e 1e |.........GB..N~.|
-00000030 23 49 44 29 53 19 9f 3b 5c bb 5d ed 6c d9 49 5d |#ID)S..;\.].l.I]|
-00000040 6e f9 d1 59 9d 40 67 b3 0c ee 41 85 6c 4a 4d 3b |n..Y.@g...A.lJM;|
-00000050 c1 e6 c8 7f 93 15 cb 2a 17 64 da 70 f3 2a c3 7c |.......*.d.p.*.||
-00000060 a2 02 48 19 fb 74 5a dc 52 0d 80 6b ed c0 8c 15 |..H..tZ.R..k....|
-00000070 3e 3b 34 7c 55 6e 95 e0 d1 4a 7f b0 bc 33 67 a7 |>;4|Un...J...3g.|
-00000080 3b 40 bb eb 83 58 4a fb fb 01 9b 0d fa ef 83 c4 |;@...XJ.........|
-00000090 87 10 75 0c a7 ad 91 14 03 03 00 01 01 16 03 03 |..u.............|
-000000a0 00 24 18 ce de 8d ab c1 6e 3b 0b 51 fe 94 ae 0a |.$......n;.Q....|
-000000b0 39 9c 4d a2 90 53 d4 1e 5f f6 96 5a 51 f2 39 c1 |9.M..S.._..ZQ.9.|
-000000c0 d6 06 c0 4e 58 99 |...NX.|
+00000010 86 10 00 00 82 00 80 61 2e 6b ad 77 48 8d 2f 0e |.......a.k.wH./.|
+00000020 e6 27 64 fd 95 22 72 68 80 8e 2b 0e b2 0f cc be |.'d.."rh..+.....|
+00000030 19 31 93 1d d3 0a fb 00 da 50 26 66 17 59 6b e9 |.1.......P&f.Yk.|
+00000040 7e 16 4e 24 ba 68 0a 0c 69 2f 03 74 34 50 12 85 |~.N$.h..i/.t4P..|
+00000050 4a f0 6c 52 d4 dd 13 18 c7 a4 9d ea f0 c6 94 d9 |J.lR............|
+00000060 ae fe 19 6c 83 dd ed 38 e3 d2 21 18 e6 76 11 e7 |...l...8..!..v..|
+00000070 62 13 8b 56 65 e0 f6 61 d9 db 7c 7b 5b 57 13 3d |b..Ve..a..|{[W.=|
+00000080 58 64 67 8d 9f 3f 6a a0 70 c5 c6 d0 db eb 17 3f |Xdg..?j.p......?|
+00000090 6c 58 d7 c3 ba ec 4c 14 03 03 00 01 01 16 03 03 |lX....L.........|
+000000a0 00 40 6e 24 1b a4 b3 e7 d4 c2 7e cb bd 82 2d 4c |.@n$......~...-L|
+000000b0 a8 f1 5e 81 c8 61 a6 2c 6a e3 6d 30 7f fa c7 f3 |..^..a.,j.m0....|
+000000c0 f6 b1 b1 4f 0b 23 9a fd 66 81 48 97 4b 0f 88 07 |...O.#..f.H.K...|
+000000d0 37 7b 97 b0 62 6c 2a e1 47 65 e9 f9 cd c1 79 99 |7{..bl*.Ge....y.|
+000000e0 6d 84 |m.|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 8b 7e 57 f3 7d |..........$.~W.}|
-00000010 ab 44 f0 c7 53 2d 39 08 14 32 12 4e 4b 45 9a e3 |.D..S-9..2.NKE..|
-00000020 1c 43 36 16 59 a0 4b e4 78 43 d2 a5 dc 96 b1 17 |.C6.Y.K.xC......|
-00000030 03 03 00 21 54 89 75 23 de 7d c7 c6 80 a6 a6 69 |...!T.u#.}.....i|
-00000040 d0 a8 95 77 71 a0 89 34 f4 c3 31 73 bb b0 ac d7 |...wq..4..1s....|
-00000050 e5 e4 83 4b 10 15 03 03 00 16 0d 44 43 67 21 cc |...K.......DCg!.|
-00000060 6c c1 7e 72 99 aa 7f a1 de 10 0b 36 ae 05 d9 9e |l.~r.......6....|
+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 40 c6 62 4e 26 |...........@.bN&|
+00000020 e7 32 09 ba d6 3b 71 79 8e 75 ee fb af 09 db c5 |.2...;qy.u......|
+00000030 a5 8b cd 1f 90 f3 65 86 4a b4 b1 9a e8 1e 80 f6 |......e.J.......|
+00000040 ad db bd c2 9f ec 98 42 0b 37 30 17 03 03 00 40 |.......B.70....@|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 a9 74 3c 13 87 f4 cf 77 be 07 c2 a1 e0 47 4e 52 |.t<....w.....GNR|
+00000070 c2 86 da 08 c2 93 21 80 4c 19 51 cc 0d 76 49 75 |......!.L.Q..vIu|
+00000080 0b 48 3d e0 e2 01 93 4b f1 73 91 17 aa 00 b5 71 |.H=....K.s.....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 1f 2f 2d d7 39 06 c4 59 49 80 66 |....../-.9..YI.f|
+000000b0 6c 35 2e a7 45 ee 0a 05 4b 1e 7f 78 5d cd 24 2c |l5..E...K..x].$,|
+000000c0 0a 3e 55 1c 7d |.>U.}|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES b/libgo/go/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES
index 8b04a5ad4d9..b412980e2af 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES
@@ -1,13 +1,12 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 83 01 00 00 7f 03 03 ec 8e d0 43 01 |..............C.|
-00000010 8e 81 3f d8 1f 7e 96 f1 de 4c 94 18 09 1d c5 8c |..?..~...L......|
-00000020 3a 58 68 5b 3e 7d 46 66 fe 04 74 00 00 04 c0 0a |:Xh[>}Ff..t.....|
-00000030 00 ff 02 01 00 00 51 00 0b 00 04 03 00 01 02 00 |......Q.........|
-00000040 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 18 00 |................|
-00000050 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 0a 00 |................|
-00000060 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 05 |.. .............|
-00000070 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 02 |................|
-00000080 02 02 03 00 0f 00 01 01 |........|
+00000000 16 03 01 00 73 01 00 00 6f 03 03 f0 4f 82 cc 2a |....s...o...O..*|
+00000010 27 0b 7f 2e e4 af 6d ba 4e fe 61 99 fc 0a 44 ee |'.....m.N.a...D.|
+00000020 c0 4e 7b 3a 7c f0 6d 12 b7 7d 9e 00 00 04 c0 0a |.N{:|.m..}......|
+00000030 00 ff 01 00 00 42 00 0b 00 04 03 00 01 02 00 0a |.....B..........|
+00000040 00 0a 00 08 00 1d 00 17 00 19 00 18 00 0d 00 20 |............... |
+00000050 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 |................|
+00000060 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 |................|
+00000070 00 16 00 00 00 17 00 00 |........|
>>> 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 |................|
@@ -45,43 +44,39 @@
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 05 03 00 8b 30 81 88 02 42 |A.Vk.Z.....0...B|
-000002a0 01 08 89 99 1c 91 97 fb e8 5b 69 5f f5 36 66 d6 |.........[i_.6f.|
-000002b0 dd 53 04 09 c8 7f c1 25 28 8c 28 57 55 3a 95 3f |.S.....%(.(WU:.?|
-000002c0 ab 09 47 9a 27 74 83 84 44 cf 86 b7 5e 7f fe db |..G.'t..D...^...|
-000002d0 05 33 3c 1a b7 f6 bc ff 0d 33 e4 ec 3c e2 1d e2 |.3<......3..<...|
-000002e0 6e ab 02 42 00 92 4e 45 a7 86 e4 bd 40 82 b7 04 |n..B..NE....@...|
-000002f0 12 fe 34 ab e3 c9 4a 05 1f 4e 58 79 67 58 94 53 |..4...J..NXygX.S|
-00000300 e8 1b ba 60 76 92 00 99 a7 5f 0a 98 cb e3 1e de |...`v...._......|
-00000310 0c df 18 76 58 d5 e1 f1 ef a5 da 9a a3 62 77 50 |...vX........bwP|
-00000320 37 d0 22 d0 31 90 16 03 03 00 04 0e 00 00 00 |7.".1..........|
+00000240 7b 6a 0f 39 95 12 07 8f 2a 16 03 03 00 b7 0c 00 |{j.9....*.......|
+00000250 00 b3 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 28 |..... /.}.G.bC.(|
+00000260 da ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 |.._.).0.........|
+00000270 99 5f 58 cb 3b 74 05 03 00 8b 30 81 88 02 42 01 |._X.;t....0...B.|
+00000280 2d d4 82 80 01 6b e6 8c 6a 2a b3 09 1b 0d 86 e6 |-....k..j*......|
+00000290 62 92 85 46 d9 e3 b2 e9 f1 5e 77 c2 27 fd 2b 68 |b..F.....^w.'.+h|
+000002a0 6a e1 3d e2 42 d2 86 96 42 b1 3b 50 7b e2 2c 34 |j.=.B...B.;P{.,4|
+000002b0 d3 e7 f6 14 89 48 eb 5c 9a 98 98 ab f3 db 85 06 |.....H.\........|
+000002c0 cb 02 42 00 df 42 94 63 a5 ff 43 a5 20 5d 83 09 |..B..B.c..C. ]..|
+000002d0 88 7d 10 ff ec 32 33 28 1d 43 b2 d2 bf 39 0c 63 |.}...23(.C...9.c|
+000002e0 9a c0 f8 0e 9f 71 a7 9a 5d 27 1a 5c f2 36 80 b3 |.....q..]'.\.6..|
+000002f0 71 0f d3 c0 fd 0d 5d 02 90 c4 9d 90 db 74 ad f6 |q.....]......t..|
+00000300 22 8f 6b 9d 55 16 03 03 00 04 0e 00 00 00 |".k.U.........|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 9e 94 25 4f 70 |....F...BA...%Op|
-00000010 a8 e0 87 3a 09 6c 58 4f 5e 76 d9 63 dc c3 d5 63 |...:.lXO^v.c...c|
-00000020 be f2 75 ff 23 23 79 6b 82 fe 56 f5 b9 7a 55 55 |..u.##yk..V..zUU|
-00000030 32 3b ee c5 f0 1f 7b e9 82 01 21 8d 06 03 48 95 |2;....{...!...H.|
-00000040 21 b8 fa 9d 18 2a 08 9c 71 a8 4d 14 03 03 00 01 |!....*..q.M.....|
-00000050 01 16 03 03 00 40 31 f0 7b 5f e8 94 a3 7f b0 12 |.....@1.{_......|
-00000060 a9 80 87 26 eb cf b6 87 61 e7 5b 9b 36 3d 11 bb |...&....a.[.6=..|
-00000070 21 55 5c f7 e8 f3 b7 1e f2 06 0d c5 a9 8d f8 48 |!U\............H|
-00000080 c2 2b 8f 83 be 17 4f ec ff 8e 24 44 74 25 09 40 |.+....O...$Dt%.@|
-00000090 90 fd 70 4d fb bb |..pM..|
+00000000 16 03 03 00 25 10 00 00 21 20 af 52 73 d4 46 4d |....%...! .Rs.FM|
+00000010 bc 0e dd 56 1f 7f 72 ce 6c 99 b9 64 53 7d 53 8d |...V..r.l..dS}S.|
+00000020 0c a4 75 8c 83 3b 4b 76 2d 4f 14 03 03 00 01 01 |..u..;Kv-O......|
+00000030 16 03 03 00 40 a0 ef 9f 54 a8 ab 7c 5b 4a a1 b2 |....@...T..|[J..|
+00000040 5d 5b 6a d7 a7 32 35 46 58 d0 ba 38 6f 94 6e 9a |][j..25FX..8o.n.|
+00000050 41 16 82 ed 4d 39 c4 ff 06 bf 2c 67 47 70 56 4e |A...M9....,gGpVN|
+00000060 c5 ac 7f a0 5d d9 89 82 7a d9 36 07 55 b3 20 f4 |....]...z.6.U. .|
+00000070 b2 73 cf c3 7d |.s..}|
>>> 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 13 eb 4e 56 3d |.............NV=|
-00000020 1b 10 2e e8 08 65 b9 53 9e 56 49 b7 e9 25 35 94 |.....e.S.VI..%5.|
-00000030 c7 df 7d f7 78 2e f3 8b 9c 2b 9d 42 90 91 5c 97 |..}.x....+.B..\.|
-00000040 22 20 ca 6d a2 83 b3 d8 b3 71 64 17 03 03 00 40 |" .m.....qd....@|
+00000010 00 00 00 00 00 00 00 00 00 00 00 73 5f db 9e 08 |...........s_...|
+00000020 10 38 3b c0 95 6b dd fc 16 b2 d1 db 63 13 ca d5 |.8;..k......c...|
+00000030 b5 be 5a 1d 74 b5 75 f3 a2 63 59 be a7 d0 ab 0d |..Z.t.u..cY.....|
+00000040 d3 43 83 8a 1d 59 ed fd ea f0 b9 17 03 03 00 40 |.C...Y.........@|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000060 97 f1 c4 2e bf 6d 85 d5 3d 4b 4a 8b ee 53 08 5a |.....m..=KJ..S.Z|
-00000070 db 8b 75 49 d9 cb db e3 86 90 ac 93 ce e7 9a 70 |..uI...........p|
-00000080 4c dc 4a f4 c9 f6 b5 fd f0 3f 9f e9 f9 c3 b3 c6 |L.J......?......|
+00000060 cf 20 4f 4f bf c4 00 05 1e ca 7f 6f 69 77 e9 52 |. OO.......oiw.R|
+00000070 14 61 02 6d f1 c0 ad 7c 1a 34 cf b2 7a 58 4a 70 |.a.m...|.4..zXJp|
+00000080 11 36 5f e9 21 62 cb eb 8f e7 11 04 bf 66 03 69 |.6_.!b.......f.i|
00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-000000a0 00 00 00 00 00 5e b1 b7 21 7d 89 65 66 17 d8 79 |.....^..!}.ef..y|
-000000b0 26 db ad 08 28 2c e7 7a c4 ec 93 19 4f c8 bb 5c |&...(,.z....O..\|
-000000c0 c2 9e 09 56 07 |...V.|
+000000a0 00 00 00 00 00 f5 35 92 09 6c 45 c0 27 95 98 a9 |......5..lE.'...|
+000000b0 86 56 53 1f a8 01 d5 0b 79 0e 91 15 3b 9a 07 21 |.VS.....y...;..!|
+000000c0 cb ce f0 2b 6a |...+j|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicket b/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicket
index 276050873ed..feced4bb8ff 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicket
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicket
@@ -1,83 +1,89 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5f 01 00 00 5b 03 03 6e cc 37 81 0a |...._...[..n.7..|
-00000010 b9 fe 58 30 8e 32 61 3c b1 38 1e 2b f6 ab 44 ee |..X0.2a<.8.+..D.|
-00000020 f2 cc fe 6e fe 40 65 49 d9 ba aa 00 00 04 00 05 |...n.@eI........|
-00000030 00 ff 02 01 00 00 2d 00 23 00 00 00 0d 00 20 00 |......-.#..... .|
-00000040 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 |................|
-00000050 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 |................|
-00000060 0f 00 01 01 |....|
+00000000 16 03 01 00 61 01 00 00 5d 03 03 b1 be 1f 18 b6 |....a...].......|
+00000010 a2 5d 4f 2f a0 e5 3b c4 4a 2d 76 bd 98 92 32 85 |.]O/..;.J-v...2.|
+00000020 9d 6b 9e 10 4b fc 03 7b fb bc e4 00 00 04 00 2f |.k..K..{......./|
+00000030 00 ff 01 00 00 30 00 23 00 00 00 0d 00 20 00 1e |.....0.#..... ..|
+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 00 16 |................|
+00000060 00 00 00 17 00 00 |......|
>>> 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 71 0b |..#...........q.|
-00000040 00 02 6d 00 02 6a 00 02 67 30 82 02 63 30 82 01 |..m..j..g0..c0..|
-00000050 cc a0 03 02 01 02 02 09 00 a2 73 00 0c 81 00 cb |..........s.....|
-00000060 f3 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........|
-00000070 30 2b 31 17 30 15 06 03 55 04 0a 13 0e 47 6f 6f |0+1.0...U....Goo|
-00000080 67 6c 65 20 54 45 53 54 49 4e 47 31 10 30 0e 06 |gle TESTING1.0..|
-00000090 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
-000000a0 0d 31 35 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.150101000000Z..|
-000000b0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 26 31 |250101000000Z0&1|
-000000c0 17 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 |.0...U....Google|
-000000d0 20 54 45 53 54 49 4e 47 31 0b 30 09 06 03 55 04 | TESTING1.0...U.|
-000000e0 03 13 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |...Go0..0...*.H.|
-000000f0 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....|
-00000100 81 00 af 87 88 f6 20 1b 95 65 6c 14 ab 44 05 af |...... ..el..D..|
-00000110 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 |;E...m..cM...jb5|
-00000120 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 31 66 00 ba |..J..|..%^zd1f..|
-00000130 f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 |.....k.v.._A.nV.|
-00000140 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 d1 bc db 1c |....<.9!f=+.....|
-00000150 c0 a7 da b7 ca ad ba da cb d5 21 50 ec de 8d ab |..........!P....|
-00000160 d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 b1 44 84 bd |.k.K......l..D..|
-00000170 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef fa d6 09 47 |!..}..M........G|
-00000180 f2 fb 02 03 01 00 01 a3 81 93 30 81 90 30 0e 06 |..........0..0..|
-00000190 03 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 |.U...........0..|
-000001a0 03 55 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 |.U.%..0...+.....|
-000001b0 03 01 06 08 2b 06 01 05 05 07 03 02 30 0c 06 03 |....+.......0...|
-000001c0 55 1d 13 01 01 ff 04 02 30 00 30 19 06 03 55 1d |U.......0.0...U.|
-000001d0 0e 04 12 04 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e |......P..o...TMn|
-000001e0 cb 69 5e 06 f4 30 1b 06 03 55 1d 23 04 14 30 12 |.i^..0...U.#..0.|
-000001f0 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea b4 03 78 48 |...=..f..@....xH|
-00000200 1a 41 30 19 06 03 55 1d 11 04 12 30 10 82 0e 65 |.A0...U....0...e|
-00000210 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 |xample.golang0..|
-00000220 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 |.*.H............|
-00000230 92 7c af 91 55 12 18 96 59 31 a6 48 40 d5 2d d5 |.|..U...Y1.H@.-.|
-00000240 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da |.......|..0}<.v.|
-00000250 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b 67 59 11 21 |O=...-3$k.{.gY.!|
-00000260 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 |...w...n.-.5.d_"|
-00000270 3e 63 10 6b be ff 14 86 6d 0d f0 15 31 a8 14 38 |>c.k....m...1..8|
-00000280 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 4f dd db 9b |.;..,...Qv..O...|
-00000290 84 04 86 40 fa 51 dd ba b4 8d eb e3 46 de 46 b9 |...@.Q......F.F.|
-000002a0 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 |O.....A4......9.|
-000002b0 16 03 03 00 04 0e 00 00 00 |.........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2f 00 00 |............./..|
+00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 59 0b |..#...........Y.|
+00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..|
+00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.|
+00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........|
+00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1|
+00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
+00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000|
+000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
+000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go|
+000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..|
+000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........|
+000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...|
+000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R|
+00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....|
+00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.|
+00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..|
+00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.|
+00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.|
+00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C|
+00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......|
+00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......|
+00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.|
+00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...|
+000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......|
+000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........|
+000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..|
+000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~|
+000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.|
+000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g|
+00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....|
+00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.|
+00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.|
+00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....|
+00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ |
+00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\|
+00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...|
+00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.|
+00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`|
+00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e 00 00 |.\!.;...........|
+000002a0 00 |.|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 5d f3 3b c6 24 |...........].;.$|
-00000010 34 17 eb e1 6c de fa cd ed 6f 42 74 01 5f 4b 22 |4...l....oBt._K"|
-00000020 9e 79 da 68 9f e9 f8 af 84 6b b7 38 52 f3 5e a1 |.y.h.....k.8R.^.|
-00000030 e2 aa d1 48 15 1e 39 6e 18 59 3e dc 57 4a fb b1 |...H..9n.Y>.WJ..|
-00000040 18 18 40 ae 84 da d8 76 50 65 3b a5 d9 7a 72 b1 |..@....vPe;..zr.|
-00000050 51 07 65 08 0e 1d 05 f5 47 a8 7d 79 89 1e fe 00 |Q.e.....G.}y....|
-00000060 89 af 01 7f 4d 0c 11 d7 02 cf 88 7b be 03 c5 65 |....M......{...e|
-00000070 44 77 32 56 5c da 01 53 d1 dd d9 b4 5f 42 85 da |Dw2V\..S...._B..|
-00000080 82 0b 95 59 45 a3 7a 48 d4 00 22 14 03 03 00 01 |...YE.zH..".....|
-00000090 01 16 03 03 00 24 dd 06 a2 4b a0 8e 8b 31 f2 26 |.....$...K...1.&|
-000000a0 b2 6f d4 5d ff 34 eb 31 42 16 e7 c2 26 3d f7 16 |.o.].4.1B...&=..|
-000000b0 ed bd 41 4b 6f d4 03 fb b7 83 |..AKo.....|
+00000000 16 03 03 00 86 10 00 00 82 00 80 8f f0 5a 2f 01 |.............Z/.|
+00000010 99 79 e6 f2 a0 31 a4 02 d8 c0 1e 70 e8 67 58 bd |.y...1.....p.gX.|
+00000020 a0 2a 37 3a 3c 2d 45 53 e7 d2 7d 94 16 ea 10 5c |.*7:<-ES..}....\|
+00000030 07 91 36 87 ab f6 d1 7a c7 40 a7 7f 23 1b ef 33 |..6....z.@..#..3|
+00000040 80 ea 7d 75 d3 62 de 7d d2 6b cf 90 54 0f e7 02 |..}u.b.}.k..T...|
+00000050 03 85 ef 38 f4 e9 88 8f e4 7c 8c ac 95 e6 88 f4 |...8.....|......|
+00000060 05 f7 c7 89 4a 64 de 34 5f 09 c2 84 19 36 c1 42 |....Jd.4_....6.B|
+00000070 ea 03 69 38 7e 32 10 8a b5 cf c7 2f 8e c6 5f 29 |..i8~2...../.._)|
+00000080 4e 8a 8e d4 17 6c 9c 18 7b ea df 14 03 03 00 01 |N....l..{.......|
+00000090 01 16 03 03 00 40 5f 50 47 5a 97 52 9d 11 b5 db |.....@_PGZ.R....|
+000000a0 ab 7b b9 e3 74 52 c5 cd f4 73 18 cf 12 c4 fe 07 |.{..tR...s......|
+000000b0 88 5f a9 18 7a 12 23 67 ec 72 07 9f 19 b5 bf 52 |._..z.#g.r.....R|
+000000c0 2f dd 26 66 25 98 8c 5a 07 0f 26 c1 b0 38 6c 01 |/.&f%..Z..&..8l.|
+000000d0 e4 f4 ee dd b3 72 |.....r|
>>> Flow 4 (server to client)
00000000 16 03 03 00 82 04 00 00 7e 00 00 00 00 00 78 50 |........~.....xP|
00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................|
-00000030 6f 2c b5 83 61 4d 51 5f 33 46 48 fe 9e e9 83 f4 |o,..aMQ_3FH.....|
-00000040 b1 aa c9 b1 61 2a b2 9d 0f 17 c4 09 f6 26 7a 75 |....a*.......&zu|
-00000050 f1 19 99 db 36 d8 32 f0 94 61 4f 8f ed 80 33 51 |....6.2..aO...3Q|
-00000060 f3 c6 15 84 6b 33 94 c8 4f 84 b7 7c 27 6d 8f fe |....k3..O..|'m..|
-00000070 41 8e b2 92 ca 80 e8 6c ba 75 77 f5 3a 87 17 ae |A......l.uw.:...|
-00000080 f8 b9 6b 10 f9 85 da 14 03 03 00 01 01 16 03 03 |..k.............|
-00000090 00 24 70 bd b9 24 02 ce 69 8a 07 c7 c8 7e cf b7 |.$p..$..i....~..|
-000000a0 4e 2b e2 dc 47 fc f7 3a c8 2d ab a0 9a ed 27 d9 |N+..G..:.-....'.|
-000000b0 71 ea 45 29 d6 25 17 03 03 00 21 d9 28 ee 99 04 |q.E).%....!.(...|
-000000c0 35 ff ca 3d 30 3f 76 fb 08 1a 56 73 f5 72 c3 fa |5..=0?v...Vs.r..|
-000000d0 cd 9e 3c 1b 3f 43 4d 56 92 38 9e a6 15 03 03 00 |..<.?CMV.8......|
-000000e0 16 6f 55 57 7b 81 6f 7d fa 90 76 0b 5b 6d 95 35 |.oUW{.o}..v.[m.5|
-000000f0 39 9f a8 c9 dc b7 80 |9......|
+00000030 6f 2c 9f 83 61 0b b1 b7 9e 10 2d 0c 56 e8 70 66 |o,..a.....-.V.pf|
+00000040 ad de b1 15 74 2f 8b 08 8c 96 bb 4b 1b 4e dd 81 |....t/.....K.N..|
+00000050 0e bf 84 4d 43 8f c0 7e a0 7f be c0 59 bf 83 26 |...MC..~....Y..&|
+00000060 0f a2 22 52 2c 33 94 5a 77 54 f3 b5 f2 22 51 d5 |.."R,3.ZwT..."Q.|
+00000070 24 c2 60 c3 2e 0f 9c 5e 33 3b e8 7c 52 2a 76 08 |$.`....^3;.|R*v.|
+00000080 58 ac 47 98 bc 36 b6 14 03 03 00 01 01 16 03 03 |X.G..6..........|
+00000090 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.@..............|
+000000a0 00 00 31 fa c3 6c 95 c0 86 a5 55 30 41 c3 2d 6b |..1..l....U0A.-k|
+000000b0 a5 00 0b af 33 63 de 80 01 3d 7a 38 8e a7 f4 b1 |....3c...=z8....|
+000000c0 2d bb e3 1d 1a b4 61 18 b5 d9 d1 7f d1 9a e7 e8 |-.....a.........|
+000000d0 49 ee 17 03 03 00 40 00 00 00 00 00 00 00 00 00 |I.....@.........|
+000000e0 00 00 00 00 00 00 00 a6 d5 e4 a8 9b d3 7d 72 1c |.............}r.|
+000000f0 ff 14 03 68 34 c9 ca 0d 2e 80 a1 09 f7 92 f6 86 |...h4...........|
+00000100 44 22 e8 1c ea e9 dd cc a7 92 9a 72 ec 22 5b 82 |D".........r."[.|
+00000110 7b 43 02 f7 fa 59 7b 15 03 03 00 30 00 00 00 00 |{C...Y{....0....|
+00000120 00 00 00 00 00 00 00 00 00 00 00 00 5f ab 03 1d |............_...|
+00000130 08 72 07 6d 78 66 5b 18 ec 3a b7 ea 75 96 ce 95 |.r.mxf[..:..u...|
+00000140 0c c9 6f 86 91 14 30 d6 2e 5d b1 b4 |..o...0..]..|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable b/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable
index b5eb6c785c2..467e3324898 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable
@@ -1,83 +1,89 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5f 01 00 00 5b 03 03 54 25 f9 0f b8 |...._...[..T%...|
-00000010 2d 52 a0 17 b6 62 1c 60 38 31 30 67 f1 55 9c c8 |-R...b.`810g.U..|
-00000020 d3 74 65 bf cd 34 fb 6f f2 60 7c 00 00 04 00 05 |.te..4.o.`|.....|
-00000030 00 ff 02 01 00 00 2d 00 23 00 00 00 0d 00 20 00 |......-.#..... .|
-00000040 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 |................|
-00000050 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 |................|
-00000060 0f 00 01 01 |....|
+00000000 16 03 01 00 61 01 00 00 5d 03 03 91 2f b7 db 1e |....a...].../...|
+00000010 41 ac c6 17 1d 0f 0c 8e 86 15 e0 de e9 c8 6b f5 |A.............k.|
+00000020 69 c7 bf ad ff 63 58 2b b1 79 a6 00 00 04 00 2f |i....cX+.y...../|
+00000030 00 ff 01 00 00 30 00 23 00 00 00 0d 00 20 00 1e |.....0.#..... ..|
+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 00 16 |................|
+00000060 00 00 00 17 00 00 |......|
>>> 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 71 0b |..#...........q.|
-00000040 00 02 6d 00 02 6a 00 02 67 30 82 02 63 30 82 01 |..m..j..g0..c0..|
-00000050 cc a0 03 02 01 02 02 09 00 a2 73 00 0c 81 00 cb |..........s.....|
-00000060 f3 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........|
-00000070 30 2b 31 17 30 15 06 03 55 04 0a 13 0e 47 6f 6f |0+1.0...U....Goo|
-00000080 67 6c 65 20 54 45 53 54 49 4e 47 31 10 30 0e 06 |gle TESTING1.0..|
-00000090 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
-000000a0 0d 31 35 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.150101000000Z..|
-000000b0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 26 31 |250101000000Z0&1|
-000000c0 17 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 |.0...U....Google|
-000000d0 20 54 45 53 54 49 4e 47 31 0b 30 09 06 03 55 04 | TESTING1.0...U.|
-000000e0 03 13 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 |...Go0..0...*.H.|
-000000f0 f7 0d 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 |...........0....|
-00000100 81 00 af 87 88 f6 20 1b 95 65 6c 14 ab 44 05 af |...... ..el..D..|
-00000110 3b 45 14 e3 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 |;E...m..cM...jb5|
-00000120 86 c0 4a f9 18 7c f6 aa 25 5e 7a 64 31 66 00 ba |..J..|..%^zd1f..|
-00000130 f4 8e 92 af c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 |.....k.v.._A.nV.|
-00000140 97 1b 97 c1 3c 12 39 21 66 3d 2b 16 d1 bc db 1c |....<.9!f=+.....|
-00000150 c0 a7 da b7 ca ad ba da cb d5 21 50 ec de 8d ab |..........!P....|
-00000160 d1 6b 81 4b 89 02 f3 c4 be c1 6c 89 b1 44 84 bd |.k.K......l..D..|
-00000170 21 d1 04 7d 9d 16 4d f9 82 15 f6 ef fa d6 09 47 |!..}..M........G|
-00000180 f2 fb 02 03 01 00 01 a3 81 93 30 81 90 30 0e 06 |..........0..0..|
-00000190 03 55 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 |.U...........0..|
-000001a0 03 55 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 |.U.%..0...+.....|
-000001b0 03 01 06 08 2b 06 01 05 05 07 03 02 30 0c 06 03 |....+.......0...|
-000001c0 55 1d 13 01 01 ff 04 02 30 00 30 19 06 03 55 1d |U.......0.0...U.|
-000001d0 0e 04 12 04 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e |......P..o...TMn|
-000001e0 cb 69 5e 06 f4 30 1b 06 03 55 1d 23 04 14 30 12 |.i^..0...U.#..0.|
-000001f0 80 10 bf 3d b6 a9 66 f2 b8 40 cf ea b4 03 78 48 |...=..f..@....xH|
-00000200 1a 41 30 19 06 03 55 1d 11 04 12 30 10 82 0e 65 |.A0...U....0...e|
-00000210 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 |xample.golang0..|
-00000220 09 2a 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 |.*.H............|
-00000230 92 7c af 91 55 12 18 96 59 31 a6 48 40 d5 2d d5 |.|..U...Y1.H@.-.|
-00000240 ee bb 02 a0 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da |.......|..0}<.v.|
-00000250 4f 3d c0 fa ae 2d 33 24 6b 03 7b 1b 67 59 11 21 |O=...-3$k.{.gY.!|
-00000260 b5 11 bc 77 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 |...w...n.-.5.d_"|
-00000270 3e 63 10 6b be ff 14 86 6d 0d f0 15 31 a8 14 38 |>c.k....m...1..8|
-00000280 1e 3b 84 87 2c cb 98 ed 51 76 b9 b1 4f dd db 9b |.;..,...Qv..O...|
-00000290 84 04 86 40 fa 51 dd ba b4 8d eb e3 46 de 46 b9 |...@.Q......F.F.|
-000002a0 4f 86 c7 f9 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 |O.....A4......9.|
-000002b0 16 03 03 00 04 0e 00 00 00 |.........|
+00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 2f 00 00 |............./..|
+00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 59 0b |..#...........Y.|
+00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..|
+00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.|
+00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........|
+00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1|
+00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo|
+00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000|
+000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000|
+000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go|
+000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..|
+000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........|
+000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...|
+000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R|
+00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....|
+00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.|
+00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..|
+00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.|
+00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.|
+00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C|
+00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......|
+00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......|
+00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.|
+00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...|
+000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......|
+000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........|
+000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..|
+000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~|
+000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.|
+000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g|
+00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....|
+00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.|
+00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.|
+00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....|
+00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ |
+00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\|
+00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...|
+00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.|
+00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`|
+00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 04 0e 00 00 |.\!.;...........|
+000002a0 00 |.|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 19 db c8 25 14 |..............%.|
-00000010 e0 7b 6e 87 7b 59 2d 85 8b 47 ce 31 d7 3a 53 06 |.{n.{Y-..G.1.:S.|
-00000020 ff cf 89 ae 45 fd 59 d2 50 c2 31 33 48 81 a8 d7 |....E.Y.P.13H...|
-00000030 47 36 b9 bd 8d f3 f9 f8 c2 6d 6a 8a 6b c4 e5 53 |G6.......mj.k..S|
-00000040 24 52 40 66 49 a9 56 74 4c 94 bc 85 5b 79 5a e1 |$R@fI.VtL...[yZ.|
-00000050 66 3c 42 d8 ca e1 3f c5 36 b8 b5 8c b2 ea 87 68 |f<B...?.6......h|
-00000060 70 eb e3 da 27 fe ed f5 d0 4a c7 fe 46 0b 0f 29 |p...'....J..F..)|
-00000070 19 41 ef dd a9 85 8a 67 02 41 04 30 20 07 09 55 |.A.....g.A.0 ..U|
-00000080 ff 92 44 f1 59 49 39 dd fa d7 a0 14 03 03 00 01 |..D.YI9.........|
-00000090 01 16 03 03 00 24 82 b5 7b d1 7c 03 93 88 fd 97 |.....$..{.|.....|
-000000a0 54 b7 ff 39 a7 11 c3 cd 53 f3 1c 6c ed ab b6 a0 |T..9....S..l....|
-000000b0 1c b9 89 f0 1a f8 5f 15 7f 85 |......_...|
+00000000 16 03 03 00 86 10 00 00 82 00 80 c5 0c 17 b1 b2 |................|
+00000010 65 0b b7 7b 45 6f cb 7d b4 9c 5c 82 3a 1a 75 11 |e..{Eo.}..\.:.u.|
+00000020 22 6f 41 3a 81 e2 81 2e 74 f8 70 61 fd e1 7c ce |"oA:....t.pa..|.|
+00000030 bf 06 d7 29 77 07 b3 9d cc 33 25 53 17 12 43 ae |...)w....3%S..C.|
+00000040 4f df ad a4 3e 49 6e 97 50 b6 23 d0 fa 3d a6 bc |O...>In.P.#..=..|
+00000050 38 d8 5f 2b 45 a7 d0 aa cd b1 39 03 8f 62 9e 46 |8._+E.....9..b.F|
+00000060 50 d4 83 1d b8 76 41 29 d4 40 9a 65 41 8d 1c f0 |P....vA).@.eA...|
+00000070 d4 4d 88 d2 5e 42 ec c8 86 d6 fd df 65 d8 f1 82 |.M..^B......e...|
+00000080 8f 6a 80 31 1a 0e fc 13 2b 90 a8 14 03 03 00 01 |.j.1....+.......|
+00000090 01 16 03 03 00 40 50 ad ed 91 c4 6a ed f8 aa 06 |.....@P....j....|
+000000a0 9e 13 03 38 bf 83 ef 4b 8e d5 89 d4 a3 f8 d9 8d |...8...K........|
+000000b0 bb 88 72 a6 16 f6 5d d5 ca 55 bb e4 76 47 08 35 |..r...]..U..vG.5|
+000000c0 b9 fb 92 a4 0a b9 36 d7 62 44 81 e8 cf db ad 9a |......6.bD......|
+000000d0 6d 72 c0 af 70 bd |mr..p.|
>>> Flow 4 (server to client)
00000000 16 03 03 00 82 04 00 00 7e 00 00 00 00 00 78 50 |........~.....xP|
00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................|
-00000030 6f 2c b5 83 61 01 55 65 2a 95 38 d4 d5 5f 41 c1 |o,..a.Ue*.8.._A.|
-00000040 45 e4 f8 4b 3b 08 44 df 0b 72 11 93 cd d4 ff 36 |E..K;.D..r.....6|
-00000050 0f 4f 3a a9 4c 9f ab c7 ae 88 97 bc 1e ff 2d 27 |.O:.L.........-'|
-00000060 39 a8 82 84 ae 33 94 48 8b 1c 58 9d 60 65 3c 3f |9....3.H..X.`e<?|
-00000070 17 9d 6a eb 50 cd 65 04 bb c7 28 c8 0d 57 44 52 |..j.P.e...(..WDR|
-00000080 e0 17 de df f3 13 b1 14 03 03 00 01 01 16 03 03 |................|
-00000090 00 24 5a 41 90 0a eb d9 6b 02 68 3d 98 12 1d fa |.$ZA....k.h=....|
-000000a0 46 7d 73 ea 8e 49 72 a5 2f 04 40 5c 7d 03 c7 3a |F}s..Ir./.@\}..:|
-000000b0 6e 50 7c 87 bb 13 17 03 03 00 21 46 da ec ad 52 |nP|.......!F...R|
-000000c0 ea 5a 01 89 15 77 79 af 86 02 b5 89 c8 97 dc f7 |.Z...wy.........|
-000000d0 ac 73 09 87 7a 61 57 d6 9b 17 10 af 15 03 03 00 |.s..zaW.........|
-000000e0 16 bb 20 22 ad 6e 65 66 8c d6 07 e3 82 5f ac 1e |.. ".nef....._..|
-000000f0 ec 54 72 eb 2d c5 af |.Tr.-..|
+00000030 6f 2c 9f 83 61 2e fe 48 fe f6 bb 98 a0 6f b0 be |o,..a..H.....o..|
+00000040 9e 86 d7 b2 f2 67 c7 44 c7 3d e4 2b de d0 f4 d2 |.....g.D.=.+....|
+00000050 17 51 84 8e 7a a7 80 c4 65 14 f7 49 09 68 15 56 |.Q..z...e..I.h.V|
+00000060 68 32 41 d1 6f 33 94 a1 3a c9 37 20 5d e6 b0 6f |h2A.o3..:.7 ]..o|
+00000070 37 0a 10 e3 28 e1 34 b6 6d e6 7a 44 24 7f 2f cf |7...(.4.m.zD$./.|
+00000080 1b ae dd 4c d0 11 75 14 03 03 00 01 01 16 03 03 |...L..u.........|
+00000090 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |.@..............|
+000000a0 00 00 7e 4a 31 e8 7d c6 eb 34 56 3b 62 0c 11 a2 |..~J1.}..4V;b...|
+000000b0 f0 bd 9b 9a 4c c9 39 2d ed 21 dd 0c 72 3a 92 e1 |....L.9-.!..r:..|
+000000c0 0f b3 7f 71 c5 cf 2a 6f 68 bc 8e 84 7e d5 10 2e |...q..*oh...~...|
+000000d0 c3 d4 17 03 03 00 40 00 00 00 00 00 00 00 00 00 |......@.........|
+000000e0 00 00 00 00 00 00 00 43 76 cc 74 b3 1c 89 c0 6b |.......Cv.t....k|
+000000f0 96 f7 2c 84 c1 0a 6e d6 7f b4 76 76 2c 2f 74 6a |..,...n...vv,/tj|
+00000100 c7 4e 18 69 1c 97 cd ca f2 7a 33 01 3e 6f bb 54 |.N.i.....z3.>o.T|
+00000110 49 4e 8e 1d f4 13 74 15 03 03 00 30 00 00 00 00 |IN....t....0....|
+00000120 00 00 00 00 00 00 00 00 00 00 00 00 2d 70 b1 13 |............-p..|
+00000130 a9 e3 72 ca 05 8e 8d b7 f4 97 de 58 46 aa 2a 9c |..r........XF.*.|
+00000140 2f 8c 3e 59 7b 64 e5 51 61 7f a6 39 |/.>Y{d.Qa..9|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-3DES b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-3DES
index 23b6c5be8c2..af50381abc8 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-3DES
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-3DES
@@ -1,77 +1,76 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5b 01 00 00 57 03 03 1e c8 d0 4c b2 |....[...W.....L.|
-00000010 8d 37 e1 88 c7 0f e0 6a 21 3c 5e 8a bf fa 97 1f |.7.....j!<^.....|
-00000020 5b 28 bc 6d 47 32 0a 6b f7 11 f5 00 00 04 00 0a |[(.mG2.k........|
-00000030 00 ff 02 01 00 00 29 00 0d 00 20 00 1e 06 01 06 |......)... .....|
-00000040 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
-00000050 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |................|
+00000000 16 03 01 00 5d 01 00 00 59 03 03 0c fb 72 82 e5 |....]...Y....r..|
+00000010 9a 04 90 c8 0d 73 25 9a 3f 88 e3 48 71 a2 33 3e |.....s%.?..Hq.3>|
+00000020 90 32 74 bc 12 38 d6 3a d3 11 1d 00 00 04 00 0a |.2t..8.:........|
+00000030 00 ff 01 00 00 2c 00 0d 00 20 00 1e 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 00 16 00 00 00 17 |................|
+00000060 00 00 |..|
>>> 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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002b0 04 0e 00 00 00 |.....|
+00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 4d c2 e0 9b 40 |...........M...@|
-00000010 44 52 aa 55 06 71 0b bc 17 89 3a 94 d8 d0 1d ed |DR.U.q....:.....|
-00000020 70 d3 21 30 1b be 97 e0 72 30 60 05 de 9a a9 dd |p.!0....r0`.....|
-00000030 8c 0c 81 78 3a 15 9c 1c c6 22 81 0a 10 57 d1 9a |...x:...."...W..|
-00000040 17 5c 74 9e 58 79 4b f1 70 d9 d9 21 d8 79 64 fa |.\t.XyK.p..!.yd.|
-00000050 aa a5 e6 93 2a 16 57 23 a7 17 fb 71 b6 c2 d3 5b |....*.W#...q...[|
-00000060 3d 22 50 16 47 17 5f 15 e8 f1 30 da 10 69 84 25 |="P.G._...0..i.%|
-00000070 05 d0 b5 f0 e8 69 72 4e 93 d3 7c 1a 01 6d 37 fb |.....irN..|..m7.|
-00000080 cf e1 af f9 da dd 71 56 9b 08 24 14 03 03 00 01 |......qV..$.....|
-00000090 01 16 03 03 00 30 53 ab b5 09 5a 36 36 df b1 ed |.....0S...Z66...|
-000000a0 d2 69 5c 45 0b a9 02 8f 6d 25 d4 01 da 5f 27 ab |.i\E....m%..._'.|
-000000b0 ba 89 6e ee d8 91 24 f8 5e ca 6e 4d 51 41 88 3c |..n...$.^.nMQA.<|
-000000c0 f8 67 b4 fb d3 cb |.g....|
+00000000 16 03 03 00 86 10 00 00 82 00 80 04 90 54 41 b9 |.............TA.|
+00000010 22 12 39 d9 1d 0b b8 6c d4 b3 8a ec 78 42 80 a5 |".9....l....xB..|
+00000020 03 c9 2a 9e 95 6f a0 28 3a 5c e9 59 28 ba 49 9b |..*..o.(:\.Y(.I.|
+00000030 37 63 61 3f c4 ac ba 55 6b 85 a5 27 ed 37 b9 25 |7ca?...Uk..'.7.%|
+00000040 04 cf 84 ad 43 6b ab 13 fa 72 29 b8 01 d9 aa 0c |....Ck...r).....|
+00000050 be b1 9a c4 5a 05 3d 2d 71 b4 72 f5 3a 77 fb 6b |....Z.=-q.r.:w.k|
+00000060 45 b0 5b 00 f8 1e f9 70 7f a4 64 c9 1e 35 56 0b |E.[....p..d..5V.|
+00000070 68 07 4c 04 95 f4 ca b1 0a b3 25 2b 93 2d be 80 |h.L.......%+.-..|
+00000080 76 15 75 07 23 ee 25 f3 1b a8 2f 14 03 03 00 01 |v.u.#.%.../.....|
+00000090 01 16 03 03 00 30 e5 cd 56 75 e6 a4 58 e5 33 cc |.....0..Vu..X.3.|
+000000a0 95 23 e0 7f 01 f2 45 21 bb 7d 7c 17 1f 59 7c f9 |.#....E!.}|..Y|.|
+000000b0 38 05 a3 95 4d 9b f2 3f 9d 84 2c 31 15 8b 4d d4 |8...M..?..,1..M.|
+000000c0 17 3c 62 2b f6 71 |.<b+.q|
>>> 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 50 83 52 65 2d 6e 76 aa 8d 2d 46 06 12 |...P.Re-nv..-F..|
-00000020 1a e7 25 79 28 61 9e 2d 07 0b fb 3c 77 38 d8 b0 |..%y(a.-...<w8..|
-00000030 af ca 86 8a 51 07 4d 83 39 81 9b 17 03 03 00 30 |....Q.M.9......0|
-00000040 00 00 00 00 00 00 00 00 a1 ea 74 b2 7b fc 3f 9d |..........t.{.?.|
-00000050 bc eb 9d 09 a2 56 4a ff d4 fd 00 23 0b e6 69 62 |.....VJ....#..ib|
-00000060 0e 4c 82 43 3f 21 8f b8 fd 5c ce 37 6c 57 d2 98 |.L.C?!...\.7lW..|
-00000070 15 03 03 00 20 00 00 00 00 00 00 00 00 dc 47 cc |.... .........G.|
-00000080 34 eb 9e 7f d0 8f 5a 32 e6 6d 76 15 18 cc 8d 21 |4.....Z2.mv....!|
-00000090 43 91 81 31 81 |C..1.|
+00000010 00 00 00 b3 85 c2 1b ac 9e c2 01 f7 0f 76 6d 09 |.............vm.|
+00000020 5c 4f 9f a6 89 1b 56 e3 05 0b 7e 0d 9d 6b 36 35 |\O....V...~..k65|
+00000030 49 99 aa 4c 14 3b 69 2a 87 71 7d 17 03 03 00 30 |I..L.;i*.q}....0|
+00000040 00 00 00 00 00 00 00 00 15 65 d4 be e5 1b c9 29 |.........e.....)|
+00000050 e9 3a c4 22 72 f8 0c 40 c7 f5 45 a1 a3 c8 a8 64 |.:."r..@..E....d|
+00000060 22 4c 6c 79 3f 32 66 d4 05 09 a8 d4 d8 a8 f3 c7 |"Lly?2f.........|
+00000070 15 03 03 00 20 00 00 00 00 00 00 00 00 fc 8d c6 |.... ...........|
+00000080 3d b1 c4 9f 30 26 e3 b9 46 8f ce 9f 7e 5b 1e a3 |=...0&..F...~[..|
+00000090 d0 98 64 3c 0d |..d<.|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES
index 66155e76d30..813f7489c80 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES
@@ -1,81 +1,80 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5b 01 00 00 57 03 03 5a ba 29 44 35 |....[...W..Z.)D5|
-00000010 c4 48 64 61 06 84 70 5c b5 65 ad 01 9b b2 29 0d |.Hda..p\.e....).|
-00000020 d1 46 17 3a 27 fb 92 d8 aa 21 aa 00 00 04 00 2f |.F.:'....!...../|
-00000030 00 ff 02 01 00 00 29 00 0d 00 20 00 1e 06 01 06 |......)... .....|
-00000040 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
-00000050 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |................|
+00000000 16 03 01 00 5d 01 00 00 59 03 03 7a e5 86 e2 0a |....]...Y..z....|
+00000010 53 e7 ba 32 d1 57 47 ed 45 29 1b 33 2c 58 33 8f |S..2.WG.E).3,X3.|
+00000020 36 2c 50 6f f9 c7 3b 12 40 23 e2 00 00 04 00 2f |6,Po..;.@#...../|
+00000030 00 ff 01 00 00 2c 00 0d 00 20 00 1e 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 00 16 00 00 00 17 |................|
+00000060 00 00 |..|
>>> 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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002b0 04 0e 00 00 00 |.....|
+00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 ad e8 09 aa 07 |................|
-00000010 c0 3c 8b 39 d2 a8 bd ca 59 eb cf 0a de 33 3e d2 |.<.9....Y....3>.|
-00000020 4f 76 1f 7a 96 50 b3 52 6b 04 9e 6f f1 06 2b 4a |Ov.z.P.Rk..o..+J|
-00000030 7f 01 f2 51 a3 a7 1e f6 20 a7 27 4e 97 68 61 98 |...Q.... .'N.ha.|
-00000040 9f fd bd aa e8 e6 80 4d 9a 65 51 35 11 44 e4 2c |.......M.eQ5.D.,|
-00000050 a2 47 33 d1 b6 b7 d5 40 c0 17 34 ff e2 12 8e 00 |.G3....@..4.....|
-00000060 41 e6 4f 3e 56 2f d9 30 6b d9 99 e3 9f ce 10 ba |A.O>V/.0k.......|
-00000070 7c 95 3b 49 c9 5f 1e 97 37 90 e4 da 9a e0 01 5f ||.;I._..7......_|
-00000080 b8 6f 95 19 40 0f ca 63 76 6b 2a 14 03 03 00 01 |.o..@..cvk*.....|
-00000090 01 16 03 03 00 40 86 cb f5 69 1b ee 67 6e 3b be |.....@...i..gn;.|
-000000a0 e0 de 22 06 8c d4 f4 98 a6 45 1c 2f e5 f0 b4 25 |.."......E./...%|
-000000b0 f4 c0 87 7f e8 1c 2c 1d 20 52 50 fe dc a3 0c 22 |......,. RP...."|
-000000c0 b7 7f d3 9c 42 b8 23 d0 3e fd 93 be a2 50 28 dd |....B.#.>....P(.|
-000000d0 79 f3 c6 90 c7 bb |y.....|
+00000000 16 03 03 00 86 10 00 00 82 00 80 8f 13 d1 23 1b |..............#.|
+00000010 8d 28 c7 a3 97 66 9f 8a c1 13 a1 c9 3b 25 93 7a |.(...f......;%.z|
+00000020 ea 54 58 fc 57 41 ca 92 77 99 13 01 61 e4 73 90 |.TX.WA..w...a.s.|
+00000030 c7 f1 2b 5e 5e 79 cf 69 7d 6b 3f 6e 5f 2e b0 f5 |..+^^y.i}k?n_...|
+00000040 f7 53 2b 46 15 92 6c 20 95 6b 44 6a 0a 3d 0b 56 |.S+F..l .kDj.=.V|
+00000050 66 53 ff 55 ec 38 10 cf 76 2c 0e ab 45 7a 02 6a |fS.U.8..v,..Ez.j|
+00000060 75 07 11 80 6c d0 57 79 ed d6 4b b8 a0 04 91 a0 |u...l.Wy..K.....|
+00000070 d4 4b 76 38 9c b3 a6 2e 0c 3e 63 a8 18 15 c9 ab |.Kv8.....>c.....|
+00000080 54 69 cd e5 6f 3c 56 a6 5f a7 e0 14 03 03 00 01 |Ti..o<V._.......|
+00000090 01 16 03 03 00 40 06 07 16 b4 7f fa 1a 8f 9b 1a |.....@..........|
+000000a0 a3 23 ba 5f ce ff 0a 70 b1 11 2b 84 77 7a 78 1a |.#._...p..+.wzx.|
+000000b0 6c 32 93 6c 31 e8 e5 26 12 97 14 33 a9 77 71 19 |l2.l1..&...3.wq.|
+000000c0 0b 20 5d 8f 3c 71 0d a4 b9 94 aa ff 42 8e d3 2d |. ].<q......B..-|
+000000d0 7e 57 3b 35 41 cc |~W;5A.|
>>> 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 70 e5 19 ef 25 |...........p...%|
-00000020 05 0b 02 79 2b 79 49 e6 2c ad c0 e7 03 b3 40 68 |...y+yI.,.....@h|
-00000030 67 98 31 7c 7e 85 86 a8 5c de 72 3f d1 59 12 20 |g.1|~...\.r?.Y. |
-00000040 87 95 44 57 64 35 03 f5 68 61 20 17 03 03 00 40 |..DWd5..ha ....@|
+00000010 00 00 00 00 00 00 00 00 00 00 00 51 27 cd 07 6e |...........Q'..n|
+00000020 72 c8 17 ba e7 62 7c d0 49 55 e7 e6 c5 2c 93 39 |r....b|.IU...,.9|
+00000030 55 02 f5 fa 9a 7a 6f c5 79 6f ff 0f 4b b9 3d ad |U....zo.yo..K.=.|
+00000040 23 c7 53 ad 13 2d d6 da 83 d0 67 17 03 03 00 40 |#.S..-....g....@|
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
-00000060 1b 17 7c bb 04 4f 31 7b da 40 5e 93 64 97 4a 8d |..|..O1{.@^.d.J.|
-00000070 98 cf 77 2d 01 53 37 53 2c 59 8f ca ac 65 ae f3 |..w-.S7S,Y...e..|
-00000080 f8 d4 ae 67 74 c8 72 21 67 51 9a 1b 71 f2 0e 04 |...gt.r!gQ..q...|
+00000060 f5 09 3b 69 c2 1f f8 03 78 1b 13 57 ca 92 96 eb |..;i....x..W....|
+00000070 f8 71 30 09 5a 68 01 47 96 b1 5b 7d b7 57 5e 70 |.q0.Zh.G..[}.W^p|
+00000080 00 77 bb 55 32 7b d9 a5 f7 e2 a8 6d 4b d6 be c6 |.w.U2{.....mK...|
00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
-000000a0 00 00 00 00 00 fd 36 99 3d c7 44 1b 30 39 4a a7 |......6.=.D.09J.|
-000000b0 40 43 e3 01 2b 22 3d c6 8c a1 0d 73 d5 16 d2 25 |@C..+"=....s...%|
-000000c0 19 c8 d7 76 ee |...v.|
+000000a0 00 00 00 00 00 58 1e a0 14 82 8d e4 c5 92 35 79 |.....X........5y|
+000000b0 3b 5e 3a fe 97 18 db 27 19 7e b5 14 8c 01 fb 6a |;^:....'.~.....j|
+000000c0 e4 26 96 e6 de |.&...|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM
index a6e7a079a75..4e52915ac5f 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM
@@ -1,86 +1,79 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 83 01 00 00 7f 03 03 19 c7 02 a0 bf |................|
-00000010 5a fb c2 d4 f5 68 0a 19 0f 5e 3a 6b c5 88 17 0b |Z....h...^:k....|
-00000020 35 ff df ee 06 32 ad 32 99 0e c9 00 00 04 c0 2f |5....2.2......./|
-00000030 00 ff 02 01 00 00 51 00 0b 00 04 03 00 01 02 00 |......Q.........|
-00000040 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 18 00 |................|
-00000050 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 0a 00 |................|
-00000060 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 05 |.. .............|
-00000070 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 02 |................|
-00000080 02 02 03 00 0f 00 01 01 |........|
+00000000 16 03 01 00 73 01 00 00 6f 03 03 4e 1a d7 67 e4 |....s...o..N..g.|
+00000010 d1 11 85 bc 62 59 da 8f ea d0 a0 2b 9b d3 47 aa |....bY.....+..G.|
+00000020 d0 39 6f 3f 42 dc 7c 16 bb 25 ef 00 00 04 c0 2f |.9o?B.|..%...../|
+00000030 00 ff 01 00 00 42 00 0b 00 04 03 00 01 02 00 0a |.....B..........|
+00000040 00 0a 00 08 00 1d 00 17 00 19 00 18 00 0d 00 20 |............... |
+00000050 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 |................|
+00000060 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 |................|
+00000070 00 16 00 00 00 17 00 00 |........|
>>> 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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002b0 cd 0c 00 00 c9 03 00 17 41 04 1e 18 37 ef 0d 19 |........A...7...|
-000002c0 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..|
-000002d0 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..|
-000002e0 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.|
-000002f0 b5 68 1a 41 03 56 6b dc 5a 89 05 01 00 80 97 53 |.h.A.Vk.Z......S|
-00000300 cc 1f a2 55 e2 52 69 a6 b3 78 4f 7e 34 3e 37 e4 |...U.Ri..xO~4>7.|
-00000310 e0 bb 15 ff 96 f8 1d 9c 11 03 2c 68 ca 6d 2b 3c |..........,h.m+<|
-00000320 b3 96 64 21 d6 3f 81 42 07 c0 1b 85 7e a9 65 54 |..d!.?.B....~.eT|
-00000330 23 89 33 c1 71 b9 29 72 47 8a 0e 71 75 20 d7 b6 |#.3.q.)rG..qu ..|
-00000340 9d c2 ac c1 a8 dc 6c 0e 7e 29 93 fc b2 68 83 2e |......l.~)...h..|
-00000350 e1 fe e5 eb 54 d7 c3 30 f2 8f 9d 91 49 48 4f 84 |....T..0....IHO.|
-00000360 1a d5 47 75 27 bf c8 09 65 4a a8 7c 65 a0 d0 23 |..Gu'...eJ.|e..#|
-00000370 9f 26 d6 57 62 cb e1 06 64 90 16 73 1b d4 16 03 |.&.Wb...d..s....|
-00000380 03 00 04 0e 00 00 00 |.......|
+00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 ac 0c 00 00 a8 03 00 1d |;...............|
+000002a0 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 | /.}.G.bC.(.._.)|
+000002b0 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b |.0.........._X.;|
+000002c0 74 05 01 00 80 b2 49 30 60 b7 0c 48 cb 9f 1c 75 |t.....I0`..H...u|
+000002d0 a6 b0 b0 7b 5e e6 f9 bc 5a 49 d4 51 e2 76 4c 01 |...{^...ZI.Q.vL.|
+000002e0 55 bd 37 cf 86 75 4f 33 9b fd 3c fc bb da 81 a9 |U.7..uO3..<.....|
+000002f0 26 7b 82 31 c5 51 0f d4 e8 fa a3 16 45 19 c8 40 |&{.1.Q......E..@|
+00000300 23 fa 32 bc 05 36 fb a7 a2 d9 6f e7 bc b8 27 0b |#.2..6....o...'.|
+00000310 2a 9e 7b 95 fd b4 c0 2e f0 73 fe fb a2 ea 20 a2 |*.{......s.... .|
+00000320 73 73 96 c8 bc 82 58 09 84 fc f4 09 2a c8 68 cb |ss....X.....*.h.|
+00000330 66 b0 de 2c 78 7a d4 ec 06 f1 1c 52 03 5a 69 24 |f..,xz.....R.Zi$|
+00000340 c4 e6 bb 68 f4 16 03 03 00 04 0e 00 00 00 |...h..........|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 1a 94 a7 1a 36 |....F...BA.....6|
-00000010 d1 ca ad d7 e8 64 03 84 b4 a6 9f dc 30 a2 a3 60 |.....d......0..`|
-00000020 a0 5a 1f a0 3d 8e d1 b8 96 75 37 ee a6 3f d6 ad |.Z..=....u7..?..|
-00000030 93 b6 7d 58 99 53 04 4b 6e c6 7f 04 bf 60 f9 ba |..}X.S.Kn....`..|
-00000040 e7 b8 04 73 10 77 ff 22 93 b2 7b 14 03 03 00 01 |...s.w."..{.....|
-00000050 01 16 03 03 00 28 29 6b 2b 14 21 a7 e4 84 c0 9d |.....()k+.!.....|
-00000060 92 07 cd dd 0b eb c1 b0 76 06 71 48 46 93 b8 05 |........v.qHF...|
-00000070 1a 2b 53 14 da 34 ac 05 4c cc 4d 47 12 28 |.+S..4..L.MG.(|
+00000000 16 03 03 00 25 10 00 00 21 20 41 d4 8d 53 2e 47 |....%...! A..S.G|
+00000010 b8 35 ba 86 3c 41 07 2e c1 a0 9d c2 e9 11 d8 20 |.5..<A......... |
+00000020 a1 fa 0a ff 28 64 5b af c3 67 14 03 03 00 01 01 |....(d[..g......|
+00000030 16 03 03 00 28 78 fd 19 36 4d a7 ca ab ba 06 6b |....(x..6M.....k|
+00000040 3f a5 79 17 2f 2b ec f6 19 db 17 1a 52 ea 72 0b |?.y./+......R.r.|
+00000050 01 af 56 8b 14 8f 8a 04 f3 ff ea fe 33 |..V.........3|
>>> 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 b9 c9 6f cb 58 df 1c a1 0a 79 4e fa 8f |.....o.X....yN..|
-00000020 41 55 8a 0a f8 d1 83 88 28 fb 44 00 8a a5 11 39 |AU......(.D....9|
-00000030 5b d4 83 17 03 03 00 25 00 00 00 00 00 00 00 01 |[......%........|
-00000040 85 4f 2a 54 aa c0 ce 7b 1e 4e e4 64 56 57 68 5e |.O*T...{.N.dVWh^|
-00000050 fa 41 67 8a da 9d f4 78 a6 c6 13 76 7c 15 03 03 |.Ag....x...v|...|
-00000060 00 1a 00 00 00 00 00 00 00 02 38 71 21 c6 82 bc |..........8q!...|
-00000070 2e 37 14 1d 15 2f 74 9d 7c 99 d8 66 |.7.../t.|..f|
+00000010 00 00 00 ec 99 e0 9a 83 28 94 e6 72 4f be 28 24 |........(..rO.($|
+00000020 64 bd 9d 86 79 cc ab 05 15 39 06 6e da 0c b8 4e |d...y....9.n...N|
+00000030 6c a9 f3 17 03 03 00 25 00 00 00 00 00 00 00 01 |l......%........|
+00000040 9a d7 b0 54 dd 3c ae 8e 3f 1f 41 68 a5 01 a0 da |...T.<..?.Ah....|
+00000050 e8 8e 90 55 1a 11 f0 70 8d a3 af a4 29 15 03 03 |...U...p....)...|
+00000060 00 1a 00 00 00 00 00 00 00 02 a8 96 cb 16 d7 b1 |................|
+00000070 41 7e bc 0e 01 8f cc 47 40 e5 c7 2a |A~.....G@..*|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384 b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384
index cc94ac745c1..36be9da0d08 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384
@@ -1,86 +1,79 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 83 01 00 00 7f 03 03 55 9b 71 e2 46 |...........U.q.F|
-00000010 88 58 c4 16 6a 6e 14 3d 3a 5a f9 fe ec 68 71 24 |.X..jn.=:Z...hq$|
-00000020 d0 06 6f a1 56 8f d6 15 42 6b ba 00 00 04 c0 30 |..o.V...Bk.....0|
-00000030 00 ff 02 01 00 00 51 00 0b 00 04 03 00 01 02 00 |......Q.........|
-00000040 0a 00 1c 00 1a 00 17 00 19 00 1c 00 1b 00 18 00 |................|
-00000050 1a 00 16 00 0e 00 0d 00 0b 00 0c 00 09 00 0a 00 |................|
-00000060 0d 00 20 00 1e 06 01 06 02 06 03 05 01 05 02 05 |.. .............|
-00000070 03 04 01 04 02 04 03 03 01 03 02 03 03 02 01 02 |................|
-00000080 02 02 03 00 0f 00 01 01 |........|
+00000000 16 03 01 00 73 01 00 00 6f 03 03 b7 d2 dc fe 53 |....s...o......S|
+00000010 d6 13 08 19 be 30 22 17 db a7 06 9b 62 82 14 38 |.....0".....b..8|
+00000020 2e 68 70 08 02 7d 22 64 13 75 f5 00 00 04 c0 30 |.hp..}"d.u.....0|
+00000030 00 ff 01 00 00 42 00 0b 00 04 03 00 01 02 00 0a |.....B..........|
+00000040 00 0a 00 08 00 1d 00 17 00 19 00 18 00 0d 00 20 |............... |
+00000050 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 |................|
+00000060 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 |................|
+00000070 00 16 00 00 00 17 00 00 |........|
>>> 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 30 00 00 |.............0..|
-00000030 05 ff 01 00 01 00 16 03 03 02 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002b0 cd 0c 00 00 c9 03 00 17 41 04 1e 18 37 ef 0d 19 |........A...7...|
-000002c0 51 88 35 75 71 b5 e5 54 5b 12 2e 8f 09 67 fd a7 |Q.5uq..T[....g..|
-000002d0 24 20 3e b2 56 1c ce 97 28 5e f8 2b 2d 4f 9e f1 |$ >.V...(^.+-O..|
-000002e0 07 9f 6c 4b 5b 83 56 e2 32 42 e9 58 b6 d7 49 a6 |..lK[.V.2B.X..I.|
-000002f0 b5 68 1a 41 03 56 6b dc 5a 89 05 01 00 80 7f 44 |.h.A.Vk.Z......D|
-00000300 af 7b 21 01 6b f0 1c 75 d3 6b 28 99 68 e1 0e d3 |.{!.k..u.k(.h...|
-00000310 a8 cb 5a 2e 23 ad d7 92 73 46 5b 66 88 bd f1 d6 |..Z.#...sF[f....|
-00000320 5d 52 d1 07 53 88 9c 64 e3 ce 80 b3 39 7f 9e 2b |]R..S..d....9..+|
-00000330 0a 02 a7 e1 3e 00 70 51 3b b4 52 d1 3c 4a e9 f7 |....>.pQ;.R.<J..|
-00000340 0f 85 fa ff d7 ba 96 fc 77 8e 66 8d c6 4c b8 c2 |........w.f..L..|
-00000350 a5 d3 ad 72 f0 8c ba d2 bf 1c 81 7b 4e d5 9e 80 |...r.......{N...|
-00000360 7e b2 90 a0 2f d6 ad c2 33 43 da 46 b0 22 40 ff |~.../...3C.F."@.|
-00000370 df 95 b3 1e f1 97 b9 7b 61 3c 78 d9 ae cb 16 03 |.......{a<x.....|
-00000380 03 00 04 0e 00 00 00 |.......|
+00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 ac 0c 00 00 a8 03 00 1d |;...............|
+000002a0 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 | /.}.G.bC.(.._.)|
+000002b0 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b |.0.........._X.;|
+000002c0 74 05 01 00 80 b8 c4 6a be 2a dd 47 03 7b 84 72 |t......j.*.G.{.r|
+000002d0 0b a4 c0 a7 2e b5 a4 be c7 6a 2a 8b d0 23 6f b5 |.........j*..#o.|
+000002e0 bc 0e ba 3c f5 9d a3 90 b0 af 80 11 bd 22 b5 7b |...<.........".{|
+000002f0 3c 53 f8 54 d0 b4 b0 53 28 75 0d 15 58 88 c2 90 |<S.T...S(u..X...|
+00000300 69 ea e0 08 aa 07 93 15 ae ed e5 a8 3d 2d 9c 62 |i...........=-.b|
+00000310 1d 40 26 7d 0e d3 23 52 71 71 ff ea 18 f9 0a eb |.@&}..#Rqq......|
+00000320 78 8a 8f 9e 12 8c 0b 33 a8 ee 42 76 16 29 58 ec |x......3..Bv.)X.|
+00000330 ea 6d 22 48 0d d0 68 c3 97 8d e9 ec cd 10 f6 47 |.m"H..h........G|
+00000340 c9 9d 42 12 54 16 03 03 00 04 0e 00 00 00 |..B.T.........|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 46 10 00 00 42 41 04 d8 85 85 d2 78 |....F...BA.....x|
-00000010 27 a5 0a bb 10 67 ec a9 d8 11 f0 ba b9 d7 21 39 |'....g........!9|
-00000020 ed c7 0a a0 a2 69 ab fb 9b 15 e0 d7 ec ca 97 c8 |.....i..........|
-00000030 c0 b2 66 0b 2c 68 37 ac f0 34 fa 3a 07 dd f2 ae |..f.,h7..4.:....|
-00000040 8e f6 e3 eb de 08 1f 56 e5 66 eb 14 03 03 00 01 |.......V.f......|
-00000050 01 16 03 03 00 28 f5 2d 89 00 0c 9d d9 0e 54 1b |.....(.-......T.|
-00000060 71 84 4d c7 bb 98 36 8c 29 b6 06 d8 7b df d9 92 |q.M...6.)...{...|
-00000070 01 00 16 44 5e e3 db f3 8f b7 fa 43 0c f7 |...D^......C..|
+00000000 16 03 03 00 25 10 00 00 21 20 20 df 4a b8 02 4f |....%...! .J..O|
+00000010 31 db 22 90 59 57 20 23 e1 72 8d 28 60 b3 f2 77 |1.".YW #.r.(`..w|
+00000020 db 3a ce 64 5a a5 63 94 be 09 14 03 03 00 01 01 |.:.dZ.c.........|
+00000030 16 03 03 00 28 de 72 f3 c3 b2 aa b4 9b b7 fe 35 |....(.r........5|
+00000040 3b 25 af 74 47 d3 49 39 07 d9 70 37 30 d0 b7 47 |;%.tG.I9..p70..G|
+00000050 bf ad 97 08 44 59 a7 3c 12 f2 4a 2d 7c |....DY.<..J-||
>>> 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 a4 82 dc d1 67 ed 17 ae 22 13 0d ac d2 |.......g..."....|
-00000020 f4 58 44 5b b4 c6 25 29 80 b6 bc 63 0e 67 22 6e |.XD[..%)...c.g"n|
-00000030 18 92 48 17 03 03 00 25 00 00 00 00 00 00 00 01 |..H....%........|
-00000040 a0 fe 37 25 fb 4d 29 96 f9 01 67 19 d8 83 26 68 |..7%.M)...g...&h|
-00000050 d0 e8 58 2c ef 90 a3 b5 26 51 26 a9 28 15 03 03 |..X,....&Q&.(...|
-00000060 00 1a 00 00 00 00 00 00 00 02 91 4b d5 54 4a ef |...........K.TJ.|
-00000070 22 88 ab b7 a2 bb 20 5a b2 3e 7b 36 |"..... Z.>{6|
+00000010 00 00 00 16 18 e1 e8 d4 c0 d1 19 3a 50 10 85 fc |...........:P...|
+00000020 fc 3e 27 54 e4 57 b6 e7 c4 25 d5 4e 10 ad 0f ff |.>'T.W...%.N....|
+00000030 ad 45 8c 17 03 03 00 25 00 00 00 00 00 00 00 01 |.E.....%........|
+00000040 50 b8 af 5f a2 3e 0f f7 f0 81 1f 32 69 39 2f f2 |P.._.>.....2i9/.|
+00000050 47 28 80 fb d0 46 d4 b7 a2 ba e3 71 ea 15 03 03 |G(...F.....q....|
+00000060 00 1a 00 00 00 00 00 00 00 02 c4 64 7a 81 b3 3a |...........dz..:|
+00000070 2c 71 35 ec f7 0c 52 36 20 2c eb fe |,q5...R6 ,..|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4 b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4
index c55f891866d..e49d1bcbbc4 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-RSA-RC4
@@ -1,73 +1,72 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 5b 01 00 00 57 03 03 ec 96 78 51 74 |....[...W....xQt|
-00000010 1b f2 21 ad f2 4f 50 aa 67 f1 20 e2 4f d3 4d 0e |..!..OP.g. .O.M.|
-00000020 54 91 df 91 d8 81 e3 75 bb 20 c2 00 00 04 00 05 |T......u. ......|
-00000030 00 ff 02 01 00 00 29 00 0d 00 20 00 1e 06 01 06 |......)... .....|
-00000040 02 06 03 05 01 05 02 05 03 04 01 04 02 04 03 03 |................|
-00000050 01 03 02 03 03 02 01 02 02 02 03 00 0f 00 01 01 |................|
+00000000 16 03 01 00 5d 01 00 00 59 03 03 55 3e 1a 3f cc |....]...Y..U>.?.|
+00000010 14 18 07 db 5e 97 15 33 62 9d de 56 7b ea 52 bf |....^..3b..V{.R.|
+00000020 a3 ce c2 75 3f 52 0a 2f 3e 99 07 00 00 04 00 05 |...u?R./>.......|
+00000030 00 ff 01 00 00 2c 00 0d 00 20 00 1e 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 00 16 00 00 00 17 |................|
+00000060 00 00 |..|
>>> 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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002b0 04 0e 00 00 00 |.....|
+00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 05 4b 04 74 76 |............K.tv|
-00000010 73 3a 92 04 4d 8b 3b 59 c2 43 c5 f4 07 e8 bc a3 |s:..M.;Y.C......|
-00000020 62 44 b7 80 9f 8f bc 43 8a 67 09 64 a7 93 9f f9 |bD.....C.g.d....|
-00000030 2c 55 03 4b e5 87 9d 18 a2 c3 48 4f 02 6e e0 23 |,U.K......HO.n.#|
-00000040 0b 2f 57 81 e4 38 50 11 d6 b1 71 4f c2 e5 a4 03 |./W..8P...qO....|
-00000050 34 a4 eb a1 42 47 79 05 bc 7b b8 26 5b c1 f9 82 |4...BGy..{.&[...|
-00000060 fc 58 49 eb 04 52 fe 57 3c ed 5c 2b d8 fe 49 d7 |.XI..R.W<.\+..I.|
-00000070 d2 2e 6c e8 74 74 0d 87 b3 f6 2d f0 ff 03 f0 2d |..l.tt....-....-|
-00000080 c8 a2 20 89 3f 3f 11 e1 fb 93 85 14 03 03 00 01 |.. .??..........|
-00000090 01 16 03 03 00 24 9a 81 c0 9e 76 b6 3d 78 37 8e |.....$....v.=x7.|
-000000a0 ab 33 48 93 bb 0d f4 86 3c ff 72 28 10 35 c2 10 |.3H.....<.r(.5..|
-000000b0 f0 a0 ff 0c 20 f3 c4 29 83 a6 |.... ..)..|
+00000000 16 03 03 00 86 10 00 00 82 00 80 a7 55 0a e7 33 |............U..3|
+00000010 8e be 5a 3a b4 f4 06 6e fc 0e 42 6e f3 0c 01 5a |..Z:...n..Bn...Z|
+00000020 65 73 36 bd cd be 0f 65 2f d2 88 1a f0 5e f8 07 |es6....e/....^..|
+00000030 c1 fe 5f 5f d6 f5 fa 79 24 44 0d 33 4f e6 74 88 |..__...y$D.3O.t.|
+00000040 86 f1 76 84 29 b4 f2 ae eb 9b 00 a2 6a e4 97 58 |..v.).......j..X|
+00000050 8b 2e 04 8f 8f 5e fe b4 9d 38 1d 8d 40 a4 9b a2 |.....^...8..@...|
+00000060 17 50 8a e5 39 c9 e9 41 3e 0d 9c 42 2c 7a 88 bf |.P..9..A>..B,z..|
+00000070 f7 09 4e 27 0b fe cc 53 13 07 d5 7e 0e e6 02 3c |..N'...S...~...<|
+00000080 8a 3f f9 03 df b6 65 a0 77 ee 50 14 03 03 00 01 |.?....e.w.P.....|
+00000090 01 16 03 03 00 24 5f 41 3e 38 05 08 74 62 5b 4e |.....$_A>8..tb[N|
+000000a0 94 55 98 74 5c 65 1a 4c 49 08 1d 77 d7 f0 12 47 |.U.t\e.LI..w...G|
+000000b0 d2 ef a6 31 5c 36 03 b5 b5 9d |...1\6....|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 93 15 62 c5 2b |..........$..b.+|
-00000010 4f 8a d7 0f 70 1f 9d 11 fc 8f 9a a9 b7 d7 44 50 |O...p.........DP|
-00000020 6e 0e 5b d7 3b de 15 7d 17 35 31 42 1f a4 40 17 |n.[.;..}.51B..@.|
-00000030 03 03 00 21 a9 ca 73 e9 ce 2d 21 ef 7d bc 40 91 |...!..s..-!.}.@.|
-00000040 41 c9 53 62 af 09 8e b4 37 0f fa ab b7 76 8f 5b |A.Sb....7....v.[|
-00000050 7d 0f 04 48 49 15 03 03 00 16 76 b1 d7 91 88 6f |}..HI.....v....o|
-00000060 b4 e7 a4 f1 d2 c2 ac 50 db 31 ae 5c f7 53 a1 68 |.......P.1.\.S.h|
+00000000 14 03 03 00 01 01 16 03 03 00 24 6f 68 a2 c0 4d |..........$oh..M|
+00000010 f4 cb c0 e5 8b 19 f9 2e 46 c3 3b 92 eb a9 42 8b |........F.;...B.|
+00000020 03 4a e2 62 9d f1 c0 39 b1 63 61 08 15 b0 ca 17 |.J.b...9.ca.....|
+00000030 03 03 00 21 50 9e 16 ce 7e af 8f 43 d1 1c 30 37 |...!P...~..C..07|
+00000040 85 e9 68 3a 9c 7e 26 90 dc 14 b1 ec 91 20 2b 4a |..h:.~&...... +J|
+00000050 24 b4 fa b1 50 15 03 03 00 16 59 74 08 41 73 01 |$...P.....Yt.As.|
+00000060 22 19 0b 35 6b 4d ee d2 15 50 42 de cc cf cc 09 |"..5kM...PB.....|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-Resume b/libgo/go/crypto/tls/testdata/Server-TLSv12-Resume
index 521376cedd2..366ca8f75d9 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-Resume
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-Resume
@@ -1,37 +1,41 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 f7 01 00 00 f3 03 03 35 70 0b ed 1c |...........5p...|
-00000010 83 57 b1 7b 0a 47 ce d4 07 3a 49 96 93 4c a1 83 |.W.{.G...:I..L..|
-00000020 4b ab b7 ab 7d b0 14 be dd 91 92 20 09 34 b7 de |K...}...... .4..|
-00000030 bd 43 e8 cd 8e f3 43 aa 04 64 8f 0a 55 a6 58 ed |.C....C..d..U.X.|
-00000040 31 8b 3d 4c 84 4f 2c 6d b0 b1 75 6f 00 04 00 05 |1.=L.O,m..uo....|
-00000050 00 ff 02 01 00 00 a5 00 23 00 78 50 46 ad c1 db |........#.xPF...|
-00000060 a8 38 86 7b 2b bb fd d0 c3 42 3e 00 00 00 00 00 |.8.{+....B>.....|
-00000070 00 00 00 00 00 00 00 00 00 00 00 94 6f 2c b5 83 |............o,..|
-00000080 61 4d 51 5f 33 46 48 fe 9e e9 83 f4 b1 aa c9 b1 |aMQ_3FH.........|
-00000090 61 2a b2 9d 0f 17 c4 09 f6 26 7a 75 f1 19 99 db |a*.......&zu....|
-000000a0 36 d8 32 f0 94 61 4f 8f ed 80 33 51 f3 c6 15 84 |6.2..aO...3Q....|
-000000b0 6b 33 94 c8 4f 84 b7 7c 27 6d 8f fe 41 8e b2 92 |k3..O..|'m..A...|
-000000c0 ca 80 e8 6c ba 75 77 f5 3a 87 17 ae f8 b9 6b 10 |...l.uw.:.....k.|
-000000d0 f9 85 da 00 0d 00 20 00 1e 06 01 06 02 06 03 05 |...... .........|
-000000e0 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 |................|
-000000f0 03 02 01 02 02 02 03 00 0f 00 01 01 |............|
+00000000 16 03 01 00 f9 01 00 00 f5 03 03 23 77 58 99 0e |...........#wX..|
+00000010 44 ed 63 44 e4 e4 eb d1 83 c3 9c d0 24 12 a3 b9 |D.cD........$...|
+00000020 55 6b 4d da bf 84 9d 35 de 43 a0 20 7b 93 cb d3 |UkM....5.C. {...|
+00000030 c5 ce 5e d5 aa 48 91 a4 b2 c2 d7 72 09 0d 21 78 |..^..H.....r..!x|
+00000040 f0 ac 7a ed 9a a9 ad dd 51 8b b2 1c 00 04 00 2f |..z.....Q....../|
+00000050 00 ff 01 00 00 a8 00 23 00 78 50 46 ad c1 db a8 |.......#.xPF....|
+00000060 38 86 7b 2b bb fd d0 c3 42 3e 00 00 00 00 00 00 |8.{+....B>......|
+00000070 00 00 00 00 00 00 00 00 00 00 94 6f 2c 9f 83 61 |...........o,..a|
+00000080 0b b1 b7 9e 10 2d 0c 56 e8 70 66 ad de b1 15 74 |.....-.V.pf....t|
+00000090 2f 8b 08 8c 96 bb 4b 1b 4e dd 81 0e bf 84 4d 43 |/.....K.N.....MC|
+000000a0 8f c0 7e a0 7f be c0 59 bf 83 26 0f a2 22 52 2c |..~....Y..&.."R,|
+000000b0 33 94 5a 77 54 f3 b5 f2 22 51 d5 24 c2 60 c3 2e |3.ZwT..."Q.$.`..|
+000000c0 0f 9c 5e 33 3b e8 7c 52 2a 76 08 58 ac 47 98 bc |..^3;.|R*v.X.G..|
+000000d0 36 b6 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 |6.... ..........|
+000000e0 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................|
+000000f0 02 01 02 02 02 03 00 16 00 00 00 17 00 00 |..............|
>>> 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 09 34 b7 de |........... .4..|
-00000030 bd 43 e8 cd 8e f3 43 aa 04 64 8f 0a 55 a6 58 ed |.C....C..d..U.X.|
-00000040 31 8b 3d 4c 84 4f 2c 6d b0 b1 75 6f 00 05 00 00 |1.=L.O,m..uo....|
+00000020 00 00 00 00 00 00 00 00 00 00 00 20 7b 93 cb d3 |........... {...|
+00000030 c5 ce 5e d5 aa 48 91 a4 b2 c2 d7 72 09 0d 21 78 |..^..H.....r..!x|
+00000040 f0 ac 7a ed 9a a9 ad dd 51 8b b2 1c 00 2f 00 00 |..z.....Q..../..|
00000050 05 ff 01 00 01 00 14 03 03 00 01 01 16 03 03 00 |................|
-00000060 24 18 67 37 5a c6 ea 3f 5f 06 2d c3 f1 2a ff d3 |$.g7Z..?_.-..*..|
-00000070 45 ce fe 38 1a e6 39 25 e7 e5 01 4d 6e fd 23 af |E..8..9%...Mn.#.|
-00000080 dc 67 1b 1d e2 |.g...|
+00000060 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |@...............|
+00000070 00 ac d9 95 88 c6 37 e8 3c 24 d8 d9 15 46 25 c6 |......7.<$...F%.|
+00000080 32 0c 75 80 11 3d 89 53 1c 7a b1 78 6a c1 1a d7 |2.u..=.S.z.xj...|
+00000090 91 6e c2 55 99 84 11 43 cd 62 99 3b 28 1b 2e 08 |.n.U...C.b.;(...|
+000000a0 a8 |.|
>>> Flow 3 (client to server)
-00000000 14 03 03 00 01 01 16 03 03 00 24 b5 75 e6 1d 1d |..........$.u...|
-00000010 cb 2c 5d 9f d1 07 de 23 11 84 c2 59 50 55 72 27 |.,]....#...YPUr'|
-00000020 f2 5e 34 e2 c1 53 bf 21 5f f4 c4 2c f1 e1 7a |.^4..S.!_..,..z|
+00000000 14 03 03 00 01 01 16 03 03 00 40 67 fd 43 2a 0b |..........@g.C*.|
+00000010 14 6b 89 53 84 a8 04 62 d6 30 af 68 eb 8e 2a de |.k.S...b.0.h..*.|
+00000020 67 c9 40 af 8b ac dd 29 a4 20 e4 da b0 dd c3 05 |g.@....). ......|
+00000030 82 83 8f 75 77 db 6c fe e7 20 54 e3 eb 51 31 68 |...uw.l.. T..Q1h|
+00000040 da 11 a3 6d a1 34 d9 f5 d1 ef c9 |...m.4.....|
>>> Flow 4 (server to client)
-00000000 17 03 03 00 21 93 92 dd 07 a3 8f 3d 34 6d b8 94 |....!......=4m..|
-00000010 a7 6f 18 27 e7 cd 30 0a 08 4f b6 9b cb 43 93 27 |.o.'..0..O...C.'|
-00000020 b6 8b 83 ae d6 8a 15 03 03 00 16 68 a1 a4 f8 66 |...........h...f|
-00000030 8a c0 e7 d3 97 83 cb 35 94 84 7a e6 47 3c 97 8c |.......5..z.G<..|
-00000040 69 |i|
+00000000 17 03 03 00 40 00 00 00 00 00 00 00 00 00 00 00 |....@...........|
+00000010 00 00 00 00 00 ee e2 75 6f 78 b0 88 1a 8b 9b 91 |.......uox......|
+00000020 c9 8c 3b ae a5 93 71 12 55 66 f8 09 a5 1f 4b 1b |..;...q.Uf....K.|
+00000030 c2 fe 65 8b 3d d9 dc fa af dc 29 1b 83 da e0 6a |..e.=.....)....j|
+00000040 4b cd d0 dc 27 |K...'|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ResumeDisabled b/libgo/go/crypto/tls/testdata/Server-TLSv12-ResumeDisabled
index c3cd2efeb94..34748371cff 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-ResumeDisabled
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ResumeDisabled
@@ -1,83 +1,89 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 f7 01 00 00 f3 03 03 2b 89 3f 02 47 |...........+.?.G|
-00000010 f6 14 64 3b 64 08 84 6e 9c e1 c9 4d 4f 30 92 06 |..d;d..n...MO0..|
-00000020 d1 19 58 5d 93 30 41 4d a6 2c f6 20 53 3c e7 f4 |..X].0AM.,. S<..|
-00000030 23 7e 59 b1 32 c4 2d db 0b 6f ab 64 4a 72 c9 31 |#~Y.2.-..o.dJr.1|
-00000040 d9 b9 38 a8 b4 4e 0c 39 f8 f4 61 7a 00 04 00 05 |..8..N.9..az....|
-00000050 00 ff 02 01 00 00 a5 00 23 00 78 50 46 ad c1 db |........#.xPF...|
-00000060 a8 38 86 7b 2b bb fd d0 c3 42 3e 00 00 00 00 00 |.8.{+....B>.....|
-00000070 00 00 00 00 00 00 00 00 00 00 00 94 6f 2c b5 83 |............o,..|
-00000080 61 01 55 65 2a 95 38 d4 d5 5f 41 c1 45 e4 f8 4b |a.Ue*.8.._A.E..K|
-00000090 3b 08 44 df 0b 72 11 93 cd d4 ff 36 0f 4f 3a a9 |;.D..r.....6.O:.|
-000000a0 4c 9f ab c7 ae 88 97 bc 1e ff 2d 27 39 a8 82 84 |L.........-'9...|
-000000b0 ae 33 94 48 8b 1c 58 9d 60 65 3c 3f 17 9d 6a eb |.3.H..X.`e<?..j.|
-000000c0 50 cd 65 04 bb c7 28 c8 0d 57 44 52 e0 17 de df |P.e...(..WDR....|
-000000d0 f3 13 b1 00 0d 00 20 00 1e 06 01 06 02 06 03 05 |...... .........|
-000000e0 01 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 |................|
-000000f0 03 02 01 02 02 02 03 00 0f 00 01 01 |............|
+00000000 16 03 01 00 f9 01 00 00 f5 03 03 e8 59 b4 a7 b2 |............Y...|
+00000010 77 86 57 47 0d d7 7b 2b c1 a2 04 fd 8d 4d e4 f5 |w.WG..{+.....M..|
+00000020 be e2 65 8e 28 9a fe c3 19 fc 43 20 40 38 fb 60 |..e.(.....C @8.`|
+00000030 f8 2f 36 f4 85 1d ee f1 53 f2 90 cf 3c 58 36 cd |./6.....S...<X6.|
+00000040 bd 22 b4 0c 92 a9 17 56 f9 b4 dd 9b 00 04 00 2f |.".....V......./|
+00000050 00 ff 01 00 00 a8 00 23 00 78 50 46 ad c1 db a8 |.......#.xPF....|
+00000060 38 86 7b 2b bb fd d0 c3 42 3e 00 00 00 00 00 00 |8.{+....B>......|
+00000070 00 00 00 00 00 00 00 00 00 00 94 6f 2c 9f 83 61 |...........o,..a|
+00000080 2e fe 48 fe f6 bb 98 a0 6f b0 be 9e 86 d7 b2 f2 |..H.....o.......|
+00000090 67 c7 44 c7 3d e4 2b de d0 f4 d2 17 51 84 8e 7a |g.D.=.+.....Q..z|
+000000a0 a7 80 c4 65 14 f7 49 09 68 15 56 68 32 41 d1 6f |...e..I.h.Vh2A.o|
+000000b0 33 94 a1 3a c9 37 20 5d e6 b0 6f 37 0a 10 e3 28 |3..:.7 ]..o7...(|
+000000c0 e1 34 b6 6d e6 7a 44 24 7f 2f cf 1b ae dd 4c d0 |.4.m.zD$./....L.|
+000000d0 11 75 00 0d 00 20 00 1e 06 01 06 02 06 03 05 01 |.u... ..........|
+000000e0 05 02 05 03 04 01 04 02 04 03 03 01 03 02 03 03 |................|
+000000f0 02 01 02 02 02 03 00 16 00 00 00 17 00 00 |..............|
>>> 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 71 0b 00 02 6d 00 |..........q...m.|
-00000040 02 6a 00 02 67 30 82 02 63 30 82 01 cc a0 03 02 |.j..g0..c0......|
-00000050 01 02 02 09 00 a2 73 00 0c 81 00 cb f3 30 0d 06 |......s......0..|
-00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2b 31 17 |.*.H........0+1.|
-00000070 30 15 06 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 |0...U....Google |
-00000080 54 45 53 54 49 4e 47 31 10 30 0e 06 03 55 04 03 |TESTING1.0...U..|
-00000090 13 07 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 35 30 |..Go Root0...150|
-000000a0 31 30 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 |101000000Z..2501|
-000000b0 30 31 30 30 30 30 30 30 5a 30 26 31 17 30 15 06 |01000000Z0&1.0..|
-000000c0 03 55 04 0a 13 0e 47 6f 6f 67 6c 65 20 54 45 53 |.U....Google TES|
-000000d0 54 49 4e 47 31 0b 30 09 06 03 55 04 03 13 02 47 |TING1.0...U....G|
-000000e0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....|
-000000f0 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 af 87 |.......0........|
-00000100 88 f6 20 1b 95 65 6c 14 ab 44 05 af 3b 45 14 e3 |.. ..el..D..;E..|
-00000110 b7 6d fd 00 63 4d 95 7f fe 6a 62 35 86 c0 4a f9 |.m..cM...jb5..J.|
-00000120 18 7c f6 aa 25 5e 7a 64 31 66 00 ba f4 8e 92 af |.|..%^zd1f......|
-00000130 c7 6b d8 76 d4 f3 5f 41 cb 6e 56 15 97 1b 97 c1 |.k.v.._A.nV.....|
-00000140 3c 12 39 21 66 3d 2b 16 d1 bc db 1c c0 a7 da b7 |<.9!f=+.........|
-00000150 ca ad ba da cb d5 21 50 ec de 8d ab d1 6b 81 4b |......!P.....k.K|
-00000160 89 02 f3 c4 be c1 6c 89 b1 44 84 bd 21 d1 04 7d |......l..D..!..}|
-00000170 9d 16 4d f9 82 15 f6 ef fa d6 09 47 f2 fb 02 03 |..M........G....|
-00000180 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..|
-00000190 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%|
-000001a0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........|
-000001b0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...|
-000001c0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....|
-000001d0 10 12 50 8d 89 6f 1b d1 dc 54 4d 6e cb 69 5e 06 |..P..o...TMn.i^.|
-000001e0 f4 30 1b 06 03 55 1d 23 04 14 30 12 80 10 bf 3d |.0...U.#..0....=|
-000001f0 b6 a9 66 f2 b8 40 cf ea b4 03 78 48 1a 41 30 19 |..f..@....xH.A0.|
-00000200 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp|
-00000210 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H|
-00000220 86 f7 0d 01 01 0b 05 00 03 81 81 00 92 7c af 91 |.............|..|
-00000230 55 12 18 96 59 31 a6 48 40 d5 2d d5 ee bb 02 a0 |U...Y1.H@.-.....|
-00000240 f5 c2 1e 7c 9b b3 30 7d 3c dc 76 da 4f 3d c0 fa |...|..0}<.v.O=..|
-00000250 ae 2d 33 24 6b 03 7b 1b 67 59 11 21 b5 11 bc 77 |.-3$k.{.gY.!...w|
-00000260 b9 d9 e0 6e a8 2d 2e 35 fa 64 5f 22 3e 63 10 6b |...n.-.5.d_">c.k|
-00000270 be ff 14 86 6d 0d f0 15 31 a8 14 38 1e 3b 84 87 |....m...1..8.;..|
-00000280 2c cb 98 ed 51 76 b9 b1 4f dd db 9b 84 04 86 40 |,...Qv..O......@|
-00000290 fa 51 dd ba b4 8d eb e3 46 de 46 b9 4f 86 c7 f9 |.Q......F.F.O...|
-000002a0 a4 c2 41 34 ac cc f6 ea b0 ab 39 18 16 03 03 00 |..A4......9.....|
-000002b0 04 0e 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 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 ab d9 61 5e d3 |.............a^.|
-00000010 87 d7 eb 21 12 6f f9 61 dd 8b de 76 d7 14 70 2f |...!.o.a...v..p/|
-00000020 9c 0f 3c d4 4c 77 41 e2 ac 73 18 c3 0f 66 f2 b1 |..<.LwA..s...f..|
-00000030 fd 4b 1e d9 cb 5c 94 16 4d c2 98 f9 0d 55 f7 79 |.K...\..M....U.y|
-00000040 e2 8d 2c 87 96 e7 10 fb 78 fb ce 27 5d 9f ac 97 |..,.....x..']...|
-00000050 d6 54 6f 0c 78 dc 7b 2e 49 4c e2 42 24 b9 3d de |.To.x.{.IL.B$.=.|
-00000060 89 5f 1a 40 54 33 11 96 89 6f 59 25 5e 89 60 40 |._.@T3...oY%^.`@|
-00000070 83 8c 0e 92 0e 7d 68 9d 17 74 ba 39 e8 6f e3 43 |.....}h..t.9.o.C|
-00000080 44 80 e6 62 4b 35 43 21 5b eb 32 14 03 03 00 01 |D..bK5C![.2.....|
-00000090 01 16 03 03 00 24 77 1a b5 2c 88 d7 a6 83 f5 30 |.....$w..,.....0|
-000000a0 a0 c3 b4 45 a6 af 9b c2 ac 55 cf 73 4f a0 ba e5 |...E.....U.sO...|
-000000b0 2a be 9c 97 d2 d2 0b e9 95 0e |*.........|
+00000000 16 03 03 00 86 10 00 00 82 00 80 5e 04 66 f2 27 |...........^.f.'|
+00000010 99 3b f8 15 9f b8 4a ab 8c 32 10 0d 5b c9 5b 0b |.;....J..2..[.[.|
+00000020 04 69 dc 2b 9e bb 28 38 b6 a0 0f 32 ae 8c 96 64 |.i.+..(8...2...d|
+00000030 63 97 6b b6 63 94 45 84 03 28 d1 d8 85 2f a7 bb |c.k.c.E..(.../..|
+00000040 be ca 3e f5 30 27 e1 fd e5 cc bc b5 61 3d 26 8d |..>.0'......a=&.|
+00000050 0e 93 dd 78 07 5c fe 1b a9 57 c7 ce e6 df eb 28 |...x.\...W.....(|
+00000060 74 ce 12 f3 df 3f c0 9e 54 b6 e0 b0 ea f7 08 c6 |t....?..T.......|
+00000070 e1 9b cb e7 e9 41 b0 b4 68 2f f2 9b 1a 0a e3 17 |.....A..h/......|
+00000080 df d7 18 ff 95 ca 36 07 32 ff f9 14 03 03 00 01 |......6.2.......|
+00000090 01 16 03 03 00 40 cb c3 74 05 82 ab 93 07 a2 8b |.....@..t.......|
+000000a0 24 27 c0 21 3e d1 15 12 9a 85 20 5b f5 7e 7e 0a |$'.!>..... [.~~.|
+000000b0 a0 8e b2 de aa 25 2a b3 3d 12 1b 01 45 ec 36 53 |.....%*.=...E.6S|
+000000c0 32 1d 81 c7 1d a6 96 c2 a9 2e af fa 90 6e 76 bb |2............nv.|
+000000d0 a2 bc 43 91 c9 ca |..C...|
>>> Flow 4 (server to client)
-00000000 14 03 03 00 01 01 16 03 03 00 24 a9 ae 0c a5 ed |..........$.....|
-00000010 51 10 d9 14 71 41 40 bd be f5 44 98 11 2f d8 0f |Q...qA@...D../..|
-00000020 4d 42 bf 28 53 bf 02 7e d6 16 92 7f dd 03 ec 17 |MB.(S..~........|
-00000030 03 03 00 21 46 c2 68 a1 6a 35 67 e7 7d 62 71 43 |...!F.h.j5g.}bqC|
-00000040 6b ea d6 fc 22 fc 2d ad 45 d6 6d 98 9e e5 88 a0 |k...".-.E.m.....|
-00000050 ac 80 f7 6f 05 15 03 03 00 16 0c ae f4 fc 0e 09 |...o............|
-00000060 0b 09 73 69 83 0d 00 89 39 ff f6 20 4e 2b 88 3d |..si....9.. N+.=|
+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 7f 39 4c 83 d4 |............9L..|
+00000020 ca a2 7a a8 eb 3e 45 18 6e 33 3d 6f eb 2d 4f 72 |..z..>E.n3=o.-Or|
+00000030 35 ee c3 f8 22 fd 39 28 47 23 55 16 6c 47 80 b7 |5...".9(G#U.lG..|
+00000040 65 31 15 f6 89 79 96 bd 6a df 1d 17 03 03 00 40 |e1...y..j......@|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 0c ea 0d 87 9a 24 d5 cc 26 9a a2 32 df 04 24 7d |.....$..&..2..$}|
+00000070 45 ed 35 4e 5b a0 57 c1 c7 f1 0f 8b b0 f9 49 85 |E.5N[.W.......I.|
+00000080 d6 e6 36 26 d5 f3 e4 00 76 d0 d6 20 be b3 31 e5 |..6&....v.. ..1.|
+00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
+000000a0 00 00 00 00 00 6c 51 e9 c2 e8 4f 43 e2 ce 01 9d |.....lQ...OC....|
+000000b0 d9 6f d7 c7 bf 16 d9 28 ca 8a ea 5e d5 84 ba 55 |.o.....(...^...U|
+000000c0 b7 23 9d 79 28 |.#.y(|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI b/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI
index ae52ac2ae18..852cc63d03d 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI
@@ -1,64 +1,81 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 6f 01 00 00 6b 03 03 07 0f b6 b9 cc |....o...k.......|
-00000010 db 23 57 92 d0 9b 37 72 9d ad 9a 0d 17 6b dd b8 |.#W...7r.....k..|
-00000020 81 b7 7c 54 dd 68 fe 4e 28 00 39 00 00 04 00 2f |..|T.h.N(.9..../|
-00000030 00 ff 02 01 00 00 3d 00 00 00 10 00 0e 00 00 0b |......=.........|
-00000040 73 6e 69 74 65 73 74 2e 63 6f 6d 00 0d 00 20 00 |snitest.com... .|
-00000050 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 |................|
-00000060 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 |................|
-00000070 0f 00 01 01 |....|
+00000000 16 03 01 00 71 01 00 00 6d 03 03 35 8f 03 0b f4 |....q...m..5....|
+00000010 81 dd d7 ec 8b cc 85 bd 07 5b 83 16 cc 6e b2 67 |.........[...n.g|
+00000020 fd 33 69 81 14 9a 14 9d 37 43 5a 00 00 04 00 2f |.3i.....7CZ..../|
+00000030 00 ff 01 00 00 40 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 20 00 1e |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 00 16 |................|
+00000070 00 00 00 17 00 00 |......|
>>> 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 |....|
+00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 72 6a 6f a8 c9 |...........rjo..|
-00000010 3e 4c 33 da 92 23 97 68 fc 4e ca 74 77 98 f3 88 |>L3..#.h.N.tw...|
-00000020 ba a0 55 b6 a0 6f ff c8 db 2b 90 17 1f 45 bc 26 |..U..o...+...E.&|
-00000030 62 6e b9 91 96 b9 03 5d eb f2 a2 59 87 7b 81 4a |bn.....]...Y.{.J|
-00000040 0c f9 e2 23 60 e3 c7 4d 53 4f 3a 1f c5 5f dd 15 |...#`..MSO:.._..|
-00000050 cc 78 c5 21 fd 33 02 68 77 7c 8d 5f e8 80 a7 84 |.x.!.3.hw|._....|
-00000060 a7 2c b3 1f 64 df 8a 63 e9 b3 24 02 c1 6a 94 bd |.,..d..c..$..j..|
-00000070 a1 62 e5 32 e5 d9 83 25 0d 0f 1a 02 90 8a cd 79 |.b.2...%.......y|
-00000080 1c bd 4a c2 f4 5d a0 24 c6 c1 ae 14 03 03 00 01 |..J..].$........|
-00000090 01 16 03 03 00 40 1f 1a 17 47 15 25 5b 3d 5f e5 |.....@...G.%[=_.|
-000000a0 f4 d9 64 47 5f 80 09 f7 dd 5a ff 58 19 08 b5 db |..dG_....Z.X....|
-000000b0 38 88 a4 44 07 01 fb 80 1d 89 b2 d4 af 95 80 b3 |8..D............|
-000000c0 75 13 82 0e 24 12 1d 5c 29 72 1d 21 d4 69 16 e0 |u...$..\)r.!.i..|
-000000d0 b5 4b 46 62 fe f7 |.KFb..|
+00000000 16 03 03 00 86 10 00 00 82 00 80 4c 15 46 23 91 |...........L.F#.|
+00000010 a0 d8 6c 45 f0 49 7e 70 84 9f bf 53 3d 68 2c cc |..lE.I~p...S=h,.|
+00000020 20 3f 28 bd cf e6 6e fd e6 90 ff 87 14 82 65 00 | ?(...n.......e.|
+00000030 d6 b6 ef 5a 0c d6 30 76 88 d2 37 33 39 de 00 b4 |...Z..0v..739...|
+00000040 ec dd 30 3b f6 88 ff 4c b2 98 75 77 fd c3 61 38 |..0;...L..uw..a8|
+00000050 2d 00 f7 14 d8 a4 37 22 c0 db 8a bd 12 0b b8 cc |-.....7"........|
+00000060 37 82 78 d3 0e f2 0b 9b 51 c5 26 c5 e2 ce 3e 0e |7.x.....Q.&...>.|
+00000070 04 34 39 83 a8 f5 65 ff 40 d9 9b 4a 11 6b b3 d2 |.49...e.@..J.k..|
+00000080 f7 02 78 a9 7c f4 69 56 3a a4 98 14 03 03 00 01 |..x.|.iV:.......|
+00000090 01 16 03 03 00 40 d6 90 b3 07 d1 a1 c1 12 35 07 |.....@........5.|
+000000a0 4e c0 df 4b 17 cc fa 49 47 c9 22 c3 6f 70 fa ee |N..K...IG.".op..|
+000000b0 cf b3 61 d6 06 54 cd ce c2 15 17 8a a0 f6 5c 43 |..a..T........\C|
+000000c0 7c 92 ce 89 d4 96 53 d0 c7 e6 9a 24 bc 5a 83 e5 ||.....S....$.Z..|
+000000d0 9c 65 72 e7 80 a4 |.er...|
>>> Flow 4 (server to client)
-00000000 15 03 03 00 02 02 14 |.......|
+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 a0 61 69 4c 9d |............aiL.|
+00000020 68 f3 f8 f6 a0 ef 1b f4 a2 f5 83 fa 03 87 ad 67 |h..............g|
+00000030 7e 9f df c6 ce 9f 69 ce 22 fc de 91 0d 18 00 fb |~.....i.".......|
+00000040 c1 5d a1 2d bb 89 29 4f f6 de 57 17 03 03 00 40 |.].-..)O..W....@|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 bb 54 f4 80 69 1d 3b 9c e7 9c 1a fb 4e 3d c1 02 |.T..i.;.....N=..|
+00000070 d3 05 86 35 47 61 59 aa 45 54 ae a2 59 4c 75 8c |...5GaY.ET..YLu.|
+00000080 8d a9 7d 7f a0 4b d9 65 7a 53 ef 7e ed a3 fa 9e |..}..K.ezS.~....|
+00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
+000000a0 00 00 00 00 00 cc fd 0f cb 74 a5 36 ce c1 cd 54 |.........t.6...T|
+000000b0 6f 66 81 c0 ab ff 72 ea f3 1f a6 b7 ef 46 45 68 |of....r......FEh|
+000000c0 9b 0b 7f 4f 46 |...OF|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate b/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate
index 7ac8dc92a77..b35cd8de268 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate
@@ -1,64 +1,81 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 6f 01 00 00 6b 03 03 fe d6 ce b5 1b |....o...k.......|
-00000010 1c 50 0c db 9c 35 5d 0e f2 ee 57 3f 65 83 9f 28 |.P...5]...W?e..(|
-00000020 96 50 1c e0 7f 95 f9 17 39 4f c3 00 00 04 00 2f |.P......9O...../|
-00000030 00 ff 02 01 00 00 3d 00 00 00 10 00 0e 00 00 0b |......=.........|
-00000040 73 6e 69 74 65 73 74 2e 63 6f 6d 00 0d 00 20 00 |snitest.com... .|
-00000050 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 |................|
-00000060 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 |................|
-00000070 0f 00 01 01 |....|
+00000000 16 03 01 00 71 01 00 00 6d 03 03 31 c7 3f 2b 99 |....q...m..1.?+.|
+00000010 95 d8 d5 b7 91 ab 95 c6 09 35 0c 2b bd b6 94 1e |.........5.+....|
+00000020 64 4a 2d b6 43 23 a0 01 e7 93 22 00 00 04 00 2f |dJ-.C#...."..../|
+00000030 00 ff 01 00 00 40 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 20 00 1e |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 00 16 |................|
+00000070 00 00 00 17 00 00 |......|
>>> 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 |....|
+00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 6f bc 33 c8 2d |...........o.3.-|
-00000010 5a 50 65 2f 06 1a 45 16 9e 5b ab 97 43 b1 9e 96 |ZPe/..E..[..C...|
-00000020 b5 4a fe c3 7c e8 e4 07 ea 00 47 d2 51 23 11 ae |.J..|.....G.Q#..|
-00000030 11 a8 79 71 b9 c6 82 17 40 ae c7 fc cd 05 4d 6d |..yq....@.....Mm|
-00000040 cb bc f1 ce 30 d0 10 37 4a e6 aa d3 14 fb bc 62 |....0..7J......b|
-00000050 eb 6c fa ec e1 e1 dd 63 39 95 0b 87 71 a0 83 ba |.l.....c9...q...|
-00000060 bf 25 f8 a9 d3 c4 35 e1 88 23 85 56 c6 f4 0b 10 |.%....5..#.V....|
-00000070 d1 70 f8 0a 3d a1 08 17 ce 27 2d 4c a7 c5 b5 0d |.p..=....'-L....|
-00000080 f2 43 b7 b9 02 21 7a eb 40 d2 66 14 03 03 00 01 |.C...!z.@.f.....|
-00000090 01 16 03 03 00 40 0a 93 47 0b 6e 40 ff cd 09 a5 |.....@..G.n@....|
-000000a0 bc a4 c5 a8 c3 1c 0a fb d4 2e 8a 2f 0c f3 d6 e1 |.........../....|
-000000b0 de 1f 56 2f 09 61 2d 31 d5 b1 29 6b f2 18 8b f2 |..V/.a-1..)k....|
-000000c0 0c 0e 09 5f ec 11 56 af 44 8b e5 2d 09 68 eb c2 |..._..V.D..-.h..|
-000000d0 91 4d 04 b2 10 02 |.M....|
+00000000 16 03 03 00 86 10 00 00 82 00 80 c9 3a 9d ea e3 |............:...|
+00000010 19 f1 07 77 61 ef 5a aa ed 0f 26 b4 7a 45 db 05 |...wa.Z...&.zE..|
+00000020 bd 51 77 f5 ee 7b c1 83 9c 95 49 7b 70 5e 5b fe |.Qw..{....I{p^[.|
+00000030 25 d2 3d 64 74 b8 a4 97 fd cb b9 75 7b 8f b0 59 |%.=dt......u{..Y|
+00000040 30 bf b3 41 ce 54 83 0a ca 29 49 5a fe 29 4c 53 |0..A.T...)IZ.)LS|
+00000050 fb d6 6e 46 d9 f7 31 17 d6 ee f9 ac 41 82 22 11 |..nF..1.....A.".|
+00000060 a7 34 07 41 50 43 2f 83 f6 1f c6 c0 9d 4a 67 5a |.4.APC/......JgZ|
+00000070 af 44 59 c0 00 33 be 24 f7 0a a4 fe 76 6b 03 05 |.DY..3.$....vk..|
+00000080 2e ec 4d 49 db 6e e5 0a 5f af 09 14 03 03 00 01 |..MI.n.._.......|
+00000090 01 16 03 03 00 40 ad 89 4d 25 a2 ce 98 8c cf b6 |.....@..M%......|
+000000a0 f5 f4 76 6b e7 71 66 4a f9 a7 67 fb 1d 6c a7 83 |..vk.qfJ..g..l..|
+000000b0 3b 1d 6a af 65 f2 c1 1d 97 03 5b c2 34 ee 3b 8e |;.j.e.....[.4.;.|
+000000c0 cc bd 8f 3a b8 9b 4f 90 3f de 1e 97 1e 8e 61 37 |...:..O.?.....a7|
+000000d0 2d 30 35 84 3b 26 |-05.;&|
>>> Flow 4 (server to client)
-00000000 15 03 03 00 02 02 14 |.......|
+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 fe 23 de 33 4b |............#.3K|
+00000020 55 f2 8e 73 09 ba ae f1 12 bd f7 15 75 90 8f 19 |U..s........u...|
+00000030 1b 19 b6 3f 2c 19 47 87 a9 43 d5 1e 85 fb 0c 90 |...?,.G..C......|
+00000040 c8 18 72 8f 08 6f 48 43 3c 5c 5a 17 03 03 00 40 |..r..oHC<\Z....@|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 4d 44 d7 eb a3 94 00 74 90 9d c0 bd 8e 11 eb b6 |MD.....t........|
+00000070 93 43 c6 14 0d ba c2 aa f0 f5 2d 85 9a 7c 27 44 |.C........-..|'D|
+00000080 fc d8 46 76 b2 21 4f 70 1a 9a df 9e 3a 8f a3 58 |..Fv.!Op....:..X|
+00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
+000000a0 00 00 00 00 00 91 0f c3 2a 98 79 57 39 3c 68 98 |........*.yW9<h.|
+000000b0 df 36 12 de e5 15 ee cb 80 ce 33 d9 20 95 33 38 |.6........3. .38|
+000000c0 8b d8 ed 8f 9b |.....|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound b/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound
index 32c0d4a5456..8ba207b2539 100644
--- a/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound
@@ -1,64 +1,81 @@
>>> Flow 1 (client to server)
-00000000 16 03 01 00 6f 01 00 00 6b 03 03 64 29 6e 67 3d |....o...k..d)ng=|
-00000010 5a 13 48 8a ae a5 67 6b 2f 5b 76 d2 c1 df 23 c6 |Z.H...gk/[v...#.|
-00000020 f9 52 26 33 ce 0b 03 f6 53 a7 db 00 00 04 00 2f |.R&3....S....../|
-00000030 00 ff 02 01 00 00 3d 00 00 00 10 00 0e 00 00 0b |......=.........|
-00000040 73 6e 69 74 65 73 74 2e 63 6f 6d 00 0d 00 20 00 |snitest.com... .|
-00000050 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 04 |................|
-00000060 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 00 |................|
-00000070 0f 00 01 01 |....|
+00000000 16 03 01 00 71 01 00 00 6d 03 03 f8 16 6b 20 c3 |....q...m....k .|
+00000010 a4 cf fc ca 04 47 7a f9 cc d9 cf 4a 15 ff 6e 82 |.....Gz....J..n.|
+00000020 14 6a 91 91 7f f1 f4 42 e6 7c d4 00 00 04 00 2f |.j.....B.|...../|
+00000030 00 ff 01 00 00 40 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 20 00 1e |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 00 16 |................|
+00000070 00 00 00 17 00 00 |......|
>>> 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 |....|
+00000030 05 ff 01 00 01 00 16 03 03 02 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 04 0e 00 00 00 |;............|
>>> Flow 3 (client to server)
-00000000 16 03 03 00 86 10 00 00 82 00 80 7b 3b b8 73 f0 |...........{;.s.|
-00000010 78 2c 75 91 ee 4a ac 6e 9d 08 8e ef dd 52 fb 38 |x,u..J.n.....R.8|
-00000020 d7 6f b3 39 8a 8c 3c dc 4b e0 a9 2b 0b de 9a d6 |.o.9..<.K..+....|
-00000030 38 72 ae 0f 76 87 4b f6 45 17 f6 fa b2 5a 07 30 |8r..v.K.E....Z.0|
-00000040 5b ef e7 40 e0 95 98 bf 8d 8d 5e 7a 6a ea 2d 2e |[..@......^zj.-.|
-00000050 9c 99 e4 47 6b 4f 16 32 fb 0d a7 01 36 2e 06 f2 |...GkO.2....6...|
-00000060 65 74 b6 ed 07 51 60 7a 98 d6 77 36 f4 c7 f6 b1 |et...Q`z..w6....|
-00000070 f1 6a 3e 38 7c 79 5c c6 b4 53 5c 85 fb 0b 2c f9 |.j>8|y\..S\...,.|
-00000080 2c 60 97 c8 73 f7 22 ef 52 4c 10 14 03 03 00 01 |,`..s.".RL......|
-00000090 01 16 03 03 00 40 4c 73 6e 5e 66 9d 53 2e fa b7 |.....@Lsn^f.S...|
-000000a0 90 2d 52 55 13 d2 67 28 aa 1a 6f 62 42 ef 2f 4d |.-RU..g(..obB./M|
-000000b0 04 1d ef 64 8f 1a 70 c0 d0 bf 06 72 ee db 3e 43 |...d..p....r..>C|
-000000c0 7f ed 37 bb a1 62 0c c5 c8 a9 c0 51 8f 77 95 b3 |..7..b.....Q.w..|
-000000d0 72 7e 01 89 c4 32 |r~...2|
+00000000 16 03 03 00 86 10 00 00 82 00 80 80 e8 00 cc 09 |................|
+00000010 fc 87 20 9f 2a 38 33 6f cb 61 71 86 6d 55 6a 87 |.. .*83o.aq.mUj.|
+00000020 e0 22 78 62 4e 3b 98 5c 87 fd 3b 1c 73 d3 77 7e |."xbN;.\..;.s.w~|
+00000030 a4 c3 6f d4 6d 82 65 40 0e 70 2f 24 e9 7d ff 49 |..o.m.e@.p/$.}.I|
+00000040 c7 bd 45 44 af ae a5 7a 06 06 5e 1e ce 31 73 4b |..ED...z..^..1sK|
+00000050 4a 38 f0 11 ba 32 58 ab a5 94 12 13 30 83 95 85 |J8...2X.....0...|
+00000060 f5 7e 8d a7 cc 6d 19 14 f9 b0 dc 64 e5 4d b1 7d |.~...m.....d.M.}|
+00000070 e6 95 d4 4a 7f 85 11 5b a7 c9 32 84 c2 ec 2e c3 |...J...[..2.....|
+00000080 40 fe 5c e2 cf 5b 96 8a 72 9f 9f 14 03 03 00 01 |@.\..[..r.......|
+00000090 01 16 03 03 00 40 a8 d2 5b 24 28 2b 86 1e c1 2e |.....@..[$(+....|
+000000a0 6f da 7a ac 6b bf 02 ea 10 5d 9c 71 fb 19 eb 17 |o.z.k....].q....|
+000000b0 19 b2 07 7c b9 df d0 6d 9f 80 cf 37 a0 2a 18 c9 |...|...m...7.*..|
+000000c0 e9 b5 9f 94 42 6a 6b 33 55 fb 6d 94 3b 79 ed 26 |....Bjk3U.m.;y.&|
+000000d0 5c 5a 7f 68 2c d8 |\Z.h,.|
>>> Flow 4 (server to client)
-00000000 15 03 03 00 02 02 14 |.......|
+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 18 e9 b5 96 14 |................|
+00000020 38 98 d4 23 cd e5 32 0e 09 ae b3 3b 90 a4 4d c2 |8..#..2....;..M.|
+00000030 e5 a8 df 72 e8 97 0b 67 cb 87 f4 d0 3e 52 ca d1 |...r...g....>R..|
+00000040 28 94 ed 88 6c cb 62 53 b2 a1 04 17 03 03 00 40 |(...l.bS.......@|
+00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00000060 0e e3 b0 da 4b 19 ca 29 7b 1d c8 e3 0d d7 f2 97 |....K..){.......|
+00000070 b0 0b 6e f0 d2 4b f0 c4 ca 87 75 3c ae 66 e1 b3 |..n..K....u<.f..|
+00000080 06 e3 e6 90 54 fd 31 f7 5d 3b 6f de 0f d5 e4 09 |....T.1.];o.....|
+00000090 15 03 03 00 30 00 00 00 00 00 00 00 00 00 00 00 |....0...........|
+000000a0 00 00 00 00 00 ee a1 b0 94 b5 86 71 73 66 14 ac |...........qsf..|
+000000b0 5c 4e 1b 67 27 af db b6 e3 44 15 38 b1 f5 e0 13 |\N.g'....D.8....|
+000000c0 a5 e1 82 c0 6a |....j|
diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-X25519-ECDHE-RSA-AES-GCM b/libgo/go/crypto/tls/testdata/Server-TLSv12-X25519-ECDHE-RSA-AES-GCM
new file mode 100644
index 00000000000..89587e9b8dc
--- /dev/null
+++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-X25519-ECDHE-RSA-AES-GCM
@@ -0,0 +1,79 @@
+>>> Flow 1 (client to server)
+00000000 16 03 01 00 73 01 00 00 6f 03 03 33 6d f4 4a 4b |....s...o..3m.JK|
+00000010 48 35 ef 62 e9 bd 66 90 7e 73 62 bf 93 51 3d 90 |H5.b..f.~sb..Q=.|
+00000020 9e f1 17 ae bd 24 28 54 44 50 8e 00 00 04 c0 2f |.....$(TDP...../|
+00000030 00 ff 01 00 00 42 00 0b 00 04 03 00 01 02 00 0a |.....B..........|
+00000040 00 0a 00 08 00 1d 00 17 00 19 00 18 00 0d 00 20 |............... |
+00000050 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 |................|
+00000060 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 |................|
+00000070 00 16 00 00 00 17 00 00 |........|
+>>> 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 59 0b 00 02 55 00 |..........Y...U.|
+00000040 02 52 00 02 4f 30 82 02 4b 30 82 01 b4 a0 03 02 |.R..O0..K0......|
+00000050 01 02 02 09 00 e8 f0 9d 3f e2 5b ea a6 30 0d 06 |........?.[..0..|
+00000060 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 1f 31 0b |.*.H........0.1.|
+00000070 30 09 06 03 55 04 0a 13 02 47 6f 31 10 30 0e 06 |0...U....Go1.0..|
+00000080 03 55 04 03 13 07 47 6f 20 52 6f 6f 74 30 1e 17 |.U....Go Root0..|
+00000090 0d 31 36 30 31 30 31 30 30 30 30 30 30 5a 17 0d |.160101000000Z..|
+000000a0 32 35 30 31 30 31 30 30 30 30 30 30 5a 30 1a 31 |250101000000Z0.1|
+000000b0 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 0b 30 09 |.0...U....Go1.0.|
+000000c0 06 03 55 04 03 13 02 47 6f 30 81 9f 30 0d 06 09 |..U....Go0..0...|
+000000d0 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00 30 |*.H............0|
+000000e0 81 89 02 81 81 00 db 46 7d 93 2e 12 27 06 48 bc |.......F}...'.H.|
+000000f0 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 45 88 7a 36 |.(!.~...]..RE.z6|
+00000100 47 a5 08 0d 92 42 5b c2 81 c0 be 97 79 98 40 fb |G....B[.....y.@.|
+00000110 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 d4 09 9e d6 |Om..+.....g.....|
+00000120 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 93 e5 96 d9 |"8.J.ts+.4......|
+00000130 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 d9 2b 2b 24 |t{.X.la<..A..++$|
+00000140 23 77 5b 1c 3b bd 75 5d ce 20 54 cf a1 63 87 1d |#w[.;.u]. T..c..|
+00000150 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 ed 97 a7 75 |.$....P....C...u|
+00000160 62 f4 14 c8 52 d7 02 03 01 00 01 a3 81 93 30 81 |b...R.........0.|
+00000170 90 30 0e 06 03 55 1d 0f 01 01 ff 04 04 03 02 05 |.0...U..........|
+00000180 a0 30 1d 06 03 55 1d 25 04 16 30 14 06 08 2b 06 |.0...U.%..0...+.|
+00000190 01 05 05 07 03 01 06 08 2b 06 01 05 05 07 03 02 |........+.......|
+000001a0 30 0c 06 03 55 1d 13 01 01 ff 04 02 30 00 30 19 |0...U.......0.0.|
+000001b0 06 03 55 1d 0e 04 12 04 10 9f 91 16 1f 43 43 3e |..U..........CC>|
+000001c0 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 03 55 1d 23 |I..m....`0...U.#|
+000001d0 04 14 30 12 80 10 48 13 49 4d 13 7e 16 31 bb a3 |..0...H.IM.~.1..|
+000001e0 01 d5 ac ab 6e 7b 30 19 06 03 55 1d 11 04 12 30 |....n{0...U....0|
+000001f0 10 82 0e 65 78 61 6d 70 6c 65 2e 67 6f 6c 61 6e |...example.golan|
+00000200 67 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |g0...*.H........|
+00000210 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 61 cb ba e5 |.....0.@+[P.a...|
+00000220 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 95 a1 ac 31 |SX...(.X..8....1|
+00000230 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 df d3 20 64 |Z..f=C.-...... d|
+00000240 38 92 24 3a 00 bc cf 9c 7d b7 40 20 01 5f aa d3 |8.$:....}.@ ._..|
+00000250 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c ee b1 87 82 |.a..v......\....|
+00000260 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c f1 0f a1 d8 |.l..s..Cw.......|
+00000270 40 83 61 c9 4c 72 2b 9d ae db 46 06 06 4d f4 c1 |@.a.Lr+...F..M..|
+00000280 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 84 5c 21 d3 |.>...B...=.`.\!.|
+00000290 3b e9 fa e7 16 03 03 00 ac 0c 00 00 a8 03 00 1d |;...............|
+000002a0 20 2f e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 | /.}.G.bC.(.._.)|
+000002b0 07 30 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b |.0.........._X.;|
+000002c0 74 05 01 00 80 61 aa 96 74 97 9f 2a 81 df 73 4d |t....a..t..*..sM|
+000002d0 58 fb 8b 34 d9 51 02 1d 30 45 98 11 fa 20 cc 48 |X..4.Q..0E... .H|
+000002e0 18 8d 92 4a bc bf 34 c2 52 cc 7b 7d 93 32 f9 98 |...J..4.R.{}.2..|
+000002f0 eb d0 6d 58 4c 24 71 f1 78 cc ee 4d f8 26 26 d3 |..mXL$q.x..M.&&.|
+00000300 b0 1c 46 67 ff 75 fc b5 b3 75 31 f3 9d d6 51 07 |..Fg.u...u1...Q.|
+00000310 7a c1 2f 52 3f 88 23 f2 90 74 d0 77 6d 2b c7 31 |z./R?.#..t.wm+.1|
+00000320 3d 81 a8 b9 84 a6 8f 96 25 91 e8 31 3b e9 20 b8 |=.......%..1;. .|
+00000330 c4 11 68 da 58 0a ee 79 de fe 32 29 d6 24 b0 56 |..h.X..y..2).$.V|
+00000340 ab e8 b5 57 fc 16 03 03 00 04 0e 00 00 00 |...W..........|
+>>> Flow 3 (client to server)
+00000000 16 03 03 00 25 10 00 00 21 20 eb 0e 38 40 3f 32 |....%...! ..8@?2|
+00000010 a4 95 fb c4 de e5 82 9a 4b 46 37 de 29 e5 6b e6 |........KF7.).k.|
+00000020 44 bf f0 af 0c 62 19 bd 5c 0e 14 03 03 00 01 01 |D....b..\.......|
+00000030 16 03 03 00 28 67 ad 91 f6 8d 8a 39 f7 f2 a6 42 |....(g.....9...B|
+00000040 f2 8c 2f 1d b3 1d dd f1 88 65 7e 66 d2 d9 70 09 |../......e~f..p.|
+00000050 4e 12 90 0d 0b d5 a5 a6 20 bc 32 63 05 |N....... .2c.|
+>>> 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 56 b1 b8 16 9a 27 c6 ee d4 7f b7 68 83 |...V....'.....h.|
+00000020 43 3b 04 92 ec cc c7 db 82 f8 7d 04 64 1d 55 cf |C;........}.d.U.|
+00000030 02 69 ac 17 03 03 00 25 00 00 00 00 00 00 00 01 |.i.....%........|
+00000040 d6 69 51 5d 3b 00 93 c2 a6 19 97 7d bf a9 d9 96 |.iQ];......}....|
+00000050 43 1d ae 32 c3 52 1a f0 18 ba 10 4c e0 15 03 03 |C..2.R.....L....|
+00000060 00 1a 00 00 00 00 00 00 00 02 1e 8a 5e 37 c0 b1 |............^7..|
+00000070 0d 1e c9 6a 90 23 d6 4c 5c 47 5b bf |...j.#.L\G[.|
diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go
index 8eef884a0f1..f2e5aea2bce 100644
--- a/libgo/go/crypto/tls/tls.go
+++ b/libgo/go/crypto/tls/tls.go
@@ -5,7 +5,7 @@
// Package tls partially implements TLS 1.2, as specified in RFC 5246.
package tls
-// BUG(agl): The crypto/tls package does not implement countermeasures
+// BUG(agl): The crypto/tls package only implements some countermeasures
// against Lucky13 attacks on CBC-mode encryption. See
// http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and
// https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
@@ -102,7 +102,7 @@ func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*
timeout := dialer.Timeout
if !dialer.Deadline.IsZero() {
- deadlineTimeout := dialer.Deadline.Sub(time.Now())
+ deadlineTimeout := time.Until(dialer.Deadline)
if timeout == 0 || deadlineTimeout < timeout {
timeout = deadlineTimeout
}
@@ -135,7 +135,7 @@ func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*
// from the hostname we're connecting to.
if config.ServerName == "" {
// Make a copy to avoid polluting argument or default.
- c := config.clone()
+ c := config.Clone()
c.ServerName = hostname
config = c
}
diff --git a/libgo/go/crypto/tls/tls_test.go b/libgo/go/crypto/tls/tls_test.go
index 48b46a003a6..8933f4f2015 100644
--- a/libgo/go/crypto/tls/tls_test.go
+++ b/libgo/go/crypto/tls/tls_test.go
@@ -11,6 +11,7 @@ import (
"fmt"
"internal/testenv"
"io"
+ "io/ioutil"
"math"
"math/rand"
"net"
@@ -98,6 +99,7 @@ var keyPairTests = []struct {
}
func TestX509KeyPair(t *testing.T) {
+ t.Parallel()
var pem []byte
for _, test := range keyPairTests {
pem = []byte(test.cert + test.key)
@@ -241,7 +243,7 @@ func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
srvCh <- nil
return
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
serr = fmt.Errorf("handshake: %v", err)
@@ -251,7 +253,7 @@ func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
srvCh <- srv
}()
- clientConfig := testConfig.clone()
+ clientConfig := testConfig.Clone()
conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil {
t.Fatal(err)
@@ -293,18 +295,20 @@ func TestTLSUniqueMatches(t *testing.T) {
for i := 0; i < 2; i++ {
sconn, err := ln.Accept()
if err != nil {
- t.Fatal(err)
+ t.Error(err)
+ return
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
- t.Fatal(err)
+ t.Error(err)
+ return
}
serverTLSUniques <- srv.ConnectionState().TLSUnique
}
}()
- clientConfig := testConfig.clone()
+ clientConfig := testConfig.Clone()
clientConfig.ClientSessionCache = NewLRUClientSessionCache(1)
conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
if err != nil {
@@ -394,7 +398,7 @@ func TestConnCloseBreakingWrite(t *testing.T) {
srvCh <- nil
return
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
serr = fmt.Errorf("handshake: %v", err)
@@ -414,7 +418,7 @@ func TestConnCloseBreakingWrite(t *testing.T) {
Conn: cconn,
}
- clientConfig := testConfig.clone()
+ clientConfig := testConfig.Clone()
tconn := Client(conn, clientConfig)
if err := tconn.Handshake(); err != nil {
t.Fatal(err)
@@ -458,6 +462,112 @@ func TestConnCloseBreakingWrite(t *testing.T) {
}
}
+func TestConnCloseWrite(t *testing.T) {
+ ln := newLocalListener(t)
+ defer ln.Close()
+
+ clientDoneChan := make(chan struct{})
+
+ serverCloseWrite := func() error {
+ sconn, err := ln.Accept()
+ if err != nil {
+ return fmt.Errorf("accept: %v", err)
+ }
+ defer sconn.Close()
+
+ serverConfig := testConfig.Clone()
+ srv := Server(sconn, serverConfig)
+ if err := srv.Handshake(); err != nil {
+ return fmt.Errorf("handshake: %v", err)
+ }
+ defer srv.Close()
+
+ data, err := ioutil.ReadAll(srv)
+ if err != nil {
+ return err
+ }
+ if len(data) > 0 {
+ return fmt.Errorf("Read data = %q; want nothing", data)
+ }
+
+ if err := srv.CloseWrite(); err != nil {
+ return fmt.Errorf("server CloseWrite: %v", err)
+ }
+
+ // Wait for clientCloseWrite to finish, so we know we
+ // tested the CloseWrite before we defer the
+ // sconn.Close above, which would also cause the
+ // client to unblock like CloseWrite.
+ <-clientDoneChan
+ return nil
+ }
+
+ clientCloseWrite := func() error {
+ defer close(clientDoneChan)
+
+ clientConfig := testConfig.Clone()
+ conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
+ if err != nil {
+ return err
+ }
+ if err := conn.Handshake(); err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ if err := conn.CloseWrite(); err != nil {
+ return fmt.Errorf("client CloseWrite: %v", err)
+ }
+
+ if _, err := conn.Write([]byte{0}); err != errShutdown {
+ return fmt.Errorf("CloseWrite error = %v; want errShutdown", err)
+ }
+
+ data, err := ioutil.ReadAll(conn)
+ if err != nil {
+ return err
+ }
+ if len(data) > 0 {
+ return fmt.Errorf("Read data = %q; want nothing", data)
+ }
+ return nil
+ }
+
+ errChan := make(chan error, 2)
+
+ go func() { errChan <- serverCloseWrite() }()
+ go func() { errChan <- clientCloseWrite() }()
+
+ for i := 0; i < 2; i++ {
+ select {
+ case err := <-errChan:
+ if err != nil {
+ t.Fatal(err)
+ }
+ case <-time.After(10 * time.Second):
+ t.Fatal("deadlock")
+ }
+ }
+
+ // Also test CloseWrite being called before the handshake is
+ // finished:
+ {
+ ln2 := newLocalListener(t)
+ defer ln2.Close()
+
+ netConn, err := net.Dial("tcp", ln2.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer netConn.Close()
+ conn := Client(netConn, testConfig.Clone())
+
+ if err := conn.CloseWrite(); err != errEarlyCloseWrite {
+ t.Errorf("CloseWrite error = %v; want errEarlyCloseWrite", err)
+ }
+ }
+}
+
func TestClone(t *testing.T) {
var c1 Config
v := reflect.ValueOf(&c1).Elem()
@@ -477,12 +587,12 @@ func TestClone(t *testing.T) {
case "Rand":
f.Set(reflect.ValueOf(io.Reader(os.Stdin)))
continue
- case "Time", "GetCertificate":
+ case "Time", "GetCertificate", "GetConfigForClient", "VerifyPeerCertificate", "GetClientCertificate":
// DeepEqual can't compare functions.
continue
case "Certificates":
f.Set(reflect.ValueOf([]Certificate{
- {Certificate: [][]byte{[]byte{'b'}}},
+ {Certificate: [][]byte{{'b'}}},
}))
continue
case "NameToCertificate":
@@ -494,6 +604,10 @@ func TestClone(t *testing.T) {
case "ClientSessionCache":
f.Set(reflect.ValueOf(NewLRUClientSessionCache(10)))
continue
+ case "KeyLogWriter":
+ f.Set(reflect.ValueOf(io.Writer(os.Stdout)))
+ continue
+
}
q, ok := quick.Value(f.Type(), rnd)
@@ -503,7 +617,11 @@ func TestClone(t *testing.T) {
f.Set(q)
}
- c2 := c1.clone()
+ c2 := c1.Clone()
+ // DeepEqual also compares unexported fields, thus c2 needs to have run
+ // serverInit in order to be DeepEqual to c1. Cloning it and discarding
+ // the result is sufficient.
+ c2.Clone()
if !reflect.DeepEqual(&c1, c2) {
t.Errorf("clone failed to copy a field")
@@ -551,7 +669,8 @@ func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool
// (cannot call b.Fatal in goroutine)
panic(fmt.Errorf("accept: %v", err))
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
+ serverConfig.CipherSuites = nil // the defaults may prefer faster ciphers
serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
srv := Server(sconn, serverConfig)
if err := srv.Handshake(); err != nil {
@@ -564,7 +683,8 @@ func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool
}()
b.SetBytes(totalBytes)
- clientConfig := testConfig.clone()
+ clientConfig := testConfig.Clone()
+ clientConfig.CipherSuites = nil // the defaults may prefer faster ciphers
clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
buf := make([]byte, bufsize)
@@ -641,7 +761,7 @@ func latency(b *testing.B, bps int, dynamicRecordSizingDisabled bool) {
// (cannot call b.Fatal in goroutine)
panic(fmt.Errorf("accept: %v", err))
}
- serverConfig := testConfig.clone()
+ serverConfig := testConfig.Clone()
serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
srv := Server(&slowConn{sconn, bps}, serverConfig)
if err := srv.Handshake(); err != nil {
@@ -651,7 +771,7 @@ func latency(b *testing.B, bps int, dynamicRecordSizingDisabled bool) {
}
}()
- clientConfig := testConfig.clone()
+ clientConfig := testConfig.Clone()
clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
buf := make([]byte, 16384)
diff --git a/libgo/go/crypto/x509/cert_pool.go b/libgo/go/crypto/x509/cert_pool.go
index 59ab8871054..fea33df379a 100644
--- a/libgo/go/crypto/x509/cert_pool.go
+++ b/libgo/go/crypto/x509/cert_pool.go
@@ -4,11 +4,7 @@
package x509
-import (
- "encoding/pem"
- "errors"
- "runtime"
-)
+import "encoding/pem"
// CertPool is a set of certificates.
type CertPool struct {
@@ -30,9 +26,6 @@ func NewCertPool() *CertPool {
// Any mutations to the returned pool are not written to disk and do
// not affect any other pool.
func SystemCertPool() (*CertPool, error) {
- if runtime.GOOS == "windows" {
- return nil, errors.New("crypto/x509: system root pool is not available on Windows")
- }
return loadSystemRoots()
}
@@ -64,6 +57,21 @@ func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCer
return
}
+func (s *CertPool) contains(cert *Certificate) bool {
+ if s == nil {
+ return false
+ }
+
+ candidates := s.byName[string(cert.RawSubject)]
+ for _, c := range candidates {
+ if s.certs[c].Equal(cert) {
+ return true
+ }
+ }
+
+ return false
+}
+
// AddCert adds a certificate to a pool.
func (s *CertPool) AddCert(cert *Certificate) {
if cert == nil {
@@ -71,10 +79,8 @@ func (s *CertPool) AddCert(cert *Certificate) {
}
// Check that the certificate isn't being added twice.
- for _, c := range s.certs {
- if c.Equal(cert) {
- return
- }
+ if s.contains(cert) {
+ return
}
n := len(s.certs)
diff --git a/libgo/go/crypto/x509/pkix/pkix.go b/libgo/go/crypto/x509/pkix/pkix.go
index faad4061fc7..39fd78df596 100644
--- a/libgo/go/crypto/x509/pkix/pkix.go
+++ b/libgo/go/crypto/x509/pkix/pkix.go
@@ -64,34 +64,36 @@ func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
if len(rdn) == 0 {
continue
}
- atv := rdn[0]
- n.Names = append(n.Names, atv)
- value, ok := atv.Value.(string)
- if !ok {
- continue
- }
- t := atv.Type
- if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 {
- switch t[3] {
- case 3:
- n.CommonName = value
- case 5:
- n.SerialNumber = value
- case 6:
- n.Country = append(n.Country, value)
- case 7:
- n.Locality = append(n.Locality, value)
- case 8:
- n.Province = append(n.Province, value)
- case 9:
- n.StreetAddress = append(n.StreetAddress, value)
- case 10:
- n.Organization = append(n.Organization, value)
- case 11:
- n.OrganizationalUnit = append(n.OrganizationalUnit, value)
- case 17:
- n.PostalCode = append(n.PostalCode, value)
+ for _, atv := range rdn {
+ n.Names = append(n.Names, atv)
+ value, ok := atv.Value.(string)
+ if !ok {
+ continue
+ }
+
+ t := atv.Type
+ if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 {
+ switch t[3] {
+ case 3:
+ n.CommonName = value
+ case 5:
+ n.SerialNumber = value
+ case 6:
+ n.Country = append(n.Country, value)
+ case 7:
+ n.Locality = append(n.Locality, value)
+ case 8:
+ n.Province = append(n.Province, value)
+ case 9:
+ n.StreetAddress = append(n.StreetAddress, value)
+ case 10:
+ n.Organization = append(n.Organization, value)
+ case 11:
+ n.OrganizationalUnit = append(n.OrganizationalUnit, value)
+ case 17:
+ n.PostalCode = append(n.PostalCode, value)
+ }
}
}
}
diff --git a/libgo/go/crypto/x509/root_cgo_darwin.go b/libgo/go/crypto/x509/root_cgo_darwin.go
index a4b33c7660e..8e805335904 100644
--- a/libgo/go/crypto/x509/root_cgo_darwin.go
+++ b/libgo/go/crypto/x509/root_cgo_darwin.go
@@ -7,7 +7,7 @@
package x509
/*
-#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1060
+#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1080
#cgo LDFLAGS: -framework CoreFoundation -framework Security
#include <errno.h>
@@ -73,10 +73,11 @@ int useOldCode() {
//
// 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.
+// Additionally, it fills untrustedPemRoots with certs that must be removed from pemRoots.
//
-// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after
-// we've consumed its content.
-int FetchPEMRoots(CFDataRef *pemRoots) {
+// Note: The CFDataRef returned in pemRoots and untrustedPemRoots must
+// be released (using CFRelease) after we've consumed its content.
+int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) {
if (useOldCode()) {
return FetchPEMRoots_MountainLion(pemRoots);
}
@@ -93,23 +94,69 @@ int FetchPEMRoots(CFDataRef *pemRoots) {
return -1;
}
+ // kSecTrustSettingsResult is defined as CFSTR("kSecTrustSettingsResult"),
+ // but the Go linker's internal linking mode can't handle CFSTR relocations.
+ // Create our own dynamic string instead and release it below.
+ CFStringRef policy = CFStringCreateWithCString(NULL, "kSecTrustSettingsResult", kCFStringEncodingUTF8);
+
CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
+ CFMutableDataRef combinedUntrustedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
for (int i = 0; i < numDomains; i++) {
CFArrayRef certs = NULL;
- // Only get certificates from domain that are trusted
OSStatus err = SecTrustSettingsCopyCertificates(domains[i], &certs);
if (err != noErr) {
continue;
}
- int numCerts = CFArrayGetCount(certs);
+ CFIndex numCerts = CFArrayGetCount(certs);
for (int j = 0; j < numCerts; j++) {
CFDataRef data = NULL;
CFErrorRef errRef = NULL;
+ CFArrayRef trustSettings = NULL;
SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, j);
if (cert == NULL) {
continue;
}
+ // We only want trusted certs.
+ int untrusted = 0;
+ if (i != 0) {
+ // Certs found in the system domain are always trusted. If the user
+ // configures "Never Trust" on such a cert, it will also be found in the
+ // admin or user domain, causing it to be added to untrustedPemRoots. The
+ // Go code will then clean this up.
+
+ // Trust may be stored in any of the domains. According to Apple's
+ // SecTrustServer.c, "user trust settings overrule admin trust settings",
+ // so take the last trust settings array we find.
+ // Skip the system domain since it is always trusted.
+ for (int k = 1; k < numDomains; k++) {
+ CFArrayRef domainTrustSettings = NULL;
+ err = SecTrustSettingsCopyTrustSettings(cert, domains[k], &domainTrustSettings);
+ if (err == errSecSuccess && domainTrustSettings != NULL) {
+ if (trustSettings) {
+ CFRelease(trustSettings);
+ }
+ trustSettings = domainTrustSettings;
+ }
+ }
+ if (trustSettings == NULL) {
+ // "this certificate must be verified to a known trusted certificate"; aka not a root.
+ continue;
+ }
+ for (CFIndex k = 0; k < CFArrayGetCount(trustSettings); k++) {
+ CFNumberRef cfNum;
+ CFDictionaryRef tSetting = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, k);
+ if (CFDictionaryGetValueIfPresent(tSetting, policy, (const void**)&cfNum)){
+ SInt32 result = 0;
+ CFNumberGetValue(cfNum, kCFNumberSInt32Type, &result);
+ // TODO: The rest of the dictionary specifies conditions for evaluation.
+ if (result == kSecTrustSettingsResultDeny) {
+ untrusted = 1;
+ }
+ }
+ }
+ CFRelease(trustSettings);
+ }
// We only want to add Root CAs, so make sure Subject and Issuer Name match
CFDataRef subjectName = SecCertificateCopyNormalizedSubjectContent(cert, &errRef);
if (errRef != NULL) {
@@ -138,13 +185,16 @@ int FetchPEMRoots(CFDataRef *pemRoots) {
}
if (data != NULL) {
- CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
+ CFMutableDataRef appendTo = untrusted ? combinedUntrustedData : combinedData;
+ CFDataAppendBytes(appendTo, CFDataGetBytePtr(data), CFDataGetLength(data));
CFRelease(data);
}
}
CFRelease(certs);
}
+ CFRelease(policy);
*pemRoots = combinedData;
+ *untrustedPemRoots = combinedUntrustedData;
return 0;
}
*/
@@ -158,7 +208,8 @@ func loadSystemRoots() (*CertPool, error) {
roots := NewCertPool()
var data C.CFDataRef = nil
- err := C.FetchPEMRoots(&data)
+ var untrustedData C.CFDataRef = nil
+ err := C.FetchPEMRoots(&data, &untrustedData)
if err == -1 {
// TODO: better error message
return nil, errors.New("crypto/x509: failed to load darwin system roots with cgo")
@@ -167,5 +218,19 @@ func loadSystemRoots() (*CertPool, error) {
defer C.CFRelease(C.CFTypeRef(data))
buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
roots.AppendCertsFromPEM(buf)
- return roots, nil
+ if untrustedData == nil {
+ return roots, nil
+ }
+ defer C.CFRelease(C.CFTypeRef(untrustedData))
+ buf = C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(untrustedData)), C.int(C.CFDataGetLength(untrustedData)))
+ untrustedRoots := NewCertPool()
+ untrustedRoots.AppendCertsFromPEM(buf)
+
+ trustedRoots := NewCertPool()
+ for _, c := range roots.certs {
+ if !untrustedRoots.contains(c) {
+ trustedRoots.AddCert(c)
+ }
+ }
+ return trustedRoots, nil
}
diff --git a/libgo/go/crypto/x509/root_darwin.go b/libgo/go/crypto/x509/root_darwin.go
index 78de56c2215..66cdb5ea261 100644
--- a/libgo/go/crypto/x509/root_darwin.go
+++ b/libgo/go/crypto/x509/root_darwin.go
@@ -6,20 +6,239 @@
package x509
-import "os/exec"
+import (
+ "bufio"
+ "bytes"
+ "crypto/sha1"
+ "encoding/pem"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+ "sync"
+)
+
+var debugExecDarwinRoots = strings.Contains(os.Getenv("GODEBUG"), "x509roots=1")
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
return nil, nil
}
+// This code is only used when compiling without cgo.
+// It is here, instead of root_nocgo_darwin.go, so that tests can check it
+// even if the tests are run with cgo enabled.
+// The linker will not include these unused functions in binaries built with cgo enabled.
+
+// execSecurityRoots finds the macOS list of trusted root certificates
+// using only command-line tools. This is our fallback path when cgo isn't available.
+//
+// The strategy is as follows:
+//
+// 1. Run "security trust-settings-export" and "security
+// trust-settings-export -d" to discover the set of certs with some
+// user-tweaked trust policy. We're too lazy to parse the XML (at
+// least at this stage of Go 1.8) to understand what the trust
+// policy actually is. We just learn that there is _some_ policy.
+//
+// 2. Run "security find-certificate" to dump the list of system root
+// CAs in PEM format.
+//
+// 3. For each dumped cert, conditionally verify it with "security
+// verify-cert" if that cert was in the set discovered in Step 1.
+// Without the Step 1 optimization, running "security verify-cert"
+// 150-200 times takes 3.5 seconds. With the optimization, the
+// whole process takes about 180 milliseconds with 1 untrusted root
+// CA. (Compared to 110ms in the cgo path)
func execSecurityRoots() (*CertPool, error) {
+ hasPolicy, err := getCertsWithTrustPolicy()
+ if err != nil {
+ return nil, err
+ }
+ if debugExecDarwinRoots {
+ println(fmt.Sprintf("crypto/x509: %d certs have a trust policy", len(hasPolicy)))
+ }
+
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
}
- roots := NewCertPool()
- roots.AppendCertsFromPEM(data)
+ var (
+ mu sync.Mutex
+ roots = NewCertPool()
+ numVerified int // number of execs of 'security verify-cert', for debug stats
+ )
+
+ blockCh := make(chan *pem.Block)
+ var wg sync.WaitGroup
+
+ // Using 4 goroutines to pipe into verify-cert seems to be
+ // about the best we can do. The verify-cert binary seems to
+ // just RPC to another server with coarse locking anyway, so
+ // running 16 at a time for instance doesn't help at all. Due
+ // to the "if hasPolicy" check below, though, we will rarely
+ // (or never) call verify-cert on stock macOS systems, though.
+ // The hope is that we only call verify-cert when the user has
+ // tweaked their trust policy. These 4 goroutines are only
+ // defensive in the pathological case of many trust edits.
+ for i := 0; i < 4; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for block := range blockCh {
+ cert, err := ParseCertificate(block.Bytes)
+ if err != nil {
+ continue
+ }
+ sha1CapHex := fmt.Sprintf("%X", sha1.Sum(block.Bytes))
+
+ valid := true
+ verifyChecks := 0
+ if hasPolicy[sha1CapHex] {
+ verifyChecks++
+ if !verifyCertWithSystem(block, cert) {
+ valid = false
+ }
+ }
+
+ mu.Lock()
+ numVerified += verifyChecks
+ if valid {
+ roots.AddCert(cert)
+ }
+ mu.Unlock()
+ }
+ }()
+ }
+ for len(data) > 0 {
+ var block *pem.Block
+ block, data = pem.Decode(data)
+ if block == nil {
+ break
+ }
+ if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
+ continue
+ }
+ blockCh <- block
+ }
+ close(blockCh)
+ wg.Wait()
+
+ if debugExecDarwinRoots {
+ mu.Lock()
+ defer mu.Unlock()
+ println(fmt.Sprintf("crypto/x509: ran security verify-cert %d times", numVerified))
+ }
+
return roots, nil
}
+
+func verifyCertWithSystem(block *pem.Block, cert *Certificate) bool {
+ data := pem.EncodeToMemory(block)
+
+ f, err := ioutil.TempFile("", "cert")
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "can't create temporary file for cert: %v", err)
+ return false
+ }
+ defer os.Remove(f.Name())
+ if _, err := f.Write(data); err != nil {
+ fmt.Fprintf(os.Stderr, "can't write temporary file for cert: %v", err)
+ return false
+ }
+ if err := f.Close(); err != nil {
+ fmt.Fprintf(os.Stderr, "can't write temporary file for cert: %v", err)
+ return false
+ }
+ cmd := exec.Command("/usr/bin/security", "verify-cert", "-c", f.Name(), "-l", "-L")
+ var stderr bytes.Buffer
+ if debugExecDarwinRoots {
+ cmd.Stderr = &stderr
+ }
+ if err := cmd.Run(); err != nil {
+ if debugExecDarwinRoots {
+ println(fmt.Sprintf("crypto/x509: verify-cert rejected %s: %q", cert.Subject.CommonName, bytes.TrimSpace(stderr.Bytes())))
+ }
+ return false
+ }
+ if debugExecDarwinRoots {
+ println(fmt.Sprintf("crypto/x509: verify-cert approved %s", cert.Subject.CommonName))
+ }
+ return true
+}
+
+// getCertsWithTrustPolicy returns the set of certs that have a
+// possibly-altered trust policy. The keys of the map are capitalized
+// sha1 hex of the raw cert.
+// They are the certs that should be checked against `security
+// verify-cert` to see whether the user altered the default trust
+// settings. This code is only used for cgo-disabled builds.
+func getCertsWithTrustPolicy() (map[string]bool, error) {
+ set := map[string]bool{}
+ td, err := ioutil.TempDir("", "x509trustpolicy")
+ if err != nil {
+ return nil, err
+ }
+ defer os.RemoveAll(td)
+ run := func(file string, args ...string) error {
+ file = filepath.Join(td, file)
+ args = append(args, file)
+ cmd := exec.Command("/usr/bin/security", args...)
+ var stderr bytes.Buffer
+ cmd.Stderr = &stderr
+ if err := cmd.Run(); err != nil {
+ // If there are no trust settings, the
+ // `security trust-settings-export` command
+ // fails with:
+ // exit status 1, SecTrustSettingsCreateExternalRepresentation: No Trust Settings were found.
+ // Rather than match on English substrings that are probably
+ // localized on macOS, just interpret any failure to mean that
+ // there are no trust settings.
+ if debugExecDarwinRoots {
+ println(fmt.Sprintf("crypto/x509: exec %q: %v, %s", cmd.Args, err, stderr.Bytes()))
+ }
+ return nil
+ }
+
+ f, err := os.Open(file)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ // Gather all the runs of 40 capitalized hex characters.
+ br := bufio.NewReader(f)
+ var hexBuf bytes.Buffer
+ for {
+ b, err := br.ReadByte()
+ isHex := ('A' <= b && b <= 'F') || ('0' <= b && b <= '9')
+ if isHex {
+ hexBuf.WriteByte(b)
+ } else {
+ if hexBuf.Len() == 40 {
+ set[hexBuf.String()] = true
+ }
+ hexBuf.Reset()
+ }
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+ }
+ if err := run("user", "trust-settings-export"); err != nil {
+ return nil, fmt.Errorf("dump-trust-settings (user): %v", err)
+ }
+ if err := run("admin", "trust-settings-export", "-d"); err != nil {
+ return nil, fmt.Errorf("dump-trust-settings (admin): %v", err)
+ }
+ return set, nil
+}
diff --git a/libgo/go/crypto/x509/root_linux.go b/libgo/go/crypto/x509/root_linux.go
index cfeca6958ca..38dd72d3ed6 100644
--- a/libgo/go/crypto/x509/root_linux.go
+++ b/libgo/go/crypto/x509/root_linux.go
@@ -6,8 +6,9 @@ package x509
// Possible certificate files; stop after finding one.
var certFiles = []string{
- "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
- "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL
- "/etc/ssl/ca-bundle.pem", // OpenSUSE
- "/etc/pki/tls/cacert.pem", // OpenELEC
+ "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
+ "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
+ "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
+ "/etc/ssl/ca-bundle.pem", // OpenSUSE
+ "/etc/pki/tls/cacert.pem", // OpenELEC
}
diff --git a/libgo/go/crypto/x509/root_windows.go b/libgo/go/crypto/x509/root_windows.go
index 392c869012d..ca2fba5cb42 100644
--- a/libgo/go/crypto/x509/root_windows.go
+++ b/libgo/go/crypto/x509/root_windows.go
@@ -225,4 +225,37 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
return chains, nil
}
-func loadSystemRoots() (*CertPool, error) { return nil, nil }
+func loadSystemRoots() (*CertPool, error) {
+ const CRYPT_E_NOT_FOUND = 0x80092004
+
+ store, err := syscall.CertOpenSystemStore(0, syscall.StringToUTF16Ptr("ROOT"))
+ if err != nil {
+ return nil, err
+ }
+ defer syscall.CertCloseStore(store, 0)
+
+ roots := NewCertPool()
+ var cert *syscall.CertContext
+ for {
+ cert, err = syscall.CertEnumCertificatesInStore(store, cert)
+ if err != nil {
+ if errno, ok := err.(syscall.Errno); ok {
+ if errno == CRYPT_E_NOT_FOUND {
+ break
+ }
+ }
+ return nil, err
+ }
+ if cert == nil {
+ break
+ }
+ // Copy the buf, since ParseCertificate does not create its own copy.
+ buf := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:]
+ buf2 := make([]byte, cert.Length)
+ copy(buf2, buf)
+ if c, err := ParseCertificate(buf2); err == nil {
+ roots.AddCert(c)
+ }
+ }
+ return roots, nil
+}
diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go
index 85c083fbb2c..29345a1755c 100644
--- a/libgo/go/crypto/x509/verify.go
+++ b/libgo/go/crypto/x509/verify.go
@@ -5,6 +5,7 @@
package x509
import (
+ "bytes"
"errors"
"fmt"
"net"
@@ -33,6 +34,9 @@ const (
// IncompatibleUsage results when the certificate's key usage indicates
// that it may only be used for a different purpose.
IncompatibleUsage
+ // NameMismatch results when the subject name of a parent certificate
+ // does not match the issuer name in the child.
+ NameMismatch
)
// CertificateInvalidError results when an odd error occurs. Users of this
@@ -54,6 +58,8 @@ func (e CertificateInvalidError) Error() string {
return "x509: too many intermediates for path length constraint"
case IncompatibleUsage:
return "x509: certificate specifies an incompatible key usage"
+ case NameMismatch:
+ return "x509: issuer name does not match subject from issuing certificate"
}
return "x509: unknown error"
}
@@ -87,12 +93,16 @@ func (h HostnameError) Error() string {
valid = c.Subject.CommonName
}
}
+
+ if len(valid) == 0 {
+ return "x509: certificate is not valid for any names, but wanted to match " + h.Host
+ }
return "x509: certificate is valid for " + valid + ", not " + h.Host
}
// UnknownAuthorityError results when the certificate issuer is unknown
type UnknownAuthorityError struct {
- cert *Certificate
+ Cert *Certificate
// hintErr contains an error that may be helpful in determining why an
// authority wasn't found.
hintErr error
@@ -108,8 +118,9 @@ func (e UnknownAuthorityError) Error() string {
if len(certName) == 0 {
if len(e.hintCert.Subject.Organization) > 0 {
certName = e.hintCert.Subject.Organization[0]
+ } else {
+ certName = "serial:" + e.hintCert.SerialNumber.String()
}
- certName = "serial:" + e.hintCert.SerialNumber.String()
}
s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName)
}
@@ -142,7 +153,7 @@ type VerifyOptions struct {
CurrentTime time.Time // if zero, the current time is used
// KeyUsage specifies which Extended Key Usage values are acceptable.
// An empty list means ExtKeyUsageServerAuth. Key usage is considered a
- // constraint down the chain which mirrors Windows CryptoAPI behaviour,
+ // constraint down the chain which mirrors Windows CryptoAPI behavior,
// but not the spec. To accept any key usage, include ExtKeyUsageAny.
KeyUsages []ExtKeyUsage
}
@@ -153,8 +164,40 @@ const (
rootCertificate
)
+func matchNameConstraint(domain, constraint string) bool {
+ // The meaning of zero length constraints is not specified, but this
+ // code follows NSS and accepts them as valid for everything.
+ if len(constraint) == 0 {
+ return true
+ }
+
+ if len(domain) < len(constraint) {
+ return false
+ }
+
+ prefixLen := len(domain) - len(constraint)
+ if !strings.EqualFold(domain[prefixLen:], constraint) {
+ return false
+ }
+
+ if prefixLen == 0 {
+ return true
+ }
+
+ isSubdomain := domain[prefixLen-1] == '.'
+ constraintHasLeadingDot := constraint[0] == '.'
+ return isSubdomain != constraintHasLeadingDot
+}
+
// isValid performs validity checks on the c.
func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error {
+ if len(currentChain) > 0 {
+ child := currentChain[len(currentChain)-1]
+ if !bytes.Equal(child.RawIssuer, c.RawSubject) {
+ return CertificateInvalidError{c, NameMismatch}
+ }
+ }
+
now := opts.CurrentTime
if now.IsZero() {
now = time.Now()
@@ -165,12 +208,9 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
if len(c.PermittedDNSDomains) > 0 {
ok := false
- for _, domain := range c.PermittedDNSDomains {
- if opts.DNSName == domain ||
- (strings.HasSuffix(opts.DNSName, domain) &&
- len(opts.DNSName) >= 1+len(domain) &&
- opts.DNSName[len(opts.DNSName)-len(domain)-1] == '.') {
- ok = true
+ for _, constraint := range c.PermittedDNSDomains {
+ ok = matchNameConstraint(opts.DNSName, constraint)
+ if ok {
break
}
}
@@ -222,7 +262,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
// WARNING: this doesn't do any revocation checking.
func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
// Platform-specific verification needs the ASN.1 contents so
- // this makes the behaviour consistent across platforms.
+ // this makes the behavior consistent across platforms.
if len(c.Raw) == 0 {
return nil, errNotParsed
}
@@ -262,9 +302,13 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
}
}
- candidateChains, err := c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts)
- if err != nil {
- return
+ var candidateChains [][]*Certificate
+ if opts.Roots.contains(c) {
+ candidateChains = append(candidateChains, []*Certificate{c})
+ } else {
+ if candidateChains, err = c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts); err != nil {
+ return nil, err
+ }
}
keyUsages := opts.KeyUsages
@@ -302,8 +346,16 @@ func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate
func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) {
possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c)
+nextRoot:
for _, rootNum := range possibleRoots {
root := opts.Roots.certs[rootNum]
+
+ for _, cert := range currentChain {
+ if cert.Equal(root) {
+ continue nextRoot
+ }
+ }
+
err = root.isValid(rootCertificate, currentChain, opts)
if err != nil {
continue
@@ -316,7 +368,7 @@ nextIntermediate:
for _, intermediateNum := range possibleIntermediates {
intermediate := opts.Intermediates.certs[intermediateNum]
for _, cert := range currentChain {
- if cert == intermediate {
+ if cert.Equal(intermediate) {
continue nextIntermediate
}
}
diff --git a/libgo/go/crypto/x509/verify_test.go b/libgo/go/crypto/x509/verify_test.go
index bacf7ded29f..15c40914444 100644
--- a/libgo/go/crypto/x509/verify_test.go
+++ b/libgo/go/crypto/x509/verify_test.go
@@ -8,6 +8,7 @@ import (
"crypto/x509/pkix"
"encoding/pem"
"errors"
+ "fmt"
"runtime"
"strings"
"testing"
@@ -103,10 +104,6 @@ var verifyTests = []verifyTest{
expectedChains: [][]string{
{"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
@@ -129,12 +126,8 @@ var verifyTests = []verifyTest{
roots: []string{startComRoot},
currentTime: 1302726541,
- // Skip when using systemVerify, since Windows
- // can only return a single chain to us (for now).
- systemSkip: true,
expectedChains: [][]string{
{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
- {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority", "StartCom Certification Authority"},
},
},
{
@@ -235,6 +228,41 @@ var verifyTests = []verifyTest{
},
},
},
+ {
+ // Putting a certificate as a root directly should work as a
+ // way of saying “exactly this”.
+ leaf: selfSigned,
+ roots: []string{selfSigned},
+ currentTime: 1471624472,
+ dnsName: "foo.example",
+ systemSkip: true,
+
+ expectedChains: [][]string{
+ {"Acme Co"},
+ },
+ },
+ {
+ // Putting a certificate as a root directly should not skip
+ // other checks however.
+ leaf: selfSigned,
+ roots: []string{selfSigned},
+ currentTime: 1471624472,
+ dnsName: "notfoo.example",
+ systemSkip: true,
+
+ errorCallback: expectHostnameError,
+ },
+ {
+ // The issuer name in the leaf doesn't exactly match the
+ // subject name in the root. Go does not perform
+ // canonicalization and so should reject this. See issue 14955.
+ leaf: issuerSubjectMatchLeaf,
+ roots: []string{issuerSubjectMatchRoot},
+ currentTime: 1475787715,
+ systemSkip: true,
+
+ errorCallback: expectSubjectIssuerMismatcthError,
+ },
}
func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
@@ -262,10 +290,15 @@ func expectUsageError(t *testing.T, i int, err error) (ok bool) {
}
func expectAuthorityUnknown(t *testing.T, i int, err error) (ok bool) {
- if _, ok := err.(UnknownAuthorityError); !ok {
+ e, ok := err.(UnknownAuthorityError)
+ if !ok {
t.Errorf("#%d: error was not UnknownAuthorityError: %s", i, err)
return false
}
+ if e.Cert == nil {
+ t.Errorf("#%d: error was UnknownAuthorityError, but missing Cert: %s", i, err)
+ return false
+ }
return true
}
@@ -289,6 +322,14 @@ func expectHashError(t *testing.T, i int, err error) bool {
return true
}
+func expectSubjectIssuerMismatcthError(t *testing.T, i int, err error) (ok bool) {
+ if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != NameMismatch {
+ t.Errorf("#%d: error was not a NameMismatch: %s", i, err)
+ return false
+ }
+ return true
+}
+
func certificateFromPEM(pemBytes string) (*Certificate, error) {
block, _ := pem.Decode([]byte(pemBytes))
if block == nil {
@@ -1088,3 +1129,253 @@ Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
-----END CERTIFICATE-----`
+
+const selfSigned = `-----BEGIN CERTIFICATE-----
+MIIC/DCCAeSgAwIBAgIRAK0SWRVmi67xU3z0gkgY+PkwDQYJKoZIhvcNAQELBQAw
+EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA4MTkxNjMzNDdaFw0xNzA4MTkxNjMz
+NDdaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDWkm1kdCwxyKEt6OTmZitkmLGH8cQu9z7rUdrhW8lWNm4kh2SuaUWP
+pscBjda5iqg51aoKuWJR2rw6ElDne+X5eit2FT8zJgAU8v39lMFjbaVZfS9TFOYF
+w0Tk0Luo/PyKJpZnwhsP++iiGQiteJbndy8aLKmJ2MpLfpDGIgxEIyNb5dgoDi0D
+WReDCpE6K9WDYqvKVGnQ2Jvqqra6Gfx0tFkuqJxQuqA8aUOlPHcCH4KBZdNEoXdY
+YL3E4dCAh0YiDs80wNZx4cHqEM3L8gTEFqW2Tn1TSuPZO6gjJ9QPsuUZVjaMZuuO
+NVxqLGujZkDzARhC3fBpptMuaAfi20+BAgMBAAGjTTBLMA4GA1UdDwEB/wQEAwIF
+oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBYGA1UdEQQPMA2C
+C2Zvby5leGFtcGxlMA0GCSqGSIb3DQEBCwUAA4IBAQBPvvfnDhsHWt+/cfwdAVim
+4EDn+hYOMkTQwU0pouYIvY8QXYkZ8MBxpBtBMK4JhFU+ewSWoBAEH2dCCvx/BDxN
+UGTSJHMbsvJHcFvdmsvvRxOqQ/cJz7behx0cfoeHMwcs0/vWv8ms5wHesb5Ek7L0
+pl01FCBGTcncVqr6RK1r4fTpeCCfRIERD+YRJz8TtPH6ydesfLL8jIV40H8NiDfG
+vRAvOtNiKtPzFeQVdbRPOskC4rcHyPeiDAMAMixeLi63+CFty4da3r5lRezeedCE
+cw3ESZzThBwWqvPOtJdpXdm+r57pDW8qD+/0lY8wfImMNkQAyCUCLg/1Lxt/hrBj
+-----END CERTIFICATE-----`
+
+const issuerSubjectMatchRoot = `
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 161640039802297062 (0x23e42c281e55ae6)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: O=Golang, CN=Root ca
+ Validity
+ Not Before: Jan 1 00:00:00 2015 GMT
+ Not After : Jan 1 00:00:00 2025 GMT
+ Subject: O=Golang, CN=Root ca
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:e9:0e:7f:11:0c:e6:5a:e6:86:83:70:f6:51:07:
+ 2e:02:78:11:f5:b2:24:92:38:ee:26:62:02:c7:94:
+ f1:3e:a1:77:6a:c0:8f:d5:22:68:b6:5d:e2:4c:da:
+ e0:85:11:35:c2:92:72:49:8d:81:b4:88:97:6b:b7:
+ fc:b2:44:5b:d9:4d:06:70:f9:0c:c6:8f:e9:b3:df:
+ a3:6a:84:6c:43:59:be:9d:b2:d0:76:9b:c3:d7:fa:
+ 99:59:c3:b8:e5:f3:53:03:bd:49:d6:b3:cc:a2:43:
+ fe:ad:c2:0b:b9:01:b8:56:29:94:03:24:a7:0d:28:
+ 21:29:a9:ae:94:5b:4a:f9:9f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 40:37:D7:01:FB:40:2F:B8:1C:7E:54:04:27:8C:59:01
+ Signature Algorithm: sha256WithRSAEncryption
+ 6f:84:df:49:e0:99:d4:71:66:1d:32:86:56:cb:ea:5a:6b:0e:
+ 00:6a:d1:5a:6e:1f:06:23:07:ff:cb:d1:1a:74:e4:24:43:0b:
+ aa:2a:a0:73:75:25:82:bc:bf:3f:a9:f8:48:88:ac:ed:3a:94:
+ 3b:0d:d3:88:c8:67:44:61:33:df:71:6c:c5:af:ed:16:8c:bf:
+ 82:f9:49:bb:e3:2a:07:53:36:37:25:77:de:91:a4:77:09:7f:
+ 6f:b2:91:58:c4:05:89:ea:8e:fa:e1:3b:19:ef:f8:f6:94:b7:
+ 7b:27:e6:e4:84:dd:2b:f5:93:f5:3c:d8:86:c5:38:01:56:5c:
+ 9f:6d
+-----BEGIN CERTIFICATE-----
+MIICIDCCAYmgAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwIzEPMA0GA1UE
+ChMGR29sYW5nMRAwDgYDVQQDEwdSb290IGNhMB4XDTE1MDEwMTAwMDAwMFoXDTI1
+MDEwMTAwMDAwMFowIzEPMA0GA1UEChMGR29sYW5nMRAwDgYDVQQDEwdSb290IGNh
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1
+siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw
++QzGj+mz36NqhGxDWb6dstB2m8PX+plZw7jl81MDvUnWs8yiQ/6twgu5AbhWKZQD
+JKcNKCEpqa6UW0r5nwIDAQABo10wWzAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYw
+FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIE
+EEA31wH7QC+4HH5UBCeMWQEwDQYJKoZIhvcNAQELBQADgYEAb4TfSeCZ1HFmHTKG
+VsvqWmsOAGrRWm4fBiMH/8vRGnTkJEMLqiqgc3Ulgry/P6n4SIis7TqUOw3TiMhn
+RGEz33Fsxa/tFoy/gvlJu+MqB1M2NyV33pGkdwl/b7KRWMQFieqO+uE7Ge/49pS3
+eyfm5ITdK/WT9TzYhsU4AVZcn20=
+-----END CERTIFICATE-----`
+
+const issuerSubjectMatchLeaf = `
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 16785088708916013734 (0xe8f09d3fe25beaa6)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: O=Golang, CN=Root CA
+ Validity
+ Not Before: Jan 1 00:00:00 2015 GMT
+ Not After : Jan 1 00:00:00 2025 GMT
+ Subject: O=Golang, CN=Leaf
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:db:46:7d:93:2e:12:27:06:48:bc:06:28:21:ab:
+ 7e:c4:b6:a2:5d:fe:1e:52:45:88:7a:36:47:a5:08:
+ 0d:92:42:5b:c2:81:c0:be:97:79:98:40:fb:4f:6d:
+ 14:fd:2b:13:8b:c2:a5:2e:67:d8:d4:09:9e:d6:22:
+ 38:b7:4a:0b:74:73:2b:c2:34:f1:d1:93:e5:96:d9:
+ 74:7b:f3:58:9f:6c:61:3c:c0:b0:41:d4:d9:2b:2b:
+ 24:23:77:5b:1c:3b:bd:75:5d:ce:20:54:cf:a1:63:
+ 87:1d:1e:24:c4:f3:1d:1a:50:8b:aa:b6:14:43:ed:
+ 97:a7:75:62:f4:14:c8:52:d7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 9F:91:16:1F:43:43:3E:49:A6:DE:6D:B6:80:D7:9F:60
+ X509v3 Authority Key Identifier:
+ keyid:40:37:D7:01:FB:40:2F:B8:1C:7E:54:04:27:8C:59:01
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 8d:86:05:da:89:f5:1d:c5:16:14:41:b9:34:87:2b:5c:38:99:
+ e3:d9:5a:5b:7a:5b:de:0b:5c:08:45:09:6f:1c:9d:31:5f:08:
+ ca:7a:a3:99:da:83:0b:22:be:4f:02:35:91:4e:5d:5c:37:bf:
+ 89:22:58:7d:30:76:d2:2f:d0:a0:ee:77:9e:77:c0:d6:19:eb:
+ ec:a0:63:35:6a:80:9b:80:1a:80:de:64:bc:40:38:3c:22:69:
+ ad:46:26:a2:3d:ea:f4:c2:92:49:16:03:96:ae:64:21:b9:7c:
+ ee:64:91:47:81:aa:b4:0c:09:2b:12:1a:b2:f3:af:50:b3:b1:
+ ce:24
+-----BEGIN CERTIFICATE-----
+MIICODCCAaGgAwIBAgIJAOjwnT/iW+qmMA0GCSqGSIb3DQEBCwUAMCMxDzANBgNV
+BAoTBkdvbGFuZzEQMA4GA1UEAxMHUm9vdCBDQTAeFw0xNTAxMDEwMDAwMDBaFw0y
+NTAxMDEwMDAwMDBaMCAxDzANBgNVBAoTBkdvbGFuZzENMAsGA1UEAxMETGVhZjCB
+nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA20Z9ky4SJwZIvAYoIat+xLaiXf4e
+UkWIejZHpQgNkkJbwoHAvpd5mED7T20U/SsTi8KlLmfY1Ame1iI4t0oLdHMrwjTx
+0ZPlltl0e/NYn2xhPMCwQdTZKyskI3dbHDu9dV3OIFTPoWOHHR4kxPMdGlCLqrYU
+Q+2Xp3Vi9BTIUtcCAwEAAaN3MHUwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG
+CCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBCfkRYf
+Q0M+SabebbaA159gMBsGA1UdIwQUMBKAEEA31wH7QC+4HH5UBCeMWQEwDQYJKoZI
+hvcNAQELBQADgYEAjYYF2on1HcUWFEG5NIcrXDiZ49laW3pb3gtcCEUJbxydMV8I
+ynqjmdqDCyK+TwI1kU5dXDe/iSJYfTB20i/QoO53nnfA1hnr7KBjNWqAm4AagN5k
+vEA4PCJprUYmoj3q9MKSSRYDlq5kIbl87mSRR4GqtAwJKxIasvOvULOxziQ=
+-----END CERTIFICATE-----
+`
+
+var unknownAuthorityErrorTests = []struct {
+ cert string
+ expected string
+}{
+ {selfSignedWithCommonName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"test\")"},
+ {selfSignedNoCommonNameWithOrgName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"ca\")"},
+ {selfSignedNoCommonNameNoOrgName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"serial:0\")"},
+}
+
+func TestUnknownAuthorityError(t *testing.T) {
+ for i, tt := range unknownAuthorityErrorTests {
+ der, _ := pem.Decode([]byte(tt.cert))
+ if der == nil {
+ t.Errorf("#%d: Unable to decode PEM block", i)
+ }
+ c, err := ParseCertificate(der.Bytes)
+ if err != nil {
+ t.Errorf("#%d: Unable to parse certificate -> %s", i, err)
+ }
+ uae := &UnknownAuthorityError{
+ Cert: c,
+ hintErr: fmt.Errorf("empty"),
+ hintCert: c,
+ }
+ actual := uae.Error()
+ if strings.Compare(actual, tt.expected) != 0 {
+ t.Errorf("#%d: UnknownAuthorityError.Error() response invalid actual: %s expected: %s", i, actual, tt.expected)
+ }
+ }
+}
+
+var nameConstraintTests = []struct {
+ constraint, domain string
+ shouldMatch bool
+}{
+ {"", "anything.com", true},
+ {"example.com", "example.com", true},
+ {"example.com", "ExAmPle.coM", true},
+ {"example.com", "exampl1.com", false},
+ {"example.com", "www.ExAmPle.coM", true},
+ {"example.com", "notexample.com", false},
+ {".example.com", "example.com", false},
+ {".example.com", "www.example.com", true},
+ {".example.com", "www..example.com", false},
+}
+
+func TestNameConstraints(t *testing.T) {
+ for i, test := range nameConstraintTests {
+ result := matchNameConstraint(test.domain, test.constraint)
+ if result != test.shouldMatch {
+ t.Errorf("unexpected result for test #%d: domain=%s, constraint=%s, result=%t", i, test.domain, test.constraint, result)
+ }
+ }
+}
+
+const selfSignedWithCommonName = `-----BEGIN CERTIFICATE-----
+MIIDCjCCAfKgAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL
+MAkGA1UEAxMCY2EwHhcNMTYwODI4MTcwOTE4WhcNMjEwODI3MTcwOTE4WjAcMQsw
+CQYDVQQKEwJjYTENMAsGA1UEAxMEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAOH55PfRsbvmcabfLLko1w/yuapY/hk13Cgmc3WE/Z1ZStxGiVxY
+gQVH9n4W/TbUsrep/TmcC4MV7xEm5252ArcgaH6BeQ4QOTFj/6Jx0RT7U/ix+79x
+8RRysf7OlzNpGIctwZEM7i/G+0ZfqX9ULxL/EW9tppSxMX1jlXZQarnU7BERL5cH
++G2jcbU9H28FXYishqpVYE9L7xrXMm61BAwvGKB0jcVW6JdhoAOSfQbbgp7JjIlq
+czXqUsv1UdORO/horIoJptynTvuARjZzyWatya6as7wyOgEBllE6BjPK9zpn+lp3
+tQ8dwKVqm/qBPhIrVqYG/Ec7pIv8mJfYabMCAwEAAaNZMFcwDgYDVR0PAQH/BAQD
+AgOoMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA
+MAoGA1UdDgQDBAEAMAwGA1UdIwQFMAOAAQAwDQYJKoZIhvcNAQELBQADggEBAAAM
+XMFphzq4S5FBcRdB2fRrmcoz+jEROBWvIH/1QUJeBEBz3ZqBaJYfBtQTvqCA5Rjw
+dxyIwVd1W3q3aSulM0tO62UCU6L6YeeY/eq8FmpD7nMJo7kCrXUUAMjxbYvS3zkT
+v/NErK6SgWnkQiPJBZNX1Q9+aSbLT/sbaCTdbWqcGNRuLGJkmqfIyoxRt0Hhpqsx
+jP5cBaVl50t4qoCuVIE9cOucnxYXnI7X5HpXWvu8Pfxo4SwVjb1az8Fk5s8ZnxGe
+fPB6Q3L/pKBe0SEe5GywpwtokPLB3lAygcuHbxp/1FlQ1NQZqq+vgXRIla26bNJf
+IuYkJwt6w+LH/9HZgf8=
+-----END CERTIFICATE-----`
+const selfSignedNoCommonNameWithOrgName = `-----BEGIN CERTIFICATE-----
+MIIC+zCCAeOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL
+MAkGA1UEAxMCY2EwHhcNMTYwODI4MTgxMzQ4WhcNMjEwODI3MTgxMzQ4WjANMQsw
+CQYDVQQKEwJjYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL5EjrUa
+7EtOMxWiIgTzp2FlQvncPsG329O3l3uNGnbigb8TmNMw2M8UhoDjd84pnU5RAfqd
+8t5TJyw/ybnIKBN131Q2xX+gPQ0dFyMvcO+i1CUgCxmYZomKVA2MXO1RD1hLTYGS
+gOVjc3no3MBwd8uVQp0NStqJ1QvLtNG4Uy+B28qe+ZFGGbjGqx8/CU4A8Szlpf7/
+xAZR8w5qFUUlpA2LQYeHHJ5fQVXw7kyL1diNrKNi0G3qcY0IrBh++hT+hnEEXyXu
+g8a0Ux18hoE8D6rAr34rCZl6AWfqW5wjwm+N5Ns2ugr9U4N8uCKJYMPHb2CtdubU
+46IzVucpTfGLdaMCAwEAAaNZMFcwDgYDVR0PAQH/BAQDAgOoMB0GA1UdJQQWMBQG
+CCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMAoGA1UdDgQDBAEAMAwG
+A1UdIwQFMAOAAQAwDQYJKoZIhvcNAQELBQADggEBAEn5SgVpJ3zjsdzPqK7Qd/sB
+bYd1qtPHlrszjhbHBg35C6mDgKhcv4o6N+fuC+FojZb8lIxWzJtvT9pQbfy/V6u3
+wOb816Hm71uiP89sioIOKCvSAstj/p9doKDOUaKOcZBTw0PS2m9eja8bnleZzBvK
+rD8cNkHf74v98KvBhcwBlDifVzmkWzMG6TL1EkRXUyLKiWgoTUFSkCDV927oXXMR
+DKnszq+AVw+K8hbeV2A7GqT7YfeqOAvSbatTDnDtKOPmlCnQui8A149VgZzXv7eU
+29ssJSqjUPyp58dlV6ZuynxPho1QVZUOQgnJToXIQ3/5vIvJRXy52GJCs4/Gh/w=
+-----END CERTIFICATE-----`
+const selfSignedNoCommonNameNoOrgName = `-----BEGIN CERTIFICATE-----
+MIIC7jCCAdagAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL
+MAkGA1UEAxMCY2EwHhcNMTYwODI4MTgxOTQ1WhcNMjEwODI3MTgxOTQ1WjAAMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp3E+Jl6DpgzogHUW/i/AAcCM
+fnNJLOamNVKFGmmxhb4XTHxRaWoTzrlsyzIMS0WzivvJeZVe6mWbvuP2kZanKgIz
+35YXRTR9HbqkNTMuvnpUESzWxbGWE2jmt2+a/Jnz89FS4WIYRhF7nI2z8PvZOfrI
+2gETTT2tEpoF2S4soaYfm0DBeT8K0/rogAaf+oeUS6V+v3miRcAooJgpNJGu9kqm
+S0xKPn1RCFVjpiRd6YNS0xZirjYQIBMFBvoSoHjaOdgJptNRBprYPOxVJ/ItzGf0
+kPmzPFCx2tKfxV9HLYBPgxi+fP3IIx8aIYuJn8yReWtYEMYU11hDPeAFN5Gm+wID
+AQABo1kwVzAOBgNVHQ8BAf8EBAMCA6gwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG
+AQUFBwMBMAwGA1UdEwEB/wQCMAAwCgYDVR0OBAMEAQAwDAYDVR0jBAUwA4ABADAN
+BgkqhkiG9w0BAQsFAAOCAQEATZVOFeiCpPM5QysToLv+8k7Rjoqt6L5IxMUJGEpq
+4ENmldmwkhEKr9VnYEJY3njydnnTm97d9vOfnLj9nA9wMBODeOO3KL2uJR2oDnmM
+9z1NSe2aQKnyBb++DM3ZdikpHn/xEpGV19pYKFQVn35x3lpPh2XijqRDO/erKemb
+w67CoNRb81dy+4Q1lGpA8ORoLWh5fIq2t2eNGc4qB8vlTIKiESzAwu7u3sRfuWQi
+4R+gnfLd37FWflMHwztFbVTuNtPOljCX0LN7KcuoXYlr05RhQrmoN7fQHsrZMNLs
+8FVjHdKKu+uPstwd04Uy4BR/H2y1yerN9j/L6ZkMl98iiA==
+-----END CERTIFICATE-----`
diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go
index 9ad3cf23f65..949ce018561 100644
--- a/libgo/go/crypto/x509/x509.go
+++ b/libgo/go/crypto/x509/x509.go
@@ -67,9 +67,8 @@ func marshalPublicKey(pub interface{}) (publicKeyBytes []byte, publicKeyAlgorith
return nil, pkix.AlgorithmIdentifier{}, err
}
publicKeyAlgorithm.Algorithm = oidPublicKeyRSA
- // This is a NULL parameters value which is technically
- // superfluous, but most other code includes it and, by
- // doing this, we match their public key hashes.
+ // This is a NULL parameters value which is required by
+ // https://tools.ietf.org/html/rfc3279#section-2.3.1.
publicKeyAlgorithm.Parameters = asn1.RawValue{
Tag: 5,
}
@@ -179,21 +178,36 @@ const (
ECDSAWithSHA256
ECDSAWithSHA384
ECDSAWithSHA512
+ SHA256WithRSAPSS
+ SHA384WithRSAPSS
+ SHA512WithRSAPSS
)
+func (algo SignatureAlgorithm) isRSAPSS() bool {
+ switch algo {
+ case SHA256WithRSAPSS, SHA384WithRSAPSS, SHA512WithRSAPSS:
+ return true
+ default:
+ return false
+ }
+}
+
var algoName = [...]string{
- MD2WithRSA: "MD2-RSA",
- MD5WithRSA: "MD5-RSA",
- SHA1WithRSA: "SHA1-RSA",
- SHA256WithRSA: "SHA256-RSA",
- SHA384WithRSA: "SHA384-RSA",
- SHA512WithRSA: "SHA512-RSA",
- DSAWithSHA1: "DSA-SHA1",
- DSAWithSHA256: "DSA-SHA256",
- ECDSAWithSHA1: "ECDSA-SHA1",
- ECDSAWithSHA256: "ECDSA-SHA256",
- ECDSAWithSHA384: "ECDSA-SHA384",
- ECDSAWithSHA512: "ECDSA-SHA512",
+ MD2WithRSA: "MD2-RSA",
+ MD5WithRSA: "MD5-RSA",
+ SHA1WithRSA: "SHA1-RSA",
+ SHA256WithRSA: "SHA256-RSA",
+ SHA384WithRSA: "SHA384-RSA",
+ SHA512WithRSA: "SHA512-RSA",
+ SHA256WithRSAPSS: "SHA256-RSAPSS",
+ SHA384WithRSAPSS: "SHA384-RSAPSS",
+ SHA512WithRSAPSS: "SHA512-RSAPSS",
+ DSAWithSHA1: "DSA-SHA1",
+ DSAWithSHA256: "DSA-SHA256",
+ ECDSAWithSHA1: "ECDSA-SHA1",
+ ECDSAWithSHA256: "ECDSA-SHA256",
+ ECDSAWithSHA384: "ECDSA-SHA384",
+ ECDSAWithSHA512: "ECDSA-SHA512",
}
func (algo SignatureAlgorithm) String() string {
@@ -269,12 +283,24 @@ var (
oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
+ oidSignatureRSAPSS = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10}
oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2}
oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
+
+ oidSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1}
+ oidSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2}
+ oidSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3}
+
+ oidMGF1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 8}
+
+ // oidISOSignatureSHA1WithRSA means the same as oidSignatureSHA1WithRSA
+ // but it's specified by ISO. Microsoft's makecert.exe has been known
+ // to produce certificates with this OID.
+ oidISOSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 29}
)
var signatureAlgorithmDetails = []struct {
@@ -286,9 +312,13 @@ var signatureAlgorithmDetails = []struct {
{MD2WithRSA, oidSignatureMD2WithRSA, RSA, crypto.Hash(0) /* no value for MD2 */},
{MD5WithRSA, oidSignatureMD5WithRSA, RSA, crypto.MD5},
{SHA1WithRSA, oidSignatureSHA1WithRSA, RSA, crypto.SHA1},
+ {SHA1WithRSA, oidISOSignatureSHA1WithRSA, RSA, crypto.SHA1},
{SHA256WithRSA, oidSignatureSHA256WithRSA, RSA, crypto.SHA256},
{SHA384WithRSA, oidSignatureSHA384WithRSA, RSA, crypto.SHA384},
{SHA512WithRSA, oidSignatureSHA512WithRSA, RSA, crypto.SHA512},
+ {SHA256WithRSAPSS, oidSignatureRSAPSS, RSA, crypto.SHA256},
+ {SHA384WithRSAPSS, oidSignatureRSAPSS, RSA, crypto.SHA384},
+ {SHA512WithRSAPSS, oidSignatureRSAPSS, RSA, crypto.SHA512},
{DSAWithSHA1, oidSignatureDSAWithSHA1, DSA, crypto.SHA1},
{DSAWithSHA256, oidSignatureDSAWithSHA256, DSA, crypto.SHA256},
{ECDSAWithSHA1, oidSignatureECDSAWithSHA1, ECDSA, crypto.SHA1},
@@ -297,12 +327,115 @@ var signatureAlgorithmDetails = []struct {
{ECDSAWithSHA512, oidSignatureECDSAWithSHA512, ECDSA, crypto.SHA512},
}
-func getSignatureAlgorithmFromOID(oid asn1.ObjectIdentifier) SignatureAlgorithm {
- for _, details := range signatureAlgorithmDetails {
- if oid.Equal(details.oid) {
- return details.algo
+// pssParameters reflects the parameters in an AlgorithmIdentifier that
+// specifies RSA PSS. See https://tools.ietf.org/html/rfc3447#appendix-A.2.3
+type pssParameters struct {
+ // The following three fields are not marked as
+ // optional because the default values specify SHA-1,
+ // which is no longer suitable for use in signatures.
+ Hash pkix.AlgorithmIdentifier `asn1:"explicit,tag:0"`
+ MGF pkix.AlgorithmIdentifier `asn1:"explicit,tag:1"`
+ SaltLength int `asn1:"explicit,tag:2"`
+ TrailerField int `asn1:"optional,explicit,tag:3,default:1"`
+}
+
+// rsaPSSParameters returns an asn1.RawValue suitable for use as the Parameters
+// in an AlgorithmIdentifier that specifies RSA PSS.
+func rsaPSSParameters(hashFunc crypto.Hash) asn1.RawValue {
+ var hashOID asn1.ObjectIdentifier
+
+ switch hashFunc {
+ case crypto.SHA256:
+ hashOID = oidSHA256
+ case crypto.SHA384:
+ hashOID = oidSHA384
+ case crypto.SHA512:
+ hashOID = oidSHA512
+ }
+
+ params := pssParameters{
+ Hash: pkix.AlgorithmIdentifier{
+ Algorithm: hashOID,
+ Parameters: asn1.RawValue{
+ Tag: 5, /* ASN.1 NULL */
+ },
+ },
+ MGF: pkix.AlgorithmIdentifier{
+ Algorithm: oidMGF1,
+ },
+ SaltLength: hashFunc.Size(),
+ TrailerField: 1,
+ }
+
+ mgf1Params := pkix.AlgorithmIdentifier{
+ Algorithm: hashOID,
+ Parameters: asn1.RawValue{
+ Tag: 5, /* ASN.1 NULL */
+ },
+ }
+
+ var err error
+ params.MGF.Parameters.FullBytes, err = asn1.Marshal(mgf1Params)
+ if err != nil {
+ panic(err)
+ }
+
+ serialized, err := asn1.Marshal(params)
+ if err != nil {
+ panic(err)
+ }
+
+ return asn1.RawValue{FullBytes: serialized}
+}
+
+func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) SignatureAlgorithm {
+ if !ai.Algorithm.Equal(oidSignatureRSAPSS) {
+ for _, details := range signatureAlgorithmDetails {
+ if ai.Algorithm.Equal(details.oid) {
+ return details.algo
+ }
}
+ return UnknownSignatureAlgorithm
+ }
+
+ // RSA PSS is special because it encodes important parameters
+ // in the Parameters.
+
+ var params pssParameters
+ if _, err := asn1.Unmarshal(ai.Parameters.FullBytes, &params); err != nil {
+ return UnknownSignatureAlgorithm
}
+
+ var mgf1HashFunc pkix.AlgorithmIdentifier
+ if _, err := asn1.Unmarshal(params.MGF.Parameters.FullBytes, &mgf1HashFunc); err != nil {
+ return UnknownSignatureAlgorithm
+ }
+
+ // PSS is greatly overburdened with options. This code forces
+ // them into three buckets by requiring that the MGF1 hash
+ // function always match the message hash function (as
+ // recommended in
+ // https://tools.ietf.org/html/rfc3447#section-8.1), that the
+ // salt length matches the hash length, and that the trailer
+ // field has the default value.
+ asn1NULL := []byte{0x05, 0x00}
+ if !bytes.Equal(params.Hash.Parameters.FullBytes, asn1NULL) ||
+ !params.MGF.Algorithm.Equal(oidMGF1) ||
+ !mgf1HashFunc.Algorithm.Equal(params.Hash.Algorithm) ||
+ !bytes.Equal(mgf1HashFunc.Parameters.FullBytes, asn1NULL) ||
+ params.TrailerField != 1 {
+ return UnknownSignatureAlgorithm
+ }
+
+ switch {
+ case params.Hash.Algorithm.Equal(oidSHA256) && params.SaltLength == 32:
+ return SHA256WithRSAPSS
+ case params.Hash.Algorithm.Equal(oidSHA384) && params.SaltLength == 48:
+ return SHA384WithRSAPSS
+ case params.Hash.Algorithm.Equal(oidSHA512) && params.SaltLength == 64:
+ return SHA512WithRSAPSS
+ }
+
return UnknownSignatureAlgorithm
}
@@ -681,11 +814,11 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey
switch algo {
case SHA1WithRSA, DSAWithSHA1, ECDSAWithSHA1:
hashType = crypto.SHA1
- case SHA256WithRSA, DSAWithSHA256, ECDSAWithSHA256:
+ case SHA256WithRSA, SHA256WithRSAPSS, DSAWithSHA256, ECDSAWithSHA256:
hashType = crypto.SHA256
- case SHA384WithRSA, ECDSAWithSHA384:
+ case SHA384WithRSA, SHA384WithRSAPSS, ECDSAWithSHA384:
hashType = crypto.SHA384
- case SHA512WithRSA, ECDSAWithSHA512:
+ case SHA512WithRSA, SHA512WithRSAPSS, ECDSAWithSHA512:
hashType = crypto.SHA512
case MD2WithRSA, MD5WithRSA:
return InsecureAlgorithmError(algo)
@@ -703,7 +836,11 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey
switch pub := publicKey.(type) {
case *rsa.PublicKey:
- return rsa.VerifyPKCS1v15(pub, hashType, digest, signature)
+ if algo.isRSAPSS() {
+ return rsa.VerifyPSS(pub, hashType, digest, signature, &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash})
+ } else {
+ return rsa.VerifyPKCS1v15(pub, hashType, digest, signature)
+ }
case *dsa.PublicKey:
dsaSig := new(dsaSignature)
if rest, err := asn1.Unmarshal(signature, dsaSig); err != nil {
@@ -738,7 +875,7 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey
// CheckCRLSignature checks that the signature in crl is from c.
func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) error {
- algo := getSignatureAlgorithmFromOID(crl.SignatureAlgorithm.Algorithm)
+ algo := getSignatureAlgorithmFromAI(crl.SignatureAlgorithm)
return c.CheckSignature(algo, crl.TBSCertList.Raw, crl.SignatureValue.RightAlign())
}
@@ -787,10 +924,19 @@ type distributionPointName struct {
RelativeName pkix.RDNSequence `asn1:"optional,tag:1"`
}
+// asn1Null is the ASN.1 encoding of a NULL value.
+var asn1Null = []byte{5, 0}
+
func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) {
asn1Data := keyData.PublicKey.RightAlign()
switch algo {
case RSA:
+ // RSA public keys must have a NULL in the parameters
+ // (https://tools.ietf.org/html/rfc3279#section-2.3.1).
+ if !bytes.Equal(keyData.Algorithm.Parameters.FullBytes, asn1Null) {
+ return nil, errors.New("x509: RSA key missing NULL parameters")
+ }
+
p := new(rsaPublicKey)
rest, err := asn1.Unmarshal(asn1Data, p)
if err != nil {
@@ -937,7 +1083,7 @@ func parseCertificate(in *certificate) (*Certificate, error) {
out.Signature = in.SignatureValue.RightAlign()
out.SignatureAlgorithm =
- getSignatureAlgorithmFromOID(in.TBSCertificate.SignatureAlgorithm.Algorithm)
+ getSignatureAlgorithmFromAI(in.TBSCertificate.SignatureAlgorithm)
out.PublicKeyAlgorithm =
getPublicKeyAlgorithmFromOID(in.TBSCertificate.PublicKey.Algorithm.Algorithm)
@@ -1545,6 +1691,9 @@ func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgori
err = errors.New("x509: cannot sign with hash function requested")
return
}
+ if requestedSigAlgo.isRSAPSS() {
+ sigAlgo.Parameters = rsaPSSParameters(hashFunc)
+ }
found = true
break
}
@@ -1577,6 +1726,10 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
}
+ if template.SerialNumber == nil {
+ return nil, errors.New("x509: no SerialNumber given")
+ }
+
hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm)
if err != nil {
return nil, err
@@ -1629,8 +1782,17 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
h.Write(tbsCertContents)
digest := h.Sum(nil)
+ var signerOpts crypto.SignerOpts
+ signerOpts = hashFunc
+ if template.SignatureAlgorithm != 0 && template.SignatureAlgorithm.isRSAPSS() {
+ signerOpts = &rsa.PSSOptions{
+ SaltLength: rsa.PSSSaltLengthEqualsHash,
+ Hash: hashFunc,
+ }
+ }
+
var signature []byte
- signature, err = key.Sign(rand, digest, hashFunc)
+ signature, err = key.Sign(rand, digest, signerOpts)
if err != nil {
return
}
@@ -1688,13 +1850,20 @@ func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts [
return nil, err
}
+ // Force revocation times to UTC per RFC 5280.
+ revokedCertsUTC := make([]pkix.RevokedCertificate, len(revokedCerts))
+ for i, rc := range revokedCerts {
+ rc.RevocationTime = rc.RevocationTime.UTC()
+ revokedCertsUTC[i] = rc
+ }
+
tbsCertList := pkix.TBSCertificateList{
Version: 1,
Signature: signatureAlgorithm,
Issuer: c.Subject.ToRDNSequence(),
ThisUpdate: now.UTC(),
NextUpdate: expiry.UTC(),
- RevokedCertificates: revokedCerts,
+ RevokedCertificates: revokedCertsUTC,
}
// Authority Key Id
@@ -1804,7 +1973,7 @@ func newRawAttributes(attributes []pkix.AttributeTypeAndValueSET) ([]asn1.RawVal
return nil, err
}
if len(rest) != 0 {
- return nil, errors.New("x509: failed to unmarshall raw CSR Attributes")
+ return nil, errors.New("x509: failed to unmarshal raw CSR Attributes")
}
return rawAttributes, nil
}
@@ -2035,7 +2204,7 @@ func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error
RawSubject: in.TBSCSR.Subject.FullBytes,
Signature: in.SignatureValue.RightAlign(),
- SignatureAlgorithm: getSignatureAlgorithmFromOID(in.SignatureAlgorithm.Algorithm),
+ SignatureAlgorithm: getSignatureAlgorithmFromAI(in.SignatureAlgorithm),
PublicKeyAlgorithm: getPublicKeyAlgorithmFromOID(in.TBSCSR.PublicKey.Algorithm.Algorithm),
diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go
index c6448d39ab5..aa30d85b7da 100644
--- a/libgo/go/crypto/x509/x509_test.go
+++ b/libgo/go/crypto/x509/x509_test.go
@@ -24,6 +24,7 @@ import (
"net"
"os/exec"
"reflect"
+ "strings"
"testing"
"time"
)
@@ -85,14 +86,21 @@ FF53oIpvxe/SCOymfWq/LW849Ytv3Xwod0+wzAP8STXG4HSELS4UedPYeHJJJYcZ
-----END PUBLIC KEY-----
`
-var pemPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
-MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
-fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
-/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
-RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
-EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
-IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
-tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
+var pemPrivateKey = `
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQCxoeCUW5KJxNPxMp+KmCxKLc1Zv9Ny+4CFqcUXVUYH69L3mQ7v
+IWrJ9GBfcaA7BPQqUlWxWM+OCEQZH1EZNIuqRMNQVuIGCbz5UQ8w6tS0gcgdeGX7
+J7jgCQ4RK3F/PuCM38QBLaHx988qG8NMc6VKErBjctCXFHQt14lerd5KpQIDAQAB
+AoGAYrf6Hbk+mT5AI33k2Jt1kcweodBP7UkExkPxeuQzRVe0KVJw0EkcFhywKpr1
+V5eLMrILWcJnpyHE5slWwtFHBG6a5fLaNtsBBtcAIfqTQ0Vfj5c6SzVaJv0Z5rOd
+7gQF6isy3t3w9IF3We9wXQKzT6q5ypPGdm6fciKQ8RnzREkCQQDZwppKATqQ41/R
+vhSj90fFifrGE6aVKC1hgSpxGQa4oIdsYYHwMzyhBmWW9Xv/R+fPyr8ZwPxp2c12
+33QwOLPLAkEA0NNUb+z4ebVVHyvSwF5jhfJxigim+s49KuzJ1+A2RaSApGyBZiwS
+rWvWkB471POAKUYt5ykIWVZ83zcceQiNTwJBAMJUFQZX5GDqWFc/zwGoKkeR49Yi
+MTXIvf7Wmv6E++eFcnT461FlGAUHRV+bQQXGsItR/opIG7mGogIkVXa3E1MCQARX
+AAA7eoZ9AEHflUeuLn9QJI/r0hyQQLEtrpwv6rDT1GCWaLII5HJ6NUFVf4TTcqxo
+6vdM4QGKTJoO+SaCyP0CQFdpcxSAuzpFcKv0IlJ8XzS/cy+mweCMwyJ1PFEc4FX6
+wg/HcAJWY60xZTJDFN+Qfx8ZQvBEin6c2/h+zZi5IVY=
-----END RSA PRIVATE KEY-----
`
@@ -127,13 +135,13 @@ func bigFromHexString(s string) *big.Int {
var rsaPrivateKey = &rsa.PrivateKey{
PublicKey: rsa.PublicKey{
- N: bigFromString("9353930466774385905609975137998169297361893554149986716853295022578535724979677252958524466350471210367835187480748268864277464700638583474144061408845077"),
+ N: bigFromString("124737666279038955318614287965056875799409043964547386061640914307192830334599556034328900586693254156136128122194531292927142396093148164407300419162827624945636708870992355233833321488652786796134504707628792159725681555822420087112284637501705261187690946267527866880072856272532711620639179596808018872997"),
E: 65537,
},
- D: bigFromString("7266398431328116344057699379749222532279343923819063639497049039389899328538543087657733766554155839834519529439851673014800261285757759040931985506583861"),
+ D: bigFromString("69322600686866301945688231018559005300304807960033948687567105312977055197015197977971637657636780793670599180105424702854759606794705928621125408040473426339714144598640466128488132656829419518221592374964225347786430566310906679585739468938549035854760501049443920822523780156843263434219450229353270690889"),
Primes: []*big.Int{
- bigFromString("98920366548084643601728869055592650835572950932266967461790948584315647051443"),
- bigFromString("94560208308847015747498523884063394671606671904944666360068158221458669711639"),
+ bigFromString("11405025354575369741595561190164746858706645478381139288033759331174478411254205003127028642766986913445391069745480057674348716675323735886284176682955723"),
+ bigFromString("10937079261204603443118731009201819560867324167189758120988909645641782263430128449826989846631183550578761324239709121189827307416350485191350050332642639"),
},
}
@@ -340,6 +348,9 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
{"RSA/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384},
{"ECDSA/RSA", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSA},
{"ECDSA/ECDSA", &ecdsaPriv.PublicKey, ecdsaPriv, true, ECDSAWithSHA1},
+ {"RSAPSS/RSAPSS", &testPrivateKey.PublicKey, testPrivateKey, true, SHA256WithRSAPSS},
+ {"ECDSA/RSAPSS", &ecdsaPriv.PublicKey, testPrivateKey, false, SHA256WithRSAPSS},
+ {"RSAPSS/ECDSA", &testPrivateKey.PublicKey, ecdsaPriv, false, ECDSAWithSHA384},
}
testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth}
@@ -761,16 +772,76 @@ func TestVerifyCertificateWithDSASignature(t *testing.T) {
}
}
+var rsaPSSSelfSignedPEM = `-----BEGIN CERTIFICATE-----
+MIIGHjCCA9KgAwIBAgIBdjBBBgkqhkiG9w0BAQowNKAPMA0GCWCGSAFlAwQCAQUA
+oRwwGgYJKoZIhvcNAQEIMA0GCWCGSAFlAwQCAQUAogMCASAwbjELMAkGA1UEBhMC
+SlAxHDAaBgNVBAoME0phcGFuZXNlIEdvdmVybm1lbnQxKDAmBgNVBAsMH1RoZSBN
+aW5pc3RyeSBvZiBGb3JlaWduIEFmZmFpcnMxFzAVBgNVBAMMDmUtcGFzc3BvcnRD
+U0NBMB4XDTEzMDUxNDA1MDczMFoXDTI5MDUxNDA1MDczMFowbjELMAkGA1UEBhMC
+SlAxHDAaBgNVBAoME0phcGFuZXNlIEdvdmVybm1lbnQxKDAmBgNVBAsMH1RoZSBN
+aW5pc3RyeSBvZiBGb3JlaWduIEFmZmFpcnMxFzAVBgNVBAMMDmUtcGFzc3BvcnRD
+U0NBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAx/E3WRVxcCDXhoST
+8nVSLjW6hwM4Ni99AegWzcGtfGFo0zjFA1Cl5URqxauvYu3gQgQHBGA1CovWeGrl
+yVSRzOL1imcYsSgLOcnhVYB3Xcrof4ebv9+W+TwNdc9YzAwcj8rNd5nP6PKXIQ+W
+PCkEOXdyb80YEnxuT+NPjkVfFSPBS7QYZpvT2fwy4fZ0eh48253+7VleSmTO0mqj
+7TlzaG56q150SLZbhpOd8jD8bM/wACnLCPR88wj4hCcDLEwoLyY85HJCTIQQMnoT
+UpqyzEeupPREIm6yi4d8C9YqIWFn2YTnRcWcmMaJLzq+kYwKoudfnoC6RW2vzZXn
+defQs68IZuK+uALu9G3JWGPgu0CQGj0JNDT8zkiDV++4eNrZczWKjr1YnAL+VbLK
+bApwL2u19l2WDpfUklimhWfraqHNIUKU6CjZOG31RzXcplIj0mtqs0E1r7r357Es
+yFoB28iNo4cz1lCulh0E4WJzWzLZcT4ZspHHRCFyvYnXoibXEV1nULq8ByKKG0FS
+7nn4SseoV+8PvjHLPhmHGMvi4mxkbcXdV3wthHT1/HXdqY84A4xHWt1+sB/TpTek
+tDhFlEfcUygvTu58UtOnysomOVVeERmi7WSujfzKsGJAJYeetiA5R+zX7BxeyFVE
+qW0zh1Tkwh0S8LRe5diJh4+6FG0CAwEAAaNfMF0wHQYDVR0OBBYEFD+oahaikBTV
+Urk81Uz7kRS2sx0aMA4GA1UdDwEB/wQEAwIBBjAYBgNVHSAEETAPMA0GCyqDCIaP
+fgYFAQEBMBIGA1UdEwEB/wQIMAYBAf8CAQAwQQYJKoZIhvcNAQEKMDSgDzANBglg
+hkgBZQMEAgEFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgEFAKIDAgEgA4IC
+AQAaxWBQn5CZuNBfyzL57mn31ukHUFd61OMROSX3PT7oCv1Dy+C2AdRlxOcbN3/n
+li0yfXUUqiY3COlLAHKRlkr97mLtxEFoJ0R8nVN2IQdChNQM/XSCzSGyY8NVa1OR
+TTpEWLnexJ9kvIdbFXwUqdTnAkOI0m7Rg8j+E+lRRHg1xDAA1qKttrtUj3HRQWf3
+kNTu628SiMvap6aIdncburaK56MP7gkR1Wr/ichOfjIA3Jgw2PapI31i0GqeMd66
+U1+lC9FeyMAJpuSVp/SoiYzYo+79SFcVoM2yw3yAnIKg7q9GLYYqzncdykT6C06c
+15gWFI6igmReAsD9ITSvYh0jLrLHfEYcPTOD3ZXJ4EwwHtWSoO3gq1EAtOYKu/Lv
+C8zfBsZcFdsHvsSiYeBU8Oioe42mguky3Ax9O7D805Ek6R68ra07MW/G4YxvV7IN
+2BfSaYy8MX9IG0ZMIOcoc0FeF5xkFmJ7kdrlTaJzC0IE9PNxNaH5QnOAFB8vxHcO
+FioUxb6UKdHcPLR1VZtAdTdTMjSJxUqD/35Cdfqs7oDJXz8f6TXO2Tdy6G++YUs9
+qsGZWxzFvvkXUkQSl0dQQ5jO/FtUJcAVXVVp20LxPemfatAHpW31WdJYeWSQWky2
++f9b5TXKXVyjlUL7uHxowWrT2AtTchDH22wTEtqLEF9Z3Q==
+-----END CERTIFICATE-----`
+
+func TestRSAPSSSelfSigned(t *testing.T) {
+ der, _ := pem.Decode([]byte(rsaPSSSelfSignedPEM))
+ if der == nil {
+ t.Fatal("Failed to find PEM block")
+ }
+
+ cert, err := ParseCertificate(der.Bytes)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err = cert.CheckSignatureFrom(cert); err != nil {
+ t.Fatal(err)
+ }
+}
+
const pemCertificate = `-----BEGIN CERTIFICATE-----
-MIIB5DCCAZCgAwIBAgIBATALBgkqhkiG9w0BAQUwLTEQMA4GA1UEChMHQWNtZSBDbzEZMBcGA1UE
-AxMQdGVzdC5leGFtcGxlLmNvbTAeFw03MDAxMDEwMDE2NDBaFw03MDAxMDIwMzQ2NDBaMC0xEDAO
-BgNVBAoTB0FjbWUgQ28xGTAXBgNVBAMTEHRlc3QuZXhhbXBsZS5jb20wWjALBgkqhkiG9w0BAQED
-SwAwSAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0fd7Ai2KW5ToIwzFo
-fvJcS/STa6HA5gQenRUCAwEAAaOBnjCBmzAOBgNVHQ8BAf8EBAMCAAQwDwYDVR0TAQH/BAUwAwEB
-/zANBgNVHQ4EBgQEAQIDBDAPBgNVHSMECDAGgAQBAgMEMBsGA1UdEQQUMBKCEHRlc3QuZXhhbXBs
-ZS5jb20wDwYDVR0gBAgwBjAEBgIqAzAqBgNVHR4EIzAhoB8wDoIMLmV4YW1wbGUuY29tMA2CC2V4
-YW1wbGUuY29tMAsGCSqGSIb3DQEBBQNBAHKZKoS1wEQOGhgklx4+/yFYQlnqwKXvar/ZecQvJwui
-0seMQnwBhwdBkHfVIU2Fu5VUMRyxlf0ZNaDXcpU581k=
+MIIDATCCAemgAwIBAgIRAKQkkrFx1T/dgB/Go/xBM5swDQYJKoZIhvcNAQELBQAw
+EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA4MTcyMDM2MDdaFw0xNzA4MTcyMDM2
+MDdaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDAoJtjG7M6InsWwIo+l3qq9u+g2rKFXNu9/mZ24XQ8XhV6PUR+5HQ4
+jUFWC58ExYhottqK5zQtKGkw5NuhjowFUgWB/VlNGAUBHtJcWR/062wYrHBYRxJH
+qVXOpYKbIWwFKoXu3hcpg/CkdOlDWGKoZKBCwQwUBhWE7MDhpVdQ+ZljUJWL+FlK
+yQK5iRsJd5TGJ6VUzLzdT4fmN2DzeK6GLeyMpVpU3sWV90JJbxWQ4YrzkKzYhMmB
+EcpXTG2wm+ujiHU/k2p8zlf8Sm7VBM/scmnMFt0ynNXop4FWvJzEm1G0xD2t+e2I
+5Utr04dOZPCgkm++QJgYhtZvgW7ZZiGTAgMBAAGjUjBQMA4GA1UdDwEB/wQEAwIF
+oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBsGA1UdEQQUMBKC
+EHRlc3QuZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggEBADpqKQxrthH5InC7
+X96UP0OJCu/lLEMkrjoEWYIQaFl7uLPxKH5AmQPH4lYwF7u7gksR7owVG9QU9fs6
+1fK7II9CVgCd/4tZ0zm98FmU4D0lHGtPARrrzoZaqVZcAvRnFTlPX5pFkPhVjjai
+/mkxX9LpD8oK1445DFHxK5UjLMmPIIWd8EOi+v5a+hgGwnJpoW7hntSl8kHMtTmy
+fnnktsblSUV4lRCit0ymC7Ojhe+gzCCwkgs5kDzVVag+tnl/0e2DloIjASwOhpbH
+KVcg7fBd484ht/sS+l0dsB4KDOSpd8JzVDMF8OZqlaydizoJO0yWr9GbCN1+OKq5
+EhLrEqU=
-----END CERTIFICATE-----`
func TestCRLCreation(t *testing.T) {
@@ -779,17 +850,31 @@ func TestCRLCreation(t *testing.T) {
block, _ = pem.Decode([]byte(pemCertificate))
cert, _ := ParseCertificate(block.Bytes)
- now := time.Unix(1000, 0)
+ loc := time.FixedZone("Oz/Atlantis", int((2 * time.Hour).Seconds()))
+
+ now := time.Unix(1000, 0).In(loc)
+ nowUTC := now.UTC()
expiry := time.Unix(10000, 0)
revokedCerts := []pkix.RevokedCertificate{
{
SerialNumber: big.NewInt(1),
+ RevocationTime: nowUTC,
+ },
+ {
+ SerialNumber: big.NewInt(42),
+ // RevocationTime should be converted to UTC before marshaling.
RevocationTime: now,
},
+ }
+ expectedCerts := []pkix.RevokedCertificate{
+ {
+ SerialNumber: big.NewInt(1),
+ RevocationTime: nowUTC,
+ },
{
SerialNumber: big.NewInt(42),
- RevocationTime: now,
+ RevocationTime: nowUTC,
},
}
@@ -798,10 +883,14 @@ func TestCRLCreation(t *testing.T) {
t.Errorf("error creating CRL: %s", err)
}
- _, err = ParseDERCRL(crlBytes)
+ parsedCRL, err := ParseDERCRL(crlBytes)
if err != nil {
t.Errorf("error reparsing CRL: %s", err)
}
+ if !reflect.DeepEqual(parsedCRL.TBSCertList.RevokedCertificates, expectedCerts) {
+ t.Errorf("RevokedCertificates mismatch: got %v; want %v.",
+ parsedCRL.TBSCertList.RevokedCertificates, expectedCerts)
+ }
}
func fromBase64(in string) []byte {
@@ -867,7 +956,7 @@ func TestParsePEMCRL(t *testing.T) {
func TestImports(t *testing.T) {
testenv.MustHaveGoRun(t)
- if err := exec.Command("go", "run", "x509_test_import.go").Run(); err != nil {
+ if err := exec.Command(testenv.GoToolPath(t), "run", "x509_test_import.go").Run(); err != nil {
t.Errorf("failed to run x509_test_import.go: %s", err)
}
}
@@ -1284,3 +1373,112 @@ func TestMD5(t *testing.T) {
t.Fatalf("certificate verification returned %v (%T), wanted InsecureAlgorithmError", err, err)
}
}
+
+// certMissingRSANULL contains an RSA public key where the AlgorithmIdentifer
+// parameters are omitted rather than being an ASN.1 NULL.
+const certMissingRSANULL = `
+-----BEGIN CERTIFICATE-----
+MIIB7TCCAVigAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD
+bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTExMTIwODA3NTUxMloXDTEyMTIwNzA4
+MDAxMlowJjEQMA4GA1UEChMHQWNtZSBDbzESMBAGA1UEAxMJMTI3LjAuMC4xMIGc
+MAsGCSqGSIb3DQEBAQOBjAAwgYgCgYBO0Hsx44Jk2VnAwoekXh6LczPHY1PfZpIG
+hPZk1Y/kNqcdK+izIDZFI7Xjla7t4PUgnI2V339aEu+H5Fto5OkOdOwEin/ekyfE
+ARl6vfLcPRSr0FTKIQzQTW6HLlzF0rtNS0/Otiz3fojsfNcCkXSmHgwa2uNKWi7e
+E5xMQIhZkwIDAQABozIwMDAOBgNVHQ8BAf8EBAMCAKAwDQYDVR0OBAYEBAECAwQw
+DwYDVR0jBAgwBoAEAQIDBDALBgkqhkiG9w0BAQUDgYEANh+zegx1yW43RmEr1b3A
+p0vMRpqBWHyFeSnIyMZn3TJWRSt1tukkqVCavh9a+hoV2cxVlXIWg7nCto/9iIw4
+hB2rXZIxE0/9gzvGnfERYraL7KtnvshksBFQRlgXa5kc0x38BvEO5ZaoDPl4ILdE
+GFGNEH5PlGffo05wc46QkYU=
+-----END CERTIFICATE-----`
+
+func TestRSAMissingNULLParameters(t *testing.T) {
+ block, _ := pem.Decode([]byte(certMissingRSANULL))
+ if _, err := ParseCertificate(block.Bytes); err == nil {
+ t.Error("unexpected success when parsing certificate with missing RSA NULL parameter")
+ } else if !strings.Contains(err.Error(), "missing NULL") {
+ t.Errorf("unrecognised error when parsing certificate with missing RSA NULL parameter: %s", err)
+ }
+}
+
+const certISOOID = `
+-----BEGIN CERTIFICATE-----
+MIIB5TCCAVKgAwIBAgIQtwyL3RPWV7dJQp34HwZG9DAJBgUrDgMCHQUAMBExDzAN
+BgNVBAMTBm15dGVzdDAeFw0xNjA4MDkyMjExMDVaFw0zOTEyMzEyMzU5NTlaMBEx
+DzANBgNVBAMTBm15dGVzdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArzIH
+GsyDB3ohIGkkvijF2PTRUX1bvOtY1eUUpjwHyu0twpAKSuaQv2Ha+/63+aHe8O86
+BT+98wjXFX6RFSagtAujo80rIF2dSm33BGt18pDN8v6zp93dnAm0jRaSQrHJ75xw
+5O+S1oEYR1LtUoFJy6qB104j6aINBAgOiLIKiMkCAwEAAaNGMEQwQgYDVR0BBDsw
+OYAQVuYVQ/WDjdGSkZRlTtJDNKETMBExDzANBgNVBAMTBm15dGVzdIIQtwyL3RPW
+V7dJQp34HwZG9DAJBgUrDgMCHQUAA4GBABngrSkH7vG5lY4sa4AZF59lAAXqBVJE
+J4TBiKC62hCdZv18rBleP6ETfhbPg7pTs8p4ebQbpmtNxRS9Lw3MzQ8Ya5Ybwzj2
+NwBSyCtCQl7mrEg4nJqJl4A2EUhnET/oVxU0oTV/SZ3ziGXcY1oG1s6vidV7TZTu
+MCRtdSdaM7g3
+-----END CERTIFICATE-----`
+
+func TestISOOIDInCertificate(t *testing.T) {
+ block, _ := pem.Decode([]byte(certISOOID))
+ if cert, err := ParseCertificate(block.Bytes); err != nil {
+ t.Errorf("certificate with ISO OID failed to parse: %s", err)
+ } else if cert.SignatureAlgorithm == UnknownSignatureAlgorithm {
+ t.Errorf("ISO OID not recognised in certificate")
+ }
+}
+
+// certMultipleRDN contains a RelativeDistinguishedName with two elements (the
+// common name and serial number). This particular certificate was the first
+// such certificate in the “Pilot” Certificate Transparency log.
+const certMultipleRDN = `
+-----BEGIN CERTIFICATE-----
+MIIFRzCCBC+gAwIBAgIEOl59NTANBgkqhkiG9w0BAQUFADA9MQswCQYDVQQGEwJz
+aTEbMBkGA1UEChMSc3RhdGUtaW5zdGl0dXRpb25zMREwDwYDVQQLEwhzaWdvdi1j
+YTAeFw0xMjExMTYxMDUyNTdaFw0xNzExMTYxMjQ5MDVaMIGLMQswCQYDVQQGEwJz
+aTEbMBkGA1UEChMSc3RhdGUtaW5zdGl0dXRpb25zMRkwFwYDVQQLExB3ZWItY2Vy
+dGlmaWNhdGVzMRAwDgYDVQQLEwdTZXJ2ZXJzMTIwFAYDVQQFEw0xMjM2NDg0MDEw
+MDEwMBoGA1UEAxMTZXBvcnRhbC5tc3MuZWR1cy5zaTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAMrNkZH9MPuBTjMGNk3sJX8V+CkFx/4ru7RTlLS6dlYM
+098dtSfJ3s2w0p/1NB9UmR8j0yS0Kg6yoZ3ShsSO4DWBtcQD8820a6BYwqxxQTNf
+HSRZOc+N/4TQrvmK6t4k9Aw+YEYTMrWOU4UTeyhDeCcUsBdh7HjfWsVaqNky+2sv
+oic3zP5gF+2QfPkvOoHT3FLR8olNhViIE6Kk3eFIEs4dkq/ZzlYdLb8pHQoj/sGI
+zFmA5AFvm1HURqOmJriFjBwaCtn8AVEYOtQrnUCzJYu1ex8azyS2ZgYMX0u8A5Z/
+y2aMS/B2W+H79WcgLpK28vPwe7vam0oFrVytAd+u65ECAwEAAaOCAf4wggH6MA4G
+A1UdDwEB/wQEAwIFoDBABgNVHSAEOTA3MDUGCisGAQQBr1kBAwMwJzAlBggrBgEF
+BQcCARYZaHR0cDovL3d3dy5jYS5nb3Yuc2kvY3BzLzAfBgNVHREEGDAWgRRwb2Rw
+b3JhLm1pemtzQGdvdi5zaTCB8QYDVR0fBIHpMIHmMFWgU6BRpE8wTTELMAkGA1UE
+BhMCc2kxGzAZBgNVBAoTEnN0YXRlLWluc3RpdHV0aW9uczERMA8GA1UECxMIc2ln
+b3YtY2ExDjAMBgNVBAMTBUNSTDM5MIGMoIGJoIGGhldsZGFwOi8veDUwMC5nb3Yu
+c2kvb3U9c2lnb3YtY2Esbz1zdGF0ZS1pbnN0aXR1dGlvbnMsYz1zaT9jZXJ0aWZp
+Y2F0ZVJldm9jYXRpb25MaXN0P2Jhc2WGK2h0dHA6Ly93d3cuc2lnb3YtY2EuZ292
+LnNpL2NybC9zaWdvdi1jYS5jcmwwKwYDVR0QBCQwIoAPMjAxMjExMTYxMDUyNTda
+gQ8yMDE3MTExNjEyNDkwNVowHwYDVR0jBBgwFoAUHvjUU2uzgwbpBAZXAvmlv8ZY
+PHIwHQYDVR0OBBYEFGI1Duuu+wTGDZka/xHNbwcbM69ZMAkGA1UdEwQCMAAwGQYJ
+KoZIhvZ9B0EABAwwChsEVjcuMQMCA6gwDQYJKoZIhvcNAQEFBQADggEBAHny0K1y
+BQznrzDu3DDpBcGYguKU0dvU9rqsV1ua4nxkriSMWjgsX6XJFDdDW60I3P4VWab5
+ag5fZzbGqi8kva/CzGgZh+CES0aWCPy+4Gb8lwOTt+854/laaJvd6kgKTER7z7U9
+9C86Ch2y4sXNwwwPJ1A9dmrZJZOcJjS/WYZgwaafY2Hdxub5jqPE5nehwYUPVu9R
+uH6/skk4OEKcfOtN0hCnISOVuKYyS4ANARWRG5VGHIH06z3lGUVARFRJ61gtAprd
+La+fgSS+LVZ+kU2TkeoWAKvGq8MAgDq4D4Xqwekg7WKFeuyusi/NI5rm40XgjBMF
+DF72IUofoVt7wo0=
+-----END CERTIFICATE-----`
+
+func TestMultipleRDN(t *testing.T) {
+ block, _ := pem.Decode([]byte(certMultipleRDN))
+ cert, err := ParseCertificate(block.Bytes)
+ if err != nil {
+ t.Fatalf("certificate with two elements in an RDN failed to parse: %v", err)
+ }
+
+ if want := "eportal.mss.edus.si"; cert.Subject.CommonName != want {
+ t.Errorf("got common name of %q, but want %q", cert.Subject.CommonName, want)
+ }
+
+ if want := "1236484010010"; cert.Subject.SerialNumber != want {
+ t.Errorf("got serial number of %q, but want %q", cert.Subject.SerialNumber, want)
+ }
+}
+
+func TestSystemCertPool(t *testing.T) {
+ _, err := SystemCertPool()
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/libgo/go/database/sql/convert.go b/libgo/go/database/sql/convert.go
index 99aed2398e2..ea2f377810e 100644
--- a/libgo/go/database/sql/convert.go
+++ b/libgo/go/database/sql/convert.go
@@ -13,16 +13,36 @@ import (
"reflect"
"strconv"
"time"
+ "unicode"
+ "unicode/utf8"
)
var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
+func describeNamedValue(nv *driver.NamedValue) string {
+ if len(nv.Name) == 0 {
+ return fmt.Sprintf("$%d", nv.Ordinal)
+ }
+ return fmt.Sprintf("with name %q", nv.Name)
+}
+
+func validateNamedValueName(name string) error {
+ if len(name) == 0 {
+ return nil
+ }
+ r, _ := utf8.DecodeRuneInString(name)
+ if unicode.IsLetter(r) {
+ return nil
+ }
+ return fmt.Errorf("name %q does not begin with a letter", name)
+}
+
// driverArgs converts arguments from callers of Stmt.Exec and
// Stmt.Query into driver Values.
//
// The statement ds may be nil, if no statement is available.
-func driverArgs(ds *driverStmt, args []interface{}) ([]driver.Value, error) {
- dargs := make([]driver.Value, len(args))
+func driverArgs(ds *driverStmt, args []interface{}) ([]driver.NamedValue, error) {
+ nvargs := make([]driver.NamedValue, len(args))
var si driver.Stmt
if ds != nil {
si = ds.si
@@ -33,26 +53,45 @@ func driverArgs(ds *driverStmt, args []interface{}) ([]driver.Value, error) {
if !ok {
for n, arg := range args {
var err error
- dargs[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
+ nv := &nvargs[n]
+ nv.Ordinal = n + 1
+ if np, ok := arg.(NamedArg); ok {
+ if err := validateNamedValueName(np.Name); err != nil {
+ return nil, err
+ }
+ arg = np.Value
+ nvargs[n].Name = np.Name
+ }
+ nv.Value, err = driver.DefaultParameterConverter.ConvertValue(arg)
+
if err != nil {
- return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
+ return nil, fmt.Errorf("sql: converting Exec argument %s type: %v", describeNamedValue(nv), err)
}
}
- return dargs, nil
+ return nvargs, nil
}
// Let the Stmt convert its own arguments.
for n, arg := range args {
+ nv := &nvargs[n]
+ nv.Ordinal = n + 1
+ if np, ok := arg.(NamedArg); ok {
+ if err := validateNamedValueName(np.Name); err != nil {
+ return nil, err
+ }
+ arg = np.Value
+ nv.Name = np.Name
+ }
// First, see if the value itself knows how to convert
// itself to a driver type. For example, a NullString
// struct changing into a string or nil.
- if svi, ok := arg.(driver.Valuer); ok {
- sv, err := svi.Value()
+ if vr, ok := arg.(driver.Valuer); ok {
+ sv, err := callValuerValue(vr)
if err != nil {
- return nil, fmt.Errorf("sql: argument index %d from Value: %v", n, err)
+ return nil, fmt.Errorf("sql: argument %s from Value: %v", describeNamedValue(nv), err)
}
if !driver.IsValue(sv) {
- return nil, fmt.Errorf("sql: argument index %d: non-subset type %T returned from Value", n, sv)
+ return nil, fmt.Errorf("sql: argument %s: non-subset type %T returned from Value", describeNamedValue(nv), sv)
}
arg = sv
}
@@ -66,18 +105,18 @@ func driverArgs(ds *driverStmt, args []interface{}) ([]driver.Value, error) {
// same error.
var err error
ds.Lock()
- dargs[n], err = cc.ColumnConverter(n).ConvertValue(arg)
+ nv.Value, err = cc.ColumnConverter(n).ConvertValue(arg)
ds.Unlock()
if err != nil {
- return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n, err)
+ return nil, fmt.Errorf("sql: converting argument %s type: %v", describeNamedValue(nv), err)
}
- if !driver.IsValue(dargs[n]) {
- return nil, fmt.Errorf("sql: driver ColumnConverter error converted %T to unsupported type %T",
- arg, dargs[n])
+ if !driver.IsValue(nv.Value) {
+ return nil, fmt.Errorf("sql: for argument %s, driver ColumnConverter error converted %T to unsupported type %T",
+ describeNamedValue(nv), arg, nv.Value)
}
}
- return dargs, nil
+ return nvargs, nil
}
// convertAssign copies to dest the value in src, converting it if possible.
@@ -330,3 +369,25 @@ func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) {
}
return
}
+
+var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
+
+// callValuerValue returns vr.Value(), with one exception:
+// If vr.Value is an auto-generated method on a pointer type and the
+// pointer is nil, it would panic at runtime in the panicwrap
+// method. Treat it like nil instead.
+// Issue 8415.
+//
+// This is so people can implement driver.Value on value types and
+// still use nil pointers to those types to mean nil/NULL, just like
+// string/*string.
+//
+// This function is mirrored in the database/sql/driver package.
+func callValuerValue(vr driver.Valuer) (v driver.Value, err error) {
+ if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
+ rv.IsNil() &&
+ rv.Type().Elem().Implements(valuerReflectType) {
+ return nil, nil
+ }
+ return vr.Value()
+}
diff --git a/libgo/go/database/sql/convert_test.go b/libgo/go/database/sql/convert_test.go
index ab81f2f65a2..4dfab1f6bef 100644
--- a/libgo/go/database/sql/convert_test.go
+++ b/libgo/go/database/sql/convert_test.go
@@ -9,6 +9,7 @@ import (
"fmt"
"reflect"
"runtime"
+ "strings"
"testing"
"time"
)
@@ -389,3 +390,85 @@ func TestUserDefinedBytes(t *testing.T) {
t.Fatal("userDefinedBytes got potentially dirty driver memory")
}
}
+
+type Valuer_V string
+
+func (v Valuer_V) Value() (driver.Value, error) {
+ return strings.ToUpper(string(v)), nil
+}
+
+type Valuer_P string
+
+func (p *Valuer_P) Value() (driver.Value, error) {
+ if p == nil {
+ return "nil-to-str", nil
+ }
+ return strings.ToUpper(string(*p)), nil
+}
+
+func TestDriverArgs(t *testing.T) {
+ var nilValuerVPtr *Valuer_V
+ var nilValuerPPtr *Valuer_P
+ var nilStrPtr *string
+ tests := []struct {
+ args []interface{}
+ want []driver.NamedValue
+ }{
+ 0: {
+ args: []interface{}{Valuer_V("foo")},
+ want: []driver.NamedValue{
+ driver.NamedValue{
+ Ordinal: 1,
+ Value: "FOO",
+ },
+ },
+ },
+ 1: {
+ args: []interface{}{nilValuerVPtr},
+ want: []driver.NamedValue{
+ driver.NamedValue{
+ Ordinal: 1,
+ Value: nil,
+ },
+ },
+ },
+ 2: {
+ args: []interface{}{nilValuerPPtr},
+ want: []driver.NamedValue{
+ driver.NamedValue{
+ Ordinal: 1,
+ Value: "nil-to-str",
+ },
+ },
+ },
+ 3: {
+ args: []interface{}{"plain-str"},
+ want: []driver.NamedValue{
+ driver.NamedValue{
+ Ordinal: 1,
+ Value: "plain-str",
+ },
+ },
+ },
+ 4: {
+ args: []interface{}{nilStrPtr},
+ want: []driver.NamedValue{
+ driver.NamedValue{
+ Ordinal: 1,
+ Value: nil,
+ },
+ },
+ },
+ }
+ for i, tt := range tests {
+ ds := new(driverStmt)
+ got, err := driverArgs(ds, tt.args)
+ if err != nil {
+ t.Errorf("test[%d]: %v", i, err)
+ continue
+ }
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("test[%d]: got %v, want %v", i, got, tt.want)
+ }
+ }
+}
diff --git a/libgo/go/database/sql/ctxutil.go b/libgo/go/database/sql/ctxutil.go
new file mode 100644
index 00000000000..1071446227f
--- /dev/null
+++ b/libgo/go/database/sql/ctxutil.go
@@ -0,0 +1,163 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sql
+
+import (
+ "context"
+ "database/sql/driver"
+ "errors"
+)
+
+func ctxDriverPrepare(ctx context.Context, ci driver.Conn, query string) (driver.Stmt, error) {
+ if ciCtx, is := ci.(driver.ConnPrepareContext); is {
+ return ciCtx.PrepareContext(ctx, query)
+ }
+ si, err := ci.Prepare(query)
+ if err == nil {
+ select {
+ default:
+ case <-ctx.Done():
+ si.Close()
+ return nil, ctx.Err()
+ }
+ }
+ return si, err
+}
+
+func ctxDriverExec(ctx context.Context, execer driver.Execer, query string, nvdargs []driver.NamedValue) (driver.Result, error) {
+ if execerCtx, is := execer.(driver.ExecerContext); is {
+ return execerCtx.ExecContext(ctx, query, nvdargs)
+ }
+ dargs, err := namedValueToValue(nvdargs)
+ if err != nil {
+ return nil, err
+ }
+
+ resi, err := execer.Exec(query, dargs)
+ if err == nil {
+ select {
+ default:
+ case <-ctx.Done():
+ return resi, ctx.Err()
+ }
+ }
+ return resi, err
+}
+
+func ctxDriverQuery(ctx context.Context, queryer driver.Queryer, query string, nvdargs []driver.NamedValue) (driver.Rows, error) {
+ if queryerCtx, is := queryer.(driver.QueryerContext); is {
+ ret, err := queryerCtx.QueryContext(ctx, query, nvdargs)
+ return ret, err
+ }
+ dargs, err := namedValueToValue(nvdargs)
+ if err != nil {
+ return nil, err
+ }
+
+ rowsi, err := queryer.Query(query, dargs)
+ if err == nil {
+ select {
+ default:
+ case <-ctx.Done():
+ rowsi.Close()
+ return nil, ctx.Err()
+ }
+ }
+ return rowsi, err
+}
+
+func ctxDriverStmtExec(ctx context.Context, si driver.Stmt, nvdargs []driver.NamedValue) (driver.Result, error) {
+ if siCtx, is := si.(driver.StmtExecContext); is {
+ return siCtx.ExecContext(ctx, nvdargs)
+ }
+ dargs, err := namedValueToValue(nvdargs)
+ if err != nil {
+ return nil, err
+ }
+
+ resi, err := si.Exec(dargs)
+ if err == nil {
+ select {
+ default:
+ case <-ctx.Done():
+ return resi, ctx.Err()
+ }
+ }
+ return resi, err
+}
+
+func ctxDriverStmtQuery(ctx context.Context, si driver.Stmt, nvdargs []driver.NamedValue) (driver.Rows, error) {
+ if siCtx, is := si.(driver.StmtQueryContext); is {
+ return siCtx.QueryContext(ctx, nvdargs)
+ }
+ dargs, err := namedValueToValue(nvdargs)
+ if err != nil {
+ return nil, err
+ }
+
+ rowsi, err := si.Query(dargs)
+ if err == nil {
+ select {
+ default:
+ case <-ctx.Done():
+ rowsi.Close()
+ return nil, ctx.Err()
+ }
+ }
+ return rowsi, err
+}
+
+var errLevelNotSupported = errors.New("sql: selected isolation level is not supported")
+
+func ctxDriverBegin(ctx context.Context, opts *TxOptions, ci driver.Conn) (driver.Tx, error) {
+ if ciCtx, is := ci.(driver.ConnBeginTx); is {
+ dopts := driver.TxOptions{}
+ if opts != nil {
+ dopts.Isolation = driver.IsolationLevel(opts.Isolation)
+ dopts.ReadOnly = opts.ReadOnly
+ }
+ return ciCtx.BeginTx(ctx, dopts)
+ }
+
+ if ctx.Done() == context.Background().Done() {
+ return ci.Begin()
+ }
+
+ if opts != nil {
+ // Check the transaction level. If the transaction level is non-default
+ // then return an error here as the BeginTx driver value is not supported.
+ if opts.Isolation != LevelDefault {
+ return nil, errors.New("sql: driver does not support non-default isolation level")
+ }
+
+ // If a read-only transaction is requested return an error as the
+ // BeginTx driver value is not supported.
+ if opts.ReadOnly {
+ return nil, errors.New("sql: driver does not support read-only transactions")
+ }
+ }
+
+ txi, err := ci.Begin()
+ if err == nil {
+ select {
+ default:
+ case <-ctx.Done():
+ txi.Rollback()
+ return nil, ctx.Err()
+ }
+ }
+ return txi, err
+}
+
+func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) {
+ dargs := make([]driver.Value, len(named))
+ for n, param := range named {
+ if len(param.Name) > 0 {
+ return nil, errors.New("sql: driver does not support the use of Named Parameters")
+ }
+ dargs[n] = param.Value
+ }
+ return dargs, nil
+}
diff --git a/libgo/go/database/sql/driver/driver.go b/libgo/go/database/sql/driver/driver.go
index 4dba85a6d34..d66196fd481 100644
--- a/libgo/go/database/sql/driver/driver.go
+++ b/libgo/go/database/sql/driver/driver.go
@@ -8,7 +8,11 @@
// Most code should use package sql.
package driver
-import "errors"
+import (
+ "context"
+ "errors"
+ "reflect"
+)
// Value is a value that drivers must be able to handle.
// It is either nil or an instance of one of these types:
@@ -21,6 +25,21 @@ import "errors"
// time.Time
type Value interface{}
+// NamedValue holds both the value name and value.
+type NamedValue struct {
+ // If the Name is not empty it should be used for the parameter identifier and
+ // not the ordinal position.
+ //
+ // Name will not have a symbol prefix.
+ Name string
+
+ // Ordinal position of the parameter starting from one and is always set.
+ Ordinal int
+
+ // Value is the parameter value.
+ Value Value
+}
+
// Driver is the interface that must be implemented by a database
// driver.
type Driver interface {
@@ -54,6 +73,17 @@ var ErrSkip = errors.New("driver: skip fast-path; continue as if unimplemented")
// you shouldn't return ErrBadConn.
var ErrBadConn = errors.New("driver: bad connection")
+// Pinger is an optional interface that may be implemented by a Conn.
+//
+// If a Conn does not implement Pinger, the sql package's DB.Ping and
+// DB.PingContext will check if there is at least one Conn available.
+//
+// If Conn.Ping returns ErrBadConn, DB.Ping and DB.PingContext will remove
+// the Conn from pool.
+type Pinger interface {
+ Ping(ctx context.Context) error
+}
+
// Execer is an optional interface that may be implemented by a Conn.
//
// If a Conn does not implement Execer, the sql package's DB.Exec will
@@ -61,10 +91,25 @@ var ErrBadConn = errors.New("driver: bad connection")
// statement.
//
// Exec may return ErrSkip.
+//
+// Deprecated: Drivers should implement ExecerContext instead (or additionally).
type Execer interface {
Exec(query string, args []Value) (Result, error)
}
+// ExecerContext is an optional interface that may be implemented by a Conn.
+//
+// If a Conn does not implement ExecerContext, the sql package's DB.Exec will
+// first prepare a query, execute the statement, and then close the
+// statement.
+//
+// ExecerContext may return ErrSkip.
+//
+// ExecerContext must honor the context timeout and return when the context is canceled.
+type ExecerContext interface {
+ ExecContext(ctx context.Context, query string, args []NamedValue) (Result, error)
+}
+
// Queryer is an optional interface that may be implemented by a Conn.
//
// If a Conn does not implement Queryer, the sql package's DB.Query will
@@ -72,10 +117,25 @@ type Execer interface {
// statement.
//
// Query may return ErrSkip.
+//
+// Deprecated: Drivers should implement QueryerContext instead (or additionally).
type Queryer interface {
Query(query string, args []Value) (Rows, error)
}
+// QueryerContext is an optional interface that may be implemented by a Conn.
+//
+// If a Conn does not implement QueryerContext, the sql package's DB.Query will
+// first prepare a query, execute the statement, and then close the
+// statement.
+//
+// QueryerContext may return ErrSkip.
+//
+// QueryerContext must honor the context timeout and return when the context is canceled.
+type QueryerContext interface {
+ QueryContext(ctx context.Context, query string, args []NamedValue) (Rows, error)
+}
+
// Conn is a connection to a database. It is not used concurrently
// by multiple goroutines.
//
@@ -95,9 +155,50 @@ type Conn interface {
Close() error
// Begin starts and returns a new transaction.
+ //
+ // Deprecated: Drivers should implement ConnBeginTx instead (or additionally).
Begin() (Tx, error)
}
+// ConnPrepareContext enhances the Conn interface with context.
+type ConnPrepareContext interface {
+ // PrepareContext returns a prepared statement, bound to this connection.
+ // context is for the preparation of the statement,
+ // it must not store the context within the statement itself.
+ PrepareContext(ctx context.Context, query string) (Stmt, error)
+}
+
+// IsolationLevel is the transaction isolation level stored in TxOptions.
+//
+// This type should be considered identical to sql.IsolationLevel along
+// with any values defined on it.
+type IsolationLevel int
+
+// TxOptions holds the transaction options.
+//
+// This type should be considered identical to sql.TxOptions.
+type TxOptions struct {
+ Isolation IsolationLevel
+ ReadOnly bool
+}
+
+// ConnBeginTx enhances the Conn interface with context and TxOptions.
+type ConnBeginTx interface {
+ // BeginTx starts and returns a new transaction.
+ // If the context is canceled by the user the sql package will
+ // call Tx.Rollback before discarding and closing the connection.
+ //
+ // This must check opts.Isolation to determine if there is a set
+ // isolation level. If the driver does not support a non-default
+ // level and one is set or if there is a non-default isolation level
+ // that is not supported, an error must be returned.
+ //
+ // This must also check opts.ReadOnly to determine if the read-only
+ // value is true to either set the read-only transaction property if supported
+ // or return an error if it is not supported.
+ BeginTx(ctx context.Context, opts TxOptions) (Tx, error)
+}
+
// Result is the result of a query execution.
type Result interface {
// LastInsertId returns the database's auto-generated ID
@@ -132,13 +233,35 @@ type Stmt interface {
// Exec executes a query that doesn't return rows, such
// as an INSERT or UPDATE.
+ //
+ // Deprecated: Drivers should implement StmtExecContext instead (or additionally).
Exec(args []Value) (Result, error)
// Query executes a query that may return rows, such as a
// SELECT.
+ //
+ // Deprecated: Drivers should implement StmtQueryContext instead (or additionally).
Query(args []Value) (Rows, error)
}
+// StmtExecContext enhances the Stmt interface by providing Exec with context.
+type StmtExecContext interface {
+ // ExecContext executes a query that doesn't return rows, such
+ // as an INSERT or UPDATE.
+ //
+ // ExecContext must honor the context timeout and return when it is canceled.
+ ExecContext(ctx context.Context, args []NamedValue) (Result, error)
+}
+
+// StmtQueryContext enhances the Stmt interface by providing Query with context.
+type StmtQueryContext interface {
+ // QueryContext executes a query that may return rows, such as a
+ // SELECT.
+ //
+ // QueryContext must honor the context timeout and return when it is canceled.
+ QueryContext(ctx context.Context, args []NamedValue) (Rows, error)
+}
+
// ColumnConverter may be optionally implemented by Stmt if the
// statement is aware of its own columns' types and can convert from
// any type to a driver Value.
@@ -169,6 +292,76 @@ type Rows interface {
Next(dest []Value) error
}
+// RowsNextResultSet extends the Rows interface by providing a way to signal
+// the driver to advance to the next result set.
+type RowsNextResultSet interface {
+ Rows
+
+ // HasNextResultSet is called at the end of the current result set and
+ // reports whether there is another result set after the current one.
+ HasNextResultSet() bool
+
+ // NextResultSet advances the driver to the next result set even
+ // if there are remaining rows in the current result set.
+ //
+ // NextResultSet should return io.EOF when there are no more result sets.
+ NextResultSet() error
+}
+
+// RowsColumnTypeScanType may be implemented by Rows. It should return
+// the value type that can be used to scan types into. For example, the database
+// column type "bigint" this should return "reflect.TypeOf(int64(0))".
+type RowsColumnTypeScanType interface {
+ Rows
+ ColumnTypeScanType(index int) reflect.Type
+}
+
+// RowsColumnTypeDatabaseTypeName may be implemented by Rows. It should return the
+// database system type name without the length. Type names should be uppercase.
+// Examples of returned types: "VARCHAR", "NVARCHAR", "VARCHAR2", "CHAR", "TEXT",
+// "DECIMAL", "SMALLINT", "INT", "BIGINT", "BOOL", "[]BIGINT", "JSONB", "XML",
+// "TIMESTAMP".
+type RowsColumnTypeDatabaseTypeName interface {
+ Rows
+ ColumnTypeDatabaseTypeName(index int) string
+}
+
+// RowsColumnTypeLength may be implemented by Rows. It should return the length
+// of the column type if the column is a variable length type. If the column is
+// not a variable length type ok should return false.
+// If length is not limited other than system limits, it should return math.MaxInt64.
+// The following are examples of returned values for various types:
+// TEXT (math.MaxInt64, true)
+// varchar(10) (10, true)
+// nvarchar(10) (10, true)
+// decimal (0, false)
+// int (0, false)
+// bytea(30) (30, true)
+type RowsColumnTypeLength interface {
+ Rows
+ ColumnTypeLength(index int) (length int64, ok bool)
+}
+
+// RowsColumnTypeNullable may be implemented by Rows. The nullable value should
+// be true if it is known the column may be null, or false if the column is known
+// to be not nullable.
+// If the column nullability is unknown, ok should be false.
+type RowsColumnTypeNullable interface {
+ Rows
+ ColumnTypeNullable(index int) (nullable, ok bool)
+}
+
+// RowsColumnTypePrecisionScale may be implemented by Rows. It should return
+// the precision and scale for decimal types. If not applicable, ok should be false.
+// The following are examples of returned values for various types:
+// decimal(38, 4) (38, 4, true)
+// int (0, 0, false)
+// decimal (math.MaxInt64, math.MaxInt64, true)
+type RowsColumnTypePrecisionScale interface {
+ Rows
+ ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool)
+}
+
// Tx is a transaction.
type Tx interface {
Commit() error
diff --git a/libgo/go/database/sql/driver/types.go b/libgo/go/database/sql/driver/types.go
index e480e701a49..8b3cb6c8f61 100644
--- a/libgo/go/database/sql/driver/types.go
+++ b/libgo/go/database/sql/driver/types.go
@@ -198,9 +198,9 @@ func IsScanValue(v interface{}) bool {
// Value method is used to return a Value. As a fallback, the provided
// argument's underlying type is used to convert it to a Value:
// underlying integer types are converted to int64, floats to float64,
-// and strings to []byte. If the argument is a nil pointer,
-// ConvertValue returns a nil Value. If the argument is a non-nil
-// pointer, it is dereferenced and ConvertValue is called
+// bool, string, and []byte to themselves. If the argument is a nil
+// pointer, ConvertValue returns a nil Value. If the argument is a
+// non-nil pointer, it is dereferenced and ConvertValue is called
// recursively. Other types are an error.
var DefaultParameterConverter defaultConverter
@@ -208,13 +208,35 @@ type defaultConverter struct{}
var _ ValueConverter = defaultConverter{}
+var valuerReflectType = reflect.TypeOf((*Valuer)(nil)).Elem()
+
+// callValuerValue returns vr.Value(), with one exception:
+// If vr.Value is an auto-generated method on a pointer type and the
+// pointer is nil, it would panic at runtime in the panicwrap
+// method. Treat it like nil instead.
+// Issue 8415.
+//
+// This is so people can implement driver.Value on value types and
+// still use nil pointers to those types to mean nil/NULL, just like
+// string/*string.
+//
+// This function is mirrored in the database/sql package.
+func callValuerValue(vr Valuer) (v Value, err error) {
+ if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
+ rv.IsNil() &&
+ rv.Type().Elem().Implements(valuerReflectType) {
+ return nil, nil
+ }
+ return vr.Value()
+}
+
func (defaultConverter) ConvertValue(v interface{}) (Value, error) {
if IsValue(v) {
return v, nil
}
- if svi, ok := v.(Valuer); ok {
- sv, err := svi.Value()
+ if vr, ok := v.(Valuer); ok {
+ sv, err := callValuerValue(vr)
if err != nil {
return nil, err
}
@@ -245,6 +267,16 @@ func (defaultConverter) ConvertValue(v interface{}) (Value, error) {
return int64(u64), nil
case reflect.Float32, reflect.Float64:
return rv.Float(), nil
+ case reflect.Bool:
+ return rv.Bool(), nil
+ case reflect.Slice:
+ ek := rv.Type().Elem().Kind()
+ if ek == reflect.Uint8 {
+ return rv.Bytes(), nil
+ }
+ return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
+ case reflect.String:
+ return rv.String(), nil
}
return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
}
diff --git a/libgo/go/database/sql/driver/types_test.go b/libgo/go/database/sql/driver/types_test.go
index 1ce0ff06541..0379bf8892f 100644
--- a/libgo/go/database/sql/driver/types_test.go
+++ b/libgo/go/database/sql/driver/types_test.go
@@ -20,6 +20,16 @@ type valueConverterTest struct {
var now = time.Now()
var answer int64 = 42
+type (
+ i int64
+ f float64
+ b bool
+ bs []byte
+ s string
+ t time.Time
+ is []int
+)
+
var valueConverterTests = []valueConverterTest{
{Bool, "true", true, ""},
{Bool, "True", true, ""},
@@ -41,6 +51,12 @@ var valueConverterTests = []valueConverterTest{
{DefaultParameterConverter, (*int64)(nil), nil, ""},
{DefaultParameterConverter, &answer, answer, ""},
{DefaultParameterConverter, &now, now, ""},
+ {DefaultParameterConverter, i(9), int64(9), ""},
+ {DefaultParameterConverter, f(0.1), float64(0.1), ""},
+ {DefaultParameterConverter, b(true), true, ""},
+ {DefaultParameterConverter, bs{1}, []byte{1}, ""},
+ {DefaultParameterConverter, s("a"), "a", ""},
+ {DefaultParameterConverter, is{1}, nil, "unsupported type driver.is, a slice of int"},
}
func TestValueConverters(t *testing.T) {
diff --git a/libgo/go/database/sql/fakedb_test.go b/libgo/go/database/sql/fakedb_test.go
index 5b238bfc5cb..4b15f5bec7b 100644
--- a/libgo/go/database/sql/fakedb_test.go
+++ b/libgo/go/database/sql/fakedb_test.go
@@ -5,11 +5,13 @@
package sql
import (
+ "context"
"database/sql/driver"
"errors"
"fmt"
"io"
"log"
+ "reflect"
"sort"
"strconv"
"strings"
@@ -32,10 +34,16 @@ var _ = log.Printf
// where types are: "string", [u]int{8,16,32,64}, "bool"
// INSERT|<tablename>|col=val,col2=val2,col3=?
// SELECT|<tablename>|projectcol1,projectcol2|filtercol=?,filtercol2=?
+// SELECT|<tablename>|projectcol1,projectcol2|filtercol=?param1,filtercol2=?param2
//
// Any of these can be preceded by PANIC|<method>|, to cause the
// named method on fakeStmt to panic.
//
+// Any of these can be proceeded by WAIT|<duration>|, to cause the
+// named method on fakeStmt to sleep for the specified duration.
+//
+// Multiple of these can be combined when separated with a semicolon.
+//
// When opening a fakeDriver's database, it starts empty with no
// tables. All tables and data are stored in memory only.
type fakeDriver struct {
@@ -101,6 +109,12 @@ type fakeTx struct {
c *fakeConn
}
+type boundCol struct {
+ Column string
+ Placeholder string
+ Ordinal int
+}
+
type fakeStmt struct {
c *fakeConn
q string // just for debugging
@@ -108,6 +122,9 @@ type fakeStmt struct {
cmd string
table string
panic string
+ wait time.Duration
+
+ next *fakeStmt // used for returning multiple results.
closed bool
@@ -116,7 +133,7 @@ type fakeStmt struct {
colValue []interface{} // used by INSERT (mix of strings and "?" for bound params)
placeholders int // used by INSERT/SELECT: number of ? params
- whereCol []string // used by SELECT (all placeholders)
+ whereCol []boundCol // used by SELECT (all placeholders)
placeholderConverter []driver.ValueConverter // used by INSERT
}
@@ -335,18 +352,23 @@ func (c *fakeConn) Close() (err error) {
return nil
}
-func checkSubsetTypes(args []driver.Value) error {
- for n, arg := range args {
- switch arg.(type) {
+func checkSubsetTypes(args []driver.NamedValue) error {
+ for _, arg := range args {
+ switch arg.Value.(type) {
case int64, float64, bool, nil, []byte, string, time.Time:
default:
- return fmt.Errorf("fakedb_test: invalid argument #%d: %v, type %T", n+1, arg, arg)
+ return fmt.Errorf("fakedb_test: invalid argument ordinal %[1]d: %[2]v, type %[2]T", arg.Ordinal, arg.Value)
}
}
return nil
}
func (c *fakeConn) Exec(query string, args []driver.Value) (driver.Result, error) {
+ // Ensure that ExecContext is called if available.
+ panic("ExecContext was not called.")
+}
+
+func (c *fakeConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
// This is an optional interface, but it's implemented here
// just to check that all the args are of the proper types.
// ErrSkip is returned so the caller acts as if we didn't
@@ -359,6 +381,11 @@ func (c *fakeConn) Exec(query string, args []driver.Value) (driver.Result, error
}
func (c *fakeConn) Query(query string, args []driver.Value) (driver.Rows, error) {
+ // Ensure that ExecContext is called if available.
+ panic("QueryContext was not called.")
+}
+
+func (c *fakeConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
// This is an optional interface, but it's implemented here
// just to check that all the args are of the proper types.
// ErrSkip is returned so the caller acts as if we didn't
@@ -377,12 +404,13 @@ func errf(msg string, args ...interface{}) error {
// parts are table|selectCol1,selectCol2|whereCol=?,whereCol2=?
// (note that where columns must always contain ? marks,
// just a limitation for fakedb)
-func (c *fakeConn) prepareSelect(stmt *fakeStmt, parts []string) (driver.Stmt, error) {
+func (c *fakeConn) prepareSelect(stmt *fakeStmt, parts []string) (*fakeStmt, error) {
if len(parts) != 3 {
stmt.Close()
return nil, errf("invalid SELECT syntax with %d parts; want 3", len(parts))
}
stmt.table = parts[0]
+
stmt.colName = strings.Split(parts[1], ",")
for n, colspec := range strings.Split(parts[2], ",") {
if colspec == "" {
@@ -399,19 +427,19 @@ func (c *fakeConn) prepareSelect(stmt *fakeStmt, parts []string) (driver.Stmt, e
stmt.Close()
return nil, errf("SELECT on table %q references non-existent column %q", stmt.table, column)
}
- if value != "?" {
+ if !strings.HasPrefix(value, "?") {
stmt.Close()
return nil, errf("SELECT on table %q has pre-bound value for where column %q; need a question mark",
stmt.table, column)
}
- stmt.whereCol = append(stmt.whereCol, column)
stmt.placeholders++
+ stmt.whereCol = append(stmt.whereCol, boundCol{Column: column, Placeholder: value, Ordinal: stmt.placeholders})
}
return stmt, nil
}
// parts are table|col=type,col2=type2
-func (c *fakeConn) prepareCreate(stmt *fakeStmt, parts []string) (driver.Stmt, error) {
+func (c *fakeConn) prepareCreate(stmt *fakeStmt, parts []string) (*fakeStmt, error) {
if len(parts) != 2 {
stmt.Close()
return nil, errf("invalid CREATE syntax with %d parts; want 2", len(parts))
@@ -430,7 +458,7 @@ func (c *fakeConn) prepareCreate(stmt *fakeStmt, parts []string) (driver.Stmt, e
}
// parts are table|col=?,col2=val
-func (c *fakeConn) prepareInsert(stmt *fakeStmt, parts []string) (driver.Stmt, error) {
+func (c *fakeConn) prepareInsert(stmt *fakeStmt, parts []string) (*fakeStmt, error) {
if len(parts) != 2 {
stmt.Close()
return nil, errf("invalid INSERT syntax with %d parts; want 2", len(parts))
@@ -450,7 +478,7 @@ func (c *fakeConn) prepareInsert(stmt *fakeStmt, parts []string) (driver.Stmt, e
}
stmt.colName = append(stmt.colName, column)
- if value != "?" {
+ if !strings.HasPrefix(value, "?") {
var subsetVal interface{}
// Convert to driver subset type
switch ctype {
@@ -473,7 +501,7 @@ func (c *fakeConn) prepareInsert(stmt *fakeStmt, parts []string) (driver.Stmt, e
} else {
stmt.placeholders++
stmt.placeholderConverter = append(stmt.placeholderConverter, converterForType(ctype))
- stmt.colValue = append(stmt.colValue, "?")
+ stmt.colValue = append(stmt.colValue, value)
}
}
return stmt, nil
@@ -483,6 +511,10 @@ func (c *fakeConn) prepareInsert(stmt *fakeStmt, parts []string) (driver.Stmt, e
var hookPrepareBadConn func() bool
func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
+ panic("use PrepareContext")
+}
+
+func (c *fakeConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
c.numPrepare++
if c.db == nil {
panic("nil c.db; conn = " + fmt.Sprintf("%#v", c))
@@ -492,38 +524,72 @@ func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
return nil, driver.ErrBadConn
}
- parts := strings.Split(query, "|")
- if len(parts) < 1 {
- return nil, errf("empty query")
- }
- stmt := &fakeStmt{q: query, c: c}
- if len(parts) >= 3 && parts[0] == "PANIC" {
- stmt.panic = parts[1]
- parts = parts[2:]
- }
- cmd := parts[0]
- stmt.cmd = cmd
- parts = parts[1:]
+ var firstStmt, prev *fakeStmt
+ for _, query := range strings.Split(query, ";") {
+ parts := strings.Split(query, "|")
+ if len(parts) < 1 {
+ return nil, errf("empty query")
+ }
+ stmt := &fakeStmt{q: query, c: c}
+ if firstStmt == nil {
+ firstStmt = stmt
+ }
+ if len(parts) >= 3 {
+ switch parts[0] {
+ case "PANIC":
+ stmt.panic = parts[1]
+ parts = parts[2:]
+ case "WAIT":
+ wait, err := time.ParseDuration(parts[1])
+ if err != nil {
+ return nil, errf("expected section after WAIT to be a duration, got %q %v", parts[1], err)
+ }
+ parts = parts[2:]
+ stmt.wait = wait
+ }
+ }
+ cmd := parts[0]
+ stmt.cmd = cmd
+ parts = parts[1:]
+
+ if stmt.wait > 0 {
+ wait := time.NewTimer(stmt.wait)
+ select {
+ case <-wait.C:
+ case <-ctx.Done():
+ wait.Stop()
+ return nil, ctx.Err()
+ }
+ }
- c.incrStat(&c.stmtsMade)
- switch cmd {
- case "WIPE":
- // Nothing
- case "SELECT":
- return c.prepareSelect(stmt, parts)
- case "CREATE":
- return c.prepareCreate(stmt, parts)
- case "INSERT":
- return c.prepareInsert(stmt, parts)
- case "NOSERT":
- // Do all the prep-work like for an INSERT but don't actually insert the row.
- // Used for some of the concurrent tests.
- return c.prepareInsert(stmt, parts)
- default:
- stmt.Close()
- return nil, errf("unsupported command type %q", cmd)
+ c.incrStat(&c.stmtsMade)
+ var err error
+ switch cmd {
+ case "WIPE":
+ // Nothing
+ case "SELECT":
+ stmt, err = c.prepareSelect(stmt, parts)
+ case "CREATE":
+ stmt, err = c.prepareCreate(stmt, parts)
+ case "INSERT":
+ stmt, err = c.prepareInsert(stmt, parts)
+ case "NOSERT":
+ // Do all the prep-work like for an INSERT but don't actually insert the row.
+ // Used for some of the concurrent tests.
+ stmt, err = c.prepareInsert(stmt, parts)
+ default:
+ stmt.Close()
+ return nil, errf("unsupported command type %q", cmd)
+ }
+ if err != nil {
+ return nil, err
+ }
+ if prev != nil {
+ prev.next = stmt
+ }
+ prev = stmt
}
- return stmt, nil
+ return firstStmt, nil
}
func (s *fakeStmt) ColumnConverter(idx int) driver.ValueConverter {
@@ -550,6 +616,9 @@ func (s *fakeStmt) Close() error {
s.c.incrStat(&s.c.stmtsClosed)
s.closed = true
}
+ if s.next != nil {
+ s.next.Close()
+ }
return nil
}
@@ -559,6 +628,9 @@ var errClosed = errors.New("fakedb: statement has been closed")
var hookExecBadConn func() bool
func (s *fakeStmt) Exec(args []driver.Value) (driver.Result, error) {
+ panic("Using ExecContext")
+}
+func (s *fakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
if s.panic == "Exec" {
panic(s.panic)
}
@@ -575,6 +647,16 @@ func (s *fakeStmt) Exec(args []driver.Value) (driver.Result, error) {
return nil, err
}
+ if s.wait > 0 {
+ time.Sleep(s.wait)
+ }
+
+ select {
+ default:
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+
db := s.c.db
switch s.cmd {
case "WIPE":
@@ -599,7 +681,7 @@ func (s *fakeStmt) Exec(args []driver.Value) (driver.Result, error) {
// When doInsert is true, add the row to the table.
// When doInsert is false do prep-work and error checking, but don't
// actually add the row to the table.
-func (s *fakeStmt) execInsert(args []driver.Value, doInsert bool) (driver.Result, error) {
+func (s *fakeStmt) execInsert(args []driver.NamedValue, doInsert bool) (driver.Result, error) {
db := s.c.db
if len(args) != s.placeholders {
panic("error in pkg db; should only get here if size is correct")
@@ -625,8 +707,18 @@ func (s *fakeStmt) execInsert(args []driver.Value, doInsert bool) (driver.Result
return nil, fmt.Errorf("fakedb: column %q doesn't exist or dropped since prepared statement was created", colname)
}
var val interface{}
- if strvalue, ok := s.colValue[n].(string); ok && strvalue == "?" {
- val = args[argPos]
+ if strvalue, ok := s.colValue[n].(string); ok && strings.HasPrefix(strvalue, "?") {
+ if strvalue == "?" {
+ val = args[argPos].Value
+ } else {
+ // Assign value from argument placeholder name.
+ for _, a := range args {
+ if a.Name == strvalue[1:] {
+ val = a.Value
+ break
+ }
+ }
+ }
argPos++
} else {
val = s.colValue[n]
@@ -646,6 +738,10 @@ func (s *fakeStmt) execInsert(args []driver.Value, doInsert bool) (driver.Result
var hookQueryBadConn func() bool
func (s *fakeStmt) Query(args []driver.Value) (driver.Rows, error) {
+ panic("Use QueryContext")
+}
+
+func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
if s.panic == "Query" {
panic(s.panic)
}
@@ -667,65 +763,101 @@ func (s *fakeStmt) Query(args []driver.Value) (driver.Rows, error) {
panic("error in pkg db; should only get here if size is correct")
}
- db.mu.Lock()
- t, ok := db.table(s.table)
- db.mu.Unlock()
- if !ok {
- return nil, fmt.Errorf("fakedb: table %q doesn't exist", s.table)
- }
+ setMRows := make([][]*row, 0, 1)
+ setColumns := make([][]string, 0, 1)
+ setColType := make([][]string, 0, 1)
- if s.table == "magicquery" {
- if len(s.whereCol) == 2 && s.whereCol[0] == "op" && s.whereCol[1] == "millis" {
- if args[0] == "sleep" {
- time.Sleep(time.Duration(args[1].(int64)) * time.Millisecond)
- }
+ for {
+ db.mu.Lock()
+ t, ok := db.table(s.table)
+ db.mu.Unlock()
+ if !ok {
+ return nil, fmt.Errorf("fakedb: table %q doesn't exist", s.table)
}
- }
-
- t.mu.Lock()
- defer t.mu.Unlock()
- colIdx := make(map[string]int) // select column name -> column index in table
- for _, name := range s.colName {
- idx := t.columnIndex(name)
- if idx == -1 {
- return nil, fmt.Errorf("fakedb: unknown column name %q", name)
+ if s.table == "magicquery" {
+ if len(s.whereCol) == 2 && s.whereCol[0].Column == "op" && s.whereCol[1].Column == "millis" {
+ if args[0].Value == "sleep" {
+ time.Sleep(time.Duration(args[1].Value.(int64)) * time.Millisecond)
+ }
+ }
}
- colIdx[name] = idx
- }
- mrows := []*row{}
-rows:
- for _, trow := range t.rows {
- // Process the where clause, skipping non-match rows. This is lazy
- // and just uses fmt.Sprintf("%v") to test equality. Good enough
- // for test code.
- for widx, wcol := range s.whereCol {
- idx := t.columnIndex(wcol)
+ t.mu.Lock()
+
+ colIdx := make(map[string]int) // select column name -> column index in table
+ for _, name := range s.colName {
+ idx := t.columnIndex(name)
if idx == -1 {
- return nil, fmt.Errorf("db: invalid where clause column %q", wcol)
+ t.mu.Unlock()
+ return nil, fmt.Errorf("fakedb: unknown column name %q", name)
}
- tcol := trow.cols[idx]
- if bs, ok := tcol.([]byte); ok {
- // lazy hack to avoid sprintf %v on a []byte
- tcol = string(bs)
+ colIdx[name] = idx
+ }
+
+ mrows := []*row{}
+ rows:
+ for _, trow := range t.rows {
+ // Process the where clause, skipping non-match rows. This is lazy
+ // and just uses fmt.Sprintf("%v") to test equality. Good enough
+ // for test code.
+ for _, wcol := range s.whereCol {
+ idx := t.columnIndex(wcol.Column)
+ if idx == -1 {
+ t.mu.Unlock()
+ return nil, fmt.Errorf("db: invalid where clause column %q", wcol)
+ }
+ tcol := trow.cols[idx]
+ if bs, ok := tcol.([]byte); ok {
+ // lazy hack to avoid sprintf %v on a []byte
+ tcol = string(bs)
+ }
+ var argValue interface{}
+ if wcol.Placeholder == "?" {
+ argValue = args[wcol.Ordinal-1].Value
+ } else {
+ // Assign arg value from placeholder name.
+ for _, a := range args {
+ if a.Name == wcol.Placeholder[1:] {
+ argValue = a.Value
+ break
+ }
+ }
+ }
+ if fmt.Sprintf("%v", tcol) != fmt.Sprintf("%v", argValue) {
+ continue rows
+ }
}
- if fmt.Sprintf("%v", tcol) != fmt.Sprintf("%v", args[widx]) {
- continue rows
+ mrow := &row{cols: make([]interface{}, len(s.colName))}
+ for seli, name := range s.colName {
+ mrow.cols[seli] = trow.cols[colIdx[name]]
}
+ mrows = append(mrows, mrow)
}
- mrow := &row{cols: make([]interface{}, len(s.colName))}
- for seli, name := range s.colName {
- mrow.cols[seli] = trow.cols[colIdx[name]]
+
+ var colType []string
+ for _, column := range s.colName {
+ colType = append(colType, t.coltype[t.columnIndex(column)])
}
- mrows = append(mrows, mrow)
+
+ t.mu.Unlock()
+
+ setMRows = append(setMRows, mrows)
+ setColumns = append(setColumns, s.colName)
+ setColType = append(setColType, colType)
+
+ if s.next == nil {
+ break
+ }
+ s = s.next
}
cursor := &rowsCursor{
- pos: -1,
- rows: mrows,
- cols: s.colName,
- errPos: -1,
+ posRow: -1,
+ rows: setMRows,
+ cols: setColumns,
+ colType: setColType,
+ errPos: -1,
}
return cursor, nil
}
@@ -760,10 +892,12 @@ func (tx *fakeTx) Rollback() error {
}
type rowsCursor struct {
- cols []string
- pos int
- rows []*row
- closed bool
+ cols [][]string
+ colType [][]string
+ posSet int
+ posRow int
+ rows [][]*row
+ closed bool
// errPos and err are for making Next return early with error.
errPos int
@@ -786,7 +920,11 @@ func (rc *rowsCursor) Close() error {
}
func (rc *rowsCursor) Columns() []string {
- return rc.cols
+ return rc.cols[rc.posSet]
+}
+
+func (rc *rowsCursor) ColumnTypeScanType(index int) reflect.Type {
+ return colTypeToReflectType(rc.colType[rc.posSet][index])
}
var rowsCursorNextHook func(dest []driver.Value) error
@@ -799,14 +937,14 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
if rc.closed {
return errors.New("fakedb: cursor is closed")
}
- rc.pos++
- if rc.pos == rc.errPos {
+ rc.posRow++
+ if rc.posRow == rc.errPos {
return rc.err
}
- if rc.pos >= len(rc.rows) {
+ if rc.posRow >= len(rc.rows[rc.posSet]) {
return io.EOF // per interface spec
}
- for i, v := range rc.rows[rc.pos].cols {
+ for i, v := range rc.rows[rc.posSet][rc.posRow].cols {
// TODO(bradfitz): convert to subset types? naah, I
// think the subset types should only be input to
// driver, but the sql package should be able to handle
@@ -831,6 +969,19 @@ func (rc *rowsCursor) Next(dest []driver.Value) error {
return nil
}
+func (rc *rowsCursor) HasNextResultSet() bool {
+ return rc.posSet < len(rc.rows)-1
+}
+
+func (rc *rowsCursor) NextResultSet() error {
+ if rc.HasNextResultSet() {
+ rc.posSet++
+ rc.posRow = -1
+ return nil
+ }
+ return io.EOF // Per interface spec.
+}
+
// fakeDriverString is like driver.String, but indirects pointers like
// DefaultValueConverter.
//
@@ -882,3 +1033,29 @@ func converterForType(typ string) driver.ValueConverter {
}
panic("invalid fakedb column type of " + typ)
}
+
+func colTypeToReflectType(typ string) reflect.Type {
+ switch typ {
+ case "bool":
+ return reflect.TypeOf(false)
+ case "nullbool":
+ return reflect.TypeOf(NullBool{})
+ case "int32":
+ return reflect.TypeOf(int32(0))
+ case "string":
+ return reflect.TypeOf("")
+ case "nullstring":
+ return reflect.TypeOf(NullString{})
+ case "int64":
+ return reflect.TypeOf(int64(0))
+ case "nullint64":
+ return reflect.TypeOf(NullInt64{})
+ case "float64":
+ return reflect.TypeOf(float64(0))
+ case "nullfloat64":
+ return reflect.TypeOf(NullFloat64{})
+ case "datetime":
+ return reflect.TypeOf(time.Time{})
+ }
+ panic("invalid fakedb column type of " + typ)
+}
diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go
index 09de1c34e82..0fa7c34a13e 100644
--- a/libgo/go/database/sql/sql.go
+++ b/libgo/go/database/sql/sql.go
@@ -8,15 +8,20 @@
// The sql package must be used in conjunction with a database driver.
// See https://golang.org/s/sqldrivers for a list of drivers.
//
-// For more usage examples, see the wiki page at
+// Drivers that do not support context cancelation will not return until
+// after the query is completed.
+//
+// For usage examples, see the wiki page at
// https://golang.org/s/sqlwiki.
package sql
import (
+ "context"
"database/sql/driver"
"errors"
"fmt"
"io"
+ "reflect"
"runtime"
"sort"
"sync"
@@ -66,6 +71,75 @@ func Drivers() []string {
return list
}
+// A NamedArg is a named argument. NamedArg values may be used as
+// arguments to Query or Exec and bind to the corresponding named
+// parameter in the SQL statement.
+//
+// For a more concise way to create NamedArg values, see
+// the Named function.
+type NamedArg struct {
+ _Named_Fields_Required struct{}
+
+ // Name is the name of the parameter placeholder.
+ //
+ // If empty, the ordinal position in the argument list will be
+ // used.
+ //
+ // Name must omit any symbol prefix.
+ Name string
+
+ // Value is the value of the parameter.
+ // It may be assigned the same value types as the query
+ // arguments.
+ Value interface{}
+}
+
+// Named provides a more concise way to create NamedArg values.
+//
+// Example usage:
+//
+// db.ExecContext(ctx, `
+// delete from Invoice
+// where
+// TimeCreated < @end
+// and TimeCreated >= @start;`,
+// sql.Named("start", startTime),
+// sql.Named("end", endTime),
+// )
+func Named(name string, value interface{}) NamedArg {
+ // This method exists because the go1compat promise
+ // doesn't guarantee that structs don't grow more fields,
+ // so unkeyed struct literals are a vet error. Thus, we don't
+ // want to allow sql.NamedArg{name, value}.
+ return NamedArg{Name: name, Value: value}
+}
+
+// IsolationLevel is the transaction isolation level used in TxOptions.
+type IsolationLevel int
+
+// Various isolation levels that drivers may support in BeginTx.
+// If a driver does not support a given isolation level an error may be returned.
+//
+// See https://en.wikipedia.org/wiki/Isolation_(database_systems)#Isolation_levels.
+const (
+ LevelDefault IsolationLevel = iota
+ LevelReadUncommitted
+ LevelReadCommitted
+ LevelWriteCommitted
+ LevelRepeatableRead
+ LevelSnapshot
+ LevelSerializable
+ LevelLinearizable
+)
+
+// TxOptions holds the transaction options to be used in DB.BeginTx.
+type TxOptions struct {
+ // Isolation is the transaction isolation level.
+ // If zero, the driver or database's default level is used.
+ Isolation IsolationLevel
+ ReadOnly bool
+}
+
// 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.
@@ -272,7 +346,7 @@ type driverConn struct {
ci driver.Conn
closed bool
finalClosed bool // ci.Close has been called
- openStmt map[driver.Stmt]bool
+ openStmt map[*driverStmt]bool
// guarded by db.mu
inUse bool
@@ -284,10 +358,10 @@ func (dc *driverConn) releaseConn(err error) {
dc.db.putConn(dc, err)
}
-func (dc *driverConn) removeOpenStmt(si driver.Stmt) {
+func (dc *driverConn) removeOpenStmt(ds *driverStmt) {
dc.Lock()
defer dc.Unlock()
- delete(dc.openStmt, si)
+ delete(dc.openStmt, ds)
}
func (dc *driverConn) expired(timeout time.Duration) bool {
@@ -297,28 +371,23 @@ func (dc *driverConn) expired(timeout time.Duration) bool {
return dc.createdAt.Add(timeout).Before(nowFunc())
}
-func (dc *driverConn) prepareLocked(query string) (driver.Stmt, error) {
- si, err := dc.ci.Prepare(query)
- if err == nil {
- // Track each driverConn's open statements, so we can close them
- // before closing the conn.
- //
- // TODO(bradfitz): let drivers opt out of caring about
- // 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.2, closing driver.Stmts
- // should be moved to driverStmt, using unique
- // *driverStmts everywhere (including from
- // *Stmt.connStmt, instead of returning a
- // driver.Stmt), using driverStmt as a pointer
- // everywhere, and making it a finalCloser.
- if dc.openStmt == nil {
- dc.openStmt = make(map[driver.Stmt]bool)
- }
- dc.openStmt[si] = true
+func (dc *driverConn) prepareLocked(ctx context.Context, query string) (*driverStmt, error) {
+ si, err := ctxDriverPrepare(ctx, dc.ci, query)
+ if err != nil {
+ return nil, err
}
- return si, err
+
+ // Track each driverConn's open statements, so we can close them
+ // before closing the conn.
+ //
+ // Wrap all driver.Stmt is *driverStmt to ensure they are only closed once.
+ if dc.openStmt == nil {
+ dc.openStmt = make(map[*driverStmt]bool)
+ }
+ ds := &driverStmt{Locker: dc, si: si}
+ dc.openStmt[ds] = true
+
+ return ds, nil
}
// the dc.db's Mutex is held.
@@ -350,17 +419,26 @@ func (dc *driverConn) Close() error {
}
func (dc *driverConn) finalClose() error {
- dc.Lock()
+ var err error
- for si := range dc.openStmt {
- si.Close()
+ // Each *driverStmt has a lock to the dc. Copy the list out of the dc
+ // before calling close on each stmt.
+ var openStmt []*driverStmt
+ withLock(dc, func() {
+ openStmt = make([]*driverStmt, 0, len(dc.openStmt))
+ for ds := range dc.openStmt {
+ openStmt = append(openStmt, ds)
+ }
+ dc.openStmt = nil
+ })
+ for _, ds := range openStmt {
+ ds.Close()
}
- dc.openStmt = nil
-
- err := dc.ci.Close()
- dc.ci = nil
- dc.finalClosed = true
- dc.Unlock()
+ withLock(dc, func() {
+ dc.finalClosed = true
+ err = dc.ci.Close()
+ dc.ci = nil
+ })
dc.db.mu.Lock()
dc.db.numOpen--
@@ -377,12 +455,21 @@ func (dc *driverConn) finalClose() error {
type driverStmt struct {
sync.Locker // the *driverConn
si driver.Stmt
+ closed bool
+ closeErr error // return value of previous Close call
}
+// Close ensures dirver.Stmt is only closed once any always returns the same
+// result.
func (ds *driverStmt) Close() error {
ds.Lock()
defer ds.Unlock()
- return ds.si.Close()
+ if ds.closed {
+ return ds.closeErr
+ }
+ ds.closed = true
+ ds.closeErr = ds.si.Close()
+ return ds.closeErr
}
// depSet is a finalCloser's outstanding dependencies
@@ -494,18 +581,36 @@ func Open(driverName, dataSourceName string) (*DB, error) {
return db, nil
}
-// Ping verifies a connection to the database is still alive,
+// PingContext verifies a connection to the database is still alive,
// establishing a connection if necessary.
-func (db *DB) Ping() error {
- // TODO(bradfitz): give drivers an optional hook to implement
- // this in a more efficient or more reliable way, if they
- // have one.
- dc, err := db.conn(cachedOrNewConn)
+func (db *DB) PingContext(ctx context.Context) error {
+ var dc *driverConn
+ var err error
+
+ for i := 0; i < maxBadConnRetries; i++ {
+ dc, err = db.conn(ctx, cachedOrNewConn)
+ if err != driver.ErrBadConn {
+ break
+ }
+ }
+ if err == driver.ErrBadConn {
+ dc, err = db.conn(ctx, alwaysNewConn)
+ }
if err != nil {
return err
}
- db.putConn(dc, nil)
- return nil
+
+ if pinger, ok := dc.ci.(driver.Pinger); ok {
+ err = pinger.Ping(ctx)
+ }
+ db.putConn(dc, err)
+ return err
+}
+
+// Ping verifies a connection to the database is still alive,
+// establishing a connection if necessary.
+func (db *DB) Ping() error {
+ return db.PingContext(context.Background())
}
// Close closes the database, releasing any open resources.
@@ -777,12 +882,19 @@ type connRequest struct {
var errDBClosed = errors.New("sql: database is closed")
// conn returns a newly-opened or cached *driverConn.
-func (db *DB) conn(strategy connReuseStrategy) (*driverConn, error) {
+func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn, error) {
db.mu.Lock()
if db.closed {
db.mu.Unlock()
return nil, errDBClosed
}
+ // Check if the context is expired.
+ select {
+ default:
+ case <-ctx.Done():
+ db.mu.Unlock()
+ return nil, ctx.Err()
+ }
lifetime := db.maxLifetime
// Prefer a free connection, if possible.
@@ -808,15 +920,21 @@ func (db *DB) conn(strategy connReuseStrategy) (*driverConn, error) {
req := make(chan connRequest, 1)
db.connRequests = append(db.connRequests, req)
db.mu.Unlock()
- ret, ok := <-req
- if !ok {
- return nil, errDBClosed
- }
- if ret.err == nil && ret.conn.expired(lifetime) {
- ret.conn.Close()
- return nil, driver.ErrBadConn
+
+ // Timeout the connection request with the context.
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ case ret, ok := <-req:
+ if !ok {
+ return nil, errDBClosed
+ }
+ if ret.err == nil && ret.conn.expired(lifetime) {
+ ret.conn.Close()
+ return nil, driver.ErrBadConn
+ }
+ return ret.conn, ret.err
}
- return ret.conn, ret.err
}
db.numOpen++ // optimistically
@@ -844,21 +962,22 @@ func (db *DB) conn(strategy connReuseStrategy) (*driverConn, error) {
// putConnHook is a hook for testing.
var putConnHook func(*DB, *driverConn)
-// noteUnusedDriverStatement notes that si is no longer used and should
+// noteUnusedDriverStatement notes that ds is no longer used and should
// be closed whenever possible (when c is next not in use), unless c is
// already closed.
-func (db *DB) noteUnusedDriverStatement(c *driverConn, si driver.Stmt) {
+func (db *DB) noteUnusedDriverStatement(c *driverConn, ds *driverStmt) {
db.mu.Lock()
defer db.mu.Unlock()
if c.inUse {
c.onPut = append(c.onPut, func() {
- si.Close()
+ ds.Close()
})
} else {
c.Lock()
- defer c.Unlock()
- if !c.finalClosed {
- si.Close()
+ fc := c.finalClosed
+ c.Unlock()
+ if !fc {
+ ds.Close()
}
}
}
@@ -952,40 +1071,53 @@ func (db *DB) putConnDBLocked(dc *driverConn, err error) bool {
// connection to be opened.
const maxBadConnRetries = 2
-// Prepare creates a prepared statement for later queries or executions.
+// PrepareContext creates a prepared statement for later queries or executions.
// Multiple queries or executions may be run concurrently from the
// returned statement.
// The caller must call the statement's Close method
// when the statement is no longer needed.
-func (db *DB) Prepare(query string) (*Stmt, error) {
+//
+// The provided context is used for the preparation of the statement, not for the
+// execution of the statement.
+func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
var stmt *Stmt
var err error
for i := 0; i < maxBadConnRetries; i++ {
- stmt, err = db.prepare(query, cachedOrNewConn)
+ stmt, err = db.prepare(ctx, query, cachedOrNewConn)
if err != driver.ErrBadConn {
break
}
}
if err == driver.ErrBadConn {
- return db.prepare(query, alwaysNewConn)
+ return db.prepare(ctx, query, alwaysNewConn)
}
return stmt, err
}
-func (db *DB) prepare(query string, strategy connReuseStrategy) (*Stmt, error) {
+// Prepare creates a prepared statement for later queries or executions.
+// Multiple queries or executions may be run concurrently from the
+// returned statement.
+// The caller must call the statement's Close method
+// when the statement is no longer needed.
+func (db *DB) Prepare(query string) (*Stmt, error) {
+ return db.PrepareContext(context.Background(), query)
+}
+
+func (db *DB) prepare(ctx context.Context, query string, strategy connReuseStrategy) (*Stmt, error) {
// TODO: check if db.driver supports an optional
// driver.Preparer interface and call that instead, if so,
// otherwise we make a prepared statement that's bound
// to a connection, and to execute this prepared statement
// we either need to use this connection (if it's free), else
// get a new connection + re-prepare + execute on that one.
- dc, err := db.conn(strategy)
+ dc, err := db.conn(ctx, strategy)
if err != nil {
return nil, err
}
- dc.Lock()
- si, err := dc.prepareLocked(query)
- dc.Unlock()
+ var ds *driverStmt
+ withLock(dc, func() {
+ ds, err = dc.prepareLocked(ctx, query)
+ })
if err != nil {
db.putConn(dc, err)
return nil, err
@@ -993,7 +1125,7 @@ func (db *DB) prepare(query string, strategy connReuseStrategy) (*Stmt, error) {
stmt := &Stmt{
db: db,
query: query,
- css: []connStmt{{dc, si}},
+ css: []connStmt{{dc, ds}},
lastNumClosed: atomic.LoadUint64(&db.numClosed),
}
db.addDep(stmt, stmt)
@@ -1001,25 +1133,31 @@ func (db *DB) prepare(query string, strategy connReuseStrategy) (*Stmt, error) {
return stmt, nil
}
-// Exec executes a query without returning any rows.
+// ExecContext executes a query without returning any rows.
// The args are for any placeholder parameters in the query.
-func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
+func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error) {
var res Result
var err error
for i := 0; i < maxBadConnRetries; i++ {
- res, err = db.exec(query, args, cachedOrNewConn)
+ res, err = db.exec(ctx, query, args, cachedOrNewConn)
if err != driver.ErrBadConn {
break
}
}
if err == driver.ErrBadConn {
- return db.exec(query, args, alwaysNewConn)
+ return db.exec(ctx, query, args, alwaysNewConn)
}
return res, err
}
-func (db *DB) exec(query string, args []interface{}, strategy connReuseStrategy) (res Result, err error) {
- dc, err := db.conn(strategy)
+// Exec executes a query without returning any rows.
+// The args are for any placeholder parameters in the query.
+func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
+ return db.ExecContext(context.Background(), query, args...)
+}
+
+func (db *DB) exec(ctx context.Context, query string, args []interface{}, strategy connReuseStrategy) (res Result, err error) {
+ dc, err := db.conn(ctx, strategy)
if err != nil {
return nil, err
}
@@ -1028,13 +1166,15 @@ func (db *DB) exec(query string, args []interface{}, strategy connReuseStrategy)
}()
if execer, ok := dc.ci.(driver.Execer); ok {
- dargs, err := driverArgs(nil, args)
+ var dargs []driver.NamedValue
+ dargs, err = driverArgs(nil, args)
if err != nil {
return nil, err
}
- dc.Lock()
- resi, err := execer.Exec(query, dargs)
- dc.Unlock()
+ var resi driver.Result
+ withLock(dc, func() {
+ resi, err = ctxDriverExec(ctx, execer, query, dargs)
+ })
if err != driver.ErrSkip {
if err != nil {
return nil, err
@@ -1043,54 +1183,63 @@ func (db *DB) exec(query string, args []interface{}, strategy connReuseStrategy)
}
}
- dc.Lock()
- si, err := dc.ci.Prepare(query)
- dc.Unlock()
+ var si driver.Stmt
+ withLock(dc, func() {
+ si, err = ctxDriverPrepare(ctx, dc.ci, query)
+ })
if err != nil {
return nil, err
}
- defer withLock(dc, func() { si.Close() })
- return resultFromStatement(driverStmt{dc, si}, args...)
+ ds := &driverStmt{Locker: dc, si: si}
+ defer ds.Close()
+ return resultFromStatement(ctx, ds, args...)
}
-// Query executes a query that returns rows, typically a SELECT.
+// QueryContext executes a query that returns rows, typically a SELECT.
// The args are for any placeholder parameters in the query.
-func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
+func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) {
var rows *Rows
var err error
for i := 0; i < maxBadConnRetries; i++ {
- rows, err = db.query(query, args, cachedOrNewConn)
+ rows, err = db.query(ctx, query, args, cachedOrNewConn)
if err != driver.ErrBadConn {
break
}
}
if err == driver.ErrBadConn {
- return db.query(query, args, alwaysNewConn)
+ return db.query(ctx, query, args, alwaysNewConn)
}
return rows, err
}
-func (db *DB) query(query string, args []interface{}, strategy connReuseStrategy) (*Rows, error) {
- ci, err := db.conn(strategy)
+// Query executes a query that returns rows, typically a SELECT.
+// The args are for any placeholder parameters in the query.
+func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
+ return db.QueryContext(context.Background(), query, args...)
+}
+
+func (db *DB) query(ctx context.Context, query string, args []interface{}, strategy connReuseStrategy) (*Rows, error) {
+ ci, err := db.conn(ctx, strategy)
if err != nil {
return nil, err
}
- return db.queryConn(ci, ci.releaseConn, query, args)
+ return db.queryConn(ctx, ci, ci.releaseConn, query, args)
}
// queryConn executes a query on the given connection.
// The connection gets released by the releaseConn function.
-func (db *DB) queryConn(dc *driverConn, releaseConn func(error), query string, args []interface{}) (*Rows, error) {
+func (db *DB) queryConn(ctx context.Context, dc *driverConn, releaseConn func(error), query string, args []interface{}) (*Rows, error) {
if queryer, ok := dc.ci.(driver.Queryer); ok {
dargs, err := driverArgs(nil, args)
if err != nil {
releaseConn(err)
return nil, err
}
- dc.Lock()
- rowsi, err := queryer.Query(query, dargs)
- dc.Unlock()
+ var rowsi driver.Rows
+ withLock(dc, func() {
+ rowsi, err = ctxDriverQuery(ctx, queryer, query, dargs)
+ })
if err != driver.ErrSkip {
if err != nil {
releaseConn(err)
@@ -1103,24 +1252,25 @@ func (db *DB) queryConn(dc *driverConn, releaseConn func(error), query string, a
releaseConn: releaseConn,
rowsi: rowsi,
}
+ rows.initContextClose(ctx)
return rows, nil
}
}
- dc.Lock()
- si, err := dc.ci.Prepare(query)
- dc.Unlock()
+ var si driver.Stmt
+ var err error
+ withLock(dc, func() {
+ si, err = ctxDriverPrepare(ctx, dc.ci, query)
+ })
if err != nil {
releaseConn(err)
return nil, err
}
- ds := driverStmt{dc, si}
- rowsi, err := rowsiFromStatement(ds, args...)
+ ds := &driverStmt{Locker: dc, si: si}
+ rowsi, err := rowsiFromStatement(ctx, ds, args...)
if err != nil {
- dc.Lock()
- si.Close()
- dc.Unlock()
+ ds.Close()
releaseConn(err)
return nil, err
}
@@ -1131,53 +1281,93 @@ func (db *DB) queryConn(dc *driverConn, releaseConn func(error), query string, a
dc: dc,
releaseConn: releaseConn,
rowsi: rowsi,
- closeStmt: si,
+ closeStmt: ds,
}
+ rows.initContextClose(ctx)
return rows, nil
}
+// QueryRowContext executes a query that is expected to return at most one row.
+// QueryRowContext always returns a non-nil value. Errors are deferred until
+// Row's Scan method is called.
+func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row {
+ rows, err := db.QueryContext(ctx, query, args...)
+ return &Row{rows: rows, err: err}
+}
+
// QueryRow executes a query that is expected to return at most one row.
// QueryRow always returns a non-nil value. Errors are deferred until
// Row's Scan method is called.
func (db *DB) QueryRow(query string, args ...interface{}) *Row {
- rows, err := db.Query(query, args...)
- return &Row{rows: rows, err: err}
+ return db.QueryRowContext(context.Background(), query, args...)
}
-// Begin starts a transaction. The isolation level is dependent on
-// the driver.
-func (db *DB) Begin() (*Tx, error) {
+// BeginTx starts a transaction.
+//
+// The provided context is used until the transaction is committed or rolled back.
+// If the context is canceled, the sql package will roll back
+// the transaction. Tx.Commit will return an error if the context provided to
+// BeginTx is canceled.
+//
+// The provided TxOptions is optional and may be nil if defaults should be used.
+// If a non-default isolation level is used that the driver doesn't support,
+// an error will be returned.
+func (db *DB) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error) {
var tx *Tx
var err error
for i := 0; i < maxBadConnRetries; i++ {
- tx, err = db.begin(cachedOrNewConn)
+ tx, err = db.begin(ctx, opts, cachedOrNewConn)
if err != driver.ErrBadConn {
break
}
}
if err == driver.ErrBadConn {
- return db.begin(alwaysNewConn)
+ return db.begin(ctx, opts, alwaysNewConn)
}
return tx, err
}
-func (db *DB) begin(strategy connReuseStrategy) (tx *Tx, err error) {
- dc, err := db.conn(strategy)
+// Begin starts a transaction. The default isolation level is dependent on
+// the driver.
+func (db *DB) Begin() (*Tx, error) {
+ return db.BeginTx(context.Background(), nil)
+}
+
+func (db *DB) begin(ctx context.Context, opts *TxOptions, strategy connReuseStrategy) (tx *Tx, err error) {
+ dc, err := db.conn(ctx, strategy)
if err != nil {
return nil, err
}
- dc.Lock()
- txi, err := dc.ci.Begin()
- dc.Unlock()
+ var txi driver.Tx
+ withLock(dc, func() {
+ txi, err = ctxDriverBegin(ctx, opts, dc.ci)
+ })
if err != nil {
db.putConn(dc, err)
return nil, err
}
- return &Tx{
- db: db,
- dc: dc,
- txi: txi,
- }, nil
+
+ // Schedule the transaction to rollback when the context is cancelled.
+ // The cancel function in Tx will be called after done is set to true.
+ ctx, cancel := context.WithCancel(ctx)
+ tx = &Tx{
+ db: db,
+ dc: dc,
+ txi: txi,
+ cancel: cancel,
+ ctx: ctx,
+ }
+ go func(tx *Tx) {
+ select {
+ case <-tx.ctx.Done():
+ if !tx.isDone() {
+ // Discard and close the connection used to ensure the transaction
+ // is closed and the resources are released.
+ tx.rollback(true)
+ }
+ }
+ }(tx)
+ return tx, nil
}
// Driver returns the database's underlying driver.
@@ -1203,10 +1393,11 @@ type Tx struct {
dc *driverConn
txi driver.Tx
- // done transitions from false to true exactly once, on Commit
+ // done transitions from 0 to 1 exactly once, on Commit
// or Rollback. once done, all operations fail with
// ErrTxDone.
- done bool
+ // Use atomic operations on value when checking value.
+ done int32
// All Stmts prepared for this transaction. These will be closed after the
// transaction has been committed or rolled back.
@@ -1214,22 +1405,33 @@ type Tx struct {
sync.Mutex
v []*Stmt
}
+
+ // cancel is called after done transitions from false to true.
+ cancel func()
+
+ // ctx lives for the life of the transaction.
+ ctx context.Context
+}
+
+func (tx *Tx) isDone() bool {
+ return atomic.LoadInt32(&tx.done) != 0
}
+// ErrTxDone is returned by any operation that is performed on a transaction
+// that has already been committed or rolled back.
var ErrTxDone = errors.New("sql: Transaction has already been committed or rolled back")
+// close returns the connection to the pool and
+// must only be called by Tx.rollback or Tx.Commit.
func (tx *Tx) close(err error) {
- if tx.done {
- panic("double close") // internal error
- }
- tx.done = true
tx.db.putConn(tx.dc, err)
+ tx.cancel()
tx.dc = nil
tx.txi = nil
}
-func (tx *Tx) grabConn() (*driverConn, error) {
- if tx.done {
+func (tx *Tx) grabConn(ctx context.Context) (*driverConn, error) {
+ if tx.isDone() {
return nil, ErrTxDone
}
return tx.dc, nil
@@ -1238,20 +1440,26 @@ func (tx *Tx) grabConn() (*driverConn, error) {
// Closes all Stmts prepared for this transaction.
func (tx *Tx) closePrepared() {
tx.stmts.Lock()
+ defer tx.stmts.Unlock()
for _, stmt := range tx.stmts.v {
stmt.Close()
}
- tx.stmts.Unlock()
}
// Commit commits the transaction.
func (tx *Tx) Commit() error {
- if tx.done {
+ if !atomic.CompareAndSwapInt32(&tx.done, 0, 1) {
return ErrTxDone
}
- tx.dc.Lock()
- err := tx.txi.Commit()
- tx.dc.Unlock()
+ select {
+ default:
+ case <-tx.ctx.Done():
+ return tx.ctx.Err()
+ }
+ var err error
+ withLock(tx.dc, func() {
+ err = tx.txi.Commit()
+ })
if err != driver.ErrBadConn {
tx.closePrepared()
}
@@ -1259,28 +1467,42 @@ func (tx *Tx) Commit() error {
return err
}
-// Rollback aborts the transaction.
-func (tx *Tx) Rollback() error {
- if tx.done {
+// rollback aborts the transaction and optionally forces the pool to discard
+// the connection.
+func (tx *Tx) rollback(discardConn bool) error {
+ if !atomic.CompareAndSwapInt32(&tx.done, 0, 1) {
return ErrTxDone
}
- tx.dc.Lock()
- err := tx.txi.Rollback()
- tx.dc.Unlock()
+ var err error
+ withLock(tx.dc, func() {
+ err = tx.txi.Rollback()
+ })
if err != driver.ErrBadConn {
tx.closePrepared()
}
+ if discardConn {
+ err = driver.ErrBadConn
+ }
tx.close(err)
return err
}
+// Rollback aborts the transaction.
+func (tx *Tx) Rollback() error {
+ return tx.rollback(false)
+}
+
// Prepare creates a prepared statement for use within a transaction.
//
-// The returned statement operates within the transaction and can no longer
-// be used once the transaction has been committed or rolled back.
+// The returned statement operates within the transaction and will be closed
+// when the transaction has been committed or rolled back.
//
// To use an existing prepared statement on this transaction, see Tx.Stmt.
-func (tx *Tx) Prepare(query string) (*Stmt, error) {
+//
+// The provided context will be used for the preparation of the context, not
+// for the execution of the returned statement. The returned statement
+// will run in the transaction context.
+func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
// TODO(bradfitz): We could be more efficient here and either
// provide a method to take an existing Stmt (created on
// perhaps a different Conn), and re-create it on this Conn if
@@ -1294,14 +1516,15 @@ func (tx *Tx) Prepare(query string) (*Stmt, error) {
// Perhaps just looking at the reference count (by noting
// Stmt.Close) would be enough. We might also want a finalizer
// on Stmt to drop the reference count.
- dc, err := tx.grabConn()
+ dc, err := tx.grabConn(ctx)
if err != nil {
return nil, err
}
- dc.Lock()
- si, err := dc.ci.Prepare(query)
- dc.Unlock()
+ var si driver.Stmt
+ withLock(dc, func() {
+ si, err = ctxDriverPrepare(ctx, dc.ci, query)
+ })
if err != nil {
return nil, err
}
@@ -1309,7 +1532,7 @@ func (tx *Tx) Prepare(query string) (*Stmt, error) {
stmt := &Stmt{
db: tx.db,
tx: tx,
- txsi: &driverStmt{
+ txds: &driverStmt{
Locker: dc,
si: si,
},
@@ -1321,7 +1544,17 @@ func (tx *Tx) Prepare(query string) (*Stmt, error) {
return stmt, nil
}
-// Stmt returns a transaction-specific prepared statement from
+// Prepare creates a prepared statement for use within a transaction.
+//
+// The returned statement operates within the transaction and can no longer
+// be used once the transaction has been committed or rolled back.
+//
+// To use an existing prepared statement on this transaction, see Tx.Stmt.
+func (tx *Tx) Prepare(query string) (*Stmt, error) {
+ return tx.PrepareContext(context.Background(), query)
+}
+
+// StmtContext returns a transaction-specific prepared statement from
// an existing statement.
//
// Example:
@@ -1329,11 +1562,11 @@ func (tx *Tx) Prepare(query string) (*Stmt, error) {
// ...
// tx, err := db.Begin()
// ...
-// res, err := tx.Stmt(updateMoney).Exec(123.45, 98293203)
+// res, err := tx.StmtContext(ctx, updateMoney).Exec(123.45, 98293203)
//
-// The returned statement operates within the transaction and can no longer
-// be used once the transaction has been committed or rolled back.
-func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
+// The returned statement operates within the transaction and will be closed
+// when the transaction has been committed or rolled back.
+func (tx *Tx) StmtContext(ctx context.Context, stmt *Stmt) *Stmt {
// TODO(bradfitz): optimize this. Currently this re-prepares
// each time. This is fine for now to illustrate the API but
// we should really cache already-prepared statements
@@ -1342,17 +1575,18 @@ func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
if tx.db != stmt.db {
return &Stmt{stickyErr: errors.New("sql: Tx.Stmt: statement from different database used")}
}
- dc, err := tx.grabConn()
+ dc, err := tx.grabConn(ctx)
if err != nil {
return &Stmt{stickyErr: err}
}
- dc.Lock()
- si, err := dc.ci.Prepare(stmt.query)
- dc.Unlock()
+ var si driver.Stmt
+ withLock(dc, func() {
+ si, err = ctxDriverPrepare(ctx, dc.ci, stmt.query)
+ })
txs := &Stmt{
db: tx.db,
tx: tx,
- txsi: &driverStmt{
+ txds: &driverStmt{
Locker: dc,
si: si,
},
@@ -1365,10 +1599,26 @@ func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
return txs
}
-// Exec executes a query that doesn't return rows.
+// Stmt returns a transaction-specific prepared statement from
+// an existing statement.
+//
+// Example:
+// updateMoney, err := db.Prepare("UPDATE balance SET money=money+? WHERE id=?")
+// ...
+// tx, err := db.Begin()
+// ...
+// res, err := tx.Stmt(updateMoney).Exec(123.45, 98293203)
+//
+// The returned statement operates within the transaction and will be closed
+// when the transaction has been committed or rolled back.
+func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
+ return tx.StmtContext(context.Background(), stmt)
+}
+
+// ExecContext executes a query that doesn't return rows.
// For example: an INSERT and UPDATE.
-func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
- dc, err := tx.grabConn()
+func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error) {
+ dc, err := tx.grabConn(ctx)
if err != nil {
return nil, err
}
@@ -1378,9 +1628,10 @@ func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
if err != nil {
return nil, err
}
- dc.Lock()
- resi, err := execer.Exec(query, dargs)
- dc.Unlock()
+ var resi driver.Result
+ withLock(dc, func() {
+ resi, err = ctxDriverExec(ctx, execer, query, dargs)
+ })
if err == nil {
return driverResult{dc, resi}, nil
}
@@ -1389,39 +1640,59 @@ func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
}
}
- dc.Lock()
- si, err := dc.ci.Prepare(query)
- dc.Unlock()
+ var si driver.Stmt
+ withLock(dc, func() {
+ si, err = ctxDriverPrepare(ctx, dc.ci, query)
+ })
if err != nil {
return nil, err
}
- defer withLock(dc, func() { si.Close() })
+ ds := &driverStmt{Locker: dc, si: si}
+ defer ds.Close()
- return resultFromStatement(driverStmt{dc, si}, args...)
+ return resultFromStatement(ctx, ds, args...)
}
-// Query executes a query that returns rows, typically a SELECT.
-func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
- dc, err := tx.grabConn()
+// Exec executes a query that doesn't return rows.
+// For example: an INSERT and UPDATE.
+func (tx *Tx) Exec(query string, args ...interface{}) (Result, error) {
+ return tx.ExecContext(context.Background(), query, args...)
+}
+
+// QueryContext executes a query that returns rows, typically a SELECT.
+func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) {
+ dc, err := tx.grabConn(ctx)
if err != nil {
return nil, err
}
releaseConn := func(error) {}
- return tx.db.queryConn(dc, releaseConn, query, args)
+ return tx.db.queryConn(ctx, dc, releaseConn, query, args)
+}
+
+// Query executes a query that returns rows, typically a SELECT.
+func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
+ return tx.QueryContext(context.Background(), query, args...)
+}
+
+// QueryRowContext executes a query that is expected to return at most one row.
+// QueryRowContext always returns a non-nil value. Errors are deferred until
+// Row's Scan method is called.
+func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row {
+ rows, err := tx.QueryContext(ctx, query, args...)
+ return &Row{rows: rows, err: err}
}
// QueryRow executes a query that is expected to return at most one row.
// QueryRow always returns a non-nil value. Errors are deferred until
// Row's Scan method is called.
func (tx *Tx) QueryRow(query string, args ...interface{}) *Row {
- rows, err := tx.Query(query, args...)
- return &Row{rows: rows, err: err}
+ return tx.QueryRowContext(context.Background(), query, args...)
}
// connStmt is a prepared statement on a particular connection.
type connStmt struct {
dc *driverConn
- si driver.Stmt
+ ds *driverStmt
}
// Stmt is a prepared statement.
@@ -1436,7 +1707,7 @@ type Stmt struct {
// If in a transaction, else both nil:
tx *Tx
- txsi *driverStmt
+ txds *driverStmt
mu sync.Mutex // protects the rest of the fields
closed bool
@@ -1452,15 +1723,15 @@ type Stmt struct {
lastNumClosed uint64
}
-// Exec executes a prepared statement with the given arguments and
+// ExecContext executes a prepared statement with the given arguments and
// returns a Result summarizing the effect of the statement.
-func (s *Stmt) Exec(args ...interface{}) (Result, error) {
+func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (Result, error) {
s.closemu.RLock()
defer s.closemu.RUnlock()
var res Result
for i := 0; i < maxBadConnRetries; i++ {
- dc, releaseConn, si, err := s.connStmt()
+ _, releaseConn, ds, err := s.connStmt(ctx)
if err != nil {
if err == driver.ErrBadConn {
continue
@@ -1468,7 +1739,7 @@ func (s *Stmt) Exec(args ...interface{}) (Result, error) {
return nil, err
}
- res, err = resultFromStatement(driverStmt{dc, si}, args...)
+ res, err = resultFromStatement(ctx, ds, args...)
releaseConn(err)
if err != driver.ErrBadConn {
return res, err
@@ -1477,13 +1748,19 @@ func (s *Stmt) Exec(args ...interface{}) (Result, error) {
return nil, driver.ErrBadConn
}
-func driverNumInput(ds driverStmt) int {
+// Exec executes a prepared statement with the given arguments and
+// returns a Result summarizing the effect of the statement.
+func (s *Stmt) Exec(args ...interface{}) (Result, error) {
+ return s.ExecContext(context.Background(), args...)
+}
+
+func driverNumInput(ds *driverStmt) int {
ds.Lock()
defer ds.Unlock() // in case NumInput panics
return ds.si.NumInput()
}
-func resultFromStatement(ds driverStmt, args ...interface{}) (Result, error) {
+func resultFromStatement(ctx context.Context, ds *driverStmt, args ...interface{}) (Result, error) {
want := driverNumInput(ds)
// -1 means the driver doesn't know how to count the number of
@@ -1493,14 +1770,15 @@ func resultFromStatement(ds driverStmt, args ...interface{}) (Result, error) {
return nil, fmt.Errorf("sql: expected %d arguments, got %d", want, len(args))
}
- dargs, err := driverArgs(&ds, args)
+ dargs, err := driverArgs(ds, args)
if err != nil {
return nil, err
}
ds.Lock()
defer ds.Unlock()
- resi, err := ds.si.Exec(dargs)
+
+ resi, err := ctxDriverStmtExec(ctx, ds.si, dargs)
if err != nil {
return nil, err
}
@@ -1536,7 +1814,7 @@ func (s *Stmt) removeClosedStmtLocked() {
// connStmt returns a free driver connection on which to execute the
// statement, a function to call to release the connection, and a
// statement bound to that connection.
-func (s *Stmt) connStmt() (ci *driverConn, releaseConn func(error), si driver.Stmt, err error) {
+func (s *Stmt) connStmt(ctx context.Context) (ci *driverConn, releaseConn func(error), ds *driverStmt, err error) {
if err = s.stickyErr; err != nil {
return
}
@@ -1551,19 +1829,18 @@ func (s *Stmt) connStmt() (ci *driverConn, releaseConn func(error), si driver.St
// transaction was created on.
if s.tx != nil {
s.mu.Unlock()
- ci, err = s.tx.grabConn() // blocks, waiting for the connection.
+ ci, err = s.tx.grabConn(ctx) // blocks, waiting for the connection.
if err != nil {
return
}
releaseConn = func(error) {}
- return ci, releaseConn, s.txsi.si, nil
+ return ci, releaseConn, s.txds, nil
}
s.removeClosedStmtLocked()
s.mu.Unlock()
- // TODO(bradfitz): or always wait for one? make configurable later?
- dc, err := s.db.conn(cachedOrNewConn)
+ dc, err := s.db.conn(ctx, cachedOrNewConn)
if err != nil {
return nil, nil, nil, err
}
@@ -1572,36 +1849,36 @@ func (s *Stmt) connStmt() (ci *driverConn, releaseConn func(error), si driver.St
for _, v := range s.css {
if v.dc == dc {
s.mu.Unlock()
- return dc, dc.releaseConn, v.si, nil
+ return dc, dc.releaseConn, v.ds, nil
}
}
s.mu.Unlock()
// No luck; we need to prepare the statement on this connection
- dc.Lock()
- si, err = dc.prepareLocked(s.query)
- dc.Unlock()
+ withLock(dc, func() {
+ ds, err = dc.prepareLocked(ctx, s.query)
+ })
if err != nil {
s.db.putConn(dc, err)
return nil, nil, nil, err
}
s.mu.Lock()
- cs := connStmt{dc, si}
+ cs := connStmt{dc, ds}
s.css = append(s.css, cs)
s.mu.Unlock()
- return dc, dc.releaseConn, si, nil
+ return dc, dc.releaseConn, ds, nil
}
-// Query executes a prepared query statement with the given arguments
+// QueryContext executes a prepared query statement with the given arguments
// and returns the query results as a *Rows.
-func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
+func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error) {
s.closemu.RLock()
defer s.closemu.RUnlock()
var rowsi driver.Rows
for i := 0; i < maxBadConnRetries; i++ {
- dc, releaseConn, si, err := s.connStmt()
+ dc, releaseConn, ds, err := s.connStmt(ctx)
if err != nil {
if err == driver.ErrBadConn {
continue
@@ -1609,7 +1886,7 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
return nil, err
}
- rowsi, err = rowsiFromStatement(driverStmt{dc, si}, args...)
+ rowsi, err = rowsiFromStatement(ctx, ds, args...)
if err == nil {
// Note: ownership of ci passes to the *Rows, to be freed
// with releaseConn.
@@ -1618,6 +1895,7 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
rowsi: rowsi,
// releaseConn set below
}
+ rows.initContextClose(ctx)
s.db.addDep(s, rows)
rows.releaseConn = func(err error) {
releaseConn(err)
@@ -1634,10 +1912,17 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
return nil, driver.ErrBadConn
}
-func rowsiFromStatement(ds driverStmt, args ...interface{}) (driver.Rows, error) {
- ds.Lock()
- want := ds.si.NumInput()
- ds.Unlock()
+// Query executes a prepared query statement with the given arguments
+// and returns the query results as a *Rows.
+func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
+ return s.QueryContext(context.Background(), args...)
+}
+
+func rowsiFromStatement(ctx context.Context, ds *driverStmt, args ...interface{}) (driver.Rows, error) {
+ var want int
+ withLock(ds, func() {
+ want = ds.si.NumInput()
+ })
// -1 means the driver doesn't know how to count the number of
// placeholders, so we won't sanity check input here and instead let the
@@ -1646,21 +1931,22 @@ func rowsiFromStatement(ds driverStmt, args ...interface{}) (driver.Rows, error)
return nil, fmt.Errorf("sql: statement expects %d inputs; got %d", want, len(args))
}
- dargs, err := driverArgs(&ds, args)
+ dargs, err := driverArgs(ds, args)
if err != nil {
return nil, err
}
ds.Lock()
- rowsi, err := ds.si.Query(dargs)
- ds.Unlock()
+ defer ds.Unlock()
+
+ rowsi, err := ctxDriverStmtQuery(ctx, ds.si, dargs)
if err != nil {
return nil, err
}
return rowsi, nil
}
-// QueryRow executes a prepared query statement with the given arguments.
+// QueryRowContext executes a prepared query statement with the given arguments.
// If an error occurs during the execution of the statement, that error will
// be returned by a call to Scan on the returned *Row, which is always non-nil.
// If the query selects no rows, the *Row's Scan will return ErrNoRows.
@@ -1670,15 +1956,30 @@ func rowsiFromStatement(ds driverStmt, args ...interface{}) (driver.Rows, error)
// Example usage:
//
// var name string
-// err := nameByUseridStmt.QueryRow(id).Scan(&name)
-func (s *Stmt) QueryRow(args ...interface{}) *Row {
- rows, err := s.Query(args...)
+// err := nameByUseridStmt.QueryRowContext(ctx, id).Scan(&name)
+func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row {
+ rows, err := s.QueryContext(ctx, args...)
if err != nil {
return &Row{err: err}
}
return &Row{rows: rows}
}
+// QueryRow executes a prepared query statement with the given arguments.
+// If an error occurs during the execution of the statement, that error will
+// be returned by a call to Scan on the returned *Row, which is always non-nil.
+// If the query selects no rows, the *Row's Scan will return ErrNoRows.
+// Otherwise, the *Row's Scan scans the first selected row and discards
+// the rest.
+//
+// Example usage:
+//
+// var name string
+// err := nameByUseridStmt.QueryRow(id).Scan(&name)
+func (s *Stmt) QueryRow(args ...interface{}) *Row {
+ return s.QueryRowContext(context.Background(), args...)
+}
+
// Close closes the statement.
func (s *Stmt) Close() error {
s.closemu.Lock()
@@ -1693,13 +1994,11 @@ func (s *Stmt) Close() error {
return nil
}
s.closed = true
+ s.mu.Unlock()
if s.tx != nil {
- err := s.txsi.Close()
- s.mu.Unlock()
- return err
+ return s.txds.Close()
}
- s.mu.Unlock()
return s.db.removeDep(s, s)
}
@@ -1709,8 +2008,8 @@ func (s *Stmt) finalClose() error {
defer s.mu.Unlock()
if s.css != nil {
for _, v := range s.css {
- s.db.noteUnusedDriverStatement(v.dc, v.si)
- v.dc.removeOpenStmt(v.si)
+ s.db.noteUnusedDriverStatement(v.dc, v.ds)
+ v.dc.removeOpenStmt(v.ds)
}
s.css = nil
}
@@ -1736,10 +2035,28 @@ type Rows struct {
releaseConn func(error)
rowsi driver.Rows
- closed bool
+ // closed value is 1 when the Rows is closed.
+ // Use atomic operations on value when checking value.
+ closed int32
+ ctxClose chan struct{} // closed when Rows is closed, may be null.
lastcols []driver.Value
lasterr error // non-nil only if closed is true
- closeStmt driver.Stmt // if non-nil, statement to Close on close
+ closeStmt *driverStmt // if non-nil, statement to Close on close
+}
+
+func (rs *Rows) initContextClose(ctx context.Context) {
+ if ctx.Done() == context.Background().Done() {
+ return
+ }
+
+ rs.ctxClose = make(chan struct{})
+ go func() {
+ select {
+ case <-ctx.Done():
+ rs.Close()
+ case <-rs.ctxClose:
+ }
+ }()
}
// Next prepares the next result row for reading with the Scan method. It
@@ -1749,7 +2066,7 @@ type Rows struct {
//
// Every call to Scan, even the first one, must be preceded by a call to Next.
func (rs *Rows) Next() bool {
- if rs.closed {
+ if rs.isClosed() {
return false
}
if rs.lastcols == nil {
@@ -1757,6 +2074,47 @@ func (rs *Rows) Next() bool {
}
rs.lasterr = rs.rowsi.Next(rs.lastcols)
if rs.lasterr != nil {
+ // Close the connection if there is a driver error.
+ if rs.lasterr != io.EOF {
+ rs.Close()
+ return false
+ }
+ nextResultSet, ok := rs.rowsi.(driver.RowsNextResultSet)
+ if !ok {
+ rs.Close()
+ return false
+ }
+ // The driver is at the end of the current result set.
+ // Test to see if there is another result set after the current one.
+ // Only close Rows if there is no further result sets to read.
+ if !nextResultSet.HasNextResultSet() {
+ rs.Close()
+ }
+ return false
+ }
+ return true
+}
+
+// NextResultSet prepares the next result set for reading. It returns true if
+// there is further result sets, or false if there is no further result set
+// or if there is an error advancing to it. The Err method should be consulted
+// to distinguish between the two cases.
+//
+// After calling NextResultSet, the Next method should always be called before
+// scanning. If there are further result sets they may not have rows in the result
+// set.
+func (rs *Rows) NextResultSet() bool {
+ if rs.isClosed() {
+ return false
+ }
+ rs.lastcols = nil
+ nextResultSet, ok := rs.rowsi.(driver.RowsNextResultSet)
+ if !ok {
+ rs.Close()
+ return false
+ }
+ rs.lasterr = nextResultSet.NextResultSet()
+ if rs.lasterr != nil {
rs.Close()
return false
}
@@ -1776,7 +2134,7 @@ func (rs *Rows) Err() error {
// Columns returns an error if the rows are closed, or if the rows
// are from QueryRow and there was a deferred error.
func (rs *Rows) Columns() ([]string, error) {
- if rs.closed {
+ if rs.isClosed() {
return nil, errors.New("sql: Rows are closed")
}
if rs.rowsi == nil {
@@ -1785,6 +2143,107 @@ func (rs *Rows) Columns() ([]string, error) {
return rs.rowsi.Columns(), nil
}
+// ColumnTypes returns column information such as column type, length,
+// and nullable. Some information may not be available from some drivers.
+func (rs *Rows) ColumnTypes() ([]*ColumnType, error) {
+ if rs.isClosed() {
+ return nil, errors.New("sql: Rows are closed")
+ }
+ if rs.rowsi == nil {
+ return nil, errors.New("sql: no Rows available")
+ }
+ return rowsColumnInfoSetup(rs.rowsi), nil
+}
+
+// ColumnType contains the name and type of a column.
+type ColumnType struct {
+ name string
+
+ hasNullable bool
+ hasLength bool
+ hasPrecisionScale bool
+
+ nullable bool
+ length int64
+ databaseType string
+ precision int64
+ scale int64
+ scanType reflect.Type
+}
+
+// Name returns the name or alias of the column.
+func (ci *ColumnType) Name() string {
+ return ci.name
+}
+
+// Length returns the column type length for variable length column types such
+// as text and binary field types. If the type length is unbounded the value will
+// be math.MaxInt64 (any database limits will still apply).
+// If the column type is not variable length, such as an int, or if not supported
+// by the driver ok is false.
+func (ci *ColumnType) Length() (length int64, ok bool) {
+ return ci.length, ci.hasLength
+}
+
+// DecimalSize returns the scale and precision of a decimal type.
+// If not applicable or if not supported ok is false.
+func (ci *ColumnType) DecimalSize() (precision, scale int64, ok bool) {
+ return ci.precision, ci.scale, ci.hasPrecisionScale
+}
+
+// ScanType returns a Go type suitable for scanning into using Rows.Scan.
+// If a driver does not support this property ScanType will return
+// the type of an empty interface.
+func (ci *ColumnType) ScanType() reflect.Type {
+ return ci.scanType
+}
+
+// Nullable returns whether the column may be null.
+// If a driver does not support this property ok will be false.
+func (ci *ColumnType) Nullable() (nullable, ok bool) {
+ return ci.nullable, ci.hasNullable
+}
+
+// DatabaseTypeName returns the database system name of the column type. If an empty
+// string is returned the driver type name is not supported.
+// Consult your driver documentation for a list of driver data types. Length specifiers
+// are not included.
+// Common type include "VARCHAR", "TEXT", "NVARCHAR", "DECIMAL", "BOOL", "INT", "BIGINT".
+func (ci *ColumnType) DatabaseTypeName() string {
+ return ci.databaseType
+}
+
+func rowsColumnInfoSetup(rowsi driver.Rows) []*ColumnType {
+ names := rowsi.Columns()
+
+ list := make([]*ColumnType, len(names))
+ for i := range list {
+ ci := &ColumnType{
+ name: names[i],
+ }
+ list[i] = ci
+
+ if prop, ok := rowsi.(driver.RowsColumnTypeScanType); ok {
+ ci.scanType = prop.ColumnTypeScanType(i)
+ } else {
+ ci.scanType = reflect.TypeOf(new(interface{})).Elem()
+ }
+ if prop, ok := rowsi.(driver.RowsColumnTypeDatabaseTypeName); ok {
+ ci.databaseType = prop.ColumnTypeDatabaseTypeName(i)
+ }
+ if prop, ok := rowsi.(driver.RowsColumnTypeLength); ok {
+ ci.length, ci.hasLength = prop.ColumnTypeLength(i)
+ }
+ if prop, ok := rowsi.(driver.RowsColumnTypeNullable); ok {
+ ci.nullable, ci.hasNullable = prop.ColumnTypeNullable(i)
+ }
+ if prop, ok := rowsi.(driver.RowsColumnTypePrecisionScale); ok {
+ ci.precision, ci.scale, ci.hasPrecisionScale = prop.ColumnTypePrecisionScale(i)
+ }
+ }
+ return list
+}
+
// Scan copies the columns in the current row into the values pointed
// at by dest. The number of values in dest must be the same as the
// number of columns in Rows.
@@ -1837,7 +2296,7 @@ func (rs *Rows) Columns() ([]string, error) {
// For scanning into *bool, the source may be true, false, 1, 0, or
// string inputs parseable by strconv.ParseBool.
func (rs *Rows) Scan(dest ...interface{}) error {
- if rs.closed {
+ if rs.isClosed() {
return errors.New("sql: Rows are closed")
}
if rs.lastcols == nil {
@@ -1857,14 +2316,21 @@ func (rs *Rows) Scan(dest ...interface{}) error {
var rowsCloseHook func(*Rows, *error)
-// Close closes the Rows, preventing further enumeration. If Next returns
-// false, the Rows are closed automatically and it will suffice to check the
+func (rs *Rows) isClosed() bool {
+ return atomic.LoadInt32(&rs.closed) != 0
+}
+
+// Close closes the Rows, preventing further enumeration. If Next is called
+// and returns false and there are no further result sets,
+// the Rows are closed automatically and it will suffice to check the
// result of Err. Close is idempotent and does not affect the result of Err.
func (rs *Rows) Close() error {
- if rs.closed {
+ if !atomic.CompareAndSwapInt32(&rs.closed, 0, 1) {
return nil
}
- rs.closed = true
+ if rs.ctxClose != nil {
+ close(rs.ctxClose)
+ }
err := rs.rowsi.Close()
if fn := rowsCloseHook; fn != nil {
fn(rs, &err)
diff --git a/libgo/go/database/sql/sql_test.go b/libgo/go/database/sql/sql_test.go
index 08df0c7666a..63e1292cb1f 100644
--- a/libgo/go/database/sql/sql_test.go
+++ b/libgo/go/database/sql/sql_test.go
@@ -5,6 +5,7 @@
package sql
import (
+ "context"
"database/sql/driver"
"errors"
"fmt"
@@ -23,6 +24,17 @@ func init() {
c *driverConn
}
freedFrom := make(map[dbConn]string)
+ var mu sync.Mutex
+ getFreedFrom := func(c dbConn) string {
+ mu.Lock()
+ defer mu.Unlock()
+ return freedFrom[c]
+ }
+ setFreedFrom := func(c dbConn, s string) {
+ mu.Lock()
+ defer mu.Unlock()
+ freedFrom[c] = s
+ }
putConnHook = func(db *DB, c *driverConn) {
idx := -1
for i, v := range db.freeConn {
@@ -35,10 +47,10 @@ func init() {
// 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.
- println("double free of conn. conflicts are:\nA) " + freedFrom[dbConn{db, c}] + "\n\nand\nB) " + stack())
+ println("double free of conn. conflicts are:\nA) " + getFreedFrom(dbConn{db, c}) + "\n\nand\nB) " + stack())
panic("double free of conn.")
}
- freedFrom[dbConn{db, c}] = stack()
+ setFreedFrom(dbConn{db, c}, stack())
}
}
@@ -140,10 +152,7 @@ func closeDB(t testing.TB, db *DB) {
if err != nil {
t.Fatalf("error closing DB: %v", err)
}
- db.mu.Lock()
- count := db.numOpen
- db.mu.Unlock()
- if count != 0 {
+ if count := db.numOpenConns(); count != 0 {
t.Fatalf("%d connections still open after closing DB", count)
}
}
@@ -182,6 +191,12 @@ func (db *DB) numFreeConns() int {
return len(db.freeConn)
}
+func (db *DB) numOpenConns() int {
+ db.mu.Lock()
+ defer db.mu.Unlock()
+ return db.numOpen
+}
+
// clearAllConns closes all connections in db.
func (db *DB) clearAllConns(t *testing.T) {
db.SetMaxIdleConns(0)
@@ -260,6 +275,257 @@ func TestQuery(t *testing.T) {
}
}
+func TestQueryContext(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+ prepares0 := numPrepares(t, db)
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ rows, err := db.QueryContext(ctx, "SELECT|people|age,name|")
+ if err != nil {
+ t.Fatalf("Query: %v", err)
+ }
+ type row struct {
+ age int
+ name string
+ }
+ got := []row{}
+ index := 0
+ for rows.Next() {
+ if index == 2 {
+ cancel()
+ time.Sleep(10 * time.Millisecond)
+ }
+ var r row
+ err = rows.Scan(&r.age, &r.name)
+ if err != nil {
+ if index == 2 {
+ break
+ }
+ t.Fatalf("Scan: %v", err)
+ }
+ if index == 2 && err == nil {
+ t.Fatal("expected an error on last scan")
+ }
+ got = append(got, r)
+ index++
+ }
+ err = rows.Err()
+ if err != nil {
+ t.Fatalf("Err: %v", err)
+ }
+ want := []row{
+ {age: 1, name: "Alice"},
+ {age: 2, name: "Bob"},
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want)
+ }
+
+ // And verify that the final rows.Next() call, which hit EOF,
+ // also closed the rows connection.
+ if n := db.numFreeConns(); n != 1 {
+ t.Fatalf("free conns after query hitting EOF = %d; want 1", n)
+ }
+ if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
+ t.Errorf("executed %d Prepare statements; want 1", prepares)
+ }
+}
+
+func waitCondition(waitFor, checkEvery time.Duration, fn func() bool) bool {
+ deadline := time.Now().Add(waitFor)
+ for time.Now().Before(deadline) {
+ if fn() {
+ return true
+ }
+ time.Sleep(checkEvery)
+ }
+ return false
+}
+
+func TestQueryContextWait(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+ prepares0 := numPrepares(t, db)
+
+ ctx, _ := context.WithTimeout(context.Background(), time.Millisecond*15)
+
+ // This will trigger the *fakeConn.Prepare method which will take time
+ // performing the query. The ctxDriverPrepare func will check the context
+ // after this and close the rows and return an error.
+ _, err := db.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|")
+ if err != context.DeadlineExceeded {
+ t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err)
+ }
+
+ // Verify closed rows connection after error condition.
+ if n := db.numFreeConns(); n != 1 {
+ t.Fatalf("free conns after query hitting EOF = %d; want 1", n)
+ }
+ if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
+ t.Errorf("executed %d Prepare statements; want 1", prepares)
+ }
+}
+
+func TestTxContextWait(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ ctx, _ := context.WithTimeout(context.Background(), time.Millisecond*15)
+
+ tx, err := db.BeginTx(ctx, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // This will trigger the *fakeConn.Prepare method which will take time
+ // performing the query. The ctxDriverPrepare func will check the context
+ // after this and close the rows and return an error.
+ _, err = tx.QueryContext(ctx, "WAIT|1s|SELECT|people|age,name|")
+ if err != context.DeadlineExceeded {
+ t.Fatalf("expected QueryContext to error with context deadline exceeded but returned %v", err)
+ }
+
+ var numFree int
+ if !waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
+ numFree = db.numFreeConns()
+ return numFree == 0
+ }) {
+ t.Fatalf("free conns after hitting EOF = %d; want 0", numFree)
+ }
+
+ // Ensure the dropped connection allows more connections to be made.
+ // Checked on DB Close.
+ waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
+ return db.numOpenConns() == 0
+ })
+}
+
+func TestMultiResultSetQuery(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+ prepares0 := numPrepares(t, db)
+ rows, err := db.Query("SELECT|people|age,name|;SELECT|people|name|")
+ if err != nil {
+ t.Fatalf("Query: %v", err)
+ }
+ type row1 struct {
+ age int
+ name string
+ }
+ type row2 struct {
+ name string
+ }
+ got1 := []row1{}
+ for rows.Next() {
+ var r row1
+ err = rows.Scan(&r.age, &r.name)
+ if err != nil {
+ t.Fatalf("Scan: %v", err)
+ }
+ got1 = append(got1, r)
+ }
+ err = rows.Err()
+ if err != nil {
+ t.Fatalf("Err: %v", err)
+ }
+ want1 := []row1{
+ {age: 1, name: "Alice"},
+ {age: 2, name: "Bob"},
+ {age: 3, name: "Chris"},
+ }
+ if !reflect.DeepEqual(got1, want1) {
+ t.Errorf("mismatch.\n got1: %#v\nwant: %#v", got1, want1)
+ }
+
+ if !rows.NextResultSet() {
+ t.Errorf("expected another result set")
+ }
+
+ got2 := []row2{}
+ for rows.Next() {
+ var r row2
+ err = rows.Scan(&r.name)
+ if err != nil {
+ t.Fatalf("Scan: %v", err)
+ }
+ got2 = append(got2, r)
+ }
+ err = rows.Err()
+ if err != nil {
+ t.Fatalf("Err: %v", err)
+ }
+ want2 := []row2{
+ {name: "Alice"},
+ {name: "Bob"},
+ {name: "Chris"},
+ }
+ if !reflect.DeepEqual(got2, want2) {
+ t.Errorf("mismatch.\n got: %#v\nwant: %#v", got2, want2)
+ }
+ if rows.NextResultSet() {
+ t.Errorf("expected no more result sets")
+ }
+
+ // And verify that the final rows.Next() call, which hit EOF,
+ // also closed the rows connection.
+ if n := db.numFreeConns(); n != 1 {
+ t.Fatalf("free conns after query hitting EOF = %d; want 1", n)
+ }
+ if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
+ t.Errorf("executed %d Prepare statements; want 1", prepares)
+ }
+}
+
+func TestQueryNamedArg(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+ prepares0 := numPrepares(t, db)
+ rows, err := db.Query(
+ // Ensure the name and age parameters only match on placeholder name, not position.
+ "SELECT|people|age,name|name=?name,age=?age",
+ Named("age", 2),
+ Named("name", "Bob"),
+ )
+ if err != nil {
+ t.Fatalf("Query: %v", err)
+ }
+ type row struct {
+ age int
+ name string
+ }
+ got := []row{}
+ for rows.Next() {
+ var r row
+ err = rows.Scan(&r.age, &r.name)
+ if err != nil {
+ t.Fatalf("Scan: %v", err)
+ }
+ got = append(got, r)
+ }
+ err = rows.Err()
+ if err != nil {
+ t.Fatalf("Err: %v", err)
+ }
+ want := []row{
+ {age: 2, name: "Bob"},
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("mismatch.\n got: %#v\nwant: %#v", got, want)
+ }
+
+ // And verify that the final rows.Next() call, which hit EOF,
+ // also closed the rows connection.
+ if n := db.numFreeConns(); n != 1 {
+ t.Fatalf("free conns after query hitting EOF = %d; want 1", n)
+ }
+ if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
+ t.Errorf("executed %d Prepare statements; want 1", prepares)
+ }
+}
+
func TestByteOwnership(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
@@ -317,6 +583,56 @@ func TestRowsColumns(t *testing.T) {
}
}
+func TestRowsColumnTypes(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+ rows, err := db.Query("SELECT|people|age,name|")
+ if err != nil {
+ t.Fatalf("Query: %v", err)
+ }
+ tt, err := rows.ColumnTypes()
+ if err != nil {
+ t.Fatalf("ColumnTypes: %v", err)
+ }
+
+ types := make([]reflect.Type, len(tt))
+ for i, tp := range tt {
+ st := tp.ScanType()
+ if st == nil {
+ t.Errorf("scantype is null for column %q", tp.Name())
+ continue
+ }
+ types[i] = st
+ }
+ values := make([]interface{}, len(tt))
+ for i := range values {
+ values[i] = reflect.New(types[i]).Interface()
+ }
+ ct := 0
+ for rows.Next() {
+ err = rows.Scan(values...)
+ if err != nil {
+ t.Fatalf("failed to scan values in %v", err)
+ }
+ ct++
+ if ct == 0 {
+ if values[0].(string) != "Bob" {
+ t.Errorf("Expected Bob, got %v", values[0])
+ }
+ if values[1].(int) != 2 {
+ t.Errorf("Expected 2, got %v", values[1])
+ }
+ }
+ }
+ if ct != 3 {
+ t.Errorf("expected 3 rows, got %d", ct)
+ }
+
+ if err := rows.Close(); err != nil {
+ t.Errorf("error closing rows: %s", err)
+ }
+}
+
func TestQueryRow(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
@@ -367,6 +683,37 @@ func TestQueryRow(t *testing.T) {
}
}
+func TestTxRollbackCommitErr(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ tx, err := db.Begin()
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = tx.Rollback()
+ if err != nil {
+ t.Errorf("expected nil error from Rollback; got %v", err)
+ }
+ err = tx.Commit()
+ if err != ErrTxDone {
+ t.Errorf("expected %q from Commit; got %q", ErrTxDone, err)
+ }
+
+ tx, err = db.Begin()
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = tx.Commit()
+ if err != nil {
+ t.Errorf("expected nil error from Commit; got %v", err)
+ }
+ err = tx.Rollback()
+ if err != ErrTxDone {
+ t.Errorf("expected %q from Rollback; got %q", ErrTxDone, err)
+ }
+}
+
func TestStatementErrorAfterClose(t *testing.T) {
db := newTestDB(t, "people")
defer closeDB(t, db)
@@ -439,7 +786,7 @@ func TestStatementClose(t *testing.T) {
msg string
}{
{&Stmt{stickyErr: want}, "stickyErr not propagated"},
- {&Stmt{tx: &Tx{}, txsi: &driverStmt{&sync.Mutex{}, stubDriverStmt{want}}}, "driverStmt.Close() error not propagated"},
+ {&Stmt{tx: &Tx{}, txds: &driverStmt{Locker: &sync.Mutex{}, si: stubDriverStmt{want}}}, "driverStmt.Close() error not propagated"},
}
for _, test := range tests {
if err := test.stmt.Close(); err != want {
@@ -513,8 +860,8 @@ func TestExec(t *testing.T) {
{[]interface{}{7, 9}, ""},
// Invalid conversions:
- {[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument #1's type: sql/driver: value 4294967295 overflows int32"},
- {[]interface{}{"Brad", "strconv fail"}, "sql: converting argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"},
+ {[]interface{}{"Brad", int64(0xFFFFFFFF)}, "sql: converting argument $2 type: sql/driver: value 4294967295 overflows int32"},
+ {[]interface{}{"Brad", "strconv fail"}, `sql: converting argument $2 type: sql/driver: value "strconv fail" can't be converted to int32`},
// Wrong number of args:
{[]interface{}{}, "sql: expected 2 arguments, got 0"},
@@ -1159,17 +1506,19 @@ func TestMaxOpenConnsOnBusy(t *testing.T) {
db.SetMaxOpenConns(3)
- conn0, err := db.conn(cachedOrNewConn)
+ ctx := context.Background()
+
+ conn0, err := db.conn(ctx, cachedOrNewConn)
if err != nil {
t.Fatalf("db open conn fail: %v", err)
}
- conn1, err := db.conn(cachedOrNewConn)
+ conn1, err := db.conn(ctx, cachedOrNewConn)
if err != nil {
t.Fatalf("db open conn fail: %v", err)
}
- conn2, err := db.conn(cachedOrNewConn)
+ conn2, err := db.conn(ctx, cachedOrNewConn)
if err != nil {
t.Fatalf("db open conn fail: %v", err)
}
@@ -1203,7 +1552,11 @@ func TestPendingConnsAfterErr(t *testing.T) {
tryOpen = maxOpen*2 + 2
)
- db := newTestDB(t, "people")
+ // No queries will be run.
+ db, err := Open("test", fakeDBName)
+ if err != nil {
+ t.Fatalf("Open: %v", err)
+ }
defer closeDB(t, db)
defer func() {
for k, v := range db.lastPut {
@@ -1215,29 +1568,29 @@ func TestPendingConnsAfterErr(t *testing.T) {
db.SetMaxIdleConns(0)
errOffline := errors.New("db offline")
+
defer func() { setHookOpenErr(nil) }()
errs := make(chan error, tryOpen)
- unblock := make(chan struct{})
+ var opening sync.WaitGroup
+ opening.Add(tryOpen)
+
setHookOpenErr(func() error {
- <-unblock // block until all connections are in flight
+ // Wait for all connections to enqueue.
+ opening.Wait()
return errOffline
})
- var opening sync.WaitGroup
- opening.Add(tryOpen)
for i := 0; i < tryOpen; i++ {
go func() {
opening.Done() // signal one connection is in flight
- _, err := db.Exec("INSERT|people|name=Julia,age=19")
+ _, err := db.Exec("will never run")
errs <- err
}()
}
- opening.Wait() // wait for all workers to begin running
- time.Sleep(10 * time.Millisecond) // make extra sure all workers are blocked
- close(unblock) // let all workers proceed
+ opening.Wait() // wait for all workers to begin running
const timeout = 5 * time.Second
to := time.NewTimer(timeout)
@@ -1254,6 +1607,24 @@ func TestPendingConnsAfterErr(t *testing.T) {
t.Fatalf("orphaned connection request(s), still waiting after %v", timeout)
}
}
+
+ // Wait a reasonable time for the database to close all connections.
+ tick := time.NewTicker(3 * time.Millisecond)
+ defer tick.Stop()
+ for {
+ select {
+ case <-tick.C:
+ db.mu.Lock()
+ if db.numOpen == 0 {
+ db.mu.Unlock()
+ return
+ }
+ db.mu.Unlock()
+ case <-to.C:
+ // Closing the database will check for numOpen and fail the test.
+ return
+ }
+ }
}
func TestSingleOpenConn(t *testing.T) {
@@ -2236,6 +2607,54 @@ func TestIssue6081(t *testing.T) {
}
}
+// TestIssue18429 attempts to stress rolling back the transaction from a
+// context cancel while simultaneously calling Tx.Rollback. Rolling back from a
+// context happens concurrently so tx.rollback and tx.Commit must guard against
+// double entry.
+//
+// In the test, a context is canceled while the query is in process so
+// the internal rollback will run concurrently with the explicitly called
+// Tx.Rollback.
+func TestIssue18429(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ ctx := context.Background()
+ sem := make(chan bool, 20)
+ var wg sync.WaitGroup
+
+ const milliWait = 30
+
+ for i := 0; i < 100; i++ {
+ sem <- true
+ wg.Add(1)
+ go func() {
+ defer func() {
+ <-sem
+ wg.Done()
+ }()
+ qwait := (time.Duration(rand.Intn(milliWait)) * time.Millisecond).String()
+
+ ctx, cancel := context.WithTimeout(ctx, time.Duration(rand.Intn(milliWait))*time.Millisecond)
+ defer cancel()
+
+ tx, err := db.BeginTx(ctx, nil)
+ if err != nil {
+ return
+ }
+ rows, err := tx.QueryContext(ctx, "WAIT|"+qwait+"|SELECT|people|name|")
+ if rows != nil {
+ rows.Close()
+ }
+ // This call will race with the context cancel rollback to complete
+ // if the rollback itself isn't guarded.
+ tx.Rollback()
+ }()
+ }
+ wg.Wait()
+ time.Sleep(milliWait * 3 * time.Millisecond)
+}
+
func TestConcurrency(t *testing.T) {
doConcurrentTest(t, new(concurrentDBQueryTest))
doConcurrentTest(t, new(concurrentDBExecTest))
@@ -2279,7 +2698,8 @@ func TestConnectionLeak(t *testing.T) {
go func() {
r, err := db.Query("SELECT|people|name|")
if err != nil {
- t.Fatal(err)
+ t.Error(err)
+ return
}
r.Close()
wg.Done()
@@ -2299,6 +2719,97 @@ func TestConnectionLeak(t *testing.T) {
wg.Wait()
}
+// badConn implements a bad driver.Conn, for TestBadDriver.
+// The Exec method panics.
+type badConn struct{}
+
+func (bc badConn) Prepare(query string) (driver.Stmt, error) {
+ return nil, errors.New("badConn Prepare")
+}
+
+func (bc badConn) Close() error {
+ return nil
+}
+
+func (bc badConn) Begin() (driver.Tx, error) {
+ return nil, errors.New("badConn Begin")
+}
+
+func (bc badConn) Exec(query string, args []driver.Value) (driver.Result, error) {
+ panic("badConn.Exec")
+}
+
+// badDriver is a driver.Driver that uses badConn.
+type badDriver struct{}
+
+func (bd badDriver) Open(name string) (driver.Conn, error) {
+ return badConn{}, nil
+}
+
+// Issue 15901.
+func TestBadDriver(t *testing.T) {
+ Register("bad", badDriver{})
+ db, err := Open("bad", "ignored")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer func() {
+ if r := recover(); r == nil {
+ t.Error("expected panic")
+ } else {
+ if want := "badConn.Exec"; r.(string) != want {
+ t.Errorf("panic was %v, expected %v", r, want)
+ }
+ }
+ }()
+ defer db.Close()
+ db.Exec("ignored")
+}
+
+type pingDriver struct {
+ fails bool
+}
+
+type pingConn struct {
+ badConn
+ driver *pingDriver
+}
+
+var pingError = errors.New("Ping failed")
+
+func (pc pingConn) Ping(ctx context.Context) error {
+ if pc.driver.fails {
+ return pingError
+ }
+ return nil
+}
+
+var _ driver.Pinger = pingConn{}
+
+func (pd *pingDriver) Open(name string) (driver.Conn, error) {
+ return pingConn{driver: pd}, nil
+}
+
+func TestPing(t *testing.T) {
+ driver := &pingDriver{}
+ Register("ping", driver)
+
+ db, err := Open("ping", "ignored")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := db.Ping(); err != nil {
+ t.Errorf("err was %#v, expected nil", err)
+ return
+ }
+
+ driver.fails = true
+ if err := db.Ping(); err != pingError {
+ t.Errorf("err was %#v, expected pingError", err)
+ }
+}
+
func BenchmarkConcurrentDBExec(b *testing.B) {
b.ReportAllocs()
ct := new(concurrentDBExecTest)
diff --git a/libgo/go/debug/elf/file.go b/libgo/go/debug/elf/file.go
index c1cbfa62254..8eeab65df89 100644
--- a/libgo/go/debug/elf/file.go
+++ b/libgo/go/debug/elf/file.go
@@ -579,7 +579,7 @@ func (f *File) Section(name string) *Section {
}
// applyRelocations applies relocations to dst. rels is a relocations section
-// in RELA format.
+// in REL or RELA format.
func (f *File) applyRelocations(dst []byte, rels []byte) error {
switch {
case f.Class == ELFCLASS64 && f.Machine == EM_X86_64:
@@ -594,6 +594,8 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error {
return f.applyRelocationsPPC(dst, rels)
case f.Class == ELFCLASS64 && f.Machine == EM_PPC64:
return f.applyRelocationsPPC64(dst, rels)
+ case f.Class == ELFCLASS32 && f.Machine == EM_MIPS:
+ return f.applyRelocationsMIPS(dst, rels)
case f.Class == ELFCLASS64 && f.Machine == EM_MIPS:
return f.applyRelocationsMIPS64(dst, rels)
case f.Class == ELFCLASS64 && f.Machine == EM_S390:
@@ -863,6 +865,44 @@ func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
return nil
}
+func (f *File) applyRelocationsMIPS(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_MIPS(rel.Info & 0xff)
+
+ if symNo == 0 || symNo > uint32(len(symbols)) {
+ continue
+ }
+ sym := &symbols[symNo-1]
+
+ switch t {
+ case R_MIPS_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) applyRelocationsMIPS64(dst []byte, rels []byte) error {
// 24 is the size of Rela64.
if len(rels)%24 != 0 {
@@ -981,7 +1021,7 @@ func (f *File) applyRelocationsSPARC64(dst []byte, rels []byte) error {
for b.Len() > 0 {
binary.Read(b, f.ByteOrder, &rela)
symNo := rela.Info >> 32
- t := R_SPARC(rela.Info & 0xffff)
+ t := R_SPARC(rela.Info & 0xff)
if symNo == 0 || symNo > uint64(len(symbols)) {
continue
diff --git a/libgo/go/debug/elf/file_test.go b/libgo/go/debug/elf/file_test.go
index f1e28a06715..58bdf277d36 100644
--- a/libgo/go/debug/elf/file_test.go
+++ b/libgo/go/debug/elf/file_test.go
@@ -511,6 +511,44 @@ var relocationTests = []relocationTest{
},
},
{
+ "testdata/go-relocation-test-gcc492-mipsle.obj",
+ []relocationTestEntry{
+ {0, &dwarf.Entry{
+ Offset: 0xb,
+ Tag: dwarf.TagCompileUnit,
+ Children: true,
+ Field: []dwarf.Field{
+ {Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -mel -march=mips2 -mtune=mips32 -mllsc -mno-shared -mabi=32 -g", Class: dwarf.ClassString},
+ {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
+ {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
+ {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+ {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+ {Attr: dwarf.AttrHighpc, Val: int64(0x58), Class: dwarf.ClassConstant},
+ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+ },
+ }},
+ },
+ },
+ {
+ "testdata/go-relocation-test-gcc540-mips.obj",
+ []relocationTestEntry{
+ {0, &dwarf.Entry{
+ Offset: 0xb,
+ Tag: dwarf.TagCompileUnit,
+ Children: true,
+ Field: []dwarf.Field{
+ {Attr: dwarf.AttrProducer, Val: "GNU C11 5.4.0 20160609 -meb -mips32 -mtune=mips32r2 -mfpxx -mllsc -mno-shared -mabi=32 -g -gdwarf-2", Class: dwarf.ClassString},
+ {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
+ {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
+ {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+ {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+ {Attr: dwarf.AttrHighpc, Val: uint64(0x5c), Class: dwarf.ClassAddress},
+ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+ },
+ }},
+ },
+ },
+ {
"testdata/go-relocation-test-gcc493-mips64le.obj",
[]relocationTestEntry{
{0, &dwarf.Entry{
diff --git a/libgo/go/debug/elf/testdata/go-relocation-test-gcc492-mipsle.obj b/libgo/go/debug/elf/testdata/go-relocation-test-gcc492-mipsle.obj
new file mode 100644
index 00000000000..a5fbcfbbdd2
--- /dev/null
+++ b/libgo/go/debug/elf/testdata/go-relocation-test-gcc492-mipsle.obj
Binary files differ
diff --git a/libgo/go/debug/elf/testdata/go-relocation-test-gcc540-mips.obj b/libgo/go/debug/elf/testdata/go-relocation-test-gcc540-mips.obj
new file mode 100644
index 00000000000..270c7775968
--- /dev/null
+++ b/libgo/go/debug/elf/testdata/go-relocation-test-gcc540-mips.obj
Binary files differ
diff --git a/libgo/go/debug/gosym/pclntab.go b/libgo/go/debug/gosym/pclntab.go
index e859d5aed50..ba1cf8b699a 100644
--- a/libgo/go/debug/gosym/pclntab.go
+++ b/libgo/go/debug/gosym/pclntab.go
@@ -295,9 +295,6 @@ func (t *LineTable) step(p *[]byte, pc *uint64, val *int32, first bool) bool {
// off is the offset to the beginning of the pc-value table,
// and entry is the start PC for the corresponding function.
func (t *LineTable) pcvalue(off uint32, entry, targetpc uint64) int32 {
- if off == 0 {
- return -1
- }
p := t.Data[off:]
val := int32(-1)
diff --git a/libgo/go/debug/gosym/pclntab_test.go b/libgo/go/debug/gosym/pclntab_test.go
index 9f82e31ae41..7e7cee67934 100644
--- a/libgo/go/debug/gosym/pclntab_test.go
+++ b/libgo/go/debug/gosym/pclntab_test.go
@@ -37,7 +37,7 @@ func dotest(t *testing.T) {
// the resulting binary looks like it was built from pclinetest.s,
// but we have renamed it to keep it away from the go tool.
pclinetestBinary = filepath.Join(pclineTempDir, "pclinetest")
- cmd := exec.Command("go", "tool", "asm", "-o", pclinetestBinary+".o", "pclinetest.asm")
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", pclinetestBinary+".o", "pclinetest.asm")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
@@ -58,7 +58,7 @@ func dotest(t *testing.T) {
t.Fatal(err)
}
- cmd = exec.Command("go", "tool", "link", "-H", "linux",
+ cmd = exec.Command(testenv.GoToolPath(t), "tool", "link", "-H", "linux",
"-o", pclinetestBinary, pclinetestBinary+".o")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
diff --git a/libgo/go/debug/macho/macho.go b/libgo/go/debug/macho/macho.go
index 31647536ac5..40ac74e9a14 100644
--- a/libgo/go/debug/macho/macho.go
+++ b/libgo/go/debug/macho/macho.go
@@ -145,7 +145,7 @@ type Section32 struct {
Reserve2 uint32
}
-// A Section32 is a 64-bit Mach-O section header.
+// A Section64 is a 64-bit Mach-O section header.
type Section64 struct {
Name [16]byte
Seg [16]byte
diff --git a/libgo/go/debug/pe/file.go b/libgo/go/debug/pe/file.go
index 3074ba0f506..87f225cb398 100644
--- a/libgo/go/debug/pe/file.go
+++ b/libgo/go/debug/pe/file.go
@@ -13,14 +13,17 @@ import (
"os"
)
+// Avoid use of post-Go 1.4 io features, to make safe for toolchain bootstrap.
+const seekStart = 0
+
// A File represents an open PE file.
type File struct {
FileHeader
OptionalHeader interface{} // of type *OptionalHeader32 or *OptionalHeader64
Sections []*Section
Symbols []*Symbol // COFF symbols with auxiliary symbol records removed
- _COFFSymbols []COFFSymbol // all COFF symbols (including auxiliary symbol records)
- _StringTable _StringTable
+ COFFSymbols []COFFSymbol // all COFF symbols (including auxiliary symbol records)
+ StringTable StringTable
closer io.Closer
}
@@ -80,7 +83,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
} else {
base = int64(0)
}
- sr.Seek(base, io.SeekStart)
+ sr.Seek(base, seekStart)
if err := binary.Read(sr, binary.LittleEndian, &f.FileHeader); err != nil {
return nil, err
}
@@ -93,23 +96,23 @@ func NewFile(r io.ReaderAt) (*File, error) {
var err error
// Read string table.
- f._StringTable, err = readStringTable(&f.FileHeader, sr)
+ f.StringTable, err = readStringTable(&f.FileHeader, sr)
if err != nil {
return nil, err
}
// Read symbol table.
- f._COFFSymbols, err = readCOFFSymbols(&f.FileHeader, sr)
+ f.COFFSymbols, err = readCOFFSymbols(&f.FileHeader, sr)
if err != nil {
return nil, err
}
- f.Symbols, err = removeAuxSymbols(f._COFFSymbols, f._StringTable)
+ f.Symbols, err = removeAuxSymbols(f.COFFSymbols, f.StringTable)
if err != nil {
return nil, err
}
// Read optional header.
- sr.Seek(base, io.SeekStart)
+ sr.Seek(base, seekStart)
if err := binary.Read(sr, binary.LittleEndian, &f.FileHeader); err != nil {
return nil, err
}
@@ -141,7 +144,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
if err := binary.Read(sr, binary.LittleEndian, sh); err != nil {
return nil, err
}
- name, err := sh.fullName(f._StringTable)
+ name, err := sh.fullName(f.StringTable)
if err != nil {
return nil, err
}
@@ -168,7 +171,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
}
for i := range f.Sections {
var err error
- f.Sections[i]._Relocs, err = readRelocs(&f.Sections[i].SectionHeader, sr)
+ f.Sections[i].Relocs, err = readRelocs(&f.Sections[i].SectionHeader, sr)
if err != nil {
return nil, err
}
diff --git a/libgo/go/debug/pe/file_test.go b/libgo/go/debug/pe/file_test.go
index 964caf56ec7..5a740c87050 100644
--- a/libgo/go/debug/pe/file_test.go
+++ b/libgo/go/debug/pe/file_test.go
@@ -307,7 +307,7 @@ func main() {
src := filepath.Join(tmpdir, "a.go")
exe := filepath.Join(tmpdir, "a.exe")
err = ioutil.WriteFile(src, []byte(prog), 0644)
- output, err := exec.Command("go", "build", "-o", exe, src).CombinedOutput()
+ output, err := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, src).CombinedOutput()
if err != nil {
t.Fatalf("building test executable failed: %s %s", err, output)
}
diff --git a/libgo/go/debug/pe/section.go b/libgo/go/debug/pe/section.go
index 8e6690f0820..b641158eccb 100644
--- a/libgo/go/debug/pe/section.go
+++ b/libgo/go/debug/pe/section.go
@@ -28,7 +28,7 @@ type SectionHeader32 struct {
// fullName finds real name of section sh. Normally name is stored
// in sh.Name, but if it is longer then 8 characters, it is stored
// in COFF string table st instead.
-func (sh *SectionHeader32) fullName(st _StringTable) (string, error) {
+func (sh *SectionHeader32) fullName(st StringTable) (string, error) {
if sh.Name[0] != '/' {
return cstring(sh.Name[:]), nil
}
@@ -41,23 +41,23 @@ func (sh *SectionHeader32) fullName(st _StringTable) (string, error) {
// TODO(brainman): copy all IMAGE_REL_* consts from ldpe.go here
-// _Reloc represents a PE COFF relocation.
+// Reloc represents a PE COFF relocation.
// Each section contains its own relocation list.
-type _Reloc struct {
+type Reloc struct {
VirtualAddress uint32
SymbolTableIndex uint32
Type uint16
}
-func readRelocs(sh *SectionHeader, r io.ReadSeeker) ([]_Reloc, error) {
+func readRelocs(sh *SectionHeader, r io.ReadSeeker) ([]Reloc, error) {
if sh.NumberOfRelocations <= 0 {
return nil, nil
}
- _, err := r.Seek(int64(sh.PointerToRelocations), io.SeekStart)
+ _, err := r.Seek(int64(sh.PointerToRelocations), seekStart)
if err != nil {
return nil, fmt.Errorf("fail to seek to %q section relocations: %v", sh.Name, err)
}
- relocs := make([]_Reloc, sh.NumberOfRelocations)
+ relocs := make([]Reloc, sh.NumberOfRelocations)
err = binary.Read(r, binary.LittleEndian, relocs)
if err != nil {
return nil, fmt.Errorf("fail to read section relocations: %v", err)
@@ -83,7 +83,7 @@ type SectionHeader struct {
// Section provides access to PE COFF section.
type Section struct {
SectionHeader
- _Relocs []_Reloc
+ Relocs []Reloc
// Embed ReaderAt for ReadAt method.
// Do not embed SectionReader directly
diff --git a/libgo/go/debug/pe/string.go b/libgo/go/debug/pe/string.go
index 69837f6d019..c30255f341a 100644
--- a/libgo/go/debug/pe/string.go
+++ b/libgo/go/debug/pe/string.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The Go Authors. All rights reserved.
+// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -19,16 +19,16 @@ func cstring(b []byte) string {
return string(b[:i])
}
-// _StringTable is a COFF string table.
-type _StringTable []byte
+// StringTable is a COFF string table.
+type StringTable []byte
-func readStringTable(fh *FileHeader, r io.ReadSeeker) (_StringTable, error) {
+func readStringTable(fh *FileHeader, r io.ReadSeeker) (StringTable, error) {
// COFF string table is located right after COFF symbol table.
if fh.PointerToSymbolTable <= 0 {
return nil, nil
}
offset := fh.PointerToSymbolTable + COFFSymbolSize*fh.NumberOfSymbols
- _, err := r.Seek(int64(offset), io.SeekStart)
+ _, err := r.Seek(int64(offset), seekStart)
if err != nil {
return nil, fmt.Errorf("fail to seek to string table: %v", err)
}
@@ -47,13 +47,13 @@ func readStringTable(fh *FileHeader, r io.ReadSeeker) (_StringTable, error) {
if err != nil {
return nil, fmt.Errorf("fail to read string table: %v", err)
}
- return _StringTable(buf), nil
+ return StringTable(buf), nil
}
// TODO(brainman): decide if start parameter should be int instead of uint32
// String extracts string from COFF string table st at offset start.
-func (st _StringTable) String(start uint32) (string, error) {
+func (st StringTable) String(start uint32) (string, error) {
// start includes 4 bytes of string table length
if start < 4 {
return "", fmt.Errorf("offset %d is before the start of string table", start)
diff --git a/libgo/go/debug/pe/symbol.go b/libgo/go/debug/pe/symbol.go
index 7b8cbf236be..7fa5948641f 100644
--- a/libgo/go/debug/pe/symbol.go
+++ b/libgo/go/debug/pe/symbol.go
@@ -23,10 +23,13 @@ type COFFSymbol struct {
}
func readCOFFSymbols(fh *FileHeader, r io.ReadSeeker) ([]COFFSymbol, error) {
+ if fh.PointerToSymbolTable == 0 {
+ return nil, nil
+ }
if fh.NumberOfSymbols <= 0 {
return nil, nil
}
- _, err := r.Seek(int64(fh.PointerToSymbolTable), io.SeekStart)
+ _, err := r.Seek(int64(fh.PointerToSymbolTable), seekStart)
if err != nil {
return nil, fmt.Errorf("fail to seek to symbol table: %v", err)
}
@@ -46,17 +49,17 @@ func isSymNameOffset(name [8]byte) (bool, uint32) {
return false, 0
}
-// _FullName finds real name of symbol sym. Normally name is stored
+// FullName finds real name of symbol sym. Normally name is stored
// in sym.Name, but if it is longer then 8 characters, it is stored
// in COFF string table st instead.
-func (sym *COFFSymbol) _FullName(st _StringTable) (string, error) {
+func (sym *COFFSymbol) FullName(st StringTable) (string, error) {
if ok, offset := isSymNameOffset(sym.Name); ok {
return st.String(offset)
}
return cstring(sym.Name[:]), nil
}
-func removeAuxSymbols(allsyms []COFFSymbol, st _StringTable) ([]*Symbol, error) {
+func removeAuxSymbols(allsyms []COFFSymbol, st StringTable) ([]*Symbol, error) {
if len(allsyms) == 0 {
return nil, nil
}
@@ -67,7 +70,7 @@ func removeAuxSymbols(allsyms []COFFSymbol, st _StringTable) ([]*Symbol, error)
aux--
continue
}
- name, err := sym._FullName(st)
+ name, err := sym.FullName(st)
if err != nil {
return nil, err
}
diff --git a/libgo/go/encoding/asn1/asn1.go b/libgo/go/encoding/asn1/asn1.go
index 2b5ad08551e..044f74ab469 100644
--- a/libgo/go/encoding/asn1/asn1.go
+++ b/libgo/go/encoding/asn1/asn1.go
@@ -841,6 +841,13 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
case reflect.Struct:
structType := fieldType
+ for i := 0; i < structType.NumField(); i++ {
+ if structType.Field(i).PkgPath != "" {
+ err = StructuralError{"struct contains unexported fields"}
+ return
+ }
+ }
+
if structType.NumField() > 0 &&
structType.Field(0).Type == rawContentsType {
bytes := bytes[initOffset:offset]
@@ -969,7 +976,7 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) {
// The following tags on struct fields have special meaning to Unmarshal:
//
// application specifies that a APPLICATION tag is used
-// default:x sets the default value for optional integer fields
+// default:x sets the default value for optional integer fields (only used if optional is also present)
// explicit specifies that an additional, explicit tag wraps the implicit one
// optional marks the field as ASN.1 OPTIONAL
// set causes a SET, rather than a SEQUENCE type to be expected
diff --git a/libgo/go/encoding/asn1/asn1_test.go b/libgo/go/encoding/asn1/asn1_test.go
index f8623fa9a21..9976656df89 100644
--- a/libgo/go/encoding/asn1/asn1_test.go
+++ b/libgo/go/encoding/asn1/asn1_test.go
@@ -132,9 +132,13 @@ func TestParseBigInt(t *testing.T) {
if ret.String() != test.base10 {
t.Errorf("#%d: bad result from %x, got %s want %s", i, test.in, ret.String(), test.base10)
}
- fw := newForkableWriter()
- marshalBigInt(fw, ret)
- result := fw.Bytes()
+ e, err := makeBigInt(ret)
+ if err != nil {
+ t.Errorf("%d: err=%q", i, err)
+ continue
+ }
+ result := make([]byte, e.Len())
+ e.Encode(result)
if !bytes.Equal(result, test.in) {
t.Errorf("#%d: got %x from marshaling %s, want %x", i, result, ret, test.in)
}
@@ -963,7 +967,7 @@ func TestUnmarshalInvalidUTF8(t *testing.T) {
func TestMarshalNilValue(t *testing.T) {
nilValueTestData := []interface{}{
nil,
- struct{ v interface{} }{},
+ struct{ V interface{} }{},
}
for i, test := range nilValueTestData {
if _, err := Marshal(test); err == nil {
@@ -971,3 +975,32 @@ func TestMarshalNilValue(t *testing.T) {
}
}
}
+
+type unexported struct {
+ X int
+ y int
+}
+
+type exported struct {
+ X int
+ Y int
+}
+
+func TestUnexportedStructField(t *testing.T) {
+ want := StructuralError{"struct contains unexported fields"}
+
+ _, err := Marshal(unexported{X: 5, y: 1})
+ if err != want {
+ t.Errorf("got %v, want %v", err, want)
+ }
+
+ bs, err := Marshal(exported{X: 5, Y: 1})
+ if err != nil {
+ t.Fatal(err)
+ }
+ var u unexported
+ _, err = Unmarshal(bs, &u)
+ if err != want {
+ t.Errorf("got %v, want %v", err, want)
+ }
+}
diff --git a/libgo/go/encoding/asn1/marshal.go b/libgo/go/encoding/asn1/marshal.go
index 30797ef0996..225fd0849c6 100644
--- a/libgo/go/encoding/asn1/marshal.go
+++ b/libgo/go/encoding/asn1/marshal.go
@@ -5,77 +5,125 @@
package asn1
import (
- "bytes"
"errors"
"fmt"
- "io"
"math/big"
"reflect"
"time"
"unicode/utf8"
)
-// A forkableWriter is an in-memory buffer that can be
-// 'forked' to create new forkableWriters that bracket the
-// original. After
-// pre, post := w.fork()
-// the overall sequence of bytes represented is logically w+pre+post.
-type forkableWriter struct {
- *bytes.Buffer
- pre, post *forkableWriter
+var (
+ byte00Encoder encoder = byteEncoder(0x00)
+ byteFFEncoder encoder = byteEncoder(0xff)
+)
+
+// encoder represents a ASN.1 element that is waiting to be marshaled.
+type encoder interface {
+ // Len returns the number of bytes needed to marshal this element.
+ Len() int
+ // Encode encodes this element by writing Len() bytes to dst.
+ Encode(dst []byte)
+}
+
+type byteEncoder byte
+
+func (c byteEncoder) Len() int {
+ return 1
}
-func newForkableWriter() *forkableWriter {
- return &forkableWriter{new(bytes.Buffer), nil, nil}
+func (c byteEncoder) Encode(dst []byte) {
+ dst[0] = byte(c)
}
-func (f *forkableWriter) fork() (pre, post *forkableWriter) {
- if f.pre != nil || f.post != nil {
- panic("have already forked")
+type bytesEncoder []byte
+
+func (b bytesEncoder) Len() int {
+ return len(b)
+}
+
+func (b bytesEncoder) Encode(dst []byte) {
+ if copy(dst, b) != len(b) {
+ panic("internal error")
}
- f.pre = newForkableWriter()
- f.post = newForkableWriter()
- return f.pre, f.post
}
-func (f *forkableWriter) Len() (l int) {
- l += f.Buffer.Len()
- if f.pre != nil {
- l += f.pre.Len()
+type stringEncoder string
+
+func (s stringEncoder) Len() int {
+ return len(s)
+}
+
+func (s stringEncoder) Encode(dst []byte) {
+ if copy(dst, s) != len(s) {
+ panic("internal error")
}
- if f.post != nil {
- l += f.post.Len()
+}
+
+type multiEncoder []encoder
+
+func (m multiEncoder) Len() int {
+ var size int
+ for _, e := range m {
+ size += e.Len()
}
- return
+ return size
}
-func (f *forkableWriter) writeTo(out io.Writer) (n int, err error) {
- n, err = out.Write(f.Bytes())
- if err != nil {
- return
+func (m multiEncoder) Encode(dst []byte) {
+ var off int
+ for _, e := range m {
+ e.Encode(dst[off:])
+ off += e.Len()
}
+}
- var nn int
+type taggedEncoder struct {
+ // scratch contains temporary space for encoding the tag and length of
+ // an element in order to avoid extra allocations.
+ scratch [8]byte
+ tag encoder
+ body encoder
+}
- if f.pre != nil {
- nn, err = f.pre.writeTo(out)
- n += nn
- if err != nil {
- return
- }
+func (t *taggedEncoder) Len() int {
+ return t.tag.Len() + t.body.Len()
+}
+
+func (t *taggedEncoder) Encode(dst []byte) {
+ t.tag.Encode(dst)
+ t.body.Encode(dst[t.tag.Len():])
+}
+
+type int64Encoder int64
+
+func (i int64Encoder) Len() int {
+ n := 1
+
+ for i > 127 {
+ n++
+ i >>= 8
}
- if f.post != nil {
- nn, err = f.post.writeTo(out)
- n += nn
+ for i < -128 {
+ n++
+ i >>= 8
}
- return
+
+ return n
}
-func marshalBase128Int(out *forkableWriter, n int64) (err error) {
+func (i int64Encoder) Encode(dst []byte) {
+ n := i.Len()
+
+ for j := 0; j < n; j++ {
+ dst[j] = byte(i >> uint((n-1-j)*8))
+ }
+}
+
+func base128IntLength(n int64) int {
if n == 0 {
- err = out.WriteByte(0)
- return
+ return 1
}
l := 0
@@ -83,54 +131,33 @@ func marshalBase128Int(out *forkableWriter, n int64) (err error) {
l++
}
+ return l
+}
+
+func appendBase128Int(dst []byte, n int64) []byte {
+ l := base128IntLength(n)
+
for i := l - 1; i >= 0; i-- {
o := byte(n >> uint(i*7))
o &= 0x7f
if i != 0 {
o |= 0x80
}
- err = out.WriteByte(o)
- if err != nil {
- return
- }
- }
-
- return nil
-}
-func marshalInt64(out *forkableWriter, i int64) (err error) {
- n := int64Length(i)
-
- for ; n > 0; n-- {
- err = out.WriteByte(byte(i >> uint((n-1)*8)))
- if err != nil {
- return
- }
+ dst = append(dst, o)
}
- return nil
+ return dst
}
-func int64Length(i int64) (numBytes int) {
- numBytes = 1
-
- for i > 127 {
- numBytes++
- i >>= 8
+func makeBigInt(n *big.Int) (encoder, error) {
+ if n == nil {
+ return nil, StructuralError{"empty integer"}
}
- for i < -128 {
- numBytes++
- i >>= 8
- }
-
- return
-}
-
-func marshalBigInt(out *forkableWriter, n *big.Int) (err error) {
if n.Sign() < 0 {
// A negative number has to be converted to two's-complement
- // form. So we'll subtract 1 and invert. If the
+ // form. So we'll invert and subtract 1. If the
// most-significant-bit isn't set then we'll need to pad the
// beginning with 0xff in order to keep the number negative.
nMinus1 := new(big.Int).Neg(n)
@@ -140,41 +167,31 @@ func marshalBigInt(out *forkableWriter, n *big.Int) (err error) {
bytes[i] ^= 0xff
}
if len(bytes) == 0 || bytes[0]&0x80 == 0 {
- err = out.WriteByte(0xff)
- if err != nil {
- return
- }
+ return multiEncoder([]encoder{byteFFEncoder, bytesEncoder(bytes)}), nil
}
- _, err = out.Write(bytes)
+ return bytesEncoder(bytes), nil
} else if n.Sign() == 0 {
// Zero is written as a single 0 zero rather than no bytes.
- err = out.WriteByte(0x00)
+ return byte00Encoder, nil
} else {
bytes := n.Bytes()
if len(bytes) > 0 && bytes[0]&0x80 != 0 {
// We'll have to pad this with 0x00 in order to stop it
// looking like a negative number.
- err = out.WriteByte(0)
- if err != nil {
- return
- }
+ return multiEncoder([]encoder{byte00Encoder, bytesEncoder(bytes)}), nil
}
- _, err = out.Write(bytes)
+ return bytesEncoder(bytes), nil
}
- return
}
-func marshalLength(out *forkableWriter, i int) (err error) {
+func appendLength(dst []byte, i int) []byte {
n := lengthLength(i)
for ; n > 0; n-- {
- err = out.WriteByte(byte(i >> uint((n-1)*8)))
- if err != nil {
- return
- }
+ dst = append(dst, byte(i>>uint((n-1)*8)))
}
- return nil
+ return dst
}
func lengthLength(i int) (numBytes int) {
@@ -186,123 +203,104 @@ func lengthLength(i int) (numBytes int) {
return
}
-func marshalTagAndLength(out *forkableWriter, t tagAndLength) (err error) {
+func appendTagAndLength(dst []byte, t tagAndLength) []byte {
b := uint8(t.class) << 6
if t.isCompound {
b |= 0x20
}
if t.tag >= 31 {
b |= 0x1f
- err = out.WriteByte(b)
- if err != nil {
- return
- }
- err = marshalBase128Int(out, int64(t.tag))
- if err != nil {
- return
- }
+ dst = append(dst, b)
+ dst = appendBase128Int(dst, int64(t.tag))
} else {
b |= uint8(t.tag)
- err = out.WriteByte(b)
- if err != nil {
- return
- }
+ dst = append(dst, b)
}
if t.length >= 128 {
l := lengthLength(t.length)
- err = out.WriteByte(0x80 | byte(l))
- if err != nil {
- return
- }
- err = marshalLength(out, t.length)
- if err != nil {
- return
- }
+ dst = append(dst, 0x80|byte(l))
+ dst = appendLength(dst, t.length)
} else {
- err = out.WriteByte(byte(t.length))
- if err != nil {
- return
- }
+ dst = append(dst, byte(t.length))
}
- return nil
+ return dst
}
-func marshalBitString(out *forkableWriter, b BitString) (err error) {
- paddingBits := byte((8 - b.BitLength%8) % 8)
- err = out.WriteByte(paddingBits)
- if err != nil {
- return
- }
- _, err = out.Write(b.Bytes)
- return
+type bitStringEncoder BitString
+
+func (b bitStringEncoder) Len() int {
+ return len(b.Bytes) + 1
}
-func marshalObjectIdentifier(out *forkableWriter, oid []int) (err error) {
- if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
- return StructuralError{"invalid object identifier"}
+func (b bitStringEncoder) Encode(dst []byte) {
+ dst[0] = byte((8 - b.BitLength%8) % 8)
+ if copy(dst[1:], b.Bytes) != len(b.Bytes) {
+ panic("internal error")
}
+}
- err = marshalBase128Int(out, int64(oid[0]*40+oid[1]))
- if err != nil {
- return
+type oidEncoder []int
+
+func (oid oidEncoder) Len() int {
+ l := base128IntLength(int64(oid[0]*40 + oid[1]))
+ for i := 2; i < len(oid); i++ {
+ l += base128IntLength(int64(oid[i]))
}
+ return l
+}
+
+func (oid oidEncoder) Encode(dst []byte) {
+ dst = appendBase128Int(dst[:0], int64(oid[0]*40+oid[1]))
for i := 2; i < len(oid); i++ {
- err = marshalBase128Int(out, int64(oid[i]))
- if err != nil {
- return
- }
+ dst = appendBase128Int(dst, int64(oid[i]))
}
+}
- return
+func makeObjectIdentifier(oid []int) (e encoder, err error) {
+ if len(oid) < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
+ return nil, StructuralError{"invalid object identifier"}
+ }
+
+ return oidEncoder(oid), nil
}
-func marshalPrintableString(out *forkableWriter, s string) (err error) {
- b := []byte(s)
- for _, c := range b {
- if !isPrintable(c) {
- return StructuralError{"PrintableString contains invalid character"}
+func makePrintableString(s string) (e encoder, err error) {
+ for i := 0; i < len(s); i++ {
+ if !isPrintable(s[i]) {
+ return nil, StructuralError{"PrintableString contains invalid character"}
}
}
- _, err = out.Write(b)
- return
+ return stringEncoder(s), nil
}
-func marshalIA5String(out *forkableWriter, s string) (err error) {
- b := []byte(s)
- for _, c := range b {
- if c > 127 {
- return StructuralError{"IA5String contains invalid character"}
+func makeIA5String(s string) (e encoder, err error) {
+ for i := 0; i < len(s); i++ {
+ if s[i] > 127 {
+ return nil, StructuralError{"IA5String contains invalid character"}
}
}
- _, err = out.Write(b)
- return
+ return stringEncoder(s), nil
}
-func marshalUTF8String(out *forkableWriter, s string) (err error) {
- _, err = out.Write([]byte(s))
- return
+func makeUTF8String(s string) encoder {
+ return stringEncoder(s)
}
-func marshalTwoDigits(out *forkableWriter, v int) (err error) {
- err = out.WriteByte(byte('0' + (v/10)%10))
- if err != nil {
- return
- }
- return out.WriteByte(byte('0' + v%10))
+func appendTwoDigits(dst []byte, v int) []byte {
+ return append(dst, byte('0'+(v/10)%10), byte('0'+v%10))
}
-func marshalFourDigits(out *forkableWriter, v int) (err error) {
+func appendFourDigits(dst []byte, v int) []byte {
var bytes [4]byte
for i := range bytes {
bytes[3-i] = '0' + byte(v%10)
v /= 10
}
- _, err = out.Write(bytes[:])
- return
+ return append(dst, bytes[:]...)
}
func outsideUTCRange(t time.Time) bool {
@@ -310,80 +308,75 @@ func outsideUTCRange(t time.Time) bool {
return year < 1950 || year >= 2050
}
-func marshalUTCTime(out *forkableWriter, t time.Time) (err error) {
+func makeUTCTime(t time.Time) (e encoder, err error) {
+ dst := make([]byte, 0, 18)
+
+ dst, err = appendUTCTime(dst, t)
+ if err != nil {
+ return nil, err
+ }
+
+ return bytesEncoder(dst), nil
+}
+
+func makeGeneralizedTime(t time.Time) (e encoder, err error) {
+ dst := make([]byte, 0, 20)
+
+ dst, err = appendGeneralizedTime(dst, t)
+ if err != nil {
+ return nil, err
+ }
+
+ return bytesEncoder(dst), nil
+}
+
+func appendUTCTime(dst []byte, t time.Time) (ret []byte, err error) {
year := t.Year()
switch {
case 1950 <= year && year < 2000:
- err = marshalTwoDigits(out, year-1900)
+ dst = appendTwoDigits(dst, year-1900)
case 2000 <= year && year < 2050:
- err = marshalTwoDigits(out, year-2000)
+ dst = appendTwoDigits(dst, year-2000)
default:
- return StructuralError{"cannot represent time as UTCTime"}
- }
- if err != nil {
- return
+ return nil, StructuralError{"cannot represent time as UTCTime"}
}
- return marshalTimeCommon(out, t)
+ return appendTimeCommon(dst, t), nil
}
-func marshalGeneralizedTime(out *forkableWriter, t time.Time) (err error) {
+func appendGeneralizedTime(dst []byte, t time.Time) (ret []byte, 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 nil, StructuralError{"cannot represent time as GeneralizedTime"}
}
- return marshalTimeCommon(out, t)
+ dst = appendFourDigits(dst, year)
+
+ return appendTimeCommon(dst, t), nil
}
-func marshalTimeCommon(out *forkableWriter, t time.Time) (err error) {
+func appendTimeCommon(dst []byte, t time.Time) []byte {
_, month, day := t.Date()
- err = marshalTwoDigits(out, int(month))
- if err != nil {
- return
- }
-
- err = marshalTwoDigits(out, day)
- if err != nil {
- return
- }
+ dst = appendTwoDigits(dst, int(month))
+ dst = appendTwoDigits(dst, day)
hour, min, sec := t.Clock()
- err = marshalTwoDigits(out, hour)
- if err != nil {
- return
- }
-
- err = marshalTwoDigits(out, min)
- if err != nil {
- return
- }
-
- err = marshalTwoDigits(out, sec)
- if err != nil {
- return
- }
+ dst = appendTwoDigits(dst, hour)
+ dst = appendTwoDigits(dst, min)
+ dst = appendTwoDigits(dst, sec)
_, offset := t.Zone()
switch {
case offset/60 == 0:
- err = out.WriteByte('Z')
- return
+ return append(dst, 'Z')
case offset > 0:
- err = out.WriteByte('+')
+ dst = append(dst, '+')
case offset < 0:
- err = out.WriteByte('-')
- }
-
- if err != nil {
- return
+ dst = append(dst, '-')
}
offsetMinutes := offset / 60
@@ -391,13 +384,10 @@ func marshalTimeCommon(out *forkableWriter, t time.Time) (err error) {
offsetMinutes = -offsetMinutes
}
- err = marshalTwoDigits(out, offsetMinutes/60)
- if err != nil {
- return
- }
+ dst = appendTwoDigits(dst, offsetMinutes/60)
+ dst = appendTwoDigits(dst, offsetMinutes%60)
- err = marshalTwoDigits(out, offsetMinutes%60)
- return
+ return dst
}
func stripTagAndLength(in []byte) []byte {
@@ -408,114 +398,130 @@ func stripTagAndLength(in []byte) []byte {
return in[offset:]
}
-func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameters) (err error) {
+func makeBody(value reflect.Value, params fieldParameters) (e encoder, err error) {
switch value.Type() {
case flagType:
- return nil
+ return bytesEncoder(nil), nil
case timeType:
t := value.Interface().(time.Time)
if params.timeType == TagGeneralizedTime || outsideUTCRange(t) {
- return marshalGeneralizedTime(out, t)
- } else {
- return marshalUTCTime(out, t)
+ return makeGeneralizedTime(t)
}
+ return makeUTCTime(t)
case bitStringType:
- return marshalBitString(out, value.Interface().(BitString))
+ return bitStringEncoder(value.Interface().(BitString)), nil
case objectIdentifierType:
- return marshalObjectIdentifier(out, value.Interface().(ObjectIdentifier))
+ return makeObjectIdentifier(value.Interface().(ObjectIdentifier))
case bigIntType:
- return marshalBigInt(out, value.Interface().(*big.Int))
+ return makeBigInt(value.Interface().(*big.Int))
}
switch v := value; v.Kind() {
case reflect.Bool:
if v.Bool() {
- return out.WriteByte(255)
- } else {
- return out.WriteByte(0)
+ return byteFFEncoder, nil
}
+ return byte00Encoder, nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return marshalInt64(out, v.Int())
+ return int64Encoder(v.Int()), nil
case reflect.Struct:
t := v.Type()
+ for i := 0; i < t.NumField(); i++ {
+ if t.Field(i).PkgPath != "" {
+ return nil, StructuralError{"struct contains unexported fields"}
+ }
+ }
+
startingField := 0
+ n := t.NumField()
+ if n == 0 {
+ return bytesEncoder(nil), nil
+ }
+
// If the first element of the structure is a non-empty
// RawContents, then we don't bother serializing the rest.
- if t.NumField() > 0 && t.Field(0).Type == rawContentsType {
+ if t.Field(0).Type == rawContentsType {
s := v.Field(0)
if s.Len() > 0 {
- bytes := make([]byte, s.Len())
- for i := 0; i < s.Len(); i++ {
- bytes[i] = uint8(s.Index(i).Uint())
- }
+ bytes := s.Bytes()
/* The RawContents will contain the tag and
* length fields but we'll also be writing
* those ourselves, so we strip them out of
* bytes */
- _, err = out.Write(stripTagAndLength(bytes))
- return
- } else {
- startingField = 1
+ return bytesEncoder(stripTagAndLength(bytes)), nil
}
+
+ startingField = 1
}
- for i := startingField; i < t.NumField(); i++ {
- var pre *forkableWriter
- pre, out = out.fork()
- err = marshalField(pre, v.Field(i), parseFieldParameters(t.Field(i).Tag.Get("asn1")))
- if err != nil {
- return
+ switch n1 := n - startingField; n1 {
+ case 0:
+ return bytesEncoder(nil), nil
+ case 1:
+ return makeField(v.Field(startingField), parseFieldParameters(t.Field(startingField).Tag.Get("asn1")))
+ default:
+ m := make([]encoder, n1)
+ for i := 0; i < n1; i++ {
+ m[i], err = makeField(v.Field(i+startingField), parseFieldParameters(t.Field(i+startingField).Tag.Get("asn1")))
+ if err != nil {
+ return nil, err
+ }
}
+
+ return multiEncoder(m), nil
}
- return
case reflect.Slice:
sliceType := v.Type()
if sliceType.Elem().Kind() == reflect.Uint8 {
- bytes := make([]byte, v.Len())
- for i := 0; i < v.Len(); i++ {
- bytes[i] = uint8(v.Index(i).Uint())
- }
- _, err = out.Write(bytes)
- return
+ return bytesEncoder(v.Bytes()), nil
}
var fp fieldParameters
- for i := 0; i < v.Len(); i++ {
- var pre *forkableWriter
- pre, out = out.fork()
- err = marshalField(pre, v.Index(i), fp)
- if err != nil {
- return
+
+ switch l := v.Len(); l {
+ case 0:
+ return bytesEncoder(nil), nil
+ case 1:
+ return makeField(v.Index(0), fp)
+ default:
+ m := make([]encoder, l)
+
+ for i := 0; i < l; i++ {
+ m[i], err = makeField(v.Index(i), fp)
+ if err != nil {
+ return nil, err
+ }
}
+
+ return multiEncoder(m), nil
}
- return
case reflect.String:
switch params.stringType {
case TagIA5String:
- return marshalIA5String(out, v.String())
+ return makeIA5String(v.String())
case TagPrintableString:
- return marshalPrintableString(out, v.String())
+ return makePrintableString(v.String())
default:
- return marshalUTF8String(out, v.String())
+ return makeUTF8String(v.String()), nil
}
}
- return StructuralError{"unknown Go type"}
+ return nil, StructuralError{"unknown Go type"}
}
-func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) {
+func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) {
if !v.IsValid() {
- return fmt.Errorf("asn1: cannot marshal nil value")
+ return nil, fmt.Errorf("asn1: cannot marshal nil value")
}
// If the field is an interface{} then recurse into it.
if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
- return marshalField(out, v.Elem(), params)
+ return makeField(v.Elem(), params)
}
if v.Kind() == reflect.Slice && v.Len() == 0 && params.omitEmpty {
- return
+ return bytesEncoder(nil), nil
}
if params.optional && params.defaultValue != nil && canHaveDefaultValue(v.Kind()) {
@@ -523,46 +529,45 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
defaultValue.SetInt(*params.defaultValue)
if reflect.DeepEqual(v.Interface(), defaultValue.Interface()) {
- return
+ return bytesEncoder(nil), nil
}
}
// 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.
+ // behavior, 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
+ return bytesEncoder(nil), nil
}
}
if v.Type() == rawValueType {
rv := v.Interface().(RawValue)
if len(rv.FullBytes) != 0 {
- _, err = out.Write(rv.FullBytes)
- } else {
- err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
- if err != nil {
- return
- }
- _, err = out.Write(rv.Bytes)
+ return bytesEncoder(rv.FullBytes), nil
}
- return
+
+ t := new(taggedEncoder)
+
+ t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound}))
+ t.body = bytesEncoder(rv.Bytes)
+
+ return t, nil
}
tag, isCompound, ok := getUniversalType(v.Type())
if !ok {
- err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
- return
+ return nil, StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
}
class := ClassUniversal
if params.timeType != 0 && tag != TagUTCTime {
- return StructuralError{"explicit time type given to non-time member"}
+ return nil, StructuralError{"explicit time type given to non-time member"}
}
if params.stringType != 0 && tag != TagPrintableString {
- return StructuralError{"explicit string type given to non-string member"}
+ return nil, StructuralError{"explicit string type given to non-string member"}
}
switch tag {
@@ -574,7 +579,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
for _, r := range v.String() {
if r >= utf8.RuneSelf || !isPrintable(byte(r)) {
if !utf8.ValidString(v.String()) {
- return errors.New("asn1: string not valid UTF-8")
+ return nil, errors.New("asn1: string not valid UTF-8")
}
tag = TagUTF8String
break
@@ -591,46 +596,46 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
if params.set {
if tag != TagSequence {
- return StructuralError{"non sequence tagged as set"}
+ return nil, StructuralError{"non sequence tagged as set"}
}
tag = TagSet
}
- tags, body := out.fork()
+ t := new(taggedEncoder)
- err = marshalBody(body, v, params)
+ t.body, err = makeBody(v, params)
if err != nil {
- return
+ return nil, err
}
- bodyLen := body.Len()
+ bodyLen := t.body.Len()
- var explicitTag *forkableWriter
if params.explicit {
- explicitTag, tags = tags.fork()
- }
+ t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound}))
- if !params.explicit && params.tag != nil {
- // implicit tag.
- tag = *params.tag
- class = ClassContextSpecific
- }
+ tt := new(taggedEncoder)
- err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
- if err != nil {
- return
- }
+ tt.body = t
- if params.explicit {
- err = marshalTagAndLength(explicitTag, tagAndLength{
+ tt.tag = bytesEncoder(appendTagAndLength(tt.scratch[:0], tagAndLength{
class: ClassContextSpecific,
tag: *params.tag,
- length: bodyLen + tags.Len(),
+ length: bodyLen + t.tag.Len(),
isCompound: true,
- })
+ }))
+
+ return tt, nil
+ }
+
+ if params.tag != nil {
+ // implicit tag.
+ tag = *params.tag
+ class = ClassContextSpecific
}
- return err
+ t.tag = bytesEncoder(appendTagAndLength(t.scratch[:0], tagAndLength{class, tag, bodyLen, isCompound}))
+
+ return t, nil
}
// Marshal returns the ASN.1 encoding of val.
@@ -643,13 +648,11 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
// 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)
- f := newForkableWriter()
- err := marshalField(f, v, fieldParameters{})
+ e, err := makeField(reflect.ValueOf(val), fieldParameters{})
if err != nil {
return nil, err
}
- _, err = f.writeTo(&out)
- return out.Bytes(), err
+ b := make([]byte, e.Len())
+ e.Encode(b)
+ return b, nil
}
diff --git a/libgo/go/encoding/asn1/marshal_test.go b/libgo/go/encoding/asn1/marshal_test.go
index cdca8aa3363..10db1aa575a 100644
--- a/libgo/go/encoding/asn1/marshal_test.go
+++ b/libgo/go/encoding/asn1/marshal_test.go
@@ -8,6 +8,7 @@ import (
"bytes"
"encoding/hex"
"math/big"
+ "strings"
"testing"
"time"
)
@@ -167,9 +168,42 @@ func TestMarshal(t *testing.T) {
}
}
+type marshalErrTest struct {
+ in interface{}
+ err string
+}
+
+var marshalErrTests = []marshalErrTest{
+ {bigIntStruct{nil}, "empty integer"},
+}
+
+func TestMarshalError(t *testing.T) {
+ for i, test := range marshalErrTests {
+ _, err := Marshal(test.in)
+ if err == nil {
+ t.Errorf("#%d should fail, but success", i)
+ continue
+ }
+
+ if !strings.Contains(err.Error(), test.err) {
+ t.Errorf("#%d got: %v want %v", i, err, test.err)
+ }
+ }
+}
+
func TestInvalidUTF8(t *testing.T) {
_, err := Marshal(string([]byte{0xff, 0xff}))
if err == nil {
t.Errorf("invalid UTF8 string was accepted")
}
}
+
+func BenchmarkMarshal(b *testing.B) {
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ for _, test := range marshalTests {
+ Marshal(test.in)
+ }
+ }
+}
diff --git a/libgo/go/encoding/base64/base64.go b/libgo/go/encoding/base64/base64.go
index c2116d8a343..d2efad4518b 100644
--- a/libgo/go/encoding/base64/base64.go
+++ b/libgo/go/encoding/base64/base64.go
@@ -23,6 +23,7 @@ type Encoding struct {
encode [64]byte
decodeMap [256]byte
padChar rune
+ strict bool
}
const (
@@ -62,6 +63,14 @@ func (enc Encoding) WithPadding(padding rune) *Encoding {
return &enc
}
+// Strict creates a new encoding identical to enc except with
+// strict decoding enabled. In this mode, the decoder requires that
+// trailing padding bits are zero, as described in RFC 4648 section 3.5.
+func (enc Encoding) Strict() *Encoding {
+ enc.strict = true
+ return &enc
+}
+
// StdEncoding is the standard base64 encoding, as defined in
// RFC 4648.
var StdEncoding = NewEncoding(encodeStd)
@@ -311,15 +320,24 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
// Convert 4x 6bit source bytes into 3 bytes
val := uint(dbuf[0])<<18 | uint(dbuf[1])<<12 | uint(dbuf[2])<<6 | uint(dbuf[3])
+ dbuf[2], dbuf[1], dbuf[0] = byte(val>>0), byte(val>>8), byte(val>>16)
switch dlen {
case 4:
- dst[2] = byte(val >> 0)
+ dst[2] = dbuf[2]
+ dbuf[2] = 0
fallthrough
case 3:
- dst[1] = byte(val >> 8)
+ dst[1] = dbuf[1]
+ if enc.strict && dbuf[2] != 0 {
+ return n, end, CorruptInputError(si - 1)
+ }
+ dbuf[1] = 0
fallthrough
case 2:
- dst[0] = byte(val >> 16)
+ dst[0] = dbuf[0]
+ if enc.strict && (dbuf[1] != 0 || dbuf[2] != 0) {
+ return n, end, CorruptInputError(si - 2)
+ }
}
dst = dst[dinc:]
n += dlen - 1
diff --git a/libgo/go/encoding/base64/base64_test.go b/libgo/go/encoding/base64/base64_test.go
index 19ddb92f644..e2e1d59f3c0 100644
--- a/libgo/go/encoding/base64/base64_test.go
+++ b/libgo/go/encoding/base64/base64_test.go
@@ -85,6 +85,11 @@ var encodingTests = []encodingTest{
{RawStdEncoding, rawRef},
{RawURLEncoding, rawUrlRef},
{funnyEncoding, funnyRef},
+ {StdEncoding.Strict(), stdRef},
+ {URLEncoding.Strict(), urlRef},
+ {RawStdEncoding.Strict(), rawRef},
+ {RawURLEncoding.Strict(), rawUrlRef},
+ {funnyEncoding.Strict(), funnyRef},
}
var bigtest = testpair{
@@ -436,6 +441,22 @@ func TestDecoderIssue7733(t *testing.T) {
}
}
+func TestDecoderIssue15656(t *testing.T) {
+ _, err := StdEncoding.Strict().DecodeString("WvLTlMrX9NpYDQlEIFlnDB==")
+ want := CorruptInputError(22)
+ if !reflect.DeepEqual(want, err) {
+ t.Errorf("Error = %v; want CorruptInputError(22)", err)
+ }
+ _, err = StdEncoding.Strict().DecodeString("WvLTlMrX9NpYDQlEIFlnDA==")
+ if err != nil {
+ t.Errorf("Error = %v; want nil", err)
+ }
+ _, err = StdEncoding.DecodeString("WvLTlMrX9NpYDQlEIFlnDB==")
+ if err != nil {
+ t.Errorf("Error = %v; want nil", err)
+ }
+}
+
func BenchmarkEncodeToString(b *testing.B) {
data := make([]byte, 8192)
b.SetBytes(int64(len(data)))
diff --git a/libgo/go/encoding/binary/binary.go b/libgo/go/encoding/binary/binary.go
index 46c6add062a..38342545966 100644
--- a/libgo/go/encoding/binary/binary.go
+++ b/libgo/go/encoding/binary/binary.go
@@ -7,7 +7,7 @@
//
// Numbers are translated by reading and writing fixed-size values.
// A fixed-size value is either a fixed-size arithmetic
-// type (int8, uint8, int16, float32, complex64, ...)
+// type (bool, int8, uint8, int16, float32, complex64, ...)
// or an array or struct containing only fixed-size values.
//
// The varint functions encode and decode single integer values using
@@ -147,6 +147,8 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
// of fixed-size values.
// Bytes read from r are decoded using the specified byte order
// and written to successive fields of the data.
+// When decoding boolean values, a zero byte is decoded as false, and
+// any other non-zero byte is decoded as true.
// 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.
@@ -169,6 +171,8 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
return err
}
switch data := data.(type) {
+ case *bool:
+ *data = b[0] != 0
case *int8:
*data = int8(b[0])
case *uint8:
@@ -185,8 +189,12 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
*data = int64(order.Uint64(bs))
case *uint64:
*data = order.Uint64(bs)
- case []int8:
+ case []bool:
for i, x := range bs { // Easier to loop over the input for 8-bit values.
+ data[i] = x != 0
+ }
+ case []int8:
+ for i, x := range bs {
data[i] = int8(x)
}
case []uint8:
@@ -243,6 +251,7 @@ func Read(r io.Reader, order ByteOrder, data interface{}) error {
// Write writes the binary representation of data into w.
// Data must be a fixed-size value or a slice of fixed-size
// values, or a pointer to such data.
+// Boolean values encode as one byte: 1 for true, and 0 for false.
// Bytes written to w are encoded using the specified byte order
// and read from successive fields of the data.
// When writing structs, zero values are written for fields
@@ -258,6 +267,26 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error {
bs = b[:n]
}
switch v := data.(type) {
+ case *bool:
+ if *v {
+ b[0] = 1
+ } else {
+ b[0] = 0
+ }
+ case bool:
+ if v {
+ b[0] = 1
+ } else {
+ b[0] = 0
+ }
+ case []bool:
+ for i, x := range v {
+ if x {
+ bs[i] = 1
+ } else {
+ bs[i] = 0
+ }
+ }
case *int8:
b[0] = byte(*v)
case int8:
@@ -378,7 +407,8 @@ func sizeof(t reflect.Type) int {
}
return sum
- case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+ case reflect.Bool,
+ 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())
@@ -395,6 +425,21 @@ type coder struct {
type decoder coder
type encoder coder
+func (d *decoder) bool() bool {
+ x := d.buf[0]
+ d.buf = d.buf[1:]
+ return x != 0
+}
+
+func (e *encoder) bool(x bool) {
+ if x {
+ e.buf[0] = 1
+ } else {
+ e.buf[0] = 0
+ }
+ e.buf = e.buf[1:]
+}
+
func (d *decoder) uint8() uint8 {
x := d.buf[0]
d.buf = d.buf[1:]
@@ -485,6 +530,9 @@ func (d *decoder) value(v reflect.Value) {
d.value(v.Index(i))
}
+ case reflect.Bool:
+ v.SetBool(d.bool())
+
case reflect.Int8:
v.SetInt(int64(d.int8()))
case reflect.Int16:
@@ -547,6 +595,9 @@ func (e *encoder) value(v reflect.Value) {
e.value(v.Index(i))
}
+ case reflect.Bool:
+ e.bool(v.Bool())
+
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
switch v.Type().Kind() {
case reflect.Int8:
@@ -609,7 +660,7 @@ func (e *encoder) skip(v reflect.Value) {
// It returns zero if the type cannot be implemented by the fast path in Read or Write.
func intDataSize(data interface{}) int {
switch data := data.(type) {
- case int8, uint8, *int8, *uint8:
+ case bool, int8, uint8, *bool, *int8, *uint8:
return 1
case []int8:
return len(data)
diff --git a/libgo/go/encoding/binary/binary_test.go b/libgo/go/encoding/binary/binary_test.go
index c0728e943e8..fc7f2765efb 100644
--- a/libgo/go/encoding/binary/binary_test.go
+++ b/libgo/go/encoding/binary/binary_test.go
@@ -27,6 +27,8 @@ type Struct struct {
Complex64 complex64
Complex128 complex128
Array [4]uint8
+ Bool bool
+ BoolArray [4]bool
}
type T struct {
@@ -58,6 +60,9 @@ var s = Struct{
),
[4]uint8{0x43, 0x44, 0x45, 0x46},
+
+ true,
+ [4]bool{true, false, true, false},
}
var big = []byte{
@@ -76,6 +81,9 @@ var big = []byte{
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
67, 68, 69, 70,
+
+ 1,
+ 1, 0, 1, 0,
}
var little = []byte{
@@ -94,6 +102,9 @@ var little = []byte{
58, 57, 56, 55, 54, 53, 52, 51, 66, 65, 64, 63, 62, 61, 60, 59,
67, 68, 69, 70,
+
+ 1,
+ 1, 0, 1, 0,
}
var src = []byte{1, 2, 3, 4, 5, 6, 7, 8}
@@ -141,6 +152,25 @@ func TestWriteSlice(t *testing.T) {
checkResult(t, "WriteSlice", BigEndian, err, buf.Bytes(), src)
}
+func TestReadBool(t *testing.T) {
+ var res bool
+ var err error
+ err = Read(bytes.NewReader([]byte{0}), BigEndian, &res)
+ checkResult(t, "ReadBool", BigEndian, err, res, false)
+ res = false
+ err = Read(bytes.NewReader([]byte{1}), BigEndian, &res)
+ checkResult(t, "ReadBool", BigEndian, err, res, true)
+ res = false
+ err = Read(bytes.NewReader([]byte{2}), BigEndian, &res)
+ checkResult(t, "ReadBool", BigEndian, err, res, true)
+}
+
+func TestReadBoolSlice(t *testing.T) {
+ slice := make([]bool, 4)
+ err := Read(bytes.NewReader([]byte{0, 1, 2, 255}), BigEndian, slice)
+ checkResult(t, "ReadBoolSlice", BigEndian, err, slice, []bool{false, true, true, true})
+}
+
// Addresses of arrays are easier to manipulate with reflection than are slices.
var intArrays = []interface{}{
&[100]int8{},
@@ -422,16 +452,15 @@ func BenchmarkReadInts(b *testing.B) {
Read(r, BigEndian, &ls.Uint32)
Read(r, BigEndian, &ls.Uint64)
}
-
+ b.StopTimer()
want := s
want.Float32 = 0
want.Float64 = 0
want.Complex64 = 0
want.Complex128 = 0
- for i := range want.Array {
- want.Array[i] = 0
- }
- b.StopTimer()
+ want.Array = [4]uint8{0, 0, 0, 0}
+ want.Bool = false
+ want.BoolArray = [4]bool{false, false, false, false}
if b.N > 0 && !reflect.DeepEqual(ls, want) {
b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want)
}
diff --git a/libgo/go/encoding/csv/reader.go b/libgo/go/encoding/csv/reader.go
index a5e03a9f8ef..c8c4ca77583 100644
--- a/libgo/go/encoding/csv/reader.go
+++ b/libgo/go/encoding/csv/reader.go
@@ -114,7 +114,14 @@ type Reader struct {
line int
column int
r *bufio.Reader
- field bytes.Buffer
+ // lineBuffer holds the unescaped fields read by readField, one after another.
+ // The fields can be accessed by using the indexes in fieldIndexes.
+ // Example: for the row `a,"b","c""d",e` lineBuffer will contain `abc"de` and
+ // fieldIndexes will contain the indexes 0, 1, 2, 5.
+ lineBuffer bytes.Buffer
+ // Indexes of fields inside lineBuffer
+ // The i'th field starts at offset fieldIndexes[i] in lineBuffer.
+ fieldIndexes []int
}
// NewReader returns a new Reader that reads from r.
@@ -134,8 +141,12 @@ func (r *Reader) error(err error) error {
}
}
-// Read reads one record from r. The record is a slice of strings with each
-// string representing one field.
+// Read reads one record (a slice of fields) from r.
+// If the record has an unexpected number of fields,
+// Read returns the record along with the error ErrFieldCount.
+// Except for that case, Read always returns either a non-nil
+// record or a non-nil error, but not both.
+// If there is no data left to be read, Read returns nil, io.EOF.
func (r *Reader) Read() (record []string, err error) {
for {
record, err = r.parseRecord()
@@ -233,31 +244,54 @@ func (r *Reader) parseRecord() (fields []string, err error) {
}
r.r.UnreadRune()
+ r.lineBuffer.Reset()
+ r.fieldIndexes = r.fieldIndexes[:0]
+
// At this point we have at least one field.
for {
+ idx := r.lineBuffer.Len()
+
haveField, delim, err := r.parseField()
if haveField {
- // If FieldsPerRecord is greater than 0 we can assume the final
- // length of fields to be equal to FieldsPerRecord.
- if r.FieldsPerRecord > 0 && fields == nil {
- fields = make([]string, 0, r.FieldsPerRecord)
- }
- fields = append(fields, r.field.String())
+ r.fieldIndexes = append(r.fieldIndexes, idx)
}
+
if delim == '\n' || err == io.EOF {
- return fields, err
- } else if err != nil {
+ if len(r.fieldIndexes) == 0 {
+ return nil, err
+ }
+ break
+ }
+
+ if err != nil {
return nil, err
}
}
+
+ fieldCount := len(r.fieldIndexes)
+ // Using this approach (creating a single string and taking slices of it)
+ // means that a single reference to any of the fields will retain the whole
+ // string. The risk of a nontrivial space leak caused by this is considered
+ // minimal and a tradeoff for better performance through the combined
+ // allocations.
+ line := r.lineBuffer.String()
+ fields = make([]string, fieldCount)
+
+ for i, idx := range r.fieldIndexes {
+ if i == fieldCount-1 {
+ fields[i] = line[idx:]
+ } else {
+ fields[i] = line[idx:r.fieldIndexes[i+1]]
+ }
+ }
+
+ return fields, nil
}
// parseField parses the next field in the record. The read field is
-// located in r.field. Delim is the first character not part of the field
+// appended to r.lineBuffer. Delim is the first character not part of the field
// (r.Comma or '\n').
func (r *Reader) parseField() (haveField bool, delim rune, err error) {
- r.field.Reset()
-
r1, err := r.readRune()
for err == nil && r.TrimLeadingSpace && r1 != '\n' && unicode.IsSpace(r1) {
r1, err = r.readRune()
@@ -310,19 +344,19 @@ func (r *Reader) parseField() (haveField bool, delim rune, err error) {
return false, 0, r.error(ErrQuote)
}
// accept the bare quote
- r.field.WriteRune('"')
+ r.lineBuffer.WriteRune('"')
}
case '\n':
r.line++
r.column = -1
}
- r.field.WriteRune(r1)
+ r.lineBuffer.WriteRune(r1)
}
default:
// unquoted field
for {
- r.field.WriteRune(r1)
+ r.lineBuffer.WriteRune(r1)
r1, err = r.readRune()
if err != nil || r1 == r.Comma {
break
diff --git a/libgo/go/encoding/csv/reader_test.go b/libgo/go/encoding/csv/reader_test.go
index be1002d034a..7b3aca4c5f3 100644
--- a/libgo/go/encoding/csv/reader_test.go
+++ b/libgo/go/encoding/csv/reader_test.go
@@ -5,6 +5,7 @@
package csv
import (
+ "io"
"reflect"
"strings"
"testing"
@@ -292,8 +293,52 @@ func TestRead(t *testing.T) {
}
}
-func BenchmarkRead(b *testing.B) {
- data := `x,y,z,w
+// nTimes is an io.Reader which yields the string s n times.
+type nTimes struct {
+ s string
+ n int
+ off int
+}
+
+func (r *nTimes) Read(p []byte) (n int, err error) {
+ for {
+ if r.n <= 0 || r.s == "" {
+ return n, io.EOF
+ }
+ n0 := copy(p, r.s[r.off:])
+ p = p[n0:]
+ n += n0
+ r.off += n0
+ if r.off == len(r.s) {
+ r.off = 0
+ r.n--
+ }
+ if len(p) == 0 {
+ return
+ }
+ }
+}
+
+// benchmarkRead measures reading the provided CSV rows data.
+// initReader, if non-nil, modifies the Reader before it's used.
+func benchmarkRead(b *testing.B, initReader func(*Reader), rows string) {
+ b.ReportAllocs()
+ r := NewReader(&nTimes{s: rows, n: b.N})
+ if initReader != nil {
+ initReader(r)
+ }
+ for {
+ _, err := r.Read()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
+
+const benchmarkCSVData = `x,y,z,w
x,y,z,
x,y,,
x,,,
@@ -305,11 +350,22 @@ x,,,
"","","",""
`
- for i := 0; i < b.N; i++ {
- _, err := NewReader(strings.NewReader(data)).ReadAll()
+func BenchmarkRead(b *testing.B) {
+ benchmarkRead(b, nil, benchmarkCSVData)
+}
- if err != nil {
- b.Fatalf("could not read data: %s", err)
- }
- }
+func BenchmarkReadWithFieldsPerRecord(b *testing.B) {
+ benchmarkRead(b, func(r *Reader) { r.FieldsPerRecord = 4 }, benchmarkCSVData)
+}
+
+func BenchmarkReadWithoutFieldsPerRecord(b *testing.B) {
+ benchmarkRead(b, func(r *Reader) { r.FieldsPerRecord = -1 }, benchmarkCSVData)
+}
+
+func BenchmarkReadLargeFields(b *testing.B) {
+ benchmarkRead(b, nil, strings.Repeat(`xxxxxxxxxxxxxxxx,yyyyyyyyyyyyyyyy,zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz,wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww,vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+xxxxxxxxxxxxxxxxxxxxxxxx,yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz,wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww,vvvv
+,,zzzz,wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww,vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz,wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww,vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+`, 3))
}
diff --git a/libgo/go/encoding/gob/encoder.go b/libgo/go/encoding/gob/encoder.go
index d6c8fdd9630..40ec81b6e69 100644
--- a/libgo/go/encoding/gob/encoder.go
+++ b/libgo/go/encoding/gob/encoder.go
@@ -215,6 +215,9 @@ func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) {
// guaranteeing that all necessary type information has been transmitted first.
// Passing a nil pointer to EncodeValue will panic, as they cannot be transmitted by gob.
func (enc *Encoder) EncodeValue(value reflect.Value) error {
+ if value.Kind() == reflect.Invalid {
+ return errors.New("gob: cannot encode nil value")
+ }
if value.Kind() == reflect.Ptr && value.IsNil() {
panic("gob: cannot encode nil pointer of type " + value.Type().String())
}
diff --git a/libgo/go/encoding/gob/encoder_test.go b/libgo/go/encoding/gob/encoder_test.go
index 22090a18a6f..9256848b50e 100644
--- a/libgo/go/encoding/gob/encoder_test.go
+++ b/libgo/go/encoding/gob/encoder_test.go
@@ -830,6 +830,20 @@ func TestPtrToMapOfMap(t *testing.T) {
}
}
+// Test that untyped nils generate an error, not a panic.
+// See Issue 16204.
+func TestCatchInvalidNilValue(t *testing.T) {
+ encodeErr, panicErr := encodeAndRecover(nil)
+ if panicErr != nil {
+ t.Fatalf("panicErr=%v, should not panic encoding untyped nil", panicErr)
+ }
+ if encodeErr == nil {
+ t.Errorf("got err=nil, want non-nil error when encoding untyped nil value")
+ } else if !strings.Contains(encodeErr.Error(), "nil value") {
+ t.Errorf("expected 'nil value' error; got err=%v", encodeErr)
+ }
+}
+
// A top-level nil pointer generates a panic with a helpful string-valued message.
func TestTopLevelNilPointer(t *testing.T) {
var ip *int
diff --git a/libgo/go/encoding/hex/example_test.go b/libgo/go/encoding/hex/example_test.go
new file mode 100644
index 00000000000..fb1554eba7e
--- /dev/null
+++ b/libgo/go/encoding/hex/example_test.go
@@ -0,0 +1,100 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package hex_test
+
+import (
+ "encoding/hex"
+ "fmt"
+ "log"
+ "os"
+)
+
+func ExampleEncode() {
+ src := []byte("Hello Gopher!")
+
+ dst := make([]byte, hex.EncodedLen(len(src)))
+ hex.Encode(dst, src)
+
+ fmt.Printf("%s\n", dst)
+
+ // Output:
+ // 48656c6c6f20476f7068657221
+}
+
+func ExampleDecode() {
+ src := []byte("48656c6c6f20476f7068657221")
+
+ dst := make([]byte, hex.DecodedLen(len(src)))
+ n, err := hex.Decode(dst, src)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Printf("%s\n", dst[:n])
+
+ // Output:
+ // Hello Gopher!
+}
+
+func ExampleDecodeString() {
+ const s = "48656c6c6f20476f7068657221"
+ decoded, err := hex.DecodeString(s)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Printf("%s\n", decoded)
+
+ // Output:
+ // Hello Gopher!
+}
+
+func ExampleDump() {
+ content := []byte("Go is an open source programming language.")
+
+ fmt.Printf("%s", hex.Dump(content))
+
+ // Output:
+ // 00000000 47 6f 20 69 73 20 61 6e 20 6f 70 65 6e 20 73 6f |Go is an open so|
+ // 00000010 75 72 63 65 20 70 72 6f 67 72 61 6d 6d 69 6e 67 |urce programming|
+ // 00000020 20 6c 61 6e 67 75 61 67 65 2e | language.|
+}
+
+func ExampleDumper() {
+ lines := []string{
+ "Go is an open source programming language.",
+ "\n",
+ "We encourage all Go users to subscribe to golang-announce.",
+ }
+
+ stdoutDumper := hex.Dumper(os.Stdout)
+
+ defer stdoutDumper.Close()
+
+ for _, line := range lines {
+ stdoutDumper.Write([]byte(line))
+ }
+
+ // Output:
+ // 00000000 47 6f 20 69 73 20 61 6e 20 6f 70 65 6e 20 73 6f |Go is an open so|
+ // 00000010 75 72 63 65 20 70 72 6f 67 72 61 6d 6d 69 6e 67 |urce programming|
+ // 00000020 20 6c 61 6e 67 75 61 67 65 2e 0a 57 65 20 65 6e | language..We en|
+ // 00000030 63 6f 75 72 61 67 65 20 61 6c 6c 20 47 6f 20 75 |courage all Go u|
+ // 00000040 73 65 72 73 20 74 6f 20 73 75 62 73 63 72 69 62 |sers to subscrib|
+ // 00000050 65 20 74 6f 20 67 6f 6c 61 6e 67 2d 61 6e 6e 6f |e to golang-anno|
+ // 00000060 75 6e 63 65 2e |unce.|
+}
+
+func ExampleEncodeToString() {
+ src := []byte("Hello")
+ encodedStr := hex.EncodeToString(src)
+
+ fmt.Printf("%s\n", encodedStr)
+
+ // Output:
+ // 48656c6c6f
+}
diff --git a/libgo/go/encoding/hex/hex.go b/libgo/go/encoding/hex/hex.go
index 73a25034be1..b43c1c4b456 100644
--- a/libgo/go/encoding/hex/hex.go
+++ b/libgo/go/encoding/hex/hex.go
@@ -12,9 +12,13 @@ import (
"io"
)
-const hextable = "0123456789abcdef"
+var hextable = [16]byte{
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'a', 'b', 'c', 'd', 'e', 'f',
+}
// EncodedLen returns the length of an encoding of n source bytes.
+// Specifically, it returns n * 2.
func EncodedLen(n int) int { return n * 2 }
// Encode encodes src into EncodedLen(len(src))
@@ -40,12 +44,15 @@ func (e InvalidByteError) Error() string {
return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e))
}
+// DecodedLen returns the length of a decoding of x source bytes.
+// Specifically, it returns x / 2.
func DecodedLen(x int) int { return x / 2 }
-// Decode decodes src into DecodedLen(len(src)) bytes, returning the actual
-// number of bytes written to dst.
+// Decode decodes src into DecodedLen(len(src)) bytes,
+// returning the actual number of bytes written to dst.
//
-// If Decode encounters invalid input, it returns an error describing the failure.
+// Decode expects that src contain only hexadecimal
+// characters and that src should have an even length.
func Decode(dst, src []byte) (int, error) {
if len(src)%2 == 1 {
return 0, ErrLength
diff --git a/libgo/go/encoding/hex/hex_test.go b/libgo/go/encoding/hex/hex_test.go
index b969636cd5e..64dabbd10a2 100644
--- a/libgo/go/encoding/hex/hex_test.go
+++ b/libgo/go/encoding/hex/hex_test.go
@@ -6,6 +6,7 @@ package hex
import (
"bytes"
+ "fmt"
"testing"
)
@@ -151,3 +152,18 @@ var expectedHexDump = []byte(`00000000 1e 1f 20 21 22 23 24 25 26 27 28 29 2a
00000010 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d |./0123456789:;<=|
00000020 3e 3f 40 41 42 43 44 45 |>?@ABCDE|
`)
+
+var sink []byte
+
+func BenchmarkEncode(b *testing.B) {
+ for _, size := range []int{256, 1024, 4096, 16384} {
+ src := bytes.Repeat([]byte{2, 3, 5, 7, 9, 11, 13, 17}, size/8)
+ sink = make([]byte, 2*size)
+
+ b.Run(fmt.Sprintf("%v", size), func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Encode(sink, src)
+ }
+ })
+ }
+}
diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go
index 2eda875bfde..77fc4607dba 100644
--- a/libgo/go/encoding/json/decode.go
+++ b/libgo/go/encoding/json/decode.go
@@ -34,6 +34,13 @@ import (
// the value pointed at by the pointer. If the pointer is nil, Unmarshal
// allocates a new value for it to point to.
//
+// To unmarshal JSON into a value implementing the Unmarshaler interface,
+// Unmarshal calls that value's UnmarshalJSON method, including
+// when the input is a JSON null.
+// Otherwise, if the value implements encoding.TextUnmarshaler
+// and the input is a JSON quoted string, Unmarshal calls that value's
+// UnmarshalText method with the unquoted form of the string.
+//
// To unmarshal JSON into a struct, Unmarshal matches incoming object
// keys to the keys used by Marshal (either the struct field name or its tag),
// preferring an exact match but also accepting a case-insensitive match.
@@ -63,8 +70,8 @@ import (
//
// To unmarshal a JSON object into a map, Unmarshal first establishes a map to
// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal
-// reuses the existing map, keeping existing entries. Unmarshal then stores key-
-// value pairs from the JSON object into the map. The map's key type must
+// reuses the existing map, keeping existing entries. Unmarshal then stores
+// key-value pairs from the JSON object into the map. The map's key type must
// either be a string, an integer, or implement encoding.TextUnmarshaler.
//
// If a JSON value is not appropriate for a given target type,
@@ -102,6 +109,9 @@ func Unmarshal(data []byte, v interface{}) error {
// The input can be assumed to be a valid encoding of
// a JSON value. UnmarshalJSON must copy the JSON data
// if it wishes to retain the data after returning.
+//
+// By convention, to approximate the behavior of Unmarshal itself,
+// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op.
type Unmarshaler interface {
UnmarshalJSON([]byte) error
}
@@ -112,9 +122,14 @@ type UnmarshalTypeError struct {
Value string // description of JSON value - "bool", "array", "number -5"
Type reflect.Type // type of Go value it could not be assigned to
Offset int64 // error occurred after reading Offset bytes
+ Struct string // name of the struct type containing the field
+ Field string // name of the field holding the Go value
}
func (e *UnmarshalTypeError) Error() string {
+ if e.Struct != "" || e.Field != "" {
+ return "json: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String()
+ }
return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
}
@@ -248,10 +263,14 @@ func isValidNumber(s string) bool {
// decodeState represents the state while decoding a JSON value.
type decodeState struct {
- data []byte
- off int // read offset in data
- scan scanner
- nextscan scanner // for calls to nextValue
+ data []byte
+ off int // read offset in data
+ scan scanner
+ nextscan scanner // for calls to nextValue
+ errorContext struct { // provides context for type errors
+ Struct string
+ Field string
+ }
savedError error
useNumber bool
}
@@ -265,22 +284,37 @@ func (d *decodeState) init(data []byte) *decodeState {
d.data = data
d.off = 0
d.savedError = nil
+ d.errorContext.Struct = ""
+ d.errorContext.Field = ""
return d
}
// error aborts the decoding by panicking with err.
func (d *decodeState) error(err error) {
- panic(err)
+ panic(d.addErrorContext(err))
}
// saveError saves the first err it is called with,
// for reporting at the end of the unmarshal.
func (d *decodeState) saveError(err error) {
if d.savedError == nil {
- d.savedError = err
+ d.savedError = d.addErrorContext(err)
}
}
+// addErrorContext returns a new error enhanced with information from d.errorContext
+func (d *decodeState) addErrorContext(err error) error {
+ if d.errorContext.Struct != "" || d.errorContext.Field != "" {
+ switch err := err.(type) {
+ case *UnmarshalTypeError:
+ err.Struct = d.errorContext.Struct
+ err.Field = d.errorContext.Field
+ return err
+ }
+ }
+ return err
+}
+
// next cuts off and returns the next full JSON value in d.data[d.off:].
// The next value is known to be an object or array, not a literal.
func (d *decodeState) next() []byte {
@@ -434,8 +468,10 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler,
if u, ok := v.Interface().(Unmarshaler); ok {
return u, nil, reflect.Value{}
}
- if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
- return nil, u, reflect.Value{}
+ if !decodingNull {
+ if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
+ return nil, u, reflect.Value{}
+ }
}
}
v = v.Elem()
@@ -457,7 +493,7 @@ func (d *decodeState) array(v reflect.Value) {
return
}
if ut != nil {
- d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
d.off--
d.next()
return
@@ -476,7 +512,7 @@ func (d *decodeState) array(v reflect.Value) {
// Otherwise it's invalid.
fallthrough
default:
- d.saveError(&UnmarshalTypeError{"array", v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
d.off--
d.next()
return
@@ -566,7 +602,7 @@ func (d *decodeState) object(v reflect.Value) {
return
}
if ut != nil {
- d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)})
d.off--
d.next() // skip over { } in input
return
@@ -594,7 +630,7 @@ func (d *decodeState) object(v reflect.Value) {
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
default:
if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) {
- d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)})
d.off--
d.next() // skip over { } in input
return
@@ -604,9 +640,9 @@ func (d *decodeState) object(v reflect.Value) {
v.Set(reflect.MakeMap(t))
}
case reflect.Struct:
-
+ // ok
default:
- d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)})
d.off--
d.next() // skip over { } in input
return
@@ -671,6 +707,8 @@ func (d *decodeState) object(v reflect.Value) {
}
subv = subv.Field(i)
}
+ d.errorContext.Field = f.name
+ d.errorContext.Struct = v.Type().Name()
}
}
@@ -682,7 +720,6 @@ func (d *decodeState) object(v reflect.Value) {
d.error(errPhase)
}
- // Read value.
if destring {
switch qv := d.valueQuoted().(type) {
case nil:
@@ -714,7 +751,7 @@ func (d *decodeState) object(v reflect.Value) {
s := string(key)
n, err := strconv.ParseInt(s, 10, 64)
if err != nil || reflect.Zero(kt).OverflowInt(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, kt, int64(start + 1)})
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
return
}
kv = reflect.ValueOf(n).Convert(kt)
@@ -722,7 +759,7 @@ func (d *decodeState) object(v reflect.Value) {
s := string(key)
n, err := strconv.ParseUint(s, 10, 64)
if err != nil || reflect.Zero(kt).OverflowUint(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, kt, int64(start + 1)})
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
return
}
kv = reflect.ValueOf(n).Convert(kt)
@@ -741,6 +778,9 @@ func (d *decodeState) object(v reflect.Value) {
if op != scanObjectValue {
d.error(errPhase)
}
+
+ d.errorContext.Struct = ""
+ d.errorContext.Field = ""
}
}
@@ -767,7 +807,7 @@ func (d *decodeState) convertNumber(s string) (interface{}, error) {
}
f, err := strconv.ParseFloat(s, 64)
if err != nil {
- return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)}
+ return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeOf(0.0), Offset: int64(d.off)}
}
return f, nil
}
@@ -786,8 +826,8 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
return
}
- wantptr := item[0] == 'n' // null
- u, ut, pv := d.indirect(v, wantptr)
+ isNull := item[0] == 'n' // null
+ u, ut, pv := d.indirect(v, isNull)
if u != nil {
err := u.UnmarshalJSON(item)
if err != nil {
@@ -800,7 +840,16 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
- d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
+ var val string
+ switch item[0] {
+ case 'n':
+ val = "null"
+ case 't', 'f':
+ val = "bool"
+ default:
+ val = "number"
+ }
+ d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.off)})
}
return
}
@@ -823,19 +872,31 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
switch c := item[0]; c {
case 'n': // null
+ // The main parser checks that only true and false can reach here,
+ // but if this was a quoted string input, it could be anything.
+ if fromQuoted && string(item) != "null" {
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ break
+ }
switch v.Kind() {
case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
v.Set(reflect.Zero(v.Type()))
// otherwise, ignore null for primitives/string
}
case 't', 'f': // true, false
- value := c == 't'
+ value := item[0] == 't'
+ // The main parser checks that only true and false can reach here,
+ // but if this was a quoted string input, it could be anything.
+ if fromQuoted && string(item) != "true" && string(item) != "false" {
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ break
+ }
switch v.Kind() {
default:
if fromQuoted {
d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
- d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.off)})
}
case reflect.Bool:
v.SetBool(value)
@@ -843,7 +904,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if v.NumMethod() == 0 {
v.Set(reflect.ValueOf(value))
} else {
- d.saveError(&UnmarshalTypeError{"bool", v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.off)})
}
}
@@ -858,10 +919,10 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
}
switch v.Kind() {
default:
- d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)})
case reflect.Slice:
if v.Type().Elem().Kind() != reflect.Uint8 {
- d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)})
break
}
b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
@@ -877,7 +938,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if v.NumMethod() == 0 {
v.Set(reflect.ValueOf(string(s)))
} else {
- d.saveError(&UnmarshalTypeError{"string", v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)})
}
}
@@ -902,7 +963,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
if fromQuoted {
d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
} else {
- d.error(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
+ d.error(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.off)})
}
case reflect.Interface:
n, err := d.convertNumber(s)
@@ -911,7 +972,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
break
}
if v.NumMethod() != 0 {
- d.saveError(&UnmarshalTypeError{"number", v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.off)})
break
}
v.Set(reflect.ValueOf(n))
@@ -919,7 +980,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.ParseInt(s, 10, 64)
if err != nil || v.OverflowInt(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)})
break
}
v.SetInt(n)
@@ -927,7 +988,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n, err := strconv.ParseUint(s, 10, 64)
if err != nil || v.OverflowUint(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)})
break
}
v.SetUint(n)
@@ -935,7 +996,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
case reflect.Float32, reflect.Float64:
n, err := strconv.ParseFloat(s, v.Type().Bits())
if err != nil || v.OverflowFloat(n) {
- d.saveError(&UnmarshalTypeError{"number " + s, v.Type(), int64(d.off)})
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)})
break
}
v.SetFloat(n)
diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go
index 255ff5c66a7..bd38ddd3190 100644
--- a/libgo/go/encoding/json/decode_test.go
+++ b/libgo/go/encoding/json/decode_test.go
@@ -11,6 +11,7 @@ import (
"fmt"
"image"
"math"
+ "math/big"
"net"
"reflect"
"strconv"
@@ -33,6 +34,11 @@ type V struct {
F1 interface{}
F2 int32
F3 Number
+ F4 *VOuter
+}
+
+type VOuter struct {
+ V V
}
// ifaceNumAsFloat64/ifaceNumAsNumber are used to test unmarshaling with and
@@ -374,6 +380,10 @@ type unmarshalTest struct {
golden bool
}
+type B struct {
+ B bool `json:",string"`
+}
+
var unmarshalTests = []unmarshalTest{
// basic types
{in: `true`, ptr: new(bool), out: true},
@@ -389,7 +399,7 @@ var unmarshalTests = []unmarshalTest{
{in: `"g-clef: \uD834\uDD1E"`, ptr: new(string), out: "g-clef: \U0001D11E"},
{in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
{in: "null", ptr: new(interface{}), out: nil},
- {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7}},
+ {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7, "T", "X"}},
{in: `{"x": 1}`, ptr: new(tx), out: tx{}},
{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
{in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: Number("1"), F2: int32(2), F3: Number("3")}, useNumber: true},
@@ -504,22 +514,22 @@ var unmarshalTests = []unmarshalTest{
{
in: `{"abc":"abc"}`,
ptr: new(map[int]string),
- err: &UnmarshalTypeError{"number abc", reflect.TypeOf(0), 2},
+ err: &UnmarshalTypeError{Value: "number abc", Type: reflect.TypeOf(0), Offset: 2},
},
{
in: `{"256":"abc"}`,
ptr: new(map[uint8]string),
- err: &UnmarshalTypeError{"number 256", reflect.TypeOf(uint8(0)), 2},
+ err: &UnmarshalTypeError{Value: "number 256", Type: reflect.TypeOf(uint8(0)), Offset: 2},
},
{
in: `{"128":"abc"}`,
ptr: new(map[int8]string),
- err: &UnmarshalTypeError{"number 128", reflect.TypeOf(int8(0)), 2},
+ err: &UnmarshalTypeError{Value: "number 128", Type: reflect.TypeOf(int8(0)), Offset: 2},
},
{
in: `{"-1":"abc"}`,
ptr: new(map[uint8]string),
- err: &UnmarshalTypeError{"number -1", reflect.TypeOf(uint8(0)), 2},
+ err: &UnmarshalTypeError{Value: "number -1", Type: reflect.TypeOf(uint8(0)), Offset: 2},
},
// Map keys can be encoding.TextUnmarshalers.
@@ -653,12 +663,12 @@ var unmarshalTests = []unmarshalTest{
{
in: `{"2009-11-10T23:00:00Z": "hello world"}`,
ptr: &map[Point]string{},
- err: &UnmarshalTypeError{"object", reflect.TypeOf(map[Point]string{}), 1},
+ err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(map[Point]string{}), Offset: 1},
},
{
in: `{"asdf": "hello world"}`,
ptr: &map[unmarshaler]string{},
- err: &UnmarshalTypeError{"object", reflect.TypeOf(map[unmarshaler]string{}), 1},
+ err: &UnmarshalTypeError{Value: "object", Type: reflect.TypeOf(map[unmarshaler]string{}), Offset: 1},
},
// related to issue 13783.
@@ -738,6 +748,51 @@ var unmarshalTests = []unmarshalTest{
out: []intWithPtrMarshalText{1, 2, 3},
golden: true,
},
+
+ {in: `0.000001`, ptr: new(float64), out: 0.000001, golden: true},
+ {in: `1e-7`, ptr: new(float64), out: 1e-7, golden: true},
+ {in: `100000000000000000000`, ptr: new(float64), out: 100000000000000000000.0, golden: true},
+ {in: `1e+21`, ptr: new(float64), out: 1e21, golden: true},
+ {in: `-0.000001`, ptr: new(float64), out: -0.000001, golden: true},
+ {in: `-1e-7`, ptr: new(float64), out: -1e-7, golden: true},
+ {in: `-100000000000000000000`, ptr: new(float64), out: -100000000000000000000.0, golden: true},
+ {in: `-1e+21`, ptr: new(float64), out: -1e21, golden: true},
+ {in: `999999999999999900000`, ptr: new(float64), out: 999999999999999900000.0, golden: true},
+ {in: `9007199254740992`, ptr: new(float64), out: 9007199254740992.0, golden: true},
+ {in: `9007199254740993`, ptr: new(float64), out: 9007199254740992.0, golden: false},
+
+ {
+ in: `{"V": {"F2": "hello"}}`,
+ ptr: new(VOuter),
+ err: &UnmarshalTypeError{
+ Value: "string",
+ Struct: "V",
+ Field: "F2",
+ Type: reflect.TypeOf(int32(0)),
+ Offset: 20,
+ },
+ },
+ {
+ in: `{"V": {"F4": {}, "F2": "hello"}}`,
+ ptr: new(VOuter),
+ err: &UnmarshalTypeError{
+ Value: "string",
+ Struct: "V",
+ Field: "F2",
+ Type: reflect.TypeOf(int32(0)),
+ Offset: 30,
+ },
+ },
+
+ // issue 15146.
+ // invalid inputs in wrongStringTests below.
+ {in: `{"B":"true"}`, ptr: new(B), out: B{true}, golden: true},
+ {in: `{"B":"false"}`, ptr: new(B), out: B{false}, golden: true},
+ {in: `{"B": "maybe"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "maybe" into bool`)},
+ {in: `{"B": "tru"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "tru" into bool`)},
+ {in: `{"B": "False"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "False" into bool`)},
+ {in: `{"B": "null"}`, ptr: new(B), out: B{false}},
+ {in: `{"B": "nul"}`, ptr: new(B), err: errors.New(`json: invalid use of ,string struct tag, trying to unmarshal "nul" into bool`)},
}
func TestMarshal(t *testing.T) {
@@ -1470,40 +1525,148 @@ func TestInterfaceSet(t *testing.T) {
}
}
+type NullTest struct {
+ Bool bool
+ Int int
+ Int8 int8
+ Int16 int16
+ Int32 int32
+ Int64 int64
+ Uint uint
+ Uint8 uint8
+ Uint16 uint16
+ Uint32 uint32
+ Uint64 uint64
+ Float32 float32
+ Float64 float64
+ String string
+ PBool *bool
+ Map map[string]string
+ Slice []string
+ Interface interface{}
+
+ PRaw *RawMessage
+ PTime *time.Time
+ PBigInt *big.Int
+ PText *MustNotUnmarshalText
+ PBuffer *bytes.Buffer // has methods, just not relevant ones
+ PStruct *struct{}
+
+ Raw RawMessage
+ Time time.Time
+ BigInt big.Int
+ Text MustNotUnmarshalText
+ Buffer bytes.Buffer
+ Struct struct{}
+}
+
+type NullTestStrings struct {
+ Bool bool `json:",string"`
+ Int int `json:",string"`
+ Int8 int8 `json:",string"`
+ Int16 int16 `json:",string"`
+ Int32 int32 `json:",string"`
+ Int64 int64 `json:",string"`
+ Uint uint `json:",string"`
+ Uint8 uint8 `json:",string"`
+ Uint16 uint16 `json:",string"`
+ Uint32 uint32 `json:",string"`
+ Uint64 uint64 `json:",string"`
+ Float32 float32 `json:",string"`
+ Float64 float64 `json:",string"`
+ String string `json:",string"`
+ PBool *bool `json:",string"`
+ Map map[string]string `json:",string"`
+ Slice []string `json:",string"`
+ Interface interface{} `json:",string"`
+
+ PRaw *RawMessage `json:",string"`
+ PTime *time.Time `json:",string"`
+ PBigInt *big.Int `json:",string"`
+ PText *MustNotUnmarshalText `json:",string"`
+ PBuffer *bytes.Buffer `json:",string"`
+ PStruct *struct{} `json:",string"`
+
+ Raw RawMessage `json:",string"`
+ Time time.Time `json:",string"`
+ BigInt big.Int `json:",string"`
+ Text MustNotUnmarshalText `json:",string"`
+ Buffer bytes.Buffer `json:",string"`
+ Struct struct{} `json:",string"`
+}
+
// JSON null values should be ignored for primitives and string values instead of resulting in an error.
// Issue 2540
func TestUnmarshalNulls(t *testing.T) {
+ // Unmarshal docs:
+ // 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.
+
jsonData := []byte(`{
- "Bool" : null,
- "Int" : null,
- "Int8" : null,
- "Int16" : null,
- "Int32" : null,
- "Int64" : null,
- "Uint" : null,
- "Uint8" : null,
- "Uint16" : null,
- "Uint32" : null,
- "Uint64" : null,
- "Float32" : null,
- "Float64" : null,
- "String" : null}`)
-
- nulls := All{
- Bool: true,
- Int: 2,
- Int8: 3,
- Int16: 4,
- Int32: 5,
- Int64: 6,
- Uint: 7,
- Uint8: 8,
- Uint16: 9,
- Uint32: 10,
- Uint64: 11,
- Float32: 12.1,
- Float64: 13.1,
- String: "14"}
+ "Bool" : null,
+ "Int" : null,
+ "Int8" : null,
+ "Int16" : null,
+ "Int32" : null,
+ "Int64" : null,
+ "Uint" : null,
+ "Uint8" : null,
+ "Uint16" : null,
+ "Uint32" : null,
+ "Uint64" : null,
+ "Float32" : null,
+ "Float64" : null,
+ "String" : null,
+ "PBool": null,
+ "Map": null,
+ "Slice": null,
+ "Interface": null,
+ "PRaw": null,
+ "PTime": null,
+ "PBigInt": null,
+ "PText": null,
+ "PBuffer": null,
+ "PStruct": null,
+ "Raw": null,
+ "Time": null,
+ "BigInt": null,
+ "Text": null,
+ "Buffer": null,
+ "Struct": null
+ }`)
+ nulls := NullTest{
+ Bool: true,
+ Int: 2,
+ Int8: 3,
+ Int16: 4,
+ Int32: 5,
+ Int64: 6,
+ Uint: 7,
+ Uint8: 8,
+ Uint16: 9,
+ Uint32: 10,
+ Uint64: 11,
+ Float32: 12.1,
+ Float64: 13.1,
+ String: "14",
+ PBool: new(bool),
+ Map: map[string]string{},
+ Slice: []string{},
+ Interface: new(MustNotUnmarshalJSON),
+ PRaw: new(RawMessage),
+ PTime: new(time.Time),
+ PBigInt: new(big.Int),
+ PText: new(MustNotUnmarshalText),
+ PStruct: new(struct{}),
+ PBuffer: new(bytes.Buffer),
+ Raw: RawMessage("123"),
+ Time: time.Unix(123456789, 0),
+ BigInt: *big.NewInt(123),
+ }
+
+ before := nulls.Time.String()
err := Unmarshal(jsonData, &nulls)
if err != nil {
@@ -1512,9 +1675,61 @@ func TestUnmarshalNulls(t *testing.T) {
if !nulls.Bool || nulls.Int != 2 || nulls.Int8 != 3 || nulls.Int16 != 4 || nulls.Int32 != 5 || nulls.Int64 != 6 ||
nulls.Uint != 7 || nulls.Uint8 != 8 || nulls.Uint16 != 9 || nulls.Uint32 != 10 || nulls.Uint64 != 11 ||
nulls.Float32 != 12.1 || nulls.Float64 != 13.1 || nulls.String != "14" {
-
t.Errorf("Unmarshal of null values affected primitives")
}
+
+ if nulls.PBool != nil {
+ t.Errorf("Unmarshal of null did not clear nulls.PBool")
+ }
+ if nulls.Map != nil {
+ t.Errorf("Unmarshal of null did not clear nulls.Map")
+ }
+ if nulls.Slice != nil {
+ t.Errorf("Unmarshal of null did not clear nulls.Slice")
+ }
+ if nulls.Interface != nil {
+ t.Errorf("Unmarshal of null did not clear nulls.Interface")
+ }
+ if nulls.PRaw != nil {
+ t.Errorf("Unmarshal of null did not clear nulls.PRaw")
+ }
+ if nulls.PTime != nil {
+ t.Errorf("Unmarshal of null did not clear nulls.PTime")
+ }
+ if nulls.PBigInt != nil {
+ t.Errorf("Unmarshal of null did not clear nulls.PBigInt")
+ }
+ if nulls.PText != nil {
+ t.Errorf("Unmarshal of null did not clear nulls.PText")
+ }
+ if nulls.PBuffer != nil {
+ t.Errorf("Unmarshal of null did not clear nulls.PBuffer")
+ }
+ if nulls.PStruct != nil {
+ t.Errorf("Unmarshal of null did not clear nulls.PStruct")
+ }
+
+ if string(nulls.Raw) != "null" {
+ t.Errorf("Unmarshal of RawMessage null did not record null: %v", string(nulls.Raw))
+ }
+ if nulls.Time.String() != before {
+ t.Errorf("Unmarshal of time.Time null set time to %v", nulls.Time.String())
+ }
+ if nulls.BigInt.String() != "123" {
+ t.Errorf("Unmarshal of big.Int null set int to %v", nulls.BigInt.String())
+ }
+}
+
+type MustNotUnmarshalJSON struct{}
+
+func (x MustNotUnmarshalJSON) UnmarshalJSON(data []byte) error {
+ return errors.New("MustNotUnmarshalJSON was used")
+}
+
+type MustNotUnmarshalText struct{}
+
+func (x MustNotUnmarshalText) UnmarshalText(text []byte) error {
+ return errors.New("MustNotUnmarshalText was used")
}
func TestStringKind(t *testing.T) {
@@ -1540,8 +1755,8 @@ func TestStringKind(t *testing.T) {
}
}
-// Custom types with []byte as underlying type could not be marshalled
-// and then unmarshalled.
+// Custom types with []byte as underlying type could not be marshaled
+// and then unmarshaled.
// Issue 8962.
func TestByteKind(t *testing.T) {
type byteKind []byte
@@ -1753,7 +1968,7 @@ var invalidUnmarshalTextTests = []struct {
{nil, "json: Unmarshal(nil)"},
{struct{}{}, "json: Unmarshal(non-pointer struct {})"},
{(*int)(nil), "json: Unmarshal(nil *int)"},
- {new(net.IP), "json: cannot unmarshal string into Go value of type *net.IP"},
+ {new(net.IP), "json: cannot unmarshal number into Go value of type *net.IP"},
}
func TestInvalidUnmarshalText(t *testing.T) {
diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go
index 6bb6de8f079..8f21ddaed94 100644
--- a/libgo/go/encoding/json/encode.go
+++ b/libgo/go/encoding/json/encode.go
@@ -34,7 +34,7 @@ import (
// and is not a nil pointer, Marshal calls its MarshalJSON method
// to produce JSON. If no MarshalJSON method is present but the
// value implements encoding.TextMarshaler instead, Marshal calls
-// its MarshalText method.
+// its MarshalText method and encodes the result as a JSON string.
// The nil pointer exception is not strictly necessary
// but mimics a similar, necessary exception in the behavior of
// UnmarshalJSON.
@@ -50,25 +50,33 @@ import (
// 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.
-// This escaping can be disabled using an Encoder with DisableHTMLEscaping.
+// This escaping can be disabled using an Encoder that had SetEscapeHTML(false)
+// called on it.
//
// Array and slice values encode as JSON arrays, except that
// []byte encodes as a base64-encoded string, and a nil slice
// encodes as the null JSON value.
//
-// Struct values encode as JSON objects. Each exported struct field
-// becomes a member of the object unless
-// - the field's tag is "-", or
-// - the field is empty and its tag specifies the "omitempty" option.
-// The empty values are false, 0, any
-// nil pointer or interface value, and any array, slice, map, or string of
-// length zero. The object's default key string is the struct field name
-// but can be specified in the struct field's tag value. The "json" key in
-// the struct field's tag value is the key name, followed by an optional comma
-// and options. Examples:
+// Struct values encode as JSON objects.
+// Each exported struct field becomes a member of the object, using the
+// field name as the object key, unless the field is omitted for one of the
+// reasons given below.
//
-// // Field is ignored by this package.
-// Field int `json:"-"`
+// The encoding of each struct field can be customized by the format string
+// stored under the "json" key in the struct field's tag.
+// The format string gives the name of the field, possibly followed by a
+// comma-separated list of options. The name may be empty in order to
+// specify options without overriding the default field name.
+//
+// The "omitempty" option specifies that the field should be omitted
+// from the encoding if the field has an empty value, defined as
+// false, 0, a nil pointer, a nil interface value, and any empty array,
+// slice, map, or string.
+//
+// As a special case, if the field tag is "-", the field is always omitted.
+// Note that a field with name "-" can still be generated using the tag "-,".
+//
+// Examples of struct field tags and their meanings:
//
// // Field appears in JSON as key "myName".
// Field int `json:"myName"`
@@ -83,6 +91,12 @@ import (
// // Note the leading comma.
// Field int `json:",omitempty"`
//
+// // Field is ignored by this package.
+// Field int `json:"-"`
+//
+// // Field appears in JSON as key "-".
+// Field int `json:"-,"`
+//
// The "string" option signals that a field is stored as JSON inside a
// JSON-encoded string. It applies only to fields of string, floating point,
// integer, or boolean types. This extra level of encoding is sometimes used
@@ -110,7 +124,9 @@ import (
//
// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
// even if there are multiple untagged fields that would otherwise conflict.
+//
// 2) If there is exactly one field (tagged or not according to the first rule), that is selected.
+//
// 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
//
// Handling of anonymous struct fields is new in Go 1.1.
@@ -427,7 +443,11 @@ func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
e.WriteString("null")
return
}
- m := v.Interface().(Marshaler)
+ m, ok := v.Interface().(Marshaler)
+ if !ok {
+ e.WriteString("null")
+ return
+ }
b, err := m.MarshalJSON()
if err == nil {
// copy JSON into buffer, checking validity.
@@ -525,7 +545,31 @@ func (bits floatEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
if math.IsInf(f, 0) || math.IsNaN(f) {
e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))})
}
- b := strconv.AppendFloat(e.scratch[:0], f, 'g', -1, int(bits))
+
+ // Convert as if by ES6 number to string conversion.
+ // This matches most other JSON generators.
+ // See golang.org/issue/6384 and golang.org/issue/14135.
+ // Like fmt %g, but the exponent cutoffs are different
+ // and exponents themselves are not padded to two digits.
+ b := e.scratch[:0]
+ abs := math.Abs(f)
+ fmt := byte('f')
+ // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
+ if abs != 0 {
+ if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
+ fmt = 'e'
+ }
+ }
+ b = strconv.AppendFloat(b, f, fmt, -1, int(bits))
+ if fmt == 'e' {
+ // clean up e-09 to e-9
+ n := len(b)
+ if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
+ b[n-2] = b[n-1]
+ b = b[:n-1]
+ }
+ }
+
if opts.quoted {
e.WriteByte('"')
}
@@ -635,7 +679,7 @@ func (me *mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
e.error(&MarshalerError{v.Type(), err})
}
}
- sort.Sort(byString(sv))
+ sort.Slice(sv, func(i, j int) bool { return sv[i].s < sv[j].s })
for i, kv := range sv {
if i > 0 {
@@ -834,15 +878,6 @@ func (w *reflectWithString) resolve() error {
panic("unexpected map key type")
}
-// byString is a slice of reflectWithString where the reflect.Value is either
-// a string or an encoding.TextMarshaler.
-// It implements the methods to sort by string.
-type byString []reflectWithString
-
-func (sv byString) Len() int { return len(sv) }
-func (sv byString) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
-func (sv byString) Less(i, j int) bool { return sv[i].s < sv[j].s }
-
// NOTE: keep in sync with stringBytes below.
func (e *encodeState) string(s string, escapeHTML bool) int {
len0 := e.Len()
@@ -850,8 +885,7 @@ func (e *encodeState) string(s string, escapeHTML bool) int {
start := 0
for i := 0; i < len(s); {
if b := s[i]; b < utf8.RuneSelf {
- if 0x20 <= b && b != '\\' && b != '"' &&
- (!escapeHTML || b != '<' && b != '>' && b != '&') {
+ if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) {
i++
continue
}
@@ -928,8 +962,7 @@ func (e *encodeState) stringBytes(s []byte, escapeHTML bool) int {
start := 0
for i := 0; i < len(s); {
if b := s[i]; b < utf8.RuneSelf {
- if 0x20 <= b && b != '\\' && b != '"' &&
- (!escapeHTML || b != '<' && b != '>' && b != '&') {
+ if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) {
i++
continue
}
@@ -1018,28 +1051,6 @@ func fillField(f field) field {
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.
-type byName []field
-
-func (x byName) Len() int { return len(x) }
-
-func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
-
-func (x byName) Less(i, j int) bool {
- if x[i].name != x[j].name {
- return x[i].name < x[j].name
- }
- if len(x[i].index) != len(x[j].index) {
- return len(x[i].index) < len(x[j].index)
- }
- if x[i].tag != x[j].tag {
- return x[i].tag
- }
- return byIndex(x).Less(i, j)
-}
-
// byIndex sorts field by index sequence.
type byIndex []field
@@ -1157,7 +1168,22 @@ func typeFields(t reflect.Type) []field {
}
}
- sort.Sort(byName(fields))
+ sort.Slice(fields, func(i, j int) bool {
+ x := fields
+ // sort field by name, breaking ties with depth, then
+ // breaking ties with "name came from json tag", then
+ // breaking ties with index sequence.
+ if x[i].name != x[j].name {
+ return x[i].name < x[j].name
+ }
+ if len(x[i].index) != len(x[j].index) {
+ return len(x[i].index) < len(x[j].index)
+ }
+ if x[i].tag != x[j].tag {
+ return x[i].tag
+ }
+ return byIndex(x).Less(i, j)
+ })
// Delete all fields that are hidden by the Go rules for embedded fields,
// except that fields with JSON tags are promoted.
diff --git a/libgo/go/encoding/json/encode_test.go b/libgo/go/encoding/json/encode_test.go
index b484022a70e..6d574cfc47b 100644
--- a/libgo/go/encoding/json/encode_test.go
+++ b/libgo/go/encoding/json/encode_test.go
@@ -7,8 +7,11 @@ package json
import (
"bytes"
"fmt"
+ "log"
"math"
"reflect"
+ "regexp"
+ "strconv"
"testing"
"unicode"
)
@@ -290,6 +293,44 @@ type BugX struct {
BugB
}
+// Issue 16042. Even if a nil interface value is passed in
+// as long as it implements MarshalJSON, it should be marshaled.
+type nilMarshaler string
+
+func (nm *nilMarshaler) MarshalJSON() ([]byte, error) {
+ if nm == nil {
+ return Marshal("0zenil0")
+ }
+ return Marshal("zenil:" + string(*nm))
+}
+
+// Issue 16042.
+func TestNilMarshal(t *testing.T) {
+ testCases := []struct {
+ v interface{}
+ want string
+ }{
+ {v: nil, want: `null`},
+ {v: new(float64), want: `0`},
+ {v: []interface{}(nil), want: `null`},
+ {v: []string(nil), want: `null`},
+ {v: map[string]string(nil), want: `null`},
+ {v: []byte(nil), want: `null`},
+ {v: struct{ M string }{"gopher"}, want: `{"M":"gopher"}`},
+ {v: struct{ M Marshaler }{}, want: `{"M":null}`},
+ {v: struct{ M Marshaler }{(*nilMarshaler)(nil)}, want: `{"M":"0zenil0"}`},
+ {v: struct{ M interface{} }{(*nilMarshaler)(nil)}, want: `{"M":null}`},
+ }
+
+ for _, tt := range testCases {
+ out, err := Marshal(tt.v)
+ if err != nil || string(out) != tt.want {
+ t.Errorf("Marshal(%#v) = %#q, %#v, want %#q, nil", tt.v, out, err, tt.want)
+ continue
+ }
+ }
+}
+
// Issue 5245.
func TestEmbeddedBug(t *testing.T) {
v := BugB{
@@ -375,6 +416,7 @@ func TestDuplicatedFieldDisappears(t *testing.T) {
}
func TestStringBytes(t *testing.T) {
+ t.Parallel()
// Test that encodeState.stringBytes and encodeState.string use the same encoding.
var r []rune
for i := '\u0000'; i <= unicode.MaxRune; i++ {
@@ -418,30 +460,6 @@ func TestStringBytes(t *testing.T) {
}
}
-func TestIssue6458(t *testing.T) {
- type Foo struct {
- M RawMessage
- }
- x := Foo{RawMessage(`"foo"`)}
-
- b, err := Marshal(&x)
- if err != nil {
- t.Fatal(err)
- }
- if want := `{"M":"foo"}`; string(b) != want {
- t.Errorf("Marshal(&x) = %#q; want %#q", b, want)
- }
-
- b, err = Marshal(x)
- if err != nil {
- t.Fatal(err)
- }
-
- if want := `{"M":"ImZvbyI="}`; string(b) != want {
- t.Errorf("Marshal(x) = %#q; want %#q", b, want)
- }
-}
-
func TestIssue10281(t *testing.T) {
type Foo struct {
N Number
@@ -483,7 +501,7 @@ func TestEncodePointerString(t *testing.T) {
t.Fatalf("Unmarshal: %v", err)
}
if back.N == nil {
- t.Fatalf("Unmarshalled nil N field")
+ t.Fatalf("Unmarshaled nil N field")
}
if *back.N != 42 {
t.Fatalf("*N = %d; want 42", *back.N)
@@ -611,3 +629,208 @@ func TestTextMarshalerMapKeysAreSorted(t *testing.T) {
t.Errorf("Marshal map with text.Marshaler keys: got %#q, want %#q", b, want)
}
}
+
+var re = regexp.MustCompile
+
+// syntactic checks on form of marshaled floating point numbers.
+var badFloatREs = []*regexp.Regexp{
+ re(`p`), // no binary exponential notation
+ re(`^\+`), // no leading + sign
+ re(`^-?0[^.]`), // no unnecessary leading zeros
+ re(`^-?\.`), // leading zero required before decimal point
+ re(`\.(e|$)`), // no trailing decimal
+ re(`\.[0-9]+0(e|$)`), // no trailing zero in fraction
+ re(`^-?(0|[0-9]{2,})\..*e`), // exponential notation must have normalized mantissa
+ re(`e[0-9]`), // positive exponent must be signed
+ re(`e[+-]0`), // exponent must not have leading zeros
+ re(`e-[1-6]$`), // not tiny enough for exponential notation
+ re(`e+(.|1.|20)$`), // not big enough for exponential notation
+ re(`^-?0\.0000000`), // too tiny, should use exponential notation
+ re(`^-?[0-9]{22}`), // too big, should use exponential notation
+ re(`[1-9][0-9]{16}[1-9]`), // too many significant digits in integer
+ re(`[1-9][0-9.]{17}[1-9]`), // too many significant digits in decimal
+ // below here for float32 only
+ re(`[1-9][0-9]{8}[1-9]`), // too many significant digits in integer
+ re(`[1-9][0-9.]{9}[1-9]`), // too many significant digits in decimal
+}
+
+func TestMarshalFloat(t *testing.T) {
+ t.Parallel()
+ nfail := 0
+ test := func(f float64, bits int) {
+ vf := interface{}(f)
+ if bits == 32 {
+ f = float64(float32(f)) // round
+ vf = float32(f)
+ }
+ bout, err := Marshal(vf)
+ if err != nil {
+ t.Errorf("Marshal(%T(%g)): %v", vf, vf, err)
+ nfail++
+ return
+ }
+ out := string(bout)
+
+ // result must convert back to the same float
+ g, err := strconv.ParseFloat(out, bits)
+ if err != nil {
+ t.Errorf("Marshal(%T(%g)) = %q, cannot parse back: %v", vf, vf, out, err)
+ nfail++
+ return
+ }
+ if f != g || fmt.Sprint(f) != fmt.Sprint(g) { // fmt.Sprint handles ±0
+ t.Errorf("Marshal(%T(%g)) = %q (is %g, not %g)", vf, vf, out, float32(g), vf)
+ nfail++
+ return
+ }
+
+ bad := badFloatREs
+ if bits == 64 {
+ bad = bad[:len(bad)-2]
+ }
+ for _, re := range bad {
+ if re.MatchString(out) {
+ t.Errorf("Marshal(%T(%g)) = %q, must not match /%s/", vf, vf, out, re)
+ nfail++
+ return
+ }
+ }
+ }
+
+ var (
+ bigger = math.Inf(+1)
+ smaller = math.Inf(-1)
+ )
+
+ var digits = "1.2345678901234567890123"
+ for i := len(digits); i >= 2; i-- {
+ for exp := -30; exp <= 30; exp++ {
+ for _, sign := range "+-" {
+ for bits := 32; bits <= 64; bits += 32 {
+ s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp)
+ f, err := strconv.ParseFloat(s, bits)
+ if err != nil {
+ log.Fatal(err)
+ }
+ next := math.Nextafter
+ if bits == 32 {
+ next = func(g, h float64) float64 {
+ return float64(math.Nextafter32(float32(g), float32(h)))
+ }
+ }
+ test(f, bits)
+ test(next(f, bigger), bits)
+ test(next(f, smaller), bits)
+ if nfail > 50 {
+ t.Fatalf("stopping test early")
+ }
+ }
+ }
+ }
+ }
+ test(0, 64)
+ test(math.Copysign(0, -1), 64)
+ test(0, 32)
+ test(math.Copysign(0, -1), 32)
+}
+
+func TestMarshalRawMessageValue(t *testing.T) {
+ type (
+ T1 struct {
+ M RawMessage `json:",omitempty"`
+ }
+ T2 struct {
+ M *RawMessage `json:",omitempty"`
+ }
+ )
+
+ var (
+ rawNil = RawMessage(nil)
+ rawEmpty = RawMessage([]byte{})
+ rawText = RawMessage([]byte(`"foo"`))
+ )
+
+ tests := []struct {
+ in interface{}
+ want string
+ ok bool
+ }{
+ // Test with nil RawMessage.
+ {rawNil, "null", true},
+ {&rawNil, "null", true},
+ {[]interface{}{rawNil}, "[null]", true},
+ {&[]interface{}{rawNil}, "[null]", true},
+ {[]interface{}{&rawNil}, "[null]", true},
+ {&[]interface{}{&rawNil}, "[null]", true},
+ {struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
+ {&struct{ M RawMessage }{rawNil}, `{"M":null}`, true},
+ {struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
+ {&struct{ M *RawMessage }{&rawNil}, `{"M":null}`, true},
+ {map[string]interface{}{"M": rawNil}, `{"M":null}`, true},
+ {&map[string]interface{}{"M": rawNil}, `{"M":null}`, true},
+ {map[string]interface{}{"M": &rawNil}, `{"M":null}`, true},
+ {&map[string]interface{}{"M": &rawNil}, `{"M":null}`, true},
+ {T1{rawNil}, "{}", true},
+ {T2{&rawNil}, `{"M":null}`, true},
+ {&T1{rawNil}, "{}", true},
+ {&T2{&rawNil}, `{"M":null}`, true},
+
+ // Test with empty, but non-nil, RawMessage.
+ {rawEmpty, "", false},
+ {&rawEmpty, "", false},
+ {[]interface{}{rawEmpty}, "", false},
+ {&[]interface{}{rawEmpty}, "", false},
+ {[]interface{}{&rawEmpty}, "", false},
+ {&[]interface{}{&rawEmpty}, "", false},
+ {struct{ X RawMessage }{rawEmpty}, "", false},
+ {&struct{ X RawMessage }{rawEmpty}, "", false},
+ {struct{ X *RawMessage }{&rawEmpty}, "", false},
+ {&struct{ X *RawMessage }{&rawEmpty}, "", false},
+ {map[string]interface{}{"nil": rawEmpty}, "", false},
+ {&map[string]interface{}{"nil": rawEmpty}, "", false},
+ {map[string]interface{}{"nil": &rawEmpty}, "", false},
+ {&map[string]interface{}{"nil": &rawEmpty}, "", false},
+ {T1{rawEmpty}, "{}", true},
+ {T2{&rawEmpty}, "", false},
+ {&T1{rawEmpty}, "{}", true},
+ {&T2{&rawEmpty}, "", false},
+
+ // Test with RawMessage with some text.
+ //
+ // The tests below marked with Issue6458 used to generate "ImZvbyI=" instead "foo".
+ // This behavior was intentionally changed in Go 1.8.
+ // See https://github.com/golang/go/issues/14493#issuecomment-255857318
+ {rawText, `"foo"`, true}, // Issue6458
+ {&rawText, `"foo"`, true},
+ {[]interface{}{rawText}, `["foo"]`, true}, // Issue6458
+ {&[]interface{}{rawText}, `["foo"]`, true}, // Issue6458
+ {[]interface{}{&rawText}, `["foo"]`, true},
+ {&[]interface{}{&rawText}, `["foo"]`, true},
+ {struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true}, // Issue6458
+ {&struct{ M RawMessage }{rawText}, `{"M":"foo"}`, true},
+ {struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
+ {&struct{ M *RawMessage }{&rawText}, `{"M":"foo"}`, true},
+ {map[string]interface{}{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458
+ {&map[string]interface{}{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458
+ {map[string]interface{}{"M": &rawText}, `{"M":"foo"}`, true},
+ {&map[string]interface{}{"M": &rawText}, `{"M":"foo"}`, true},
+ {T1{rawText}, `{"M":"foo"}`, true}, // Issue6458
+ {T2{&rawText}, `{"M":"foo"}`, true},
+ {&T1{rawText}, `{"M":"foo"}`, true},
+ {&T2{&rawText}, `{"M":"foo"}`, true},
+ }
+
+ for i, tt := range tests {
+ b, err := Marshal(tt.in)
+ if ok := (err == nil); ok != tt.ok {
+ if err != nil {
+ t.Errorf("test %d, unexpected failure: %v", i, err)
+ } else {
+ t.Errorf("test %d, unexpected success", i)
+ }
+ }
+ if got := string(b); got != tt.want {
+ t.Errorf("test %d, Marshal(%#v) = %q, want %q", i, tt.in, got, tt.want)
+ }
+ }
+}
diff --git a/libgo/go/encoding/json/example_marshaling_test.go b/libgo/go/encoding/json/example_marshaling_test.go
new file mode 100644
index 00000000000..1c4f783a693
--- /dev/null
+++ b/libgo/go/encoding/json/example_marshaling_test.go
@@ -0,0 +1,75 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package json_test
+
+import (
+ "encoding/json"
+ "fmt"
+ "log"
+ "strings"
+)
+
+type Animal int
+
+const (
+ Unknown Animal = iota
+ Gopher
+ Zebra
+)
+
+func (a *Animal) UnmarshalJSON(b []byte) error {
+ var s string
+ if err := json.Unmarshal(b, &s); err != nil {
+ return err
+ }
+ switch strings.ToLower(s) {
+ default:
+ *a = Unknown
+ case "gopher":
+ *a = Gopher
+ case "zebra":
+ *a = Zebra
+ }
+
+ return nil
+}
+
+func (a Animal) MarshalJSON() ([]byte, error) {
+ var s string
+ switch a {
+ default:
+ s = "unknown"
+ case Gopher:
+ s = "gopher"
+ case Zebra:
+ s = "zebra"
+ }
+
+ return json.Marshal(s)
+}
+
+func Example_customMarshalJSON() {
+ blob := `["gopher","armadillo","zebra","unknown","gopher","bee","gopher","zebra"]`
+ var zoo []Animal
+ if err := json.Unmarshal([]byte(blob), &zoo); err != nil {
+ log.Fatal(err)
+ }
+
+ census := make(map[Animal]int)
+ for _, animal := range zoo {
+ census[animal] += 1
+ }
+
+ fmt.Printf("Zoo Census:\n* Gophers: %d\n* Zebras: %d\n* Unknown: %d\n",
+ census[Gopher], census[Zebra], census[Unknown])
+
+ // Output:
+ // Zoo Census:
+ // * Gophers: 3
+ // * Zebras: 2
+ // * Unknown: 3
+}
diff --git a/libgo/go/encoding/json/scanner_test.go b/libgo/go/encoding/json/scanner_test.go
index 70a28974f78..c5c1be31f1e 100644
--- a/libgo/go/encoding/json/scanner_test.go
+++ b/libgo/go/encoding/json/scanner_test.go
@@ -119,6 +119,7 @@ func TestCompactBig(t *testing.T) {
}
func TestIndentBig(t *testing.T) {
+ t.Parallel()
initBig()
var buf bytes.Buffer
if err := Indent(&buf, jsonBig, "", "\t"); err != nil {
diff --git a/libgo/go/encoding/json/stream.go b/libgo/go/encoding/json/stream.go
index 87f0e57c6cd..95e30ce36d5 100644
--- a/libgo/go/encoding/json/stream.go
+++ b/libgo/go/encoding/json/stream.go
@@ -246,9 +246,12 @@ func (enc *Encoder) SetEscapeHTML(on bool) {
// be used to delay JSON decoding or precompute a JSON encoding.
type RawMessage []byte
-// MarshalJSON returns *m as the JSON encoding of m.
-func (m *RawMessage) MarshalJSON() ([]byte, error) {
- return *m, nil
+// MarshalJSON returns m as the JSON encoding of m.
+func (m RawMessage) MarshalJSON() ([]byte, error) {
+ if m == nil {
+ return []byte("null"), nil
+ }
+ return m, nil
}
// UnmarshalJSON sets *m to a copy of data.
diff --git a/libgo/go/encoding/json/tables.go b/libgo/go/encoding/json/tables.go
new file mode 100644
index 00000000000..10acdc18c6b
--- /dev/null
+++ b/libgo/go/encoding/json/tables.go
@@ -0,0 +1,218 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package json
+
+import "unicode/utf8"
+
+// safeSet holds the value true if the ASCII character with the given array
+// position can be represented inside a JSON string without any further
+// escaping.
+//
+// All values are true except for the ASCII control characters (0-31), the
+// double quote ("), and the backslash character ("\").
+var safeSet = [utf8.RuneSelf]bool{
+ ' ': true,
+ '!': true,
+ '"': false,
+ '#': true,
+ '$': true,
+ '%': true,
+ '&': true,
+ '\'': true,
+ '(': true,
+ ')': true,
+ '*': true,
+ '+': true,
+ ',': true,
+ '-': true,
+ '.': true,
+ '/': true,
+ '0': true,
+ '1': true,
+ '2': true,
+ '3': true,
+ '4': true,
+ '5': true,
+ '6': true,
+ '7': true,
+ '8': true,
+ '9': true,
+ ':': true,
+ ';': true,
+ '<': true,
+ '=': true,
+ '>': true,
+ '?': true,
+ '@': true,
+ 'A': true,
+ 'B': true,
+ 'C': true,
+ 'D': true,
+ 'E': true,
+ 'F': true,
+ 'G': true,
+ 'H': true,
+ 'I': true,
+ 'J': true,
+ 'K': true,
+ 'L': true,
+ 'M': true,
+ 'N': true,
+ 'O': true,
+ 'P': true,
+ 'Q': true,
+ 'R': true,
+ 'S': true,
+ 'T': true,
+ 'U': true,
+ 'V': true,
+ 'W': true,
+ 'X': true,
+ 'Y': true,
+ 'Z': true,
+ '[': true,
+ '\\': false,
+ ']': true,
+ '^': true,
+ '_': true,
+ '`': true,
+ 'a': true,
+ 'b': true,
+ 'c': true,
+ 'd': true,
+ 'e': true,
+ 'f': true,
+ 'g': true,
+ 'h': true,
+ 'i': true,
+ 'j': true,
+ 'k': true,
+ 'l': true,
+ 'm': true,
+ 'n': true,
+ 'o': true,
+ 'p': true,
+ 'q': true,
+ 'r': true,
+ 's': true,
+ 't': true,
+ 'u': true,
+ 'v': true,
+ 'w': true,
+ 'x': true,
+ 'y': true,
+ 'z': true,
+ '{': true,
+ '|': true,
+ '}': true,
+ '~': true,
+ '\u007f': true,
+}
+
+// htmlSafeSet holds the value true if the ASCII character with the given
+// array position can be safely represented inside a JSON string, embedded
+// inside of HTML <script> tags, without any additional escaping.
+//
+// All values are true except for the ASCII control characters (0-31), the
+// double quote ("), the backslash character ("\"), HTML opening and closing
+// tags ("<" and ">"), and the ampersand ("&").
+var htmlSafeSet = [utf8.RuneSelf]bool{
+ ' ': true,
+ '!': true,
+ '"': false,
+ '#': true,
+ '$': true,
+ '%': true,
+ '&': false,
+ '\'': true,
+ '(': true,
+ ')': true,
+ '*': true,
+ '+': true,
+ ',': true,
+ '-': true,
+ '.': true,
+ '/': true,
+ '0': true,
+ '1': true,
+ '2': true,
+ '3': true,
+ '4': true,
+ '5': true,
+ '6': true,
+ '7': true,
+ '8': true,
+ '9': true,
+ ':': true,
+ ';': true,
+ '<': false,
+ '=': true,
+ '>': false,
+ '?': true,
+ '@': true,
+ 'A': true,
+ 'B': true,
+ 'C': true,
+ 'D': true,
+ 'E': true,
+ 'F': true,
+ 'G': true,
+ 'H': true,
+ 'I': true,
+ 'J': true,
+ 'K': true,
+ 'L': true,
+ 'M': true,
+ 'N': true,
+ 'O': true,
+ 'P': true,
+ 'Q': true,
+ 'R': true,
+ 'S': true,
+ 'T': true,
+ 'U': true,
+ 'V': true,
+ 'W': true,
+ 'X': true,
+ 'Y': true,
+ 'Z': true,
+ '[': true,
+ '\\': false,
+ ']': true,
+ '^': true,
+ '_': true,
+ '`': true,
+ 'a': true,
+ 'b': true,
+ 'c': true,
+ 'd': true,
+ 'e': true,
+ 'f': true,
+ 'g': true,
+ 'h': true,
+ 'i': true,
+ 'j': true,
+ 'k': true,
+ 'l': true,
+ 'm': true,
+ 'n': true,
+ 'o': true,
+ 'p': true,
+ 'q': true,
+ 'r': true,
+ 's': true,
+ 't': true,
+ 'u': true,
+ 'v': true,
+ 'w': true,
+ 'x': true,
+ 'y': true,
+ 'z': true,
+ '{': true,
+ '|': true,
+ '}': true,
+ '~': true,
+ '\u007f': true,
+}
diff --git a/libgo/go/encoding/json/tagkey_test.go b/libgo/go/encoding/json/tagkey_test.go
index c1739ea97f7..f77c49c7647 100644
--- a/libgo/go/encoding/json/tagkey_test.go
+++ b/libgo/go/encoding/json/tagkey_test.go
@@ -44,6 +44,10 @@ type punctuationTag struct {
V string `json:"!#$%&()*+-./:<=>?@[]^_{|}~"` // https://golang.org/issue/3546
}
+type dashTag struct {
+ V string `json:"-,"`
+}
+
type emptyTag struct {
W string
}
@@ -80,6 +84,7 @@ var structTagObjectKeyTests = []struct {
{basicLatin6xTag{"6x"}, "6x", "abcdefghijklmno"},
{basicLatin7xTag{"7x"}, "7x", "pqrstuvwxyz"},
{miscPlaneTag{"いろはにほへと"}, "いろはにほへと", "色は匂へど"},
+ {dashTag{"foo"}, "foo", "-"},
{emptyTag{"Pour Moi"}, "Pour Moi", "W"},
{misnamedTag{"Animal Kingdom"}, "Animal Kingdom", "X"},
{badFormatTag{"Orfevre"}, "Orfevre", "Y"},
diff --git a/libgo/go/encoding/pem/example_test.go b/libgo/go/encoding/pem/example_test.go
new file mode 100644
index 00000000000..ffd962bd68f
--- /dev/null
+++ b/libgo/go/encoding/pem/example_test.go
@@ -0,0 +1,46 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package pem_test
+
+import (
+ "crypto/x509"
+ "encoding/pem"
+ "fmt"
+ "log"
+)
+
+func ExampleDecode() {
+ var pubPEMData = []byte(`
+-----BEGIN PUBLIC KEY-----
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlRuRnThUjU8/prwYxbty
+WPT9pURI3lbsKMiB6Fn/VHOKE13p4D8xgOCADpdRagdT6n4etr9atzDKUSvpMtR3
+CP5noNc97WiNCggBjVWhs7szEe8ugyqF23XwpHQ6uV1LKH50m92MbOWfCtjU9p/x
+qhNpQQ1AZhqNy5Gevap5k8XzRmjSldNAFZMY7Yv3Gi+nyCwGwpVtBUwhuLzgNFK/
+yDtw2WcWmUU7NuC8Q6MWvPebxVtCfVp/iQU6q60yyt6aGOBkhAX0LpKAEhKidixY
+nP9PNVBvxgu3XZ4P36gZV6+ummKdBVnc3NqwBLu5+CcdRdusmHPHd5pHf4/38Z3/
+6qU2a/fPvWzceVTEgZ47QjFMTCTmCwNt29cvi7zZeQzjtwQgn4ipN9NibRH/Ax/q
+TbIzHfrJ1xa2RteWSdFjwtxi9C20HUkjXSeI4YlzQMH0fPX6KCE7aVePTOnB69I/
+a9/q96DiXZajwlpq3wFctrs1oXqBp5DVrCIj8hU2wNgB7LtQ1mCtsYz//heai0K9
+PhE4X6hiE0YmeAZjR0uHl8M/5aW9xCoJ72+12kKpWAa0SFRWLy6FejNYCYpkupVJ
+yecLk/4L1W0l6jQQZnWErXZYe0PNFcmwGXy1Rep83kfBRNKRy5tvocalLlwXLdUk
+AIU+2GKjyT3iMuzZxxFxPFMCAwEAAQ==
+-----END PUBLIC KEY-----
+and some more`)
+
+ block, rest := pem.Decode(pubPEMData)
+ if block == nil || block.Type != "PUBLIC KEY" {
+ log.Fatal("failed to decode PEM block containing public key")
+ }
+
+ pub, err := x509.ParsePKIXPublicKey(block.Bytes)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Printf("Got a %T, with remaining data: %q", pub, rest)
+ // Output: Got a *rsa.PublicKey, with remaining data: "and some more"
+}
diff --git a/libgo/go/encoding/pem/pem.go b/libgo/go/encoding/pem/pem.go
index ff2bed161ad..fbf49997d5e 100644
--- a/libgo/go/encoding/pem/pem.go
+++ b/libgo/go/encoding/pem/pem.go
@@ -119,19 +119,36 @@ func Decode(data []byte) (p *Block, rest []byte) {
rest = next
}
- var endIndex int
+ var endIndex, endTrailerIndex int
+
// If there were no headers, the END line might occur
// immediately, without a leading newline.
if len(p.Headers) == 0 && bytes.HasPrefix(rest, pemEnd[1:]) {
endIndex = 0
+ endTrailerIndex = len(pemEnd) - 1
} else {
endIndex = bytes.Index(rest, pemEnd)
+ endTrailerIndex = endIndex + len(pemEnd)
}
if endIndex < 0 {
return decodeError(data, rest)
}
+ // After the "-----" of the ending line should be the same type and a
+ // final five dashes.
+ endTrailer := rest[endTrailerIndex:]
+ endTrailerLen := len(typeLine) + len(pemEndOfLine)
+ if len(endTrailer) < endTrailerLen {
+ return decodeError(data, rest)
+ }
+
+ endTrailer = endTrailer[:endTrailerLen]
+ if !bytes.HasPrefix(endTrailer, typeLine) ||
+ !bytes.HasSuffix(endTrailer, pemEndOfLine) {
+ return decodeError(data, rest)
+ }
+
base64Data := removeWhitespace(rest[:endIndex])
p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data)))
n, err := base64.StdEncoding.Decode(p.Bytes, base64Data)
diff --git a/libgo/go/encoding/pem/pem_test.go b/libgo/go/encoding/pem/pem_test.go
index 958dbc1a3a6..6321dec3820 100644
--- a/libgo/go/encoding/pem/pem_test.go
+++ b/libgo/go/encoding/pem/pem_test.go
@@ -78,6 +78,48 @@ func TestDecode(t *testing.T) {
}
}
+const pemTooFewEndingDashes = `
+-----BEGIN FOO-----
+dGVzdA==
+-----END FOO----`
+
+const pemWrongEndingType = `
+-----BEGIN FOO-----
+dGVzdA==
+-----END BAR-----`
+
+const pemMissingEndingSpace = `
+-----BEGIN FOO-----
+dGVzdA==
+-----ENDBAR-----`
+
+var badPEMTests = []struct {
+ name string
+ input string
+}{
+ {
+ "too few trailing dashes",
+ pemTooFewEndingDashes,
+ },
+ {
+ "incorrect ending type",
+ pemWrongEndingType,
+ },
+ {
+ "missing ending space",
+ pemMissingEndingSpace,
+ },
+}
+
+func TestBadDecode(t *testing.T) {
+ for _, test := range badPEMTests {
+ result, _ := Decode([]byte(test.input))
+ if result != nil {
+ t.Errorf("unexpected success while parsing %q", test.name)
+ }
+ }
+}
+
func TestEncode(t *testing.T) {
r := EncodeToMemory(privateKey2)
if string(r) != pemPrivateKey2 {
diff --git a/libgo/go/encoding/xml/marshal.go b/libgo/go/encoding/xml/marshal.go
index abb078ce270..1176f5d717d 100644
--- a/libgo/go/encoding/xml/marshal.go
+++ b/libgo/go/encoding/xml/marshal.go
@@ -24,10 +24,10 @@ const (
// Marshal returns the XML encoding of v.
//
-// Marshal handles an array or slice by marshalling each of the elements.
-// Marshal handles a pointer by marshalling the value it points at or, if the
+// Marshal handles an array or slice by marshaling each of the elements.
+// Marshal handles a pointer by marshaling the value it points at or, if the
// pointer is nil, by writing nothing. Marshal handles an interface value by
-// marshalling the value it contains or, if the interface value is nil, by
+// marshaling the value it contains or, if the interface value is nil, by
// writing nothing. Marshal handles all other data by writing one or more XML
// elements containing the data.
//
@@ -36,9 +36,9 @@ const (
// - the value of the XMLName field of type Name
// - the tag of the struct field used to obtain the data
// - the name of the struct field used to obtain the data
-// - the name of the marshalled type
+// - the name of the marshaled type
//
-// The XML element for a struct contains marshalled elements for each of the
+// The XML element for a struct contains marshaled elements for each of the
// exported fields of the struct, with these exceptions:
// - the XMLName field, described above, is omitted.
// - a field with tag "-" is omitted.
@@ -51,9 +51,9 @@ const (
// - a field with tag ",cdata" is written as character data
// wrapped in one or more <![CDATA[ ... ]]> tags, not as an XML element.
// - a field with tag ",innerxml" is written verbatim, not subject
-// to the usual marshalling procedure.
+// to the usual marshaling procedure.
// - a field with tag ",comment" is written as an XML comment, not
-// subject to the usual marshalling procedure. It must not contain
+// subject to the usual marshaling procedure. It must not contain
// the "--" string within it.
// - a field with a tag including the "omitempty" option is omitted
// if the field value is empty. The empty values are false, 0, any
@@ -494,7 +494,6 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
continue
}
fv := finfo.value(val)
- name := Name{Space: finfo.xmlns, Local: finfo.name}
if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
continue
@@ -504,69 +503,10 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
continue
}
- if fv.CanInterface() && fv.Type().Implements(marshalerAttrType) {
- attr, err := fv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
- if err != nil {
- return err
- }
- if attr.Name.Local != "" {
- start.Attr = append(start.Attr, attr)
- }
- continue
- }
-
- if fv.CanAddr() {
- pv := fv.Addr()
- if pv.CanInterface() && pv.Type().Implements(marshalerAttrType) {
- attr, err := pv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
- if err != nil {
- return err
- }
- if attr.Name.Local != "" {
- start.Attr = append(start.Attr, attr)
- }
- continue
- }
- }
-
- if fv.CanInterface() && fv.Type().Implements(textMarshalerType) {
- text, err := fv.Interface().(encoding.TextMarshaler).MarshalText()
- if err != nil {
- return err
- }
- start.Attr = append(start.Attr, Attr{name, string(text)})
- continue
- }
-
- if fv.CanAddr() {
- pv := fv.Addr()
- if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
- text, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
- if err != nil {
- return err
- }
- start.Attr = append(start.Attr, Attr{name, string(text)})
- continue
- }
- }
-
- // Dereference or skip nil pointer, interface values.
- switch fv.Kind() {
- case reflect.Ptr, reflect.Interface:
- if fv.IsNil() {
- continue
- }
- fv = fv.Elem()
- }
-
- s, b, err := p.marshalSimple(fv.Type(), fv)
- if err != nil {
+ name := Name{Space: finfo.xmlns, Local: finfo.name}
+ if err := p.marshalAttr(&start, name, fv); err != nil {
return err
}
- if b != nil {
- s = string(b)
- }
- start.Attr = append(start.Attr, Attr{name, s})
}
if err := p.writeStart(&start); err != nil {
@@ -596,6 +536,90 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat
return p.cachedWriteError()
}
+// marshalAttr marshals an attribute with the given name and value, adding to start.Attr.
+func (p *printer) marshalAttr(start *StartElement, name Name, val reflect.Value) error {
+ if val.CanInterface() && val.Type().Implements(marshalerAttrType) {
+ attr, err := val.Interface().(MarshalerAttr).MarshalXMLAttr(name)
+ if err != nil {
+ return err
+ }
+ if attr.Name.Local != "" {
+ start.Attr = append(start.Attr, attr)
+ }
+ return nil
+ }
+
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(marshalerAttrType) {
+ attr, err := pv.Interface().(MarshalerAttr).MarshalXMLAttr(name)
+ if err != nil {
+ return err
+ }
+ if attr.Name.Local != "" {
+ start.Attr = append(start.Attr, attr)
+ }
+ return nil
+ }
+ }
+
+ if val.CanInterface() && val.Type().Implements(textMarshalerType) {
+ text, err := val.Interface().(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ return err
+ }
+ start.Attr = append(start.Attr, Attr{name, string(text)})
+ return nil
+ }
+
+ if val.CanAddr() {
+ pv := val.Addr()
+ if pv.CanInterface() && pv.Type().Implements(textMarshalerType) {
+ text, err := pv.Interface().(encoding.TextMarshaler).MarshalText()
+ if err != nil {
+ return err
+ }
+ start.Attr = append(start.Attr, Attr{name, string(text)})
+ return nil
+ }
+ }
+
+ // Dereference or skip nil pointer, interface values.
+ switch val.Kind() {
+ case reflect.Ptr, reflect.Interface:
+ if val.IsNil() {
+ return nil
+ }
+ val = val.Elem()
+ }
+
+ // Walk slices.
+ if val.Kind() == reflect.Slice && val.Type().Elem().Kind() != reflect.Uint8 {
+ n := val.Len()
+ for i := 0; i < n; i++ {
+ if err := p.marshalAttr(start, name, val.Index(i)); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+
+ if val.Type() == attrType {
+ start.Attr = append(start.Attr, val.Interface().(Attr))
+ return nil
+ }
+
+ s, b, err := p.marshalSimple(val.Type(), val)
+ if err != nil {
+ return err
+ }
+ if b != nil {
+ s = string(b)
+ }
+ start.Attr = append(start.Attr, Attr{name, s})
+ return nil
+}
+
// defaultStart returns the default start element to use,
// given the reflect type, field info, and start template.
func defaultStart(typ reflect.Type, finfo *fieldInfo, startTemplate *StartElement) StartElement {
@@ -760,14 +784,6 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
}
vf := finfo.value(val)
- // Dereference or skip nil pointer, interface values.
- switch vf.Kind() {
- case reflect.Ptr, reflect.Interface:
- if !vf.IsNil() {
- vf = vf.Elem()
- }
- }
-
switch finfo.flags & fMode {
case fCDATA, fCharData:
emit := EscapeText
@@ -800,6 +816,16 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
continue
}
}
+ // Drill into interfaces and pointers.
+ // This can turn into an infinite loop given a cyclic chain,
+ // but it matches the Go 1 behavior.
+ for vf.Kind() == reflect.Interface || vf.Kind() == reflect.Ptr {
+ if vf.IsNil() {
+ return nil
+ }
+ vf = vf.Elem()
+ }
+
var scratch [64]byte
switch vf.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
diff --git a/libgo/go/encoding/xml/marshal_test.go b/libgo/go/encoding/xml/marshal_test.go
index fe8b16fe431..d79b99a1e0b 100644
--- a/libgo/go/encoding/xml/marshal_test.go
+++ b/libgo/go/encoding/xml/marshal_test.go
@@ -199,6 +199,17 @@ type AttrTest struct {
Bytes []byte `xml:",attr"`
}
+type AttrsTest struct {
+ Attrs []Attr `xml:",any,attr"`
+ Int int `xml:",attr"`
+ Named int `xml:"int,attr"`
+ Float float64 `xml:",attr"`
+ Uint8 uint8 `xml:",attr"`
+ Bool bool `xml:",attr"`
+ Str string `xml:",attr"`
+ Bytes []byte `xml:",attr"`
+}
+
type OmitAttrTest struct {
Int int `xml:",attr,omitempty"`
Named int `xml:"int,attr,omitempty"`
@@ -207,6 +218,7 @@ type OmitAttrTest struct {
Bool bool `xml:",attr,omitempty"`
Str string `xml:",attr,omitempty"`
Bytes []byte `xml:",attr,omitempty"`
+ PStr *string `xml:",attr,omitempty"`
}
type OmitFieldTest struct {
@@ -217,6 +229,7 @@ type OmitFieldTest struct {
Bool bool `xml:",omitempty"`
Str string `xml:",omitempty"`
Bytes []byte `xml:",omitempty"`
+ PStr *string `xml:",omitempty"`
Ptr *PresenceTest `xml:",omitempty"`
}
@@ -317,6 +330,10 @@ func (m *MyMarshalerAttrTest) MarshalXMLAttr(name Name) (Attr, error) {
return Attr{name, "hello world"}, nil
}
+func (m *MyMarshalerAttrTest) UnmarshalXMLAttr(attr Attr) error {
+ return nil
+}
+
type MarshalerStruct struct {
Foo MyMarshalerAttrTest `xml:",attr"`
}
@@ -373,12 +390,13 @@ var (
nameAttr = "Sarah"
ageAttr = uint(12)
contentsAttr = "lorem ipsum"
+ empty = ""
)
// Unless explicitly stated as such (or *Plain), all of the
// tests below are two-way tests. When introducing new tests,
// please try to make them two-way as well to ensure that
-// marshalling and unmarshalling are as symmetrical as feasible.
+// marshaling and unmarshaling are as symmetrical as feasible.
var marshalTests = []struct {
Value interface{}
ExpectXML string
@@ -823,6 +841,53 @@ var marshalTests = []struct {
` Bool="false" Str="" Bytes=""></AttrTest>`,
},
{
+ Value: &AttrsTest{
+ Attrs: []Attr{
+ {Name: Name{Local: "Answer"}, Value: "42"},
+ {Name: Name{Local: "Int"}, Value: "8"},
+ {Name: Name{Local: "int"}, Value: "9"},
+ {Name: Name{Local: "Float"}, Value: "23.5"},
+ {Name: Name{Local: "Uint8"}, Value: "255"},
+ {Name: Name{Local: "Bool"}, Value: "true"},
+ {Name: Name{Local: "Str"}, Value: "str"},
+ {Name: Name{Local: "Bytes"}, Value: "byt"},
+ },
+ },
+ ExpectXML: `<AttrsTest Answer="42" Int="8" int="9" Float="23.5" Uint8="255" Bool="true" Str="str" Bytes="byt" Int="0" int="0" Float="0" Uint8="0" Bool="false" Str="" Bytes=""></AttrsTest>`,
+ MarshalOnly: true,
+ },
+ {
+ Value: &AttrsTest{
+ Attrs: []Attr{
+ {Name: Name{Local: "Answer"}, Value: "42"},
+ },
+ Int: 8,
+ Named: 9,
+ Float: 23.5,
+ Uint8: 255,
+ Bool: true,
+ Str: "str",
+ Bytes: []byte("byt"),
+ },
+ ExpectXML: `<AttrsTest Answer="42" Int="8" int="9" Float="23.5" Uint8="255" Bool="true" Str="str" Bytes="byt"></AttrsTest>`,
+ },
+ {
+ Value: &AttrsTest{
+ Attrs: []Attr{
+ {Name: Name{Local: "Int"}, Value: "0"},
+ {Name: Name{Local: "int"}, Value: "0"},
+ {Name: Name{Local: "Float"}, Value: "0"},
+ {Name: Name{Local: "Uint8"}, Value: "0"},
+ {Name: Name{Local: "Bool"}, Value: "false"},
+ {Name: Name{Local: "Str"}},
+ {Name: Name{Local: "Bytes"}},
+ },
+ Bytes: []byte{},
+ },
+ ExpectXML: `<AttrsTest Int="0" int="0" Float="0" Uint8="0" Bool="false" Str="" Bytes="" Int="0" int="0" Float="0" Uint8="0" Bool="false" Str="" Bytes=""></AttrsTest>`,
+ MarshalOnly: true,
+ },
+ {
Value: &OmitAttrTest{
Int: 8,
Named: 9,
@@ -831,9 +896,10 @@ var marshalTests = []struct {
Bool: true,
Str: "str",
Bytes: []byte("byt"),
+ PStr: &empty,
},
ExpectXML: `<OmitAttrTest Int="8" int="9" Float="23.5" Uint8="255"` +
- ` Bool="true" Str="str" Bytes="byt"></OmitAttrTest>`,
+ ` Bool="true" Str="str" Bytes="byt" PStr=""></OmitAttrTest>`,
},
{
Value: &OmitAttrTest{},
@@ -864,6 +930,7 @@ var marshalTests = []struct {
Bool: true,
Str: "str",
Bytes: []byte("byt"),
+ PStr: &empty,
Ptr: &PresenceTest{},
},
ExpectXML: `<OmitFieldTest>` +
@@ -874,6 +941,7 @@ var marshalTests = []struct {
`<Bool>true</Bool>` +
`<Str>str</Str>` +
`<Bytes>byt</Bytes>` +
+ `<PStr></PStr>` +
`<Ptr></Ptr>` +
`</OmitFieldTest>`,
},
@@ -1092,7 +1160,7 @@ type AttrParent struct {
}
type BadAttr struct {
- Name []string `xml:"name,attr"`
+ Name map[string]string `xml:"name,attr"`
}
var marshalErrorTests = []struct {
@@ -1128,8 +1196,8 @@ var marshalErrorTests = []struct {
Err: `xml: X>Y chain not valid with attr flag`,
},
{
- Value: BadAttr{[]string{"X", "Y"}},
- Err: `xml: unsupported type: []string`,
+ Value: BadAttr{map[string]string{"X": "Y"}},
+ Err: `xml: unsupported type: map[string]string`,
},
}
@@ -1732,7 +1800,7 @@ func TestDecodeEncode(t *testing.T) {
in.WriteString(`<?xml version="1.0" encoding="UTF-8"?>
<?Target Instruction?>
<root>
-</root>
+</root>
`)
dec := NewDecoder(&in)
enc := NewEncoder(&out)
@@ -1823,3 +1891,14 @@ func TestSimpleUseOfEncodeToken(t *testing.T) {
t.Errorf("enc.EncodeToken: expected %q; got %q", want, buf.String())
}
}
+
+// Issue 16158. Decoder.unmarshalAttr ignores the return value of copyValue.
+func TestIssue16158(t *testing.T) {
+ const data = `<foo b="HELLOWORLD"></foo>`
+ err := Unmarshal([]byte(data), &struct {
+ B byte `xml:"b,attr,omitempty"`
+ }{})
+ if err == nil {
+ t.Errorf("Unmarshal: expected error, got nil")
+ }
+}
diff --git a/libgo/go/encoding/xml/read.go b/libgo/go/encoding/xml/read.go
index 937432e3a7e..5a89d5f504a 100644
--- a/libgo/go/encoding/xml/read.go
+++ b/libgo/go/encoding/xml/read.go
@@ -52,6 +52,11 @@ import (
// the explicit name in a struct field tag of the form "name,attr",
// Unmarshal records the attribute value in that field.
//
+// * If the XML element has an attribute not handled by the previous
+// rule and the struct has a field with an associated tag containing
+// ",any,attr", Unmarshal records the attribute value in the first
+// such field.
+//
// * If the XML element contains character data, that data is
// accumulated in the first struct field that has tag ",chardata".
// The struct field may have type []byte or string.
@@ -85,7 +90,7 @@ import (
// * An anonymous struct field is handled as if the fields of its
// value were part of the outer struct.
//
-// * A struct field with tag "-" is never unmarshalled into.
+// * A struct field with tag "-" is never unmarshaled into.
//
// Unmarshal maps an XML element to a string or []byte by saving the
// concatenation of that element's character data in the string or
@@ -94,8 +99,12 @@ import (
// Unmarshal maps an attribute value to a string or []byte by saving
// the value in the string or slice.
//
-// Unmarshal maps an XML element to a slice by extending the length of
-// the slice and mapping the element to the newly created value.
+// Unmarshal maps an attribute value to an Attr by saving the attribute,
+// including its name, in the Attr.
+//
+// Unmarshal maps an XML element or attribute value to a slice by
+// extending the length of the slice and mapping the element or attribute
+// to the newly created value.
//
// Unmarshal maps an XML element or attribute value to a bool by
// setting it to the boolean value represented by the string.
@@ -133,7 +142,7 @@ func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
return d.unmarshal(val.Elem(), start)
}
-// An UnmarshalError represents an error in the unmarshalling process.
+// An UnmarshalError represents an error in the unmarshaling process.
type UnmarshalError string
func (e UnmarshalError) Error() string { return string(e) }
@@ -232,7 +241,6 @@ func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
}
val = val.Elem()
}
-
if val.CanInterface() && val.Type().Implements(unmarshalerAttrType) {
// This is an unmarshaler with a non-pointer receiver,
// so it's likely to be incorrect, but we do what we're told.
@@ -258,11 +266,30 @@ func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error {
}
}
- copyValue(val, []byte(attr.Value))
- return nil
+ if val.Type().Kind() == reflect.Slice && val.Type().Elem().Kind() != reflect.Uint8 {
+ // Slice of element values.
+ // Grow slice.
+ n := val.Len()
+ val.Set(reflect.Append(val, reflect.Zero(val.Type().Elem())))
+
+ // Recur to read element into slice.
+ if err := p.unmarshalAttr(val.Index(n), attr); err != nil {
+ val.SetLen(n)
+ return err
+ }
+ return nil
+ }
+
+ if val.Type() == attrType {
+ val.Set(reflect.ValueOf(attr))
+ return nil
+ }
+
+ return copyValue(val, []byte(attr.Value))
}
var (
+ attrType = reflect.TypeOf(Attr{})
unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
unmarshalerAttrType = reflect.TypeOf((*UnmarshalerAttr)(nil)).Elem()
textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
@@ -359,16 +386,7 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
// Slice of element values.
// Grow slice.
n := v.Len()
- if n >= v.Cap() {
- ncap := 2 * n
- if ncap < 4 {
- ncap = 4
- }
- new := reflect.MakeSlice(typ, n, ncap)
- reflect.Copy(new, v)
- v.Set(new)
- }
- v.SetLen(n + 1)
+ v.Set(reflect.Append(val, reflect.Zero(v.Type().Elem())))
// Recur to read element into slice.
if err := p.unmarshal(v.Index(n), start); err != nil {
@@ -415,22 +433,40 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
}
// Assign attributes.
- // Also, determine whether we need to save character data or comments.
- for i := range tinfo.fields {
- finfo := &tinfo.fields[i]
- switch finfo.flags & fMode {
- case fAttr:
- strv := finfo.value(sv)
- // Look for attribute.
- for _, a := range start.Attr {
+ for _, a := range start.Attr {
+ handled := false
+ any := -1
+ for i := range tinfo.fields {
+ finfo := &tinfo.fields[i]
+ switch finfo.flags & fMode {
+ case fAttr:
+ strv := finfo.value(sv)
if a.Name.Local == finfo.name && (finfo.xmlns == "" || finfo.xmlns == a.Name.Space) {
if err := p.unmarshalAttr(strv, a); err != nil {
return err
}
- break
+ handled = true
+ }
+
+ case fAny | fAttr:
+ if any == -1 {
+ any = i
}
}
+ }
+ if !handled && any >= 0 {
+ finfo := &tinfo.fields[any]
+ strv := finfo.value(sv)
+ if err := p.unmarshalAttr(strv, a); err != nil {
+ return err
+ }
+ }
+ }
+ // Determine whether we need to save character data or comments.
+ for i := range tinfo.fields {
+ finfo := &tinfo.fields[i]
+ switch finfo.flags & fMode {
case fCDATA, fCharData:
if !saveData.IsValid() {
saveData = finfo.value(sv)
@@ -546,7 +582,9 @@ Loop:
case reflect.String:
t.SetString(string(saveXMLData))
case reflect.Slice:
- t.Set(reflect.ValueOf(saveXMLData))
+ if t.Type().Elem().Kind() == reflect.Uint8 {
+ t.Set(reflect.ValueOf(saveXMLData))
+ }
}
return nil
diff --git a/libgo/go/encoding/xml/read_test.go b/libgo/go/encoding/xml/read_test.go
index 7a98092803a..273c303d16d 100644
--- a/libgo/go/encoding/xml/read_test.go
+++ b/libgo/go/encoding/xml/read_test.go
@@ -705,7 +705,7 @@ func TestUnmarshalIntoInterface(t *testing.T) {
}
pea, ok := pod.Pea.(*Pea)
if !ok {
- t.Fatalf("unmarshalled into wrong type: have %T want *Pea", pod.Pea)
+ t.Fatalf("unmarshaled into wrong type: have %T want *Pea", pod.Pea)
}
have, want := pea.Cotelydon, "Green stuff"
if have != want {
@@ -733,3 +733,22 @@ func TestMalformedComment(t *testing.T) {
}
}
}
+
+type IXField struct {
+ Five int `xml:"five"`
+ NotInnerXML []string `xml:",innerxml"`
+}
+
+// Issue 15600. ",innerxml" on a field that can't hold it.
+func TestInvalidInnerXMLType(t *testing.T) {
+ v := new(IXField)
+ if err := Unmarshal([]byte(`<tag><five>5</five><innertag/></tag>`), v); err != nil {
+ t.Errorf("Unmarshal failed: got %v", err)
+ }
+ if v.Five != 5 {
+ t.Errorf("Five = %v, want 5", v.Five)
+ }
+ if v.NotInnerXML != nil {
+ t.Errorf("NotInnerXML = %v, want nil", v.NotInnerXML)
+ }
+}
diff --git a/libgo/go/encoding/xml/typeinfo.go b/libgo/go/encoding/xml/typeinfo.go
index 70da962ffaa..6623c78308e 100644
--- a/libgo/go/encoding/xml/typeinfo.go
+++ b/libgo/go/encoding/xml/typeinfo.go
@@ -48,7 +48,7 @@ var tinfoLock sync.RWMutex
var nameType = reflect.TypeOf(Name{})
// getTypeInfo returns the typeInfo structure with details necessary
-// for marshalling and unmarshalling typ.
+// for marshaling and unmarshaling typ.
func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
tinfoLock.RLock()
tinfo, ok := tinfoMap[typ]
@@ -151,7 +151,7 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro
switch mode := finfo.flags & fMode; mode {
case 0:
finfo.flags |= fElement
- case fAttr, fCDATA, fCharData, fInnerXml, fComment, fAny:
+ case fAttr, fCDATA, fCharData, fInnerXml, fComment, fAny, fAny | fAttr:
if f.Name == "XMLName" || tag != "" && mode != fAttr {
valid = false
}
@@ -214,7 +214,7 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro
}
// If the field type has an XMLName field, the names must match
- // so that the behavior of both marshalling and unmarshalling
+ // so that the behavior of both marshaling and unmarshaling
// is straightforward and unambiguous.
if finfo.flags&fElement != 0 {
ftyp := f.Type
@@ -334,7 +334,7 @@ Loop:
return nil
}
-// A TagPathError represents an error in the unmarshalling process
+// A TagPathError represents an error in the unmarshaling process
// caused by the use of field tags with conflicting paths.
type TagPathError struct {
Struct reflect.Type
diff --git a/libgo/go/expvar/expvar.go b/libgo/go/expvar/expvar.go
index d5465c518f8..7339fa00b79 100644
--- a/libgo/go/expvar/expvar.go
+++ b/libgo/go/expvar/expvar.go
@@ -49,6 +49,10 @@ type Int struct {
i int64
}
+func (v *Int) Value() int64 {
+ return atomic.LoadInt64(&v.i)
+}
+
func (v *Int) String() string {
return strconv.FormatInt(atomic.LoadInt64(&v.i), 10)
}
@@ -66,6 +70,10 @@ type Float struct {
f uint64
}
+func (v *Float) Value() float64 {
+ return math.Float64frombits(atomic.LoadUint64(&v.f))
+}
+
func (v *Float) String() string {
return strconv.FormatFloat(
math.Float64frombits(atomic.LoadUint64(&v.f)), 'g', -1, 64)
@@ -219,6 +227,14 @@ type String struct {
s string
}
+func (v *String) Value() string {
+ v.mu.RLock()
+ defer v.mu.RUnlock()
+ return v.s
+}
+
+// String implements the Val interface. To get the unquoted string
+// use Value.
func (v *String) String() string {
v.mu.RLock()
s := v.s
@@ -237,6 +253,10 @@ func (v *String) Set(value string) {
// and formatting the returned value using JSON.
type Func func() interface{}
+func (f Func) Value() interface{} {
+ return f()
+}
+
func (f Func) String() string {
v, _ := json.Marshal(f())
return string(v)
@@ -322,6 +342,13 @@ func expvarHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "\n}\n")
}
+// Handler returns the expvar HTTP Handler.
+//
+// This is only needed to install the handler in a non-standard location.
+func Handler() http.Handler {
+ return http.HandlerFunc(expvarHandler)
+}
+
func cmdline() interface{} {
return os.Args
}
diff --git a/libgo/go/expvar/expvar_test.go b/libgo/go/expvar/expvar_test.go
index 7b1c9dfc4f8..0efa8643c0b 100644
--- a/libgo/go/expvar/expvar_test.go
+++ b/libgo/go/expvar/expvar_test.go
@@ -7,13 +7,12 @@ package expvar
import (
"bytes"
"encoding/json"
- "math"
"net"
"net/http/httptest"
+ "reflect"
"runtime"
"strconv"
"sync"
- "sync/atomic"
"testing"
)
@@ -58,6 +57,10 @@ func TestInt(t *testing.T) {
if reqs.i != -2 {
t.Errorf("reqs.i = %v, want -2", reqs.i)
}
+
+ if v, want := reqs.Value(), int64(-2); v != want {
+ t.Errorf("reqs.Value() = %q, want %q", v, want)
+ }
}
func BenchmarkIntAdd(b *testing.B) {
@@ -80,10 +83,6 @@ func BenchmarkIntSet(b *testing.B) {
})
}
-func (v *Float) val() float64 {
- return math.Float64frombits(atomic.LoadUint64(&v.f))
-}
-
func TestFloat(t *testing.T) {
RemoveAll()
reqs := NewFloat("requests-float")
@@ -96,8 +95,8 @@ func TestFloat(t *testing.T) {
reqs.Add(1.5)
reqs.Add(1.25)
- if v := reqs.val(); v != 2.75 {
- t.Errorf("reqs.val() = %v, want 2.75", v)
+ if v := reqs.Value(); v != 2.75 {
+ t.Errorf("reqs.Value() = %v, want 2.75", v)
}
if s := reqs.String(); s != "2.75" {
@@ -105,8 +104,8 @@ func TestFloat(t *testing.T) {
}
reqs.Add(-2)
- if v := reqs.val(); v != 0.75 {
- t.Errorf("reqs.val() = %v, want 0.75", v)
+ if v := reqs.Value(); v != 0.75 {
+ t.Errorf("reqs.Value() = %v, want 0.75", v)
}
}
@@ -146,6 +145,10 @@ func TestString(t *testing.T) {
t.Errorf("from %q, name.String() = %q, want %q", name.s, s, want)
}
+ if s, want := name.Value(), "Mike"; s != want {
+ t.Errorf("from %q, name.Value() = %q, want %q", name.s, s, want)
+ }
+
// Make sure we produce safe JSON output.
name.Set(`<`)
if s, want := name.String(), "\"\\u003c\""; s != want {
@@ -177,7 +180,7 @@ func TestMapCounter(t *testing.T) {
if x := colors.m["blue"].(*Int).i; x != 4 {
t.Errorf("colors.m[\"blue\"] = %v, want 4", x)
}
- if x := colors.m[`green "midori"`].(*Float).val(); x != 4.125 {
+ if x := colors.m[`green "midori"`].(*Float).Value(); x != 4.125 {
t.Errorf("colors.m[`green \"midori\"] = %v, want 4.125", x)
}
@@ -242,6 +245,9 @@ func TestFunc(t *testing.T) {
if s, exp := f.String(), `["a","b"]`; s != exp {
t.Errorf(`f.String() = %q, want %q`, s, exp)
}
+ if v := f.Value(); !reflect.DeepEqual(v, x) {
+ t.Errorf(`f.Value() = %q, want %q`, v, x)
+ }
x = 17
if s, exp := f.String(), `17`; s != exp {
diff --git a/libgo/go/flag/export_test.go b/libgo/go/flag/export_test.go
index 12d3dc76dfe..edbe83c6648 100644
--- a/libgo/go/flag/export_test.go
+++ b/libgo/go/flag/export_test.go
@@ -13,5 +13,6 @@ import "os"
// exit the program.
func ResetForTesting(usage func()) {
CommandLine = NewFlagSet(os.Args[0], ContinueOnError)
+ CommandLine.Usage = commandLineUsage
Usage = usage
}
diff --git a/libgo/go/flag/flag.go b/libgo/go/flag/flag.go
index fa0f05e9683..bbbc55a2799 100644
--- a/libgo/go/flag/flag.go
+++ b/libgo/go/flag/flag.go
@@ -94,7 +94,7 @@ func (b *boolValue) Set(s string) error {
func (b *boolValue) Get() interface{} { return bool(*b) }
-func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }
+func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) }
func (b *boolValue) IsBoolFlag() bool { return true }
@@ -121,7 +121,7 @@ func (i *intValue) Set(s string) error {
func (i *intValue) Get() interface{} { return int(*i) }
-func (i *intValue) String() string { return fmt.Sprintf("%v", *i) }
+func (i *intValue) String() string { return strconv.Itoa(int(*i)) }
// -- int64 Value
type int64Value int64
@@ -139,7 +139,7 @@ func (i *int64Value) Set(s string) error {
func (i *int64Value) Get() interface{} { return int64(*i) }
-func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) }
+func (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) }
// -- uint Value
type uintValue uint
@@ -157,7 +157,7 @@ func (i *uintValue) Set(s string) error {
func (i *uintValue) Get() interface{} { return uint(*i) }
-func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) }
+func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i), 10) }
// -- uint64 Value
type uint64Value uint64
@@ -175,7 +175,7 @@ func (i *uint64Value) Set(s string) error {
func (i *uint64Value) Get() interface{} { return uint64(*i) }
-func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) }
+func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
// -- string Value
type stringValue string
@@ -192,7 +192,7 @@ func (s *stringValue) Set(val string) error {
func (s *stringValue) Get() interface{} { return string(*s) }
-func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) }
+func (s *stringValue) String() string { return string(*s) }
// -- float64 Value
type float64Value float64
@@ -210,7 +210,7 @@ func (f *float64Value) Set(s string) error {
func (f *float64Value) Get() interface{} { return float64(*f) }
-func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) }
+func (f *float64Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 64) }
// -- time.Duration Value
type durationValue time.Duration
@@ -238,6 +238,8 @@ func (d *durationValue) String() string { return (*time.Duration)(d).String() }
// rather than using the next command-line argument.
//
// Set is called once, in command line order, for each flag present.
+// The flag package may call the String method with a zero-valued receiver,
+// such as a nil pointer.
type Value interface {
String() string
Set(string) error
@@ -500,7 +502,7 @@ func PrintDefaults() {
}
// defaultUsage is the default function to print a usage message.
-func defaultUsage(f *FlagSet) {
+func (f *FlagSet) defaultUsage() {
if f.name == "" {
fmt.Fprintf(f.out(), "Usage:\n")
} else {
@@ -819,11 +821,7 @@ func (f *FlagSet) failf(format string, a ...interface{}) error {
// or the appropriate default usage function otherwise.
func (f *FlagSet) usage() {
if f.Usage == nil {
- if f == CommandLine {
- Usage()
- } else {
- defaultUsage(f)
- }
+ f.defaultUsage()
} else {
f.Usage()
}
@@ -953,6 +951,18 @@ func Parsed() bool {
// methods of CommandLine.
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
+func init() {
+ // Override generic FlagSet default Usage with call to global Usage.
+ // Note: This is not CommandLine.Usage = Usage,
+ // because we want any eventual call to use any updated value of Usage,
+ // not the value it has when this line is run.
+ CommandLine.Usage = commandLineUsage
+}
+
+func commandLineUsage() {
+ Usage()
+}
+
// NewFlagSet returns a new, empty flag set with the specified name and
// error handling property.
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
@@ -960,6 +970,7 @@ func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
name: name,
errorHandling: errorHandling,
}
+ f.Usage = f.defaultUsage
return f
}
diff --git a/libgo/go/fmt/doc.go b/libgo/go/fmt/doc.go
index c312914b44a..a2faecb36e1 100644
--- a/libgo/go/fmt/doc.go
+++ b/libgo/go/fmt/doc.go
@@ -48,13 +48,10 @@
Pointer:
%p base 16 notation, with leading 0x
- 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 default format for %v is:
bool: %t
int, int8 etc.: %d
- uint, uint8 etc.: %d, %x if printed with %#v
+ uint, uint8 etc.: %d, %#x if printed with %#v
float32, complex64, etc: %g
string: %s
chan: %p
@@ -177,6 +174,9 @@
that type has a String method. Such pathologies are rare, however,
and the package does not protect against them.
+ When printing a struct, fmt cannot and therefore does not invoke
+ formatting methods such as Error or String on unexported fields.
+
Explicit argument indexes:
In Printf, Sprintf, and Fprintf, the default behavior is for each
@@ -247,31 +247,42 @@
Scanln, Fscanln and Sscanln stop scanning at a newline and
require that the items be followed by a newline or EOF.
- Scanf, Fscanf and Sscanf require that (after skipping spaces)
- newlines in the format are matched by newlines in the input
- and vice versa. This behavior differs from the corresponding
- routines in C, which uniformly treat newlines as spaces.
-
- When scanning with Scanf, Fscanf, and Sscanf, all non-empty
- runs of space characters (except newline) are equivalent
- to a single space in both the format and the input. With
- that proviso, text in the format string must match the input
- text; scanning stops if it does not, with the return value
- of the function indicating the number of arguments scanned.
-
Scanf, Fscanf, and Sscanf parse the arguments according to a
- format string, analogous to that of Printf. For example, %x
- will scan an integer as a hexadecimal number, and %v will scan
- the default representation format for the value.
-
- The formats behave analogously to those of Printf with the
- following exceptions:
-
- %p is not implemented
- %T is not implemented
- %e %E %f %F %g %G are all equivalent and scan any floating point or complex value
- %s and %v on strings scan a space-delimited token
- Flags # and + are not implemented.
+ format string, analogous to that of Printf. In the text that
+ follows, 'space' means any Unicode whitespace character
+ except newline.
+
+ In the format string, a verb introduced by the % character
+ consumes and parses input; these verbs are described in more
+ detail below. A character other than %, space, or newline in
+ the format consumes exactly that input character, which must
+ be present. A newline with zero or more spaces before it in
+ the format string consumes zero or more spaces in the input
+ followed by a single newline or the end of the input. A space
+ following a newline in the format string consumes zero or more
+ spaces in the input. Otherwise, any run of one or more spaces
+ in the format string consumes as many spaces as possible in
+ the input. Unless the run of spaces in the format string
+ appears adjacent to a newline, the run must consume at least
+ one space from the input or find the end of the input.
+
+ The handling of spaces and newlines differs from that of C's
+ scanf family: in C, newlines are treated as any other space,
+ and it is never an error when a run of spaces in the format
+ string finds no spaces to consume in the input.
+
+ The verbs behave analogously to those of Printf.
+ For example, %x will scan an integer as a hexadecimal number,
+ and %v will scan the default representation format for the value.
+ The Printf verbs %p and %T and the flags # and + are not implemented,
+ and the verbs %e %E %f %F %g and %G are all equivalent and scan any
+ floating-point or complex value.
+
+ Input processed by verbs is implicitly space-delimited: the
+ implementation of every verb except %c starts by discarding
+ leading spaces from the remaining input, and the %s verb
+ (and %v reading into a string) stops consuming input at the first
+ space or newline character.
The familiar base-setting prefixes 0 (octal) and 0x
(hexadecimal) are accepted when scanning integers without
@@ -300,6 +311,9 @@
All arguments to be scanned must be either pointers to basic
types or implementations of the Scanner interface.
+ Like Scanf and Fscanf, Sscanf need not consume its entire input.
+ There is no way to recover how much of the input string Sscanf used.
+
Note: Fscan etc. can read one character (rune) past the input
they return, which means that a loop calling a scan routine
may skip some of the input. This is usually a problem only
diff --git a/libgo/go/fmt/export_test.go b/libgo/go/fmt/export_test.go
index 12d5a1130a4..14163a29afe 100644
--- a/libgo/go/fmt/export_test.go
+++ b/libgo/go/fmt/export_test.go
@@ -5,3 +5,4 @@
package fmt
var IsSpace = isSpace
+var Parsenum = parsenum
diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go
index b6582367673..ce00456c7ba 100644
--- a/libgo/go/fmt/fmt_test.go
+++ b/libgo/go/fmt/fmt_test.go
@@ -605,7 +605,10 @@ var fmtTests = []struct {
{"%x", I(23), `3c32333e`},
{"%#x", I(23), `0x3c32333e`},
{"%# x", I(23), `0x3c 0x32 0x33 0x3e`},
- {"%d", I(23), `23`}, // Stringer applies only to string formats.
+ // Stringer applies only to string formats.
+ {"%d", I(23), `23`},
+ // Stringer applies to the extracted value.
+ {"%s", reflect.ValueOf(I(23)), `<23>`},
// go syntax
{"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`},
@@ -1560,18 +1563,23 @@ func TestWidthAndPrecision(t *testing.T) {
}
}
-// Panic is a type that panics in String.
-type Panic struct {
+// PanicS is a type that panics in String.
+type PanicS struct {
message interface{}
}
// Value receiver.
-func (p Panic) GoString() string {
+func (p PanicS) String() string {
panic(p.message)
}
+// PanicGo is a type that panics in GoString.
+type PanicGo struct {
+ message interface{}
+}
+
// Value receiver.
-func (p Panic) String() string {
+func (p PanicGo) GoString() string {
panic(p.message)
}
@@ -1591,13 +1599,15 @@ var panictests = []struct {
out string
}{
// String
- {"%s", (*Panic)(nil), "<nil>"}, // nil pointer special case
- {"%s", Panic{io.ErrUnexpectedEOF}, "%!s(PANIC=unexpected EOF)"},
- {"%s", Panic{3}, "%!s(PANIC=3)"},
+ {"%s", (*PanicS)(nil), "<nil>"}, // nil pointer special case
+ {"%s", PanicS{io.ErrUnexpectedEOF}, "%!s(PANIC=unexpected EOF)"},
+ {"%s", PanicS{3}, "%!s(PANIC=3)"},
// GoString
- {"%#v", (*Panic)(nil), "<nil>"}, // nil pointer special case
- {"%#v", Panic{io.ErrUnexpectedEOF}, "%!v(PANIC=unexpected EOF)"},
- {"%#v", Panic{3}, "%!v(PANIC=3)"},
+ {"%#v", (*PanicGo)(nil), "<nil>"}, // nil pointer special case
+ {"%#v", PanicGo{io.ErrUnexpectedEOF}, "%!v(PANIC=unexpected EOF)"},
+ {"%#v", PanicGo{3}, "%!v(PANIC=3)"},
+ // Issue 18282. catchPanic should not clear fmtFlags permanently.
+ {"%#v", []interface{}{PanicGo{3}, PanicGo{3}}, "[]interface {}{%!v(PANIC=3), %!v(PANIC=3)}"},
// Format
{"%s", (*PanicF)(nil), "<nil>"}, // nil pointer special case
{"%s", PanicF{io.ErrUnexpectedEOF}, "%!s(PANIC=unexpected EOF)"},
@@ -1739,3 +1749,26 @@ func TestFormatterFlags(t *testing.T) {
}
}
}
+
+func TestParsenum(t *testing.T) {
+ testCases := []struct {
+ s string
+ start, end int
+ num int
+ isnum bool
+ newi int
+ }{
+ {"a123", 0, 4, 0, false, 0},
+ {"1234", 1, 1, 0, false, 1},
+ {"123a", 0, 4, 123, true, 3},
+ {"12a3", 0, 4, 12, true, 2},
+ {"1234", 0, 4, 1234, true, 4},
+ {"1a234", 1, 3, 0, false, 1},
+ }
+ for _, tt := range testCases {
+ num, isnum, newi := Parsenum(tt.s, tt.start, tt.end)
+ if num != tt.num || isnum != tt.isnum || newi != tt.newi {
+ t.Errorf("parsenum(%q, %d, %d) = %d, %v, %d, want %d, %v, %d", tt.s, tt.start, tt.end, num, isnum, newi, tt.num, tt.isnum, tt.newi)
+ }
+ }
+}
diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go
index 023647501a0..f77048338ae 100644
--- a/libgo/go/fmt/format.go
+++ b/libgo/go/fmt/format.go
@@ -46,7 +46,7 @@ type fmt struct {
wid int // width
prec int // precision
- // intbuf is large enought to store %b of an int64 with a sign and
+ // intbuf is large enough to store %b of an int64 with a sign and
// avoids padding at the end of the struct on 32 bit architectures.
intbuf [68]byte
}
diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go
index f8c731656e5..a7ef2e5ac21 100644
--- a/libgo/go/fmt/print.go
+++ b/libgo/go/fmt/print.go
@@ -535,7 +535,11 @@ 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.
+
+ oldFlags := p.fmt.fmtFlags
+ // For this output we want default behavior.
+ p.fmt.clearflags()
+
p.buf.WriteString(percentBangString)
p.buf.WriteRune(verb)
p.buf.WriteString(panicString)
@@ -543,6 +547,8 @@ func (p *pp) catchPanic(arg interface{}, verb rune) {
p.printArg(err, 'v')
p.panicking = false
p.buf.WriteByte(')')
+
+ p.fmt.fmtFlags = oldFlags
}
}
@@ -659,6 +665,14 @@ func (p *pp) printArg(arg interface{}, verb rune) {
case []byte:
p.fmtBytes(f, verb, "[]byte")
case reflect.Value:
+ // Handle extractable values with special methods
+ // since printValue does not handle them at depth 0.
+ if f.IsValid() && f.CanInterface() {
+ p.arg = f.Interface()
+ if p.handleMethods(verb) {
+ return
+ }
+ }
p.printValue(f, verb, 0)
default:
// If the type is not simple, it might have methods.
@@ -805,16 +819,15 @@ func (p *pp) printValue(value reflect.Value, verb rune, depth int) {
if f.Kind() == reflect.Slice && f.IsNil() {
p.buf.WriteString(nilParenString)
return
- } else {
- p.buf.WriteByte('{')
- for i := 0; i < f.Len(); i++ {
- if i > 0 {
- p.buf.WriteString(commaSpaceString)
- }
- p.printValue(f.Index(i), verb, depth+1)
+ }
+ p.buf.WriteByte('{')
+ for i := 0; i < f.Len(); i++ {
+ if i > 0 {
+ p.buf.WriteString(commaSpaceString)
}
- p.buf.WriteByte('}')
+ p.printValue(f.Index(i), verb, depth+1)
}
+ p.buf.WriteByte('}')
} else {
p.buf.WriteByte('[')
for i := 0; i < f.Len(); i++ {
diff --git a/libgo/go/fmt/scan.go b/libgo/go/fmt/scan.go
index fdf419795d9..cd7232c33c4 100644
--- a/libgo/go/fmt/scan.go
+++ b/libgo/go/fmt/scan.go
@@ -1075,6 +1075,58 @@ func (s *ss) doScan(a []interface{}) (numProcessed int, err error) {
func (s *ss) advance(format string) (i int) {
for i < len(format) {
fmtc, w := utf8.DecodeRuneInString(format[i:])
+
+ // Space processing.
+ // In the rest of this comment "space" means spaces other than newline.
+ // Newline in the format matches input of zero or more spaces and then newline or end-of-input.
+ // Spaces in the format before the newline are collapsed into the newline.
+ // Spaces in the format after the newline match zero or more spaces after the corresponding input newline.
+ // Other spaces in the format match input of one or more spaces or end-of-input.
+ if isSpace(fmtc) {
+ newlines := 0
+ trailingSpace := false
+ for isSpace(fmtc) && i < len(format) {
+ if fmtc == '\n' {
+ newlines++
+ trailingSpace = false
+ } else {
+ trailingSpace = true
+ }
+ i += w
+ fmtc, w = utf8.DecodeRuneInString(format[i:])
+ }
+ for j := 0; j < newlines; j++ {
+ inputc := s.getRune()
+ for isSpace(inputc) && inputc != '\n' {
+ inputc = s.getRune()
+ }
+ if inputc != '\n' && inputc != eof {
+ s.errorString("newline in format does not match input")
+ }
+ }
+ if trailingSpace {
+ inputc := s.getRune()
+ if newlines == 0 {
+ // If the trailing space stood alone (did not follow a newline),
+ // it must find at least one space to consume.
+ if !isSpace(inputc) && inputc != eof {
+ s.errorString("expected space in input to match format")
+ }
+ if inputc == '\n' {
+ s.errorString("newline in input does not match format")
+ }
+ }
+ for isSpace(inputc) && inputc != '\n' {
+ inputc = s.getRune()
+ }
+ if inputc != eof {
+ s.UnreadRune()
+ }
+ }
+ continue
+ }
+
+ // Verbs.
if fmtc == '%' {
// % at end of string is an error.
if i+w == len(format) {
@@ -1087,48 +1139,8 @@ func (s *ss) advance(format string) (i int) {
}
i += w // skip the first %
}
- sawSpace := false
- wasNewline := false
- // Skip spaces in format but absorb at most one newline.
- for isSpace(fmtc) && i < len(format) {
- if fmtc == '\n' {
- if wasNewline { // Already saw one; stop here.
- break
- }
- wasNewline = true
- }
- sawSpace = true
- i += w
- fmtc, w = utf8.DecodeRuneInString(format[i:])
- }
- if sawSpace {
- // There was space in the format, so there should be space
- // in the input.
- inputc := s.getRune()
- if inputc == eof {
- return
- }
- if !isSpace(inputc) {
- // Space in format but not in input.
- s.errorString("expected space in input to match format")
- }
- // Skip spaces but stop at newline.
- for inputc != '\n' && isSpace(inputc) {
- inputc = s.getRune()
- }
- if inputc == '\n' {
- if !wasNewline {
- s.errorString("newline in input does not match format")
- }
- // We've reached a newline, stop now; don't read further.
- return
- }
- s.UnreadRune()
- if wasNewline {
- s.errorString("newline in format does not match input")
- }
- continue
- }
+
+ // Literals.
inputc := s.mustReadRune()
if fmtc != inputc {
s.UnreadRune()
diff --git a/libgo/go/fmt/scan_test.go b/libgo/go/fmt/scan_test.go
index e36b62e78a8..d7019d94394 100644
--- a/libgo/go/fmt/scan_test.go
+++ b/libgo/go/fmt/scan_test.go
@@ -291,6 +291,97 @@ var scanfTests = []ScanfTest{
{"%c", " ", &uintVal, uint(' ')}, // %c must accept a blank.
{"%c", "\t", &uintVal, uint('\t')}, // %c must accept any space.
{"%c", "\n", &uintVal, uint('\n')}, // %c must accept any space.
+
+ // space handling
+ {"%d", "27", &intVal, 27},
+ {"%d", "27 ", &intVal, 27},
+ {"%d", " 27", &intVal, 27},
+ {"%d", " 27 ", &intVal, 27},
+
+ {"X%d", "X27", &intVal, 27},
+ {"X%d", "X27 ", &intVal, 27},
+ {"X%d", "X 27", &intVal, 27},
+ {"X%d", "X 27 ", &intVal, 27},
+
+ {"X %d", "X27", &intVal, nil}, // expected space in input to match format
+ {"X %d", "X27 ", &intVal, nil}, // expected space in input to match format
+ {"X %d", "X 27", &intVal, 27},
+ {"X %d", "X 27 ", &intVal, 27},
+
+ {"%dX", "27X", &intVal, 27},
+ {"%dX", "27 X", &intVal, nil}, // input does not match format
+ {"%dX", " 27X", &intVal, 27},
+ {"%dX", " 27 X", &intVal, nil}, // input does not match format
+
+ {"%d X", "27X", &intVal, nil}, // expected space in input to match format
+ {"%d X", "27 X", &intVal, 27},
+ {"%d X", " 27X", &intVal, nil}, // expected space in input to match format
+ {"%d X", " 27 X", &intVal, 27},
+
+ {"X %d X", "X27X", &intVal, nil}, // expected space in input to match format
+ {"X %d X", "X27 X", &intVal, nil}, // expected space in input to match format
+ {"X %d X", "X 27X", &intVal, nil}, // expected space in input to match format
+ {"X %d X", "X 27 X", &intVal, 27},
+
+ {"X %s X", "X27X", &stringVal, nil}, // expected space in input to match format
+ {"X %s X", "X27 X", &stringVal, nil}, // expected space in input to match format
+ {"X %s X", "X 27X", &stringVal, nil}, // unexpected EOF
+ {"X %s X", "X 27 X", &stringVal, "27"},
+
+ {"X%sX", "X27X", &stringVal, nil}, // unexpected EOF
+ {"X%sX", "X27 X", &stringVal, nil}, // input does not match format
+ {"X%sX", "X 27X", &stringVal, nil}, // unexpected EOF
+ {"X%sX", "X 27 X", &stringVal, nil}, // input does not match format
+
+ {"X%s", "X27", &stringVal, "27"},
+ {"X%s", "X27 ", &stringVal, "27"},
+ {"X%s", "X 27", &stringVal, "27"},
+ {"X%s", "X 27 ", &stringVal, "27"},
+
+ {"X%dX", "X27X", &intVal, 27},
+ {"X%dX", "X27 X", &intVal, nil}, // input does not match format
+ {"X%dX", "X 27X", &intVal, 27},
+ {"X%dX", "X 27 X", &intVal, nil}, // input does not match format
+
+ {"X%dX", "X27X", &intVal, 27},
+ {"X%dX", "X27X ", &intVal, 27},
+ {"X%dX", " X27X", &intVal, nil}, // input does not match format
+ {"X%dX", " X27X ", &intVal, nil}, // input does not match format
+
+ {"X%dX\n", "X27X", &intVal, 27},
+ {"X%dX \n", "X27X ", &intVal, 27},
+ {"X%dX\n", "X27X\n", &intVal, 27},
+ {"X%dX\n", "X27X \n", &intVal, 27},
+
+ {"X%dX \n", "X27X", &intVal, 27},
+ {"X%dX \n", "X27X ", &intVal, 27},
+ {"X%dX \n", "X27X\n", &intVal, 27},
+ {"X%dX \n", "X27X \n", &intVal, 27},
+
+ {"X%c", "X\n", &runeVal, '\n'},
+ {"X%c", "X \n", &runeVal, ' '},
+ {"X %c", "X!", &runeVal, nil}, // expected space in input to match format
+ {"X %c", "X\n", &runeVal, nil}, // newline in input does not match format
+ {"X %c", "X !", &runeVal, '!'},
+ {"X %c", "X \n", &runeVal, '\n'},
+
+ {" X%dX", "X27X", &intVal, nil}, // expected space in input to match format
+ {" X%dX", "X27X ", &intVal, nil}, // expected space in input to match format
+ {" X%dX", " X27X", &intVal, 27},
+ {" X%dX", " X27X ", &intVal, 27},
+
+ {"X%dX ", "X27X", &intVal, 27},
+ {"X%dX ", "X27X ", &intVal, 27},
+ {"X%dX ", " X27X", &intVal, nil}, // input does not match format
+ {"X%dX ", " X27X ", &intVal, nil}, // input does not match format
+
+ {" X%dX ", "X27X", &intVal, nil}, // expected space in input to match format
+ {" X%dX ", "X27X ", &intVal, nil}, // expected space in input to match format
+ {" X%dX ", " X27X", &intVal, 27},
+ {" X%dX ", " X27X ", &intVal, 27},
+
+ {"%d\nX", "27\nX", &intVal, 27},
+ {"%dX\n X", "27X\n X", &intVal, 27},
}
var overflowTests = []ScanTest{
@@ -416,11 +507,17 @@ func TestScanf(t *testing.T) {
for _, test := range scanfTests {
n, err := Sscanf(test.text, test.format, test.in)
if err != nil {
- t.Errorf("got error scanning (%q, %q): %s", test.format, test.text, err)
+ if test.out != nil {
+ t.Errorf("Sscanf(%q, %q): unexpected error: %v", test.text, test.format, err)
+ }
+ continue
+ }
+ if test.out == nil {
+ t.Errorf("Sscanf(%q, %q): unexpected success", test.text, test.format)
continue
}
if n != 1 {
- t.Errorf("count error on entry (%q, %q): got %d", test.format, test.text, n)
+ t.Errorf("Sscanf(%q, %q): parsed %d field, want 1", test.text, test.format, n)
continue
}
// The incoming value may be a pointer
@@ -430,7 +527,7 @@ func TestScanf(t *testing.T) {
}
val := v.Interface()
if !reflect.DeepEqual(val, test.out) {
- t.Errorf("scanning (%q, %q): expected %#v got %#v, type %T", test.format, test.text, test.out, val, val)
+ t.Errorf("Sscanf(%q, %q): parsed value %T(%#v), want %T(%#v)", test.text, test.format, val, val, test.out, test.out)
}
}
}
@@ -1113,9 +1210,47 @@ func TestScanfNewlineMatchFormat(t *testing.T) {
{"space-newline in both", "1 \n2", "%d \n%d", 2, true},
{"extra space in format", "1\n2", "%d\n %d", 2, true},
{"two extra spaces in format", "1\n2", "%d \n %d", 2, true},
+ {"space vs newline 0000", "1\n2", "%d\n%d", 2, true},
+ {"space vs newline 0001", "1\n2", "%d\n %d", 2, true},
+ {"space vs newline 0010", "1\n2", "%d \n%d", 2, true},
+ {"space vs newline 0011", "1\n2", "%d \n %d", 2, true},
+ {"space vs newline 0100", "1\n 2", "%d\n%d", 2, true},
+ {"space vs newline 0101", "1\n 2", "%d\n%d ", 2, true},
+ {"space vs newline 0110", "1\n 2", "%d \n%d", 2, true},
+ {"space vs newline 0111", "1\n 2", "%d \n %d", 2, true},
+ {"space vs newline 1000", "1 \n2", "%d\n%d", 2, true},
+ {"space vs newline 1001", "1 \n2", "%d\n %d", 2, true},
+ {"space vs newline 1010", "1 \n2", "%d \n%d", 2, true},
+ {"space vs newline 1011", "1 \n2", "%d \n %d", 2, true},
+ {"space vs newline 1100", "1 \n 2", "%d\n%d", 2, true},
+ {"space vs newline 1101", "1 \n 2", "%d\n %d", 2, true},
+ {"space vs newline 1110", "1 \n 2", "%d \n%d", 2, true},
+ {"space vs newline 1111", "1 \n 2", "%d \n %d", 2, true},
+ {"space vs newline no-percent 0000", "1\n2", "1\n2", 0, true},
+ {"space vs newline no-percent 0001", "1\n2", "1\n 2", 0, true},
+ {"space vs newline no-percent 0010", "1\n2", "1 \n2", 0, true},
+ {"space vs newline no-percent 0011", "1\n2", "1 \n 2", 0, true},
+ {"space vs newline no-percent 0100", "1\n 2", "1\n2", 0, false}, // fails: space after nl in input but not pattern
+ {"space vs newline no-percent 0101", "1\n 2", "1\n2 ", 0, false}, // fails: space after nl in input but not pattern
+ {"space vs newline no-percent 0110", "1\n 2", "1 \n2", 0, false}, // fails: space after nl in input but not pattern
+ {"space vs newline no-percent 0111", "1\n 2", "1 \n 2", 0, true},
+ {"space vs newline no-percent 1000", "1 \n2", "1\n2", 0, true},
+ {"space vs newline no-percent 1001", "1 \n2", "1\n 2", 0, true},
+ {"space vs newline no-percent 1010", "1 \n2", "1 \n2", 0, true},
+ {"space vs newline no-percent 1011", "1 \n2", "1 \n 2", 0, true},
+ {"space vs newline no-percent 1100", "1 \n 2", "1\n2", 0, false}, // fails: space after nl in input but not pattern
+ {"space vs newline no-percent 1101", "1 \n 2", "1\n 2", 0, true},
+ {"space vs newline no-percent 1110", "1 \n 2", "1 \n2", 0, false}, // fails: space after nl in input but not pattern
+ {"space vs newline no-percent 1111", "1 \n 2", "1 \n 2", 0, true},
}
for _, test := range tests {
- n, err := Sscanf(test.text, test.format, &a, &b)
+ var n int
+ var err error
+ if strings.Contains(test.format, "%") {
+ n, err = Sscanf(test.text, test.format, &a, &b)
+ } else {
+ n, err = Sscanf(test.text, test.format)
+ }
if n != test.count {
t.Errorf("%s: expected to scan %d item(s), scanned %d", test.name, test.count, n)
}
diff --git a/libgo/go/go/ast/ast.go b/libgo/go/go/ast/ast.go
index d3dcd7915ba..a197b5a5bfc 100644
--- a/libgo/go/go/ast/ast.go
+++ b/libgo/go/go/ast/ast.go
@@ -317,7 +317,7 @@ type (
Fun Expr // function expression
Lparen token.Pos // position of "("
Args []Expr // function arguments; or nil
- Ellipsis token.Pos // position of "...", if any
+ Ellipsis token.Pos // position of "..." (token.NoPos if there is no "...")
Rparen token.Pos // position of ")"
}
@@ -902,7 +902,7 @@ type (
// A GenDecl node (generic declaration node) represents an import,
// constant, type or variable declaration. A valid Lparen position
- // (Lparen.Line > 0) indicates a parenthesized declaration.
+ // (Lparen.IsValid()) indicates a parenthesized declaration.
//
// Relationship between Tok value and Specs element type:
//
diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go
index 78e95c14880..cb053ebbed2 100644
--- a/libgo/go/go/build/build.go
+++ b/libgo/go/go/build/build.go
@@ -76,8 +76,9 @@ type Context struct {
// If IsDir is nil, Import calls os.Stat and uses the result's IsDir method.
IsDir func(path string) bool
- // HasSubdir reports whether dir is a subdirectory of
- // (perhaps multiple levels below) root.
+ // HasSubdir reports whether dir is lexically a subdirectory of
+ // root, perhaps multiple levels below. It does not try to check
+ // whether dir exists.
// If so, HasSubdir sets rel to a slash-separated path that
// can be joined to root to produce a path equivalent to dir.
// If HasSubdir is nil, Import uses an implementation built on
@@ -256,37 +257,23 @@ func (ctxt *Context) SrcDirs() []string {
// if set, or else the compiled code's GOARCH, GOOS, and GOROOT.
var Default Context = defaultContext()
-// Also known to cmd/dist/build.go.
-var cgoEnabled = map[string]bool{
- "darwin/386": true,
- "darwin/amd64": true,
- "darwin/arm": true,
- "darwin/arm64": true,
- "dragonfly/amd64": true,
- "freebsd/386": true,
- "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,
- "openbsd/386": true,
- "openbsd/amd64": true,
- "solaris/amd64": true,
- "windows/386": true,
- "windows/amd64": true,
+func defaultGOPATH() string {
+ env := "HOME"
+ if runtime.GOOS == "windows" {
+ env = "USERPROFILE"
+ } else if runtime.GOOS == "plan9" {
+ env = "home"
+ }
+ if home := os.Getenv(env); home != "" {
+ def := filepath.Join(home, "go")
+ if def == runtime.GOROOT() {
+ // Don't set the default GOPATH to GOROOT,
+ // as that will trigger warnings from the go tool.
+ return ""
+ }
+ return def
+ }
+ return ""
}
func defaultContext() Context {
@@ -295,7 +282,7 @@ func defaultContext() Context {
c.GOARCH = envOr("GOARCH", runtime.GOARCH)
c.GOOS = envOr("GOOS", runtime.GOOS)
c.GOROOT = pathpkg.Clean(runtime.GOROOT())
- c.GOPATH = envOr("GOPATH", "")
+ c.GOPATH = envOr("GOPATH", defaultGOPATH())
c.Compiler = runtime.Compiler
// Each major Go release in the Go 1.x series should add a tag here.
@@ -303,9 +290,14 @@ func defaultContext() Context {
// in all releases >= Go 1.x. Code that requires Go 1.x or later should
// 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".
- c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7"}
-
- switch os.Getenv("CGO_ENABLED") {
+ c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6", "go1.7", "go1.8"}
+
+ env := os.Getenv("CGO_ENABLED")
+ // No defaultCGO_ENABLED in gccgo.
+ // if env == "" {
+ // env = defaultCGO_ENABLED
+ // }
+ switch env {
case "1":
c.CgoEnabled = true
case "0":
@@ -313,7 +305,8 @@ func defaultContext() Context {
default:
// 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]
+ // Always enabled for gccgo.
+ c.CgoEnabled = true
break
}
c.CgoEnabled = false
@@ -369,6 +362,11 @@ const (
// See golang.org/s/go15vendor for more information.
//
// Setting IgnoreVendor ignores vendor directories.
+ //
+ // In contrast to the package's ImportPath,
+ // the returned package's Imports, TestImports, and XTestImports
+ // are always the exact import paths from the source files:
+ // Import makes no attempt to resolve or check those paths.
IgnoreVendor
)
@@ -414,15 +412,15 @@ type Package struct {
CgoPkgConfig []string // Cgo pkg-config directives
// Dependency information
- Imports []string // imports from GoFiles, CgoFiles
+ Imports []string // import paths from GoFiles, CgoFiles
ImportPos map[string][]token.Position // line information for Imports
// Test information
TestGoFiles []string // _test.go files in package
- TestImports []string // imports from TestGoFiles
+ TestImports []string // import paths from TestGoFiles
TestImportPos map[string][]token.Position // line information for TestImports
XTestGoFiles []string // _test.go files outside package
- XTestImports []string // imports from XTestGoFiles
+ XTestImports []string // import paths from XTestGoFiles
XTestImportPos map[string][]token.Position // line information for XTestImports
}
@@ -669,7 +667,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
format = "\t%s"
}
if len(tried.gopath) == 0 {
- paths = append(paths, "\t($GOPATH not set)")
+ paths = append(paths, "\t($GOPATH not set. For more details see: 'go help gopath')")
}
return p, fmt.Errorf("cannot find package %q in any of:\n%s", path, strings.Join(paths, "\n"))
}
@@ -1096,10 +1094,14 @@ func (ctxt *Context) matchFile(dir, name string, returnImports bool, allTags map
}
// Look for +build comments to accept or reject the file.
- if !ctxt.shouldBuild(data, allTags, binaryOnly) && !ctxt.UseAllFiles {
+ var sawBinaryOnly bool
+ if !ctxt.shouldBuild(data, allTags, &sawBinaryOnly) && !ctxt.UseAllFiles {
return
}
+ if binaryOnly != nil && sawBinaryOnly {
+ *binaryOnly = true
+ }
match = true
return
}
@@ -1143,9 +1145,8 @@ var binaryOnlyComment = []byte("//go:binary-only-package")
//
// marks the file as applicable only on Windows and Linux.
//
-// If shouldBuild finds a //go:binary-only-package comment in a file that
-// should be built, it sets *binaryOnly to true. Otherwise it does
-// not change *binaryOnly.
+// If shouldBuild finds a //go:binary-only-package comment in the file,
+// it sets *binaryOnly to true. Otherwise it does not change *binaryOnly.
//
func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool, binaryOnly *bool) bool {
sawBinaryOnly := false
@@ -1315,7 +1316,8 @@ func expandSrcDir(str string, srcdir string) (string, bool) {
// We never pass these arguments to a shell (just to programs we construct argv for), so this should be okay.
// See golang.org/issue/6038.
// The @ is for OS X. See golang.org/issue/13720.
-const safeString = "+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$@"
+// The % is for Jenkins. See golang.org/issue/16959.
+const safeString = "+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$@%"
const safeSpaces = " "
var safeBytes = []byte(safeSpaces + safeString)
diff --git a/libgo/go/go/build/build_test.go b/libgo/go/go/build/build_test.go
index 9f3c83258c7..2e2ff84fb12 100644
--- a/libgo/go/go/build/build_test.go
+++ b/libgo/go/go/build/build_test.go
@@ -285,6 +285,7 @@ func TestShellSafety(t *testing.T) {
result bool
}{
{"-I${SRCDIR}/../include", "/projects/src/issue 11868", "-I/projects/src/issue 11868/../include", true},
+ {"-I${SRCDIR}", "wtf$@%", "-Iwtf$@%", true},
{"-X${SRCDIR}/1,${SRCDIR}/2", "/projects/src/issue 11868", "-X/projects/src/issue 11868/1,/projects/src/issue 11868/2", true},
{"-I/tmp -I/tmp", "/tmp2", "-I/tmp -I/tmp", false},
{"-I/tmp", "/tmp/[0]", "-I/tmp", true},
diff --git a/libgo/go/go/build/deps_test.go b/libgo/go/go/build/deps_test.go
index 5b2529129cc..147eaf6aba3 100644
--- a/libgo/go/go/build/deps_test.go
+++ b/libgo/go/go/build/deps_test.go
@@ -59,7 +59,6 @@ var pkgDeps = map[string][]string{
"math": {"unsafe"},
"math/cmplx": {"math"},
"math/rand": {"L0", "math"},
- "sort": {},
"strconv": {"L0", "unicode/utf8", "math"},
"unicode/utf16": {},
"unicode/utf8": {},
@@ -94,8 +93,8 @@ var pkgDeps = map[string][]string{
// L3 adds reflection and some basic utility packages
// and interface definitions, but nothing that makes
// system calls.
- "crypto": {"L2", "hash"}, // interfaces
- "crypto/cipher": {"L2", "crypto/subtle"}, // interfaces
+ "crypto": {"L2", "hash"}, // interfaces
+ "crypto/cipher": {"L2", "crypto/subtle"},
"crypto/subtle": {},
"encoding/base32": {"L2"},
"encoding/base64": {"L2"},
@@ -109,11 +108,13 @@ var pkgDeps = map[string][]string{
"image/color": {"L2"}, // interfaces
"image/color/palette": {"L2", "image/color"},
"reflect": {"L2"},
+ "sort": {"reflect"},
"L3": {
"L2",
"crypto",
"crypto/cipher",
+ "crypto/internal/cipherhw",
"crypto/subtle",
"encoding/base32",
"encoding/base64",
@@ -170,17 +171,18 @@ var pkgDeps = map[string][]string{
"log": {"L1", "os", "fmt", "time"},
// Packages used by testing must be low-level (L2+fmt).
- "regexp": {"L2", "regexp/syntax"},
- "regexp/syntax": {"L2"},
- "runtime/debug": {"L2", "fmt", "io/ioutil", "os", "time"},
- "runtime/pprof": {"L2", "fmt", "os", "text/tabwriter"},
- "runtime/trace": {"L0"},
- "text/tabwriter": {"L2"},
-
- "testing": {"L2", "flag", "fmt", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"},
+ "regexp": {"L2", "regexp/syntax"},
+ "regexp/syntax": {"L2"},
+ "runtime/debug": {"L2", "fmt", "io/ioutil", "os", "time"},
+ "runtime/pprof/internal/protopprof": {"L2", "fmt", "internal/pprof/profile", "os", "time"},
+ "runtime/pprof": {"L2", "fmt", "internal/pprof/profile", "os", "runtime/pprof/internal/protopprof", "text/tabwriter", "time"},
+ "runtime/trace": {"L0"},
+ "text/tabwriter": {"L2"},
+
+ "testing": {"L2", "flag", "fmt", "internal/race", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"},
"testing/iotest": {"L2", "log"},
"testing/quick": {"L2", "flag", "fmt", "reflect"},
- "internal/testenv": {"L2", "OS", "flag", "testing"},
+ "internal/testenv": {"L2", "OS", "flag", "testing", "syscall"},
// L4 is defined as L3+fmt+log+time, because in general once
// you're using L3 packages, use of fmt, log, or time is not a big deal.
@@ -219,50 +221,53 @@ var pkgDeps = map[string][]string{
"go/types": {"L4", "GOPARSER", "container/heap", "go/constant"},
// One of a kind.
- "archive/tar": {"L4", "OS", "syscall"},
- "archive/zip": {"L4", "OS", "compress/flate"},
- "container/heap": {"sort"},
- "compress/bzip2": {"L4"},
- "compress/flate": {"L4"},
- "compress/gzip": {"L4", "compress/flate"},
- "compress/lzw": {"L4"},
- "compress/zlib": {"L4", "compress/flate"},
- "context": {"errors", "fmt", "reflect", "sync", "time"},
- "database/sql": {"L4", "container/list", "database/sql/driver"},
- "database/sql/driver": {"L4", "time"},
- "debug/dwarf": {"L4"},
- "debug/elf": {"L4", "OS", "debug/dwarf", "compress/zlib"},
- "debug/gosym": {"L4"},
- "debug/macho": {"L4", "OS", "debug/dwarf"},
- "debug/pe": {"L4", "OS", "debug/dwarf"},
- "debug/plan9obj": {"L4", "OS"},
- "encoding": {"L4"},
- "encoding/ascii85": {"L4"},
- "encoding/asn1": {"L4", "math/big"},
- "encoding/csv": {"L4"},
- "encoding/gob": {"L4", "OS", "encoding"},
- "encoding/hex": {"L4"},
- "encoding/json": {"L4", "encoding"},
- "encoding/pem": {"L4"},
- "encoding/xml": {"L4", "encoding"},
- "flag": {"L4", "OS"},
- "go/build": {"L4", "OS", "GOPARSER"},
- "html": {"L4"},
- "image/draw": {"L4", "image/internal/imageutil"},
- "image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"},
- "image/internal/imageutil": {"L4"},
- "image/jpeg": {"L4", "image/internal/imageutil"},
- "image/png": {"L4", "compress/zlib"},
- "index/suffixarray": {"L4", "regexp"},
- "internal/singleflight": {"sync"},
- "internal/trace": {"L4", "OS"},
- "math/big": {"L4"},
- "mime": {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
- "mime/quotedprintable": {"L4"},
- "net/internal/socktest": {"L4", "OS", "syscall"},
- "net/url": {"L4"},
- "text/scanner": {"L4", "OS"},
- "text/template/parse": {"L4"},
+ "archive/tar": {"L4", "OS", "syscall"},
+ "archive/zip": {"L4", "OS", "compress/flate"},
+ "container/heap": {"sort"},
+ "compress/bzip2": {"L4"},
+ "compress/flate": {"L4"},
+ "compress/gzip": {"L4", "compress/flate"},
+ "compress/lzw": {"L4"},
+ "compress/zlib": {"L4", "compress/flate"},
+ "context": {"errors", "fmt", "reflect", "sync", "time"},
+ "database/sql": {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"},
+ "database/sql/driver": {"L4", "context", "time", "database/sql/internal"},
+ "debug/dwarf": {"L4"},
+ "debug/elf": {"L4", "OS", "debug/dwarf", "compress/zlib"},
+ "debug/gosym": {"L4"},
+ "debug/macho": {"L4", "OS", "debug/dwarf"},
+ "debug/pe": {"L4", "OS", "debug/dwarf"},
+ "debug/plan9obj": {"L4", "OS"},
+ "encoding": {"L4"},
+ "encoding/ascii85": {"L4"},
+ "encoding/asn1": {"L4", "math/big"},
+ "encoding/csv": {"L4"},
+ "encoding/gob": {"L4", "OS", "encoding"},
+ "encoding/hex": {"L4"},
+ "encoding/json": {"L4", "encoding"},
+ "encoding/pem": {"L4"},
+ "encoding/xml": {"L4", "encoding"},
+ "flag": {"L4", "OS"},
+ "go/build": {"L4", "OS", "GOPARSER"},
+ "html": {"L4"},
+ "image/draw": {"L4", "image/internal/imageutil"},
+ "image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"},
+ "image/internal/imageutil": {"L4"},
+ "image/jpeg": {"L4", "image/internal/imageutil"},
+ "image/png": {"L4", "compress/zlib"},
+ "index/suffixarray": {"L4", "regexp"},
+ "internal/singleflight": {"sync"},
+ "internal/trace": {"L4", "OS"},
+ "internal/pprof/profile": {"L4", "OS", "compress/gzip", "regexp"},
+ "math/big": {"L4"},
+ "mime": {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
+ "mime/quotedprintable": {"L4"},
+ "net/internal/socktest": {"L4", "OS", "syscall"},
+ "net/url": {"L4"},
+ "plugin": {"L0", "OS", "CGO"},
+ "testing/internal/testdeps": {"L4", "runtime/pprof", "regexp"},
+ "text/scanner": {"L4", "OS"},
+ "text/template/parse": {"L4"},
"html/template": {
"L4", "OS", "encoding/json", "html", "text/template",
@@ -297,7 +302,7 @@ var pkgDeps = map[string][]string{
"context", "math/rand", "os", "sort", "syscall", "time",
"internal/nettrace",
"internal/syscall/windows", "internal/singleflight", "internal/race",
- "golang_org/x/net/route",
+ "golang_org/x/net/lif", "golang_org/x/net/route",
},
// NET enables use of basic network-related packages.
@@ -332,6 +337,9 @@ var pkgDeps = map[string][]string{
"crypto/sha1",
"crypto/sha256",
"crypto/sha512",
+ "golang_org/x/crypto/chacha20poly1305",
+ "golang_org/x/crypto/curve25519",
+ "golang_org/x/crypto/poly1305",
},
// Random byte, number generation.
@@ -375,16 +383,24 @@ var pkgDeps = map[string][]string{
// HTTP, kingpin of dependencies.
"net/http": {
"L4", "NET", "OS",
- "context", "compress/gzip", "container/list", "crypto/tls",
- "mime/multipart", "runtime/debug",
- "net/http/internal",
+ "compress/gzip",
+ "container/list",
+ "context",
+ "crypto/rand",
+ "crypto/tls",
"golang_org/x/net/http2/hpack",
+ "golang_org/x/net/idna",
"golang_org/x/net/lex/httplex",
+ "golang_org/x/text/unicode/norm",
+ "golang_org/x/text/width",
"internal/nettrace",
+ "mime/multipart",
"net/http/httptrace",
+ "net/http/internal",
+ "runtime/debug",
},
"net/http/internal": {"L4"},
- "net/http/httptrace": {"context", "internal/nettrace", "net", "reflect", "time"},
+ "net/http/httptrace": {"context", "crypto/tls", "internal/nettrace", "net", "reflect", "time"},
// HTTP-using packages.
"expvar": {"L4", "OS", "encoding/json", "net/http"},
@@ -392,7 +408,7 @@ var pkgDeps = map[string][]string{
"net/http/cookiejar": {"L4", "NET", "net/http"},
"net/http/fcgi": {"L4", "NET", "OS", "net/http", "net/http/cgi"},
"net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http", "net/http/internal"},
- "net/http/httputil": {"L4", "NET", "OS", "net/http", "net/http/internal"},
+ "net/http/httputil": {"L4", "NET", "OS", "context", "net/http", "net/http/internal"},
"net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof", "runtime/trace"},
"net/rpc": {"L4", "NET", "encoding/gob", "html/template", "net/http"},
"net/rpc/jsonrpc": {"L4", "NET", "encoding/json", "net/rpc"},
diff --git a/libgo/go/go/build/doc.go b/libgo/go/go/build/doc.go
index 9f7ac8f8ac4..979d0477dfb 100644
--- a/libgo/go/go/build/doc.go
+++ b/libgo/go/go/build/doc.go
@@ -104,6 +104,7 @@
// - "go1.5", from Go version 1.5 onward
// - "go1.6", from Go version 1.6 onward
// - "go1.7", from Go version 1.7 onward
+// - "go1.8", from Go version 1.8 onward
// - any additional words listed in ctxt.BuildTags
//
// If a file's name, after stripping the extension and a possible _test suffix,
diff --git a/libgo/go/go/build/syslist.go b/libgo/go/go/build/syslist.go
index 60c9fbcb74f..ea316ea61a2 100644
--- a/libgo/go/go/build/syslist.go
+++ b/libgo/go/go/build/syslist.go
@@ -4,5 +4,5 @@
package build
-const goosList = "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows "
+const goosList = "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows zos "
const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be alpha m68k ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le mipso32 mipsn32 mipsn64 mipso64 ppc s390 s390x sparc sparc64 "
diff --git a/libgo/go/go/constant/value.go b/libgo/go/go/constant/value.go
index ab10ae32998..7c32473c616 100644
--- a/libgo/go/go/constant/value.go
+++ b/libgo/go/go/constant/value.go
@@ -43,13 +43,14 @@ type Value interface {
// Kind returns the value kind.
Kind() Kind
- // String returns a short, human-readable form of the value.
+ // String returns a short, quoted (human-readable) form of the value.
// For numeric values, the result may be an approximation;
// for String values the result may be a shortened string.
// Use ExactString for a string representing a value exactly.
String() string
- // ExactString returns an exact, printable form of the value.
+ // ExactString returns an exact, quoted (human-readable) form of the value.
+ // If the Value is of Kind String, use StringVal to obtain the unquoted string.
ExactString() string
// Prevent external implementations.
@@ -847,6 +848,10 @@ Error:
func ord(x Value) int {
switch x.(type) {
+ default:
+ // force invalid value into "x position" in match
+ // (don't panic here so that callers can provide a better error message)
+ return -1
case unknownVal:
return 0
case boolVal, stringVal:
@@ -861,15 +866,13 @@ func ord(x Value) int {
return 5
case complexVal:
return 6
- default:
- panic("unreachable")
}
}
// match returns the matching representation (same type) with the
// smallest complexity for two values x and y. If one of them is
-// numeric, both of them must be numeric. If one of them is Unknown,
-// both results are Unknown.
+// numeric, both of them must be numeric. If one of them is Unknown
+// or invalid (say, nil) both results are that value.
//
func match(x, y Value) (_, _ Value) {
if ord(x) > ord(y) {
@@ -879,9 +882,6 @@ func match(x, y Value) (_, _ Value) {
// ord(x) <= ord(y)
switch x := x.(type) {
- case unknownVal:
- return x, x
-
case boolVal, stringVal, complexVal:
return x, y
@@ -920,6 +920,7 @@ func match(x, y Value) (_, _ Value) {
case complexVal:
return vtoc(x), y
}
+
case floatVal:
switch y := y.(type) {
case floatVal:
@@ -929,18 +930,23 @@ func match(x, y Value) (_, _ Value) {
}
}
- panic("unreachable")
+ // force unknown and invalid values into "x position" in callers of match
+ // (don't panic here so that callers can provide a better error message)
+ return x, x
}
// BinaryOp returns the result of the binary expression x op y.
// The operation must be defined for the operands. If one of the
// operands is Unknown, the result is Unknown.
+// BinaryOp doesn't handle comparisons or shifts; use Compare
+// or Shift instead.
+//
// To force integer division of Int operands, use op == token.QUO_ASSIGN
// instead of token.QUO; the result is guaranteed to be Int in this case.
// Division by zero leads to a run-time panic.
//
-func BinaryOp(x Value, op token.Token, y Value) Value {
- x, y = match(x, y)
+func BinaryOp(x_ Value, op token.Token, y_ Value) Value {
+ x, y := match(x_, y_)
switch x := x.(type) {
case unknownVal:
@@ -1107,7 +1113,7 @@ func BinaryOp(x Value, op token.Token, y Value) Value {
}
Error:
- panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y))
+ panic(fmt.Sprintf("invalid binary operation %v %s %v", x_, op, y_))
}
func add(x, y Value) Value { return BinaryOp(x, token.ADD, y) }
@@ -1167,7 +1173,7 @@ func cmpZero(x int, op token.Token) bool {
case token.GEQ:
return x >= 0
}
- panic("unreachable")
+ panic(fmt.Sprintf("invalid comparison %v %s 0", x, op))
}
// Compare returns the result of the comparison x op y.
@@ -1175,8 +1181,8 @@ func cmpZero(x int, op token.Token) bool {
// If one of the operands is Unknown, the result is
// false.
//
-func Compare(x Value, op token.Token, y Value) bool {
- x, y = match(x, y)
+func Compare(x_ Value, op token.Token, y_ Value) bool {
+ x, y := match(x_, y_)
switch x := x.(type) {
case unknownVal:
@@ -1246,5 +1252,5 @@ func Compare(x Value, op token.Token, y Value) bool {
}
}
- panic(fmt.Sprintf("invalid comparison %v %s %v", x, op, y))
+ panic(fmt.Sprintf("invalid comparison %v %s %v", x_, op, y_))
}
diff --git a/libgo/go/go/doc/comment.go b/libgo/go/go/doc/comment.go
index ed8eef4c61f..15e034b6df8 100644
--- a/libgo/go/go/doc/comment.go
+++ b/libgo/go/go/doc/comment.go
@@ -53,7 +53,7 @@ const (
filePart = `[a-zA-Z0-9_?%#~&/\-+=()]+` // parentheses may not be matching; see pairedParensPrefixLen
urlRx = `(` + protocol + `)://` + // http://
hostPart + `([.:]` + hostPart + `)*/?` + // //www.google.com:8080/
- filePart + `([:.,]` + filePart + `)*`
+ filePart + `([:.,;]` + filePart + `)*`
)
var matchRx = regexp.MustCompile(`(` + urlRx + `)|(` + identRx + `)`)
diff --git a/libgo/go/go/doc/comment_test.go b/libgo/go/go/doc/comment_test.go
index ad65c2a27f8..76dfbeac796 100644
--- a/libgo/go/go/doc/comment_test.go
+++ b/libgo/go/go/doc/comment_test.go
@@ -162,6 +162,7 @@ var emphasizeTests = []struct {
{"Hello http://example.com/%2f/ /world.", `Hello <a href="http://example.com/%2f/">http://example.com/%2f/</a> /world.`},
{"Lorem http: ipsum //host/path", "Lorem http: ipsum //host/path"},
{"javascript://is/not/linked", "javascript://is/not/linked"},
+ {"http://git.qemu.org/?p=qemu.git;a=blob;f=qapi-schema.json;hb=HEAD", `<a href="http://git.qemu.org/?p=qemu.git;a=blob;f=qapi-schema.json;hb=HEAD">http://git.qemu.org/?p=qemu.git;a=blob;f=qapi-schema.json;hb=HEAD</a>`},
}
func TestEmphasize(t *testing.T) {
diff --git a/libgo/go/go/doc/reader.go b/libgo/go/go/doc/reader.go
index e4e7b7c1c7d..8e823538689 100644
--- a/libgo/go/go/doc/reader.go
+++ b/libgo/go/go/doc/reader.go
@@ -362,6 +362,11 @@ func (r *reader) readFunc(fun *ast.FuncDecl) {
// associate methods with the receiver type, if any
if fun.Recv != nil {
// method
+ if len(fun.Recv.List) == 0 {
+ // should not happen (incorrect AST); (See issue 17788)
+ // don't show this method
+ return
+ }
recvTypeName, imp := baseTypeName(fun.Recv.List[0].Type)
if imp {
// should not happen (incorrect AST);
@@ -645,7 +650,9 @@ func (r *reader) computeMethodSets() {
func (r *reader) cleanupTypes() {
for _, t := range r.types {
visible := r.isVisible(t.name)
- if t.decl == nil && (predeclaredTypes[t.name] || visible && (t.isEmbedded || r.hasDotImp)) {
+ predeclared := predeclaredTypes[t.name]
+
+ if t.decl == nil && (predeclared || visible && (t.isEmbedded || r.hasDotImp)) {
// t.name is a predeclared type (and was not redeclared in this package),
// or it was embedded somewhere but its declaration is missing (because
// the AST is incomplete), or we have a dot-import (and all bets are off):
@@ -660,10 +667,12 @@ func (r *reader) cleanupTypes() {
r.funcs[name] = f
}
// 3) move methods
- for name, m := range t.methods {
- // don't overwrite functions with the same name - drop them
- if _, found := r.funcs[name]; !found {
- r.funcs[name] = m
+ if !predeclared {
+ for name, m := range t.methods {
+ // don't overwrite functions with the same name - drop them
+ if _, found := r.funcs[name]; !found {
+ r.funcs[name] = m
+ }
}
}
}
@@ -809,6 +818,11 @@ func noteBodies(notes []*Note) []string {
// ----------------------------------------------------------------------------
// Predeclared identifiers
+// IsPredeclared reports whether s is a predeclared identifier.
+func IsPredeclared(s string) bool {
+ return predeclaredTypes[s] || predeclaredFuncs[s] || predeclaredConstants[s]
+}
+
var predeclaredTypes = map[string]bool{
"bool": true,
"byte": true,
diff --git a/libgo/go/go/doc/testdata/issue17788.0.golden b/libgo/go/go/doc/testdata/issue17788.0.golden
new file mode 100644
index 00000000000..42c00da5041
--- /dev/null
+++ b/libgo/go/go/doc/testdata/issue17788.0.golden
@@ -0,0 +1,8 @@
+//
+PACKAGE issue17788
+
+IMPORTPATH
+ testdata/issue17788
+
+FILENAMES
+ testdata/issue17788.go
diff --git a/libgo/go/go/doc/testdata/issue17788.1.golden b/libgo/go/go/doc/testdata/issue17788.1.golden
new file mode 100644
index 00000000000..42c00da5041
--- /dev/null
+++ b/libgo/go/go/doc/testdata/issue17788.1.golden
@@ -0,0 +1,8 @@
+//
+PACKAGE issue17788
+
+IMPORTPATH
+ testdata/issue17788
+
+FILENAMES
+ testdata/issue17788.go
diff --git a/libgo/go/go/doc/testdata/issue17788.2.golden b/libgo/go/go/doc/testdata/issue17788.2.golden
new file mode 100644
index 00000000000..42c00da5041
--- /dev/null
+++ b/libgo/go/go/doc/testdata/issue17788.2.golden
@@ -0,0 +1,8 @@
+//
+PACKAGE issue17788
+
+IMPORTPATH
+ testdata/issue17788
+
+FILENAMES
+ testdata/issue17788.go
diff --git a/libgo/go/go/doc/testdata/issue17788.go b/libgo/go/go/doc/testdata/issue17788.go
new file mode 100644
index 00000000000..883ad5f7695
--- /dev/null
+++ b/libgo/go/go/doc/testdata/issue17788.go
@@ -0,0 +1,8 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package issue17788
+
+func ( /* receiver type */ ) f0() {
+}
diff --git a/libgo/go/go/doc/testdata/predeclared.0.golden b/libgo/go/go/doc/testdata/predeclared.0.golden
new file mode 100644
index 00000000000..9f37b069f07
--- /dev/null
+++ b/libgo/go/go/doc/testdata/predeclared.0.golden
@@ -0,0 +1,8 @@
+// Package predeclared is a go/doc test for handling of exported ...
+PACKAGE predeclared
+
+IMPORTPATH
+ testdata/predeclared
+
+FILENAMES
+ testdata/predeclared.go
diff --git a/libgo/go/go/doc/testdata/predeclared.1.golden b/libgo/go/go/doc/testdata/predeclared.1.golden
new file mode 100644
index 00000000000..2ff8ee666bd
--- /dev/null
+++ b/libgo/go/go/doc/testdata/predeclared.1.golden
@@ -0,0 +1,22 @@
+// Package predeclared is a go/doc test for handling of exported ...
+PACKAGE predeclared
+
+IMPORTPATH
+ testdata/predeclared
+
+FILENAMES
+ testdata/predeclared.go
+
+TYPES
+ //
+ type bool int
+
+ // Must not be visible.
+ func (b bool) String() string
+
+ //
+ type error struct{}
+
+ // Must not be visible.
+ func (e error) Error() string
+
diff --git a/libgo/go/go/doc/testdata/predeclared.2.golden b/libgo/go/go/doc/testdata/predeclared.2.golden
new file mode 100644
index 00000000000..9f37b069f07
--- /dev/null
+++ b/libgo/go/go/doc/testdata/predeclared.2.golden
@@ -0,0 +1,8 @@
+// Package predeclared is a go/doc test for handling of exported ...
+PACKAGE predeclared
+
+IMPORTPATH
+ testdata/predeclared
+
+FILENAMES
+ testdata/predeclared.go
diff --git a/libgo/go/go/doc/testdata/predeclared.go b/libgo/go/go/doc/testdata/predeclared.go
new file mode 100644
index 00000000000..c6dd806cba0
--- /dev/null
+++ b/libgo/go/go/doc/testdata/predeclared.go
@@ -0,0 +1,22 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package predeclared is a go/doc test for handling of
+// exported methods on locally-defined predeclared types.
+// See issue 9860.
+package predeclared
+
+type error struct{}
+
+// Must not be visible.
+func (e error) Error() string {
+ return ""
+}
+
+type bool int
+
+// Must not be visible.
+func (b bool) String() string {
+ return ""
+}
diff --git a/libgo/go/go/format/format_test.go b/libgo/go/go/format/format_test.go
index b5817a5dd18..72b8d5aeeb5 100644
--- a/libgo/go/go/format/format_test.go
+++ b/libgo/go/go/format/format_test.go
@@ -6,9 +6,11 @@ package format
import (
"bytes"
+ "fmt"
"go/parser"
"go/token"
"io/ioutil"
+ "log"
"strings"
"testing"
)
@@ -143,3 +145,28 @@ func TestPartial(t *testing.T) {
}
}
}
+
+func ExampleNode() {
+ const expr = "(6+2*3)/4"
+
+ // parser.ParseExpr parses the argument and returns the
+ // corresponding ast.Node.
+ node, err := parser.ParseExpr(expr)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Create a FileSet for node. Since the node does not come
+ // from a real source file, fset will be empty.
+ fset := token.NewFileSet()
+
+ var buf bytes.Buffer
+ err = Node(&buf, fset, node)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println(buf.String())
+
+ // Output: (6 + 2*3) / 4
+}
diff --git a/libgo/go/go/internal/gccgoimporter/importer.go b/libgo/go/go/internal/gccgoimporter/importer.go
index 19b9c735686..a22d8fed90e 100644
--- a/libgo/go/go/internal/gccgoimporter/importer.go
+++ b/libgo/go/go/internal/gccgoimporter/importer.go
@@ -63,6 +63,7 @@ func findExportFile(searchpaths []string, pkgpath string) (string, error) {
const (
gccgov1Magic = "v1;\n"
+ gccgov2Magic = "v2;\n"
goimporterMagic = "\n$$ "
archiveMagic = "!<ar"
)
@@ -91,7 +92,7 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e
var elfreader io.ReaderAt
switch string(magic[:]) {
- case gccgov1Magic, goimporterMagic:
+ case gccgov1Magic, gccgov2Magic, goimporterMagic:
// Raw export data.
reader = f
return
@@ -168,7 +169,7 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo
}
switch string(magic[:]) {
- case gccgov1Magic:
+ case gccgov1Magic, gccgov2Magic:
var p parser
p.init(fpath, reader, imports)
pkg = p.parsePackage()
diff --git a/libgo/go/go/internal/gccgoimporter/importer_test.go b/libgo/go/go/internal/gccgoimporter/importer_test.go
index c10fa484e39..2b454701beb 100644
--- a/libgo/go/go/internal/gccgoimporter/importer_test.go
+++ b/libgo/go/go/internal/gccgoimporter/importer_test.go
@@ -95,8 +95,12 @@ var importerTests = [...]importerTest{
{pkgpath: "complexnums", name: "NP", want: "const NP untyped complex", wantval: "(-1 + 1i)"},
{pkgpath: "complexnums", name: "PN", want: "const PN untyped complex", wantval: "(1 + -1i)"},
{pkgpath: "complexnums", name: "PP", want: "const PP untyped complex", wantval: "(1 + 1i)"},
- // TODO: enable this entry once bug has been tracked down
- //{pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}},
+ {pkgpath: "conversions", name: "Bits", want: "const Bits Units", wantval: `"bits"`},
+ {pkgpath: "time", name: "Duration", want: "type Duration int64"},
+ {pkgpath: "time", name: "Nanosecond", want: "const Nanosecond Duration", wantval: "1"},
+ {pkgpath: "unicode", name: "IsUpper", want: "func IsUpper(r rune) bool"},
+ {pkgpath: "unicode", name: "MaxRune", want: "const MaxRune untyped rune", wantval: "1114111"},
+ {pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}},
}
func TestGoxImporter(t *testing.T) {
diff --git a/libgo/go/go/internal/gccgoimporter/parser.go b/libgo/go/go/internal/gccgoimporter/parser.go
index c06cce435b1..3b97c96d433 100644
--- a/libgo/go/go/internal/gccgoimporter/parser.go
+++ b/libgo/go/go/internal/gccgoimporter/parser.go
@@ -19,6 +19,7 @@ import (
type parser struct {
scanner scanner.Scanner
+ version string // format version
tok rune // current token
lit string // literal string; only valid for Ident, Int, String tokens
pkgpath string // package path of imported package
@@ -245,9 +246,20 @@ func (p *parser) parseVar(pkg *types.Package) *types.Var {
return types.NewVar(token.NoPos, pkg, name, p.parseType(pkg))
}
-// ConstValue = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) .
+// Conversion = "convert" "(" Type "," ConstValue ")" .
+func (p *parser) parseConversion(pkg *types.Package) (val constant.Value, typ types.Type) {
+ p.expectKeyword("convert")
+ p.expect('(')
+ typ = p.parseType(pkg)
+ p.expect(',')
+ val, _ = p.parseConstValue(pkg)
+ p.expect(')')
+ return
+}
+
+// ConstValue = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) | Conversion .
// FloatOrComplex = float ["i" | ("+"|"-") float "i"] .
-func (p *parser) parseConstValue() (val constant.Value, typ types.Type) {
+func (p *parser) parseConstValue(pkg *types.Package) (val constant.Value, typ types.Type) {
switch p.tok {
case scanner.String:
str := p.parseString()
@@ -262,6 +274,9 @@ func (p *parser) parseConstValue() (val constant.Value, typ types.Type) {
case "true":
b = true
+ case "convert":
+ return p.parseConversion(pkg)
+
default:
p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit)
}
@@ -348,7 +363,7 @@ func (p *parser) parseConst(pkg *types.Package) *types.Const {
typ = p.parseType(pkg)
}
p.expect('=')
- val, vtyp := p.parseConstValue()
+ val, vtyp := p.parseConstValue(pkg)
if typ == nil {
typ = vtyp
}
@@ -696,7 +711,10 @@ func (p *parser) parseType(pkg *types.Package) (t types.Type) {
func (p *parser) parsePackageInit() PackageInit {
name := p.parseUnquotedString()
initfunc := p.parseUnquotedString()
- priority := int(p.parseInt())
+ priority := -1
+ if p.version == "v1" {
+ priority = int(p.parseInt())
+ }
return PackageInit{Name: name, InitFunc: initfunc, Priority: priority}
}
@@ -723,7 +741,7 @@ func (p *parser) maybeCreatePackage() {
}
}
-// InitDataDirective = "v1" ";" |
+// InitDataDirective = ( "v1" | "v2" ) ";" |
// "priority" int ";" |
// "init" { PackageInit } ";" |
// "checksum" unquotedString ";" .
@@ -734,7 +752,8 @@ func (p *parser) parseInitDataDirective() {
}
switch p.lit {
- case "v1":
+ case "v1", "v2":
+ p.version = p.lit
p.next()
p.expect(';')
@@ -750,6 +769,15 @@ func (p *parser) parseInitDataDirective() {
}
p.expect(';')
+ case "init_graph":
+ p.next()
+ // The graph data is thrown away for now.
+ for p.tok != ';' && p.tok != scanner.EOF {
+ p.parseInt()
+ p.parseInt()
+ }
+ p.expect(';')
+
case "checksum":
// Don't let the scanner try to parse the checksum as a number.
defer func(mode uint) {
@@ -766,8 +794,9 @@ func (p *parser) parseInitDataDirective() {
}
// Directive = InitDataDirective |
-// "package" unquotedString ";" |
+// "package" unquotedString [ unquotedString ] [ unquotedString ] ";" |
// "pkgpath" unquotedString ";" |
+// "prefix" unquotedString ";" |
// "import" unquotedString unquotedString string ";" |
// "func" Func ";" |
// "type" Type ";" |
@@ -780,13 +809,17 @@ func (p *parser) parseDirective() {
}
switch p.lit {
- case "v1", "priority", "init", "checksum":
+ case "v1", "v2", "priority", "init", "init_graph", "checksum":
p.parseInitDataDirective()
case "package":
p.next()
p.pkgname = p.parseUnquotedString()
p.maybeCreatePackage()
+ if p.version == "v2" && p.tok != ';' {
+ p.parseUnquotedString()
+ p.parseUnquotedString()
+ }
p.expect(';')
case "pkgpath":
@@ -795,6 +828,11 @@ func (p *parser) parseDirective() {
p.maybeCreatePackage()
p.expect(';')
+ case "prefix":
+ p.next()
+ p.pkgpath = p.parseUnquotedString()
+ p.expect(';')
+
case "import":
p.next()
pkgname := p.parseUnquotedString()
diff --git a/libgo/go/go/internal/gccgoimporter/testdata/conversions.go b/libgo/go/go/internal/gccgoimporter/testdata/conversions.go
new file mode 100644
index 00000000000..653927ad670
--- /dev/null
+++ b/libgo/go/go/internal/gccgoimporter/testdata/conversions.go
@@ -0,0 +1,5 @@
+package conversions
+
+type Units string
+
+const Bits = Units("bits")
diff --git a/libgo/go/go/internal/gcimporter/bimport.go b/libgo/go/go/internal/gcimporter/bimport.go
index 75c2d9123e9..a8f349052ac 100644
--- a/libgo/go/go/internal/gcimporter/bimport.go
+++ b/libgo/go/go/internal/gcimporter/bimport.go
@@ -11,7 +11,9 @@ import (
"go/token"
"go/types"
"sort"
+ "strconv"
"strings"
+ "sync"
"unicode"
"unicode/utf8"
)
@@ -21,7 +23,7 @@ type importer struct {
data []byte
path string
buf []byte // for reading strings
- version string
+ version int // export format version
// object lists
strList []string // in order of appearance
@@ -33,6 +35,8 @@ type importer struct {
posInfoFormat bool
prevFile string
prevLine int
+ fset *token.FileSet
+ files map[string]*token.File
// debugging support
debugFormat bool
@@ -41,37 +45,74 @@ type importer struct {
// BImportData imports a package from the serialized package data
// and returns the number of bytes consumed and a reference to the package.
-// If data is obviously malformed, an error is returned but in
-// general it is not recommended to call BImportData on untrusted data.
-func BImportData(imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {
+// If the export data version is not recognized or the format is otherwise
+// compromised, an error is returned.
+func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, _ *types.Package, err error) {
+ // catch panics and return them as errors
+ defer func() {
+ if e := recover(); e != nil {
+ // The package (filename) causing the problem is added to this
+ // error by a wrapper in the caller (Import in gcimporter.go).
+ err = fmt.Errorf("cannot import, possibly version skew (%v) - reinstall package", e)
+ }
+ }()
+
p := importer{
imports: imports,
data: data,
path: path,
+ version: -1, // unknown version
strList: []string{""}, // empty string is mapped to 0
+ fset: fset,
+ files: make(map[string]*token.File),
+ }
+
+ // read version info
+ var versionstr string
+ if b := p.rawByte(); b == 'c' || b == 'd' {
+ // Go1.7 encoding; first byte encodes low-level
+ // encoding format (compact vs debug).
+ // For backward-compatibility only (avoid problems with
+ // old installed packages). Newly compiled packages use
+ // the extensible format string.
+ // TODO(gri) Remove this support eventually; after Go1.8.
+ if b == 'd' {
+ p.debugFormat = true
+ }
+ p.trackAllTypes = p.rawByte() == 'a'
+ p.posInfoFormat = p.int() != 0
+ versionstr = p.string()
+ if versionstr == "v1" {
+ p.version = 0
+ }
+ } else {
+ // Go1.8 extensible encoding
+ // read version string and extract version number (ignore anything after the version number)
+ versionstr = p.rawStringln(b)
+ if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" {
+ if v, err := strconv.Atoi(s[1]); err == nil && v > 0 {
+ p.version = v
+ }
+ }
}
- // read low-level encoding format
- switch format := p.rawByte(); format {
- case 'c':
- // compact format - nothing to do
- case 'd':
- p.debugFormat = true
+ // read version specific flags - extend as necessary
+ switch p.version {
+ // case 4:
+ // ...
+ // fallthrough
+ case 3, 2, 1:
+ p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
+ p.trackAllTypes = p.int() != 0
+ p.posInfoFormat = p.int() != 0
+ case 0:
+ // Go1.7 encoding format - nothing to do here
default:
- return p.read, nil, fmt.Errorf("invalid encoding format in export data: got %q; want 'c' or 'd'", format)
+ errorf("unknown export format version %d (%q)", p.version, versionstr)
}
- p.trackAllTypes = p.rawByte() == 'a'
-
- p.posInfoFormat = p.int() != 0
-
// --- generic export data ---
- p.version = p.string()
- if p.version != "v0" && p.version != "v1" {
- return p.read, nil, fmt.Errorf("unknown export data version: %s", p.version)
- }
-
// populate typList with predeclared "known" types
p.typList = append(p.typList, predeclared...)
@@ -91,7 +132,7 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (i
// self-verification
if count := p.int(); count != objcount {
- panic(fmt.Sprintf("got %d objects; want %d", objcount, count))
+ errorf("got %d objects; want %d", objcount, count)
}
// ignore compiler-specific import data
@@ -119,6 +160,10 @@ func BImportData(imports map[string]*types.Package, data []byte, path string) (i
return p.read, pkg, nil
}
+func errorf(format string, args ...interface{}) {
+ panic(fmt.Sprintf(format, args...))
+}
+
func (p *importer) pkg() *types.Package {
// if the package was seen before, i is its index (>= 0)
i := p.tagOrIndex()
@@ -128,7 +173,7 @@ func (p *importer) pkg() *types.Package {
// otherwise, i is the package tag (< 0)
if i != packageTag {
- panic(fmt.Sprintf("unexpected package tag %d", i))
+ errorf("unexpected package tag %d", i)
}
// read package data
@@ -137,13 +182,13 @@ func (p *importer) pkg() *types.Package {
// we should never see an empty package name
if name == "" {
- panic("empty package name in import")
+ errorf("empty package name in import")
}
// an empty path denotes the package we are currently importing;
// it must be the first package we see
if (path == "") != (len(p.pkgList) == 0) {
- panic(fmt.Sprintf("package path %q for pkg index %d", path, len(p.pkgList)))
+ errorf("package path %q for pkg index %d", path, len(p.pkgList))
}
// if the package was imported before, use that one; otherwise create a new one
@@ -155,61 +200,104 @@ func (p *importer) pkg() *types.Package {
pkg = types.NewPackage(path, name)
p.imports[path] = pkg
} else if pkg.Name() != name {
- panic(fmt.Sprintf("conflicting names %s and %s for package %q", pkg.Name(), name, path))
+ errorf("conflicting names %s and %s for package %q", pkg.Name(), name, path)
}
p.pkgList = append(p.pkgList, pkg)
return pkg
}
+// objTag returns the tag value for each object kind.
+// obj must not be a *types.Alias.
+func objTag(obj types.Object) int {
+ switch obj.(type) {
+ case *types.Const:
+ return constTag
+ case *types.TypeName:
+ return typeTag
+ case *types.Var:
+ return varTag
+ case *types.Func:
+ return funcTag
+ // Aliases are not exported multiple times, thus we should not see them here.
+ default:
+ errorf("unexpected object: %v (%T)", obj, obj) // panics
+ panic("unreachable")
+ }
+}
+
+func sameObj(a, b types.Object) bool {
+ // Because unnamed types are not canonicalized, we cannot simply compare types for
+ // (pointer) identity.
+ // Ideally we'd check equality of constant values as well, but this is good enough.
+ return objTag(a) == objTag(b) && types.Identical(a.Type(), b.Type())
+}
+
func (p *importer) declare(obj types.Object) {
pkg := obj.Pkg()
if alt := pkg.Scope().Insert(obj); alt != nil {
- // This could only trigger if we import a (non-type) object a second time.
- // This should never happen because 1) we only import a package once; and
- // b) we ignore compiler-specific export data which may contain functions
- // whose inlined function bodies refer to other functions that were already
- // imported.
- // (See also the comment in cmd/compile/internal/gc/bimport.go importer.obj,
- // switch case importing functions).
- panic(fmt.Sprintf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", alt, obj))
+ // This can only trigger if we import a (non-type) object a second time.
+ // Excluding aliases, this cannot happen because 1) we only import a package
+ // once; and b) we ignore compiler-specific export data which may contain
+ // functions whose inlined function bodies refer to other functions that
+ // were already imported.
+ // However, aliases require reexporting the original object, so we need
+ // to allow it (see also the comment in cmd/compile/internal/gc/bimport.go,
+ // method importer.obj, switch case importing functions).
+ // Note that the original itself cannot be an alias.
+ if !sameObj(obj, alt) {
+ errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", obj, alt)
+ }
}
}
func (p *importer) obj(tag int) {
switch tag {
case constTag:
- p.pos()
+ pos := p.pos()
pkg, name := p.qualifiedName()
typ := p.typ(nil)
val := p.value()
- p.declare(types.NewConst(token.NoPos, pkg, name, typ, val))
+ p.declare(types.NewConst(pos, pkg, name, typ, val))
case typeTag:
- _ = p.typ(nil)
+ p.typ(nil)
case varTag:
- p.pos()
+ pos := p.pos()
pkg, name := p.qualifiedName()
typ := p.typ(nil)
- p.declare(types.NewVar(token.NoPos, pkg, name, typ))
+ p.declare(types.NewVar(pos, pkg, name, typ))
case funcTag:
- p.pos()
+ pos := p.pos()
pkg, name := p.qualifiedName()
params, isddd := p.paramList()
result, _ := p.paramList()
sig := types.NewSignature(nil, params, result, isddd)
- p.declare(types.NewFunc(token.NoPos, pkg, name, sig))
+ p.declare(types.NewFunc(pos, pkg, name, sig))
+
+ case aliasTag:
+ pos := p.pos()
+ name := p.string()
+ var orig types.Object
+ if pkg, name := p.qualifiedName(); pkg != nil {
+ orig = pkg.Scope().Lookup(name)
+ }
+ // Alias-related code. Keep for now.
+ _ = pos
+ _ = name
+ _ = orig
+ // p.declare(types.NewAlias(pos, p.pkgList[0], name, orig))
default:
- panic(fmt.Sprintf("unexpected object tag %d", tag))
+ errorf("unexpected object tag %d", tag)
}
}
-func (p *importer) pos() {
+func (p *importer) pos() token.Pos {
if !p.posInfoFormat {
- return
+ return token.NoPos
}
file := p.prevFile
@@ -225,12 +313,45 @@ func (p *importer) pos() {
}
p.prevLine = line
- // TODO(gri) register new position
+ // Synthesize a token.Pos
+
+ // Since we don't know the set of needed file positions, we
+ // reserve maxlines positions per file.
+ const maxlines = 64 * 1024
+ f := p.files[file]
+ if f == nil {
+ f = p.fset.AddFile(file, -1, maxlines)
+ p.files[file] = f
+ // Allocate the fake linebreak indices on first use.
+ // TODO(adonovan): opt: save ~512KB using a more complex scheme?
+ fakeLinesOnce.Do(func() {
+ fakeLines = make([]int, maxlines)
+ for i := range fakeLines {
+ fakeLines[i] = i
+ }
+ })
+ f.SetLines(fakeLines)
+ }
+
+ if line > maxlines {
+ line = 1
+ }
+
+ // Treat the file as if it contained only newlines
+ // and column=1: use the line number as the offset.
+ return f.Pos(line - 1)
}
+var (
+ fakeLines []int
+ fakeLinesOnce sync.Once
+)
+
func (p *importer) qualifiedName() (pkg *types.Package, name string) {
name = p.string()
- pkg = p.pkg()
+ if name != "" {
+ pkg = p.pkg()
+ }
return
}
@@ -263,19 +384,19 @@ func (p *importer) typ(parent *types.Package) types.Type {
switch i {
case namedTag:
// read type object
- p.pos()
+ pos := p.pos()
parent, name := p.qualifiedName()
scope := parent.Scope()
obj := scope.Lookup(name)
// if the object doesn't exist yet, create and insert it
if obj == nil {
- obj = types.NewTypeName(token.NoPos, parent, name, nil)
+ obj = types.NewTypeName(pos, parent, name, nil)
scope.Insert(obj)
}
if _, ok := obj.(*types.TypeName); !ok {
- panic(fmt.Sprintf("pkg = %s, name = %s => %s", parent, name, obj))
+ errorf("pkg = %s, name = %s => %s", parent, name, obj)
}
// associate new named type with obj if it doesn't exist yet
@@ -296,7 +417,7 @@ func (p *importer) typ(parent *types.Package) types.Type {
// read associated methods
for i := p.int(); i > 0; i-- {
// TODO(gri) replace this with something closer to fieldName
- p.pos()
+ pos := p.pos()
name := p.string()
if !exported(name) {
p.pkg()
@@ -305,13 +426,10 @@ func (p *importer) typ(parent *types.Package) types.Type {
recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver?
params, isddd := p.paramList()
result, _ := p.paramList()
-
- if p.version == "v1" {
- p.int() // nointerface flag - discarded
- }
+ p.int() // go:nointerface pragma - discarded
sig := types.NewSignature(recv.At(0), params, result, isddd)
- t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig))
+ t0.AddMethod(types.NewFunc(pos, parent, name, sig))
}
return t
@@ -385,7 +503,7 @@ func (p *importer) typ(parent *types.Package) types.Type {
// no embedded interfaces with gc compiler
if p.int() != 0 {
- panic("unexpected embedded interface")
+ errorf("unexpected embedded interface")
}
t := types.NewInterface(p.methodList(parent), nil)
@@ -421,14 +539,15 @@ func (p *importer) typ(parent *types.Package) types.Type {
case 3 /* Cboth */ :
dir = types.SendRecv
default:
- panic(fmt.Sprintf("unexpected channel dir %d", d))
+ errorf("unexpected channel dir %d", d)
}
val := p.typ(parent)
*t = *types.NewChan(dir, val)
return t
default:
- panic(fmt.Sprintf("unexpected type tag %d", i))
+ errorf("unexpected type tag %d", i) // panics
+ panic("unreachable")
}
}
@@ -445,7 +564,7 @@ func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags [
}
func (p *importer) field(parent *types.Package) *types.Var {
- p.pos()
+ pos := p.pos()
pkg, name := p.fieldName(parent)
typ := p.typ(parent)
@@ -459,12 +578,12 @@ func (p *importer) field(parent *types.Package) *types.Var {
case *types.Named:
name = typ.Obj().Name()
default:
- panic("anonymous field expected")
+ errorf("anonymous field expected")
}
anonymous = true
}
- return types.NewField(token.NoPos, pkg, name, typ, anonymous)
+ return types.NewField(pos, pkg, name, typ, anonymous)
}
func (p *importer) methodList(parent *types.Package) (methods []*types.Func) {
@@ -478,28 +597,28 @@ func (p *importer) methodList(parent *types.Package) (methods []*types.Func) {
}
func (p *importer) method(parent *types.Package) *types.Func {
- p.pos()
+ pos := p.pos()
pkg, name := p.fieldName(parent)
params, isddd := p.paramList()
result, _ := p.paramList()
sig := types.NewSignature(nil, params, result, isddd)
- return types.NewFunc(token.NoPos, pkg, name, sig)
+ return types.NewFunc(pos, pkg, name, sig)
}
func (p *importer) fieldName(parent *types.Package) (*types.Package, string) {
+ name := p.string()
pkg := parent
if pkg == nil {
// use the imported package instead
pkg = p.pkgList[0]
}
- name := p.string()
- if name == "" {
- return pkg, "" // anonymous
+ if p.version == 0 && name == "_" {
+ // version 0 didn't export a package for _ fields
+ return pkg, name
}
- if name == "?" || name != "_" && !exported(name) {
- // explicitly qualified field
+ if name != "" && !exported(name) {
if name == "?" {
- name = "" // anonymous
+ name = ""
}
pkg = p.pkg()
}
@@ -538,7 +657,7 @@ func (p *importer) param(named bool) (*types.Var, bool) {
if named {
name = p.string()
if name == "" {
- panic("expected named parameter")
+ errorf("expected named parameter")
}
if name != "_" {
pkg = p.pkg()
@@ -575,8 +694,11 @@ func (p *importer) value() constant.Value {
return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
case stringTag:
return constant.MakeString(p.string())
+ case unknownTag:
+ return constant.MakeUnknown()
default:
- panic(fmt.Sprintf("unexpected value tag %d", tag))
+ errorf("unexpected value tag %d", tag) // panics
+ panic("unreachable")
}
}
@@ -639,7 +761,7 @@ func (p *importer) tagOrIndex() int {
func (p *importer) int() int {
x := p.int64()
if int64(int(x)) != x {
- panic("exported integer too large")
+ errorf("exported integer too large")
}
return int(x)
}
@@ -678,24 +800,34 @@ func (p *importer) string() string {
func (p *importer) marker(want byte) {
if got := p.rawByte(); got != want {
- panic(fmt.Sprintf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read))
+ errorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)
}
pos := p.read
if n := int(p.rawInt64()); n != pos {
- panic(fmt.Sprintf("incorrect position: got %d; want %d", n, pos))
+ errorf("incorrect position: got %d; want %d", n, pos)
}
}
-// rawInt64 should only be used by low-level decoders
+// rawInt64 should only be used by low-level decoders.
func (p *importer) rawInt64() int64 {
i, err := binary.ReadVarint(p)
if err != nil {
- panic(fmt.Sprintf("read error: %v", err))
+ errorf("read error: %v", err)
}
return i
}
+// rawStringln should only be used to read the initial version string.
+func (p *importer) rawStringln(b byte) string {
+ p.buf = p.buf[:0]
+ for b != '\n' {
+ p.buf = append(p.buf, b)
+ b = p.rawByte()
+ }
+ return string(p.buf)
+}
+
// needed for binary.ReadVarint in rawInt64
func (p *importer) ReadByte() (byte, error) {
return p.rawByte(), nil
@@ -716,7 +848,7 @@ func (p *importer) rawByte() byte {
case '|':
// nothing to do
default:
- panic("unexpected escape sequence in export data")
+ errorf("unexpected escape sequence in export data")
}
}
p.data = p.data[r:]
@@ -758,7 +890,11 @@ const (
fractionTag // not used by gc
complexTag
stringTag
+ nilTag // only used by gc (appears in exported inlined function bodies)
unknownTag // not used by gc (only appears in packages with errors)
+
+ // Aliases
+ aliasTag
)
var predeclared = []types.Type{
diff --git a/libgo/go/go/internal/gcimporter/exportdata.go b/libgo/go/go/internal/gcimporter/exportdata.go
index 4c0d2fe7616..c12e459c3db 100644
--- a/libgo/go/go/internal/gcimporter/exportdata.go
+++ b/libgo/go/go/internal/gcimporter/exportdata.go
@@ -8,7 +8,6 @@ package gcimporter
import (
"bufio"
- "errors"
"fmt"
"io"
"strconv"
@@ -29,7 +28,7 @@ func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
size, err = strconv.Atoi(s)
if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
- err = errors.New("invalid archive header")
+ err = fmt.Errorf("invalid archive header")
return
}
name = strings.TrimSpace(string(hdr[:16]))
@@ -46,6 +45,7 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
// Read first line to make sure this is an object file.
line, err := r.ReadSlice('\n')
if err != nil {
+ err = fmt.Errorf("can't find export data (%v)", err)
return
}
@@ -58,13 +58,14 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
// First entry should be __.PKGDEF.
if name != "__.PKGDEF" {
- err = errors.New("go archive is missing __.PKGDEF")
+ err = fmt.Errorf("go archive is missing __.PKGDEF")
return
}
// Read first line of __.PKGDEF data, so that line
// is once again the first line of the input.
if line, err = r.ReadSlice('\n'); err != nil {
+ err = fmt.Errorf("can't find export data (%v)", err)
return
}
}
@@ -72,7 +73,7 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
// Now at __.PKGDEF in archive or still at beginning of file.
// Either way, line should begin with "go object ".
if !strings.HasPrefix(string(line), "go object ") {
- err = errors.New("not a go object file")
+ err = fmt.Errorf("not a Go object file")
return
}
@@ -80,6 +81,7 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
// Begins after first line starting with $$.
for line[0] != '$' {
if line, err = r.ReadSlice('\n'); err != nil {
+ err = fmt.Errorf("can't find export data (%v)", err)
return
}
}
diff --git a/libgo/go/go/internal/gcimporter/gcimporter.go b/libgo/go/go/internal/gcimporter/gcimporter.go
index 2c6e676225f..f99f0f8befe 100644
--- a/libgo/go/go/internal/gcimporter/gcimporter.go
+++ b/libgo/go/go/internal/gcimporter/gcimporter.go
@@ -7,21 +7,14 @@ package gcimporter // import "go/internal/gcimporter"
import (
"bufio"
- "errors"
"fmt"
"go/build"
"go/token"
- "io"
+ "go/types"
"io/ioutil"
"os"
"path/filepath"
- "sort"
- "strconv"
"strings"
- "text/scanner"
-
- exact "go/constant"
- "go/types"
)
// debugging/development support
@@ -86,38 +79,6 @@ func FindPkg(path, srcDir string) (filename, id string) {
return
}
-// ImportData imports a package by reading the gc-generated export data,
-// adds the corresponding package object to the packages map indexed by id,
-// and returns the object.
-//
-// The packages map must contains all packages already imported. The data
-// reader position must be the beginning of the export data section. The
-// filename is only used in error messages.
-//
-// If packages[id] contains the completely imported package, that package
-// can be used directly, and there is no need to call this function (but
-// there is also no harm but for extra time used).
-//
-func ImportData(packages map[string]*types.Package, filename, id string, data io.Reader) (pkg *types.Package, err error) {
- // support for parser error handling
- defer func() {
- switch r := recover().(type) {
- case nil:
- // nothing to do
- case importError:
- err = r
- default:
- panic(r) // internal error
- }
- }()
-
- var p parser
- p.init(filename, id, data, packages)
- pkg = p.parseExport()
-
- return
-}
-
// Import imports a gc-generated package given its import path and srcDir, adds
// the corresponding package object to the packages map, and returns the object.
// The packages map must contain all packages already imported.
@@ -146,7 +107,7 @@ func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types
f.Close()
if err != nil {
// add file name to error
- err = fmt.Errorf("reading export data: %s: %v", filename, err)
+ err = fmt.Errorf("%s: %v", filename, err)
}
}()
@@ -158,12 +119,15 @@ func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types
switch hdr {
case "$$\n":
- return ImportData(packages, filename, id, buf)
+ err = fmt.Errorf("import %q: old export format no longer supported (recompile library)", path)
case "$$B\n":
var data []byte
data, err = ioutil.ReadAll(buf)
if err == nil {
- _, pkg, err = BImportData(packages, data, id)
+ // TODO(gri): allow clients of go/importer to provide a FileSet.
+ // Or, define a new standard go/types/gcexportdata package.
+ fset := token.NewFileSet()
+ _, pkg, err = BImportData(fset, packages, data, id)
return
}
default:
@@ -173,312 +137,6 @@ func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types
return
}
-// ----------------------------------------------------------------------------
-// Parser
-
-// TODO(gri) Imported objects don't have position information.
-// Ideally use the debug table line info; alternatively
-// create some fake position (or the position of the
-// import). That way error messages referring to imported
-// objects can print meaningful information.
-
-// parser parses the exports inside a gc compiler-produced
-// object/archive file and populates its scope with the results.
-type parser struct {
- scanner scanner.Scanner
- tok rune // current token
- lit string // literal string; only valid for Ident, Int, String tokens
- id string // package id of imported package
- sharedPkgs map[string]*types.Package // package id -> package object (across importer)
- localPkgs map[string]*types.Package // package id -> package object (just this package)
-}
-
-func (p *parser) init(filename, id string, src io.Reader, packages map[string]*types.Package) {
- p.scanner.Init(src)
- p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
- p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
- p.scanner.Whitespace = 1<<'\t' | 1<<' '
- p.scanner.Filename = filename // for good error messages
- p.next()
- p.id = id
- p.sharedPkgs = packages
- if debug {
- // check consistency of packages map
- for _, pkg := range packages {
- if pkg.Name() == "" {
- fmt.Printf("no package name for %s\n", pkg.Path())
- }
- }
- }
-}
-
-func (p *parser) next() {
- p.tok = p.scanner.Scan()
- switch p.tok {
- case scanner.Ident, scanner.Int, scanner.Char, scanner.String, '·':
- p.lit = p.scanner.TokenText()
- default:
- p.lit = ""
- }
- if debug {
- fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
- }
-}
-
-func declTypeName(pkg *types.Package, name string) *types.TypeName {
- scope := pkg.Scope()
- if obj := scope.Lookup(name); obj != nil {
- return obj.(*types.TypeName)
- }
- obj := types.NewTypeName(token.NoPos, pkg, name, nil)
- // a named type may be referred to before the underlying type
- // is known - set it up
- types.NewNamed(obj, nil, nil)
- scope.Insert(obj)
- return obj
-}
-
-// ----------------------------------------------------------------------------
-// Error handling
-
-// Internal errors are boxed as importErrors.
-type importError struct {
- pos scanner.Position
- err error
-}
-
-func (e importError) Error() string {
- return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
-}
-
-func (p *parser) error(err interface{}) {
- if s, ok := err.(string); ok {
- err = errors.New(s)
- }
- // panic with a runtime.Error if err is not an error
- panic(importError{p.scanner.Pos(), err.(error)})
-}
-
-func (p *parser) errorf(format string, args ...interface{}) {
- p.error(fmt.Sprintf(format, args...))
-}
-
-func (p *parser) expect(tok rune) string {
- lit := p.lit
- if p.tok != tok {
- p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
- }
- p.next()
- return lit
-}
-
-func (p *parser) expectSpecial(tok string) {
- sep := 'x' // not white space
- i := 0
- for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' {
- sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
- p.next()
- i++
- }
- if i < len(tok) {
- p.errorf("expected %q, got %q", tok, tok[0:i])
- }
-}
-
-func (p *parser) expectKeyword(keyword string) {
- lit := p.expect(scanner.Ident)
- if lit != keyword {
- p.errorf("expected keyword %s, got %q", keyword, lit)
- }
-}
-
-// ----------------------------------------------------------------------------
-// Qualified and unqualified names
-
-// PackageId = string_lit .
-//
-func (p *parser) parsePackageId() string {
- id, err := strconv.Unquote(p.expect(scanner.String))
- if err != nil {
- p.error(err)
- }
- // id == "" stands for the imported package id
- // (only known at time of package installation)
- if id == "" {
- id = p.id
- }
- return id
-}
-
-// PackageName = ident .
-//
-func (p *parser) parsePackageName() string {
- return p.expect(scanner.Ident)
-}
-
-// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
-func (p *parser) parseDotIdent() string {
- ident := ""
- if p.tok != scanner.Int {
- sep := 'x' // not white space
- for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
- ident += p.lit
- sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
- p.next()
- }
- }
- if ident == "" {
- p.expect(scanner.Ident) // use expect() for error handling
- }
- return ident
-}
-
-// QualifiedName = "@" PackageId "." ( "?" | dotIdentifier ) .
-//
-func (p *parser) parseQualifiedName() (id, name string) {
- p.expect('@')
- id = p.parsePackageId()
- p.expect('.')
- // Per rev f280b8a485fd (10/2/2013), qualified names may be used for anonymous fields.
- if p.tok == '?' {
- p.next()
- } else {
- name = p.parseDotIdent()
- }
- return
-}
-
-// getPkg returns the package for a given id. If the package is
-// not found, create the package and add it to the p.localPkgs
-// and p.sharedPkgs maps. name is the (expected) name of the
-// package. If name == "", the package name is expected to be
-// set later via an import clause in the export data.
-//
-// id identifies a package, usually by a canonical package path like
-// "encoding/json" but possibly by a non-canonical import path like
-// "./json".
-//
-func (p *parser) getPkg(id, name string) *types.Package {
- // package unsafe is not in the packages maps - handle explicitly
- if id == "unsafe" {
- return types.Unsafe
- }
-
- pkg := p.localPkgs[id]
- if pkg == nil {
- // first import of id from this package
- pkg = p.sharedPkgs[id]
- if pkg == nil {
- // first import of id by this importer;
- // add (possibly unnamed) pkg to shared packages
- pkg = types.NewPackage(id, name)
- p.sharedPkgs[id] = pkg
- }
- // add (possibly unnamed) pkg to local packages
- if p.localPkgs == nil {
- p.localPkgs = make(map[string]*types.Package)
- }
- p.localPkgs[id] = pkg
- } else if name != "" {
- // package exists already and we have an expected package name;
- // make sure names match or set package name if necessary
- if pname := pkg.Name(); pname == "" {
- pkg.SetName(name)
- } else if pname != name {
- p.errorf("%s package name mismatch: %s (given) vs %s (expected)", id, pname, name)
- }
- }
- return pkg
-}
-
-// parseExportedName is like parseQualifiedName, but
-// the package id is resolved to an imported *types.Package.
-//
-func (p *parser) parseExportedName() (pkg *types.Package, name string) {
- id, name := p.parseQualifiedName()
- pkg = p.getPkg(id, "")
- return
-}
-
-// ----------------------------------------------------------------------------
-// Types
-
-// BasicType = identifier .
-//
-func (p *parser) parseBasicType() types.Type {
- id := p.expect(scanner.Ident)
- obj := types.Universe.Lookup(id)
- if obj, ok := obj.(*types.TypeName); ok {
- return obj.Type()
- }
- p.errorf("not a basic type: %s", id)
- return nil
-}
-
-// ArrayType = "[" int_lit "]" Type .
-//
-func (p *parser) parseArrayType(parent *types.Package) types.Type {
- // "[" already consumed and lookahead known not to be "]"
- lit := p.expect(scanner.Int)
- p.expect(']')
- elem := p.parseType(parent)
- n, err := strconv.ParseInt(lit, 10, 64)
- if err != nil {
- p.error(err)
- }
- return types.NewArray(elem, n)
-}
-
-// MapType = "map" "[" Type "]" Type .
-//
-func (p *parser) parseMapType(parent *types.Package) types.Type {
- p.expectKeyword("map")
- p.expect('[')
- key := p.parseType(parent)
- p.expect(']')
- elem := p.parseType(parent)
- return types.NewMap(key, elem)
-}
-
-// Name = identifier | "?" | QualifiedName .
-//
-// For unqualified and anonymous names, the returned package is the parent
-// package unless parent == nil, in which case the returned package is the
-// package being imported. (The parent package is not nil if the the name
-// is an unqualified struct field or interface method name belonging to a
-// type declared in another package.)
-//
-// For qualified names, the returned package is nil (and not created if
-// it doesn't exist yet) unless materializePkg is set (which creates an
-// unnamed package with valid package path). In the latter case, a
-// subsequent import clause is expected to provide a name for the package.
-//
-func (p *parser) parseName(parent *types.Package, materializePkg bool) (pkg *types.Package, name string) {
- pkg = parent
- if pkg == nil {
- pkg = p.sharedPkgs[p.id]
- }
- switch p.tok {
- case scanner.Ident:
- name = p.lit
- p.next()
- case '?':
- // anonymous
- p.next()
- case '@':
- // exported name prefixed with package path
- pkg = nil
- var id string
- id, name = p.parseQualifiedName()
- if materializePkg {
- pkg = p.getPkg(id, "")
- }
- default:
- p.error("name expected")
- }
- return
-}
-
func deref(typ types.Type) types.Type {
if p, _ := typ.(*types.Pointer); p != nil {
return p.Elem()
@@ -486,531 +144,6 @@ func deref(typ types.Type) types.Type {
return typ
}
-// Field = Name Type [ string_lit ] .
-//
-func (p *parser) parseField(parent *types.Package) (*types.Var, string) {
- pkg, name := p.parseName(parent, true)
- typ := p.parseType(parent)
- anonymous := false
- if name == "" {
- // anonymous field - typ must be T or *T and T must be a type name
- switch typ := deref(typ).(type) {
- case *types.Basic: // basic types are named types
- pkg = nil // objects defined in Universe scope have no package
- name = typ.Name()
- case *types.Named:
- name = typ.Obj().Name()
- default:
- p.errorf("anonymous field expected")
- }
- anonymous = true
- }
- tag := ""
- if p.tok == scanner.String {
- s := p.expect(scanner.String)
- var err error
- tag, err = strconv.Unquote(s)
- if err != nil {
- p.errorf("invalid struct tag %s: %s", s, err)
- }
- }
- return types.NewField(token.NoPos, pkg, name, typ, anonymous), tag
-}
-
-// StructType = "struct" "{" [ FieldList ] "}" .
-// FieldList = Field { ";" Field } .
-//
-func (p *parser) parseStructType(parent *types.Package) types.Type {
- var fields []*types.Var
- var tags []string
-
- p.expectKeyword("struct")
- p.expect('{')
- for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ {
- if i > 0 {
- p.expect(';')
- }
- fld, tag := p.parseField(parent)
- if tag != "" && tags == nil {
- tags = make([]string, i)
- }
- if tags != nil {
- tags = append(tags, tag)
- }
- fields = append(fields, fld)
- }
- p.expect('}')
-
- return types.NewStruct(fields, tags)
-}
-
-// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
-//
-func (p *parser) parseParameter() (par *types.Var, isVariadic bool) {
- _, name := p.parseName(nil, false)
- // remove gc-specific parameter numbering
- if i := strings.Index(name, "·"); i >= 0 {
- name = name[:i]
- }
- if p.tok == '.' {
- p.expectSpecial("...")
- isVariadic = true
- }
- typ := p.parseType(nil)
- if isVariadic {
- typ = types.NewSlice(typ)
- }
- // ignore argument tag (e.g. "noescape")
- if p.tok == scanner.String {
- p.next()
- }
- // TODO(gri) should we provide a package?
- par = types.NewVar(token.NoPos, nil, name, typ)
- return
-}
-
-// Parameters = "(" [ ParameterList ] ")" .
-// ParameterList = { Parameter "," } Parameter .
-//
-func (p *parser) parseParameters() (list []*types.Var, isVariadic bool) {
- p.expect('(')
- for p.tok != ')' && p.tok != scanner.EOF {
- if len(list) > 0 {
- p.expect(',')
- }
- par, variadic := p.parseParameter()
- list = append(list, par)
- if variadic {
- if isVariadic {
- p.error("... not on final argument")
- }
- isVariadic = true
- }
- }
- p.expect(')')
-
- return
-}
-
-// Signature = Parameters [ Result ] .
-// Result = Type | Parameters .
-//
-func (p *parser) parseSignature(recv *types.Var) *types.Signature {
- params, isVariadic := p.parseParameters()
-
- // optional result type
- var results []*types.Var
- if p.tok == '(' {
- var variadic bool
- results, variadic = p.parseParameters()
- if variadic {
- p.error("... not permitted on result type")
- }
- }
-
- return types.NewSignature(recv, types.NewTuple(params...), types.NewTuple(results...), isVariadic)
-}
-
-// InterfaceType = "interface" "{" [ MethodList ] "}" .
-// MethodList = Method { ";" Method } .
-// Method = Name Signature .
-//
-// The methods of embedded interfaces are always "inlined"
-// by the compiler and thus embedded interfaces are never
-// visible in the export data.
-//
-func (p *parser) parseInterfaceType(parent *types.Package) types.Type {
- var methods []*types.Func
-
- p.expectKeyword("interface")
- p.expect('{')
- for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ {
- if i > 0 {
- p.expect(';')
- }
- pkg, name := p.parseName(parent, true)
- sig := p.parseSignature(nil)
- methods = append(methods, types.NewFunc(token.NoPos, pkg, name, sig))
- }
- p.expect('}')
-
- // Complete requires the type's embedded interfaces to be fully defined,
- // but we do not define any
- return types.NewInterface(methods, nil).Complete()
-}
-
-// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
-//
-func (p *parser) parseChanType(parent *types.Package) types.Type {
- dir := types.SendRecv
- if p.tok == scanner.Ident {
- p.expectKeyword("chan")
- if p.tok == '<' {
- p.expectSpecial("<-")
- dir = types.SendOnly
- }
- } else {
- p.expectSpecial("<-")
- p.expectKeyword("chan")
- dir = types.RecvOnly
- }
- elem := p.parseType(parent)
- return types.NewChan(dir, elem)
-}
-
-// Type =
-// BasicType | TypeName | ArrayType | SliceType | StructType |
-// PointerType | FuncType | InterfaceType | MapType | ChanType |
-// "(" Type ")" .
-//
-// BasicType = ident .
-// TypeName = ExportedName .
-// SliceType = "[" "]" Type .
-// PointerType = "*" Type .
-// FuncType = "func" Signature .
-//
-func (p *parser) parseType(parent *types.Package) types.Type {
- switch p.tok {
- case scanner.Ident:
- switch p.lit {
- default:
- return p.parseBasicType()
- case "struct":
- return p.parseStructType(parent)
- case "func":
- // FuncType
- p.next()
- return p.parseSignature(nil)
- case "interface":
- return p.parseInterfaceType(parent)
- case "map":
- return p.parseMapType(parent)
- case "chan":
- return p.parseChanType(parent)
- }
- case '@':
- // TypeName
- pkg, name := p.parseExportedName()
- return declTypeName(pkg, name).Type()
- case '[':
- p.next() // look ahead
- if p.tok == ']' {
- // SliceType
- p.next()
- return types.NewSlice(p.parseType(parent))
- }
- return p.parseArrayType(parent)
- case '*':
- // PointerType
- p.next()
- return types.NewPointer(p.parseType(parent))
- case '<':
- return p.parseChanType(parent)
- case '(':
- // "(" Type ")"
- p.next()
- typ := p.parseType(parent)
- p.expect(')')
- return typ
- }
- p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
- return nil
-}
-
-// ----------------------------------------------------------------------------
-// Declarations
-
-// ImportDecl = "import" PackageName PackageId .
-//
-func (p *parser) parseImportDecl() {
- p.expectKeyword("import")
- name := p.parsePackageName()
- p.getPkg(p.parsePackageId(), name)
-}
-
-// int_lit = [ "+" | "-" ] { "0" ... "9" } .
-//
-func (p *parser) parseInt() string {
- s := ""
- switch p.tok {
- case '-':
- s = "-"
- p.next()
- case '+':
- p.next()
- }
- return s + p.expect(scanner.Int)
-}
-
-// number = int_lit [ "p" int_lit ] .
-//
-func (p *parser) parseNumber() (typ *types.Basic, val exact.Value) {
- // mantissa
- mant := exact.MakeFromLiteral(p.parseInt(), token.INT, 0)
- if mant == nil {
- panic("invalid mantissa")
- }
-
- if p.lit == "p" {
- // exponent (base 2)
- p.next()
- exp, err := strconv.ParseInt(p.parseInt(), 10, 0)
- if err != nil {
- p.error(err)
- }
- if exp < 0 {
- denom := exact.MakeInt64(1)
- denom = exact.Shift(denom, token.SHL, uint(-exp))
- typ = types.Typ[types.UntypedFloat]
- val = exact.BinaryOp(mant, token.QUO, denom)
- return
- }
- if exp > 0 {
- mant = exact.Shift(mant, token.SHL, uint(exp))
- }
- typ = types.Typ[types.UntypedFloat]
- val = mant
- return
- }
-
- typ = types.Typ[types.UntypedInt]
- val = mant
- return
-}
-
-// ConstDecl = "const" ExportedName [ Type ] "=" Literal .
-// Literal = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit .
-// bool_lit = "true" | "false" .
-// complex_lit = "(" float_lit "+" float_lit "i" ")" .
-// rune_lit = "(" int_lit "+" int_lit ")" .
-// string_lit = `"` { unicode_char } `"` .
-//
-func (p *parser) parseConstDecl() {
- p.expectKeyword("const")
- pkg, name := p.parseExportedName()
-
- var typ0 types.Type
- if p.tok != '=' {
- // constant types are never structured - no need for parent type
- typ0 = p.parseType(nil)
- }
-
- p.expect('=')
- var typ types.Type
- var val exact.Value
- switch p.tok {
- case scanner.Ident:
- // bool_lit
- if p.lit != "true" && p.lit != "false" {
- p.error("expected true or false")
- }
- typ = types.Typ[types.UntypedBool]
- val = exact.MakeBool(p.lit == "true")
- p.next()
-
- case '-', scanner.Int:
- // int_lit
- typ, val = p.parseNumber()
-
- case '(':
- // complex_lit or rune_lit
- p.next()
- if p.tok == scanner.Char {
- p.next()
- p.expect('+')
- typ = types.Typ[types.UntypedRune]
- _, val = p.parseNumber()
- p.expect(')')
- break
- }
- _, re := p.parseNumber()
- p.expect('+')
- _, im := p.parseNumber()
- p.expectKeyword("i")
- p.expect(')')
- typ = types.Typ[types.UntypedComplex]
- val = exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
-
- case scanner.Char:
- // rune_lit
- typ = types.Typ[types.UntypedRune]
- val = exact.MakeFromLiteral(p.lit, token.CHAR, 0)
- p.next()
-
- case scanner.String:
- // string_lit
- typ = types.Typ[types.UntypedString]
- val = exact.MakeFromLiteral(p.lit, token.STRING, 0)
- p.next()
-
- default:
- p.errorf("expected literal got %s", scanner.TokenString(p.tok))
- }
-
- if typ0 == nil {
- typ0 = typ
- }
-
- pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, typ0, val))
-}
-
-// TypeDecl = "type" ExportedName Type .
-//
-func (p *parser) parseTypeDecl() {
- p.expectKeyword("type")
- pkg, name := p.parseExportedName()
- obj := declTypeName(pkg, name)
-
- // The type object may have been imported before and thus already
- // have a type associated with it. We still need to parse the type
- // structure, but throw it away if the object already has a type.
- // This ensures that all imports refer to the same type object for
- // a given type declaration.
- typ := p.parseType(pkg)
-
- if name := obj.Type().(*types.Named); name.Underlying() == nil {
- name.SetUnderlying(typ)
- }
-}
-
-// VarDecl = "var" ExportedName Type .
-//
-func (p *parser) parseVarDecl() {
- p.expectKeyword("var")
- pkg, name := p.parseExportedName()
- typ := p.parseType(pkg)
- pkg.Scope().Insert(types.NewVar(token.NoPos, pkg, name, typ))
-}
-
-// Func = Signature [ Body ] .
-// Body = "{" ... "}" .
-//
-func (p *parser) parseFunc(recv *types.Var) *types.Signature {
- sig := p.parseSignature(recv)
- if p.tok == '{' {
- p.next()
- for i := 1; i > 0; p.next() {
- switch p.tok {
- case '{':
- i++
- case '}':
- i--
- }
- }
- }
- return sig
-}
-
-// MethodDecl = "func" Receiver Name Func .
-// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" .
-//
-func (p *parser) parseMethodDecl() {
- // "func" already consumed
- p.expect('(')
- recv, _ := p.parseParameter() // receiver
- p.expect(')')
-
- // determine receiver base type object
- base := deref(recv.Type()).(*types.Named)
-
- // parse method name, signature, and possibly inlined body
- _, name := p.parseName(nil, false)
- sig := p.parseFunc(recv)
-
- // methods always belong to the same package as the base type object
- pkg := base.Obj().Pkg()
-
- // add method to type unless type was imported before
- // and method exists already
- // TODO(gri) This leads to a quadratic algorithm - ok for now because method counts are small.
- base.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))
-}
-
-// FuncDecl = "func" ExportedName Func .
-//
-func (p *parser) parseFuncDecl() {
- // "func" already consumed
- pkg, name := p.parseExportedName()
- typ := p.parseFunc(nil)
- pkg.Scope().Insert(types.NewFunc(token.NoPos, pkg, name, typ))
-}
-
-// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
-//
-func (p *parser) parseDecl() {
- if p.tok == scanner.Ident {
- switch p.lit {
- case "import":
- p.parseImportDecl()
- case "const":
- p.parseConstDecl()
- case "type":
- p.parseTypeDecl()
- case "var":
- p.parseVarDecl()
- case "func":
- p.next() // look ahead
- if p.tok == '(' {
- p.parseMethodDecl()
- } else {
- p.parseFuncDecl()
- }
- }
- }
- p.expect('\n')
-}
-
-// ----------------------------------------------------------------------------
-// Export
-
-// Export = "PackageClause { Decl } "$$" .
-// PackageClause = "package" PackageName [ "safe" ] "\n" .
-//
-func (p *parser) parseExport() *types.Package {
- p.expectKeyword("package")
- name := p.parsePackageName()
- if p.tok == scanner.Ident && p.lit == "safe" {
- // package was compiled with -u option - ignore
- p.next()
- }
- p.expect('\n')
-
- pkg := p.getPkg(p.id, name)
-
- for p.tok != '$' && p.tok != scanner.EOF {
- p.parseDecl()
- }
-
- if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
- // don't call next()/expect() since reading past the
- // export data may cause scanner errors (e.g. NUL chars)
- p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
- }
-
- if n := p.scanner.ErrorCount; n != 0 {
- p.errorf("expected no scanner errors, got %d", n)
- }
-
- // Record all locally referenced packages as imports.
- var imports []*types.Package
- for id, pkg2 := range p.localPkgs {
- if pkg2.Name() == "" {
- p.errorf("%s package has no name", id)
- }
- if id == p.id {
- continue // avoid self-edge
- }
- imports = append(imports, pkg2)
- }
- sort.Sort(byPath(imports))
- pkg.SetImports(imports)
-
- // package was imported completely and without errors
- pkg.MarkComplete()
-
- return pkg
-}
-
type byPath []*types.Package
func (a byPath) Len() int { return len(a) }
diff --git a/libgo/go/go/internal/gcimporter/gcimporter_test.go b/libgo/go/go/internal/gcimporter/gcimporter_test.go
index d8c5bcfb1ca..a0697faeb68 100644
--- a/libgo/go/go/internal/gcimporter/gcimporter_test.go
+++ b/libgo/go/go/internal/gcimporter/gcimporter_test.go
@@ -5,6 +5,7 @@
package gcimporter
import (
+ "bytes"
"fmt"
"internal/testenv"
"io/ioutil"
@@ -34,22 +35,7 @@ func skipSpecialPlatforms(t *testing.T) {
}
func compile(t *testing.T, dirname, filename string) string {
- testenv.MustHaveGoBuild(t)
- cmd := exec.Command("go", "tool", "compile", filename)
- cmd.Dir = dirname
- out, err := cmd.CombinedOutput()
- if err != nil {
- t.Logf("%s", out)
- t.Fatalf("go tool compile %s failed: %s", filename, err)
- }
- // filename should end with ".go"
- return filepath.Join(dirname, filename[:len(filename)-2]+"o")
-}
-
-// TODO(gri) Remove this function once we switched to new export format by default.
-func compileNewExport(t *testing.T, dirname, filename string) string {
- testenv.MustHaveGoBuild(t)
- cmd := exec.Command("go", "tool", "compile", "-newexport", filename)
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", filename)
cmd.Dir = dirname
out, err := cmd.CombinedOutput()
if err != nil {
@@ -121,6 +107,8 @@ func TestImportTestdata(t *testing.T) {
// additional packages that are not strictly required for
// import processing alone (they are exported to err "on
// the safe side").
+ // TODO(gri) update the want list to be precise, now that
+ // the textual export data is gone.
got := fmt.Sprint(pkg.Imports())
for _, want := range []string{"go/ast", "go/token"} {
if !strings.Contains(got, want) {
@@ -130,27 +118,66 @@ func TestImportTestdata(t *testing.T) {
}
}
-// TODO(gri) Remove this function once we switched to new export format by default
-// (and update the comment and want list in TestImportTestdata).
-func TestImportTestdataNewExport(t *testing.T) {
+func TestVersionHandling(t *testing.T) {
+ skipSpecialPlatforms(t) // we really only need to exclude nacl platforms, but this is fine
+
// This package only handles gc export data.
if runtime.Compiler != "gc" {
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
return
}
- if outFn := compileNewExport(t, "testdata", "exports.go"); outFn != "" {
- defer os.Remove(outFn)
+ const dir = "./testdata/versions"
+ list, err := ioutil.ReadDir(dir)
+ if err != nil {
+ t.Fatal(err)
}
- if pkg := testPath(t, "./testdata/exports", "."); pkg != nil {
- // The package's Imports list must include all packages
- // explicitly imported by exports.go, plus all packages
- // referenced indirectly via exported objects in exports.go.
- want := `[package ast ("go/ast") package token ("go/token")]`
- got := fmt.Sprint(pkg.Imports())
- if got != want {
- t.Errorf(`Package("exports").Imports() = %s, want %s`, got, want)
+ for _, f := range list {
+ name := f.Name()
+ if !strings.HasSuffix(name, ".a") {
+ continue // not a package file
+ }
+ if strings.Contains(name, "corrupted") {
+ continue // don't process a leftover corrupted file
+ }
+ pkgpath := "./" + name[:len(name)-2]
+
+ // test that export data can be imported
+ _, err := Import(make(map[string]*types.Package), pkgpath, dir)
+ if err != nil {
+ t.Errorf("import %q failed: %v", pkgpath, err)
+ continue
+ }
+
+ // create file with corrupted export data
+ // 1) read file
+ data, err := ioutil.ReadFile(filepath.Join(dir, name))
+ if err != nil {
+ t.Fatal(err)
+ }
+ // 2) find export data
+ i := bytes.Index(data, []byte("\n$$B\n")) + 5
+ j := bytes.Index(data[i:], []byte("\n$$\n")) + i
+ if i < 0 || j < 0 || i > j {
+ t.Fatalf("export data section not found (i = %d, j = %d)", i, j)
+ }
+ // 3) corrupt the data (increment every 7th byte)
+ for k := j - 13; k >= i; k -= 7 {
+ data[k]++
+ }
+ // 4) write the file
+ pkgpath += "_corrupted"
+ filename := filepath.Join(dir, pkgpath) + ".a"
+ ioutil.WriteFile(filename, data, 0666)
+ defer os.Remove(filename)
+
+ // test that importing the corrupted file results in an error
+ _, err = Import(make(map[string]*types.Package), pkgpath, dir)
+ if err == nil {
+ t.Errorf("import corrupted %q succeeded", pkgpath)
+ } else if msg := err.Error(); !strings.Contains(msg, "version skew") {
+ t.Errorf("import %q error incorrect (%s)", pkgpath, msg)
}
}
}
diff --git a/libgo/go/go/internal/gcimporter/testdata/exports.go b/libgo/go/go/internal/gcimporter/testdata/exports.go
index 8ee28b0942b..9a0273ba207 100644
--- a/libgo/go/go/internal/gcimporter/testdata/exports.go
+++ b/libgo/go/go/internal/gcimporter/testdata/exports.go
@@ -7,9 +7,7 @@
package exports
-import (
- "go/ast"
-)
+import "go/ast"
// Issue 3682: Correctly read dotted identifiers from export data.
const init1 = 0
@@ -77,7 +75,8 @@ type (
var (
V0 int
- V1 = -991.0
+ V1 = -991.0
+ V2 float32 = 1.2
)
func F1() {}
diff --git a/libgo/go/go/internal/gcimporter/testdata/versions/test.go b/libgo/go/go/internal/gcimporter/testdata/versions/test.go
new file mode 100644
index 00000000000..ac9c968c2d0
--- /dev/null
+++ b/libgo/go/go/internal/gcimporter/testdata/versions/test.go
@@ -0,0 +1,25 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// To create a test case for a new export format version,
+// build this package with the latest compiler and store
+// the resulting .a file appropriately named in the versions
+// directory. The VersionHandling test will pick it up.
+//
+// In the testdata/versions:
+//
+// go build -o test_go1.$X_$Y.a test.go
+//
+// with $X = Go version and $Y = export format version.
+//
+// Make sure this source is extended such that it exercises
+// whatever export format change has taken place.
+
+package test
+
+// Any release before and including Go 1.7 didn't encode
+// the package for a blank struct field.
+type BlankField struct {
+ _ int
+}
diff --git a/libgo/go/go/parser/interface.go b/libgo/go/go/parser/interface.go
index bff79cab462..724d8658a7d 100644
--- a/libgo/go/go/parser/interface.go
+++ b/libgo/go/go/parser/interface.go
@@ -173,7 +173,7 @@ func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, m
}
// ParseExprFrom is a convenience function for parsing an expression.
-// The arguments have the same meaning as for Parse, but the source must
+// The arguments have the same meaning as for ParseFile, but the source must
// be a valid Go (type or value) expression. Specifically, fset must not
// be nil.
//
diff --git a/libgo/go/go/printer/printer.go b/libgo/go/go/printer/printer.go
index a3eaa6638e3..eabf23e8b28 100644
--- a/libgo/go/go/printer/printer.go
+++ b/libgo/go/go/printer/printer.go
@@ -712,6 +712,16 @@ func (p *printer) writeCommentSuffix(needsLinebreak bool) (wroteNewline, dropped
return
}
+// containsLinebreak reports whether the whitespace buffer contains any line breaks.
+func (p *printer) containsLinebreak() bool {
+ for _, ch := range p.wsbuf {
+ if ch == newline || ch == formfeed {
+ return true
+ }
+ }
+ return false
+}
+
// intersperseComments consumes all comments that appear before the next token
// tok and prints it together with the buffered whitespace (i.e., the whitespace
// that needs to be written before the next token). A heuristic is used to mix
@@ -730,23 +740,31 @@ 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
+ // If the last comment is a /*-style comment and the next item
// 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
+ // add an extra separator unless explicitly disabled. Use a blank
+ // as separator unless we have pending linebreaks and they are not
+ // disabled, in which case we want a linebreak (issue 15137).
+ needsLinebreak := false
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)
+ if p.containsLinebreak() && p.mode&noExtraLinebreak == 0 {
+ needsLinebreak = true
+ } else {
+ p.writeByte(' ', 1)
+ }
+ }
+ // Ensure that there is a line break after a //-style comment,
+ // before EOF, and before a closing '}' unless explicitly disabled.
+ if last.Text[1] == '/' ||
+ tok == token.EOF ||
+ tok == token.RBRACE && p.mode&noExtraLinebreak == 0 {
+ needsLinebreak = true
}
- // ensure that there is a line break after a //-style comment,
- // before a closing '}' unless explicitly disabled, or at eof
- needsLinebreak :=
- last.Text[1] == '/' ||
- tok == token.RBRACE && p.mode&noExtraLinebreak == 0 ||
- tok == token.EOF
return p.writeCommentSuffix(needsLinebreak)
}
@@ -1292,6 +1310,8 @@ func (cfg *Config) Fprint(output io.Writer, fset *token.FileSet, node interface{
// Fprint "pretty-prints" an AST node to output.
// It calls Config.Fprint with default settings.
+// Note that gofmt uses tabs for indentation but spaces for alignent;
+// use format.Node (package go/format) for output that matches gofmt.
//
func Fprint(output io.Writer, fset *token.FileSet, node interface{}) error {
return (&Config{Tabwidth: 8}).Fprint(output, fset, node)
diff --git a/libgo/go/go/printer/printer_test.go b/libgo/go/go/printer/printer_test.go
index 73f9ead5a3e..0badbfba697 100644
--- a/libgo/go/go/printer/printer_test.go
+++ b/libgo/go/go/printer/printer_test.go
@@ -197,12 +197,17 @@ var data = []entry{
}
func TestFiles(t *testing.T) {
+ t.Parallel()
for _, e := range data {
source := filepath.Join(dataDir, e.source)
golden := filepath.Join(dataDir, e.golden)
- check(t, source, golden, e.mode)
- // TODO(gri) check that golden is idempotent
- //check(t, golden, golden, e.mode)
+ mode := e.mode
+ t.Run(e.source, func(t *testing.T) {
+ t.Parallel()
+ check(t, source, golden, mode)
+ // TODO(gri) check that golden is idempotent
+ //check(t, golden, golden, e.mode)
+ })
}
}
@@ -295,6 +300,7 @@ func testComment(t *testing.T, f *ast.File, srclen int, comment *ast.Comment) {
// even if the position information of comments introducing newlines
// is incorrect.
func TestBadComments(t *testing.T) {
+ t.Parallel()
const src = `
// first comment - text and position changed by test
package p
@@ -481,6 +487,7 @@ func TestStmtLists(t *testing.T) {
}
func TestBaseIndent(t *testing.T) {
+ t.Parallel()
// The testfile must not contain multi-line raw strings since those
// are not indented (because their values must not change) and make
// this test fail.
@@ -495,28 +502,31 @@ func TestBaseIndent(t *testing.T) {
panic(err) // error in test
}
- var buf bytes.Buffer
for indent := 0; indent < 4; indent++ {
- buf.Reset()
- (&Config{Tabwidth: tabwidth, Indent: indent}).Fprint(&buf, fset, file)
- // all code must be indented by at least 'indent' tabs
- lines := bytes.Split(buf.Bytes(), []byte{'\n'})
- for i, line := range lines {
- if len(line) == 0 {
- continue // empty lines don't have indentation
- }
- n := 0
- for j, b := range line {
- if b != '\t' {
- // end of indentation
- n = j
- break
+ indent := indent
+ t.Run(fmt.Sprint(indent), func(t *testing.T) {
+ t.Parallel()
+ var buf bytes.Buffer
+ (&Config{Tabwidth: tabwidth, Indent: indent}).Fprint(&buf, fset, file)
+ // all code must be indented by at least 'indent' tabs
+ lines := bytes.Split(buf.Bytes(), []byte{'\n'})
+ for i, line := range lines {
+ if len(line) == 0 {
+ continue // empty lines don't have indentation
+ }
+ n := 0
+ for j, b := range line {
+ if b != '\t' {
+ // end of indentation
+ n = j
+ break
+ }
+ }
+ if n < indent {
+ t.Errorf("line %d: got only %d tabs; want at least %d: %q", i, n, indent, line)
}
}
- if n < indent {
- t.Errorf("line %d: got only %d tabs; want at least %d: %q", i, n, indent, line)
- }
- }
+ })
}
}
@@ -567,6 +577,7 @@ func (l *limitWriter) Write(buf []byte) (n int, err error) {
// Test whether the printer stops writing after the first error
func TestWriteErrors(t *testing.T) {
+ t.Parallel()
const filename = "printer.go"
src, err := ioutil.ReadFile(filename)
if err != nil {
diff --git a/libgo/go/go/printer/testdata/comments.golden b/libgo/go/go/printer/testdata/comments.golden
index 849fa624489..4d92e653279 100644
--- a/libgo/go/go/printer/testdata/comments.golden
+++ b/libgo/go/go/printer/testdata/comments.golden
@@ -601,6 +601,32 @@ func _() {
_ = a
}
+// Test cases from issues 11274, 15137:
+// Semicolon must not be lost when multiple statements are on the same line with a comment.
+func _() {
+ x := 0 /**/
+ y := 1
+}
+
+func _() {
+ f()
+ f()
+ f() /* comment */
+ f()
+ f() /* comment */
+ f()
+ f() /* a */ /* b */
+ f()
+ f() /* a */ /* b */
+ f()
+ f() /* a */ /* b */
+ f()
+}
+
+func _() {
+ f() /* a */ /* b */
+}
+
// Comments immediately adjacent to punctuation followed by a newline
// remain after the punctuation (looks better and permits alignment of
// comments).
diff --git a/libgo/go/go/printer/testdata/comments.input b/libgo/go/go/printer/testdata/comments.input
index 30cd23c6dd4..40351eeef69 100644
--- a/libgo/go/go/printer/testdata/comments.input
+++ b/libgo/go/go/printer/testdata/comments.input
@@ -607,6 +607,24 @@ func _() {
_ = a
}
+// Test cases from issues 11274, 15137:
+// Semicolon must not be lost when multiple statements are on the same line with a comment.
+func _() {
+ x := 0 /**/; y := 1
+}
+
+func _() {
+ f(); f()
+ f(); /* comment */ f()
+ f() /* comment */; f()
+ f(); /* a */ /* b */ f()
+ f() /* a */ /* b */; f()
+ f() /* a */; /* b */ f()
+}
+
+func _() {
+ f() /* a */ /* b */ }
+
// Comments immediately adjacent to punctuation followed by a newline
// remain after the punctuation (looks better and permits alignment of
// comments).
diff --git a/libgo/go/go/scanner/scanner.go b/libgo/go/go/scanner/scanner.go
index ce660c71d5c..a86e4eb668c 100644
--- a/libgo/go/go/scanner/scanner.go
+++ b/libgo/go/go/scanner/scanner.go
@@ -349,7 +349,11 @@ exponent:
if s.ch == '-' || s.ch == '+' {
s.next()
}
- s.scanMantissa(10)
+ if digitVal(s.ch) < 10 {
+ s.scanMantissa(10)
+ } else {
+ s.error(offs, "illegal floating-point exponent")
+ }
}
if s.ch == 'i' {
diff --git a/libgo/go/go/scanner/scanner_test.go b/libgo/go/go/scanner/scanner_test.go
index 0d21905166c..ff41c036f00 100644
--- a/libgo/go/go/scanner/scanner_test.go
+++ b/libgo/go/go/scanner/scanner_test.go
@@ -716,6 +716,7 @@ var errors = []struct {
{"078.", token.FLOAT, 0, "078.", ""},
{"07801234567.", token.FLOAT, 0, "07801234567.", ""},
{"078e0", token.FLOAT, 0, "078e0", ""},
+ {"0E", token.FLOAT, 0, "0E", "illegal floating-point exponent"}, // issue 17621
{"078", token.INT, 0, "078", "illegal octal number"},
{"07800000009", token.INT, 0, "07800000009", "illegal octal number"},
{"0x", token.INT, 0, "0x", "illegal hexadecimal number"},
diff --git a/libgo/go/go/token/position.go b/libgo/go/go/token/position.go
index 7306083b0dd..d4171d80e0c 100644
--- a/libgo/go/go/token/position.go
+++ b/libgo/go/go/token/position.go
@@ -446,7 +446,9 @@ func (s *FileSet) File(p Pos) (f *File) {
func (s *FileSet) PositionFor(p Pos, adjusted bool) (pos Position) {
if p != NoPos {
if f := s.file(p); f != nil {
+ s.mutex.RLock()
pos = f.position(p, adjusted)
+ s.mutex.RUnlock()
}
}
return
diff --git a/libgo/go/go/token/position_test.go b/libgo/go/go/token/position_test.go
index d26939ce277..63984bc872c 100644
--- a/libgo/go/go/token/position_test.go
+++ b/libgo/go/go/token/position_test.go
@@ -214,7 +214,7 @@ func TestFileSetCacheUnlikely(t *testing.T) {
}
}
-// issue 4345. Test concurrent use of FileSet.Pos does not trigger a
+// issue 4345. Test that concurrent use of FileSet.Pos does not trigger a
// race in the FileSet position cache.
func TestFileSetRace(t *testing.T) {
fset := NewFileSet()
@@ -237,6 +237,35 @@ func TestFileSetRace(t *testing.T) {
stop.Wait()
}
+// issue 16548. Test that concurrent use of File.AddLine and FileSet.PositionFor
+// does not trigger a race in the FileSet position cache.
+func TestFileSetRace2(t *testing.T) {
+ const N = 1e3
+ var (
+ fset = NewFileSet()
+ file = fset.AddFile("", -1, N)
+ ch = make(chan int, 2)
+ )
+
+ go func() {
+ for i := 0; i < N; i++ {
+ file.AddLine(i)
+ }
+ ch <- 1
+ }()
+
+ go func() {
+ pos := file.Pos(0)
+ for i := 0; i < N; i++ {
+ fset.PositionFor(pos, false)
+ }
+ ch <- 1
+ }()
+
+ <-ch
+ <-ch
+}
+
func TestPositionFor(t *testing.T) {
src := []byte(`
foo
diff --git a/libgo/go/go/types/api.go b/libgo/go/go/types/api.go
index ca109f0a80f..5b911cb96cc 100644
--- a/libgo/go/go/types/api.go
+++ b/libgo/go/go/types/api.go
@@ -5,7 +5,7 @@
// Package types declares the data types and implements
// the algorithms for type-checking of Go packages. Use
// Config.Check to invoke the type checker for a package.
-// Alternatively, create a new type checked with NewChecker
+// Alternatively, create a new type checker with NewChecker
// and invoke it incrementally by calling Checker.Files.
//
// Type-checking consists of several interdependent phases:
@@ -135,7 +135,8 @@ type Config struct {
// be incomplete.
type Info struct {
// Types maps expressions to their types, and for constant
- // expressions, their values. Invalid expressions are omitted.
+ // expressions, also their values. Invalid expressions are
+ // omitted.
//
// For (possibly parenthesized) identifiers denoting built-in
// functions, the recorded signatures are call-site specific:
@@ -143,9 +144,13 @@ type Info struct {
// an argument-specific signature. Otherwise, the recorded type
// is invalid.
//
- // Identifiers on the lhs of declarations (i.e., the identifiers
- // which are being declared) are collected in the Defs map.
- // Identifiers denoting packages are collected in the Uses maps.
+ // The Types map does not record the type of every identifier,
+ // only those that appear where an arbitrary expression is
+ // permitted. For instance, the identifier f in a selector
+ // expression x.f is found only in the Selections map, the
+ // identifier z in a variable declaration 'var z int' is found
+ // only in the Defs map, and identifiers denoting packages in
+ // qualified identifiers are collected in the Uses map.
Types map[ast.Expr]TypeAndValue
// Defs maps identifiers to the objects they define (including
diff --git a/libgo/go/go/types/api_test.go b/libgo/go/go/types/api_test.go
index 33cdb5d62c0..818a51993ed 100644
--- a/libgo/go/go/types/api_test.go
+++ b/libgo/go/go/types/api_test.go
@@ -172,13 +172,11 @@ func TestTypesInfo(t *testing.T) {
`x.(int)`,
`(int, bool)`,
},
- // TODO(gri): uncomment if we accept issue 8189.
- // {`package p2; type mybool bool; var m map[string]complex128; var b mybool; func _() { _, b = m["foo"] }`,
- // `m["foo"]`,
- // `(complex128, p2.mybool)`,
- // },
- // TODO(gri): remove if we accept issue 8189.
- {`package p2; var m map[string]complex128; var b bool; func _() { _, b = m["foo"] }`,
+ {`package p2a; type mybool bool; var m map[string]complex128; var b mybool; func _() { _, b = m["foo"] }`,
+ `m["foo"]`,
+ `(complex128, p2a.mybool)`,
+ },
+ {`package p2b; var m map[string]complex128; var b bool; func _() { _, b = m["foo"] }`,
`m["foo"]`,
`(complex128, bool)`,
},
@@ -574,26 +572,25 @@ func TestInitOrderInfo(t *testing.T) {
"a = next()", "b = next()", "c = next()", "d = next()", "e = next()", "f = next()", "_ = makeOrder()",
}},
// test case for issue 10709
- // TODO(gri) enable once the issue is fixed
- // {`package p13
-
- // var (
- // v = t.m()
- // t = makeT(0)
- // )
-
- // type T struct{}
-
- // func (T) m() int { return 0 }
-
- // func makeT(n int) T {
- // if n > 0 {
- // return makeT(n-1)
- // }
- // return T{}
- // }`, []string{
- // "t = makeT(0)", "v = t.m()",
- // }},
+ {`package p13
+
+ var (
+ v = t.m()
+ t = makeT(0)
+ )
+
+ type T struct{}
+
+ func (T) m() int { return 0 }
+
+ func makeT(n int) T {
+ if n > 0 {
+ return makeT(n-1)
+ }
+ return T{}
+ }`, []string{
+ "t = makeT(0)", "v = t.m()",
+ }},
// test case for issue 10709: same as test before, but variable decls swapped
{`package p14
@@ -614,6 +611,24 @@ func TestInitOrderInfo(t *testing.T) {
}`, []string{
"t = makeT(0)", "v = t.m()",
}},
+ // another candidate possibly causing problems with issue 10709
+ {`package p15
+
+ var y1 = f1()
+
+ func f1() int { return g1() }
+ func g1() int { f1(); return x1 }
+
+ var x1 = 0
+
+ var y2 = f2()
+
+ func f2() int { return g2() }
+ func g2() int { return x2 }
+
+ var x2 = 0`, []string{
+ "x1 = 0", "y1 = f1()", "x2 = 0", "y2 = f2()",
+ }},
}
for _, test := range tests {
@@ -1003,7 +1018,11 @@ func TestScopeLookupParent(t *testing.T) {
}
var info Info
makePkg := func(path string, files ...*ast.File) {
- imports[path], _ = conf.Check(path, fset, files, &info)
+ var err error
+ imports[path], err = conf.Check(path, fset, files, &info)
+ if err != nil {
+ t.Fatal(err)
+ }
}
makePkg("lib", mustParse("package lib; var X int"))
@@ -1011,17 +1030,44 @@ func TestScopeLookupParent(t *testing.T) {
// name at that point and checks that it resolves to a decl of
// the specified kind and line number. "undef" means undefined.
mainSrc := `
+/*lib=pkgname:5*/ /*X=var:1*/ /*Pi=const:8*/ /*T=typename:9*/ /*Y=var:10*/ /*F=func:12*/
package main
+
import "lib"
-var Y = lib.X
-func f() {
- print(Y) /*Y=var:4*/
- z /*z=undef*/ := /*z=undef*/ 1 /*z=var:7*/
- print(z)
- /*f=func:5*/ /*lib=pkgname:3*/
- type /*T=undef*/ T /*T=typename:10*/ *T
+import . "lib"
+
+const Pi = 3.1415
+type T struct{}
+var Y, _ = lib.X, X
+
+func F(){
+ const pi, e = 3.1415, /*pi=undef*/ 2.71828 /*pi=const:13*/ /*e=const:13*/
+ type /*t=undef*/ t /*t=typename:14*/ *t
+ print(Y) /*Y=var:10*/
+ x, Y := Y, /*x=undef*/ /*Y=var:10*/ Pi /*x=var:16*/ /*Y=var:16*/ ; _ = x; _ = Y
+ var F = /*F=func:12*/ F /*F=var:17*/ ; _ = F
+
+ var a []int
+ for i, x := range /*i=undef*/ /*x=var:16*/ a /*i=var:20*/ /*x=var:20*/ { _ = i; _ = x }
+
+ var i interface{}
+ switch y := i.(type) { /*y=undef*/
+ case /*y=undef*/ int /*y=var:23*/ :
+ case float32, /*y=undef*/ float64 /*y=var:23*/ :
+ default /*y=var:23*/:
+ println(y)
+ }
+ /*y=undef*/
+
+ switch int := i.(type) {
+ case /*int=typename:0*/ int /*int=var:31*/ :
+ println(int)
+ default /*int=var:31*/ :
+ }
}
+/*main=undef*/
`
+
info.Uses = make(map[*ast.Ident]Object)
f := mustParse(mainSrc)
makePkg("main", f)
@@ -1127,3 +1173,279 @@ func TestIssue15305(t *testing.T) {
}
t.Errorf("CallExpr has no type")
}
+
+// TestCompositeLitTypes verifies that Info.Types registers the correct
+// types for composite literal expressions and composite literal type
+// expressions.
+func TestCompositeLitTypes(t *testing.T) {
+ for _, test := range []struct {
+ lit, typ string
+ }{
+ {`[16]byte{}`, `[16]byte`},
+ {`[...]byte{}`, `[0]byte`}, // test for issue #14092
+ {`[...]int{1, 2, 3}`, `[3]int`}, // test for issue #14092
+ {`[...]int{90: 0, 98: 1, 2}`, `[100]int`}, // test for issue #14092
+ {`[]int{}`, `[]int`},
+ {`map[string]bool{"foo": true}`, `map[string]bool`},
+ {`struct{}{}`, `struct{}`},
+ {`struct{x, y int; z complex128}{}`, `struct{x int; y int; z complex128}`},
+ } {
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, test.lit, "package p; var _ = "+test.lit, 0)
+ if err != nil {
+ t.Fatalf("%s: %v", test.lit, err)
+ }
+
+ info := &Info{
+ Types: make(map[ast.Expr]TypeAndValue),
+ }
+ if _, err = new(Config).Check("p", fset, []*ast.File{f}, info); err != nil {
+ t.Fatalf("%s: %v", test.lit, err)
+ }
+
+ cmptype := func(x ast.Expr, want string) {
+ tv, ok := info.Types[x]
+ if !ok {
+ t.Errorf("%s: no Types entry found", test.lit)
+ return
+ }
+ if tv.Type == nil {
+ t.Errorf("%s: type is nil", test.lit)
+ return
+ }
+ if got := tv.Type.String(); got != want {
+ t.Errorf("%s: got %v, want %s", test.lit, got, want)
+ }
+ }
+
+ // test type of composite literal expression
+ rhs := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec).Values[0]
+ cmptype(rhs, test.typ)
+
+ // test type of composite literal type expression
+ cmptype(rhs.(*ast.CompositeLit).Type, test.typ)
+ }
+}
+
+// TestObjectParents verifies that objects have parent scopes or not
+// as specified by the Object interface.
+func TestObjectParents(t *testing.T) {
+ const src = `
+package p
+
+const C = 0
+
+type T1 struct {
+ a, b int
+ T2
+}
+
+type T2 interface {
+ im1()
+ im2()
+}
+
+func (T1) m1() {}
+func (*T1) m2() {}
+
+func f(x int) { y := x; print(y) }
+`
+
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, "src", src, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ info := &Info{
+ Defs: make(map[*ast.Ident]Object),
+ }
+ if _, err = new(Config).Check("p", fset, []*ast.File{f}, info); err != nil {
+ t.Fatal(err)
+ }
+
+ for ident, obj := range info.Defs {
+ if obj == nil {
+ // only package names and implicit vars have a nil object
+ // (in this test we only need to handle the package name)
+ if ident.Name != "p" {
+ t.Errorf("%v has nil object", ident)
+ }
+ continue
+ }
+
+ // struct fields, type-associated and interface methods
+ // have no parent scope
+ wantParent := true
+ switch obj := obj.(type) {
+ case *Var:
+ if obj.IsField() {
+ wantParent = false
+ }
+ case *Func:
+ if obj.Type().(*Signature).Recv() != nil { // method
+ wantParent = false
+ }
+ }
+
+ gotParent := obj.Parent() != nil
+ switch {
+ case gotParent && !wantParent:
+ t.Errorf("%v: want no parent, got %s", ident, obj.Parent())
+ case !gotParent && wantParent:
+ t.Errorf("%v: no parent found", ident)
+ }
+ }
+}
+
+// Alias-related code. Keep for now.
+/*
+func TestAliases(t *testing.T) {
+ testenv.MustHaveGoBuild(t)
+
+ const src = `
+package b
+
+import (
+ "./testdata/alias"
+ a "./testdata/alias"
+ "math"
+)
+
+const (
+ c1 = alias.Pi1
+ c2 => a.Pi1
+ c3 => a.Pi2
+ c4 => math.Pi
+)
+
+var (
+ v1 => alias.Default
+ v2 => a.Default
+ v3 = f1
+)
+
+type (
+ t1 => alias.Context
+ t2 => a.Context
+)
+
+func f1 => alias.Sin
+func f2 => a.Sin
+
+func _() {
+ assert(c1 == alias.Pi1 && c2 == a.Pi1 && c3 == a.Pi2 && c4 == math.Pi)
+ assert(c2 == c2 && c2 == c3 && c3 == c4)
+ v1 = v2 // must be assignable
+ var _ *t1 = new(t2) // must be assignable
+ var _ t2 = alias.Default
+ f1(1) // must be callable
+ f2(1)
+ _ = alias.Sin(1)
+ _ = a.Sin(1)
+}
+`
+
+ if out := compile(t, "testdata", "alias.go"); out != "" {
+ defer os.Remove(out)
+ }
+
+ DefPredeclaredTestFuncs() // declare assert built-in for testing
+ mustTypecheck(t, "Aliases", src, nil)
+}
+
+func compile(t *testing.T, dirname, filename string) string {
+ cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", filename)
+ cmd.Dir = dirname
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Logf("%s", out)
+ t.Fatalf("go tool compile %s failed: %s", filename, err)
+ }
+ // filename should end with ".go"
+ return filepath.Join(dirname, filename[:len(filename)-2]+"o")
+}
+
+func TestAliasDefUses(t *testing.T) {
+ testenv.MustHaveGoBuild(t)
+
+ const src = `
+package p
+
+import(
+ "go/build"
+ "go/types"
+)
+
+// Defs
+const Invalid => types.Invalid
+type Struct => types.Struct
+var Default => build.Default
+func Implements => types.Implements
+
+// Uses
+const _ = Invalid
+var _ types.Struct = Struct{} // types must be identical
+var _ build.Context = Default
+var _ = Implements(nil, nil)
+`
+
+ info := Info{
+ Defs: make(map[*ast.Ident]Object),
+ Uses: make(map[*ast.Ident]Object),
+ }
+ mustTypecheck(t, "TestAliasDefUses", src, &info)
+
+ // verify Defs
+ defs := map[string]string{
+ "Invalid": "types.Invalid",
+ "Struct": "types.Struct",
+ "Default": "build.Default",
+ "Implements": "types.Implements",
+ }
+
+ for ident, obj := range info.Defs {
+ if alias, ok := obj.(*Alias); ok {
+ if want := defs[ident.Name]; want != "" {
+ orig := alias.Orig()
+ if got := orig.Pkg().Name() + "." + orig.Name(); got != want {
+ t.Errorf("%v: got %v, want %v", ident, got, want)
+ }
+ delete(defs, ident.Name) // mark as found
+ } else {
+ t.Errorf("unexpected alias def of %v", ident)
+ }
+ }
+ }
+
+ if len(defs) != 0 {
+ t.Errorf("missing aliases: %v", defs)
+ }
+
+ // verify Uses
+ uses := map[string]string{
+ "Invalid": "types.Invalid",
+ "Struct": "types.Struct",
+ "Default": "build.Default",
+ "Implements": "types.Implements",
+ }
+
+ for ident, obj := range info.Uses {
+ if alias, ok := obj.(*Alias); ok {
+ if want := uses[ident.Name]; want != "" {
+ orig := alias.Orig()
+ if got := orig.Pkg().Name() + "." + orig.Name(); got != want {
+ t.Errorf("%v: got %v, want %v", ident, got, want)
+ }
+ delete(uses, ident.Name) // mark as found
+ } else {
+ t.Errorf("unexpected alias use of %v", ident)
+ }
+ }
+ }
+
+ if len(uses) != 0 {
+ t.Errorf("missing aliases: %v", defs)
+ }
+}
+*/
diff --git a/libgo/go/go/types/assignments.go b/libgo/go/go/types/assignments.go
index 6ebf3b5eab0..18f893d4781 100644
--- a/libgo/go/go/types/assignments.go
+++ b/libgo/go/go/types/assignments.go
@@ -41,7 +41,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
x.mode = invalid
return
}
- target = defaultType(x.typ)
+ target = Default(x.typ)
}
check.convertUntyped(x, target)
if x.mode == invalid {
@@ -116,7 +116,7 @@ func (check *Checker) initVar(lhs *Var, x *operand, context string) Type {
lhs.typ = Typ[Invalid]
return nil
}
- typ = defaultType(typ)
+ typ = Default(typ)
}
lhs.typ = typ
}
diff --git a/libgo/go/go/types/builtins.go b/libgo/go/go/types/builtins.go
index 0082be9e2e9..596a989a2df 100644
--- a/libgo/go/go/types/builtins.go
+++ b/libgo/go/go/types/builtins.go
@@ -434,7 +434,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
return
}
if nargs < min || min+1 < nargs {
- check.errorf(call.Pos(), "%s expects %d or %d arguments; found %d", call, min, min+1, nargs)
+ check.errorf(call.Pos(), "%v expects %d or %d arguments; found %d", call, min, min+1, nargs)
return
}
var sizes []int64 // constant integer arguments, if any
@@ -595,7 +595,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
return
}
if !constant.BoolVal(x.val) {
- check.errorf(call.Pos(), "%s failed", call)
+ check.errorf(call.Pos(), "%v failed", call)
// compile-time assertion failure - safe to continue
}
// result is constant - no need to record signature
@@ -632,7 +632,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
func makeSig(res Type, args ...Type) *Signature {
list := make([]*Var, len(args))
for i, param := range args {
- list[i] = NewVar(token.NoPos, nil, "", defaultType(param))
+ list[i] = NewVar(token.NoPos, nil, "", Default(param))
}
params := NewTuple(list...)
var result *Tuple
diff --git a/libgo/go/go/types/call.go b/libgo/go/go/types/call.go
index 45f3e9a6056..8e5c5371f22 100644
--- a/libgo/go/go/types/call.go
+++ b/libgo/go/go/types/call.go
@@ -275,24 +275,34 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
// so we don't need a "package" mode for operands: package names
// can only appear in qualified identifiers which are mapped to
// selector expressions.
+ // (see also decl.go: checker.aliasDecl)
+ // TODO(gri) factor this code out and share with checker.aliasDecl
if ident, ok := e.X.(*ast.Ident); ok {
_, obj := check.scope.LookupParent(ident.Name, check.pos)
- if pkg, _ := obj.(*PkgName); pkg != nil {
- assert(pkg.pkg == check.pkg)
- check.recordUse(ident, pkg)
- pkg.used = true
- exp := pkg.imported.scope.Lookup(sel)
+ if pname, _ := obj.(*PkgName); pname != nil {
+ assert(pname.pkg == check.pkg)
+ check.recordUse(ident, pname)
+ pname.used = true
+ pkg := pname.imported
+ exp := pkg.scope.Lookup(sel)
if exp == nil {
- if !pkg.imported.fake {
- check.errorf(e.Pos(), "%s not declared by package %s", sel, ident)
+ if !pkg.fake {
+ check.errorf(e.Pos(), "%s not declared by package %s", sel, pkg.name)
}
goto Error
}
if !exp.Exported() {
- check.errorf(e.Pos(), "%s not exported by package %s", sel, ident)
+ check.errorf(e.Pos(), "%s not exported by package %s", sel, pkg.name)
// ok to continue
}
check.recordUse(e.Sel, exp)
+ exp = original(exp)
+
+ // avoid further errors if the imported object is an alias that's broken
+ if exp == nil {
+ goto Error
+ }
+
// Simplified version of the code for *ast.Idents:
// - imported objects are always fully initialized
switch exp := exp.(type) {
@@ -315,6 +325,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
x.typ = exp.typ
x.id = exp.id
default:
+ check.dump("unexpected object %v", exp)
unreachable()
}
x.expr = e
diff --git a/libgo/go/go/types/check.go b/libgo/go/go/types/check.go
index 0279be0e848..28e94f1940e 100644
--- a/libgo/go/go/types/check.go
+++ b/libgo/go/go/types/check.go
@@ -345,7 +345,6 @@ func (check *Checker) recordImplicit(node ast.Node, obj Object) {
func (check *Checker) recordSelection(x *ast.SelectorExpr, kind SelectionKind, recv Type, obj Object, index []int, indirect bool) {
assert(obj != nil && (recv == nil || len(index) > 0))
check.recordUse(x.Sel, obj)
- // TODO(gri) Should we also call recordTypeAndValue?
if m := check.Selections; m != nil {
m[x] = &Selection{kind, recv, obj, index, indirect}
}
diff --git a/libgo/go/go/types/check_test.go b/libgo/go/go/types/check_test.go
index 5e2043be84b..f8445752695 100644
--- a/libgo/go/go/types/check_test.go
+++ b/libgo/go/go/types/check_test.go
@@ -72,6 +72,7 @@ var tests = [][]string{
{"testdata/const1.src"},
{"testdata/constdecl.src"},
{"testdata/vardecl.src"},
+ //{"testdata/aliasdecl.src"},
{"testdata/expr0.src"},
{"testdata/expr1.src"},
{"testdata/expr2.src"},
@@ -80,6 +81,7 @@ var tests = [][]string{
{"testdata/shifts.src"},
{"testdata/builtins.src"},
{"testdata/conversions.src"},
+ {"testdata/conversions2.src"},
{"testdata/stmt0.src"},
{"testdata/stmt1.src"},
{"testdata/gotos.src"},
diff --git a/libgo/go/go/types/conversions.go b/libgo/go/go/types/conversions.go
index f98cc8d81a8..2bf1e2d5e38 100644
--- a/libgo/go/go/types/conversions.go
+++ b/libgo/go/go/types/conversions.go
@@ -55,7 +55,7 @@ func (check *Checker) conversion(x *operand, T Type) {
// not []byte as type for the constant "foo").
// - Keep untyped nil for untyped nil arguments.
if IsInterface(T) || constArg && !isConstType(T) {
- final = defaultType(x.typ)
+ final = Default(x.typ)
}
check.updateExprType(x.expr, final, true)
}
@@ -69,18 +69,19 @@ func (x *operand) convertibleTo(conf *Config, T Type) bool {
return true
}
- // "x's type and T have identical underlying types"
+ // "x's type and T have identical underlying types if tags are ignored"
V := x.typ
Vu := V.Underlying()
Tu := T.Underlying()
- if Identical(Vu, Tu) {
+ if IdenticalIgnoreTags(Vu, Tu) {
return true
}
- // "x's type and T are unnamed pointer types and their pointer base types have identical underlying types"
+ // "x's type and T are unnamed pointer types and their pointer base types
+ // have identical underlying types if tags are ignored"
if V, ok := V.(*Pointer); ok {
if T, ok := T.(*Pointer); ok {
- if Identical(V.base.Underlying(), T.base.Underlying()) {
+ if IdenticalIgnoreTags(V.base.Underlying(), T.base.Underlying()) {
return true
}
}
diff --git a/libgo/go/go/types/decl.go b/libgo/go/go/types/decl.go
index 1ecfb35f60c..dced7a6d6dc 100644
--- a/libgo/go/go/types/decl.go
+++ b/libgo/go/go/types/decl.go
@@ -85,6 +85,10 @@ func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) {
case *Func:
// functions may be recursive - no need to track dependencies
check.funcDecl(obj, d)
+ // Alias-related code. Keep for now.
+ // case *Alias:
+ // // aliases cannot be recursive - no need to track dependencies
+ // check.aliasDecl(obj, d)
default:
unreachable()
}
@@ -329,6 +333,106 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
}
}
+// original returns the original Object if obj is an Alias;
+// otherwise it returns obj. The result is never an Alias,
+// but it may be nil.
+func original(obj Object) Object {
+ // an alias stands for the original object; use that one instead
+ if alias, _ := obj.(*disabledAlias); alias != nil {
+ obj = alias.orig
+ // aliases always refer to non-alias originals
+ if _, ok := obj.(*disabledAlias); ok {
+ panic("original is an alias")
+ }
+ }
+ return obj
+}
+
+func (check *Checker) aliasDecl(obj *disabledAlias, decl *declInfo) {
+ assert(obj.typ == nil)
+
+ // alias declarations cannot use iota
+ assert(check.iota == nil)
+
+ // assume alias is invalid to start with
+ obj.typ = Typ[Invalid]
+
+ // rhs must be package-qualified identifer pkg.sel (see also call.go: checker.selector)
+ // TODO(gri) factor this code out and share with checker.selector
+ rhs := decl.init
+ var pkg *Package
+ var sel *ast.Ident
+ if sexpr, ok := rhs.(*ast.SelectorExpr); ok {
+ if ident, ok := sexpr.X.(*ast.Ident); ok {
+ _, obj := check.scope.LookupParent(ident.Name, check.pos)
+ if pname, _ := obj.(*PkgName); pname != nil {
+ assert(pname.pkg == check.pkg)
+ check.recordUse(ident, pname)
+ pname.used = true
+ pkg = pname.imported
+ sel = sexpr.Sel
+ }
+ }
+ }
+ if pkg == nil {
+ check.errorf(rhs.Pos(), "invalid alias: %v is not a package-qualified identifier", rhs)
+ return
+ }
+
+ // qualified identifier must denote an exported object
+ orig := pkg.scope.Lookup(sel.Name)
+ if orig == nil || !orig.Exported() {
+ if !pkg.fake {
+ check.errorf(rhs.Pos(), "%s is not exported by package %s", sel.Name, pkg.name)
+ }
+ return
+ }
+ check.recordUse(sel, orig)
+ orig = original(orig)
+
+ // avoid further errors if the imported object is an alias that's broken
+ if orig == nil {
+ return
+ }
+
+ // An alias declaration must not refer to package unsafe.
+ if orig.Pkg() == Unsafe {
+ check.errorf(rhs.Pos(), "invalid alias: %s refers to package unsafe (%v)", obj.Name(), orig)
+ return
+ }
+
+ // The original must be of the same kind as the alias declaration.
+ var why string
+ switch obj.kind {
+ case token.CONST:
+ if _, ok := orig.(*Const); !ok {
+ why = "constant"
+ }
+ case token.TYPE:
+ if _, ok := orig.(*TypeName); !ok {
+ why = "type"
+ }
+ case token.VAR:
+ if _, ok := orig.(*Var); !ok {
+ why = "variable"
+ }
+ case token.FUNC:
+ if _, ok := orig.(*Func); !ok {
+ why = "function"
+ }
+ default:
+ unreachable()
+ }
+ if why != "" {
+ check.errorf(rhs.Pos(), "invalid alias: %v is not a %s", orig, why)
+ return
+ }
+
+ // alias is valid
+ obj.typ = orig.Type()
+ obj.orig = orig
+}
+
func (check *Checker) declStmt(decl ast.Decl) {
pkg := check.pkg
diff --git a/libgo/go/go/types/expr.go b/libgo/go/go/types/expr.go
index 4430c45d140..f76da17fe53 100644
--- a/libgo/go/go/types/expr.go
+++ b/libgo/go/go/types/expr.go
@@ -541,7 +541,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) {
if !t.Empty() {
goto Error
}
- target = defaultType(x.typ)
+ target = Default(x.typ)
}
case *Pointer, *Signature, *Slice, *Map, *Chan:
if !x.isNil() {
@@ -605,8 +605,8 @@ func (check *Checker) comparison(x, y *operand, op token.Token) {
// time will be materialized. Update the expression trees.
// If the current types are untyped, the materialized type
// is the respective default type.
- check.updateExprType(x.expr, defaultType(x.typ), true)
- check.updateExprType(y.expr, defaultType(y.typ), true)
+ check.updateExprType(x.expr, Default(x.typ), true)
+ check.updateExprType(y.expr, Default(y.typ), true)
}
// spec: "Comparison operators compare two operands and yield
@@ -1015,32 +1015,38 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
}
case *ast.CompositeLit:
- typ := hint
- openArray := false
- if e.Type != nil {
+ var typ, base Type
+
+ switch {
+ case e.Type != nil:
+ // composite literal type present - use it
// [...]T array types may only appear with composite literals.
// Check for them here so we don't have to handle ... in general.
- typ = nil
if atyp, _ := e.Type.(*ast.ArrayType); atyp != nil && atyp.Len != nil {
if ellip, _ := atyp.Len.(*ast.Ellipsis); ellip != nil && ellip.Elt == nil {
// We have an "open" [...]T array type.
// Create a new ArrayType with unknown length (-1)
// and finish setting it up after analyzing the literal.
typ = &Array{len: -1, elem: check.typ(atyp.Elt)}
- openArray = true
+ base = typ
+ break
}
}
- if typ == nil {
- typ = check.typ(e.Type)
- }
- }
- if typ == nil {
+ typ = check.typ(e.Type)
+ base = typ
+
+ case hint != nil:
+ // no composite literal type present - use hint (element type of enclosing type)
+ typ = hint
+ base, _ = deref(typ.Underlying()) // *T implies &T{}
+
+ default:
// TODO(gri) provide better error messages depending on context
check.error(e.Pos(), "missing type in composite literal")
goto Error
}
- switch typ, _ := deref(typ); utyp := typ.Underlying().(type) {
+ switch utyp := base.Underlying().(type) {
case *Struct:
if len(e.Elts) == 0 {
break
@@ -1106,9 +1112,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
case *Array:
n := check.indexedElts(e.Elts, utyp.elem, utyp.len)
- // if we have an "open" [...]T array, set the length now that we know it
- if openArray {
+ // If we have an "open" [...]T array, set the length now that we know it
+ // and record the type for [...] (usually done by check.typExpr which is
+ // not called for [...]).
+ if utyp.len < 0 {
utyp.len = n
+ check.recordTypeAndValue(e.Type, typexpr, utyp, nil)
}
case *Slice:
diff --git a/libgo/go/go/types/initorder.go b/libgo/go/go/types/initorder.go
index cf9b8709d8d..966dccb8289 100644
--- a/libgo/go/go/types/initorder.go
+++ b/libgo/go/go/types/initorder.go
@@ -15,7 +15,7 @@ func (check *Checker) initOrder() {
// built from several calls to (*Checker).Files. Clear it.
check.Info.InitOrder = check.Info.InitOrder[:0]
- // Compute the transposed object dependency graph and initialize
+ // Compute the object dependency graph and initialize
// a priority queue with the list of graph nodes.
pq := nodeQueue(dependencyGraph(check.objMap))
heap.Init(&pq)
@@ -25,22 +25,25 @@ func (check *Checker) initOrder() {
fmt.Printf("Computing initialization order for %s\n\n", check.pkg)
fmt.Println("Object dependency graph:")
for obj, d := range check.objMap {
- if len(d.deps) > 0 {
- fmt.Printf("\t%s depends on\n", obj.Name())
- for dep := range d.deps {
- fmt.Printf("\t\t%s\n", dep.Name())
+ // only print objects that may appear in the dependency graph
+ if obj, _ := obj.(dependency); obj != nil {
+ if len(d.deps) > 0 {
+ fmt.Printf("\t%s depends on\n", obj.Name())
+ for dep := range d.deps {
+ fmt.Printf("\t\t%s\n", dep.Name())
+ }
+ } else {
+ fmt.Printf("\t%s has no dependencies\n", obj.Name())
}
- } else {
- fmt.Printf("\t%s has no dependencies\n", obj.Name())
}
}
fmt.Println()
- fmt.Println("Transposed object dependency graph:")
+ fmt.Println("Transposed object dependency graph (functions eliminated):")
for _, n := range pq {
- fmt.Printf("\t%s depends on %d nodes\n", n.obj.Name(), n.in)
- for _, out := range n.out {
- fmt.Printf("\t\t%s is dependent\n", out.obj.Name())
+ fmt.Printf("\t%s depends on %d nodes\n", n.obj.Name(), n.ndeps)
+ for p := range n.pred {
+ fmt.Printf("\t\t%s is dependent\n", p.obj.Name())
}
}
fmt.Println()
@@ -54,34 +57,40 @@ func (check *Checker) initOrder() {
// In a valid Go program, those nodes always have zero dependencies (after
// removing all incoming dependencies), otherwise there are initialization
// cycles.
- mark := 0
emitted := make(map[*declInfo]bool)
for len(pq) > 0 {
// get the next node
- n := heap.Pop(&pq).(*objNode)
+ n := heap.Pop(&pq).(*graphNode)
if debug {
fmt.Printf("\t%s (src pos %d) depends on %d nodes now\n",
- n.obj.Name(), n.obj.order(), n.in)
+ n.obj.Name(), n.obj.order(), n.ndeps)
}
// if n still depends on other nodes, we have a cycle
- if n.in > 0 {
- mark++ // mark nodes using a different value each time
- cycle := findPath(n, n, mark)
- if i := valIndex(cycle); i >= 0 {
- check.reportCycle(cycle, i)
+ if n.ndeps > 0 {
+ cycle := findPath(check.objMap, n.obj, n.obj, make(objSet))
+ // If n.obj is not part of the cycle (e.g., n.obj->b->c->d->c),
+ // cycle will be nil. Don't report anything in that case since
+ // the cycle is reported when the algorithm gets to an object
+ // in the cycle.
+ // Furthermore, once an object in the cycle is encountered,
+ // the cycle will be broken (dependency count will be reduced
+ // below), and so the remaining nodes in the cycle don't trigger
+ // another error (unless they are part of multiple cycles).
+ if cycle != nil {
+ check.reportCycle(cycle)
}
- // ok to continue, but the variable initialization order
+ // Ok to continue, but the variable initialization order
// will be incorrect at this point since it assumes no
- // cycle errors
+ // cycle errors.
}
// reduce dependency count of all dependent nodes
// and update priority queue
- for _, out := range n.out {
- out.in--
- heap.Fix(&pq, out.index)
+ for p := range n.pred {
+ p.ndeps--
+ heap.Fix(&pq, p.index)
}
// record the init order for variables with initializers only
@@ -118,102 +127,147 @@ func (check *Checker) initOrder() {
}
}
-// findPath returns the (reversed) list of nodes z, ... c, b, a,
-// such that there is a path (list of edges) from a to z.
+// findPath returns the (reversed) list of objects []Object{to, ... from}
+// such that there is a path of object dependencies from 'from' to 'to'.
// If there is no such path, the result is nil.
-// Nodes marked with the value mark are considered "visited";
-// unvisited nodes are marked during the graph search.
-func findPath(a, z *objNode, mark int) []*objNode {
- if a.mark == mark {
+func findPath(objMap map[Object]*declInfo, from, to Object, visited objSet) []Object {
+ if visited[from] {
return nil // node already seen
}
- a.mark = mark
+ visited[from] = true
- for _, n := range a.out {
- if n == z {
- return []*objNode{z}
+ for d := range objMap[from].deps {
+ if d == to {
+ return []Object{d}
}
- if P := findPath(n, z, mark); P != nil {
- return append(P, n)
+ if P := findPath(objMap, d, to, visited); P != nil {
+ return append(P, d)
}
}
return nil
}
-// valIndex returns the index of the first constant or variable in a,
-// if any; or a value < 0.
-func valIndex(a []*objNode) int {
- for i, n := range a {
- switch n.obj.(type) {
- case *Const, *Var:
- return i
- }
- }
- return -1
-}
-
-// reportCycle reports an error for the cycle starting at i.
-func (check *Checker) reportCycle(cycle []*objNode, i int) {
- obj := cycle[i].obj
+// reportCycle reports an error for the given cycle.
+func (check *Checker) reportCycle(cycle []Object) {
+ obj := cycle[0]
check.errorf(obj.Pos(), "initialization cycle for %s", obj.Name())
- // print cycle
- for _ = range cycle {
+ // subtle loop: print cycle[i] for i = 0, n-1, n-2, ... 1 for len(cycle) = n
+ for i := len(cycle) - 1; i >= 0; i-- {
check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
- i++
- if i >= len(cycle) {
- i = 0
- }
- obj = cycle[i].obj
+ obj = cycle[i]
}
+ // print cycle[0] again to close the cycle
check.errorf(obj.Pos(), "\t%s", obj.Name())
}
-// An objNode represents a node in the object dependency graph.
-// Each node b in a.out represents an edge a->b indicating that
-// b depends on a.
-// Nodes may be marked for cycle detection. A node n is marked
-// if n.mark corresponds to the current mark value.
-type objNode struct {
- obj Object // object represented by this node
- in int // number of nodes this node depends on
- out []*objNode // list of nodes that depend on this node
- index int // node index in list of nodes
- mark int // for cycle detection
+// ----------------------------------------------------------------------------
+// Object dependency graph
+
+// A dependency is an object that may be a dependency in an initialization
+// expression. Only constants, variables, and functions can be dependencies.
+// Constants are here because constant expression cycles are reported during
+// initialization order computation.
+type dependency interface {
+ Object
+ isDependency()
+}
+
+// A graphNode represents a node in the object dependency graph.
+// Each node p in n.pred represents an edge p->n, and each node
+// s in n.succ represents an edge n->s; with a->b indicating that
+// a depends on b.
+type graphNode struct {
+ obj dependency // object represented by this node
+ pred, succ nodeSet // consumers and dependencies of this node (lazily initialized)
+ index int // node index in graph slice/priority queue
+ ndeps int // number of outstanding dependencies before this object can be initialized
+}
+
+type nodeSet map[*graphNode]bool
+
+func (s *nodeSet) add(p *graphNode) {
+ if *s == nil {
+ *s = make(nodeSet)
+ }
+ (*s)[p] = true
}
-// dependencyGraph computes the transposed object dependency graph
-// from the given objMap. The transposed graph is returned as a list
-// of nodes; an edge d->n indicates that node n depends on node d.
-func dependencyGraph(objMap map[Object]*declInfo) []*objNode {
- // M maps each object to its corresponding node
- M := make(map[Object]*objNode, len(objMap))
+// dependencyGraph computes the object dependency graph from the given objMap,
+// with any function nodes removed. The resulting graph contains only constants
+// and variables.
+func dependencyGraph(objMap map[Object]*declInfo) []*graphNode {
+ // M is the dependency (Object) -> graphNode mapping
+ M := make(map[dependency]*graphNode)
for obj := range objMap {
- M[obj] = &objNode{obj: obj}
+ // only consider nodes that may be an initialization dependency
+ if obj, _ := obj.(dependency); obj != nil {
+ M[obj] = &graphNode{obj: obj}
+ }
}
- // G is the graph of nodes n
- G := make([]*objNode, len(M))
- i := 0
+ // compute edges for graph M
+ // (We need to include all nodes, even isolated ones, because they still need
+ // to be scheduled for initialization in correct order relative to other nodes.)
for obj, n := range M {
- deps := objMap[obj].deps
- n.in = len(deps)
- for d := range deps {
- d := M[d] // node n depends on node d
- d.out = append(d.out, n) // add edge d->n
+ // for each dependency obj -> d (= deps[i]), create graph edges n->s and s->n
+ for d := range objMap[obj].deps {
+ // only consider nodes that may be an initialization dependency
+ if d, _ := d.(dependency); d != nil {
+ d := M[d]
+ n.succ.add(d)
+ d.pred.add(n)
+ }
}
+ }
- G[i] = n
+ // remove function nodes and collect remaining graph nodes in G
+ // (Mutually recursive functions may introduce cycles among themselves
+ // which are permitted. Yet such cycles may incorrectly inflate the dependency
+ // count for variables which in turn may not get scheduled for initialization
+ // in correct order.)
+ var G []*graphNode
+ for obj, n := range M {
+ if _, ok := obj.(*Func); ok {
+ // connect each predecessor p of n with each successor s
+ // and drop the function node (don't collect it in G)
+ for p := range n.pred {
+ // ignore self-cycles
+ if p != n {
+ // Each successor s of n becomes a successor of p, and
+ // each predecessor p of n becomes a predecessor of s.
+ for s := range n.succ {
+ // ignore self-cycles
+ if s != n {
+ p.succ.add(s)
+ s.pred.add(p)
+ delete(s.pred, n) // remove edge to n
+ }
+ }
+ delete(p.succ, n) // remove edge to n
+ }
+ }
+ } else {
+ // collect non-function nodes
+ G = append(G, n)
+ }
+ }
+
+ // fill in index and ndeps fields
+ for i, n := range G {
n.index = i
- i++
+ n.ndeps = len(n.succ)
}
return G
}
+// ----------------------------------------------------------------------------
+// Priority queue
+
// nodeQueue implements the container/heap interface;
// a nodeQueue may be used as a priority queue.
-type nodeQueue []*objNode
+type nodeQueue []*graphNode
func (a nodeQueue) Len() int { return len(a) }
@@ -227,7 +281,7 @@ func (a nodeQueue) Less(i, j int) bool {
x, y := a[i], a[j]
// nodes are prioritized by number of incoming dependencies (1st key)
// and source order (2nd key)
- return x.in < y.in || x.in == y.in && x.obj.order() < y.obj.order()
+ return x.ndeps < y.ndeps || x.ndeps == y.ndeps && x.obj.order() < y.obj.order()
}
func (a *nodeQueue) Push(x interface{}) {
diff --git a/libgo/go/go/types/object.go b/libgo/go/go/types/object.go
index 707b806d3fc..6c0c5c4a244 100644
--- a/libgo/go/go/types/object.go
+++ b/libgo/go/go/types/object.go
@@ -19,7 +19,7 @@ import (
// All objects implement the Object interface.
//
type Object interface {
- Parent() *Scope // scope in which this object is declared
+ Parent() *Scope // scope in which this object is declared; nil for methods and struct fields
Pos() token.Pos // position of object identifier in declaration
Pkg() *Package // nil for objects in the Universe scope and labels
Name() string // package local object name
@@ -152,6 +152,7 @@ func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val constant.V
}
func (obj *Const) Val() constant.Value { return obj.val }
+func (*Const) isDependency() {} // a constant may be a dependency of an initialization expression
// A TypeName represents a declared type.
type TypeName struct {
@@ -184,8 +185,8 @@ func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool
}
func (obj *Var) Anonymous() bool { return obj.anonymous }
-
-func (obj *Var) IsField() bool { return obj.isField }
+func (obj *Var) IsField() bool { return obj.isField }
+func (*Var) isDependency() {} // a variable may be a dependency of an initialization expression
// A Func represents a declared function, concrete method, or abstract
// (interface) method. Its Type() is always a *Signature.
@@ -211,10 +212,31 @@ func (obj *Func) FullName() string {
return buf.String()
}
-func (obj *Func) Scope() *Scope {
- return obj.typ.(*Signature).scope
+func (obj *Func) Scope() *Scope { return obj.typ.(*Signature).scope }
+func (*Func) isDependency() {} // a function may be a dependency of an initialization expression
+
+// An Alias represents a declared alias.
+type disabledAlias struct {
+ object
+ orig Object // aliased constant, type, variable, or function; never an alias
+ kind token.Token // token.CONST, token.TYPE, token.VAR, or token.FUNC (only needed during resolve phase)
+}
+
+func disabledNewAlias(pos token.Pos, pkg *Package, name string, orig Object) *disabledAlias {
+ var typ Type = Typ[Invalid]
+ if orig != nil {
+ typ = orig.Type()
+ }
+ // No need to set a valid Alias.kind - that field is only used during identifier
+ // resolution (1st type-checker pass). We could store the field outside but it's
+ // easier to keep it here.
+ return &disabledAlias{object{nil, pos, pkg, name, typ, 0, token.NoPos}, orig, token.ILLEGAL}
}
+// Orig returns the aliased object, or nil if there was an error.
+// The returned object is never an Alias.
+func (obj *disabledAlias) disabledOrig() Object { return obj.orig }
+
// A Label represents a declared label.
type Label struct {
object
@@ -273,6 +295,10 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
}
return
+ // Alias-related code. Keep for now.
+ // case *Alias:
+ // buf.WriteString("alias")
+
case *Label:
buf.WriteString("label")
typ = nil
@@ -327,14 +353,15 @@ func ObjectString(obj Object, qf Qualifier) string {
return buf.String()
}
-func (obj *PkgName) String() string { return ObjectString(obj, nil) }
-func (obj *Const) String() string { return ObjectString(obj, nil) }
-func (obj *TypeName) String() string { return ObjectString(obj, nil) }
-func (obj *Var) String() string { return ObjectString(obj, nil) }
-func (obj *Func) String() string { return ObjectString(obj, nil) }
-func (obj *Label) String() string { return ObjectString(obj, nil) }
-func (obj *Builtin) String() string { return ObjectString(obj, nil) }
-func (obj *Nil) String() string { return ObjectString(obj, nil) }
+func (obj *PkgName) String() string { return ObjectString(obj, nil) }
+func (obj *Const) String() string { return ObjectString(obj, nil) }
+func (obj *TypeName) String() string { return ObjectString(obj, nil) }
+func (obj *Var) String() string { return ObjectString(obj, nil) }
+func (obj *Func) String() string { return ObjectString(obj, nil) }
+func (obj *disabledAlias) String() string { return ObjectString(obj, nil) }
+func (obj *Label) String() string { return ObjectString(obj, nil) }
+func (obj *Builtin) String() string { return ObjectString(obj, nil) }
+func (obj *Nil) String() string { return ObjectString(obj, nil) }
func writeFuncName(buf *bytes.Buffer, f *Func, qf Qualifier) {
if f.typ != nil {
diff --git a/libgo/go/go/types/ordering.go b/libgo/go/go/types/ordering.go
index 6bb98f2dc10..3579abf7d7b 100644
--- a/libgo/go/go/types/ordering.go
+++ b/libgo/go/go/types/ordering.go
@@ -56,13 +56,9 @@ func (check *Checker) resolveOrder() []Object {
// sort interface types topologically by dependencies,
// and in source order if there are no dependencies
sort.Sort(inSourceOrder(ifaces))
- if debug {
- for _, obj := range ifaces {
- assert(check.objMap[obj].mark == 0)
- }
- }
+ visited := make(objSet)
for _, obj := range ifaces {
- check.appendInPostOrder(&order, obj)
+ check.appendInPostOrder(&order, obj, visited)
}
// sort everything else in source order
@@ -89,25 +85,25 @@ func (check *Checker) interfaceFor(obj Object) *ast.InterfaceType {
return ityp
}
-func (check *Checker) appendInPostOrder(order *[]Object, obj Object) {
- d := check.objMap[obj]
- if d.mark != 0 {
+func (check *Checker) appendInPostOrder(order *[]Object, obj Object, visited objSet) {
+ if visited[obj] {
// We've already seen this object; either because it's
// already added to order, or because we have a cycle.
// In both cases we stop. Cycle errors are reported
// when type-checking types.
return
}
- d.mark = 1
+ visited[obj] = true
+ d := check.objMap[obj]
for _, obj := range orderedSetObjects(d.deps) {
- check.appendInPostOrder(order, obj)
+ check.appendInPostOrder(order, obj, visited)
}
*order = append(*order, obj)
}
-func orderedSetObjects(set map[Object]bool) []Object {
+func orderedSetObjects(set objSet) []Object {
list := make([]Object, len(set))
i := 0
for obj := range set {
diff --git a/libgo/go/go/types/predicates.go b/libgo/go/go/types/predicates.go
index 5509069fb63..21fd81e3c26 100644
--- a/libgo/go/go/types/predicates.go
+++ b/libgo/go/go/types/predicates.go
@@ -112,7 +112,12 @@ func hasNil(typ Type) bool {
// Identical reports whether x and y are identical.
func Identical(x, y Type) bool {
- return identical(x, y, nil)
+ return identical(x, y, true, nil)
+}
+
+// IdenticalIgnoreTags reports whether x and y are identical if tags are ignored.
+func IdenticalIgnoreTags(x, y Type) bool {
+ return identical(x, y, false, nil)
}
// An ifacePair is a node in a stack of interface type pairs compared for identity.
@@ -125,7 +130,7 @@ func (p *ifacePair) identical(q *ifacePair) bool {
return p.x == q.x && p.y == q.y || p.x == q.y && p.y == q.x
}
-func identical(x, y Type, p *ifacePair) bool {
+func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
if x == y {
return true
}
@@ -143,13 +148,13 @@ func identical(x, y Type, p *ifacePair) bool {
// Two array types are identical if they have identical element types
// and the same array length.
if y, ok := y.(*Array); ok {
- return x.len == y.len && identical(x.elem, y.elem, p)
+ return x.len == y.len && identical(x.elem, y.elem, cmpTags, p)
}
case *Slice:
// Two slice types are identical if they have identical element types.
if y, ok := y.(*Slice); ok {
- return identical(x.elem, y.elem, p)
+ return identical(x.elem, y.elem, cmpTags, p)
}
case *Struct:
@@ -162,9 +167,9 @@ func identical(x, y Type, p *ifacePair) bool {
for i, f := range x.fields {
g := y.fields[i]
if f.anonymous != g.anonymous ||
- x.Tag(i) != y.Tag(i) ||
+ cmpTags && x.Tag(i) != y.Tag(i) ||
!f.sameId(g.pkg, g.name) ||
- !identical(f.typ, g.typ, p) {
+ !identical(f.typ, g.typ, cmpTags, p) {
return false
}
}
@@ -175,7 +180,7 @@ func identical(x, y Type, p *ifacePair) bool {
case *Pointer:
// Two pointer types are identical if they have identical base types.
if y, ok := y.(*Pointer); ok {
- return identical(x.base, y.base, p)
+ return identical(x.base, y.base, cmpTags, p)
}
case *Tuple:
@@ -186,7 +191,7 @@ func identical(x, y Type, p *ifacePair) bool {
if x != nil {
for i, v := range x.vars {
w := y.vars[i]
- if !identical(v.typ, w.typ, p) {
+ if !identical(v.typ, w.typ, cmpTags, p) {
return false
}
}
@@ -202,8 +207,8 @@ func identical(x, y Type, p *ifacePair) bool {
// names are not required to match.
if y, ok := y.(*Signature); ok {
return x.variadic == y.variadic &&
- identical(x.params, y.params, p) &&
- identical(x.results, y.results, p)
+ identical(x.params, y.params, cmpTags, p) &&
+ identical(x.results, y.results, cmpTags, p)
}
case *Interface:
@@ -249,7 +254,7 @@ func identical(x, y Type, p *ifacePair) bool {
}
for i, f := range a {
g := b[i]
- if f.Id() != g.Id() || !identical(f.typ, g.typ, q) {
+ if f.Id() != g.Id() || !identical(f.typ, g.typ, cmpTags, q) {
return false
}
}
@@ -260,14 +265,14 @@ func identical(x, y Type, p *ifacePair) bool {
case *Map:
// Two map types are identical if they have identical key and value types.
if y, ok := y.(*Map); ok {
- return identical(x.key, y.key, p) && identical(x.elem, y.elem, p)
+ return identical(x.key, y.key, cmpTags, p) && identical(x.elem, y.elem, cmpTags, p)
}
case *Chan:
// Two channel types are identical if they have identical value types
// and the same direction.
if y, ok := y.(*Chan); ok {
- return x.dir == y.dir && identical(x.elem, y.elem, p)
+ return x.dir == y.dir && identical(x.elem, y.elem, cmpTags, p)
}
case *Named:
@@ -286,11 +291,11 @@ func identical(x, y Type, p *ifacePair) bool {
return false
}
-// defaultType returns the default "typed" type for an "untyped" type;
+// Default returns the default "typed" type for an "untyped" type;
// it returns the incoming type for all other types. The default type
// for untyped nil is untyped nil.
//
-func defaultType(typ Type) Type {
+func Default(typ Type) Type {
if t, ok := typ.(*Basic); ok {
switch t.kind {
case UntypedBool:
diff --git a/libgo/go/go/types/resolver.go b/libgo/go/go/types/resolver.go
index cb8e72e4a6a..046e147456d 100644
--- a/libgo/go/go/types/resolver.go
+++ b/libgo/go/go/types/resolver.go
@@ -14,18 +14,23 @@ import (
"unicode"
)
-// A declInfo describes a package-level const, type, var, or func declaration.
+// A declInfo describes a package-level const, type, var, func, or alias declaration.
type declInfo struct {
file *Scope // scope of file containing this declaration
lhs []*Var // lhs of n:1 variable declarations, or nil
typ ast.Expr // type, or nil
- init ast.Expr // init expression, or nil
+ init ast.Expr // init/orig expression, or nil
fdecl *ast.FuncDecl // func declaration, or nil
- deps map[Object]bool // type and init dependencies; lazily allocated
- mark int // for dependency analysis
+ // The deps field tracks initialization expression dependencies.
+ // As a special (overloaded) case, it also tracks dependencies of
+ // interface types on embedded interfaces (see ordering.go).
+ deps objSet // lazily initialized
}
+// An objSet is simply a set of objects.
+type objSet map[Object]bool
+
// hasInitializer reports whether the declared object has an initialization
// expression or function body.
func (d *declInfo) hasInitializer() bool {
@@ -36,7 +41,7 @@ func (d *declInfo) hasInitializer() bool {
func (d *declInfo) addDep(obj Object) {
m := d.deps
if m == nil {
- m = make(map[Object]bool)
+ m = make(objSet)
d.deps = m
}
m[obj] = true
@@ -269,6 +274,13 @@ func (check *Checker) collectObjects() {
check.declare(fileScope, nil, obj, token.NoPos)
}
+ // Alias-related code. Keep for now.
+ // case *ast.AliasSpec:
+ // obj := NewAlias(s.Name.Pos(), pkg, s.Name.Name, nil)
+ // obj.typ = nil // unresolved
+ // obj.kind = d.Tok
+ // check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, init: s.Orig})
+
case *ast.ValueSpec:
switch d.Tok {
case token.CONST:
diff --git a/libgo/go/go/types/sizes.go b/libgo/go/go/types/sizes.go
index 87c3ce41597..3bbe5aee40a 100644
--- a/libgo/go/go/types/sizes.go
+++ b/libgo/go/go/types/sizes.go
@@ -64,12 +64,25 @@ func (s *StdSizes) Alignof(T Type) int64 {
}
}
return max
+ case *Slice, *Interface:
+ // Multiword data structures are effectively structs
+ // in which each element has size WordSize.
+ return s.WordSize
+ case *Basic:
+ // Strings are like slices and interfaces.
+ if t.Info()&IsString != 0 {
+ return s.WordSize
+ }
}
a := s.Sizeof(T) // may be 0
// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
if a < 1 {
return 1
}
+ // complex{64,128} are aligned like [2]float{32,64}.
+ if isComplex(T) {
+ a /= 2
+ }
if a > s.MaxAlign {
return s.MaxAlign
}
@@ -132,8 +145,8 @@ func (s *StdSizes) Sizeof(T Type) int64 {
if n == 0 {
return 0
}
- setOffsets(t, s)
- return t.offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
+ offsets := s.Offsetsof(t.fields)
+ return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
case *Interface:
return s.WordSize * 2
}
@@ -158,22 +171,18 @@ func (conf *Config) offsetsof(T *Struct) []int64 {
if T.NumFields() > 0 {
// compute offsets on demand
if s := conf.Sizes; s != nil {
- calculated := setOffsets(T, s)
- offsets = T.offsets
- if calculated {
- // sanity checks
- if len(offsets) != T.NumFields() {
- panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
- }
- for _, o := range offsets {
- if o < 0 {
- panic("Config.Sizes.Offsetsof returned an offset < 0")
- }
+ offsets = s.Offsetsof(T.fields)
+ // sanity checks
+ if len(offsets) != T.NumFields() {
+ panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
+ }
+ for _, o := range offsets {
+ if o < 0 {
+ panic("Config.Sizes.Offsetsof returned an offset < 0")
}
}
} else {
- setOffsets(T, &stdSizes)
- offsets = T.offsets
+ offsets = stdSizes.Offsetsof(T.fields)
}
}
return offsets
@@ -207,15 +216,3 @@ func align(x, a int64) int64 {
y := x + a - 1
return y - y%a
}
-
-// setOffsets sets the offsets of s for the given sizes if necessary.
-// The result is true if the offsets were not set before; otherwise it
-// is false.
-func setOffsets(s *Struct, sizes Sizes) bool {
- var calculated bool
- s.offsetsOnce.Do(func() {
- calculated = true
- s.offsets = sizes.Offsetsof(s.fields)
- })
- return calculated
-}
diff --git a/libgo/go/go/types/sizes_test.go b/libgo/go/go/types/sizes_test.go
new file mode 100644
index 00000000000..dea18e7db4a
--- /dev/null
+++ b/libgo/go/go/types/sizes_test.go
@@ -0,0 +1,119 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for sizes.
+
+package types_test
+
+import (
+ "go/ast"
+ // "go/importer"
+ "go/parser"
+ "go/token"
+ "go/types"
+ "testing"
+)
+
+// findStructType typechecks src and returns the first struct type encountered.
+func findStructType(t *testing.T, src string) *types.Struct {
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, "x.go", src, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ info := types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
+ var conf types.Config
+ _, err = conf.Check("x", fset, []*ast.File{f}, &info)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, tv := range info.Types {
+ if ts, ok := tv.Type.(*types.Struct); ok {
+ return ts
+ }
+ }
+ t.Fatalf("failed to find a struct type in src:\n%s\n", src)
+ return nil
+}
+
+// Issue 16316
+func TestMultipleSizeUse(t *testing.T) {
+ const src = `
+package main
+
+type S struct {
+ i int
+ b bool
+ s string
+ n int
+}
+`
+ ts := findStructType(t, src)
+ sizes := types.StdSizes{WordSize: 4, MaxAlign: 4}
+ if got := sizes.Sizeof(ts); got != 20 {
+ t.Errorf("Sizeof(%v) with WordSize 4 = %d want 20", ts, got)
+ }
+ sizes = types.StdSizes{WordSize: 8, MaxAlign: 8}
+ if got := sizes.Sizeof(ts); got != 40 {
+ t.Errorf("Sizeof(%v) with WordSize 8 = %d want 40", ts, got)
+ }
+}
+
+// Issue 16464
+func TestAlignofNaclSlice(t *testing.T) {
+ const src = `
+package main
+
+var s struct {
+ x *int
+ y []byte
+}
+`
+ ts := findStructType(t, src)
+ sizes := &types.StdSizes{WordSize: 4, MaxAlign: 8}
+ var fields []*types.Var
+ // Make a copy manually :(
+ for i := 0; i < ts.NumFields(); i++ {
+ fields = append(fields, ts.Field(i))
+ }
+ offsets := sizes.Offsetsof(fields)
+ if offsets[0] != 0 || offsets[1] != 4 {
+ t.Errorf("OffsetsOf(%v) = %v want %v", ts, offsets, []int{0, 4})
+ }
+}
+
+/*
+Doesn't compile with current gccgo.
+
+sizes_test.go:101:3: error: use of undefined type 'Importer'
+
+func TestIssue16902(t *testing.T) {
+ const src = `
+package a
+
+import "unsafe"
+
+const _ = unsafe.Offsetof(struct{ x int64 }{}.x)
+`
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, "x.go", src, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ info := types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
+ conf := types.Config{
+ Importer: importer.Default(),
+ Sizes: &types.StdSizes{WordSize: 8, MaxAlign: 8},
+ }
+ _, err = conf.Check("x", fset, []*ast.File{f}, &info)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, tv := range info.Types {
+ _ = conf.Sizes.Sizeof(tv.Type)
+ _ = conf.Sizes.Alignof(tv.Type)
+ }
+}
+
+*/
diff --git a/libgo/go/go/types/stdlib_test.go b/libgo/go/go/types/stdlib_test.go
index e40734f147f..8fc51d4b17d 100644
--- a/libgo/go/go/types/stdlib_test.go
+++ b/libgo/go/go/types/stdlib_test.go
@@ -161,6 +161,8 @@ func TestStdFixed(t *testing.T) {
"issue7746.go", // large constants - consumes too much memory
"issue11362.go", // canonical import path check
"issue15002.go", // uses Mmap; testTestDir should consult build tags
+ "issue16369.go", // go/types handles this correctly - not an issue
+ "issue18459.go", // go/types doesn't check validity of //go:xxx directives
)
}
diff --git a/libgo/go/go/types/stmt.go b/libgo/go/go/types/stmt.go
index 5764430b1bf..4e423bd686f 100644
--- a/libgo/go/go/types/stmt.go
+++ b/libgo/go/go/types/stmt.go
@@ -68,13 +68,19 @@ func (check *Checker) usage(scope *Scope) {
}
// stmtContext is a bitset describing which
-// control-flow statements are permissible.
+// control-flow statements are permissible,
+// and provides additional context information
+// for better error messages.
type stmtContext uint
const (
+ // permissible control-flow statements
breakOk stmtContext = 1 << iota
continueOk
fallthroughOk
+
+ // additional context information
+ finalSwitchCase
)
func (check *Checker) simpleStmt(s ast.Stmt) {
@@ -292,7 +298,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
}(check.scope)
}
- inner := ctxt &^ fallthroughOk
+ inner := ctxt &^ (fallthroughOk | finalSwitchCase)
switch s := s.(type) {
case *ast.BadStmt, *ast.EmptyStmt:
// ignore
@@ -454,7 +460,11 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
}
case token.FALLTHROUGH:
if ctxt&fallthroughOk == 0 {
- check.error(s.Pos(), "fallthrough statement out of place")
+ msg := "fallthrough statement out of place"
+ if ctxt&finalSwitchCase != 0 {
+ msg = "cannot fallthrough final case in switch"
+ }
+ check.error(s.Pos(), msg)
}
default:
check.invalidAST(s.Pos(), "branch statement: %s", s.Tok)
@@ -523,6 +533,8 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
inner := inner
if i+1 < len(s.Body.List) {
inner |= fallthroughOk
+ } else {
+ inner |= finalSwitchCase
}
check.stmtList(inner, clause.Body)
check.closeScope()
@@ -616,9 +628,9 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
T = x.typ
}
obj := NewVar(lhs.Pos(), check.pkg, lhs.Name, T)
- scopePos := clause.End()
- if len(clause.Body) > 0 {
- scopePos = clause.Body[0].Pos()
+ scopePos := clause.Pos() + token.Pos(len("default")) // for default clause (len(List) == 0)
+ if n := len(clause.List); n > 0 {
+ scopePos = clause.List[n-1].End()
}
check.declare(check.scope, nil, obj, scopePos)
check.recordImplicit(clause, obj)
@@ -810,12 +822,12 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
// declare variables
if len(vars) > 0 {
+ scopePos := s.X.End()
for _, obj := range vars {
// spec: "The scope of a constant or variable identifier declared inside
// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
// for short variable declarations) and ends at the end of the innermost
// containing block."
- scopePos := s.End()
check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
}
} else {
diff --git a/libgo/go/go/types/type.go b/libgo/go/go/types/type.go
index 4e00da3212f..01adee8a3ef 100644
--- a/libgo/go/go/types/type.go
+++ b/libgo/go/go/types/type.go
@@ -4,10 +4,7 @@
package types
-import (
- "sort"
- "sync"
-)
+import "sort"
// A Type represents a type of Go.
// All types implement the Type interface.
@@ -121,10 +118,8 @@ func (s *Slice) Elem() Type { return s.elem }
// A Struct represents a struct type.
type Struct struct {
- fields []*Var
- tags []string // field tags; nil if there are no tags
- offsets []int64 // field offsets in bytes, lazily initialized
- offsetsOnce sync.Once // for threadsafe lazy initialization of offsets
+ fields []*Var
+ tags []string // field tags; nil if there are no tags
}
// NewStruct returns a new struct with the given fields and corresponding field tags.
diff --git a/libgo/go/go/types/typexpr.go b/libgo/go/go/types/typexpr.go
index 931b9247124..ecc0a7da021 100644
--- a/libgo/go/go/types/typexpr.go
+++ b/libgo/go/go/types/typexpr.go
@@ -45,6 +45,17 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeNa
delete(check.unusedDotImports[scope], pkg)
}
+ // Alias-related code. Keep for now.
+ // An alias stands for the original object; use that one instead.
+ // TODO(gri) We should be able to factor out the Typ[Invalid] test.
+ // if alias, _ := obj.(*Alias); alias != nil {
+ // obj = original(obj)
+ // if obj == nil || typ == Typ[Invalid] {
+ // return
+ // }
+ // assert(typ == obj.Type())
+ // }
+
switch obj := obj.(type) {
case *PkgName:
check.errorf(e.Pos(), "use of package %s not in selector", obj.name)
@@ -623,8 +634,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
// current field typ and tag
var typ Type
var tag string
- // anonymous != nil indicates an anonymous field.
- add := func(field *ast.Field, ident *ast.Ident, anonymous *TypeName, pos token.Pos) {
+ add := func(field *ast.Field, ident *ast.Ident, anonymous bool, pos token.Pos) {
if tag != "" && tags == nil {
tags = make([]string, len(fields))
}
@@ -633,15 +643,12 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
}
name := ident.Name
- fld := NewField(pos, check.pkg, name, typ, anonymous != nil)
+ fld := NewField(pos, check.pkg, name, typ, anonymous)
// spec: "Within a struct, non-blank field names must be unique."
if name == "_" || check.declareInSet(&fset, pos, fld) {
fields = append(fields, fld)
check.recordDef(ident, fld)
}
- if anonymous != nil {
- check.recordUse(ident, anonymous)
- }
}
for _, f := range list.List {
@@ -650,7 +657,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
if len(f.Names) > 0 {
// named fields
for _, name := range f.Names {
- add(f, name, nil, name.Pos())
+ add(f, name, false, name.Pos())
}
} else {
// anonymous field
@@ -668,7 +675,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
check.errorf(pos, "anonymous field type cannot be unsafe.Pointer")
continue
}
- add(f, name, Universe.Lookup(t.name).(*TypeName), pos)
+ add(f, name, true, pos)
case *Named:
// spec: "An embedded type must be specified as a type name
@@ -690,7 +697,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
continue
}
}
- add(f, name, t.obj, pos)
+ add(f, name, true, pos)
default:
check.invalidAST(pos, "anonymous field type %s must be named", typ)
diff --git a/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305.go b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305.go
new file mode 100644
index 00000000000..eb6739a109f
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305.go
@@ -0,0 +1,83 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package chacha20poly1305 implements the ChaCha20-Poly1305 AEAD as specified in RFC 7539.
+package chacha20poly1305
+
+import (
+ "crypto/cipher"
+ "errors"
+)
+
+const (
+ // KeySize is the size of the key used by this AEAD, in bytes.
+ KeySize = 32
+ // NonceSize is the size of the nonce used with this AEAD, in bytes.
+ NonceSize = 12
+)
+
+type chacha20poly1305 struct {
+ key [32]byte
+}
+
+// New returns a ChaCha20-Poly1305 AEAD that uses the given, 256-bit key.
+func New(key []byte) (cipher.AEAD, error) {
+ if len(key) != KeySize {
+ return nil, errors.New("chacha20poly1305: bad key length")
+ }
+ ret := new(chacha20poly1305)
+ copy(ret.key[:], key)
+ return ret, nil
+}
+
+func (c *chacha20poly1305) NonceSize() int {
+ return NonceSize
+}
+
+func (c *chacha20poly1305) Overhead() int {
+ return 16
+}
+
+func (c *chacha20poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
+ if len(nonce) != NonceSize {
+ panic("chacha20poly1305: bad nonce length passed to Seal")
+ }
+
+ if uint64(len(plaintext)) > (1<<38)-64 {
+ panic("chacha20poly1305: plaintext too large")
+ }
+
+ return c.seal(dst, nonce, plaintext, additionalData)
+}
+
+var errOpen = errors.New("chacha20poly1305: message authentication failed")
+
+func (c *chacha20poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+ if len(nonce) != NonceSize {
+ panic("chacha20poly1305: bad nonce length passed to Open")
+ }
+ if len(ciphertext) < 16 {
+ return nil, errOpen
+ }
+ if uint64(len(ciphertext)) > (1<<38)-48 {
+ panic("chacha20poly1305: ciphertext too large")
+ }
+
+ return c.open(dst, nonce, ciphertext, additionalData)
+}
+
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+ if total := len(in) + n; cap(in) >= total {
+ head = in[:total]
+ } else {
+ head = make([]byte, total)
+ copy(head, in)
+ }
+ tail = head[len(in):]
+ return
+}
diff --git a/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
new file mode 100644
index 00000000000..47550332126
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
@@ -0,0 +1,80 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7,amd64,!gccgo,!appengine
+
+package chacha20poly1305
+
+import "encoding/binary"
+
+//go:noescape
+func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
+
+//go:noescape
+func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
+
+//go:noescape
+func haveSSSE3() bool
+
+var canUseASM bool
+
+func init() {
+ canUseASM = haveSSSE3()
+}
+
+// setupState writes a ChaCha20 input matrix to state. See
+// https://tools.ietf.org/html/rfc7539#section-2.3.
+func setupState(state *[16]uint32, key *[32]byte, nonce []byte) {
+ state[0] = 0x61707865
+ state[1] = 0x3320646e
+ state[2] = 0x79622d32
+ state[3] = 0x6b206574
+
+ state[4] = binary.LittleEndian.Uint32(key[:4])
+ state[5] = binary.LittleEndian.Uint32(key[4:8])
+ state[6] = binary.LittleEndian.Uint32(key[8:12])
+ state[7] = binary.LittleEndian.Uint32(key[12:16])
+ state[8] = binary.LittleEndian.Uint32(key[16:20])
+ state[9] = binary.LittleEndian.Uint32(key[20:24])
+ state[10] = binary.LittleEndian.Uint32(key[24:28])
+ state[11] = binary.LittleEndian.Uint32(key[28:32])
+
+ state[12] = 0
+ state[13] = binary.LittleEndian.Uint32(nonce[:4])
+ state[14] = binary.LittleEndian.Uint32(nonce[4:8])
+ state[15] = binary.LittleEndian.Uint32(nonce[8:12])
+}
+
+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
+ if !canUseASM {
+ return c.sealGeneric(dst, nonce, plaintext, additionalData)
+ }
+
+ var state [16]uint32
+ setupState(&state, &c.key, nonce)
+
+ ret, out := sliceForAppend(dst, len(plaintext)+16)
+ chacha20Poly1305Seal(out[:], state[:], plaintext, additionalData)
+ return ret
+}
+
+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+ if !canUseASM {
+ return c.openGeneric(dst, nonce, ciphertext, additionalData)
+ }
+
+ var state [16]uint32
+ setupState(&state, &c.key, nonce)
+
+ ciphertext = ciphertext[:len(ciphertext)-16]
+ ret, out := sliceForAppend(dst, len(ciphertext))
+ if !chacha20Poly1305Open(out, state[:], ciphertext, additionalData) {
+ for i := range out {
+ out[i] = 0
+ }
+ return nil, errOpen
+ }
+
+ return ret, nil
+}
diff --git a/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
new file mode 100644
index 00000000000..b9a55ea046f
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_generic.go
@@ -0,0 +1,70 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package chacha20poly1305
+
+import (
+ "encoding/binary"
+
+ "golang_org/x/crypto/chacha20poly1305/internal/chacha20"
+ "golang_org/x/crypto/poly1305"
+)
+
+func roundTo16(n int) int {
+ return 16 * ((n + 15) / 16)
+}
+
+func (c *chacha20poly1305) sealGeneric(dst, nonce, plaintext, additionalData []byte) []byte {
+ var counter [16]byte
+ copy(counter[4:], nonce)
+
+ var polyKey [32]byte
+ chacha20.XORKeyStream(polyKey[:], polyKey[:], &counter, &c.key)
+
+ ret, out := sliceForAppend(dst, len(plaintext)+poly1305.TagSize)
+ counter[0] = 1
+ chacha20.XORKeyStream(out, plaintext, &counter, &c.key)
+
+ polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(plaintext))+8+8)
+ copy(polyInput, additionalData)
+ copy(polyInput[roundTo16(len(additionalData)):], out[:len(plaintext)])
+ binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
+ binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(plaintext)))
+
+ var tag [poly1305.TagSize]byte
+ poly1305.Sum(&tag, polyInput, &polyKey)
+ copy(out[len(plaintext):], tag[:])
+
+ return ret
+}
+
+func (c *chacha20poly1305) openGeneric(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+ var tag [poly1305.TagSize]byte
+ copy(tag[:], ciphertext[len(ciphertext)-16:])
+ ciphertext = ciphertext[:len(ciphertext)-16]
+
+ var counter [16]byte
+ copy(counter[4:], nonce)
+
+ var polyKey [32]byte
+ chacha20.XORKeyStream(polyKey[:], polyKey[:], &counter, &c.key)
+
+ polyInput := make([]byte, roundTo16(len(additionalData))+roundTo16(len(ciphertext))+8+8)
+ copy(polyInput, additionalData)
+ copy(polyInput[roundTo16(len(additionalData)):], ciphertext)
+ binary.LittleEndian.PutUint64(polyInput[len(polyInput)-16:], uint64(len(additionalData)))
+ binary.LittleEndian.PutUint64(polyInput[len(polyInput)-8:], uint64(len(ciphertext)))
+
+ ret, out := sliceForAppend(dst, len(ciphertext))
+ if !poly1305.Verify(&tag, polyInput, &polyKey) {
+ for i := range out {
+ out[i] = 0
+ }
+ return nil, errOpen
+ }
+
+ counter[0] = 1
+ chacha20.XORKeyStream(out, ciphertext, &counter, &c.key)
+ return ret, nil
+}
diff --git a/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
new file mode 100644
index 00000000000..4c2eb703c32
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_noasm.go
@@ -0,0 +1,15 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !amd64 !go1.7 gccgo appengine
+
+package chacha20poly1305
+
+func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte {
+ return c.sealGeneric(dst, nonce, plaintext, additionalData)
+}
+
+func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
+ return c.openGeneric(dst, nonce, ciphertext, additionalData)
+}
diff --git a/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_test.go b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_test.go
new file mode 100644
index 00000000000..78f981a74f4
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_test.go
@@ -0,0 +1,182 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package chacha20poly1305
+
+import (
+ "bytes"
+ cr "crypto/rand"
+ "encoding/hex"
+ mr "math/rand"
+ "testing"
+)
+
+func TestVectors(t *testing.T) {
+ for i, test := range chacha20Poly1305Tests {
+ key, _ := hex.DecodeString(test.key)
+ nonce, _ := hex.DecodeString(test.nonce)
+ ad, _ := hex.DecodeString(test.aad)
+ plaintext, _ := hex.DecodeString(test.plaintext)
+
+ aead, err := New(key)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ct := aead.Seal(nil, nonce, plaintext, ad)
+ if ctHex := hex.EncodeToString(ct); ctHex != test.out {
+ t.Errorf("#%d: got %s, want %s", i, ctHex, test.out)
+ continue
+ }
+
+ plaintext2, err := aead.Open(nil, nonce, ct, ad)
+ if err != nil {
+ t.Errorf("#%d: Open failed", i)
+ continue
+ }
+
+ if !bytes.Equal(plaintext, plaintext2) {
+ t.Errorf("#%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext)
+ continue
+ }
+
+ if len(ad) > 0 {
+ alterAdIdx := mr.Intn(len(ad))
+ ad[alterAdIdx] ^= 0x80
+ if _, err := aead.Open(nil, nonce, ct, ad); err == nil {
+ t.Errorf("#%d: Open was successful after altering additional data", i)
+ }
+ ad[alterAdIdx] ^= 0x80
+ }
+
+ alterNonceIdx := mr.Intn(aead.NonceSize())
+ nonce[alterNonceIdx] ^= 0x80
+ if _, err := aead.Open(nil, nonce, ct, ad); err == nil {
+ t.Errorf("#%d: Open was successful after altering nonce", i)
+ }
+ nonce[alterNonceIdx] ^= 0x80
+
+ alterCtIdx := mr.Intn(len(ct))
+ ct[alterCtIdx] ^= 0x80
+ if _, err := aead.Open(nil, nonce, ct, ad); err == nil {
+ t.Errorf("#%d: Open was successful after altering ciphertext", i)
+ }
+ ct[alterCtIdx] ^= 0x80
+ }
+}
+
+func TestRandom(t *testing.T) {
+ // Some random tests to verify Open(Seal) == Plaintext
+ for i := 0; i < 256; i++ {
+ var nonce [12]byte
+ var key [32]byte
+
+ al := mr.Intn(128)
+ pl := mr.Intn(16384)
+ ad := make([]byte, al)
+ plaintext := make([]byte, pl)
+ cr.Read(key[:])
+ cr.Read(nonce[:])
+ cr.Read(ad)
+ cr.Read(plaintext)
+
+ aead, err := New(key[:])
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ct := aead.Seal(nil, nonce[:], plaintext, ad)
+
+ plaintext2, err := aead.Open(nil, nonce[:], ct, ad)
+ if err != nil {
+ t.Errorf("Random #%d: Open failed", i)
+ continue
+ }
+
+ if !bytes.Equal(plaintext, plaintext2) {
+ t.Errorf("Random #%d: plaintext's don't match: got %x vs %x", i, plaintext2, plaintext)
+ continue
+ }
+
+ if len(ad) > 0 {
+ alterAdIdx := mr.Intn(len(ad))
+ ad[alterAdIdx] ^= 0x80
+ if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil {
+ t.Errorf("Random #%d: Open was successful after altering additional data", i)
+ }
+ ad[alterAdIdx] ^= 0x80
+ }
+
+ alterNonceIdx := mr.Intn(aead.NonceSize())
+ nonce[alterNonceIdx] ^= 0x80
+ if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil {
+ t.Errorf("Random #%d: Open was successful after altering nonce", i)
+ }
+ nonce[alterNonceIdx] ^= 0x80
+
+ alterCtIdx := mr.Intn(len(ct))
+ ct[alterCtIdx] ^= 0x80
+ if _, err := aead.Open(nil, nonce[:], ct, ad); err == nil {
+ t.Errorf("Random #%d: Open was successful after altering ciphertext", i)
+ }
+ ct[alterCtIdx] ^= 0x80
+ }
+}
+
+func benchamarkChaCha20Poly1305Seal(b *testing.B, buf []byte) {
+ b.SetBytes(int64(len(buf)))
+
+ var key [32]byte
+ var nonce [12]byte
+ var ad [13]byte
+ var out []byte
+
+ aead, _ := New(key[:])
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ out = aead.Seal(out[:0], nonce[:], buf[:], ad[:])
+ }
+}
+
+func benchamarkChaCha20Poly1305Open(b *testing.B, buf []byte) {
+ b.SetBytes(int64(len(buf)))
+
+ var key [32]byte
+ var nonce [12]byte
+ var ad [13]byte
+ var ct []byte
+ var out []byte
+
+ aead, _ := New(key[:])
+ ct = aead.Seal(ct[:0], nonce[:], buf[:], ad[:])
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ out, _ = aead.Open(out[:0], nonce[:], ct[:], ad[:])
+ }
+}
+
+func BenchmarkChacha20Poly1305Open_64(b *testing.B) {
+ benchamarkChaCha20Poly1305Open(b, make([]byte, 64))
+}
+
+func BenchmarkChacha20Poly1305Seal_64(b *testing.B) {
+ benchamarkChaCha20Poly1305Seal(b, make([]byte, 64))
+}
+
+func BenchmarkChacha20Poly1305Open_1350(b *testing.B) {
+ benchamarkChaCha20Poly1305Open(b, make([]byte, 1350))
+}
+
+func BenchmarkChacha20Poly1305Seal_1350(b *testing.B) {
+ benchamarkChaCha20Poly1305Seal(b, make([]byte, 1350))
+}
+
+func BenchmarkChacha20Poly1305Open_8K(b *testing.B) {
+ benchamarkChaCha20Poly1305Open(b, make([]byte, 8*1024))
+}
+
+func BenchmarkChacha20Poly1305Seal_8K(b *testing.B) {
+ benchamarkChaCha20Poly1305Seal(b, make([]byte, 8*1024))
+}
diff --git a/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_test_vectors.go b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_test_vectors.go
new file mode 100644
index 00000000000..49f0da6b738
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_test_vectors.go
@@ -0,0 +1,332 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package chacha20poly1305
+
+var chacha20Poly1305Tests = []struct {
+ plaintext, aad, key, nonce, out string
+}{
+ {
+ "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e",
+ "50515253c0c1c2c3c4c5c6c7",
+ "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
+ "070000004041424344454647",
+ "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691",
+ },
+ {
+ "1400000cebccee3bf561b292340fec60",
+ "00000000000000001603030010",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "2b487a2941bc07f3cc76d1a531662588ee7c2598e59778c24d5b27559a80d163",
+ },
+ {
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000000000000000000000000",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "3f487a25aa70e9c8391763370569c9e83b7650dd1921c8b78869f241f25d2096c910b180930c5b8747fd90959fe8ca2dcadb4fa50fa1439f916b2301e1cc0810d6725775d3ab86721700f96e22709b0a7a8bef32627dd929b2dd3ba15772b669062bb558bc92e6c241a1d60d9f0035e80c335f854815fe1138ab8af653eab3e122135feeec7dfaba1cc24af82a2b7acccdd824899a7e03cc29c25be8a4f56a66673845b93bae1556f09dafc89a0d22af207718e2a6bb022e9d917597295992ea3b750cc0e7a7c3d33b23c5a8aeab45f5bb542f6c9e6c1747ae5a344aff483ba38577ad534b33b3abc7d284776ea33ed488c2a2475648a4fcda561745ea7787ed60f2368deb27c75adce6ff9b6cc6de1f5e72a741e2d59f64751b3ae482d714e0c90e83c671ff98ed611823afb39e6e5019a6ba548a2a72e829c7b7b4a101ac9deb90a25d3e0c50d22e1fc26c7c02296fa13c6d9c14767f68aaf46450a8d0fd5feb60d9d73c6e68623425b4984a79d619dd6bf896459aa77a681ec9c1a97f645e121f47779b051f8948a817f84d1f55da170d5bbbaf2f64e18b97ed3fd822db2819f523314f1e5ac72e8f69bbe6c87c22daddb0e1ac6790f8534071de2f258064b99789bfb165b065b8fe96f9127cd7dca9f7cb0368420f1e802faa3ca23792f2a5b93773dd405e71c320b211b54f7a26626b03c060e1ab87f32ac588abfa056ce090bd7c69913a700c80f325bfe824fa",
+ },
+ {
+ "0967de57eefe1aaa999b9b746d88a1a248000d8734e0e938c6aa87",
+ "e4f0a3a4f90a8250f8806aa319053e8d73c62f150e2f239563037e9cc92823ad18c65111d0d462c954cc6c6ed2aafb45702a5a7e597d13bd8091594ab97cf7d1",
+ "f2db28620582e05f00f31c808475ca3df1c20e340bf14828352499466d79295f",
+ "4349e2131d44dc711148dfe3",
+ "bd06cc144fdc0d8b735fa4452eabbf78fd4ad2966ea41a84f68da40ca2da439777bc2ba6c4ec2de0d003eb",
+ },
+ {
+ "c4c920fb52a56fe66eaa8aa3fa187c543e3db8e5c8094c4313dc4ed35dfc5821c5791d171e8cfe8d37883031a0ad",
+ "85deea3dc4",
+ "05ff881d1e151bab4ca3db7d44880222733fe62686f71ce1e4610f2ea19599a7",
+ "b34710f65aed442e4a40866b",
+ "b154452fb7e85d175dd0b0db08591565c5587a725cf22386922f5d27a01015aba778975510b38754b2182e24352f019b7ad493e1ed255906715644aec6e0",
+ },
+ {
+ "c4b337df5e83823900c6c202e93541cf5bc8c677a9aad8b8d87a4d7221e294e595cbc4f34e462d4e0def50f62491c57f598cf60236cfba0f4908816aea154f80e013732e59a07c668fcc5cb35d2232b7ae29b9e4f874f3417c74ab6689fae6690d5a9766fa13cd8adf293d3d4b70f4f999adde9121d1d29d467d04cf77ea398444d0ea3fe4b7c9c3e106002c76f4260fa204a0c3d5",
+ "72611bef65eb664f24ea94f4d5d3d88c9c9c6da29c9a1991c02833c4c9f6993b57b5",
+ "dd0f2d4bb1c9e5ca5aa5f38d69bc8402f7dbb7229857b4a41b3044d481b7655e",
+ "2bbca0910cc47ca0b8517391",
+ "83aa28d6d98901e2981d21d3758ae4db8cce07fe08d82ca6f036a68daa88a7dda56eeb38040c942bdda0fd2d369eec44bd070e2c9314992f68dc16989a6ac0c3912c378cf3254f4bae74a66b075e828df6f855c0d8a827ffed3c03582c12a9112eeb7be43dfe8bd78beb2d1e56678b99a0372531727cb7f2b98d2f917ec10de93fe86267100c20356e80528c5066688c8b7acba76e591449952343f663993d5b642e59eb0f",
+ },
+ {
+ "a9775b8e42b63335439cf1c79fe8a3560b3baebfdfc9ef239d70da02cea0947817f00659a63a8ee9d67fb1756854cc738f7a326e432191e1916be35f0b78d72268de7c0e180af7ee8aa864f2fc30658baa97f9edb88ace49f5b2a8002a8023925e9fa076a997643340c8253cf88ac8a221c190d94c5e224110cb423a4b65cca9046c1fad0483e1444c0680449148e7b20a778c56d5ae97e679d920c43eed6d42598cf05d10d1a15cd722a0686a871b74fea7cad45562bacf3bda937ac701bc218dac7e9d7d20f955429abdac21d821207febf4d54daea4898837035038bf71c66cef63e90f5d3e51f7fcfe18d41f38540a2c2958dacde16304e4b33da324030f1366f923c337",
+ "74ba3372d308910b5c9c3885f41252d57556",
+ "9cf77bd06a4ed8fb59349791b98ba40b6019611942f5768e8be2ee88477149e3",
+ "b928935c4c966c60fd6583c0",
+ "ec7fd64fd75b254961a2b7fc942470d8620f439258b871d0d00f58028b5e0bee5e139e8108ac439391465d6658f559b1df57aa21cf826ede1a28bc11af885e13eebfc009870928fae8abfdd943a60c54fca93f0502dc23d29c2fd5340f9bc0e6ef2a18b66ef627af95f796d5bbca50de22c8ec802da9397089b25c6ba5262468e3977b45dc112e51896c70731b0a52d7efec7c93b41995823436bf4b0c477ae79684407c9831b487928b2b8303caca752b3edf1f0598e15831155462706f94ef3fa3a9e5f937f37085afa9b4bbf939d275796a61b78f70597acfd25cd87f967021cd99328fc371b5eb5739869520657b30e4a5b0db7c8715cbe275dee78e719b357d3a9731f9eaba95986479bb2004a77822fc115a3d",
+ },
+ {
+ "b3d3128bce6bbf66fd78f1a18352bae56bfcdae18b65c379ee0aeb37ee54fba1270d2df578ec5b75654d16e89fd1cd0acda7ec580dafd2fbbabd32a8112d49383a762db2638928c8d63eb0750f7e7fdd256b35321b072dd5c45f7dd58cc60dc63d3b79a0c4a1689adf180fef968eccbcfa01ee15091ceacd7b67a3082db0ce6aeb470aafe87249c88b58b721e783dde184ccf68de8e05b6347fe6b74ae3adf9a81e9496a5c9332e7ebe908d26ce6b3f0b2a97e9a89d9fdd0d7694585a3241f240d698e69fcc050e7a959ba153f6d06f117848ba05d887134f1b6b994dad9b9e74247513e08a125b1fadfc7394dcd2a6451b504ae3e75e22f2b9bc405747dedb6c43ef4ccdf1a7edaf9451346123eaa63f3af113124f361508e255503a242b96680ae3360c8b13ac1f64d08088bb26b7f617cb0866f11d6fd362b00d86eba3fee68724e302388f119d6f92161ac8ce00d08919377a26974d99575b1032ff0f1976240c785c8b89e9eb2bf005e4be06b5371ffca14683fedfdb49e00e38ff27af1324177faf91599abd5990920797574eb743effdc7decda318ada1419cc8e0bfecf82f9c99792746c2b",
+ "7e8da4f3018f673f8e43bd7a1dee05f8031ec49129c361abbc2a434e9eaf791c3c1d0f3dad767d3bba3ab6d728bbcf2bd994bd03571eae1348f161e6a1da03ddf7121ba4",
+ "7ee32dd501dce849cd492f6e23324c1a4567bfceff9f11d1352bcb8615f1b093",
+ "8998e043d2961afa51ea262a",
+ "ba85e72af18cb5ba85a4a0d6c28b4ac1e5509a3a2fdb0e3255cbc559df5e6a661fc560c756a0264dd99b72c61c51a4b7ad56ca4c8ccb7e8edfc48ff3cceac5d1e8ac5fc87096adc4d0e9a27492857b17604c3a694cfe0e70b22df106c8f3c61f840bcd634964cdb571840e125e381e7dd3a0d97972e965f16f775fa4ce555124318290bf508beb7bd77e633042deb0e863631478fc3dc9122862b3c31264471bcce54e0b74040c8bafd481cf798f332e8940f1134d3027d6f28e771d15e154fc89c6c25fe18a5d312807cc2e623bb1bbb4f0b6ec71d009407eb54bb0759f03682f65d0da8812f84d8e97483f6a8d76a8417efcd9526444abba24288647609791578887ef49780b0b89f51b072cae81c5b5014463da3633dda105b82add0f9c2f065dca46eedd2928be2570493c79a996fa78ea6aec0996497fe2dc444432ade4eaa662ee2255f0f4b92d593288a8e3ffe7a15a10e9d33b0203af23f4c9fd2cfcb6160db63b52810869ff1e65423dbe2c4415884b9f8dec3c968e14cd74f323c89053a96111bc9ce59ec483832c49c53a648e5f0f797f53642ac60170c94b473f1f2e7d8a38e46460b81219b52081263027f74cbf63a75af3a7",
+ },
+ {
+ "68d5ba501e87994ef6bc8042d7c5a99693a835a4796ad044f0e536a0790a7ee1e03832fec0cb4cb688cdf85f92a1f526492acac2949a0684803c24f947a3da27db0c259bd87251603f49bfd1eab4f733dec2f5725cfcf6dc381ad57fbdb0a699bccc34943e86f47dcfb34eba6746ed4508e3b764dfad4117c8169785c63d1e8309531747d90cc4a8bf13622759506c613324c512d10629991dc01fe3fe3d6607907e4f698a1312492674707fc4dde0f701a609d2ac336cc9f38badf1c813f9599148c21b5bd4658249d5010db2e205b3880e863441f2fe357dab2645be1f9e5067616bc335d0457ea6468c5828910cb09f92e5e184e316018e3c464c5ce59cc34608867bd8cbfa7e1286d73a17e3ebb675d097f9b3adfa41ea408d46252a096b3290e70a5be1896d6760a87e439334b863ccb11679ab5763ebe4a9110eb37c4043634b9e44d40cab34b42977475e2faa2ae0c0a38b170776fbb0870a63044aa6679545ac6951579d0581144cdf43f60923b6acaecdb325c864acd2c7b01d6e18b2b3c41c041bb9099cce557b114b84350131e3cee4089648b5691065867e7d38314154355d0e3ef9dc9375eddef922df2a06ad0f0e4357c3ac672932e5a66b16e8bf4b45cd893ea91cb397faadb9d9d7bf86e6ceca3e9176a5baa98b6114a149d3ed8ea176cc4a9380e18d2d9b67045aedeb28b729ba2ece74d759d5ebfb1ebee8ac5f5e79aaf1f98b7f2626e62a81d315a98b3e",
+ "63b90dd89066ad7b61cc39497899a8f14399eace1810f5fe3b76d2501f5d8f83169c5ba602082164d45aad4df3553e36ef29050739fa067470d8c58f3554124bf06df1f27612564a6c04976059d69648ff9b50389556ad052e729563c6a7",
+ "7d5c4314a542aff57a454b274a7999dfdc5f878a159c29be27dabdfcf7c06975",
+ "aeb6159fa88bb1ffd51d036d",
+ "7597f7f44191e815a409754db7fea688e0105c987fa065e621823ea6dea617aed613092ad566c487cfa1a93f556615d2a575fb30ac34b11e19cd908d74545906f929dc9e59f6f1e1e6eaaabe182748ef87057ef7820ffcf254c40237d3ea9ff004472db783ed54b5a294a46cf90519bf89367b04fc01ce544c5bcdd3197eb1237923ce2c0c99921ca959c53b54176d292e97f6d9696ded6054711721aebda543e3e077c90e6f216cdc275b86d45603521c5aab24f08fd06833b0743c388382f941e19e0283ac7c4ef22383e1b9b08572882769c1382bab9ad127e7f3e09b5330b82d3e0c7d6f0df46edc93265999eef8e7afa0cb1db77df7accf5bff8631a320d146a5c751a637a80f627b0c9a41b44f09212f38c154226de02f4906ef34139bbeacc3f06739c8540e37334392d38ba1cbf4bc7debe77c09b35d2200216db15ed4389f43bfd8ae9bf76fd8243c3d869546e16b8e44a6cd1edbd2c58ef890b5a84cda889131e5cd9402ca4d8271052c6b4fe3f2dff54fb77bcb575c315b9109f90b14bc8e109919808a581c1809e2a188d29fd34ce639088a6683f641925f5b4b3529baa34e080bb47fb7ad9b43d0d67c9e6ae7cacb50527fa74e56d0c8b20149f5d332d686d48ebbe634c2b5d35fc84c69a5bcc93b93dedcf9fdf19a1fb9b75f6df9692d16f6c3490377a06294499e4b8ebeaa0cfd840bfa05fde21c0b5e94d13063b3f5da7b537caefe89069cfa9de9eb8f06e4d30125de64716f821bcc8279c0c7ea2e",
+ },
+ {
+ "89c1ee38b6697d0190c87a2aa756892ee09fca095df1e31aeedbda5750f604d9b8f2116e5b8f70ec57ea16fe419f2d213ef72b9be90eb5d7e98f2e398632123e2524ac80b31c6c0a07820848223569602d94fc16a3b1ed8c411bc6c74ed80573fcb1f3afce60b9d5e2c21d04f78665241b613abe12274a5343101a91e91f04e5d1f7959f574e743a10913e0817a32c320467f0178e3b6ad14b856234a4661a755eaf14b5fd88ef0e192e1631d14263d6a954ed388f5709dadc6c0f81d229f630d80be6d593d5e3ad03f9ded53c41abe595981d24ef27ffcc930e4d653743960f4e7ce4e251c88f55c16d2afdaed5e3446d00685c276728ba757520acb9b6bb0732a0e9836878d829e5022794d70ad8440a40a132a8c9ec1d3f0ccaf8c285fff425e9788d6150b74753dedb2ae8b36ff2f310249bd911b9181d8310e00810d42ef94cbb5a9d72a1f0507c1a382f892b23994fbe7360778b7efa9c5e03ac3231a57fecff1c5fa10caf1d26e84db0137049622ebcc3a64841a0e49fa390d1d43550c1346c20d578cff39fb7404fcab0982dde55f0849d312581d0c811a19d46f25e7a5e7e50d74d43760583c5cf335dfc11b2ec964f1dbbd0ed83e18f2027817ea2dffcf2b64a352c4fb8f11eeb4f1bfc01079251254d2112d103a1f12a2270cc026cbeb8b6f3e505abd62496253f93274625786b73997e449c1f35c742a593441252fcc845e1cef1b8f287dd311a0477407ce3b31661f7b2802c79c2d20d06e45f03aca4e47a959c6c1d7a9d377e1577fbf82a115921c3d94e3d9c204aa204a9a5b04d8a2be3269700a035371f4aaf1a42d92b9bfbee74492b106975b36d1e581d6ce2484f09e04fa91586c85f35e2a10f0d3c0afcb05327c1bc9d7429bbcc4627af8f76b86fc561844c2ae3810c84901ac09a1670ed3d31a9daa5d296",
+ "7219bd21a834d917f93a9b45647ec77102578bc2f2a132dfde6489b9095b4f7b740c9c1c4075333ab0ce7f14",
+ "a7f849b054982cc8a4c8e5e53e181feee79e0233e58882839892134ad582da7c",
+ "4c46854e9e101090b1436f90",
+ "ab2e189baf60886bed88eb751bf3560a8bd3cdb6ee621d8c18b5fb3aa418f350048ecf359a7d542daf7090ec8688c3b0fe85914aa49d83be4ae3396f7bdc48051afae6a97fca7b42c0bf612a42d3c79ef6aadceb57f5cfe8d67f89d49add0ea1ffd423da058297239e72a85fa6cd1d82e243a503b1b0e12d7510a9ee98d7921dae2754d7581e52acb8ab9e7f9df3c73410789115cef6ce7c937a5441ad4edf2b7a8c0c6d152d5a5909c4ce839d59594a6163364038c4c71a1507389717f61e2bda1ea66a83ef477762e7834ebcfaa8f2ee61ced1605ba1380108236e1763bf40af5259da07dd3e3d0fb2801868c2e7c839e318678687cbe33384e2ef5750a0a0e2d2e19e869a4277e32a315ed4de79357f6a12a8a25d5b18291316d9bf40dad2d05d1b523ade76650669c700a1c2965f4e51337aa5d45ec7b4981072779401d6d30ed69034053334bccb18425ac68460becf2aeccc75aacd3d6709f07ee10366ed848c8a54904af4ea71fc2117de133f01e1cc031f2a4d0779b997b82682433ee615202d5dfffba6c916f11a00551d56ffde8c36b303263e14adaf45b6eab0bedf344e5214ce52f071d2f40154d788c6870020791a03d2fd4ec5879d9026241954ed45cfddef4937ea3d0d45647f252be31411237983a1be340fc65ebab9a5620abb0e8d475af4e89e842e895eda0cbd283bb5d0bf20236c62d956de733d60ebceb42fc0c9adbf9b69f8d66551b0aca0e260625ad41cad75d752a234af7caf7902c2c5b62f04b6a8e019a6179d44feeb2ad5859ef1c45371e66f1af1fe0de63997266c290e27f0dd62185c53f81e0a50c296a51ace7c90d9cf0dda8b2d7e72a347f64c44262e2a544d1acc7bb05734dc1783bbc1903279092fe7fe434610aa95fc2ce5fc5ee45858f5e8337d8fcb0a468464becb1cef6b7e5ea48ba383ad8a406df9c581f1cac057d8711fcb",
+ },
+ {
+ "2dcfbb59975f217c445f95634d7c0250afe7d8316a70c47dba99ff94167ab74349729ce1d2bd5d161df27a6a6e7cba1e63924fcd03134abdad4952c3c409060d7ca2ee4e5f4c647c3edee7ad5aa1cbbd341a8a372ed4f4db1e469ee250a4efcc46de1aa52a7e22685d0915b7aae075defbff1529d40a04f250a2d4a046c36c8ca18631cb055334625c4919072a8ee5258efb4e6205525455f428f63aeb62c68de9f758ee4b8c50a7d669ae00f89425868f73e894c53ce9b964dff34f42b9dc2bb03519fbc169a397d25197cae5bc50742f3808f474f2add8d1a0281359043e0a395705fbc0a89293fa2a5ddfe6ae5416e65c0a5b4eb83320585b33b26072bc99c9c1948a6a271d64517a433728974d0ff4586a42109d6268f9961a5908d6f2d198875b02ae7866fff3a9361b41842a35dc9477ec32da542b706f8478457649ddfda5dfab1d45aa10efe12c3065566541ebdc2d1db6814826f0cc9e3642e813408df3ebaa3896bb2777e757dc3dbc1d28994a454fcb8d76bc5914f29cfc05dc89f8c734315def58d4d6b0b0136ccd3c05178155e30fcb9f68df9104dc96e0658fa899c0058818da5ec88a723558ae3a6f2f8f523e5af1a73a82ab16198c7ba8341568399d8013fc499e6e7ef61cb8654b48b88aa2a931dc2cdcf245686eed9c8355d620d5e91c1e878a9c7da655e3f29d9b7c3f44ad1c70890eb5f27ca28efff76420cd4e3cebd5c788536ddd365f7ad1dbb91588d58612e43b0460de9260d5f780a245bc8e1a83166df1f3a3506d742c268ab4fc10c6e04bca40295da0ff5420a199dd2fb36045215138c4a2a539ceccc382c8d349a81e13e848708947c4a9e85d861811e75d323896f6da3b2fa807f22bcfc57477e487602cf8e973bc925b1a19732b00d15d38675313a283bbaa75e6793b5af11fe2514bda3abe96cc19b0e58ddbe55e381ec58c31670fec1184d38bbf2d7cde0fcd29e907e780d30130b98e0c9eec44bcb1d0ed18dfda2a64adb523da3102eafe2bd3051353d8148491a290308ed4ec3fa5da5784b481e861360c3b670e256539f96a4c4c4360d0d40260049035f1cfdacb275e7fa847e0df531b466141ac9a3a16e7865947572e4ab732daec23aac6eed1256d796c4d58bf699f20aa4bbae461a16abbe9c1e9",
+ "33791b0d653fb72c2d88519b02bde85a7c51f99cfb4456dfa6f84a61e10b4a14846521",
+ "a0a7b73ca2fc9282a28acc036bd74d7f5cb2a146577a5c29dbc3963fe7ebfd87",
+ "eaa4d916d261676d632455be",
+ "c9a631de470fd04dcbf8ea9f4d8ac37c3988878b6381707ac2c91d3720edbb31576ba90731f433a5e13582aca2b3c76ae75ca8881a463ecfa789910d3a776a9ad4800521c6baa120b2f1afd10f32ef8da63f5b69f5e5fd88ee84bf66b0666b15d05c4050f5358a050b9d5cf1503719f56cd48ceba78f29efe2ae8092e37f5134df526831532f86ccb9339637e2c9e9b9036f83cc058fda23e826a188456e7fd3f4ee20f4e4a3221883fe3232b49db607b90a8956133ab95051c9ec33a908ea7e81a1bfa7bd06c09f0143d07bb23a3feeac7f0d7720269c93e2df19d03605828c8713b84d183c9a50954c12fe3b047511ad15ef03a63355520cbd224d06a34de67a671368e6a8f9feeefe48fc273764a8c69c00314e5d693f159cb5270544f3c4e1760b0529e3303ab308e9a6d03835a3a42aef2df5f7643696f707a574d1dcc676aeecdd9947ebe8c13bcf15d30b2d10d2cd95445a307c1d22d39450615ad38f9302c6eb9dc05764b0503d6a7eaff9feb94834853b47bc25660207be3e7c0e27cb3127b5402cb016396e5ff07ddc3df29861dd68a17f53bf660b23352b739d6da72381b8d19a9fc95da7efb79330a2b360dce4309860af429e3fd10cab235c4acc1d80d9e20d67019375bd161ab65648400f308815afe63cfc717f7d0eea150e687caac25b6603287d44dca4a7cc2f67c3bdd54450bd3170340253b03ba054ec003070eddf9c14fb9dc595e228e4968524900cb5d85af6d1e658a42d744e0e7eb6995023823a8dc33528c6715b2e1aa607782c8e1ddddad72026d657bf122ece8685f6e92236e809139325e4a3c069facf94c10b7896995bba01eb22c7b3a87ea2114a7649d7ed3e83d223e5e785c66a75119beab0968d3eaf0cbcc2d7ede95d024041e6db39a880ce3e19efea32fb89a40a2aae22f407e5fd615e51e48dbd50a8b4ec27ce95e2ba1928bf699d0418705482ed0ed7acc858dfbd690403c74667a88dd5221bb79940c6c4a268379c10343aaefb635982c14f33ad83d47ced9682961540bd4f75804d3d48ba8aa67fb2e3a1db83fbcbe57fec9e4ffb1b575e947f8bd8263c680357960e3a39382974774b5a013f2f8514b3c63c21dbfd314fd5d927d82ba616d76629ac018879f54ff84b5808e94af4fcfe1cf8845b65208ca5510b5b593ce6c109611652cd",
+ },
+ {
+ "c335b055b752e083554b5aa2cbb6556cfcace658d5c11b6b000256fd89e9b24c1e62a2d5b582580acdb2ad9869020465aeeabe83acd9eeacdc44aa652d5cb24bbe542073d6787ea32b2b3c942d40f9db2bb75ed7914c836d902dd2be89840948d82abbaea23952cd648e6191ce5b6cf912cad0a3165410a781e3650b676e5340980eee3b484008acce6a3e9dc5aa96d775677b8bbb8b323c6e9747d6069a169ea904d9f145e29d134cdbb0118647e8fbae638669efb9a55d50ed33568749f5304ece2193b0bfa6fc9a570d209ef61b4c59a2b5485b5aa6ab47d902cf23f7ff71c5210476e0aa727a01809b9f76b6ebcf58a018b3fbbe5f42976111ba58112b1d322f9312da068cdb86277bfcde66cb3607e3ea02a1494439aa56f302671f1f994eb3ab28b937043f5f7f3b3de50673ecea5dee8ba633c45089b852f0d772892525344ede6b521dcad15807b65e7ba348d891d47fc498cf4d50223d2794c64db9fa9b9766edb430be0c38746ab317b38ba9870a6d1fdabb70fcf89790bfe449b97fe01f6c94502aa0889f0a3bb6bdc65f44d1cd64ab88d4a7806b373f5080f9cf60183cf4686694f0059e2bbc5cf21ba0c3e8046e70d815f1444c3094cc29632c429f20aa06b49b0b52c6c7aeb8e34f7bcb53e93c2cfe2d704a5d0416876742c90762730d160e1869d5e0178dc366098ebaf2cae6f1f7563b555a52dcc194a5c8f718d50d27ee76fcce8e8991f4921fae85ea9476e1eab1364403120698b7ce8fd0a49cf79213f360a17cf1950f104494fad80adcc3bb1207bf250d57dcdce6ac8082a312959672361363cc227310b66ee8c04aab7b5cb33a81c0915e9c770a1cfaae2e8f44a0c65703927977a22fe58aef2f366b8be9a50da9376b46ae7562a82391386831febf359039ac326891bc58c0f2c34bdb6858859fc3cb4e392df65cbe2ec4f02c8425bcbdd1ee2562ab7d229d406d79a9c6fe4889c996c2f68d1fb5bbe3a5e867caa4249b934afd3ec71fdb088c54b15252f9dc1b909e121dbdc7d8a16cc00836652dd1f877ce363eed11467966f7ccb8f1a8d48146e69e04ad76a51937ad4f9cda209451eeca90dbdbd65441ce20fabfc8ce400fb4de136154b87a8b65c92740e9bb91d78521b261f806a2c6279c85ef6ac5fe1ea3117ff7c9f9832fc2aa6fab660082eb22344c1a3befe0628b6551f62a5014cd6194c42b8d475a50f2c9fb58c97e43ebb29005ed7fe54f0a4aa10074f1154152a9067d364dd7863fa082976a00db55b26b5ba0ea40eff48b90",
+ "f5ff810a41d4b34751e9942970d4c9f26b33f24689a4b1e4449b243490afc485af468ff01a42376b2bcb949b9f5e8d0b917f511a",
+ "a74271c184a82cb074c14b131fd91eb05870cb7c73c9e511ec8140bfe2f34089",
+ "2403fe689e239c2ed261b381",
+ "af9be893d5fd23aab42e6a2e59a8e7cb13d4f543db02af87cb0802bc1af7c717cd0093cc8244994cf21189146922b69927ffd5745e57118bea07a6afe7c21d952c13ab636b3c2e461dc9ffb3ae701175360156338be94b1fa7115799831019455cfaf5114010fe45f8fb9c77ec50fe06f2c5a32423edccb3b2210ee1200a78e1a3130c567542377827586ca8cf0c14c19fa1449a2cce9c039bb441b04e9c0a3f9a743b31c828032174fcdb7c894349aa68f5adf97dfe9294d24e6b5fed95eb994397883f58487bf5c57b0aea5268be7cee9efeab370f89805ebe5373ab2e93658fc078955ccf68b554dd5605005751ee8531c35ca5336a5d0ce273370c0dc9307779b86e96d2d1daf2620d67d43e1fb7800ccf250ca3c02eb74047c1d2a2bc7f29fff8320301694b80d0fd975f834337d00d5f0e4215044d52aa4ca21e6a9d7e03f186d7cdd5c48e3765dc926fb0a46bb0f05c50d9f69c9c507527a60366b7dc251aae1d6bb0d9c73735dcfab959f6fd4382fe2a1f6ad07affb0601bb9040f81b55a48f6a6c5f8ac4a2acc2b0c9a6c439198f7926460695fa11e0b0b017e39de5cf0d5d5f84d972b5eee7b5d1e0343b5485cd84b92ad892e5b23f3e803f5b363f2398c11c15be9f13e59922b0d49902dc8483fb142850b4226da2fb84e9b434a34f6bb67f575a9e57fde3354bc3077a876e260311bb2481bb139aa9af55df5074749fe532d7b8a554218a90cc7e7ac69db280bae5d55a174dfc8d325b9909a8da1016d4e162fe5ba70cf8726cdf291f5e47083d9929cd5e32021cbfd982fd0975f6f9baf4322b553cb3174b11c007559879f308419ff9e4e18eee8d3640cec8aea082b90f69cf3c7676c28af0265c24c91cd58a06513198892ce6ce1ab3ee9ac0a2e937b973a9cac06a039a54f8d994c13d42c59187f677352e5feb32a417aebec4d852b2595e7e67450e06dbd183279e3b63022a3813b37257b085bf8454d6890875a2950d20210a8df4f9da746722f62687e92f0e9efc3e5d526d65ccfbcc042fcac7964dbe147932c73924bdcdf62f9eae58d29e8567ffed90048bcf0566b952e986efeae4c477944af18bd243c3eccf8d88c06d07279adad037450cb8547a8aa0a74223f4851747c803cb21a2dd027e7080aed75038cdcecbc4639d87763cdd41829a1b72cedf0d722b180d0d492a5740ea7607b95f3201df352fb1ab28149124d2df5d5ec106867897b537302c3431402348f94d28eebc701ae1b49d10adedea38f1654fbc48885e59e6e6dfd413c6b5a97d8c35dfb07a6cdefe317bf61cf91",
+ },
+ {
+ "4aba5a776ace38b6e2578f0007e770d264e39c49f588ca3547ad2888365e3a811994f8836330394587c8458eb0b6611499fd5d8e8527c3cdd4ec550b4a8f8c632384e786b420cb3be911c999c72aad60270aefad31b27a069ecf11e95e9d4c81213308d554d3103de4d9d6ab04830c2b8dfbd8bead52c44c21d5357f72810193b5096809dc7846c1521c6c569f78812c735aea21acaf6dce84a24df7234e8ad857f3e1346b27f5bd436113e2da950e4deff96e9ba8db692c7db723a105ae795da15b910c8286cac6e7dda8c172b70f61b07dfd58596684d61da8772356f180f74c1103ce97cd947eab3d401df44f7fa4cc7cfc25e280fc002873237e64a375b0b4797f4b4613c9f150090f44588ee8250ae44aec6546ec8dba0f0c1eb281cf66fa4eb141617b32b28441f6ddcfdf02d9c34cc62893b2b64dc2c26b74433adb3e888c7fea07b19c8cf39269c2716b9c35b7625d4a141397d6d5034b193d2657c6b2d6b0ba874c467adeaf3d501ad985d13be21c4ff6b326cbb671e4f4973bba49116a0399b6491394f850e4122969e4644c00b442b3da0d6a4bf25ee22d182b3f822fd83878ebcc713cb183651a67ca66677ea81b58b685a3a8e385d5fbb0147ddfecb558d881c914324c794db443b31bc15c361912bbbcba9e418f99f2a416d190cb29684df27c7f3ff6ccf339800efbdc4514ee00d1a89f12373804db4fd66c1affd467f251e73147b3248033327b0f7790fd7861a51773dd4f78b89e4e24b94df9203f4a077091bb9411eec78dfe3e1dfbb67ea1cdf17e1d6936bbb75b74055495449e9cb52f5749404610cd444fea3f0568e0d35a5ef0c395ab7bf0208044b5c4e2517911a9c351efd31f33220972287253fbccb1eb8f46960a36b68a7a6b4f5cbdc86d668bbf555fde8881e7faa9594da425ff8fb54526bf7cdc4af64899530561c06bed7fc04c5d48cd4542779e901bc48fab79d4d13850ad8247f51b9afa7d5a656ada25b6376d837cb0fa1b4016dfcfc158a39290f43f133b352ed52fab2f951509bacb41284fbdd849d8185fb7e7200f8ab2a07ef2b3b927e18e568dbeeba2c7a66e08cebdc6a6069ebe6656a586652f3905ae2bb867529af6a827b494c97b3a378408f44aaefbe86c613e11e7a44020a9ee4b62569dfc4c462300daec7b1424ff1c1849ca1332367470475c14877cbe76c820cc651c18ab3f18852b93994f93b568dc7f7b0eb5f07ffc4c9384c851fa9071c6f68ddea1ccf627f889c0471c76aff9f52b07ab1b86a7671a2b2f6b25c0ddebb66ac95737bf7e2f493f7665b5265eaa5166556cecfdd3062802724ec24f3978b903d0f0c24e1f0b8d967142bccfed0d354279223f4c28684e9ab611e9ef89a3f25993b5a8b3c0354931780501651236a78b58e7d7814f251b053605f4c0a8e7193b9cc1ee5cf7378e6f3c8fd44ec57bd91e62b09fb1d6bab60cbfabcc6792e6a32ea7918a9ec9180d05a7e1546d5d2d8bbfde2a71b4e427c0a4d28d0b6473ae",
+ "921a401db90935c60edda8624a0590d5c46eff3522e35de2872f6f9394e24126fd8143b68a797c995624fba0298b75eef974",
+ "6a4d35ae03bf277f587da4541dcddf92bbd906dff45d5ff23c0f60ae53b062be",
+ "231b5780fedfb06d724450b3",
+ "ba40968282d98849b19d867f8b564ea5a81d657516099362926bca4cb6e9ae02719d10c8061f53008c727a0eeea5e1e36c9e55c117e9434e213316c96840231a1e356b254a9981d4a6ca3c66cfc61018bcaade1a4486506559e6aa3a86bac980d391d835fd5ded98d10f1394d84bf1bbf2cd3397890d704154802f7864ecc753db782fd3d19213ae65ace4770e1bacf32d61c6730aa5adcab4d7e2e437888c11c29abba4890a17a00f67a53b660becd94092df0598df5ac57326f6860593a519e28bd4a39f6481e1a4748881fd5f0456a3cd9f28d1d1e78dc64030cbd8fdb2c5abdab3f13d6ccccd187e71e989f8c486929efcdbf2a763effa95af62db5cef95e9081b818275c69267022fda4b7fdb8c650b491a785b03d4d0186625962b6326ec3f4e176373da4dc1f83a14815adf82c6bffa7c6967d77528d0249754bb4d17656bc4a89449b16152a4a1aea7eb0054a8892f271138971507d2f3b237ba5b620f444544e4a8c2b1ab4f9168762c27478c9f776c47ee2e9ff05bfa35ed127f0cabe7cc053640bb8aa01f8359b74bf89ef43ca94c48fcd201eae39d1835957eeccd6b3a852f4e1bbfef9a469f42c764481ff8408fe5871afeeae7676b58f4202199aad50a596626dff97c8e60d750cc59da9f595ce12ce9afdce14481cb1e39994de8fe4cce07845110d6703dc59d34734e93e9e57e1c52d61f44143a2d290220a4bad5098d098ee65ea4b6757d8a9bf5485aa3d697a7826d4a285186f5da10eff707566c23c6a15033365bcb498c44487c72d96402d1834753fdbf86770239761f03e0dc8963766441da99c0813e4f1df5a1d018c8799861a396562eb24ce305ca15f4022d83ea3c56b68d9a7ceac4742ec0ce50f4d36273df26005ec2b051fa071b319be2d8a5ed26eb75bc1ea83761b8454db234d15d84d6706cd178981c1f156e6d28f774aee3e9a4fade022e71b52b50aa532b8bc7fe464f22d6eb169c69671875d614e987658820c2f584a4fea3008afdcbb646dba3d69020fbf503f121be3480344db23efdda0d255aa058c3ff66abd3a5fe35db977521608bba7eddae72ae801f4fbb12a1de4133039e046ceb8db87e465e5ede1d79a08c857d59076d7ff858942c31e15cbbdae6fc15c3f9545a0825d6ff8583c0aba8a7d143d27b93f6caefb98c0d83bd8715abcab2a49087f55a9daf9090eacdf45be08ad80b5df5070e1719f68c4cc8f8711083f0f7823a09ec092f22df95fe9e95114fdf82a3f6eed0bfc9c0aa65222609442776154a474dbc9e662cd5dce66846572e52417ee5d7eb59287d07ef60a9537fe1f85c7fa74fe84dea0da235ac7574335e6649b54a6bd33397df4bf4a7976c4ab868aa702766d2bc8d2c82c2d1c2653fc8428b8d1e61852ac185a3a0b416dbcf8eb54c44967ff43c44f2b32c6d4a9dbf2c2f3a587b430aef50f0375cdb4c1b319ac9aca486d9bb321141b065f52f7b6decaf1985531ca7bbc3772a561eb1efb8a6297075920bc432131a5b211bf25e35fa31e12833bc77a9de14c7",
+ },
+ {
+ "6c0056937faf1023032df1e2bfacbbc58bb022eba25ffa020d4eb26f0caf0678af5d0b2f0c1b520f4843f107f0adcc7b5dee66ff4d61025bafb4cabb64d133132e3e423a599549a1d83aa8c8e774444462aa44b00b460bbafad5755ea6a872d4e6b40e3f4957e0229288ea79fc2ebe5fd9020fe4481a9f42ef14a196bd136aa3c779e311d0c333624c1ddc484c9aa7259cb609e4d0a826c0bdc7567adac01da23900b30ac4e66c100348584fe200747eb67e6287268947e3509d5d2b5d7bcd977b80a13f660d4f6956a8b938a82db75eab19e5d2a22cb5f3c9131e278eebbe096b5f49d16c983ac240f3fbe821b247cccb2c9e6e59546122677f49f56a07fed56647a6d3e0e09520d49009f54250c10e7c607cd5b4ddf81b5c4110c6490e9baf56418236211856f5a85feaebafacf92c0c7501c052f9dbae3beb7484f90f334f50b68571cedc67763b5161ebfd5a1709cf18c92112a4cf4d8f43d1895204d8a2ba5e14883a7bff75cc6060cabb77d38a909daca2417befd1bfc05a11c432b47f90c807ca4306400f67a0d92218adaca84a584a8bd4395c93f9b6a4bde9583c79204444634a8473b1244cd33cf980e443d82ecfac672b3f60e2e41ecb3c5a445d9e88c0e90c339a31806e6d79ee52bdc6808c73e8b7b24899966664d3c1a9305f31f0483e24e36fa451dc1d3f2eda05af6678971e2bdfb7c1461c9407c5c466f6b5af34d992a37de3809a22ae75275ddba0f4f9cbd4b18c1acd212192e587889a36bd73c860f0abe08bcd8f00f5ecdb95e1d560b586eccf530df0e5f3776d8dae2a01768bf1226b7ceffa7ce4e75879c82dd97db3c64c06d33cebc6b35854618355d80e46fa79c3e9743fce5b974723c421a077e7ec7dba286881dbc1d53d442a1552700fcb33f83f73c69a0a0ebdcf2f5d461649c4d0712c514ded268a31509f83c1ae4ff4a68e676d29727be641aa4487c08d4b90ff78e24c6508d69759751a1a23690ec9f8763621e8b107295b4bb01bd9fcacd8748e24d996fa70ef6f8b0992f4185bec8e920d7643159f9f604fba394b6611bff435998b2f097a9e948430899c8c752a1e83a061983f00f88ebb32da214399167932a1a83c1b47d09f77593b03cf6521520583ea4483e2d33e14ad60584676d1791779b532c085d238df0d3bae735d0078e0eabd63cc90a2e13d023983780afc8f83b1c14437937c16a1b7c41414c48cf4ae49587ad9fa5b16fc949a749e96032248c4667f58e295f999590dae1d99a2cbe3fa45bcf4a1d3f0356d64d40367f64b2c5cca843e5f7dd7b88a85d52328a00622e6c317879607bc036c9006d38652ffe21c83207c00f8348a7d0aaea5aab4c89077df170de6d41052641726eb6925cd85a9ee01a9e636346340e209ea96d17b0eb0921b96662ce9cb430fb6ac348331dd7133875769bbbba99dc49333950e4145a15ddb0789c4d2ccd38878080ca9e57ddc6cd5452790eec45482f8e990392e319609391fce0beba19463a9a00d8f1de9fbf22f23821de7d69fdfbf3019ed61aff79acfc5a6ba663a1e10da2b9ff7149aea43bd6c61a543008402309df0924de72c1cacd2d6120cf422e61fc1de345cc8771934d8be77d9437a09e06a9b2d51c849fd9a200fa714328d34f36b684f33df6968b827df916a599a4bc3367814fec21198e2213ff653cd2a463892966c72ffd42a26b3bb91",
+ "0d55dcd08b54e58916f622f81761ef6a2e19b167ac47d3",
+ "e42e1d6d44138f3d2bf12c951f454686f18d590fd30057405b5a3dc2b317fa97",
+ "1e46a7486c5a03fd6758d938",
+ "fd3c1fac10cc82e49235fd57f5aea0ee7a7bd6d539b138d4b3fb623aee591615c1a61228ef9673113a3a90a3687a12d4c6367d5f7bc67d422fdc4106455084d79c2c42c5e86368dd164bcbce7925bfffe7d96c13a2f49aac8e9d1ada3554e3fdc21aab00455a0f33b0c1fdea91b3588e7ad301bfccf9940027332fbdf966463491f7a33c093e0a13831ea9d2183294f89f414cf7b5876af04fa68d594430194429df74fa5915394427259e832bc545c13400aef6cf16620d48280798a6e49773c9316d79fa1dc758e54cde2e2cdb856092d83f4e9b698385cb976fd6cc2538abe055273a5b34a784182ea5e7d3ac9019a05de5e5afe4308a7ed2d363cd50ed6a52df1c616e4a82f607ced768445d13ae4884f2ae1f9fd8313924e8a1a8a23905c92eb231f638dfa6f4cb27bbb9844e05afbbe2ca4d1a3b3a5b371bf33c9ab6f82a7387d61cf8bf662097624145a983839b0cb9f4bd07556800b4054fb3d0bac94f44bcc9b4ac49c39f5571fac4e02ff09f08b3ed5add4bf8bba934e9feb773c0590b45c45fa036382f3fe9782ad19107d4630321e414b7b442b64f18fdd5219039e5740f34b3ce8925d1afe8a39e35ce8db086060bab63b9720700499f82db19a62897c6d845389461260303f9cf2bc7235a898b4620c2191ef05604a5c8c783d58009533a86b27c12b0772635d34ac53993ccf174c9087073e5e69b26c0c3d9f768507ac4d4e2af847b65e3a6e1b7a6dafb0aefc190871cdae6c60f0b1d6137c351d4cb211870791cf4cb8af2ea446f6401eb9ec8a5bcebccce898d1dfb13454df6b35b81ed6d7637e6e261e004080c60944f3a08e8e5fc7e2e4939e7c2607c8cf07d1d10883ba3ad43e2611826f245df571857ae0a7a867df9659f2082c19f94ce400132e48c7f8de2b102c7f83ba5cd1e785597a0ba0d73bb81bba0c00300d4bcd6ec25fb73105a46122873bfa729c0979d8d314ab7ea52391aabab513dbfd1cf01c2990c0a3612f4511c2bcf0f5a07e659a881a7f99c3f1fc4a46e66904427fe26a4a80a904c047d090c861a075c0ae4e29bfbc18b9620aaa42237f4c6fa76ee7491ee638ab5f1cf0b440759828e1ec519679efc776eb1468999a00f667e87199ad6891e98b95fb682e02517b024a6bb803ed23c944010cb7bad0733eccc12d6ab6030c6e88d510ce92e2f98fdcfaa1e37e41fbfb4e99589c0e8efbefd40473db42b3a73b57b22a2f8c9bdaab16831f1b117dd83a77dd01ee8d0c2e92203adb670f4fd65e618823ad196220d70e014c1aafd8863797c61c16382c2600062683ed3a180c70891717c52da15191b02f25d1715ebf33a5e6037092421989c942082f4b836423cc3e976c9bcda185de36f06265dfc250a27d2de0bc48c73b3bff704f3b386f962522f572108458bdb283c6ab3fd33b3ac13a406268fd5d97e17db9c0f780b4b2a8f761d15a4d8b3a0cd73357ecf4d26a6492ee069f19325823ef50bcb2f73326719a57b67eeef506fe8915a1b1ba1a637592268257b91e9c7c5d33cdd947967efc1952005d82ccef9a3ad7ef8ffbb6b658983d64c51242ba53f8f8963245b87a25aa9324c527e53f8c11d55f30aab598401589acd13f090541b3b057b162190f27910718b02a6b8ddbb8ca6cf40bf0d2848f4b76341bd5e78f476862bcdbe2d1bac84c0566fb45b21388221ecd8483d99fe603646b1a9f38a49230cf4dbe5d7883d73eece01bf",
+ },
+ {
+ "04892b94c65685f2eba438322b29bf8439938590d3e0eb10a29e279d356cb439f6dfcdbc3552af21f7e753221012a649a52bda780bc589ae63b04b981dffd113df9fcf14f17e35e865880a769bb1bf40dc99b9e85e4296c1f2e1590fe02b22bfcaf2d4bb7009a4d692ae4c2d5f0b6d3ca526240368bac55b9b1e6a7b498d3b137f0fcfef1873c5aa2111d7811d45bdc26be1c5d49b8a2f36a999b1f226ec06a5fbd59514485abe696c96ea89dba74b4688101a239b495944e30b3609f73caff3114407599ec5c30a5bad933655de7dddef97018ae15acec46504cd5d417c5052c057ac5f1c6f69781cfdae71db2b4fcac35054a4aa22681027356d68b2bdba721466d130d53ba8f23857631382b2de450232e9ad5551bd7c872ae439e79eabfb057d2bdab8d4ccf02b3003ade2e1f3e514dc92692e4fe5b579c9ee6067995b6c168647ce5a13be8543c23326a3260bb7029d2030ec05e565ced3c5366d20a283a6e95201fd108640d2b96676df712de20e4e12fa53f85f22cb24583844fabcebe40eece11e7221f12c88670bf994ed08e2000236f86258c386b0fccbaab8b68ec6a26fe41491d540193c4c12d1391ab3391de9317f41f505f1f1d09ca9862a6f289a533d2b297d4465c956360371ea3c8ed36e0d1563120654e3a2fd69cd6c9267bfcf92e84cd64e162c84199d6e552b42c33857264b5d7a2e007797cde32934a3f8c68b459cd95bc85e7466ccc9910e8dca65b315c32e43c3a5da908904c42cfc8ab74126919ceeef1054bbdae6ca67b02f1ac5f24808b5eee24577e609a3e3935a24b9ebc1a8dad1fc96abe26012928f2d5782755f3763427dda28867d0b1ad830d3c3f17b9ec278346e5a9480ed23ad44a523a4dd86e65a610ee0de1afab64ace7a3b4918fdc14c6b1ce0ec0903994da9bcf18643d7e0a4e6c08200bb394a89b385d2cb829417eeb0f7dab9fa7306a330f82973cf0917b5ca99b585d2ff0e8584e050077467f5245ecfdd5942e4fc72dc26e5ab2ffc61f996167e68168cee9a6d3ea1e1a696060465e35da8c75a1aa380004faffcb0a992c627fbdcb4e97721271802cdaf08d214ec2fbcb389d75709d7a6b9d35662661c8961f93d4a705e7188613f3769114c55400809cadf60d3b6068c8a5ceef078785171b59be1140c6a754ba1de5ced349df63d67d59d3a8ca3c716ffb506772d57e9e3f2caf7fe346c4ad64aa6c37e43b9bbaa8f58e51bfbac31fa6137728f8e5b728025697e5ad5c8301f6ff39eb2ad595d3cb24257adee88a84fbf1ade4d7550cd9ab94bf48e1424ae83184c35c5a5920157d45805c2e0ad129fc7f0ec3c41b9d6fa04cb8918ef379b0783d1cc2863cd80382585fa05320ca4f9fd90353e490b384ed6c166c6f802cd7bd39aa43667246e8da96992db7537d472c709b01114e95febaac5b1a3c77e1e9a18c2d180e63f0d8fa89f6a1ed63e909e4741af5c2a0e47d4d3f8779b7696358f58060f3f461cceeebb390c92779d30bfdedf1b08ed62dcc05a545bd0ea915f42976e81dd8a50cc4689d8d8007508bf53e7da5bd43c3894968cf0677681c6b818353af6bf8ac205139add1310e5d363ccadbfa0eaf735808325e7f9a6aeb1bee3ebb4a27576a88811859c216b6f84371c43d8063a0d87bd326eb6d81c6896ff534ba2c9c14a51d2cfedf33a5c787279bb4a7ff65706b389756a6191d2f791254233ee047d40d64c2dca878a42f903fd4382f39a89a723fe11848fe37b2008be53f7c2d037981d6462a4eea49df1a2e074957afd3c9dfb4d218a309cab395afe301ccf",
+ "67b5eccb1790babc2dab5e0d1ff3871c3024177d45a2ae",
+ "259603e1c3af3fd0ce3257eb627b02e0c0a48ea2f175de3d8c36570a445e5369",
+ "e14de73c4b17581a7e0d0649",
+ "33522e67ef932da5fa8abe628b51f3abd5049951dbc982ea95b7769652d4830c588fa45e3fcff094c8602b9008d7b2f9bf6c1c4a8cfb515401c7c44a7ec42ccb967722a710199e121a41160b1ec581507e9bd2e2e506b10c4b5a8d6977435aa08e27504957cd49e756e1574c4ccbbdde937de35128b7ee3455d2e665c596c2e97c253c94e405f85eb5de84874c099b4a97eb8f492d28f2e4bc64b228dd5984e76ca08376d7f1355ba8e0fa60fca96635075417d8b436278e0fb91e3bfc7d61ca8c7407086933c061b2d318f46f352099e1d317d6c44098539d1d2c1b7894db668e7a82ff991864fae236570cc420a4229883f1e2242d05aa07e175bc6abe11cc643cf1786a4456a2de8c066fb1a70fe387f149ffbe8cca7b110e256fd0c09b1d3bd7381cfa82fa700c8db1e79809ccf75ea52d0b349264557046e8703a191ddaace00ccfc513db5e78810eaac0a99d7bb1a5725e722d4e595216a0e12f3a7aab2e623ea9e1dad06169914bcd51b643016fea7dc3f2743b1e65877f1fd5581bee5ef206d86494a587ec8462a170746fcedb2c9f99090674ee687382711b4610ddac599732453dc063518aa36f5b4129098fb9fddc02eb8f8cfc2fdf0d904ef4d6d06014f977b29d0e9aab4044ce9c662a18b1a8db1ceea97854e90704430fe9b1046b221b27ac79054fcc68c3abd6fab7da66e255ff0cbd0506c852e961e619615c944cd9a05c25abb63742f5da7bd9939feb0f2f2208c8ce82f551a9d4d70e935dad018e3e4e6998e39670221601c3e34716ba75eb4e2fdf53c4d471c444330514986de45cf44d77f793c17e36a271fc65e6bf08943aef4c66547dc310c7a430e3fe7a54898de48f69f282f52bbdc4daabdb325cec7ab66fce1aea4e2fd932dc1a316c821f5220ea437447feae2fa478adade7cd515a27d8c132d0299b3ca1bc8516c9d9e7c65c38c238c69f03e104eb42a29cacc8d79b808ea6fb233a5056201e3697f81a2d49ccd8b8efd1ab0fd407c16a210767d1d3ca798ee53a4bbf1ce5090d321b1a64fc2c5f013c23829f5b0d2737936ca71595a1d02711c8a7b0e74654e5d76376ae26977dd49c68e3c0a7b36e047d44be42d732c31f681bd7b1b4b339f004ecd847960377acd005debfab13d0fb88355025877630aff753a7cfddf6851e8bcc8ec37b8f9149830f47e6b601098b2ba19a4c0808e31e8927b2525cb82bfddc9b4bcba2b46bbe768ee278fb89010243d16f9679f5ba4f13cfe76b5beb16c7b28daf99b0873098115c2233ee3402ac0f6c899a2cfcc83b2ccc06676999ad48017c4ace507080a26501993327ebdcbd1e2eaaaa99f4998b716cd9e36eb26b4573a03fd1d18047198fdf675ef4f979864ac85d230a011c69d8b6c45e9efbdc2a03f195c9731b4cefa60208ba845c0978e73d082bf6d6a513b93dc805a4f5973f4158f60a200167ca88704a15ac5ab1f38ed455a426f7c6a96b6bfea2ebc1ae1247cfe5ff29ee81bdbcb53b03b89568bae9a6f311d2b20e31c2d91bd18fd93a37be266d0de8015d52e325f78356dea0b77cc76f28e0f06e4ec705d1328340013a77b0b6196f44b7712fff4ae0ac7f6afab9456a95012b7c6d387285487476d189977e28f6c9d1a3f736320d61302c2d627d5a7ac8cde4988056b55eeba27efe7e640f94c115762ad5849423ae138c76f15b47bd2a2bde2c492489b7980aaf1c4e32a155f858d7be4fcd0f8a18e7b5d97c5a08d7885d6d56222ef49542c7f80498a14a8eed1c092543aac3439966d5b5d0cb9e602f4fd795c09d652b64f9ab67e38f48c88d18e30a9774f37e9c77b7a94cc7310d",
+ },
+ {
+ "4ab8068988d4bbe0bf1e5bc2fe1c668cbe58019c958dd2ec97164aea7f3f41c9f747527f1c0e5fdb2cbb9d2ad704b6955cb731f14403dddb1a28c5996707635e4eb5dd6ac33d46eff8e319cfe7cf6443869534ca9812a5b23a6b4ca172afffc064dc2b28197117115431e03c00447f87d9b45172c6f724006270a1d41fa094847cbfac9630c3a785f488c1f5cc407ca6f4cd18bac43cba26ad5bfaccfb8f50784efc0e7fc0b504b43dc5a90a0525b0faf3c8b4b7046fdeb1cad87ec667ce3eb6cb4c358b01393f3ffee949030ef9fd01c1b2b9c5219777eb6ff5b1d7c3ef8d8e3bc2193dfb597cf942c5fc50befa527fac0b44cda2bbb811b06ae87459750295371cd232754e2bb7132807d1225950ce64949b0650531800bd0074177677acad937ee008cc0bbfdf33c6b0552000238494be8be412a3e5cfa359e619d092c76310a76bdcb22abbe6f16b3b116b5f95001d20e42fc3c9ff6723e580f378475788eec265a1ed2087de8cc2eff72184f73fa5dc6e68a56dcfc85350bccb97135386d5b827c2d9aea065708f5c921454d1b9303f21d5adf19e00415acbd86d1e5e42d78505b033a515a435713649c50702f54623cbf31469f355c3be2e30dd8c72b4127764451d79e952ea1f9bb0269da56dc07060d5d9542a9c1258ccefe53fa3f7b6073cd38026256b45c01b6c5dc0d91e3139f30a8d1da7a076738f5bb23352693a8e3cbbb46226fa22416680013f9e3278913d06aee4a62457357f0a68d173a360af5e1411840e34c574b4c6b352f92ce33632911ad8b6710d357b7607ee19679e777baffb8ae3c0fe9786b2e97fdeccb5105ecfe81441f549bc6b50ab84b749fb33f8f6bddcb6bb733d6d5dbc4b29725b8741439b8239e53fa435ea29ed3324202b1bdd07d1987b0e06d8cb51013dad897ef02401290940ce3f2af72c5d1b4c8836299008c10b16c7e3e119e41ec66d9db6929ee09bdeaeda08a50665c052edf77b7dff3d8815046bf71d5015e3bdb29a4f507aeb2e28c536cdcc9b8d1e89849a0683d78f99dbfa90f94aa5dc08587657a8f042d718080de5d4a973f232f78c387b63c7143fc2a4380c491414a18b6c4a7bae2194b62e798ad7ec7d09e409425f6d0973accb17e4d860f8ec0283584cff076d93bd9b0c4873f9c57cddcebe3c3bc8afe793c6cb6b26c4582847b07446b7e1d9757de6bdf0df826cbc502bf88cf3a773866d3ff293034abc4afa3091b2126a278f50e47f2f66ebebb616e342098ab690f7f5828bf8cc4742c677d378893e9f188e8397bee983a9a0998de2a31798330f8db59a8581e1c847589bc0e2d95ffa68e39226cc15cf6cae5c4f5174e7848375391dfabafec202565ec2383721339f04c5c5d1da953d88f18cda65745ee8e99805e35203a6545a0416923b38c5db3c8aa00d64354bed27d7c78c4b257534bd7a18107ebe64d8c27b6afdb330d8efba79fd1fae480cd51fd3626bf8d79fb651b7c6cf752aa737a5123558420d48fc86451b358d270aacfa6c17f343b7a9956e6f64e4990c1b3f1e5097605edf5ce4247819b19f245e9a90758dd42c36699ba5cd7f3ed99a7df7eb155749f4b42d192c47cacb6b2865fb9ef2cfca283865cd06e40cdf7f89d76a9e2eb393e2e0ac0e2776da929f3f8e3d325d075a966d289c51347bd0bd523a5c81edef63ce9b72f5114c88b08b16edbd73f518096240a5b37421843173be8df4ac7c587a17ca6f2916f7d9a10dc75f81bc778a1eb730d12b51555cc414eab9c066113a7edba9a7f1a18092ae47f12f0368ba211feaf34a3b48a7ff5c91b81cf7c95675a4001c95a19d284fe4197fe8823909a123fcec5e45935da12416be1bdf14918414ad19b54a41052f5b8417ddbd207ee01d6a3e62fd9b0321b1c13d91d6ce15ea7b2ea0c670a5f5cb290ca8e62c26c6499104ab8e9fafb05170ede246bbf7313625d1fc9576f1609ffd08852a2f4b73c04f1f4eeecefe3f3eeb2185a618b6dd3e87d9d3fdcb349cc83c21f26b6c662bbb857aa95378e991640a160a23cce76153c134508c68ec54a5",
+ "0d471079ad3c3432b6de852ec71692d12d9df4f984554d458a9dd1f28a2697976da8111ae4454c9a23d1c8eae75bbc14f8b00e7c065bc290f8938282b91a1a26c22b40a6708c40945d087e45633a595beb67d8f1c29a81",
+ "f3dac58738ce057d3140d68d2b3e651c00ff9dbb2ca0f913be50219dd36f23c6",
+ "bb2d033de71d570ddf824e85",
+ "238c4e6be84bfb151557327095c88f6dc2889bce2d6f0329e0c42a5cd7554ab16c8b5a4db26eab30f519c24766b1085e11d40823053ca77adfe2af387b4dcde12bc38502229510606ff086265f45b1087375dc4a022eb0b641101c74ad566ab6f230133b7aa61861aa8202b67beddc30dda506691a42032357010d45adc7ee633b536a2fefb3b2143837bb46db04f66a6e2bc628d6041b3d306ff78e96205ab66847036efa1fb6e6a387cf8d5a105738be7163df9da0db48e3d8fd6a786f0f887968e180ad6888e110fb3d7919c42a7f8c92491d795c813f30ea645fafcddf877f5035f133f864fd0ba1415b3d698f2349ebe03d9e76610355e7fc23221c5c72b1b2628a40b14badf93288fc4abeaff5306d274f21938650ab236a39496d3f8a6e9086eac058e365d4335b51eafac813f9175bb7bebb75605909ec3fde6515694e119f7b6e96aa1d6d6454c3a7dddeacc83bf0c1f5f6c2a9dd2f460f3e5b074a33b8d7904e6988ae43a22a87f0933f812e45c4c518bf83e606bad4c3c55422ab2207e9d3cfcbc5819049f55e35b9663273d9d3a6f8a897fa38b0dca77eb6c344290cc007b68d913187f2cd480a40262623a4e95d90d5701ac2b9d858d70a27f0672f919c2ded1fb89134ac9a8ba6ac62931c832372abb70e811dc50cce264ece65e87338231f18ac007c5f68f3b1c5904ffbb2e1dc361d53914917770d66afe28c547d8cd5896d892cbdadc34cd6af348c93bdb8b072f38b085361e62ded7a38b4368824c759ec7d2cf4caddb9191e5deedc8b8388bc4ba2c0672321bcda3a7343c9ea71ef03750912f35624d81da5fa8a6ee676c4efd99d0c7258b844ded7b35d8c8233a316b508d79c7c0b3edabad5db9543615179b1c111bfd78b79327ac5b4155336d670baa592d441c810cb1b7c07f3d35473a45b57e780b7d997782aeecfc0363976fb608d6967844ed00b63ba75996054d090aeb605c195b1ff86f9d9ab5892d27632cbb59c06b3ccd69d33ed5dea9398f00b7c6404fcfe2fcb5924e4cb75cbcae0a1b084ea8b15eaa5847431e9ab70e4afe15b4c82239f6165e243e3b76d6c91d23b16edecad8bcb16898641f8e323671452034a8ec9b42b29cec0db210bad0444f1c5bf3505cc41d514d5a270d556f0a34333bd06cd6509ba253a6ba7a6db8f1a60c99f0c3d566a038a72f1271a178cc3ff890b0df1e7438c0c1a12d9873643e2d7bfeb92379545de50834abe2a345faf7ca49beeab87ee516dd8598b71196b8cdb15e7200cb5bd814338babd74c565faaf33d9a8ed4209b417345a1ae611880ea22ab2e894d5d14a28fe3835d3b2718125f0e6daabd85327455646290ceab89e579ed5e1d72a0172e4a6d8da70290b5022c941f3866f96cc4218de5d2622d13af6dab15760a1ec5d10918267f9585284058aba611ba07b1d5711cef505869831699bedc2b190fe1d578814065c91d87a8c8dc9b0d4dae0c80cd241f0bda3a6d5e714c894b7a48b1e5eed4555f103eb03c9db30efcb855df422d7451a6d70f28174c7ebff536dd2cd2891f6c3f264d632ca924c4e0d84b37cf8e06e6f2e29efac6cf008cc27f062441278dbc9f09cf44987e0e9ca088a48437b0b89efb9cf00d3d0c5fb449fd4b64e21dc48cf300c2d80a502cb583219f1881e78e647783d91dd2f3b389a1594eefd8ea07d4786f983d13e33cf7a34e4c9a0ec4b791f1666a4eef4e63bde7a241f49b5cf615888bd8130743bc8a6d502bfc73ab64d1184ead9a611832b7e24483a1a0fc475d9ff6166b86a18a3dc96910ff182cf326456c4461ce8acb3467f801890eaf1ce0b24791da9c650876e718c0bf43c475174f9712dd4a228695e8f8b2b23fc4a06358b4a6a8e1afa87a0280c3e098f218f7a6d6bd716f8c105a7eb799ba0220837fa5a96c8a22a826a6f7ea9d7216a24acbc7b0133210cc17c8190507badb421bc54997ff9340cdc1ee415126ac46a4fec9fee12d40f06300f7e397b228250f36d6f0d2ddad5fe1898ea690e4c7cc3a116a70bfaf6d2dc996753fffae40ba5280b8356b7ab4ffbc914ec74eaa070581fdd1d9e5aa2",
+ },
+ {
+ "4d81b652fee892d575bd13dad913d976cf0517c819d5183a72eba995b1f27efe743451721ce34791a15a6b7a6e44f13d4a080563dd1d9d4f0946e5ba3863b9ac970a1fb4ed66458ec1b1092ff5fa6c3f0271a2df8e3f2e97851352be760b6a0e1589c202f00791b1b89ae0ae944ced96bd90754bcfa3e355b735132d407d3b5507fd57f705e8a8bd82886b16d459ac91e921dcb8c5bf0d7cf420a9349ee589a5e2e19ce7c944a54ccc1062a0690f3152300d0bf5cd1871c1391bf6d7007f7ce26018ca2a5c6f76287fd8c8e9e7f93b1806460dd35f7f95989a8b6f9a0aeb7c6b0346955fb50b8735e34f1ecb4859e34ea0f022ff6fb797094206a34cf120b7f4664c531c57da513b296f0671c8e9bf68d9e1674998fe52da04f627f516dee97c2b3c988216e9bd3f58c3b021ac70898651f1cfeaef21c4f417ebe92dcad3aaf50f4277262c356584f816a5a5862f2bd720fac10f1b86033371ed603bc00a30cf4da8f579dd5bfdd571a37af7d2a5cef29f9001bb1605ee87f24ec3b259f381a69b771f78d21c4e43bfc83a916e08830d9885c8ae8ab6367c05f92e5eecaf0488262300f83f4e3bff177590857e149216995bc52311fb9f16f4cd74e07c7868a39b699bdbb7d7dace4c6a53ca7ee6e11741a63a52a1d96995a6dd752356dec6f14761ccfe38a6cd8511204f8f0630a747d6e19a77bb030c61e0828436604a28a7acf4a5e49b7269ac93b93b99e9e2e1c0c47b377f7e44e05ec6659526afbdcd5bb172404ce5a9f8786234114c16f20cda6d4359eb873a4a4d9fdf734e9c40aa4db3ea9a98939210f6c62142dd144eb78191116d194bb766ea96da38321ae27fcdcc196560ac75567297984fabe6072c771899906350f74de6d18518eb6898b934b11e945d94ead02b821fd6682602e03e9c70a1ec67eed33874eb24dc83dd1035fba5928f8f62ba1282907aa8935ae72fcb881b3277ee6bebda8fc75d6cd792677c25f70c87b11e094298b2d5f39904be211ff0980e5b83e8ea4a455622d8be9efdb5aa8466c88ea861407d54d98112faa10293af5e16974861dc9f83b45d21b112cc367894c421f5049e49dd205bd7c15e6a70bc810704e2e3a3659800864912527f8be743acdc474a26246a81fc2bdf669b9be7a2a0c986432e1e44b5675607e7e1ee2a8dcb72d8f1964272926e52f909ede0ac8daa32d1d850158db76b959e4d83c9da4e3bb23fd1f5b26463045d6cf13d187fe74a50c09a654d52d0e2f01d66b9f8b4f4aaf4c69fa62a02aa876f9bc4871aacd26a6c6ccfb9bea09cafbd0268b5b65d60aa23ff504d02fad4719698f8b044ca1bb037ea6af58a06a448080dfdbe6a5d698d5db9da5fb4aed04a46c8fa8b93153bca00a5bf8aab64d2b371d072db2ddb688a9442e948f0b99236828dc115a2fddfa2a29e2d4e02ff0173cf734efd4eb687e3f8712be82abe1fac4be0c1eddda090803fbdce41bccfb58c43038991ba1074b281a09bac5eba58a99a1a9678ba26f8f9e3c63ba095f02cd8f3b56aadc5de60477efbf3dcb54b854f651cc72042bf19268554c61b44f2f338a75de56c3c45b3ba40a697f5f21c4557380c777bcc91a151e5676c2a59606200bd476cf98d20b4cdc64bc3b8670810a014871be018bc32fe239e287cfe8a7cbcd1e8b55e08692ccfb4ef871cf797bc0b1fd7ec37931e35b6bc5d32bbe7ae77b9962c179f96436e4a32f566298d2235acf921e38c3f1942fb7674b65e222d17b95a2e58f072c63aa4bba1ce48c303f4bd24d84963f18c5e670015c52342dcdc9c0b348c7dfac721b568effe2bf2f2e816ca3279bbbed823beede8e12fc5bdccd0f1584deb1f6ea1875e9fb350919b675ccde0178bb83a4aa5232bd5e8e9a1b8daf905c6197367a0d106532297ef89f3bc690b48224592c768bd9c50a63d0881370d475081aef052b444744b33fd3fef674a37898fc950f887ed482d2a51ae615ef5b1dfa3a23257e6a6a319a4e2080b2c4094bb09e4b390d1fcbefc4d6c5dab620f8b05b1bd5d976300b007e2b8120ef8a6c9028b7d925c795058c6bdb6711fc5fc2476b9810d1d81bd24637537716edd3b7068b802c531531df710d3682f9865530e1ed51b3b56d860ba4e972bbc74662cdd1e2ea24f81bf469193afc02b14143a32e9556e3f2ecef97c65",
+ "2538d98b64b6aa9258f9141840a5abef66d6037a10356366a3a294719c10d6c148b04cac66f63ebff052d730f8821f5e5822d869573bcffbdd636c7973433abbf38767597da5186df8ef9df071bc4ecade2633366102313e659db8d8e0f293d379fa2df79f456497",
+ "a5049b0aa153e282457555bf6f82b60fc81aa6fd1c2ea3db031478ffb74b5b5d",
+ "350287a6bed5709dfba3d35c",
+ "849670914f5fe318eb01e8849e536374ec11e813acdbbe6a5e82a506f6aef4f916a3a7fb2e41db3adf990175e21f2386d1805af9bbc32a6ac156b13b1a9505958f68599019c4b7297314229c467114754277b10e9f49a4d12837ef24184629c8902ebe2a23f740dc826b01f8963d47100bf617b314835e436104eb207fa9a1079b8feba06d9369b9aa8222d38d87096b73678bc5db9a1add59394530e678b6ec93a80efc6e8320f2909e3e891306d69b016ade0d30cde64c2c903b401f9d01a29b5cb8619dc68ad6c21900b365a6b657f7d9ca4c145fe598a94eeea741e20a9329996b17aba5d7115c93623f2f5d6927068d0f190b49eb885429d771bbbb3980e9293e4d664a71c3cb629d869dc97e58fc3d328331b11df19a38d61e1705ec4c3d779168abe049e9d675337ff658e00d2d610c8f227d1341d1c41f1c01d8b5d83c4b1b30ae4318da9822f46402ee8cd5cfe9f3f22d90a5ec2d0aaa0baa85e10f5295cc6005c5a0887287b0c867a23da1a4c2196f91fe0bd4f0db1ab324c26fe6088d7583f3cd052b7f6fca38e8b21f98fd07fe78b7657da1f586f1fbd3d2b4079e20f21dccc0d269d53a29deb7c7fb63cc291d1d2c50ff163e08ce612310d3bd622f2416e193078ce4e1463f8a3490578af96ca98e665468281f1af9117a2ed23367df19b570885de9d6594f09aaba4090bdd1079720b08d54311793c97bbe14433b031c865b059cb4f75db74779b82c4f83eb4bd829c62eab995027b548063d7cab7d1a6f9642da6cf7181c0ac71594b97fc2c84b1768f81eb287091f63c76623c61e7ba90c922c74d46b9ae5d8094d9752bc1e8020a82601c356a201e0473d540053c707a88f4baad37826152dd245c4cee6b0019583c61e4327fdf6bdcae53584cdba8a503b835bfb5df9d649705fcc1f09376eec96c3da1e105accc1cbc21d90f527041a9beb85f8cbb1ee8db798838bb45374b741618f83b5d0801a3af2f640abdbe74ec3dc15d6711b4c1480aa8d6084defba82ed221ba359c9744705c4feee0955c27ef468cbb816694516f73fb541e0ad4ccf99ec8b67ef090505d1f7c4c3a8ed7e291c820261f12d92bbc6609da6c275349819848c9112826674f243acb9a29ab73f17c8f8af12c7437c11972c824f00db7ad284e51b9b508a925f0664bb259b4443d56463bffc9e5d845c9b9f79b24c1f457088fadd281f48238866e0b92d6253638eb188bbaa8bf6a81d2b1087904974752697cffb00b4ba05e5b7b842a3d2c0a743e4bd691625788fbe9df14600643b1d161bb2916176b6ee40aee38dbb594ec2735d41369ed3a0c6dd9073f1eb51d1b77eb9a967b53670a8ed755f3b2b73a6cb50a9e1ea7549346646dbe4b801c8aa642779d8761b6c2d2e1a9995e758ab92f07c4eb4a23c042171a4b354f434ced5f6d9ccd26cd6c2506e5023dc076ced15566fdabc7364f4a8594cd6ec404e1a9470f52a83052390e4f7789ade9179b069d9f84ca2c7ac9eea51035db817845aded7405bee90cbe92364c8c7cf8a366cbebd7a972438f2a9881395a8610a2cd0c06c46b60cdae5b1f473f4fd6ec48479cf35101656f05485198a470cd36af22838e7ba3e28863cd8ba7bbba7e3c2625c1106a6be44c9e3d9b9938679b26f0713c62c3757a2dc8b2d9eed5e652220a7711cd220bc91a9afd7c940dd8be71616ebb8b2cb0686dfa161c6ef56994a3cafaec5e79bd0a2531fd1c1a42771acb101a38988bcba51ad85bffcd8c67aebec5b37d526b29f7b9d31388e1e7ad7154f8e65516f0d80a30b88c2b868be2541d19ea1d2bcbadd30e2fbb1b4678bfef7f200e0f8309ac0701000c52ebbcd6fa00cb85c8d3ea9c5aceeb3adcf3773cfb3bfc9ac764d031d7c63ab888e9b03eb9fa74554dab4719d426d0875a508c8c86b22cabfeeb70b0f1461db4e5f639d2a2d28a089dbcc48e3f34394ff1acb887b89f75d3236c8143bb9b06273c3878744340ea1858a9f383f8bbdc259250e23a3c3992bf8b7ca7e1a66913547710402bb538a8866772d11cf4214060ed091d403e1c9ca3af75859259f88656a1cfecfdb49d57c193e60a2223627c681a2fbc7390140aeddc19df035a5207adde4f5736bc542bfdc943ae8b094f4a8701618688fadc2284fb423f602c41ad8ee11e5d9fdfa67fb7dc7d4dce7847d4875b3af667168ebb6082f6911c95",
+ },
+ {
+ "67f0494a728fbfc84e2f4a043e121ee40f3b12b31616c78e157ed970db28674318b08d8b3f4c538d7b9d91b9b0b09ebfebb07201c6398fdbb8684c9390b3d6a8636333a3b086302b24c2e5d47283935d33065efa3fedd5f755218be5d4618d38c5c1db75470ba06bcd853f3f08d39c3cd9fa3618e70b103c2d9b2101fcaf39c1701436b720d723ed5c622d6535c9a10ec4d727abe237e80fd20911ceb84a90285fc6e07f9d036cfa65995f9b6300a927d7d0d2b907bac9d9c4daa87c2438a583fe85029c886f96ed08f5886bf53292cc0265850a1f4ee3e3288b604dc305d0c28ad35e1242f4ff4ae988b6deba48aabcad2fc6cd7eaab0a63510f3f915c4bb9f9719b1d90db123f639d9d4f3227eafcfad769c2b204dd2555dc54e738909122022c4f92f751d25aef6f9a1187750e825c68450e6d1223c2fe88aa27194b492b6788be6eda80b9b9f053cb77c8d9fa15324f23af5147624fc00c66e947b004bf38b31e1343c7cd341b98abe462a5f994e51d343664968624a2ed0dea9d0299d5c5a7e9097fa63d8b3ed96f917f693654766a9adb01110fa3fe0d8e9b102860d5c049df3fe00ccb2ed62ab05583e6aa0a5134d55245d4f643e274def29d3fc86d79979d599458786a8338b0071f6a01609ee6b2e4bba9289e2df780bb27491890d0b5ea650e62df819b8f98aae99a1b8870ce6d3c7785ca957d5b4094946925751f0fda1d62a9aefe3937a912c1b49b4272f87eea7e397feb84c0702929959e38a568460811e5064b1caf5dee53f920c6e19fb16fc9214b5de1cb770b510533f66d8a0e7f6f04ba8ba41869f8018abee31a6042d3919e217359988eaa9db2a10b3caf7aaba43527484d81304f0bef22165f74e9e1031b545ca3d2f74195984cc237b76ddbec85142a06446902339b1883000264031db85fb19b46f320ef3fe316f750f2d3d6070dec5b66ee8ef20701f20965f5171e44c8a99bcbca7afbbd81e30e74c6d48bc4b0d72baf562da6581fafbe14b6cc597f75e53b305036ede219ec56d0c0d29571a9c110ffeeb747fe56f6030dc26c8d3841b868a1ef56840932dad9f3bd7f75573086571f4d9f0d949510a2577d2f8fbed7e850c73ed4c071bf9a656d09dab43a610b49aeaa57333f67d586d4f50683dceee4942db9549f68eef4c5f8df8a2330857cdf2fc4025f2be7d5f0dcdc74a9cb593de91282787b716d416a3ccb8d6d40fa3c70be4ecfda26a5caf3724fad3d98db16ab6d8f26defc68392923b69664b0c2d56f01a549284b042bbd43c8faec940187f190aec08d06f9a62ab03c9f610f64c0010a0939451d5502511dfd3da1fec5a38f64640c7b6db2961def257eee9a3eff944828e9557deba68bd8e42dc7a9c1570e35537993061fa0f5351fd3cf4ec36386ec4cdc5a2882d5f16703b900c5000efa63888d69982e5ecd3e329c8cf5f003e23ce03c55631246ca15ffcadb0fc9d5634252ccda812ba7bf5e343c44244026512062a68374ed4d8add0855dcc22b30148e0cef0f2886be76bafabadf3ae1205b43c6deb8a41c338114895dd6b49deb329ada31b350e02a1bdad4eb05b61b50f9d22fa2863bd607406f552713e302467ddc78213d584b4933202438d63f99d011b97297f5589f35b7e45ccbd76f02453b7a7668c2b1a1f5d1d63eb805c8881771faaf67433eacfb22f9b6fa58b93f9423a5fcf667aeec39751ae17ad36992556431bca77059a29353598dac12bd3036633d2ccadc18f44123e5bc074f4e5ca380095af062fd83b647015259be929011cfbcdc9bc5d0dcf9b688f0f5d74da95746f447a9e1cb5028ccb2827b45129d04cf6990953a6d8ee0e67fe6bdbd8004f4744cae5607fe7ec4a0f14fe603dcead3367b6870d8e751cf57387d04b881f92cce9772d695f19b36e2db2cf6a807c9ee83225f5c09a11b50e99855921a4eced8e631af7c234aa31615c00ccdd7c6ac5ae8fba6e29cc233765a891864c7d73dae08ed1a3c27cd423d8d4efb550597afee8356c12018f496637daec83575f5e38ed2fdbafabafd38483c239d31cb4d104e93d16eacc6050033a3c86929be4ca8914a538bf540b43d7ce7daaea317bee1ab80504846554879f900d312bf2fbb406a0edc5f4f809cbc68675b0b7f09fd1a8a4d52c0929b3a8b9c1dae4b3d599b976867e6a7e8736450dabf5c49c949544386a71419324ea4ce5c4319899ca510f50d07ace57b013655b0929f79dbf3cd629ad17bdd10109b7c53a4f5f04a16e5471e823c898362df43f57ebdd1627b33fd4cafca6cc065d9140acf0454d5f99be47bc87e0f3b4d4320bbf0f21e7c261bb8d5d615963beeaa46bdbe9b83a8277813ffe6132b23564bef5",
+ "74dfdc364097c39ef91c01b707a522e28edb1c11529d5050ff820234e6c0295aa00591e09d547e9671804d7825705ab44b76c59d1315ed1297ef477db070d85076693013bdafa92e2ff6a654660008b176cd4e8ae23b9c792be3f7db54cf2bca385bddf50a8624397cca8ee3cb96944164e3cb461e68",
+ "b3b5ccd7ef49a27d2c6d13c0ae77a37abec2e27e0b2d3530cdbb7f36792a7d2c",
+ "c0494bb7249f864f69beab46",
+ "ed8d6e964bcde1df68e7f362243073941fd68ac77929c8e480c89f519f748b3dc337b1af6231632c975167a8425b174b42c2c60dfc0ec85a0a212bf5c9aada818a83f9664c8712d96de1036b5e5d8c8298786b753638de3a8da958549f16eb9c723355cdf7b999aac464ec39df7d6c1607e81b88b63043d1c847dab618f1b19336911b4b0145c2a694e61db71e021282006d48e37f10f3b6314dd012a07618228532c28ca84a936e0eff83723d117b2f2db857d14af5bbd5948a0e53018b31e57cc2a81f36aa013a844990753ccb347fe98fab294cbd252a8b8f7246276275d2780511fd3cb7baa2fd1548184f968c422230f7ad73ae9dde91295f79f6b799e7d234dfd6573fee6d6ae748b0a8cd7ed4862ebd957390826f276c2afb01fbb4b64b61a1bfc138508efd630e77580867bdc1e96a48a694cf0db6c2a11f05dd0bc8769e7200bb0749f5798b6f3559de55d0c281eb5df22b731fbbc109da9c68f209b888e61240c4c0ca006d105c0a7f43144021547d3316e5a99f6c429f9ea2f17d77dc68bc9d5125b6260f79bc8b3b8061972e6757d87b6544f21645c0b4debe5224f7c48142c09f35b8e144c0c1e6521f04c170519ff744d61abd59a56d25a26c5ed5972191b25e78e2140f3ce68fe17be9e59a79f6c69619a79b83614c670c7736d19c27fd22515fb5b896a6418cc0b4850e85c07b38b995cffafd9f69763cbbcfa9d1bbea6868244a66a5cc82e815fae09f5775d28437634926d571c2b0d200855e09cbdc67d10f85bd4cc334ded4c83aeea57f8e373a950f135997666b653e8de47a3bc0059525720045996bff500a47baeec97808fe971d7693dfde339e8beca3598fbc053121536c30d0af10f8f5d8e5eeaaaa9586d7abb563fd69e88351f93bcc46520f6d97c1a49ba9f8f6a25cdcfc11b2a722910aabe7435ac8f0dcda9f824fdde80850f21a2d4bcbfd2e9fcbd14dec05c117a9796db49e2f0dc55e74c7f0f615bd049fa7d0bfcf197dcda3ef3de90762e6f6f9f8a8936bd04fcf2a97cf18ecc8f2f118ffbf02b67f252097e4289d02f264161f6f90f79e1e1ef8414b01a9e1a77b88c039ad6eda6df1e28fcfe9370f0d574aa9e857dcebb19eb7ce8af9b19b4481c9fb3e1f0db3b02af483f737ce3ea824b2165e7c0fca8585383d4b0a16eab2c7e3ee5c038f939a97bc8e1c093cc5372ee45d81836c988f3ab3e6ee0e5f9549e4b7bc381a2afac2074cf75ed56b0e757e7966cb253d549fb0902da98294c6dd4de3c2e166b7e45098d2729b1393deb68471d4d3218dea3dfd0183b654ae4092a79357945eea4b28cfd06b40d30d1b4b8f19827895f6f908f0fe511f74ec84cbab2483ca4bdfc6ef50178eabad79b18b58529c9328c13c52c2869858cc20ec36ef7717e1c743d13f9607bbdb0b701d9df6aca7366814e883d23e51ee5b0f20ef70e2c4134ab037d213315fddc89009260981329a1872e541767adbd5ee9501e7df4ef0cdfae9769961f8716ee7dfbab0ec89b3f62e987387d5842e124a69b07245d359052ada50cfd67472d27ce2c4eacb5421b62dd7331da54ebf0989803797f4c8c781d0e2e6477b421c7d5cefc8146aacc0012af3f1f7cd71ce2b1045d86bf48c9a13fe469a1865294e160b4975023d0eb24ed26837afefc250a914f86f8b1f5d67d65e9737e841519148d4dd5dbf2b5a8b073861288ec9793d4b113d71c01727f67d791852fc3946dc912d60fc66bffccf4c45d859eed9f0bfc7f89086df5d5cd830ac919aa7cdb4504018052d67f6a3ca012ed69187cd5fbe91875cfade381bff1e804ba59cd59f0f75cb46dcfba234ab9832c3fb9aa8dde19fc1fb30677ac1793a38d94aefd9ffcd4e777e9e4f6d49e0cdac6c16a36bc2f3ed8e23b80350e3be6d866aaafbc8cbf7c69fe44c2aa80651164803150c23ebe262aa669c77ca94d215895d2ee9c3e325a0bf2c61e419a41e0f7b1ba8ee0508307d49301abccd5b74c054b6c7bd1aa67cffeafee033761d8226d9dbd7214b130a867764062cf4da685deefa23693b8549d5ef5e53df85c19bfb3c43c6bd073e7a836f849587a4747e1a9a3c7194f6d5472d2e3e4c81784a3061fc9bd3b94862c4784974d859134369486f2651f1db94f511c6f59f41da0d75307191602730b88e4e6101fc8d392c87687f3be454dd92fb8ec380715bcd88aadb63717cbce4db91a36821a572c363759d8d0a2ab007e5981b78731dfdea20d900b14f0c5ee6a4a9b532ed2134e6edb4dc267f001cb88dbe43aac4aad453b839d035697df7de98ca7a9ee7601228a79004b89796e9ab971aeb8e62c789bb21f38b77b492c57db402bf6a42ad0cee169e9251d865ea3e5f79b1801ef1e53797aa6c7060d6f9486081",
+ },
+ {
+ "04cf92a64cbe135f7fc1d7223b95e41d13f04b482018039f4e7ccacba8aa15ac79a752c5666524e527fb076290ec80a3dccbebfce3ee9b316a65fd130f12bf88b9124d1f7772049e6d0c01fef881a1d44c8dd02f7b6b60e6d15df9e06fb86929cab64842284de09659e19451623525aec2f5dd3e603e24319b1d120bd57b34a0317ce25ac9c2f022a4847306b998b57c8d92baeed0de1f6cfb3177d0acab70de275238f1152813b9ac87bf651f74e1ad079b9bd779ba4374ecba459865b5768d08ae7e1dd691d6821895e8380ac9e5116580e8de3a2c5326e698bf4c4d35d955e45772bae8483d01de2539e8ee1ef9539ee132d80d85fff41dbe406af319c0d7703292587bcf5959f49241e2b03a364e1b682729ed261d0ae45d74d77634afe667413ee210983b042a7ce6dbb61c29d18450fa7176177b5a74f032ea24e1d08b220f6d32a7a836d1241cacda39d6acbd26a62f9dbeaaf7329a291dbf0aed4a2cfcb85ea360947585b1215feaf70ba71eb2d6bb7081b2a21bdcbfdae6ad2513a9dd714d3d06c2c2b7e322a1db2d48f9df1fb44fa066f2bb42b196295ebb3c0898ad55d5b317986afaba0bd5e754cec773821613e908ce2bba6454181f9020b73e758df18c255c87df675cc6bb2b8d2eada44196ac10c26674167f94a79f4be515d8d6a1fd3228dc9a85a355b030845dd4c5f481d5b6e74acc66de730629581b022fbcff61e5dcfb6a7f511aafd577849a6b057021ecbaee53986159c1ba74c3e930c34a159f467f1e9799cd6c1151067c56769e43308c96c8edef8aa7634d909310dba9af2128cdb8c29b24d3ec2a4f43a1ed86d1791c9a670b240e6e719f01827aaa319bd3ff53959a776886a1b7c942a54f141e6bae8576d294e44333e6c5ad90f74863f69bf890126016b318e0f6bd2f0adb9bb861118af5f6cd28dc93d56c8a1dd080b8c810ca29267d410673fe367dd9d1353ae2bf2fd88d57b4202c21aa49f12a01b93acbe260492367bc219d3afb6e6f35502f6529bcbcdddce9fe8632efb034a9eaff8b4a48afb105d04e3fcbbcae010ddd6636992213750b12fb3e01ab72aa957136e0bae591bfb5e0fe819cac82a98ae8df230af399160594540640c6b1d537e7b5f1cc47b08127ae02c35b846de56c4c08773fa18d4436e14b76a7fc4bdee301d0af4880306f2f33328ab79f6f24ec779b2b1928704f09bbc5b0b7108e9a115e4959df79c80eacfb98649a0788867e23b2974b22e654ddab0494bc922ecdf17727d0f0efde9dea7601857d890bfbacbd93f7df794bbc254f50e1e17eaed2f5d5a2e6c58083aff68434730d406fb9fd02b0dd7bfb99a04aea812b6830fe5e05a044ca21c77a174bae8b58eefa11ecfcc1c977bc6218064c9931b5c92f13cfd05799f11e130869c293c1b08dd29c899365014fc8195514b286c97cb6dc4b8633e47751f87fbaba137b6aa04d072ae06c2b2f34448449f60b1272c1efbd4722a2be749a3d2e5450aabef1f7c51bd8324607668a8caf8097c2f358b1b09fd3525d47ec9a7640eb20ffdc17c4f7eff63df75dc7830c471ace3a727feb11533d6e9a2a08106af33069cf482ec63724032e81cab18e12cb5c4c3ddc374e2f75bcc99fc5da09b80a738852a14e8ac552b8471c6ad52e35317b730db2c13c277e06c643e0d0fbea43833de4d2c7a9247ff040e9c56f1ff7ea92049c5341c4d1478a14275a10119d934e8165152b89951bca7ee1399dd8232fdcbf831d8354640e698b68799d060ceb877201b2fb96cec514affeb28721e163e1648164b9e5722271db9b0ee1a7f96819fa1b1590e9daa598d9571ffa3882db9d034056e9b2785a8d13686eba61d7d45cf2e9ecdbc391739ce89297211472be18b21401658c5bf29fc3615924382d802a166d05dafe7876e70a0d081e80c63632da379766928a0555eb5e7a238cfa4da267527c66caf34dd40055f2801b29b3f5604a5bf3d46048bfbec2e24abd2fed2481698a4b5cd71f5d2c12dd473b903c9bdb978eaff7d76fb69951005681ed7b0257054eb3dd6d10097fee51ba7e8d565925e4091cbb78d255c9d3ab4ac0264d172c9bcb0908db1288c9634248f198a1167daa323822058decd83936985f83b08b1e7b942756a7af200af168fb8a091107b4443fd649cdc22106f9b9657c69f19be485c23b2c715b3762c332eccc44f380883357d10019f20612ab6b8f155c2af9e2ec340e5d8f45bf5278ac1fbc9f9f44d2f615d21007d822b244b1c7a0dbc182c7f5912485d6e4d74e90f60a2f964e028c63d49c6aadbf1df170e4914ca514139ba538207b1cf7caaceed4db8423dd1086b2adf15f6c0e50dcf2e12898f53c339a745316904ae03c38b417bcd7f5cd5ea77a4f06e65d56c24f37ebe72d271ac79b6ddd2bb8bd67f0727ead49737aa71af4f620da53769ca3ae878adbaea5a249128074ca3ddbbbaf5a68f9cde2a0e8d69708b0ea7f4c8d2dd4180882bdaacccf2a409a681c551776bd10439fb12b7548342532b371c0e045d8e8c895929464bdd4fe25f0533c66104daaaffed52446094978bcbb389c",
+ "001084c8a5175c0ad43108f9215c35886c82321c800740c6118a3fcd45776a4588ee0e2d056a37d99b40d2bd9c0845088a77240b7e65d18fef105d3488c77910b5873dbbf275948db5",
+ "d614d2e671066e387f7eee07bca9f9313d86e6a4d1371360900d670e11ecf1e7",
+ "674a516f8f59f9067e0485e3",
+ "1ee376e9e3c89b2147bcf75480ff0dec1d0e8cd45ba812f34c84124871d484b4ca87bfc8cf99f85ad452c482933801426e2737a97468809fa36caebebe8eed07a626b3bc3614ef1ceb54f9221ecb16f413f0bd9ed4b3010c40632f05223484af7bf5948c2fb8a3d2ce04c53e3f2682494f3969a0f8eb738cf93c0141799c9e6b68924433f0326991e19626bb19e6fbb5dd46baf39f92e830f9b1ff465a007f031891fb1f1799cc122d3ae7a55624356b5297bd5d948d9ff2e414cd8adf00a53524df43f398938d33c93b2c06bcde2679566c0a7b0177b4a873f35874739d550712d5cfe3d25c19292ba97c01d84224738bb25546e5c252fe5e5f260ca881aaf176a271a6fca2edbb2cf23ae6d4c56c20daadadb8205c2e33881867cd67ae6e59132edccc3601f014b744ff8eb6aef5e09b358607695d3af42ab8fa30e9fdf99ce54427ba9da3699de19f7a8f9be368df47ff0607601a91e7a5fa6e72be50bb32b825427cdeda3972a18a23af290986cde14f5fb9cbddad336f5efcd2d7a0cf3d5b23e54b702352fd5ee52d7e3479441497d56e17d5868574c56cfc421ee47bb00e9c75b84262a1b9e2cbfcccfed9c4c386ef0d2c1be9a7b7556909b5d72a38b7258acdd624de2396c75386e077c34f005f92a2203c82d1072c8998f03b1df22de832ac733977705453b1d72336b8d371cf1ed3923f462ecd22075de5df68c83ab1e6648ede7fd5ee5794a744abcb32af73bcb182cf97d36f37c15535c4107b7c8f2321f9fe0e2b6ccbe74204df3d748c05bc1e0e2c55ae1aee2d4aa4a52e98ca7229d6d06576196ac8e4b14a9ce807075cdc876aaf904c9962741efa8c6caf41e6b87b2ecd6636e2e58f3ecf576e5d8b895162545e618960ff6e336ff17eacd5a1eb335001633fa78c41ed05466d904ef9b81b643a043298c0e291a085e4e67da72e329adfccc407f800709865147db49cbdf4232073b7bc7ad89b3dd901d927ee08ae6497e0f2f9d052ca8d7444d2e2ae2197f930a7b1c8af38d8739ad298464169823684612cb628c484f710cf9c552551b6837b575a43275100bf800b7a3d777adc44d07f67cee5000422b9049dcfbedfccded0f2aa4d189621579b01e3fdaedc4d772dcc593316ca85e7aa248d219dac21c561d318a4936ac0d3bd5c75311486c174e0e2182affdf69bdd6a086534e4a602efba2b9363beeb5346539b45336cbaf479da6b15b226a9ac026482216dedb84ae3443b306820d9f05f78dca7090d727c7481d82c6e5df80e189e24e46f5758e453e542bd91a58eb51a89e07c50afb543c6b998704432e863dc4c0d0236e0672835a7b0b64e14f5ced2904e54da4287597f920bb4d542c35d3b0271cf0eec055656d523d7d2cbd667445d3e8634854f8616b7d7a7f3e14fd32651e9df40e1daedfdff1371f16d5549ed5646adf2d417e4b3a4d145bbe0974ab388c2716861a08296b862e4fd035163281457877eff89dadb160eb2b780414435784804bf4fd36602699d8c2f6a8cbcb509198c38e2df2edaae7bd7c93313ca98a9c2d24419a12ce35b0b3d68c18840e3ff8739d70969927c7db9a6569787bdedf5c99948a9e79b2302a83a71159f4c789b3b3f05f1e574f8a24c899ae3457f8e73f9bd86976fbddd83b1af337eb8da4c0dbac3792921597e18a2fd3a0ac89a270794529d370d36bb6dc7452e754e903781cbf57c8646b92d5d02842e7df229b3d721f9b981f9d61a48f00e53948a5dbc4f739849609d94aba3e3f5f8163d40321576cb8eb8e89953b608a01184d41aafc13f40c47b12240e3ad49413473c26b6843f4514be221c2af632d1a54cba230457f23f00b2608485c381ae03b389ad0a1671fb416de4659cc7f7a9c4b6d9807789c307d061fcf613b96a2d79e5e3e20b863c8b1b75f35c982b40ac8dcb7d2712ef7df94901facef783e8015a9a48574aa6f0cfb0bf6c1a3409028f8d62137c347f5a35ad6a3cd60d71aeb29bae56bb4590f69226fb4e08fab7a9f41e58f4d5784540a70e7a97720c549c8440b089eabd0eb3e4d37a2e54b1160572ce568f4256dd244decec31fec555017ebf488e878945383750eff26a8a1cca73e7d6f52d8cb229d5603360a3bffec23029ee34145c4aade82d486758e0aea9e1b7bf0b4bfbd4fcc96aab66a27fb463b48c6a6c5c5a60253e2fbc5716ef55629277a5f3b89c300e21bf1226241ce0d587fe3f5b11e47f35614169dcfaa375ee1aa589be33a4363765368f5666d155cf72e851d426fa67b982aac4dbbc29356d71deb0715b34e00b9fd8876bbb09ca0701b15615f05cc45e128b3864b26003e6ffe801c4e27402f37b8997e0c29ebc273dc03358cd22fdb68d9cd3b56ff8248a727c2d4ac65acda4d0e0f511bc07ab06cefcf444f1002c151b953d7f7b19695668a86683497c2a2d2e69f19a4997148d2e8d158da859c8f44437d9ce9db92f84a88e89cbffc74c0ef4295088e2543a4f7c6ae9c908bd987bcfd7a074f83ffaf3888bd7f430dc5a5bb70d223c21b1bcd8bff2103408460df864dcc168486f6a66d67ded366c6e10f50bcddada93627cda711764a57ec36035ebc",
+ },
+ {
+ "ce72c93caa49bb9850774149a87fcf8e23a0c53701554468645554553d54190bc6e247712b02097b794bc421ca94afed34742435ca689d2ebef183fb469c060c7f4d7daa508726c9d2eaeb9c7e9a89b30faee8d9168607d4778acfbd27d5caa623475073ce763ca061273cdfc2c692d1747baa8a01b15f783b2e36620400082747599a16cfd6b630fef310c0b9a2912d1d3bb71eec16972745cd8a49cd927014eb0a2abbe0e1ebded4fb9e8d9e2fbabb6a71da5688717ecd3e08160b9a861f86904a41702b2c4fff28ed8cc61d468187b75bde3fcc5c0c0a642215fea83584387fc5a9aaf2f8a91ae535e0027b618a32bd687289c47e9428a1a92649deab825d702b076223b07c08e55c0b60be95937bfd0504c18398e924420f6e20baf07e2b1b858d3e360a461b66517c24e60f9fe314a4a4973c8dbc7e9d2a9f571a1d8235a21073d81ab9f4800b70a5f17f44d593e8792a2507e6a3a41042fb2a5f7e5f028ed2daa88cce28973ecd88bd125d50fad77b1fde61c38272057d9c65fbfc6789ce41315a105af14e277a0c39d75c34aed7538c39160eab1c8c47818743e8111229426c399c5e88c4d894fdaff0315ec885ea019bf9acb785f3380c37201d494a60b583fc130bc0eb9fbe9b90eff95874e35910dc05c761f8006e2f208b786aeb2eeee841f9a82d9966c82956c181caa4dada81dfa2e2d7a25007c2dc7f2dc7ad1bafef14581cadbee4d614a557df4931b9ca105bade8fdfdefc0d96eeda11c08500b1ca827ca670ba07bb0f85af92914c43a6f71226d6e112d487f1ae99b2239a63ee2cd0849d8a9c488a11f82ca334604a2b7260f25373c6db75656527890f9b772c6bfbb9f687f27099ea9d4d1efd874a6ff83cc36c039ed1690408f20394692ff054d9e6eccc6776b6f4b3c5f24b0052334d159f40b470a9b8799bbc0df4dbfe59a5e536624cad193160ef23abef85df2c9b6e6d4fdf16f848a2a446a77044f1162a278866c491982570cbc16041908cdd0efa2cde011526a3c96d4b39a23c5fcc53d8232869cb4dea871f4ac8afc795aeb1b28cb2d7a3669100a1cab2ee1a7f31e2a25a5c6da836e4b771ad57393305faf582adcd26045e26b618d9943358c615fb206258c8993d700adac7440dcd3ef34fdcb065e10e9c9727662b5abee160aa01d2f2ca6c203a76fb01bb08cee9fc1eb6bc7497bb012ed2774a2d263b9dd03d60c307ccf33233ee33eee702c8e3118f9f86174a97462d0e804a24bbd7f4f938c7f105bb23399967288069e1637b60f2f1883d88ce5a874ea4bc0a7ca0f3b568e4bb1407e4bd6f0d3dc8fe91345f8435d7b1be961c45e4b0f1ef2d92d2d30bb78e1fbf72cd2e7ffae76e8c2bce005195c2003bde46108f37ffacdac28fd67a0de62970b347f0ae3f5f3a5b1d3aacb2fcaceecaf2ff4a2aeef6f5a176cc1b74b234f5658ce603bc353e075278a4056540e43033d37a6eb2615453d8206f5cd294423811283bcd5d79c4afe268a547b98977ed5cf24c0f53a0533bc0b2889356cacb67e2f7353060f9e04362859b1c1f02f96bf5457b58e5ce84a6810d39d7c7f53faaec64db5d6ebb90c1412bdd503ec6bc240c277ce1f5f18876feb24eb6a77e5193e33ce141e8720329add079dc9735f0a35d7d85436f1dba6dcff9147777760b5aa2ec9c8b5e9fb4fc602ec8f754c99ab2372ff5963dbff3fda91865108e606b214cf7acab875197e78060eed52a798751998ce7c73cebc4d5f429f6729a5193d7593072d0921ac8127ba6e796107ee7b9fbcf7128ab35fe9f6fe501fa4695c19fd64460685f287acacf5250efc13899bcf80ad5a340d432a0b9449affda5c8fa090f008e01873aae7d5fbc7972451542c5c29cf9cfdf23db736c8a7112536b1b626caa63f3e4117044cdeab612fff8d8c194d19174f56ce761f6587349c48fab30390f231d209461ee7e18007d10d83ea5aacf199f3b00003259747b1d03274d3c3670595604bb4482d345ffe31d3e88c70da16649a2677bfbdbf618de1d651a53d573aada2eee5c01335ce5519a6d18a70f7ff0b1e66bacc162c49f7f29b9d3fe2c7dd85b6b355c9f9141f02baf08d2be87c36f6d2e1b2e90dfcd100886e306b360df0ecb146a6aa5ac5ad05b63a219ea65885894a386248254348ada17908d776f9b438306ad28b208f80d6b9b265500aead945134b9d388ed5d6205edf07c5d8bbfe0916d0943750150e09c76359d24e3317517ea489fd8a501dd93f159f07d19d00e86d952fbdba2db771910143df346b30a30fba908a1abe5349c3f241958f428dece7ad9a91cb42035c43573b87b26c2ab216cb4c21799f6b3d81acd300ff50edd6fe7868b9ba6c160db3418565ada027b46b63e5d4f3411284fde585ed3673b424ec1cdea678e4a43c262991c3c9b988351d6e0a10af1c959cf21b7a288f2e4d7b3b2c11b400b5e036df71fa993b72ce48d0d8598fe4ef1ce70a970f89b55cf4f07906a479bc84a08bf6ab25221de37afebbc47ea0b38b87be128737d7d43cc84d336cc6ffe1677bd802910a2084751f30398dd0ed09589b2befd2f3b40fbc013318c822fa2faec2323fcc52b43161f47aefc557e92df3050dc5f8b1c5a4b2f8bd7b2ba7aaca79dcfa362fbe7781a2e261683a4a862d5f83e34845a8fcf8a1aa73cd521e87cbeb71f20b20698cc34bee3b8628b1a3784596c",
+ "08b3fbd73d157e79ea9f61665d19867dcb8c1598c1d37b793606936d8aecd992a0d46addeae857d488b83be5d1c1639d4d78350e4cb08782b61bef4107c9d3a79d3d85",
+ "a56f38b4bbe83b3d9e562cdf5ef5b30593f08a1a166676c4fb0d5861654e640b",
+ "8726dc5cae9497936658f603",
+ "88420357d1ad70e7c7bfd55b3cfd4bf06cd4e9b4ed5cba681045199a06985956d35fe86b28b9a4599964930d05d230a23c55a6a152f67082a453fc31f68489df05c553f9ae5cdb3f611445db384d79af865e52440a876fc4153d896b7a2318dbc2a4495ecdbb2e9dc68022326d35289e82aa55197aedc266dd91ba3018c7b474ba22b4e773773f3e9890ea84bc16a6b235e4bb69e785c40c1adc15b0e0ef03aa147b0d14e62341e27398b84a53f72c9199cc1c94cbcad2bd31aa69c96b06d01775b8c0f80278a43f526664bdd430164863c9c9140ad87798a5b8f38dfe90d37f54d1137709d5311136b728e6c799da244294daa4c8b44bfb0acc603a16c088a081129a0d2cff55ce1c4ccb486fa0ecc3098ef2196f47c49f9d253112bd5746fd99df5d2be577617dc2519c0ad04ee49ee1d7be3d50492017108fffc9a414ea227af39fe49fb2c895fcf00d927bf4a2d78c466fd44df4768e6775d39fa5c834b60979ca27ee9f00faf37a090838f56275a894ddadd265a8d2de74265e4d8d286639ce8f01eccd4f551cf6b4429eae3f08902b6ce6ef422cf91ce8946d9403fe8064784895b62a7f5df76ea294132c59da6b9f53d4195c1e9000bec499c14cf8bad460aebb024a76ac50616f0dcda71c0f56dd3239b11764f3ed6ed06c049b2ad673e4beea391dbb854fde1f01b1900858b9809259f3906b34f95a1c6ce8d24fdf0cf7c2ab7bde2202a7f1482baa6e51caaccef9f541c377da620bfbc63955cae0e6644ec8ed6878f704f1dea30d6b50d4291892bad19b0234582d50c6cc0b4165322cff24a9dc2ce1be35be0fdb3bb7abb777ff0b2f4cf16277388af5a89220d59f1f45ee9cc2a0fd7af9aa8e9e8d548fd65be4e47e7f8ef58f7701f93a42e7ff78f70e807fb63513157fcba96ad9731b2e8f80da85ef407d5c368ad16f0657620bfc122ba1b10d7ac2bf46d8133a9c6fec1fe04882f3d5765da8f825e1984a4313f72b67d806ed45c000dd3ddedd524d474b9b5788547d0712e8edb4c6c586d0cdf8f2384f1e093a7f6dffea6e79df9cb9398f5d0b9a7cbd63d489430fbfa397a0d03ef916b7702f33a54ebab84a7055b7ec6179b0ab7722f03e126ed343b1cdf2af3763df7e3a070162535514b01ad86c6cb051859aba1cc4766b12c8cd57b73fdd3c65af6961c45395aa7b885dd59e115db885f644e1c94bfa26b3804f767601c86e2c7dcecd4daa59955e6a40991a4b4701e63fc82b46dc0ccf59af40a8583171375551c868436ede535705f2e6380c5899cddfcaf9e94314794bab98846cd5ba9e9afbdbe1ea7fec5e22e7b2aae59fa598f4d6c0cc6f936a616e11bf01a2acc891cbfa2bc53c511a8a3a3da2e3aa5907d123ab2a4a3c0009fdb5235a3c33718fe4c504e1539abac6370e06150c402b5fc2f8c32608db4ce2eca9d1e4b96371ee195f6cd632f5b972385f9d5d357b87c78cb4e2c27aa9851534de14de923543f5fd9d55e34d6e8b7e1f3f2735df80046de01f79d0321066f9bbd76299c7386d285f7bf4ac15e033e89a040710c90f87aacc09fb8159f93c8b4860247eef079e32d05707e88aac734a2eadaa853f528d9986e0af3435b5c5f44ddfdab9b0c9ab3eea97676e920f80d1794740067f9b229fb018c804e595aa997533a5e967cb79ee58eea18995a90ac08333f1c69600b17ef4f454f540dbfa8b502457761bc4daa876d9053ae1f55001b6916ce559dc6268d01841255990e56614e6f4ee4ce04472dff0657360d75da4e83a71c852a2585110e53137e91bd89d64d99b5614ab2a5691c876f15d9931b092fc6729c0732db5cc40f966fe440ff99d7d05b24a872f552c27fb0cf2af443340b153214b407fb9ca3750d9c157aa75763b0b7600959663889d00f392d6ebc12835bd2f03ad802a21d0228f1d2e9731d0f0051eb2d5369ab790d1134c38e28d2bc2d5d57d6d897244742c176559961a1e40c84ee5c8225c8d72b92352a011e3785c262aac115cafccc2fe1b5e81a677a0220f207ebadd786b93f58e40eb6ade68ddda5b66c5f0f6b4b95cdb8241156110ba3303beb79acbd54423315768bb43b4fe8c4a465e50c4e63bce272c4d731ea4c797e14b2de31ce4264e2479179b906f67af4a23c56e817abafedc2c7a65aa45f0c89fcd0baba60561a8d013e2d5e0bdf9fbcc1346d3edb20e6e9f9c410982e1ac43039ad8fd0ebd453a6788376951fc20374b59946a6803498929d9fdf2e0f5e58c441329a79d1232e957b3a9ed17231c663b4819dcb6b4e33d205edaeb7d7ec466930bd84a064b40aa67fd76f6ca005408062b45b5aed6f8161836c7160a8c8313dc9aa1c6d42c2c16972a1065e41aea9c58db7916e1670cb42a8b54d85498561b4401761506860b19b446655f8988101fb4c45067e30edc3f00df8d88ee34111dd6626d605d993ff207be09704fd8dc242ce514bae77cecd20f10d4a38435a3f5e545882fdc224586a04ca6a162e118d23716240fa67892b78faf98a17916471f7f121fb9f85497a0b34bf5aaa4ee1ed8a4681bec55d1b4973d4368600115bea70f20a37c9e942b87f6cd1e2ab70fd401e703e3c8334c75fc338508e06d6370779578fbe737a75954b4701bfd92028ec32d3d7ae606caaf9f049d9774f70efa707c1c1174d9fcb5b0a0ae2a961c6f58e48ba82c2db14ebbbdc24288e42879f547b855c86dea9a3b9877e4b105515bd78cc43465",
+ },
+ {
+ "bf7884fab52251e202afd7b5b46aa53f85bca5fb80a009d8016e276579e401385d853312a884f4aa33cc5fe7360426bbc0ccb7416cc0196e2e40d3a825d5e0825a1394029789acca550bb28b10d847d0a4fe1111be2b7fec6b5294902775128288a784203031ea853c9c104c75571d19552e2a1359a900c5fc9455230968a5920f2ab23f5b9cc49739d4e4ae2c01c7812ff295899b954e9729a3bb330b60c51a8a7759e5131d7d4cf261fa1e62c29f91b4341a4fc968e7f30ca2261702eb328d628b7275a9efc29b50bcb9b27e5844328d5e8256c76949d30b6fea0d5a1c9abca80d3251fcf4ec4db0a5ff2ffd43618aa2e3e1694c2a3c579a2665f443ffb1eb0ce33c09d7285687cd55b6ca9918553bfb36a44860e09ffa0604ef4904a034108370195a986fe165c598305eb08599abbb3df31b1d93162397056d9ba5a1ac2812c582aa356310fafb4058abc5f157802e4a9b4bddb16e75b6db105b7dbc838f820539b76949b1648909104efa67ce28b16a738f1be104d2bd142d3ad1b1c953b6020a1f4cbb84d5c49424befbf2e6ac5c593b783a3f4af75477312528fa78dffd82fe493d821e011642bf1135a5be91fef909383953308dcb61b2f35c2ad259acd1a2e953c0ea6a03a97b384e39c94c33d3846c26b4f9f116abe572d5b7cb81886d6adc2d544630fdc1684bfb32972e051b9a2bd0931de63e025813b923944290fe1ebd5264ee4f25569a2088314e8d4ce8b91c7bd602b9d85acc917d60d30d5ef1cbb055b9ff7b0f999b98caea2517d2de334eb436078c90d41e0e34f11b93e3e643389f43b3afdc4f47a7396cbe0b4bf159ff27618cb835aac6699be1fc7ec840b767836a165fb95d06f2cac4fe15b65714ddb8a095ed4a5b57e63d536405931b6c168683763fe07c32aa4130bff787d4d440746a2dbfc584a502d809076b257482abf7f8ead7741c82b54c41acd41581148aeb4149b0c6eeb39ef7ba091c2e8bc72583b2fdf8ce7fad1bc05aefd6db0360c644a9760a9729a88ee4b2ab123d7238c12435b9f3b4660e74c0fd4a9b00aa614453d84fea01f779e5a924f8e79630a8bb6561ae19c7bc8d88b9d823b98285fdd65d4cc05e443944ed5d3cd4f46c7cafd1dd5deaa519772dd24f508bd2d588a832d5689119a2d506ff11dbf37d57a24e35ff38da18af07eaff5775d12dfe795fd3e1f0ec83c5f283d6cd76532519a15a18d93431893b1b88929159bf8fd21f62b30f4e37d540baab0e30ff3349a08d627ac19303fcae8b8e3fe44eceb66d30697c7ea051bf5afdcd8bfc00d49c8d36164ec9194a78a4d8b78826863e93b6a810354861f4a35ec12e5ac102f74e390d9c0227e67acbbe3254e5b892786e3a88a383ea9726485854a319569a678fa70392cee90c9aa83eee8df6800565bb8e083e78a064c0f8b863120efd799ea57d3073663c0d0e7bfb9b717ca1d6372fdf75a77fd9677791cb899fc8033d6d806de1e6aaeef525ea909666316d9d604c1207cbeb6f427c3acc1b02cf59704fc65135703f2a9529bb2c8fec992c4de53e54b029c3f2a5fdbec1008d1a70dce0c11251003ce62af712b9e4abe631902485404e4933f346f1b4467fceb65baf776d0078aae6a2a1f95b85a441b635663c75b485a8a7cb9a5c12192ac874d940e2d9b88cc05a2db9b5b35df769925da508112ab0b8f64a1408633fd0d81810baf2c846b222736bd826c8cf905b2c35633d6013f5565e0a5ec1492e99613f53530799052a0d70023339d1c394fdf9f73a590a2faf68390d2a823bc3e47a173782b03dacbdadaef1e67fb47a7cad71b6067ce5b5e41fc20ea1fed28578e9bdfa99faa657a754488ed3fc084faa7a05b0f6eb66da0a28e9ab26bb319fa4ee993de840948f94dc1d68d926b783a0bd3396a89970b2c2595de8148e87b87c21f664618af4f567115d403715c3d7d2f66d7a90de2c5237893a4c18c20494e3faf94485ed39ecfe972c36acef0d7ee57bf8755924c790ad02dcc5c4e15aa7db53eb6040244c3ebb7874676782e54dfdddc256018ae6af8cc37450a4cef77f21e2e061062ca0c2a514290c960f5993ec1ce9eea6d09d3293118237e079b6015b966361c3032368174d74ae5cce4148ea2b3690fbd3c28ee544c5c5bd7bc618122979d52c9d3d44eab1f2467f338e695ec5f95998bbe77dffac42bc2809d43a324e0f5feb4ca3d5fd951b7dc8a9e6276ee080079b68849b14c7573cd02c76027a856165d1043acf99554c62fe32896d120974ae71f84986bfa0c28fcc399246bef3ab90f8e55f913aabf339dd7ca6f0861a9ef712e77dd28740615479f39a37e746c7df2b267066d1649fafe0459f665f3d5e7124db43ab1ba5ff94989acc7fe0935e0bbacf718b33103a1355d97ab416d8263ab369e6cf0ee563a77f2f265fc3856b7d54dc0887ed439a421c14f733ec1d6da086536f9539d23cb8026218c5e783423b5f4ac24c8d5d8faa7186dd5ea34afe299e6dbed73ffa8f415da706442a48808a9342d6209f65ca11eba76f8ef26db890da76671971f65bce9e6112c8aa92523dd5295d748e28857acff408c161c0513b37b855a8afb0764d118815bb1b68f8f09156641f7eea994ddea20f4062607b9919d041c880b71592402a4d5b92464b239caf431a99dc67787e76b8e1d7337af004bcb88473cd16b3f7640e8aaa59ad4609f060a2cdc71a4b3ed22c1506a7050a63bd8ed68aa58a8109980bb3f2b9f9fba9599d7620b8c25e8aee739095789af83529cfbfce5941d7f14c8ae30583deafdc7c25fc34e75bbed6ce4f6b47e9647c12333ce08c7db77dc94161cfc43f7ea0bba39def8bf8ae61c6fdcc0de6308af963c6d9ef43916d0cd2cedb970d5937c9fdd4b888cc66e99363b5a04ae62a4349f01c3933ada64080741b1781754e4a722303faef69e382cd9823177e4d5ac83e76017124a7b1a41bcdbb9c4209e7b42c",
+ "eaae1c53919e2029c137a80f91704d0871be2c1870d0333d8bcf7f94",
+ "4c434cddb399e52457113cc7e16f046c3f8301f5b6c296979f8a091a9ea557ea",
+ "b633c1a0e1ddf4727b149b3d",
+ "f1de487001a580cee6edadb1ef6b700c861a70c6ef16274447b8c61bb10d2d1efbf104d5f7d7172c6a5cf9c06d886165a2919ee9418e2e8f803d47832dae5ef232ee300d1f973a6298c22d777a1b16264353cc731a7a683cfe31e0abc704460788c555c0c24f281b81d7761235a955c736f17f213a896b40a034609ca8456ec3cf5906d01121b7580ce19d89347b6a59c81add318df487b2442a7a8b5e30df78467abbf46bcd5ee5b994a39ca5bd8846caba6f02f4f1335b73d4e20be0b6ad85966f86d1bb857713ebf947ae936782f1f4929498bbd66bdd5ad6fa252364a5a6b46180e93b54cc321b3cf63cf23d55392475c6b8c8c9dc707924b55544151c7c55ae0bf391f793e52bed70829fcd32b2926600f65be0943d6a9a96547675426b0dca9cc7b0f5dbc9d5439d0281014c6c159d055d6bd89d67828ba7fd2a0570ba82996037f7dcce297fe6518331270f6fd5ee63d406cc5081472bc5f2298a9208dba9398ccf807ce9af982885897715b3c5742456f756d79c70434a9baf7b4b6664c9d9f5696c5256b74099e593f97a2d4a469cb3430d0c3eb06083398cabd58af598945a85c9235a3fdd9ba7686e54d0de9afb594b1bb030be8e6bb839f6b45699dbcd2f771db64b0c62bbf6c8672fb412d60c00b3d87f82ffff6512e8308877573323c5a2d6a216ce3e2ce07c9763835ae59d44d7958fd873e3995b62b1b347e489ce86e023ae27a6cb03ddec27a38fb233499a714acd89232a91d38abce30299f38f437f7a46df647f2be862c1e7bcc1e4263c2147b13ee5b345b7fcb973f3ac71db8bc12309f67ddb62659bd73fbd20664eadcd23a79233386aeec1a6fcc8c592053954ee53826cb9b6bba22400648887311cdfa5414c96d5956fe193a3729be1434d923a3f9849f6c419f77ea05fb72f3c4f75ccec03b7f7aef8c8e55c8c5480ee505ae1a7594e6a911dfbc39dbb0ae8656f5972eb644c64203a920fe0078f3d050cc5666ed9747c23df7853d6913005d0156e741a5ead3bb1b22e5bd802c303a73a961f0b60d0fa698041c22577b44eba5d6071de4b545d9f5de24944c151de6a189bfdc223e0507c74ff929f06a2e7497e8c63073294b4aba110a006a6e9510a9617405d9ee711831e085940006761822672549d1d1c70e50002c2227f6f304b9a7f11dc05751be2dfd297087044d2e20ecfa0c091478d62c1bf5f0aacd25bb0384853762a51144b77d30418b633c4c10a6eda7b2eac46905641da0b685f85349749a91cdbaa4027fc50eb97a7dea9e8cbb5b5f386ace0363803ba579cd16ef80dc40ba1044b4ecd0e81e382635d7855e2341b18e0ca705ff46990282fe25093a248ca04a1fff64ebee25065350ea4b9e5990da4dd2e28688ab08b6d6fcb54d70f6d74fd7e5e05d21c12f5b140839aa966aea9ee094a923ee5ec704b5b709ff009c20ed89a75468c48b505d07c7a5ba1ad54ed610886c9d84468eaa598c71b017578404c909dbca431703e0cb1cfb975a696a1677bc015a75db007eccdcb21b9e5e119c48f148c2cffcf29e245e52156ba5ba0a8b0031570e4cbe7b3ac4646353594f0c4a9424c9d97845c5e1a4b4016df9be8df3013e5269484cf32258849afbdd733189ea11783f0f64d3aba9b4f48818011e868cc03ecaa44ff0ab83ed12981a6df445294ff672f3a16d6e0d19b90007d4646e967e0fb1763b3c879f548e1103a75c94f3a7f72be78555eafc086c1c58d1761aac60b843704f234c55b951a1303a12705f2120f784c2bc1494432a94c835d908f0edd5cbb169afd2d38087ca5bc5e5df9c3bd970dd2da4fb2a00933538148ebf669a20b5beef0402e53dbfc3a0f289b33b41ca27eb2f036a22f0d02e0617bd01e8c74be264515c9b46b9ab6fc67403a35837844580794088a9d3c14ad9309435daa0396f48017be524856ab6c191350529962ead64bab33171a01bb3c144b23bed406cb05102c693ce5df36eb541c47e871acf56f2b47de687eb9b3511ae83d06b1f69fbcef3225c3469c304741437fcd0ff4ae3484c117f51d24b6ae1363beb7d85d9b61e01e3dee901b90f2d3272eedb384ddb4d3b9594b9c0926595e500f8ce2e5cd407bd7a4e2c8e6f4315bf693e8c961ba5b8a6c7f5030c68a6b995e9d3f9eaee9eebc9d679eaf72a5f1cb6b2fc66edc7dffa2370dd778ea7ff446121999afba7bb35ceabf626c6269bc466d65f7f812c663bcb2fd87d3e09ab7d71e727f66d20ec48a5d2bf0aaf0aca05d1546d6e974f90df85c1393e3d45731f71ec7b5cb6cfb4e5c29976ead6944a99df2045056e198b19905362d4e9b765adb65eb089233a8b3777352665489c9456cceed593c6590d9f3cc4024d0bb92e1a0dc619bf8ae65be77456c18f8171e4d2d846073cf5c57ba93adbc0db9799e3d98934aa6899372acfa4d7d2ea32e20164b79c71d7bd33c94f9a781a25cbcafe563462eeacaec0e8d9d6c0199de85558a3a05d1ee3483351915d8a4e65ca0ab129a2386a9e26aff9b912c588babbcf25f8c467145061b9b8fbbff19d8c6ded8527d457be7c926c8f490bbcd627b3002044b7729a52e94147f95772591616f6074047e758597f410b3100f9efafaa4137dedfd0edfa85b0927804f0b4fcea1a174622116222004d42b36c2c73d04781f2f49d080f351e57154a3980005bcfb0ea34288e2fafec5bfd01e1f7901b3efc71ae58bf8df4cd7c045856103b77bd78073f0174aaaef4a3c0e8b5b46dc92db55478f012dc1b7d513e215e735573257f105d2390b5366f49b61809033c13ed4e1ebe19ab89313c947f2585f0788a0c5de90b41ad0dbbfc604a0d414d0e5390a0f3c9616cfce4097e38e05888b8bc6e55e40368bacdba7e5b76f4bd8fe619746155c30b38807a1ad325b00ecc3dbcf23014e79f1c39af7cdd0dc7ea58ce733e6611b7eae069deb047aeadfc21960e614db19d2e7e0905a9873268b9a24f856c28059321a742cd6cb3d1527",
+ },
+ {
+ "c89c3cadc094bffd5ba06c600dabe30ea19ad037316fc13b895fe0e14ac8841264c1bf25557e22b01f8e102c3af43adb8e0a12bf79d3fa0232dae37ca3688e07294e2c7ecc4e2eebdd3f17173351f2c15b0480d4d77bd70955ba86f82214004b622cc92f7bf81a5837326f6a83612bdf65abb33c268a457c45cb7467e074b342a17c711c748c74abbee31541444020a9ecd4e5125e2a8ea3f6030bd677be18183a8a34af16a85ad48b7015cfb036789c0a5daf68883d0c7e401754b8d56cd00ff605be0cad19e03989f608392c81d636de859e66c2aae403c138bb96a58ba69b9064a83e7d8877067e7f40aa0016e0df9b7f455d292a60eb621b8107a727a3378c4b7509d3ec10526c50fc6c66dd4b015c915e85bbbf701ddaf2258119c8b9a5132eafe61bbf38870f35f375123f766ed0d4f38b9364a86e56cdef6f95a815a8d7c48ff283c77992fc6c070eab7d7c7b517006e5d4af532a7c429912ebaebac27249b4f5112d870d998e1c450b98c05d08c742dc769506f2d7a004c24ebf84c10838b619653e27ffcc4344d8db0435e4cb77c0410cc734e36738a6b5f72a7600632d19c86b40c737830b0f5f104443dbbb031dc7ca51ab318951e7817b5d81de8a9aa7f5db6e2d5e7a3cbd8a8100653c048204ced3af005d00e7de7b445f5acff901c4d46ff133e92ef073aff1d9ebf55befc32f9ec38c9eaa6a1aefc974bec2758297e474cacea2ba4151ab1a3ca0762c64a5ca273169d29b83c164f77f266c01bd5075871e17426068ed7aa58ef0d1f2959b19c604eb6187acc57e2becea2da93ba23159ba73b9226034c7ee2498e0ba34fa8038e5e2c092a73ebd9329ea3d648d6ebd47e1776941ab3130cfc91089fd0a0a36f0ecf68293343f275d2a64c1b7d27ffeb3f667f4a19824706235fa5f3f04952ff08bb183c0f1aa1d1b0edfd2e05ed093543788f5d0ac6532e15f912163275053b202d772f381900e906fe070cdb00421e78c16b7387be91adb7b3b3ea28b92548d69c780ea578e7ac66eeb931eefb4067bcabdb345a7cd2022085fc494f118215adfa2443630bffc9faa8fbd9943c3140d81c7532895734a9dd20e31c326531d06f5623c252139c4cbc882640c457819c63f6ceed4e03872b246a3766df69373ebf5af1116e8d5e1b15745bd9dbdd663fd4352d1238a43d5d1e74b3edddfb1c9d460daeb49afccfa0712b7a4cf8d07ccd0599ef3e4e1c9b5c814f3a6f3a46fc80449b34df87f47ff91fea3618cab2d5c04cb50e8ad199d752d901b21348ae939d39c86cc1bcecbadcc6f0e581a3bb51e070507b41ea4294b35456c69cf55a2a3f1296f0df73abac3a9c81cc303d1e20ad6e9bef48de83fc22dac2cfc01ce9ff3f70e00ee49bab2f282ceb6859f989075814e690e36a8d16354fd6056cbff49c30e49b1570363498531ff0ad0979a4518e9ae271f57f883abf5e301c0e24a83f09335479698911bca90269a28c0e040a98e67c9e55f4c91542f921511dd980270cd490766da22306b48ca9309aad3b2393b7b1e9ac7afeff64204081f9c0a8f6a5396d02eb9009901ca2c0a75ffbdae3a38ccd5007cc4f6bec8fedd64086cce5c039e8abc9e23bd694fc8de4e858c89bd585ebdd422b492eab26f4ebbdc1d17dfbba19b5ac458c31320a161a52dea638548205a6ad4ec54875ca34238c059177bfab2d5be0a98d12b3932d0661d33ec655446d0283224af8ec7f1c6874add03448fd8029a71d3c5aa06951123c9fd881d435845757df50444e6cacc31a8cf7537a778d1184b96c3512cd474f5d1fd1214555789d24c8d173358e36400b2d937595109729d9f35eecb0963c0da60d2eeb52a778876059fa95d820d5d34e7948d389dffd53d34c4083d27c917879b053cc57dc43c8263e5dfe5f33c19dad0a7126ea6e8abdbacb318d37c305a183596ddb25b1934beff13a4f24fbdcc2064de8e0bc639e672ecfe45692e9f8164365e1691784b4f775ef369aeb135ce15135c20da95064c810592ea33316b9767caaef842f948b9573b2205ec57d3026a2f2244c42991462e233061549cf9bc66a7b4a8a0fc61f73883fd24dad02644004989c4721a0aa03d3b0191d7fa4d3da102e541fe463936c9365ba30681e706ca70cb3c8ad5dcc710de59e7d8a6247aa809bba74ff4dd182a38bb31baa337841302c19ed89d65e87bbed05465f4ce0dfe89b44d7e9266a8ca21d984c41109d813ca76eb67dbd4e39aa437ff98050c968ec1e40c534ab51d6b8ea2309fab08b3757e9edc5972bff316f6f2affbff458ac0299613734b30dfdad20f797d172cf295cbcfee3d8ee25485d40380d3480a9372a1a6e5ecd7c4c6a9d34027ea6c197f37e86e757750c9fc24cc7cf814878b8628326c140930dbb2041bd9ee87f36ebfdbdc34522cfd4e50c9cb48dd52d4647a06d08e0f0069c104849bf30c8e61cb693dffbc69fc0ab9c5d502a227d606a1dcd630ebd799acdb1e47ce2ad52ff53f6cf4fbd5f0058fb5db915702675ea44334d42e0b6ddae78b22b5b5f7e5aa36519e31278e37b64312479b14aef9b8f12d8c1f39faf920851bd53b13bae5490c847b3312b2e956c430f1d8deea91cf171dee5017e7709d0346d81600bd5f0c41da3f548c28aa50589b293685ba059cd7f3edefdb5d8cdea364f4a42153b0632ef0b7ba18610b71fc34a781eead1dc5a00ab47b6840590ba44dafc6a16029cf50e089684194d93dc881beb62edb7ccee6304a4e71a35915f109db92690461b9e4ea21257ffb62477c20feaafc7a78e2aac2301b66893157920ce9fb114ab4f534d61bb3d17dfb4d9ef9f79a736f7c1d32ac3998356aefc876d8c38722787d564e980a1f15056cb3fe634d71d2c98e0475c79cab318b73a863362f85aeacdcfc44e61b5aeb870de9ea5b5abd24e8c19ab05e45e1e9b8894deeb9d29d65ae99aa94b5047f3c1168276cc2e491aba52b5b03703ced28c63a167f0cb3e4bb4d8e4f0292cf3ea4376510fa49a1a5efcc00f23c3cdf6402197b81262e66e17bf4307d87ffbc2b37213b316bddd65aa9d64ce6122c4a1545c5966bf4fc4c6ff17ded787ca9a3b3cadee435bbba8f6590dc4ba30895b84d5b4eb94f4b05be3c",
+ "82abb4ff5457b21f359754f151e456e2c0a185c8363d15918bcee0d6d49f12564ac655",
+ "b63b577e719494032062e3f63682098dcdcfe26cedea2a40893c847a331e4ce9",
+ "9f1d08be539f1244f0f69ad2",
+ "88dcdb0309f8c4a96ad5560f8210eda1f5afb31b85b7a8b15525777748967d4ed77c063f65d64ef19b31044f2adc690f5e457faa1abe2e127b38c626eaa94053c9ae1b6b4d0db1f02c8404b50f58210cc9fcc6fa4ecc615631da631031cd6253b4a13a3e88295ffdc775fd4bdf29655d9780dbe02b0a82aad4c4088e90b51f170909c0f98ff93ca3926067ec94be05841603db4f913b7025a9ee34b8d8bc629ed827a2a9857e0814d36b83cba21e670f8f94ceb4be5757e0b8782895b5d8605868e4f584b5bb6a5f3a94edd9b23fc2b6fa06914aec970c260fc370aa245ca68888c90c43eecb68474c9e45c53a7da055f5bfe39b56769fa56264dc8bf4c1616e30262bd501ff9fc5cd78f73ad89e093feba0393a11c6b2cbca765ba025c40dd0417dfa644fce96db5a0362235ad37a317145e7b5f3c7213c7fb3c393be57a1cb55035f06da1f0bf665653c5fe8a0f3ca67dbcbfc59852694d34819d0978cd09b508d103017168f6848258493be737cc24c2112f2afeabf41038bea1f74bc8656d9910b77d33cc691a0d9b12f7c518ecef93423cb4871949a518d2f06e5427823324275b97110f8f88b0d14788741e617f4b194e679a1627da50376a08d4f23b005c0446b46d4f534ed85e4692e7946ec818437089425ee30e47de995e8774b61003801de67939d9fed7bf0cdaf625798d0d0d04a61a2482217b890168e36f20cf1d6b81f9daf1a49a781567c4363ac2f3ebf0252d5adfbed17f98cc264ed2765aa279b7437410ee8b4cf42932e5055f4884deefd2a979ab1328f97cb750b3b7e4615b9c1c61659c90a5ff6d1c736e785587ec85040fb2c6decf789c2707974bfcbd0c7f699627b31e0762321d55bcc6acf1aabbd44abd7766d397bfbb68c424b311611d9eeb6598ca3126f569f688455da8d5ab86eb01f9c96186858c4b5e447aa2b9ca11aa5453f731beed4e09f95bb7376e200212e2f03551b8b09a19d6910f25898d692bc20bf6ed3ac9a0276db560de5c9e264f4db8fec6577042fbbd4510bb7070086508ac451a1fda26582c259412fbf1bd60cd5e921160c2604fde559b5ed4df52b805010b225f999450adadc6e108b70f169a3d8da6efbe1cce1c4908b004e928e3cdfdd0b4c5f742fd72a11c9585aa3517486201b6d9a98739b77970a88072750d29d005a291546f13b576b4249d71f04a9abf8f653ca206d98f738af2a1203bf0975f0a40138df054ee834ab73a3b1d7036567369a7ae15f808904e08adfc84b34a0e1356009d8a82e51c3e8f2170908179bfe47be8ad819cb12e85b6b76bba7c9b9398dfc00f550e32c171b4d5f2d9676063efee0b0b49660c10260ce052dd00addc3359e35c25dc33066d4b05bec7d93f71e0ad7d5ab83d844c7f33137894327f464260688ea4ce9847046e7dd0bfa48d4e15277a9586b4742daf0c5ecc59aceea6867068b03c20aad38d04a814472287d809a9285cd4dcdbf68f3f4ffb794701f4c265b2dff4aee55c9815938689162e08309df150538e60dccc03d495adcc560fb831444b922a6375845cef5dec56eff2910b5bde5f25f0e550ab5a13205de91d20896fe04a8ecc2c83d1371cf381424f8c43d2a5ced374878405f52bb92f4fa3c15d29ec151508488f9b4e42527921e245a8ee4b5d6ee95797f6ec4374d79acd7b467454a1d7eda05a8ae104534b23c46b27581abed6afc3ca555202dda94fc2b93501fe78867730a84f6f726dfd7364bc240b65d6c3022a04e09c89e36a809fbf244cc5522315110e9e33c8a4e1f1396e3e51fcdd53d9ae94fe7bf6c6ccef0ce02048a11441de3c25aa9787c577501977e486f8dfaa4c81e3183e648311148ce5cf3de56878847a9d14c0645777022c158670377dd9553eb63eb17e19ebb06202be8fd9bc2b24878cc86f9938e5996751ad9ca04b636497199f7f27dfa0f5ba2a01c3a491bec6dc5113d127f6aae38fa07ce7539a0c1817f7f0de0da538f4d85ffa394784a42eb50994e28530e3997e3345db28bafbb836fa463d34146d9f46d8d2b28b3954b9bc7f84046828e9b55e2fd663e562aa95caa97873f48f0a003d2251fb3ddbce0b6072fc17e0d3f99b655b8f41e8e6986ef7526544222e2d402489eabed4c219540605b9f5dd321ad902708601e85bc874c11efedd072aab7e10272c87b08b9457223de9fbc3abc2d1346656a524e9c67d79d4053c4257e886d6b430f5b7f57b2e5e92ae69273c1705a3074d5066def69fadea1af8fa9b3bf4890f9cda4b1833e5ed27f22bc4fe4cf452880c7b53320bc7cb748c0af6e7550ffa84e4714ec18d208131ae9e3edc6cd6fa2c60ab8ebc1ee56eafc01fbfba061e55014b9711eb58fdd01f8936d29dd081565de0b175b02989c5ff374e6f58c3383e9bc00d8a93903e6a221c7475e15aaef77594849af877f3807a76e03bdd54ff0b192bf34385d24d858d6f454810ee48141d73e3acf1aa3d19cd4c723a634cd8e25b4fb604c744e408dfd82961e46e8444f001d0991af24b3b6ec57ba41fb45122afc73ec6b25f501f1abd46181247945729337bf5083e5821968502a5a696043ee696c290095feac000957f968ac61ccb572ab2f37008830ab9a81d02456190af99873450b52df1888c3d8b6b13df65a9bb36a4b6d0538a0f179daebca2bed6f94b4670560fc5471c3770f2d004b6a138b8243068d754fd246e9881242638c6675f1611f237146f6e0f72ff2fba96f479fe0a662a81f40928f5400a0bbfb5ed07a87f457d5febdbdd6f323e2a59f749e6fc8a51d08b023734c762a91cc517401be57ffdf6a52b9174ea153abf2190ae2642955c3c02b4a15d72456c9d2f323de6fabbf56dfa3b566f1aa688c86b662bd34cf2511cc4a30621b6f1f1ac382bc1c4fa4c0d4d5a30ae90a5e54a9fb4afc1475e7c612eeb7f0e09e894c2004cd04126df9359d525d7f090e4b531916207c38c3512341c84218c86fc50061043ba1b89ddfb21cd756b391cb53e8c1cd55352be05efe562669e3986c022e30c79a97bdf087889a392e6da0d72cc7ea208aaf23408df23f3a9ea9bf9a935e49c9994a37a5dd0faf1267d5f7db47cf64ae1d3ec166466b2f882eb21698aa375cb50146c0e660e9bbb38d7bbc1c1c6d8333f7031d6a",
+ },
+ {
+ "68ca38fccd585eb14f953358220027046c14ef965478d3d8f206f63fef4fe3571a1b53e774b298c347cc1b69cc426d39575ccfabd5a284c7a87a0698cae9efe40543cb79f5643c3c3057a5fc991235f06f059c44a7200b509a12e864fbd748001a14790f78b54ba80cf0a4a603da9672df32b68652c1d6edd3be51cf969acfb0ae49c026fe0bce0bfc72b1ff4c47712b7a27b2cce888b9bc470b8bdda55a8d53a34d79a25947ad55b95e5406a5c5311fece3ecd46ca590b3b01b9055761da8196b21bbc468681922c66d286c32598b1e3d77f2a91d835ccd9eec231409cb2e74ede9385552517718be9f84f0f9100e368701dfa4843b7222279537306065a54d4edda3a02f1ab9edba3ddeb34dece9d5edc8797103eb942a80cb5ae130ff2e7eddd11f0cecd8f9a615d75963c44238b10ab1230d9db7371d8291feb2912d306efe4f7aea2773903d4be9a00f2bd8c03589e342269a79441c0b42ce9c6fff0a6e4e845876f7e9b342d25351fe2b1233b4f576db90ef1facfa617b96d17aa03fc824973e1c80f15e5344b0516fc28424b7faff47ea1ef4e47f6f7b50e91b8fb14027f05ca7e1bafa266a4b952cd0b9e4cab82bb4d61f99568e14a6772f36296f5d19cb04fa86ff20f04ab61d1a6f01e5282c99fe4c3254da46fb5276317be58e94b1928e3791af27dc6544f6d445dbfc7275fbbea74f98ee4aea647b654909f9fa9c88312d3759099c9d0070e3db6d55506813f8b7abe602964a7dfb9387f58e237dbf50b4185a50b65ac099352dee8695017e4dac644f42aecc3e415333cf76b08fc764a721b45d7b74f6b0a2e43637e5b4849218d3d4c6a01208f345d76af56631590e520d6bcd82627d2446b45b2c68e0be81b3924753a54f47ea27b1e08de2399b34470701c9697eedaf3248db9b28991cdc2c632fd1b376bbda279b6709d5033d1c0a3ee573bdd222ef1afe8a4397a61fc30a4e94bdc55097ecebfef6c00133dc0b72c17e2f93a11eae9fa9f1364f10fa595e8e1623dead10caac068aad3967b9ab2837dabcd8f96a77a25baef16ba84bc93661ed150ffddfbb0369683cd021e8f959c2b531bb1fa95d7a574fe5ff9aae35fb9b4a0a9829c59b932ed8634fc05ca88211da3e30839baadaea8fd9843e0e80d9598a7282500d157ee579cda5d57628e7506617d301c2adec5186708f94f069ed7bdb70cbe88549cefe1673d48c9bbbdc01d2af03945cefe6e25f757750de64cbb9d496a25adf7058f5e32c827fe75e80ba0e834e6a72344dd2aac4228828ed42fd83e4576254af5737dcd9b6c338377d46baccb02d00fdffaac12133ea0e75e791593ef3aded4ae4c9249b8d5cd20aa28cd652b9d750b88111d9b4fbe729e27882206b2f0eb614d7daaf6436816fd80d452ac71c7a7f9e8c595287407c6ab9fe8a242e98da4270b4f1d4ea7243c27f89ed46a567c643f31f967b5f12e518106f3d3e08178078cc714cb6e39079631966a9becd6f02c18e983ceeaa2106ba9043f9985b791027eb5dddceed563106bcdbc48a4ac64bd95e87c708a8cdc33811bcd16c35e193203e70ef2bc7203183fbf60d46bc581f1bdfe62387b3e6c0c4a29130d872c3f8b134e7dcfb080e7e03048c49c0e468dbc44eff4b02e50bc6889cf7600fba58c0ee409ce948aa684baef4956fd8fd4a9c4c49e84e2ff314b7900b179fc66f5fb4affb9ef7a6064354fad8c3d2d50e6f2157576f864a843dda8f547955c4d80a73d4a86b7aaeaecea886927a5ba0e97df740ec7e8b70bb650010df55d4b75f478b07b205b560d45de666d84206c1bffd02ab7b8d1c37f21c47d1711b89d16214d8151a8e75eeeb5c54c39e5a855d578708d314240a064051d8b26c6183ce755be38fe9597dd5b5d198532b1db083a4b856b8dd60bf1db197cf1df852eb6daecffd97287a6cdd4c05307722e0fac798507f75b03e9361d5627ecdb56a3b633938fa61b2673efe6c6e768e4e7055e6c1d55c7113efd3e95151b606bbf169f4296455dccb93da370150c54fc11b3682f092f30381c6ecd218a3d9d39442c8bea61d9a71b174a8b2c56e028689380879cafb7c4bc2691dda0cf6ada039755edf93f851446df9f63267f8b8f030c069fabbe6457d4f63575b5905fb927a5a720d52c351bfbc48f12440a91471697e6b2564b1a2b314fa0e6dff090079637287b635d875f120671561102ad27aa83d9f0cee41bf023bcd703ad670b43ae23bf01713650834cc1e95dd486757f0a4f6fc9337bb95738805ad5e756198579c886eb0ee77e4ba957997dde0eecd84e4c9171c84ad8f0cb23c6a289e037f3a8beeea7965ce34fa47cbd727baa4ac9e6dc3baf17049fd2386674b246aca5ef6b8496f1d17a3175f6fee86299232c7fff682f066cbed895155d475bf9fd4b5571d257534c88c93377b1a600d4c280d42aafda975eb32c740073cffa610b5fd2dda7262a2fff5da7a0f3a875c62949e0c9247827d7a49bd8185bc27967124c34b9725ee961bc8102a029786652c2571be6cf33be63cf867c2b48e5826b31b714a415fe05c27f0862a870d8fb33200719ef4ac8530a4ecf2597b4a7f2e66f078a7505803774889a1cf963083c831f46725a1ec5545d8489e53921d81f80ef99f5e51a2d5992c7769c2a7ec8bd8e0f2fd81de53c7b69b650a2d838b269185c5efd668c470943bd956e3c5e1bba5d3b927b10cee68a75372d4d6fdfa6782c05659281bc9bc56a2123967f4f50cc7ae3379ba21e1617553354b5030b3d3f0092c1824f5d47b97e6b4fedaa90aa2573e1b115ffc72d44fa8209fd8d372c8dc9ee00193b47c2a9a302875da331731713243d02eb5a57d5dc51c35988ffd742ddd75c191f1eb2c2214a1fc47b82db8ea708818262d9583f2b1b98a40b6ff6e94742f25661a51882ef28475aab12d9422b6ac48e341cbd6f38460333b5fa1cfd4d0f43aeb46c21938468fe3f7bc771972246156652d2c58b18c8cecec2dbbc0feb0fae9f6bc022e029111f94e8913c0ad741612a1426b53cff73fbb24fb7b22ab750ba1310ecf339fe12ced6a3fae17b4c429550794a8d68be891b0e30cd28e81de2fb2ecfee58bdf11794951276005eb8a5af21e03c8aaeb595ace652c5ce60a8b98f6897d82698ffbb2e02213e50d9d3f00bb42c8652d22bffb87ec576ef6e206ed6c846fd5136a87f38c9ad899371799f35a6258878418830b04da79fabd80e7290456fe17c0850a4c20e2e657f97f4a53e1a3db65bb5e71bf38eab9f56aa11e6ef71c85b8a28f04c271",
+ "ea196b6a64be4b0799b1c2f72281300c3a2577db44e5d3606b8b02fa8fc46c7aded7e442",
+ "7c86a2c06b7520d60023d18fe73d09c514ed07a91d50d8fd5bff00e7550faed1",
+ "952f492fe00b26028c560fc6",
+ "b3f3294815ce461c8843172efe93f73a8254e58a0e71953e35c15aa89a7bd9dfee967853dcbfba73d3b87fa60449cbcabf13b1206d0cb27d2c3fedcfa695b6d41efda37bb6db35449bd470a23787619ee48f981d3f0b1c8e121725b2289b6d67858a4f9ab41683bdaec8a913ca2cc292a9640efe50fb85a1d1f7b286f45d4448f85b3242f45ab44e3281d759db24dfabbae4259f127d6546ecb914d7e93e2c19230c67fba8a6cba6069023ff7ea3d8a170289c2b4391bb97a7b899228d032b36186dfbb29ae8f0e6c06d753f4c6b21982d49ee682bef50a5c2c8434510c5fa2b9c0349592f33f8d7ad6f7243d42b292aee6d210c61e3f898875b91a17a89148275031b74cb34e628d7b701775dbfcf87c79ab279a73dad14d8eed365eb9f29a007b7d2ccc07ceb8cdcdaece67fa0166e135c9a4b939426882eeca98ab887ed2e4888bbebd5afc9f2da3e9162527262b0fa85903246bc8b80df3060c890ebaa516781a2b2a138b98001287e12a9c68471912dd297bc0beadccdc31a27b7c726baf31510cd355a28e4ef786b30084af66ef135909795aa73814cbbc6552270d5e11d46e9497ba30d6d8cecf343d16e7e3357bc9bbfbc7c1dcaa5fafd8a9b07056129da02e6228886463474c5af1d670bc14cf2868b816cc71578ad807a37477341c8192bfc2e8b1f7bfd58827e041f70384f92bb4c6acc415dde5099a1c2b27b709f9e53d1dab07c87a042ca4af7a2a6ee57b37bf2bb42259d372ecfeaf1dc55ac3a9f211f16fef3b2d5f11dc19fd1f425c14779580b2501ec6e0a84220e7e12baf9e0fee3e8cf499a7fba6721a746f598f04ee8ab4df31fb8fa5ce2d2419d5551155c009f2780cdd225ec2c19f94fb9c8b785ad4574b4da766eabfa696a1994e64a2518d1bcade6390cc683a6e80cf8b163c3e58cfa1134ee743079347f08a89c81478668df32ce9cdd7b853db5cf7af13436f3bbb11bcfa8f6b6d727a1df84f99fb3a5c248b8fd5baf669b68fd9af45298030f3251bf0351fa9b58b0b9fba53ecfd838300790ebd689744c1b7b333fbed76c8fb96fc669ecc6695ff5bf8379dd2a3c270af858cc60894be8922d69fb9707bd2a7825f2eec4a5056e5e91714f4dcfa86974259fcbfd5f20d55923a0a9936fb20e5ae9670e2019336e15f530c0be449fe355a7a02c0938d60720d5b8f4f59d2e4213ad5251c6058312b43d47c44ffc8946a98797f5ace279d3e126da63633c0eff1c412febdd47817aaee466c639e43637c1e179f606780ab490d3f0b3c2d79709f1262305fc87c02f68da2dc32f8c544e7b358c3a5d2c27986a19d13fe736c60a3524e94caa55e853eedeece985d16bfa6c487bed6583436cf82077fcdcf90a05f49db50588f46550f7a0c3a1cfca902d66d25dba8d2c53bb5557cc1d87c8a407898b3c30c4f0852df92d839859c191228d0a47324ea9ec2e0ae84513cbe4ff4aff85e77b8587f1044bcb9775099ebc2f28fbcd1cad58a8ce1f072f2228f559fbfdd8405d86f8262c27c3d95e01016b343c6a4e59dec81b59bb6e3c6109a4cffffa85e9752ed2149b5624417c0dfd1a27bd2630bf59814f15820c43bfa317be59ef6f433c95e8be154a8ae94765bcedadebb717f0d8c24e01e1952bd104ba9620f067554ae0faeb78f13c622c45d97b2b5774a3e30cb07f2cf0e8b19d1266d8a8861f3772305e24ec5c9cb714806c7d705a3bed6385f8be4e12562e17ec3df01afb4ef6f7427c48a1bc0e64fc65eb1c3d3ff2d6687e4c275a019f5ab5c63bbe47e3680fb1802d5835c4d494f0f394de1ae47f81eef005127d0971c4589c456ae6a69855f35635c28b590c1b93f155fabcab59b6c7cd8ea1c4ed1f67093aa782c54329cdcf9bf84a40400de707b894587d6e08cf7fd72fa45b6709a26e97ff5ec1269b8042358f872a79e8c2db1c7ebffac014d6b6f71b0c1c1945ddedaf5b6911668059b61b55eea4737aa307c829309c9ea548fba2bede023849bd61b5a467cd1ab1c61205ce64301e2531e5d58d03c74ecdafe1f5b74627be8716cad0d0a0be60984c9f9dfeae24a6c4949170ce2f589326e0a76c447a578ea3a5e4bd9f18884f18843eb1a78aa2fae06a7569a97551b227c34d429c8e1c8c5417ced93c30dcc607cb32a365d87328aaecb4ce57ab8e74f0d9099e267cfb747a3bca9f76b5f6dfb543bc4b5c06c3646062ec14f511058eb2939601913f8a0f1785249cb72b0bb1c12a9508b23caf490537eec53f614f3e06592eb61f75c1cecfa514cf7b500b0375095d5db74556220131390b77d0db72711c0c7229a5769b1d2b3f5105f3a4370beb1cacbd93ce32f89f1fc833c7949211dd204616c013a3399a22f5325f1a00008f4c8ee7dc5bd7476848721fef843123a6213cb0c0b6ae84233ed01a77a115d06e08990b8e60cfa4f41dbc9505cfae76463278b6c6b5ac7c3b83284caaba4a6a1d739c392528ff5b06bc3b82e98060e3001279a44aabaacc661fb14e7581d1235940cbe067c6b386da09454e0467c785ed0b65d41ff4cf36ba5f63d3ff2b45c11c6c22d3ea8ebbf1d52d770e0ebf2ba0c67c7d3641c145cab474a88119335990137fa82a340c2cc8c453752a3aa801127a47aeefe66d1af1a26ee1cd0e6d935bd548f6ce33a9c204be02ba08f9fa03c685665375db7c0c656ddf3e441ddd96b0d2018beff5086cc63339f26bc8332a5e6a1422bfedb69187a3443c23b630a28b02f8075faf3ff2fbeef6cdf02ba4af47a765003de2254b69f487bb5d038759a33ce6885611198b81b0b6fc5d7a531a7a90dbc3556aa758db1657698cb3698b8207b1c1b589efe5d52790667ac483dde9543953c6392d5eb8afdafa205d325e314f810e9c7722cbf5bb76fd6502733149bf21c60717ff5bc366b85ee9f206bb1f330ea72f61a9766090eabde747b1eb9c046cc8713d5a4f8d4b7dcd7c61f2496c5b467608cd9260382b8f11b04c318a5ebb6411a4c7fa060e08c295c6062ac644bd3d10bcbfcfe2e3748eba66f65d904ff21147faa8475f508f21238d42f62b697249b9fceb905127f7684c8130cb8663f09cd25ea038078e1980237389337d1446c3a77bce41b37b50b9c3a020526e7b7b3bef370cd7af71b225700627060eb65693899d277ed130ec5ed9eee75d4886f31aa93bbf302e0c69c9c4499396b43dceb67c02fafaff8b56698308393a03f60babde883f00de2c66831f024fafaf98b2fcf37a9ce01d4f34e95c9408395716dcf83fe86c7a0f5e3e6741c3b63b6ebe9964f1d5005eeb732ce66402007beb3e6a087053",
+ },
+ {
+ "9100c5b2d7c5d5a854bce55e82f94b89a268da7b66357a661dcf75cba10a1b320ae0e4e1a5b989f9766e57f867a3810a0b5b857191ffd7aece4c796f5694a2617486421940cc12b63a6aaea20d2fac188b318a1c3061cafeae436e04d710654b96a864d674768caee03a50ed6afc06f52d90115df1db5c9f1ecaa4f5da094070b1a447251ad3d4fb0e24e87821ee6d4e7e7eac7059080f77d2b36cacbdac1c6e5063946a376865458c4ebdad3c2afcbba8a82b01b03a7882eee42eab904a19e0aead4ae515b02aa2fee74f3a114bf5b9f320baa35b3225491653f4a69e0d864cbbd031d0805b727e42c2b9530dae0c01cfc6a42af8ca730e1d67b4bb743a072f0a38008b937209d534c2284271344340fae76af2b1dd00cf44b48ab8ee92e8f9cae8845e5a8d338f505cd1c19014018bfb6b7dad487e7c8c32064421982c1a63149ec16f2bf4fe7b50cf3ce1e33d6cdea8e98bf067077c9a0ec1bba6edd5090273ca719ebf6f1a0f3e56f021945cff3c468b2dad92a947a06a024758d7505a4a1bcbe9da3a03e97859da99ed36982a7c23572ab60071566b749dc34bee1d9609e87fe32282cc9adba633c9ddcbf359ef4a83a54af5fbb5699978b487954a907dc9739f4b3f3927e66cf0c338e31c272da0cc7795c72dfe60a5b2e73bfd77b8c6ea58122a913910fe29d3360cef5d398f29b024f0dd225183d538bed2b076989aceaac460e3d45e0ca7941897f151261a024b0adf6d5b62429420144497adde6557a3c53b7723471fb760b6a8b1dcc2b327cd939528f5d7bc16ec00ad99df12f082d82bf9fb7318b3d3ce5b84ab1e38d2ebcb6713c03fd0d62bd083c4af96b4316ee02b6953431c261278aabd96e28f81adf7946e3664446135c825e45ed916ccb941350c84523296cadd5360bfe3e16dda75db10da1f710fe796f3456f0911294a4735cf9968656345b9c3049ca47176194c86f36cf702538df699fcffaa254af15b198ac37eed0837b00cd3547e496ecacf6136c6648a535a235059cd75a3bfd0bc49933b379b72e7a8463c268faaf05f0b27256fb179c9d4c923a13ec6600f83aaa2bee13e30c8e676040c06aefc65ba238a29d403f3a8cc164a0bdcaa1a5f54bc1d35fa4efee0c402eccab1e92f6b0cba94e1bd87898a9dd3957a7eafd9d26bf70866450646090833d4b91c032428bdb9097b409305de669a58e44931b7b428bf1a6dc56177cd944b87b04eabd80c64e287a5758c83db26dbc06f0c772335363ea2fb9f19c833644fe3b3fbbbbf5f9d460412d287eef862ae676f258aa45bc8465667601e9ac46e7d77693936c8d67ccde94e54d746b785ad26aa38ca0500105b6870790235e780ac50b9e3198f5fe678ae3a4ff4f1d4a2177edae183daf2de42625845973fc544907e27a90d868f8634c9d529bbaacbd228a5b4ac7fa68ac208e207a022cce4b24a0b5b5791eaddc6b3b3ef6e5dba41855ff531de9bbca0a39ea743c0732772bd32cd15c4b7f28a6ba579d902331a88920fb970aa75114e14b891d42cb947e9eb14feafccf1393796b21099e52b21773adae8e550f93364b1c438dd7d7fc76994c51860b652974d04a7e6ead207610de149f231422595f4e9ced1674d98d0e15ee841143ad8613f804729524e8a5f30d451611676f70a60c5dcc7127497f4d27f35e7ba0e48f98e9022e0deac400e809170970867a1682c7d2f3ef2c632c44568abff76f4f804841ae462c7247147b6e1debe48802674fd55b2ef1be5b4604d5f60c35358c7d773ab3a3ad0ab81868c6044d4e06a48ddbffacddadf813a2ce09aef34f3b60b666245a032f021b87c81fc506166983f25930cff728d399f6dd48ea1c745ad2da7f2cdd9e3ee915f708db0d1f3481018db1c174ea950ed17247bb8ebc065186758e5403bd4d19a445e4a15519326696e4280bcecd1a903f525bbe1e521f94d79df8db4b35f4ef7bd990c0f2c32789a75f95761ca0064bf251fa00b409a58b979e56d2c44bc2302552f118162891bd78272384c739c0c98bbaca3fc46fbb5bfe123eb25df0e27343e38b5a0c2d0774443af91b64b9d4e0649f20290edb84fcedb3bf4ba491bee8754a32716739e5ab64deb6c9888bb9fd2ada1629a59b16934ec5dee3678dcbdcc7fe5e2f3833da9d1281669b1d108837eaae5180396813883de26b957037623825b0675df431fb06b35191c06229f84cc849ccf1b1e079efc2e575331cd77b3297d2908c048b82b7dd14883f3e707bf6ca38f87c19625bec47c11f54988a97205d27ac51a32f19704391af72021b78cc4461386dc3844a1b45596fede3f70e311eba92b1d9ac221d3dc19f3fdd080c2169348f2cc8c9380e12a7ebf69efa37bda4ca6f7e66919b94532ac43022c0518c04d0a8cd99e0cbac88b7a317a1dac5469534b4fbc64080196b44498e149b0a196bb2d6f59392a21c4a4523ec1ff922a52de790e42810fd9355471169d22b734dde4a3361ecd57e271a92132a8b35cfa91d508d45618ad8c6c1ea209405a3d1d3ee1535caeaa3f20546052fc13aff7a584ff79db1726678344098d8563caa2a2abf6fe5aa03d7af49dccf1b17be85600e7cfdbfff54282394b0fbeafda615185574fdff78d59ec2a26dddba1c531a1ac007cabf5be2e2f0a3dedb9174e0a9da5597c9de6d68911fc66ec9d2b1e3fd71ebb83147ab14384ee303d067f47a324a01fc187f54a98f1b0848fdba2ceb3c18936d503e71887d548c4dbc70b7eecac9ead3393f8cb85a84f1484f2e237b36b6d886f54a0f629e8bb05b0c6839c722149a5b541703aeac04e6eb230a5659b12ed0a668d018f75bc94258218c1f5390b9aee4c0b2836cb76a47da649e2425bcf4cc15c4d51d109e5f78cfdb88137c31b2510264e46f1c4eb6e6b3450ad901ff9517b47a24d508844dc85fc5dbcc079e2d09f301691f401ff5f36500cc66f0617eb4dba389d427c7ac778d78438506608f0961f818a2080ea56d0f61c40fc342b49ee63e730df61f757387b9089e1987977b7fa02d87aec2e4be24b8bdf7fb6286d190f9df870944fa910df32f178ab692fa56b071f57366a3981f51800ab416dc4500abcc19e0c6aaeeb9ca063470993ec749a0bcbd07604516b1d51175ebedbaec8986f67a4d9158f75b5f3bcbe86a83220b4fdf12a0242951f94ac7d52882b1b209b82c4749753ea4d46a60bcc4f3eed033bde2d3d20c25cb46fd907f7052217a0a4db143b2efe8875a59441f4d22ef70d0c244b2de6a7e15581e84c860a6326ae3e3aea6d3972e2de0623d2d852c9e65eed318bd3d86d29595575df60d9050e1740f884796b6657718a294adcf2303adf61c6b23933db93885172e82a78f741b8efc6315a2c88ccb6b11692a346cd82a79334e0c610734e61e6378b5e2ecc161d924778bfcf4475805a0823a0d5a54768d9272ee99b7c4a81b3d5dfe1a2f5ff34",
+ "3c77f30bbb698b1571aeb54653fcae2c23dc16be58603f0c361eedd813ec0c4f63005a1e69e533da93e820e6e4ce1308aa29c60289060ebf24fc9738e8a4874ca4e26a0dc79ee75b8607416bd554737f",
+ "0223c0a6052bb3cdc99a284fa169ba76be2df53b677642a606090a9267a60769",
+ "7d3981073f90c6648c5e9c74",
+ "61ec5230306b70113f67b340575b77ef76d521ff75b754d551e4177591a02351ad382b2a4067f2b3af7e8e15431c7133e98be9d8293d17ef40161dbad9a4f1a4f30cdd557bb9a8b03b5f1b277c850e23ecfa0fc2ab1102e4b1d5e836a606883c3d43527fc3aa26955964b144a9a56cafa7b174d72a0635b80e7b4f871ead3838a955a14c4b8c5c3c66fd86a5e4ff10dfaa92105378bbc5f76ad29727e5bc4779ba3e6dc19bf45020f6ce4dfb3400df05cac51577d58eec21b22839b8f055226b204e641783bb3305b4461172f1c1d48eec56fe6f82aae564ac6688d7b0994747d9b23a24418e69f8a4fc548f854f86baacbdec78b7597b138c453349034c8cad2ff272781e0e6799ef2f8addaf18528736aef21ef8c2d213161e36b2c7815fcfc40747626e0165684e46a9a2275c533d548e52a9952a556168195d602ead86f6bd699e97ca59f4cb2050ff148f5bdfec358dc4542ff2f700db9861dfe5ba377ec7fdc0fcb2501e72fe6873c7cc76b95b4f300857f76e6e6e370119f403b556115b19fee7009f4f6675ad2d174f44002e35ddc360f309f20a3a1dbf39d90d7e5fa2106c53afb0bf445e4cede59cb50b8a7a2c0961d00b2c251f2d815309f74a46a424838ee87f1229273ff3b66dfb79e3b1ce11bd60e061e60e3f37bd7ac896b618cd78388590f44b1a276b965a4b95f2e3a7a175b30fb45dc7a71d4b3a1a33e98af30dbb46a217c50046ac21b8bbe9537c02f05a5780c8a5d796bd6424fd9e9f3ed5932069bc050bf4a1898a0ef0ca756aa2e2269b709cc92e0c5192ab49d692143388ede2bde4923c85eae8f59db5c7711dabeb33743c692be6dfebd815456958b5e1384a109f891f433e7b4a1031d4f30478b05766dd97eb964a28f2f7b55aa6c27c7f4ebf4d47ee8709bf99915426b3896412a855798e392e111789213af537cff7a976b4509e0eb6ffbb8e886a3596a242d16d95109b0ff562c624e06636a3611f804f9b2e252afe8a4e5e868b48e9e734f688f2da2012d7fdfe2d3aca75fd74730a85aae90353417fd52b92d28a5098b6af358a096b859859916bcd5a8f779676c6e04ea461fe62872050af92d08cdf1124bde1e889ace3c923457ecfe0a635ec757907a131ad7c2ca3f60e1317880f843c5e63f4ba59ab2882a492dd1e070b070af6f60e18cca29541206a7b267c3f75a5327fd9b8ffc9b36b57b73b36e586541d15c85253e17a2581e8f8a1518f275cc79afcf2b5c88a16e9bf553e757df089b5db90a9dcdc1867b788fe75abb5161dd7ee1cf37d3f0faa793ddb1bbf1eca13f4220ea63af8ef7c0e7144d999ba1c5a983e74d48cef708c1d28d3c0a168ab87d0ef70f381693f0d438ce013ffa2cba65a8cf6b498a7120209564535b7372690329cdbd74eaa76765962720f06aae58338a10064ad80f5a67395db2c31d36b1f5eb777306395f192599d2f737327afdcd9f14b3f24155a3f974915d3302427494fad756703b13afcd1764ef9735e7dbff920f1253cb668e9f40632aea1e0b4620db162138e4a97e6f0729b14be4a7c3256250d5e7423ba1238c704503c51cfc9cb68db7001b2f597a15e77138beea02e11e0bb98a72f2a77b7260e9172fe7e60483114ddd836addd966b69570db5eb26a0cfc4f8a8b80d26357ed51a70165bc0dd11ad7467688025bdb532e7222ea12f23c44d08d111b0ad4acb2f5b3d6b45c387d541ffc84466ed57acacefb1436ef00bcb5b6211dfd0650113ac369b9f3e4891acb2693c377467b1e9c949cc0ea6c4a72ef9292964275ed397cd2b1ed25fe1aa8f47e90cde362392da5e53893eef6e4f61decae1a75e3b726f0596f09c3cba62aa08bea89984b484d5768296a5afa8b0759dceba530a169d22b81979212b3343db35ce4e4766dd251ea6a47f5033cc090d6577efbed441bb4f8944937e812f12ef17ede76df621bd4cfa31567ade18b74583a2b783279150d584ca13c0d4784b70156afdf9be8ae96666b82def888465cd3df349de427d5f5b3572e4f963d33f968e6780e381ca196bc04a6664fe93fdc8558b21b84130dfa2a646950eb2e927885925af46d7a28d1507bcc3c02ba98318bfebe5b9eea1bd47935ad869eb701cbc35a9aef5efad88ff54eb350a34ccef2e159de8e16135b81105bf799fbd86aa11653b5ef93a1ab1c367231d61b42b8bdb4f04d8d05396d53247d51890be9b56c51cb19eec0fd1e6b8cdc98376b6c6b30963ac7ab02656ff94dec0e3a0eb3f3ffb8bebd99d5889df98e6c77093c370373dd5f17871fb334c7eb12c6ca22deb75bdac9eaf24281c965dffe03da9c940e13fb382fb6be332797813710a7cd2e7720f5b9e53fc0d98fcceeea4a8e9f787e670d60bfc4a849f34571e5d09b9e9c28cdf2b2d888eca9bb31ea8b9239bd19dca86880ad3e12b1583acc3a6d1f0a438ce3b5a337487279dc4ead1b214272d455e6a2c8cce4ae3bb29abfdbe77a67ababeaff5dd9c96b17f589cd4615c0209eba5e4b1c7167b4b739ca4b9957185961529d1082226f85068890c94aa1f1c244259ef7b120e40114926a49c4412b67b4caef1ff3ce6f3aea3c6107b830cd34df9f4d73d7d978b6b9d5c481e9d76e83d649e742b098334838fe50d80975fb567642d3b72c461ef3072ebb1d03c0099e97575bae6a12cd2352d9d296351df6965d736d7568c2911394a73d199743526ba54dd62c56c598f4e78495c0172739274c0b8c96755e489765723a24a8704093a94544f6c8764dcd1ce6b4bf2917cfad27d85e4442b4e5bd577ea1a88c2b79d61cc1be01ee9028235b36444483b4e45da1087bf6d45ca540620de5aacc644a0d5c4b807b582c7b058e140eebca539947502bf73c9abc81a0e3a618b39d3a38c4ff7f94767fd7e6b9eb61e629806bc3d183bdade7e369d180dd2f57fef677e22ce41be7224f11723a85a3f1d14d7b72dc98ccb2816b77e625ce3db3e2c5753af8b079e0d63939079a01910ee4699cb405d4d9c60e4ac86a7fda3a4c9c290662afbdb7678c3a84c87ff83470fa8a416511a06d3216a1445699d7ad7e6980491fd596d39762d576b08fcbf0825243c1fc01ec8300780857c429c607113160a8354f6699b368a87983464472a5754fd58943fca6f6779764fbe6cbb510d5280292df02c4a7ed9acec8c95ad67ebcda71d0f519ac18db9b43b28244cd34fe02c5d694df57410eb54c5e1ca0f8501e7776a811d7ee81eb9d8c80b2ca50a012b5eecd5428af965b217e7fdac80be88a01f76d473105b027eb557a523f13c55e1670ff34627667649573e0f19dda41c525a8c96c2866a88bd73e66c786767e1657960f6676d8a22be1c6024158a0f0e4ec761148b5a3d8ea481d8fed94855be82479ba23213190054f937838f0e35e00aa74c89b294c29ea25ad7e96b4b6fa952ea8f1cbe5397b7c86d0b74ccc25e22c88736b045fe86110bffa0679f28a1f27162b51410498cb7",
+ },
+ {
+ "0fcff2c29cbb5cc40bfd2ec573ecf368275ade6a00e5730b77dab17e437b46524b3814e7f470acff6ddac4e0c6b748ed112657120bca1d83a4ce01e74a473995804d7c74bd28732a02370ac8ef52b600790d1284d82f077cfe096448509dddd0eb5944a882b7d384efdd4dde3003dea910f12de82035651e3ec9668e66435f519da3fa1f5bcda34aaaf028daf3068304f7b1ec18e65136241a9db281e011d27db5cc9c1099405a4430821e2488a228805314983966ce5d806b0f014c21d4c9d6a066e63aa6407ed6c29cfa4a3e22ca913762ca9d31271d9c371fe858f3b22e931814cdbe544b9416e88f6026b12bb8e88d8285beaaa35be1c24339b5f567480d7b16cbcf6160e549ef4570a0702889feaa0ebc54b11735735b6e2850d5715e5087291fe8890432784aa219bacaa2b874b075c9628cfed5e76dfe38426f9693f6bfb2de49b710c101b2dabb7c7c74f12de9ba8f75b8645d25629568d12bfbc7eaada63364b6f56569cf21e54c95d6797e9008f3496c506ecfe5d6a010d168fb7f0e2ee3c423492df36a133fffe9b87d7ac070c32cc131fba6089cb7d904b25812e03cd6048504f7ef1736ee00ee6b7aaedb3dda9c6fd6437772fa5076aca9888ce55e906a62875979bd477aabb2f4598d32342aa10a6d187c6768f213117a9ff6d830603bb7b9b475002e20b2237a4055ae6af6b8d70e343e76265188a0f07e7820dfb3d898684d99966d4bb9e78b0e95f5044dcc12810a89a75b11474c8fc06c6e734407db91a072ffeb2be6773a7c6c3ec939514b43daf29feb3aeb7afa57e96d9cf0492d90bb2c7be613f2208f5f5f5898b0a3db8a967a75d065efcabdd83759c88086583bb3d422c6c6425525a1adbd515199dbe71350b77940813618b88fe139153974c80d968ed4d9e3f97a91b7cce250a7c963f880dc38011250b9a131f2b76b677f78fd0e4cd6f1465182fd1d644dc42db0bcad8df4ae9f456841765af8e1c1775abf85a69577ece6f9e9035e36c88be784397479e713be4f5434aa4c166bc4702a4916c0c003a6baecaa182372a30af6dc7e6fc4912d13e662bd327829f6e85340fe130001babaee64d211d6761bcc52993c162a692a10cbe7434310392b64792a777a2b31341995072a6b7d4538cfde74e609dd1019a9f75cec0896186c0f42e3896d15be87aac5b11642f74e11d5c2f7de9f07f848ff543507ea4d73fa8f5683fc6b41831606352c482c7a5a013c51e0db59d824582c595f17a6d2113528943194d6b5aadcead62516507f178cd0f76729cf8b81fce4e0138ab224bfdbb8f16f8ea6196b90ef90a63f0fbdcbdfb5320984be8a80a26b932d1db7ecf870dd67fe838069136ff9b9ae087779e82cacf1b06a7b310ce6c439047c26fcec0364ea87e4549a544d540256cb7c3ef7282fa792aad89e919dd89519fe910501f5ef88da43232e917730e742ac2539d454e066feb9058f56dd246fdbb674dcab636585a788b338ffe41f4190447a65985acb9613d02669ad4ad888004c65acb0ca315752e58f51c9ae9259f20cbe8a668a207a5a46e30891bc909108f53db8bf6f0f11549e621d4cf4763e0035c867bfe9e1192fc421c080b25289a78f4167fe517852efdb6f3ccfe67ad01b4337da2c18f35bdc151c5dc76ee66efd27d5fc784e4e6829bea4f8a41ec8bf61ff998d178ce9f4a10551687337d7705eac6cd7fabb3f2379e31c1d01e4dc63e475f0fb01d9efa3de400b5177e2c2d68f2ead89e9ecad62cfc97fd0ad5b3391d0248dd2fd7c75dcbd802d3463ef0af21eb77b07a3286a72f1e9439f457630159abde7983a5c74f7dda12b40913632afedadb691d62003c70a46664fbd976457544cef8ea863858505b1c596e7f745d4a5fb657b1c694226afa9756c40d9c49425b323ce17a8531c5919b24010f715b5f27a300ee37334931ca9ff5c83c3f0a87713768ebccaaa15e35c56f3536ba945e5d954c94c885c68325bc4b51fb55d96c8d424849ece9a812af0747d5b1dc240f71609439f65acd1c17086e025e376eeb79a7255680cd692fc4b0f5768d1985fe8a1a387074f58c8bfdea8e5c11ed379b845ce2052a5b24ef0c1a658923eb87adf5b01e6aa59ae6937564ef97421722c67404cb9e5fe07d5bfad2e52ebe6cccb41ceb1eb2760545fb6a3582bc4ca572b0aa4e4f0a2ecc56299f3b485d980501a4e010576615ad518fd2d43c1f79aed013ed1f1e1bdb74357aaf7dc84772c9ec62da43c8ffe11a7fb3eeabc3584a936c37b28a438dfe78f89de6b0d5597ac1bc55057544e68fb49a6e505db69af122c2a3ad06219b7f2a2955db0ebf55c06baac5e0efac609436dee484857f75a8421945484ad0c7650a1d3008cc85c938208f19002b7994524878d6ddf85c763a65cb72a09c3a059657459f13cb584bfbd754fbf2de904517092be4f1786b2bde26ae8eb2d884592fc9e84395408f8117e47d1ab30d5fca167bbf07e41a33c230d240e3aac53cda9f251e24659da57d721288252fe7ff3653ae3e47b86209e9344accef0009b99f2ec7b3845558f1d77b89fc9b61ebc1b589fffd3261f71b9631e87541e22ed100e694854bed771358f10fe452fba61875a605b8080cc39e3eac13708e32518f28e60464c38b782c7c7800df63b6e7e95ced9154ea54e32900f6998f38eb1e51c112b6949e2eb11a96b1ea0a68c1e3b5af750a99c9fdb2cae44c5a1d37686ef87b158d19343e23daf00dd558cfb91e6f2e18f8e806abb2faf80d082f657717d08ca4e9c0d30d9bc30b612bcb1a3a3a3843231059dec344c6c04ce625b3fe064092e00175fd9d38f8fe54c4088efe30d211412be01460a6d4ad8d0a618b00a21de0a383de30ccd72f119b27a08958729a999e8aadff21829cbe8cfe398d90476e33db4c64981383a9aeab4a27f3bcb29d4b3d3b3a6ebdd71d3ac546b8658e269959630de176819b153cd53d2091efbddd2cf9178ba6ee98e1a3df9a095db0a2b713a0988a22239f5f08cc8f9abc3d67d9267f54dd5dedbf01bd490b0b09adb21d4e5aa7707e36cf77034f01bf8c7988a2e8dd7046bb2f486878436371f1258f3f7026afee6d7f6560be67103ad098edc9665e00118d4879f58bdd677cf2e6bc631d5c517acbb6db8a1debb4fe7492b7daf0b7ec7df056637c23caf926a1a589bef1db29cd81f547afd0fc9e459f46108ffdfcfdee43515a771c439dbde9177ceaf296a8749be0146cdca2b26be8c2ebd6cfd9b5032b1f7a375307f54c2f622711f8cf8684afaaf17c4da3e83666c40d26adc239c8d1a40024bbf560db5787ed404763d4e70ec6635c6a4b82c10f8ff7ad42217613c57648716ba94cb33129f3789dc86f9c8ec2e8e90e6bba0dfba1bb3dc3215188979a09f33346a6647099ed0e624c9ae10f83da0def840bdb25b718e8d86a616ff46b5327b1f99c22937920f5b5bbd6b53fa0b32f24befa4a7603234e6d94be51f00189a20b15c49e8ee58434a15ae9d10b9cf0204bfa7ab1fd9e006b22bebd22b036c4bb4c9949cb7ecdf01028d9f12466e144b2dbbf64d95d65347013e192d428678f64f0d9306f97208fb00a70d4615229143dd8890725ee3ba6021d38d6359055aa812edaf",
+ "0c5fb7075f5e15a6733737b614bf46871e29417e4b140bae6e10081623f5c52f557c36b4da4b5a4e82920497514b1e6f745fedbf73f86ee10976f82c6cbd5bc13a917514ddd062",
+ "e70954c812cac03e367e99f7b82a6dcc073d2f679f965d524872756ee58654cc",
+ "5f6267f6b3b21423267310e6",
+ "c53868c0fdc14e891ae1bc257fbb13be210a5d9cdbd9d18fe1b474f9a1929dbba3f25222d8fe8c1be3eef22352100064b922fd9642ad128a202b6382ae0a67c8affb0c5bfa1a80e55c1084cc372485243df872d677a80a3ef1ca3589908bca621f6f50133eb762cb9c05775d13db7dd3eb65ffd3eef96e8dd42928facc68390f6bbc50b17e1ef5ea6310d8756dd177be2cceb63a97bcceaa046794915589ca022d90756b02c22e8634c0ed44192abc3b8b1e2814c855ab27aaae3bdd801a73e6209fdd559ceb59a94fd98a66d12a31a643ca2f4b07ed910bc390f77ab89395d5cd1d783d8940dad4447f0452991b209cfcd998b0c814cebd08f9ff15052818bab0bf51c3b72ac1020d3b0974fbdf4ff941b1ab9c01f284fe82f2fd89c0aeb4b9fbb0a74ece08b3debc7b65e7263e2922fd4aba15ae3cba7885d04127c8e06a67f244e7aa4556f8694a5db6653f6e48d6de54f9e4024d25d3236d4f933205b6a358aa1506f832ef7d556c6a1bfe4aabfce51f3b5ac64bf6ab1e665bddb12fe13db9f07a55db3da3886df36ddb89f3a4939b1e9e5b701301570e3d01c0b947f498dcc6af438cc15e6038cb78a78986da0316cab67bca3e28c95e6b7e6b36cae9202cf4a77a0e15d3c3291d267aeee172dd587a944719b9fbe077603b4d39d4302b9a6415aa07af309a5e1cf7a9379552becdb4bc6a0b5c85d2e63bb141c405afc58a8b2b4188b3883a24eedf98dd50fc54725c440ccdb03514a6f37cab49296b6826b6bc7d7ad8cac0a3425eeb6866d94119acdad468cefe162a29e8831c77aa83321e8ae3e20e968cfe51dbf2b63f4e26c61536e6be4f63d61bbd06af38023b15f4fccb8ae0356d924dbf646bff69d1ac0d6e1c7f40b12d6d16e52d1c15958add5708bd38c514e47fe623a67c9ec211cd625b398fa7fd67a23e6e9f65d42dda2bae94524372fbc1a7e0ab3f1c451c126135536e73c573749aa60177dfb68843752b010e2cb9c1afaf51c94a48cf8ac7aab3fb200aaebcedefc6cccb581848da0121af92d9f4be002f0c2beffdfa65c36bec80e7f62d7009b1eb719d24b96e97059e6b50a52662c2c833738849f342391514349305228b29bfa9c7cf2a931558ca8e704c600148a28bd871465b23af499c11784aa45acd051f276d82789c58b14f12619372be4bc3a285f6cee21d65648d18e61752d6e7957736d3385f8ad36702c451c61ed475997d6d9f11c8be5257d8febce329aa701028aa2b5644b8515a95b5e866780e32754ac2e6f2e31b2c04a4ad35cbcbc25b23e9bf49cb1a5d877ca30880741757c29303af8676546760016f1538991b37cf0cd24ad3b1d877e5e1bd083e4b990af6ff5c0b28e530db3f463d21e76c928c8e1ffaa6c045937ea171a9071827a173e231f50e95430ae4895932c88ce048058ce6d0a50ca5c1842506158e98bb2912a61c7991a2256c97cb9050a4bb3ca32594622756291340561e9e584dd2e096263b6ff8eb898ae86f5f24500320d2d0ebb30d84cb4ef876a877dad23a611b39bf0cba5e22f2850e11c298fa23fed40691b83acc87136f8fa540b1dc40d1b0d0bd489ee9dad785c121955a094a2c6bd3353e142c04f7b88b2eb3305fd00d5eddb391b73fa2b16a6357aaa2abf2059ec979bd3ce06d5fff1c325bbe5c833a101615750613047d8155ac0c3a0734cc6aaeae7cb65d7501cb95f9d6d1161d09c961c0681547faf7983ed2efaf4e0fbb87a06169ecff1d0ee540a9223a73f75584441d4669cac09c2dbdb8aa2aed74eb9a2870f2021eb16e5f5c3e79a24d7110af4bece22a1086d27642550cadfa4f0e03f2c032a2745e1c9277a4f67fa4dc74ba056110fed3a63f643567d079c9430b8d5b3bf57a9b3f02d486d870229fee5462043b6bda8d265c745ddc1b8952bf91828d6db2edcfca7051e74df9dd456dca5e04ba469b9ff6a8130aab3903c05659b8f31cf4ba4c22511493a36541ff9d88c708dfb714d52a3c0356543e6efad37530b598bb63c3724772907abe4cad39c896c62daf5b30cd7d37eb36a7be2494353028c76e8d148b018c7bb755c45d2a33f61944071bae8316881e9aa37e4ec2374aac4f8436ed3c7db2092326538f07fc6644e0239899e3335f73c1e3c4602b12d19d7b639d4968974b6b2703ec1add8cd930cbafff4158f68f06aaac83bb4a2e31466e2ddc247ad71c5f4c49af7defd1394e21819cc24c78380caefb2ce87c0d1050680313037def12ca21cf67bb6692d6e4a9e90a9c9a0b7118ac300c6c6f636337aa25bc59cf1d9749dc183803cc0ccd1ff53210352795c6edb49ff1e5e8ebaee7b3eda6e3c0c340fa60594115e37fab60133b8a3b39d2e63db0bc6a03973e236fca801553912f93feafd8b96766049dd2066f3c5ac9222121ee9d36cbcd8f713adc8779949941f8a8dcc92ade62e46e9f1b292d5f7eced14c3bff50a811cb762ced1f103652773ef946e18569eb5892626627e085d4ffb3102c1586ddf88acbaeed903b22d3e7ccd8b8ddcdfddb872403240bc8e0e46a068f55bbddaf90fffb9a914187aac2ceedf21fefa1fe32fc7bdbb9fd76dcda1fca7b39107d308d11a118e47499dc4092ef0cd28d0d9af84440f095b4feb7adcba198894cd89a324c60ed0b996c520d4b33391bbbef1997256af7ba7ec1069244359066af81543ca23105742fee3480f890373d3205236bed566cd22a62bf69f8c0f27b714f84a203bca1605865e2cc2f9211389e0df7a4b3aab9d10826639357efe1f5fe64a1bd6d06d0b5605658c4d2d12e1bec77e70ea393b0a09043dd7d6684bd53f4c883f2f6928d99ba91873d063d43600f9105d503b11d8dc2b05e34b4fcf18e78b2b6c97d3b2c9249a2f6566ddab2a8a67fed6c9f8af2f4ef98dd579f2d4fb572e178489c503df5d5f03bee9920db347a6e734ed72ec7233387f1579c13725599a33a90915ddf03725dce20fd3806abc1029a20732380596057830ed63b6edcaa4d4418871bbfd58de1d1f2800588ed207f2016e11abd1baf1895f6096e2c75cc5916836a9ddc09cab4c28e53fadbd7d3080088131cc270095315b61011b0cea5b4d64b647bbcea54d20be1eec0992c72fc9c9771cae19191cf6a6f1840acec1deff605626d0a0d79ea8fe0af63ea75e80f8141fa8d7ca6f4c99dc7e78aeacc67762ed0134f1a0b053debfb9ccb145800b9818c2deb46f7124e8655f37c3291af107ed75384afcedb44518ca14cdea341c9657ec638531011cb957ed6b3434b736ae8c8199684cc58862638c5f6c07e1cbe8ae68c5582b1697ca9dbdd01e97023138a9173d6b1294cd99514a28102e6912b1c87ef22cdc611133bcc111e95c355a26b20a3d6f0ead66e932c5e1229b0fc17a7d6f78134c69beb362ca75017b1bf1105ac8970fad48acb8313cb3ff10e9d72c4ff11f95c2dab59575525c98653a9c7d31585a3742267c062d6ffc7a4303a3e81a45bf39e1ce2097623bba70f216aa612c64ba06ed6d596ad6abbdde69d56ab45e25ebcd4e485824449550232be26f987c14008f67c9db9d0f709f567fa44502b9e0839457e5f0aadec0395bf5c38ed8de7529708e58c0a895198fc8b2570fb6e68547630ca7f313526d392ac4776be973205f971854c300454d5",
+ },
+ {
+ "95a17355dfa9d378a18ba20e58aa4b8711ea1d6e3c65e0b2d3c6382892c7d02768437d47ed50bf8edc619c340be7bb1cd1d88b0d3d6bbf1031f738c4be09eb264c686d39b92cc7958e63c9994a84b61b5c412999ace8a9dee0e2a29eeb8dc537f63271af5f3844ed9c0d86e6913c02ed7d2b862a132f08f311aa92fc3757342d89a5dce8dd20d5792d5c60be9862ab168d3140a061489472f2266f297da357064833ef2554c49f8120ff40b961ebcfee1d0f8e7e5722f049485f72c502c9cc4afdbb70517f0fd2a00e12596ffe285d1b37eb998e0e89d756e9491ceb13e83610a3a66122b533c2c3461b3244438f5f7a7af8088881dfdf6a29fb563ce38c4c8632ada8e7e06baa2686dc6aca6bc944e5c14d6e432c4dad554803912b8fddb1c18a59a86bc452914b2efc1599c5597f87a6edcad33a7728827bbaad0a975ecc22b7748d7cc71ec7f51adc8fe0350e67dcfb31af35a8d7b72391642e29c2fa4b796ed8f535f6bc2b1198baf1cec858aac38959f83130af55c21383ebd57d364eeb0e442104004c1599060667ce5e1191e76a89199a386e5c4bf147206e7d6e598bb27a90b3c6a54cccacb39a0ac42bf22eb40bc8ec7925376a6c57d8eac6317578ac052b72ab773f572ad961ee05531cb95ee5a6d70add4176351960fb4bd673f7db9f698616a8dd41823f2f87924c40f131e6c83bc40ab1f92312f46ee86765c306cf4a1d77275ef9668d80f9d9c1ea0aa7b2456bbcf764e009584ef1c0b4b4c683fee3fa2641f48ccf7485a8356fb3dd22f848deefadbef8050de9c5c19e8c449c6f3ec2b1324f80a7d428dc44dbb966d40244c3af03bcb410a57ad1430615e07553a22686f1a62dc6cf090aaac3707ec5b44274b7fe28c7a3a298e7a8adc71e016944875bebb421babd2b64809be3454f25b90723e2cec68467ad2d14744b15de8f9c397a505a340e85998e207cd46fa18d76c46f458af4ac3821c0ac6cd68afb72c376c31daad1a2435fc2bf333260c1a82430edaf2499e7455a93b1301eada2e12365ffcd36a1119664d0c996318a3e55bb2c04dfc5eb251f7fd64f9d83f27ea6577d748e1f85248355ed19867857dc3383e01249cc37684b0eb8e891aa663801e4ac8f0331b38686a19f0d19f6e94c7ac95ec395962be0a4e3c8358d2f6d8f13191e164ad29cd1733bde8c31c7d8ab90366e26cc9a06707dcfa60bfe139a112db827778ac348fdfe26892fed61db7e9849a464e3aad561797b6c778e0688bbbeaf3349727b4670a2d0a08f317b0dc9c4b12ea85c0309d57e754d0c7bd5c83985fb82f776c968189908a8ca83b5944767c2efc3c5f898436de54fe8bb17224012a437896d9fa106a749d12aff657266276129ec5ac12fc7a77eb06296d2a2a876d931e479d3ea201cbb4b1b20bd81471eaa33786c624013e1f07577c2171f38f0511c6924078a40c2d55ce392dd2ab0885e29f4c06907a1597c181b933853838970edad7777ed394c491cde27478eafa5b7a36520aa0779261f94b957e83ce058298dcfa07b08ecc425caeb6c599a11103d7631e77daa0d9d3fc6f42703d57f2c624ecddd56b9a27b848de7dd28f8ed656f1e4decc95a8908217e2f2453ae50b5fc1d9352d735ce5bc2b538eaae25501d449d090df793151811443c64f28d19eeaaac4081e10edca4c4148e723ade8f7e7b988b732ba08b3ce4c8a0d655bac4ff66048148135decd7727a49ac59d82ad470b5479c55d3d8399b790ff033d3ef99d770e1eacecdc140480aeca1e2167553cbbdef2090c7592b40681b733b0a0d127beefd49bcbe8904c975a5ab8b1afe56d7ed7667b5cf92f537ad6972b876843364817c20400524097ac9b405e4b35bbba0d12355a0b54bd763b4491b2acd4e8e4fcaaf8fcfd398499d4c4e81ffa93ca07a5ff51a1540f178f43a931e07e1ad56ab5ce57a2f7dc3ccca114dc9ba8a6934e95f4efe9f3f76947909b280ea5fd795bbbc0feb3ad2b704e305cd9d8f37d178961f77355eedc9d7f77c58e1db2f7797eb8682255939293c3ef7dacd2eab46c4cbbdf929aac301a13f59831a88fab173803399d96dc216abb9f079e79bbfab667ca590266891c8a7ea4bc1724573e5c5a67e9f1341b5bffaa538e240f78da7733237999ac86141b2ac0324f17609b71c885630c90befc3b027a5f01e33979165ce2a00968c414838446c2aba76e1d7fe3707c742f68af21d30e23b637accc848f6c8df820a27bb4e94e5090ac6e008fde7cf3fdd5931fa891335ec8d01b5d6f77db57a87dc35d6701adf7ae0bf82dda6511c83ab4d7d3460b221eeb3d6c4aa537924db5559b1c6739040534fc330f5144c78bf99f5f4faa715e85aebac043e2529197a82ca40f65a8149a9447a9e58c61618600b0c5ab221420c0cee114a133a648dbc2eceb2894ffc329376d1eb3ce7039cf30ff6a53038b23c26c38739fdebc7b919956ca2e468d577dea6621a8d66b78075ad26a6e6d8e20c9b694698540d516ea2bd108625e5fd038b5f1e19c5d5993b82bfe16897c375322dbbca81c81cef6ad900f0ffe5ed02714c208a12f5234d78e32ee07af155ad1e1077a0d8938f426d8f326c751f6ee66c8f707e8493cbfc76f9ddf1ea329e094315a91ba9385e16c890823db0f0231c7f939a042665009d5edd8e48102c515341fa6eea33cc00fb5d82380d735b29f2eec3f61428f7b186d43fcee46b2037ad1aa6974d729848cf1a80dc8ddb0580c9c876def06d8f7642cf45263a655ee77f047fcd76171546319622bf71283f3bf0b519e123a85765779c8bb201e99981ed184e642f63aa61f9cc206bf45fa6e514bfc637671d9cdfba2891bb112a3cff438a6372ee0dd3e7d9f352ce52f8b367b7799e1f963bfe50638f0c74b94873fcd3d66fc1e342a8bd36fb8b88f33eefabb78eca4dc9c89e2c57aaa010f2140dc5ea7c86cebe2f8bf42a167d1d546cc80bfa9258c35af6efb1a090c293a4cf588e4bdf5c090ee7fe38fd7b5551e71e5ce2b0b5a50bab95bc4c257edfc94d37579816b4a2249ba05c991bb2ea02d047e480fc8a8ba71f48f344c6d20d140a64ac20184e45b4eea14d0953370c237ef0a47a7a2f22997715dd3ee8ea52f24ffe12674d571b3bf968454ca051701e411499bc43bb55bbd033f9b81d4baa6c49bdd49614efd20d58175af868ca16a9deaf65216abbdc3beed5f30b209e786a5b4c006f3bd27d93e9d78b51a1a2fb7f5160a0bc1b7df70952ea1573888ddde3d9dd5314b0d0a899a733eb48d5e6c7274667e362e4da6b37c480aa4d0d8730e66483fb1453a3aefad69942ac7f09d3c571b6275590938c541336a121bdd20722550236a9a5e4a37c7de628fceffbc260b1e9b6417c4295907937b13609b8585ebb8f076073abdcf19104ed80ffafe1b09997f115d987a552be5689c70fe125ca702d2ae4d807d5690bc2e90b72cabb0b61ad203b34c68df21c16b92bf8def5680b204ce327214c32e4363d5600f96162a6819dda472acc6441858f396385a16fa5ee52cc0f9ffef3d53c49d535aa37db2cd4b573ff81d74006677969ec1ad891082b5d18ca5b0b9f975574ccffaca72b805c9f7fdd76bfe3dd384dc953255a5b50b7731a137fb9aad42e77d3da1eff5a7b9eda5814993cf2d289bb25ae1680ffcdf419e073d38b4701021adb2019359bb70ff4cca930be7bb979a0678f20665d14803d8753c8ce54cae92feb026486ba747a861daa449863bd38cb4d5831aa6db1e7f404b0c3587aac8765aeecec686066ee7d11321574f04d3f3da571e71222ce07277eca7ff97607",
+ "5e24f34a8d53b17bd0c2aee5369e3276dbd7e7c2ea0990f1300fbbb00831b76655aab1e2fd625ecd",
+ "c1d796f1e651a1ee825855d80206baff6818cc8c247ee6ce62b7531e6e9ac32f",
+ "240cb25aaae4d085bbb747a5",
+ "319e968ad291ea5d4a057c38f7afa4ddb9c9565962fa1a7b231e397a268ad8e0c5030a2df09dc4f99402ddf2e0d06e753bf55e1b318b3e5ff0108de2328d3b8d53e23e08bf7d84d59fededd60d47bbb52736b0491f82c616eb5f779c496abd6499555035e4513c8613e7204e6bff8d06dfecd9ce38c6b83efd8d0e41f84f7cfc9ae07113237987a4b2eaa87f7e0a310155e282e57858244e9071712fa026cb781e5a4bfe6fa1bc480e534096394459a3d1354e2d9a54aac6926a60b388410fd0b53f7a3a9116292f37406369c22ea674418c4deeead171e00f74f5cabae5d24a0686a4bcd8ba99aea613a23edd0a019a319daa3779c212fbdca9d772fc3fe612cf178c2aca2aeaf6bce2433494027a474eff699bba95fc7dcf79ca1d77b1e097439a9050a5cc78e0b78bf2e7f50f959ea2986a59be3880519cd84d0a673acb0432feb1945c603e70748445c74600ccfec60efcf9e4d02a7df5f967de4b473f63b0b0499ff4ba350ec1182f3a0ac17ef9ae28945fc9bc714c49909a7c1e2f311aa6ad7652e22e1f48bb51cf53814a2125152813752d86c7f9468a991d0ac84b1a2f3969b8081c228b7f5760718036e26a10e211ff04ea323acdaaddf9b06a08c92ed663d0fdf13fa601cda45c416c2d3803dd9b5ca29cba57e59cf4ad93176c65c64507b1995d638541c90b381ff758833a2ad67b0de44c280fdfd82b3c6d4353ae30b33768863cd3169a2032f26e37ddd57e7da1673cfc7375bf6e6792495a2b434155d684f2a6f2b919f944469d47be5aa7da74eed69d871e6f65c3ae08904a9ad042ba39905188f0b9158fd14094bd6a408fba6ef57566d69eccda86bb54cd3ca7381f51bffeaf8bcc1ae8df91d22c359888e21b70f640d6f3726a34e6100ee269124747f0ca05110f63deee07e3628bd6aacf926036ccec02c0b6bd7259db52ea8b7a686b36ba1d0296c85e43e25d72ce46c66a1e646301dafd2f4c502281e6f949011cea69459c026c65bd130d6ef06be17b23a9c9a84746e39d017b144135025ac527c1e653f233770cd68e9f232c3b623ceda836843b3e9ea313cc6a57d28ce71ccfb7265ce73b06bce1447220645e6f66caeb06b55129b97c8dd8db54c94d771504d24cedc86a8ec706a9f7dcbbcd7fc7cf38005b2913b1cfb77370bd23183ac7b5ca5135a2738cc91d05b2b22640469e3daeb6a7b0f14fc6652563663520f7754aba624a35e5d24529a6ee9f5ef0d019d83c04f5a93a38b68cbce0cecd42a11aae305475806326aebb4f673791f50c9f90894add51a0fd7c02807efd8c1bd21fa717a860e224bc9fa3f40975fd8d558e4844a09f8920256528450d77e546604e2ce2d38efadaf39a0ea3ea12156174aa8a20481e6c1190e448564675f9ca60bcef37cacec5aa218122e7bd25b571ff10f54979d62018b779a2a3d5d7d6cd56ae31efef2c844ba50ff9da88eba7a8e0d9fc5388a805ba4ad35eaa4798e395d2fe112083cce2f11cc850d25ca5c6e60a9996cee4789ca99d519daedb62f4fb1e535b742a35d71d7390117e93821ff18948a78c1fcdcb90a5f1211327d7ee0663ef16ff446e0e22d8cb7b2d3d05469b1c02864f4a87e2d9715f60c9e7be841e308d0a5f6c50161a4a0464aebafb88e0d2df8cefcead93c9623106d5518a9852f320235594be10c45bc0cf06c9daa007100ff97959357f9be8e49c870d0a11c884213e266c35e9131439fb3654fd5f1abd1e778ccb02b8c262753a22653a09272a0c33b6b2683c9045e8f967af756b98dc1797ff605c64ac5bda8252e9ebfe0e4d8d7ca754fcca5e3de3c4b63678da095281d76d60fa12ff4ca818825f346b9c4e426cee16db5818d78a527a901cd088bc2983f9b83430b50683018996996717a1738439680b68e3f61cbdcd0f0e1a6b436af8fa05d3ce2228054e319bad1dc6ac970c75313c552fc1136fabc302fcd1d09ef1b9138d18133a772cbd9cb197ff58c6e898f9e83e4e27206f3b15b6bf2778aaf9fb38e0d50152f8dbf5763816132a04b4b2e9639584b3dc8ea6d95ade024f9497944200ab0aeab206ef099859b9240aaa15f737c1e0fe6d015d04f47261ade4928e3c2ca21d1f5ab4a3f571f2ed92ebeeebf2493e6e39f0063ba931e165384ee1b5081f5f8d26ec24716757037f5158d35effbe67009080ad7b0381292a513f312eb28328cf5ff47a6599e36c14277c3eb5053c5aca530ff5954c21c03fb3fd5fc0facdac36dd819b0495fde421411e0440991da0cc4a20d294446115c0b79045037fbfacfeac574da3bf192fec4bf38c27cef71d03787430223b6069ba6d9273ec8679736a832277c657862ca791b559a5054ee8c7c07618083f75480c8aa01cb086c7317315911802e6cefb15bbe20494b14d97e3a885806db775c216dc15949e3b724f7cbb30bd2c46bd5a2fd6132352c2b21cc2b47891dd9794975f70a6fa7a0791ee761ccf4c263f27f64790826c1aa656c39483e029baef0855935e7e6c133a4035a3699925fbde131ca62948879373346af35bd7fa52b8d6c3338f213bbd9c79977c0d710028d1d386df614c5faf4a1f8fe5506a9af7059370893ff6d07d91383baba67a617b5d829e0e2eb20e541ed5c34be7ef0eaf6c6f6f52d7ca01933a2a4e8de46e422dc95161ba8ad354f6bc7c8e4cf8ab5e08607530147fcd7c9481afc621c5a3230a05e2c4db79db9e1e73f43556a8e8f0dff7ffe420282212f23d4c5f6f8d2febe129b9fe5ba7ddf27f72ae898a4eba270b5d2bb3b6b06e38c546ba80a9b2bc46097d0b47db5ae72485ef2c6419e856c33c2d66a861b9d474699e730eb8a8992e3ea9c1ed74316687d5d9fc611189eba2aa31af5ba8e81179866dc016bda977c59c595e40001c8ab3a4a44cec00ff84c6dbd9ad4be30bcc080e69b9398089d6ea464a70f536ace3b447693301c94850606d0de1299770b5f45e6d28f8ab83e3ffe52178522eb91fdaa9e4a696674ba0f52ee18e960b04415782f018d67479081b1bf9b4c9b90de026cbb66bf7d9d12cddccdd9b2c8ee2f010892571c6f0c0feac9555c71bf61f9cd69553cf7fc2be8d058e0c3430e134adb1ba28985fdc4f0cf71bd3cd09f5f82f303cded0de62f98404477bdd0a846c6c51e3e82ebf72f475afc8e6388aec57206018ba2528ede194345cc1ee95cb2023793f692f708aac3c9e8a682af36b078f5d6c7a3ed07475e9fe73b95d1eee048ab898edfee3fac4beda45f03eeb64b2128f6df9453ed77c6010e13c0270c068f704f49e62fb7410be90ffee47584ca2efc5287dae1f63bcc1819e7548eb9f0d8a3182f9ed00da3817255a2ff735876b75cd21cb25e86aa4b2893f9e5089dfac76194563f9a14335dd37ef06a501c89623caaf6feb4afb792092dfed515ba7518e278c341834a9dd17b50a0fc860b62ec621b69408cb3fbf7d4ab88a3e367fda84c82357376fa9b1161b739361c313b99dcbf4122f3870c8175093298cf432174217398928983ab6cea4759f18e7a21d71fe1b0f3cda05d241e12db0818b8763bd23d958d6e52981ce8d84cd6d82640d2000874a53c0bd14949ec99e48ce6c954ef0d08e6e319de5ebf7e142f25c0f50ff13f6acecde6a270c8d8de05ef4c310ce9e92f40f6f2b77d6e7aa3f056d4a20f7faa7cd0b93d82e3972343a50a26ff462caada10621bc953b73913944246d2a4da25fa52cc6ee1293c436ab9031ee2dc79cce39f139f44d473c236731257c6f65ca4d383e39cf8d33923afea3c80244021d36e0ed43230c44e7d1a1297d35464861f9149d869f26cc51879027169803e43c898d1b4a2a2480197500",
+ },
+ {
+ "2158abc2472e1b9c061da2c01d0ad9e996fd687cccca331fe8a2baacd12c06f284b1b5cbdfd067e5ed09a60a137ff4a97c5c26482659680ffb22bbcd4ec1bfd272749e52440537320fdd3c225c30ccd98cf221b34b89c247ab7d14f93ed3ccb0486a028c6f3abe7e17fba1742b6d4db85f6e6baaf82df1a3aa059de8d9699821d39bad42d56cc1ec67626092cfad4a2e1cb5d814e2cab78ccf5474a8bd0dc990a877d37de394694af6cadcc57727f393dccba7bf955f4b65b3c00d71cdd701754ed4f231685b7b5e2557239d7e16305be2d81a773765dcea25ea5bf2c15d670f3159409ab5bbf8da121c779132a8ec1480068cb76b68a19152fd83135aeb228b446225f91d1ed4303a4bc16cf3ad8173b30d2a1e75ccafc8c933db231efeae6260d45c7ef230ae2c7b6f986f1c19e2cf260ded9cd99d64a2d03fc5ee3d73509e47ac1c39dcca655839fec75517a9243eb611da8fae3e317e7df66cbb6abd59b16975eb463f509e784e65cd660ef1a4c5027e54b1bc862f397c9cf4e6594d98c2c2830801d3a679220b46881a372cdf3aaa33eb66b91a9f36b6941c0fe1b4d2a437daa50b811f2d8c65b5a69de185d78bb9c2f172dc90a89324c5a2067974aab14f4fbcd06ee95cd49e03717f88480a410afbb4e68b5c79b0211cb69b90604cdfaf08af1ef10cf28f0f630e97ab18d9b5138d9b9ee9154e0b3104a6c164f2a114fa5032eb5c247a6b87880332a0dce7b36982515297a05dc8a4038a09f52b1def7b4fdad8735443fadc462c7c22132f8b9581de2d213bf5c53f7fce34aaeb24263afefead5341a72f88d3acaae6db367c5c14a97d4f9e438e1e11c3c8fde7ee37e5ece5382e8c68b660146046ef96c24caa6bc9fa0a0c88281e4bf01b32df5218cb3750f9c4b8af24cc106abca62d085198d14ba2ded3cafc1fbb17519a696965a1ba5f65720e893f1ef3fbc5200316b9d4615bb23426ae53e1c5a57b2f0ee0d0c83f353b4ebe7a6cb17531d278478b4ca8e6ffdd0cad30ed73d568a2e44972ac88a7e7d665614316d674e84ebc739b645a9a4166477254ba47bc5c2b05ced88e75bf64da21a7f1f71cd946d84de13ca77b7e0dc2f0617d371ed96323a83bb11dfa16f81bbde913d9c259b10f3aeeb6b56cc4775c25f49343cef667763118932c2e8b47ec745ac537b37746ed65fda2d1c11a2de60ec02adcb79152e8a9e614d8715cc4e6b6891d6a0063576560fa3621146308222432ffdbc351c36c37d844a934088fea92ac54920facf870a62e91ba9299dcb6cbdb918e2d54fb642c3f0d60489c4bda489f6c584b64c8f19359ab25f388dbbe636c4d90c048f5ed87024dcf9f98a9e738163f837a07750d61203254a80d120c795f9c3aa791272f9474fe330da81a45be5ac838613d46c25e781606862912ff88af393040605fd4d55d07e2052227c37ceffcdd2d42a08bbab69140dfa4406853799893daf768af546f915a91b81d0da719ebd45b8b5f1641f15621959689e810217bea18e3996c532ac6e4e2e4f289fddd5e5968bd6fa9aec5ca435c532b6c74a7568c8aeff9dd19bfc2fba3b484a191e2faf9a069a24e2e6d928ac0bdf635644cc1ef3bbacc547a8e4f1d42d4bed3b6b8cc56216fa550dc37da9cf4d1d1591d9348594d14adc7a3fde5e5d1a3b9875c85de7df483cdd0baa86dae793e0796d14fef1f649de6079acbec6b6fa5f2cb2bd0481f5316f00dbe5dbc379bc3cd6d13bd8c775a727ef43e6a5fad1051783b22c05a75d64a8394a73fcb430299b015563c8cb0ae0aa4ec750399855411c076d21aeca8656f3d0cae084fb0a1ffc6f73b52a7ea5d4bd6d24e7057a3811719533105fc967439a32241f2d3e3f299da2deb821748cdee1a1c5e71bfdf88d833bade2f505268f375a9e6488cd8e16705cce91d15b60b2fd269a19148296a7be348aa349a12270fbc0d5748e538afeb0598081a4f1349217ceab3c4141d40f765ea2bfffd530fb9606601469fb131a44939be984c07bac8f26d8c068accfdefb729eeb47cfd6ddc646e22031f53a7698c6501d86cbba05e282d64b2f962a1b08b9064078dd1e3f14006f45f599bc8e600cabe6d855fcbae8c3060859202361d929a241f6c0711ac0d050b67a1d44da19e0b0e236adad1f60a327c9c34b2b9c64cdde5b8e4f664f2fc70599d44a63ee2b14d051c27d71231098ecd3d4086038d63e84547dfaa39db1a92785e38b640ea0345062a1c185b25a72862e7ae6574114eba592d6492087e2580dc5d361c473a614d647e66c0a30de806f4976b69a8b92301e68794ee05b96ee116a5fd5edf5eab43dc1103801eec861383f17c2bab9f2d9126c1802b7aee0c909309ee72679ab644abb9c4caa54add283b5954e6f881781e42f849bce6554c7a5e3becc5d5a209805ccd4a0117272a53807e3978ffb19641a9dffd9034490a9284f658599961daf52f24f6464c2099cc9ed3459d84dbde2ebbdbbeef25c882a9beda03573bdd4c6a0143b14d634a1a021d5f9fa23a7ed0f5598ee57e56672814412b6c7c08b8e709fb98575fe2716100d000a20a7e7200d800e556564c7e6a8da9d609b18ff0bb8a8812e96b834a6b534b0d5dc97f5da17f42f8d58e763f1b201625d1a5158c2f9e9e190921637474ae81d278002f197f7211540088931ca8a941794e56067ef4a497fdc6fa713aa9f20c21f23c3a71ae4cc5aed459ca7c020bf55162fbcf56a066546660c5a009b8ad2aaae9651c97b1e145853a10013d1bf68e7df25dd492c328f823ed982da54557502ebc6cc56d4d0bf2881bf3c536ea53b4dcb0886e73b066969dfec343441b9372d7ff38454c4337d45e2b999415ec48f19cd05f0f80c5a61ec369610784f47a5cf3b2a13ff5d8145303ade7189a300936006846812dec9ff15500f8daf47236e724d72619af3a6cb3e854cb8284d5b8843dfe056beaa45c40a4541a98c7507feb27a605d6e07189c8c5554a492a03ce6701d3d2ec782e2c1c8346b54a963435bdda3a93bbac1d837172cebb9cd18903d25cd6bed404eaf18730a6d1c6da0783b5411770ed34f35fa6c11a4292a34565ff1b23d4200ec5a73e6b7905458088fac19f6aafd35e0e791f28bbb2cb0117ca1c3a9e3c4863e487ce5d8c14dd140e9eb4794d87d75b01f683bca84ebdbf19dafab716421bfac9e95755fd346a0cd31e8520a55c7ca652ff63fb4e20ba67fab41e11f7390bc02363162097802c6a9eb18b430d07ea60064d5b546d15bb68cada79c113848136e797577f1783e9b53574f9427be3a28230fdd69d139205dd6c7e9e7f031fb6eab70d69ce905384c5c77d084360aac590a89b2dbb2d339899b13619b455cf9f0cdc08db6c5b5f3223dc3a663ce42bcc8cc6f947f42cdf8dde15a6926b753177513a52be95b1f0b88d2a1ec90e49959b108fe204bbc29199d7382c42ad5dbaff970cbd2dbeade54bd70415e54daa805d396361f525f38efc2bba3fd818f9d7af0594dcc341c20f18c624fe13ce7e7108e1d2fd06c58b03f04642c95e3ba00d4035ea0476ac138f72378d85050bf60dedc90af38e96f67fdc38483a73e847b41d31b894ddcb234f02b0d507bbcb15a8941f9c23b592a291cbeacb3ed213f2f044aa842275a7717757467f121294bba6b357c969e96bfab455c6f328d9e5181d909c3f0543b17d9af7fcac099067b043be79aca8e5a75c3a6d4f6246357a63c516a3ca595447f34b43a055d3070517c67ec36e636aca9ed71a001d4f7b81149124deeb7826dec3697e183d861d544c9c17baff82849d599e9e77ed19f801aa1ce095940674576ff270ac788d00c429187e299a03c6f3a1646a8f7d6290287e70bd1276316ae624da929c67936191abdfba45e2803884e5a3136205a38a841448968a7900709dda033a42969bd3417a8d865d0dbee1f261f4556797dfebab278136a182a63e5ca9789e3f1371808efe06eb0cc5ccfe26c0538d573378035afa39fb7cdf3ad889b277c8c6e84954e74f3ff3140bf13bcb45c822784125d23b5eceb73e",
+ "088fc7ba068f80efd8d4d62813c93c1eba77e9ff400c7781314abc901873ce200295da09245bf8fd2fce254397616151d94b511957c89a881256182ac9e64acb7b25d4a080cc9daf9ac2f231235483fc9fd415f69caf7eaf0597",
+ "78d5f86b071bbf8a185e5e2d54faddd2a9e26983b1e7a74be0f0b979b9f4af31",
+ "d9ce7d249af9496e99c93b36",
+ "ad542824b49fc520f0b7ff8ce2bff8b3d47baacb4a1c95ed56a306483aac551fffba48e8a8f5e4cc536e9266182f6811d070fb9282f5c542cefb4993ccc7044b42cfd6fc71793dc8dd2de23c630f9ceaeddba45efed9d7fca25fcb07d193c000822478b19c2ee9fb31760cfe01475ba8a003db469d1130318a79345a29d054a9f9412dca1edf6d8f1498af5bb6fdbbd3d5f9a244ff176f62742c53779291ef6294df6540d841f4ee8c7c58fc8497ba74d9cf7947add5373427d81ae928305b93dd26cfc65e63b0ed0812ce759511bfbb10aca98f2abdbc9055c4e5ab82637f6a965bb74f592bdf11118b8eb79d50331e76cb4d10c6b4428cd4ec2ef4cb727bdba2b5375f5184d77772d0f9fd3a3c579a4a548b9c2dadc22c805ae959617af49a514b43f47af834313ed2e4d1fcec2c4b9ea87f328fa3d23129a36e6c54bcd08f7e30645de86e98ebb11bcaf99543503eb1e024bc9fd51fe6bd5e6d749033f2452cdf28b3d0f8a304111bdd26dbde641c02fcb15dc21b1a9baac5e86d35b4126ed1cc8a2c3c2a5b94c99fb9b2008daf1a0c090633bf9e31326428c75a50e821b1e72a6504c9d7bcfcaabecd929163d365832e8971f5efebff99ee3f5b95f957e8904d05b410936d8a81c60b4947f8605c58e5b727d491995c76fbe06e556c8ab5cc661a0c09ebc98d61010050f68b31fbe1f9de8f6481b2704204b0164d8433ba4dc1076908c782826e9b555e8d608463581099a466f92bfd6ac9796eacc0ab771a3f11d03806b0f33ec04c69cef6b87d58c11acb5d1374450ce61ba159456b915043c5c17cb03f0ba66d027105bb6fff41e6422f13e2a466f073358bf68149a3b577cfba7ea08b42f83fbc5a2aff17c5ee7dbdac3ff97389f5b8d1f3750e5c9be651209eeb9574127ea81bd7619da16d1cfab85754883543f6474c8c0cc9d5b80e34bf8262d2b4798f9917bcab4b880339397907a5bafe7d149247fd735523df3cbb17ae5e298846ad3bfb7d4f902aa549b7667d3ea945b002e7b209bc83842a7b120d6d27ce80631404371f31d1f61efc5423e1822032a1cbf4fa1a6b6fe79934a202d5add8c6e3595e49be3dd9553a569521c50e9653bc684ef2b73c3526ff7a0843fcac9cc9ecf46e63df5b9328a54c576bd299a366bbdc0f83a9de67b03f1da16244bd6d52e7e4b52c4ed693827735554b05b3a260cd01a41d7c944d0b7b58ae4b0eb052da34bc22b779d7ad46f90f3d4049c097e0adeaf71bbb30ed24b32ff5c7a65177db77492c2571e9cd99f15e613797e319ea7377038d53b28a4cd66a697e5e8f84cf16bd0f0430b34826114b4e1d1ebaaf2939dff7f9f4ce7c0861e51701c42d9cc9e871018b447ccaf4e402e3d63be164dcdf6799314a389ada8bf5e51a35148acf627e51481b9b0e4bec09c9e6d59229721b151fa9adf8323001fcf33afbc9a949643172f39b0d10ef57b37973683fdd9b9eb46e63054fd05ffbef889ff8fc8f251b0ab41fb00757ec1964ef373fceb8f6d148a7f7c89944b3cfc240d091601b23046188ba70a7cdf7b6f96eb93dcd3d24d4aebdc4a29a749bfe3cf5f6e1a025b62982ce188e6b57245d829c9fc1dcaaa5309a8b9557b8824a78eceef6e977721de4065b474ae008642b974001a5565ef5fe4250194e8b861cc45a8691c461817f10b646fb526bf0fe7790bb0db29d1356e8c7a197ec78df8310431d632a032b5490c2a458eb8d4327a9679d7e8ef8739797b0e820e2c567ce3562592e862a1dfcecd50bf77fcfcd00518db65ee0effb9eb3655d5d401a4a47808faa596d17b316f828cbbc14a7e018a0593da9320140a752f3824b5fcb66aa4c3cb94366ee8b821b09e7bea2c04ece15e8a7be1f58463b525e8cfcfc3fdd395ec5b0575094313557e632d0a65e3099e3c653111a5fb4f0eb2aa710229fc055a2bfd8a7147cbecc10823f1244fbb6894af1408ff9047d6483ef83573b5421b9798ee387dc38f166b11de6c33e9785e9b3d9d28bc24c37890e4f8f8ff24cca298b44d6fb1c6aad28cc634a67dd427205285521a172c2a4884ac5b038e261e38faf0086a02aa29195713cea335c47d03d67fa0dec7a8cb21db741519f5f0ba0143f14d71e33d82c75d6a19b3f7a42e6c16d762354daa2670ffa55bd400637de9cddf9e7964a03b4c8956f36bf54d89cf16de23e8c52957b52eb4572a11d1398be72bdb129e2c1abb58c65cc291bb7b0d2dc326c6125a441863a6c92de0f47a355222d58bf10af0d297a86a98b4e933a8f844fc7f1bbc8ba77919dfc50c41219e3db309b92ba056349faa758daf360b8ac05e43fc2069cd46e63fec399cd7764b111467fc65407ac06f5f84a3179930f6215ac5ec906146c19e0d3e162e77a2bca3582128284282b251cdcac03ecc204266ac3a9cfe8d8854008baf89c0ea0096a400d6a0d2f7c681c99462cf0105f7a3dde690ece0438fbb820b9c73c6cdf6208c336831101b904526cf8ac331d879d71615d8b1f750ac7f0ec692d97a5e21e17e194a98c10172b5c4bc1049a8743188ae7c4d70384a7e68c1353aab7882bb91aa383821046ed0ebabb4b2dd126ccb935f48646b299095cdb71ecd5cc402e4635a3f7a3c8a6f54f4076ba028dedb402bcc92f5668dec3d91dda7319f58382017e306237e42480ee2c1f5930564cf16fdf37a3434585336b8e4535bba87311cd47722b9da727250560624a5dde48a2090ee44592d2fc06edda634b600fad9f843c6b2eaa0697b42858afee8191dd2a31e5685bd104188e2ccb057dd0a8d4d1205d7c846f5b8ec0f06bff61c7f47ac4da30e1bc80a4e95af79b14a83e9af2e0f195cb92d14f752a5f12ff90a05765be453075d799694848fcddb07859336ec101c8052bdc273d4abc313cfb351b543fa340dcd01bf32fea59881ddb8f33c6023ccea70532814ce4a2d0c66c846347b86c29dfc34f6fa4db298911d4367c59939020a3d078194e6a3a3c5126c24ed182398468e77fd61a5b1271f5cb2a97868876954c3f7179d6a045f4bd770f681cd82216cd2b1ceeb4e724b3fddeb74481e662fbd7f5dd45bed6d4f89d21b8dd9c1009ad2b0b16954e97993ab8f3fdd9d61f8db102a945591b4552f419971a9e46a792dd8392c8d9502767c82d9b4f69e66071eb579859e9ca070cad5fe3b7fcb77b8474926ea991ce7ad201421f8a79c051b762a066027ab2b9595a1c97ad57f3149f5872ed4d8e99195d47bd3c03bbee590a50a99d8048e912aaeed797977b52f0240a6cf2c865b108456881adbfda60cf701454da17bae879cf098df808f34e50bccaada2d3edeb1aa73cfe3c512d814eb33897b6ff9d67d3d682517cc333c3c2552adc99860b1f0d1076390de9f84fcc9e802581f77e14f5254da01831c70cb8581630dadb44209377d90447a1a21cc8a2d6d897db62d8420afbcc6ed85ce42f3281255bd43e0afd3e86b27d3b957104ef54959282b0e1b381a26f16057246704c7888126055af5a1f494540f01897e8781e1a5c0193b7bef4b5588d0e9b9c8de74dcdb63f03f7b15cf48fbb71c7c3bbe9329e3d326988bad7d0cb85537c1e0b3cd88f37a3c7765f548f99e495ddc29daed8c7f15dadf2e5b79def91dbbea277c51a5da250e66c305604bcce4789ca2df9a10614d72824ba8e4f179f35ccae7119fd962cce13b282f0f970ca6c4776374c4bc438f0de98aa04fb3cf23d2c6800a4a666c15bd20c486e88e688ff9e5fce906b4ae96ec7c3388d7567ce6c8bc61f6d2373b93f9ddbb02b384084b3f28f54c9ddda232d3084daa5fac5ca356ac0059f2fd3fde5d6a9516d0954653b699aa986f70733538e19721daa41329abb95058450e602eb5726ad5a8b81aa474650659c6f7f6f53f8a6e635bf35f4b1191e0dbefad3be756c6141c7d55f007f4fd131e5d5eaa120ba31cc32b8d4c69d4fa784fe0af7dc272898789c774e7995cb252eb6c8e8053c9e7adb59c27f675952d161dba78bdfb15859fdfe4fe4a44c01efd394bf51d43c600aa9a527d9c490971e188e28b980e77a9c6ea0a4ef6bd38d11b47f5745ecdb",
+ },
+ {
+ "9cd1c25b5bdab9b9080db3e5e05dc749e0783087c310777d89307138613bdffe0ca259677c13208420d4690031314a11a97a986d8b0fea143f5b4da0972c9ea3cef80b4b0b2bcf2bff392c306a764113f0d9807be86a9027c6ddc85d096600d85e0b236937f295362bc1679537a8a9278229a36a9433925a105ab719c0b7f11fc31488fa071d3032de97c81540713dc29ae02c2e13be8823183f3cd9f72ef8ba4280b4499ee47c7c7c4492bcb5cf7e4fafaa7ec26906e58146215a3d4f52f792d3abdb718f57ed0b9b7fc7504e45a0fdf01ebf5924a4da6ac635a715879ea75a4983cbd9dab9e47638acc687f16684e184443aa9e81513ae4abbc4d1596b2ca3eef77cc9b0603fe90c0570fe6cf4dff0381a99212fadcf7968934ac1ff7664ed6ee0b61e41f5074dfb774b676c2b57a445f1c5749e95ed062837c727ae2c151c0ccb3a4dc1429bbcb9e62325117aca566b8fca0924b70f4defd7749d0389b90f55f35d1635f8d2efdef514f06fde46db6e11e492c8f4dfb7cb5454cedd0ddd32013a4836321a25110f3a017f18475a86583e192132f8d8fd4c2dcb2a3aa95c3be3a57216bf9727cfd1284eea6fa870c8e689e91982c116ceeee2f8298b55646efad684b96eab883fd3d629437e9a0b6523f47ea5b59474a4766ccd01c13170bb08f47576a0fdb573d4dfb65279c1b79cb535426bcab60f4022dc42e40db29f15a6148b461241bae62070389932f035e7257752ef2d6130503d72344b24d360cae8ec11fa2dcbe04d3b18e66d081b552e93a71dc0094d1046bf4491e318f2ae00debffa0b8ada58c5f23e33fb598829ec2f46ad3894bd7f530210371a02e51ae0a414eb2eee43f3e08126dbdbae04c7de4b7416df32953234a6694ea84e6889f27c74206ab8144a393a2614e92adcc77550dd54827387b619f004c13f6c4a31e8bf525277669db0a0c3c589eda15063f12eb774a13e2aba2f2f7b6e9bc69f8485f1d6fc5773acf83671812412d28704003e78a17da25bacd1d61a6d9cb9f121abc71d023bcafa713b7c954e4e1c524e5bcaefd86c4a843e209eabbd579cde0263fc059ec6ff10017ba54fc9c2a1171d6b06f5d85079167117c12e6e5d0c71c008765fce756fd0f1141fbad6c1d2f32cd8e80429611a9a78dbc8e738d458f9ddce58ab43c77b34db9befb25cc1a588998e8dc2efa75c6883244fbbf9a7b4d6750c81b8d3fdedaf98dc61f49d067c369409f984b155ec347a3bef73e2a44957b0ca0f84c7fc335fd89453759ad0ac2fd9a5b38afa9fbe74daaee7bc52301302fb2286c21fb922f74d756de84519171fbecaa9b869682d431614ff6845126a4034f10253aa244bf89ab8e0dfd1f7fe8fc1a8472a10746d26896c8ece7ef80eb2e910069435518ccf096caeda63ad692455b04e6525bb8bae27197ca5118a57fb9a5d8fcfae1b9eb7874d91eafafa0e4fab5cb4d0173f7e3e58fae369843a641e98f3ee460e8cfe95d98f7fd38a8d2235e9d6050015833e6d7d21d7015c3b1ff42f0d3a3d9a38d373c8524752e06987c9408cca550f08c38c2a9a8d86d5ac7a04bab44254ed15c7b5670e0747788e11b81adb0d29e3d0b50d6a429340ee0d44a8c286fcaf9bc46403d26b4a4af95b021336103c1ae0f1274b33bb8b21c8cfca8a56c639f18a9df45d083fa7019aaa14d1ba50eb9a4112e574cd70969640602096265a87b1f77c0e00bbb501555f1626196611b4a824991cf10ab2874a12a8e0390267eaf9e3f8f99eadfbf40d111a26772cda1f50743c417eeec9c80171a83a730f246cf31c6691c96185d672a0fde9ccd7091c4b455dc93326913497396e0a4992773caeddcd783e534eb0f34b99bf23a2db6ee738381b5fc94ff603be014c507888ff55557793a8c5439b11dc5a347f35a2666eda81cda4d1c3a78fc4f3df3c7bde91d05524791b67142c446f60c3a4022912ddabdf817ca3280b671beaa496c935661e5adf39c1f4650563c5c807c8f21aa59df926199c4e2404690ea8ffd7dd65f637452ff93995fe9c5ac7a322b9bdc756b7ed6f533b9357a4a1ffa379dd096f144e9e0d87330c238ed3c6b08c8478e23b65518ea1e4e64585e5e9fec2f26dd7400ce4c73ff0eacdc3b07e4f34f6316f5b82fefc66e442ecc92bea8c1d58635d644724a3380e71fbbeef4bf3e57c6240ff603d65447f510eaa3c9ac794fd24f844489b7c560c7814fbc307e03f6a213eca5ea40fddf51d8731b74ec5b472bdf8ba59751065ed2461b02c41ef96622e60c0d26f9dc78c24f94372bef7e47cf09ed565ae3a52d39b02ffddf1953f1ff500f1659db9f1c2b23534702c19ec1cb7c18166fcd33997d53874c7cdb4e6c2b4d82751911913434e48b37a61a0971861187e5decb7f5c1ef6988bc1d6f7fd147a623d8bf361b0d7ece88df6e1ff8d037762d232e22e51d8c6ddaa9dc597b23ff9efbbfd416cc53e5543253732a23aba151cecf73b3ecff21c6a9fd1f24211fc21cde9633aae918ff1c6b72468f1de7e0ecb6539fa353c069fcbe8920dfa8e2fb86782e3062462f7eb2a2c441bfac21ab62744b05c70b6fc3c9f8e3a8a0c5a4263ed256a019861ecb28e20ce78e2d93f1a1def669e9652cb35d105bfdd5ff2313d27ab3eb00d1b628b4c20f42efa23390802af96a8f261ded3678ea0b780e1f4a88d23588a4ebb058adbf9a9c62ce2ce2f8264c874c697482e25f8d5a6daca4f57fd97d23c42d7b71ec150d4ee33931db5f7d63abe7d72dc936bb23a367c798e6a01509644284d52f9ae27d7d1bae597b2cbc26139354dcca0fff6d76c6065d661b66ca5eeb9f8d85810a029cb95b17e5173ef8ab92d475a1d3e21799e874ff04dbc962c668ef4be9f94d85b2a99d97c0db8f6b6d63e00e36c325cfab9aceaf7597113bff0086e8fad36eac7c0b443de6d3a8533789616d4c863df7200ba795a3b8d0a2b9568bb32af95fa604a3e3ea778c3dae159e1b612458584564ffda07b8aba9710134242b2d83d23127b51b9e41584c56f667b71bc01060240f3a2bc7e5d438e7095c1236e0e468079a83a5dbdcf132d258e9ed18f94d3c098867d06d3c09544565677b454be34ce567f1c143e2f3153bdc0353d65090dfd8f7af4633b89a781e01f4634dd7b0323ea1f38184e697bfc39a1299eaa278c39a2709cde0a346fea53a61f211112450b318d137fe68f6c102085aedabd2b045fab912da5c58d8019239f3a44b18f4fe30c5352e2e2bf030334a1dde1dcd23178636f1e38ec9e42102d8c54df0b94b207e804eacab3edddf89fabda6c8e1bd4e17ae31a57716c679ee8bc7de4412fec3934c6f3e8b4c1d1447dbba0fbc775dd3258f789ca53f1593cadc710fef6fd282bb41c0468ede5ad5b914e4758b4148b0d0c04c75ff6208ca3e79d92de8abafa4ec70ea7a4e454f0759337ce575c4954584e2bb8444c34e823d27b025d25fc9becfb4391df9882452bca0373164cd76e9af316df3f5bb7532e22557b485217254d5ab72ce349620f03758219b259784d4c9f1c7beac3cf08e624742e768b53b3d60ad0b94442c847b84a516a93d9b7d068c44c43980b4c7e2fb0ac964bf05a11fb2adb4f6d938715dde88061b238321afc7e5e84799b02a94baf3f879f89a98ab474ca12085137d639b837ebe069f6dcd8456141d063eb1c032aa392a44d1d58b1e77aba38a280625ab84e3b123507ea7a692c4acd1756c031fa52d637703ee957a993804c13e296cc20c1de55c9b8c032e50afffc51c02e5c12f48383237cdacd005b09243d9fe05e51cea42b77645e5c6f4e48c10e671d216b90a48f0d8f5c1dda553217f5126646d11a62587eb0a4ee0efdaf0d54bc2eb04cd34f5a529b682ce09a34d5acab2c8db58ed6244f7b024e68a14bcd5d7a7daa4dbcf490485cbd38e6f20e839d2b0142b9d766f9527937bb1a737877edf6122ba306bbfb5379243a6b22bdf85dcf3b079691f0e90b28a4259c1c9d8a02afa5b5a661a0f9dac52435e7d22e3591593d37eb2e10f646b51be2d1a96cd4490289ef642ad93eeffd64d7cf830d60dc4a98c768a9bdbf6ec9923062ff04abf19e8b65b95494a9420971018c7e6268b8fb2021a4ddd103976333fa52389643c711a980664e29a8479aa9c4091c2cc2074ce3ac1ab4afa217d39c6a1",
+ "c22add33457539a957d32dd07ec9110f8cdd2f00ab6ac256b4bc7732f63dd3b867b0ecac262555",
+ "e71f9a3dd457b4064df1d9055889f105af175a2d10dd7b8729da0d0116c2d9fd",
+ "7df9824e774c5f86d83cb5d8",
+ "689683c9e7aa9c48b9fda0cfffea0458ea0c3dedccd21efeb06126f1194780917c9f4f2f44b1daceec3f6b1f75506f4169bdacf12c1f65958784851056fe0b4b42a22aeb043ab35ca73747346ac58c550324c4b849a404c94b8860967b6fc58aff25dad0556f1952c045b91f56ec8eebf6f552c18b2a0641c037e6c6538b289601e1fd5a7bbe7b6e0b224124fec341bf77615183abafb52b3e30082a0abfc2cf224324338c132426011d9f800b382e6b834896ea48a8247f149d92ded7e69c7800096076cd2a729a1fe41c70dafb1f855ffa2ffc27b93e2f5f6827ade7118af60730033675d84de9cde6c260d3d615a945dfe0ed25f33b6cbd2c0e204ee919219d85c7536f4700f06fa61937f8dbbe9bda88db1f4ba8a8d195cd385eec62edd9ce673880800be9aa4430e5c10a5908f6dd349af70f32b32d8db38a7d73821af47b993b622bf168565082d07e88fc48231a440469adeca59263302438ece96d89de11cf8057454d1bfe8e4e36965a4d82618834a0847af39dd8776866d9558a5cff79a1cc9d1e3c22e050677e54ead68b3cf0094daa01330d41bb66708a8bbb8a196fae5c77dc6774629d38905e81d97c5b16d755182f687a8046e55d148419cf9c12139fee50c0533b0f04a805723ce1ea5595fca5b668e58f6b3b396f438308372489b640317cfa3a79392cf6d1afdd8c3359557a83790021a4eb418fa189ad15ba9be0f74182ac76076f102ec171117a3d16ca20b4d200e03e54f1f0ee6308e463a148c0c85aac3ccbe5781cf45b53a313f7c9975a45d1853ed9104a860c08634a8211b87500b5ffa3d8d9d56f22256d485b9b45b24d3873159adb8ae25966cc40f164f342519e88d1ead1e711e1b2bbd4be64c7e83f056f797c2d3a5cf7c5025f92be5637fa7738a1bbba55f761dcd1451ce4b1e85a6628b629a2f7917a86363b01516472c0f8614abe2ad1c9d5501b2a44a68e3eeeb34a64541125bf49138bcd15b7c82dfd40708414b85107d8b982c4f99783a03c707a37787a91a7198063f0e8a2d52dca61755105faaa09c063c7a0849570cba1aa7ddb3600eeba602c7e7c9b90ed00ec731d4d1d8e4bb42f9e9db21616c4aca48dc27b939428834404331288f03c2b5e887103c51748d0257519c3988f6492eb70cabbc2dd8a8a910d737a678d0970ec48bef3b81673bd10b687b37e11d49e7cf90c03c54826ecd833bfd9dbb8174274dd45b139d08371d5d248ee33298193194734c5863adf4bca92bc282bae2f47da5201fc240dd0710a22a8d922faf92c2071a7eede7ee17232d3b6ee5f3ebb1a8b230600b243c860968ab427a5f540912e5e7bfa0271201f288727f2bd5173539d5318e5c1c0a71cba4d9501b91c3bffa7bb61b3713f1751efe94a66e17d2b42da51d13c3df40f4db988dace42a6a1b9d138c4f590b7227990711afbf8f56fa63f2800cc019bbd4a7b3a0983c9b9e5f77562dcad6de96e3b2eb85cd99d28a021a10d6734400a91369236b48ed68528afc68f247d45c79318fc5d634ecb0f3ef8536d8ec2e877adc3308be906c5b96777d0e05970023e5c5dffed12310cc97249e4b95e32451c9acca8394fde699deda57e938bed7167e62e2cb62357f82fbe821ee73b4e09c6e2f512515412c2f27805762a8493e74a3d30bb409e499002a97354381318af28311ce484bdf7c39db53f08f73ca5793945e13fc8c66d503fa95506b37ce134ce2945d75b424ca6367ef4ed47b9cb8ba7de80e773279bf23ac888eb105385ea958b1b49b27c8db6b1e14a5c8ed5d28808a7d0b6bff1a58f24f9c57fd8b8f477a9d1365f89c698b8ba923896181299d474b93e05d3c915b10a69e61910761a6d8644933c593661b0828afeca590ca18e702322d9140d98fcf836c2f7a4f72b59eb529823a52ab05d919c3eee4db2cae1067213c5070450a160fd52fa44bc9bacc5c136701cd7adb1faf484da376477da08f6a4dcaa37af47c7b026c2da9d5fd0b30741357104cb2bc0d3cebd132b5fc7c873ebeceec5492aecab95ab393f35b93b923d2ca071e6bd8522c3ad8598a05e96646504f1620c045aa5734d665acbdda0ef73612be4ca4d95ba069041e042497f7b10445869989ce30f55206a1feb4e64890b7d1f7e9df2e88a352674a52ae4267c06592d425ed1d88101cf94588135892218ac11f3976ab2b47a27f02eb887696c94b13d48b4370eb11222274b5513a0fef905c66d0c1893832ffdb9b333178b65338fd8b81094d8f86f2e4e96a47e72032cd6fd47af87eec295c6e980f595b57f79abeb4654c4039fa03ade732b1e579551898b801ecd6e0fb1c5fd198335834b51673d074a8222640d2a969998f5b878bf897fdcf3426c4e24a7c599e5567643fa79ea5d20e7de581a873ee0181e3632a4e304f9dae09a81f882d4061ec17e588793b160c93a926874d5a8b78727f88de9bc125589a9562db5bb1c01012bbea1b2eeab68877871ce83455db43cc48455effbc71c436aebe362af22c6a319d134f65681c4d0d51f9aa42fb20f48ae3f7065664aeff5d8349624a5d79eb0bef3cbb2a1244ee445f560a6bf7a796b2c950a37dfb85ed5be11e8e305e835c9e077e676aa5ce23edb1f74806278548e3fa35059abc2f032289f9bd76043c8dd1352b6131cf34f66bcd0e7f1d13081f5b08ed0c69136f3b7ad8e05e9fe99a9b73624095f96740c1f40074e5d92ffeccdc0f15502082fdfcfc97a800be511c22b875f2832b2b891cb1aad2a17c7bd0be4427a4549404172f7c14d5e425e14498237c26a7813cd8612d048703cb180f1a6194f688b4644304950b078692faec7a2a5c5bbc482f3a7e8ef2825c4c19032a7a79a2908ca9774c6403e6b15625c485f2dd078902aff769dfee2dca9373704bf63ad981b51f61253910fd48c49ef10e3938f35ca8dd491a8e569baef675df30367b093f1088ebe8f876191dc32055481d074e5e47a4bd728efaea9fee3e83d8556255ffb2fa08194bdc66897d97d1557186d5f873169461494a83368ed8065b9a033fa4c2f07f7c60f945b60479e3c89233d58f674c0c6fa5918150bae0c6de2b65a09ccd490e2ad8571745bc37e70982411af667f3e8e9b9f7f75d863e5fef05c1f0d2acc7c86585a83ee32e0a64a9e67e75b80def5bfeb7cffe6e6822efa7a9cf049689b58336b081c039696e0fd3b2a2a6b0d177c9b3f8fe5cbb1c69ea93c1235b2c5b6934f603127eeafc4ed0728161612acdb2ba894a5ac376c4ef1fa8d49b4722379e5cb39752837395c413dd29a2a88c03849b6fb2221fd85ba6d5a50ba7ee9c09ecc5e6dc66afdaa1b021282cadc68f19529eadab809341187d57cfdfe01d0798ab8a94277b9b868612e575bd98f70de80ebe5f57637c511800373262eb5ac3836b03808ca5d5f732f286a5f18a7b7fb8cd8f60e4debe54731c9c524b84694c5469975443964ed28ccff2f4e8e0cf4c60c1c8a092e986cf12fa90a994e4f26ac89fabe8a0d1e27fdc00f1d3d3fdb73bb76809f93ea113e336cb0a5438147e454e262fbb7d656aa1be1288839bc342b48ba7d0e72c85a2e24be1a97dfb2db85b5d850481e62f3b11a28c6407686e73d550b9f1d0f010602e82af26813d2484a8db2da0814782c8404b2865abfbe3c98a07ffb37eea6de7992cad73a9b81ae96a9acb13ba213eb4111d868cc73b0432d2b6c2d7e0e0ca7ccbdce86d01576e1136871a07c76498eae53fb7ebf2e85fb8561d10dfba740400ef4495ece7eb33ce3bce26344eddd88cf1ed8028ec5fe8e71edda54dbdae08f50f8df6295f6d7ef1163f62262a200456a7777d0565d7f5832fcc7ac144b5c3e0ce3e5c9b7f880a54ed5e80662e96b356ff58f2e372b1dc0d73cb8b96c72caa9e5dd312841a8be23f838bc706d893e1a8a48b2c069874c293c41d00226f73f987aec8686046ac4c0c972c991c38b98cabce30e7255dbf16039b95dc7d103fde630b03441b15bd2c214763fece9d6778d1c6354d2c9478c226175c02cb006006715fffc879a6a2b4111f6234ee330d6c84d453c9ffac08efda1f380110a8ef8c2fe44e2ed644cc3e0146b4d02f76586fbb6d69b827be38b9add444e2bac4d7165007cdbf2ea8c4b967fc1bb70c68b229f19bc3f79cb13ee6265264885f04c09a96583f331ed46de3e5dcaf08313ba6053f3d0c1916a0f",
+ },
+ {
+ "3ab6cbeebc18df951d371e0f3cce2697fb367476bd9d50ca9e668c77636eeb9d24b68be0ce6a75eca194fbde6221755d57e9d3148623de24896a9becd98789fd3d14de0c7e53f81fe7f3fd491472a66b5b797fe19c5d0525c7a111a0289a9e65ae7c712ccf694cb75c490070bca7db17205af9bdb7fee27f9ff41fc78ebd2d3d399e690908b5c064ffc0d5bb67b0d2880bcb45c2ca2741691b6131aa1e5ee758fc50610406216905e13ec049ee92d1f95e16bc283dfd91595ec2037d20ead51d3a362140578a4538c80581b79852b0f6686c1ea66aafffc872024592ec1aaf2650d167a75bace024b261db4ab48b401cf85ec2620dc12a7fc37012af8ac1d6db923d82eee962129bc4ede578782594708357d29118fd10dc6d228bf7e461d2769e556488b776237b6309f3dc2e884cb2df1f43f71c53d389765f805ac053d05fa835e75fab0adb0f13ceeb425637f43556372d728a00fb005f7c5a20cf2b7f776066d60b70b11a848005c6d63dba0c93f139067b39017c997dd6b94c0138c3619e9a6d0e4b8792cb8d58a2ca12ae5d03e7637f2065fbb9e2d1722fd3aaf234488ca157d829e9a3b642458054f3dd58da41d7fba6d2b488a327b776d1aaab1a364c710e755ab22b9cf7abf1eb8949c5ca20c070f275f8959cb00c6d5ab7879003f89f795351a4ef4850e033d929f9a349b9133b2e0bd1cabbdd381594bfa697b845100b96b5fade05db12de040b814ec49489f39f5abd5b37f570cbb516636d5b7378f12872d02d4de20b52ed8ca0b12029a4c084621bbb578b870ca2ea79fd5df1ef8664bfb3b1a1bf038e4ba33f6ccde42c5146470c9dd293aa747d2372db1561617920142ac1d32e4f1fd18e8b9e72b7efb8fefc56d08f00450d23b7e8381849b1385ddcf9310a4850dbd6db7a4992690190655760f557a5027b5ceab3743365ac9041a5c14bed1126c4eca00d7e0a0e0e6f666f64bd1466387150ece5835192149237d5dd25e703e9d3a4f652ae04601d6acf8228e4e86055394c3abc9dccd02f04a60c298d101260b408b2620c137f77e2019fc6eaff1b234c56dfe922b0192656254fe3356143e969f64b7609cbedebcc8cb2b68bcdd9d723b9c14669da6cbfffbca2351de51e87db6afde435ead0017682b8014f91d9734a9ab9b374257273e114a8fffac786d53183ba666d8a67e30c1fe45bb1bdcefb5787afcbad213f8e36e78d30ae1305df96bf450349ade655cccbb17d887f79e00728abb449ea427fd2d0af80e3b5607a74a57dbe5264131f2fc49cb74415974b3d43ff872d4106ff11b680f56be06fdf85ec9dd850b1f77f759337b9a9ce04e611036d3f45743e562abe4b959eba7424a712fcf7c3f3773886aef22f7cf6168efa83cd3ff70b9521cae1b6689b2b8c423d883a007bb138025f2a31db2147691bcb365ac242efe40cd09a746cc501ae0289e80205993b07f86538d486803da14b74fb0db6ebf1c2bb8c36275137d654c1be56c65891cd50f705247d85621fd0d61ade8c05cf4ec15b84e8adbcbe017d7d5743d5e91025e0154a5d9bac7c6b8297490e9c195c5d74e046219c042219817a5c56636c7c4382c6a01d721d88f4b4d20250eb5eae5f3ef481dbf8a3f47a1d51d080bd4cc33f12645c8481e57835b77a85a2d83301172782f22026e69a43376ac4f5b78734c9eb914e6c76c6a12d4127cf195ad030825322a279093cbc40a680355d086a27f3fb7560713b019e7c286d96833dc60590e9a709f2e3c632894668e74ed20e42cd83a23ebea3dc3bcc49d14f8697541780fb2072dee6a5672d0d4e7bdf5cbdacdf5fea9e03c6d9cf0faa1e954172acc26dcd344bb3d9b2e0e6015cc55d19713d795bdb7c21b44b305e69c69fdb7261483f9693f36f45d356462f1ba4498de1c2e8bc3e0a70893acef2006dcd73cf15b265a8a5d4ed792a34a846d8f1d3b9b3bb75f1c5e57a00b36c00203973ef4e2654f6cb29e4445318ed99f0de6ca992281e83ed03feedb66aeed6a461c6f2871ae95343cd9797e58430d5639d7ef5c59c78b29f76a055e18e2b85eff177770c60ca4f2d61e612e617e749b4653e7901b62ba02dcbf50e59219349120ac01e6b8a6e98eb54abd16b921a1ff85898f90fc49a3c8f8f4ae9b0dd32c3e7f2e1527c4feb67a496390f28532f20acc71abb8bb4f71b434104f41e36b705289858a4e8430b8cd9449b0198ca2244923cff1df0f63833373c275572de5a9a77b23e5ff54aebce8e86d02651f26ae32e69001e5f3951967579ebe8574682cef8c12dee0b18bc999f8cc0f07e2ad3ac94d3caf30c1c8a8295756aecbbecbbb4ade8a2b8015e52a0eb1290693c6316d036e0c443fc4ec591c32f7e7f1b3933c921d5812233d3c21ee5528822b59ef2ec7eb62f7b04f40cc8238a473ec37a07e54f8907825ccaa1421c2964d2c756be450dedc011e1cdd9045720421b9a4a00e9d3076c2fd10d71ee36d5c0fd2c7e42396b034a4cd0245027449242dfdc42c8af4a34df1b4150097726c9745247b78bb2bad5fe8af94eb13ee1f41dbd36e56d801a4c9c5b9ca5d3c26f4714b6fe9f69b87567426eb6f4ac97e8c9541eafc19fc90d3b24aae0f76c4f3f81063d206ff695d638048c2cb023147a78332939d2f2470d16f1ed0e5d3d4dde438affb2809488b99815e54938fac3b02deceaffde310cf422f9027f364f5e79da5d2b5af1b4138ac9f9d301f396b220829c1f60cd2b54ef24576e5ba6ccd4802900db1bb4eea57de7787eda0e30fa90cc19f099444488699bf7c442c398c2ed989d084c8cadc97325484e337848c34562b3dea6f7670f935ed3d5216c970e04351651c1c31a34e862821bdbcbde202d91fed38965e31cc3b6f1e52288f327bd0a787ecd92b3b6f535d1d000b0f02d41ee01ca54e4e6179ad7fcbd60f0e41dfa5c9cc7ee4f7de3844fb385ffa3b24092b30be697f1fd32c9faef29ead346e42fe2ab1d312901b678b43b7758edb7eaa1c2d038b4cd6a7dc759a6b12cec955bcf4179006a7ab6e22ef15986df107080d340b8870e2304d57caa87a9961c04655d7d66c7f71ca9260e02aced131d6de65d256d6b487141c51bc86eb1e4721742f07d09e799b30da7b5ba94c8d701ae34271ba06f8ce134a7a9a2598d1570cf05edd9ec868cfa2e41b4c20a8bc4b8bfebd45f5a60408f08e931617746d1464bbe1f3844ab3272ede635f771f9af30e483903ee4d0cdecbaff4d31451e7791dc97c92042fb932fe1c82652c1d682a55912e33de3b1299db076cef594458670dc4f911f4a244e2bec757dad4b0052a41235e2f5e60b929682608c16a61287826218a1ac3cf0d8286555d5b0552754685c365d4342f0d9c45065daf6786179da791a86b50a5edd6fb4b21f09d9747136aacf79ecbf52b00fb88b0630ec7f0a6699901ba4eff913a3ab33ac85a71ebb51ed343eac86eebb3e79c16e664078ccda09e77ef8e0919b8cc447116b65ccbd5200fbfe86e9bac5637b33c9bcac9596b57c14ad5da548e96a8ffad5f5c69247c68d464c770011da7b45a337f138cda6b4e15311879bfaf12af4c61fba596780e6adcd5dadde372823da6014122dbac70f0dd896a8d387d3c74df282a659028d06cfeab3ae22dcd1fc3ce60f69a0d678aeae0e5681952949e31ccb8975cd167c9d012f4b230b1c1f47022eb1a3042951b338a734cdd17db0ed483a621650deb3510efe74191a94611dc212c0c73b117a73b8ae41892cf176742bd98a7cb73dcdc53b42df56d640739852335f8d44d901fc884286b433fc285fd5b3db8df0a8522cea3182c071f559c328b8516c9252681a94eecec7ebf626c0a9014d9aaaa0c694d14855433dae06656657d1f8a939123d28e00513d72bd3802d211ad7c1e06b9228c0d5656edccad5339bcdddd5e01afdc01f10974be3187804324fc513ba583b7b2da1e9096bbe3d078c1adc6c34d92c54e9c49fccdc17d10e66962120ee5d9b1cfe852569436270cf7c4c3bb12568050e2ca4db08bbac16214238413195dd4d936272fca5d56d7551b9b002df1807ed44abc84c66746387b79bc9e830a635c308a7bfad7c2c22cee6d3d0c5ebd8b230837b7ceaefdf71a67a3a8eaae0c36de86b2d96e759b8b53f8b8604775eb7a7e13223cb21033dc87d775628581a954085c2d66c1c8f225b1aa86091061738e7495cb36a5ff032dc678904bfa39a00285cd6947865b6d4805e3411644b4a4c94a6fffe05ef31e156bae6165d801685dcec195552d029d22e5de393a82ddf3cd3de3ad8cd6bba2325a03982204f07fc3c21518ef17a601fd743b27f7191bb446ff61d3c61d7608777990997e911932532e5b3235f13423756f5b6c786720cf6682932c90092",
+ "50772c5a0e156ba13a9d86edc0e600021d56f7d31e7e452a74ad53a6775339c7ca6521d87a8c79b42900a1e9e6a1ec03f7e3d615611c3fd5c9927c40e5b508af1a298794b60148df01e9c9e78ab5ea8198c097fadcd6cfa6694be64e00eefe1a1885aece86f6ad87df766e692b58ebc41982bef5",
+ "93a2561a9904a1787a10e2a668cd6a814f2877a7b512698e94796805875c8d1a",
+ "588d9bc1d98210d9700ef488",
+ "165d8c9eabcd5e93e6eff7be122c8c242e1a7f284790c93324f924efabcec4a4ce48262011b7360c2833143d645ff295453853c92f0c48c6dfc2af7ec58d9bec0d13239c7e5593cdb39d49376c6341263df80c0ed2ed79fe9899d0c07de93f6ea95a5dfd307e49bdb5672b158a4df623ee86d54cd1a0fa9a60ce39d1f5f4b6b0ce9daf2a61a907cff3bdd3f29156ac439638e0910d728843ae17ea7368814ad7734732e7c023d4954e1cd5fd19fc9b76e9bb84b61dd4371478917757b14b366b4bfab4eab0d9de746088ad43d8742e2b9e58faff15c2eff084df5f4316111d5dd7d23cc0b1ee1000253f26cd260aa636f03f64a8342e531ca1515b3beecc3ee07a29184988325322d5c09754c278231f92c0d980adc919d4fccf4a1da1d37f1ddb58ca997d6d700946199fa007c43853b6caf5f8049233584087fb23c3952414ac487e452f0c3898486d04e5b008b843122501f9c8a294da9159a04119ad5c8e9f5c211411e34559d3a7bcf2ac10e0174f94f3f2968c80ebdf4498de172884dbdad0acc3a887f9bfe896a6004d54cc424567d53f1198ba33c56aa460edc6af0e437b34322c1144854bafb2434f00703c1992dbad0ceaa0616aec60a380676ca11558cece57a936959d6c2ffe0647eeffd37524fbafa9691f31499701b202d9dc9980e79ea517089eced779aa45b522c9ad193e63ea8b64e8a942f630d44370f23b7e9acfedac51dd9f139f8806b09a8fbbabc76fec3c3721fad5087a6d41f93973af8d787d8bc74a3122d99ea14e2f30a3c90be4b695c8b269784eefafa52d6a79e785eb47a23d72f037ca572b7029d2f37baabce57658119fb02c5b659e3aadfe0052f1cc3c0afc6fe4624533d9700388713945c20c1d175da53738fc73f48fe57fef8305e796b474b6f8d3fc5040042373a13384237d95bb045ce0c20934a964a8372acedfd6e559aa84180a86311a3996cc17bf7f73e5d85d4db2529989e5836edad490aaa5f56d17326825aa20608fd209903335de4b36b79f68b6a52194f6ea8ce42570533df650e65b50c367f69b9f08c32b3ce3e75318106b8b2c6b6d09369c781fbf2aaa35053af215b621f833814ec4778ac683de0dc22c418b077a917a6e405ccbde9f72ed523aa696be1a6f247b096b9235217bcf19b88d43178cce5a7d82335fccb4c079e00280bfd272b9f16ffefa7fea38d09dfb2e4874553b135052595812aed3fa15096abf1eebf9abd598289e0d156974de4c2654c60825d42b662ca7439816d9d3a0255f40a4965504f643f029da535d4b109e8658ec570e99859382ca0ede0b0495d508c63c7f1eff3f648c60e9b773590cc663a751178ba7603a11985ff519056661b9460c1aabc30e83bb0073a927682a06d1b8050c345f7920c1a37546d79587fae2a92c803a986248f90547f0b6c0ad0552d8260d2a0dc3cc76d092ab76b8c12f05dcf141167a6ea300bc23227933396ef6fe9d51a1ba5a754485950f06cfa6964db2d0fd1d4393cc36f0592fca25ac1a6aacda2a32f548ed20287e3d291661848a62d41504e4fcb1cd1785617fa5786712b3005f1a1041733df6cf838ea3ea0b93685889bc6b2857d80a9bc0e7a66f7fb3d805770402f049889311fc112dccc72a25bd127777fd87bf5ab56d39bfe6be2b45a8301c2f324dcc50b27540200d522c24941701f7293b8877ac84cf35638507c7d912a3a94e4384b68c507412df65d0c4ca8ec2da704bd4483eb2e0d13b68c0c2b68c106a55b9710ad0a1436d655a3cf3c419d5e6f027ddf5dcfc896a5b316a7dae9290a7bf81aed539a647c8c98e24e7ed6a4f7f00a11134ca715e5826625c250500f8f16b40de048b095b5dd08268407f58a91c86c36ca5a2bf4f8fc682adf1bf601da24414c74956e1a8fd2888b5260e980c32f6678a4dc4ff73220c22593d23144b84c2ff56920342248876d15ea54fc100c09a81b802dd15f030bda9aa08727ea49e34f0ca8693e0a06d0af06ea7ceddbf0584adfdebeb20510bbac683451d9f84cf0f4e85c34d979e550e07e7f414d6f1011cb3dc28d0df6d4aac113f2d5b04e4486ee2cdcd4157dafcbbd55e8330a7176d1b231d9f47a63da9ee30fec6cc2c5aba3a8c6154f79997af89d972743255355647235ee939f4f305ec655271e0cd562ff6f401b86dd5826c769298445108ad0d9e13c504551f74c507436911331db60ef0ea99dc259b13cfcb0596fa9b3c95cd7fc3b1611e3b012b6719afbcee7548939676dffc372276aecd08e6a14251407cf995266545427d49ae5ab245cd5d534c52542fc71b3973f0b766f3d234c8baaec8b74eaa8ba90abe160b4504769d02e08d7af4e7ecc167780c619cefa58865169b674b2b1e10d82f6560ba0be41a781f4afa46bd722566d941a8e6f87e4a5c03d89685a22a3470354f2922e2915f9d46288a5e8896ed13617dce694a595e379f25fe621dde8ba73d865976950954e5bd07db147a0fb74f87cb06aba49b073942b82fab33a878651df73df2721ef800b658bdc6c359d396f684598e93f38e79639b8736b02dfcc124fb9fc199c35f2fa1d0dc39939c57286e58a7deed7b6c76e02b99a14d9bbf11f65d8eb7fa096fe4baf0f78cb34736499a0ca550f10d7edc8909dc34b039e3abdf1aa67a51d37a2eaf4c07022897d4d8355d3325bcf392d91d02d462488ead90b366e9645b956c3802e4249d34b5b2b2484a1dec15a9477821df6bef5e1626ec5ee9832fc3bd0b63a3c4100d32fac3e9085f0b5ba43123f54beaa7ccbe6ba68231649f35a28acfcbbf97dea2d6cfd96025032b3950ec8437108d0f07baf1bc89e3afbc2cdbb5031d3cd9e20b19018adda466382059229e4c8c54b455eda4280bde43b36afa96e146e408c7104523d5f565d22ef86d4c7cbf9c6e0d0b30e37b37feb9332939c642eacfe19d0dae1259d3267635051ea5f9b518dd74786e45fb8bdf72cbe3753bd50bea2a961b49cc0e2d589e77fd25ebd962463fc728b1d288c38a79a182b124d345872afbcfe792d259e7e5334311244edc75d05f9a12eadb61fd3ff79fe8c097eb01a4ac1f0c339d3be74be3d96b0b6a15e8868d043a0f2007ee8aa51756d78b7a78ad90fd9a26afbcb51fdc20ed7a3947f715c833e363bb87504d8efc9f8b93a993e2e26430f79f3cce203b09093c9b456b1967212eb0db4f7688d4dccd4a523866f75c9d9e7ce07825ae34399c5607a60b771866a647b6d5e1e20795ca906e451f367d8c40ffe79a2cecfe7aa47a402f8d49be9084661c96ebb11f1b48e7e8abd2978ee626f962e98f99db4eb3c6a52aa2bb2e62194120ce1e773b9db784e8c9b5adcfb70e3bd5717293eebf014e9872c5c1bdf3fb296cb88eab5e97a5ac320092033b49f37d840dac23021c19ab2a89190f3c8dde927f6e6b41874bf71ba7747a616682bd5b3f17a1dad40f4993a1b186ce4f44afb4e36af7715450bac62cb1527eb8db1d87bbc4d9c99415d16660e48efd911e02f5777a77e72733af3c3f5315dd0c785d5212b79c46c3bccd74582c57cfac0d50fc0c85370476913f9d8e8e10d0f6602f2271994972de49ab1a91728713c3cfcedb0e61c270b5fb331a980965bcfe10b41251a0f7915d5943f49fb139626f1c424524f2fba3a407e77dd7513669894fd09fff4185fbb997b4e4677f6ea0b52892f013f1691bdb38eee9307a565e396bab484d91cea9268f49aed29e319b0add900b6a75f7461db5486aaf5366f98df05674361308931de753c70777de73337a996f6d4b0e06d63a69849ba7533bb0e446f062edbd6250e61a49f4120f84efc1cf74c1bd30cc61a2d719fa76991dab119fc814a7c56f48bd584c7935679c53bb0ac78905b5d961fcd89a4b567d17a5182651cb07146aa9a94972ce613e8ff9c878a8433c0244052f09980a52d800e97ba65e8ac186862def58c72b9feec91266e26aa5075b3337c7bb8716b3acafe666ffe2df32b78f9995661d3ba28f8a8780436aae1da2a3e6a0a16dc562b8d5df6f68391aab73a10508e0f55208f974a0505f0fc0d8a55049a7b631fc94fab91459ae1f199527362695b41972e50faee34c5cca9e35e8682099f5e9652f88cfe9fa990ff2154c89c1c2a4ed6bb8a889fecfdf048ee0aae7798c55d6cdfd062cbca97ca289578c832d658ceaf26faba54c9c3ee9eb5bac80698c1441b9cba287f749a5e30d5cc715a01c89353ceab0974ae77fecc1d2dfb31a5101783cbc002c73cd155dfd14685c2f9acc170dc437c649b6b4720b676848a7f9b56cc4787eabe72f6e3f2aed776f9bb1432fba93a63bfa44fbcfcb6eaa9ef4b79b32bdbd68cddbb9897cf5a02c6f99fc765790092edf0d5bca7c55cf232a03fbb6f3eae09b12e09a9b49a538e0589394700d16ebd3",
+ },
+ {
+ "3497e8d61062e6f2084ebf72d00e9a47b550591edeee9746f31ea28039a1646d384c4348af293ab778f92a4807c48fbd14e8dbf3d67339c991dc4aca7dae38b5fb7bfeaaa538611d328b653950f4f664dcd257b345917cd66dc6a1ea75d99f70549d1af9d67b1608077b41576f38bb4c0a13ff4fa47b251142c6fbb79f9a27f43841ed0ebc0416c37f571aef8fd63b99e93ae88db50e9ef7d499ae7433d5686b165579d3598f96d9e7b1c876870310703df8fdf2069beadb34984f676eb7d3840c4c5766dcee3fc39f0739260a499647429339482e232362bc72c92a299cae36e9069cc5f4db8893e2c1b9ec0b4f334de26c951090b9724c2b3b7655d8248bc12a27861e020eb1e4cf6ad0dab903279b6fbdabff761d4ba159c1f631e681f210a8782faa86e08e554b5e30046157a0d1144bd08a691c2cc2dd22f3c3a4e5d44c5d03f7e3e385382ee4683345c0d316d41ee75f87038b49e0ad3ca45121789e7e7b95615e1a9a8dfe02c044c2935a97b141f639448182252ebfc980e0411e5fbcb3c01acd5aa7cc5d67101ffa6ab6acacace5f02d67155c26dedc071ffa66dbad26f67a819d46de0556fdffc1b4ab6d60905d8ef873ea1e51c62571c08b4c6db242e733e02e11e5840ee445c290b2232010b118839b37d4615c4521e8928e9ad475cdb4a3de9928ec7e6daf0e20d22e308347b31e7e877fdacda0c25f2e5c33a329e84707816ff4ffdca30dfc753c2cf883df16016795db34359e9363fac60624ae4d2b30bc1f2f99c23d953779c22ffca145fd08dad83c0f76cf727196799544c6c07483e0a41ca2e1b1da5a730956154f531d292b5a39a229ab13bf24a804eb68786e481c8aebfd3bc557afceadc41d00e1472c3b80ce652be1245089283bf1a1a93abd3325bb6eea121db8c0e1d6c0c31decfe9dba63c89b881824b0531651fc500f2f75ca9e5fdcbb179c9ded5d600a495ea704c2709f4a88c4fadcda4cd82a5b089f25a6fe0161159efe03fb5e0d44bdb5487f25e8c9adacc389860f62b06a6a4f8f104d9171622f70652ace736e8b28b70a4d9fd3fa4b9784d1a6e6811150d0a0601d31d17f6041e58a1058f99b80b0a6cd4f79c79a104b6bb731ecc881bc68e1d99ab358faf43d8504957ea0152e46e27dbfaa17d0f58287276e4fa82ab78a03513d5b4c3199d1362e4fd6447d1c26fadbd011abc69332ed0181952b391f2e8a5c89d68e22a7c451f69a9573b6bb6d918c7e3d52116f3f12f1d43d2af46bb450f58bde1732a268293cfd9cf2b90a844588c1979a30d6ac21aaea4b9e5500ef4a8bcd62bd70cae6acc8839f818d23c615e45daf14335c36dd46817c9b816be60c3848caa812b055da33f45bc01721d6fb7e850fb1e1458f27c70bc34876a955aef11f5703cfacde03a039c3b75b99b2d91fc18b00071a28ce25eb169b946b49858aa0885a4c665deca020a3fbba55d4d9175fd91e7901ec9eec0239806e8305f8238e5270f4af5c94d0008f8a5564636cc33c8a3d3e76db2a7915abe798b0dfbb3e322b33e188c7b188573bddbb9e4a7edbd4bb194b9743c4aceeab449f8affddbc2b109eb3d84f3b2f8b18ea2962680437241d82bb6146674ff1abee7baacc38d5dcd688b425c3e3b0dccdda3e36de755afcf7155d3d7cac2e279baad167e2a743b82ff8ddf3db8ecfa9680ddf468339427a4e9fb8ca4ce6f1e790c24e7269912a9989088c65965b0efe68ed44eb26876674261e3e72042f5995f1a7075b3932f4c23a8027d0db35ce4322122f489995bcc0b3fa32b7298c4c1b3354766c866a2fc0ea5690c58c5e08ae7037f70accb3ca7faefc37d78883f2bcd768285dd2571dbcaead813a0b8ae87cc1df868e93500d414c4418d5c80b919f73b9fd46111a02bfc884f9d30ee14fcfc1d55d54256b9572afad4777b8d8172c911472a22e7461f6f85aca063c19d6fdef3351149ee6864e93cdc54ca5dc7837f0ead91f5e3b155795df5dd1f933cee8671ffc05058353995019e5f6f55d2de6470605a5411afcd7fa5aa8f38d77dbf496d7fa9c5a4d35ab661aa15c77ce42bed44763166160ed5bba954e470c293ca301363f5b837406ea8ea746057588c34acf266030864d8c40e2da88ef04c49205fad1607d456767d30eadd884359bce04c12e35487bc1885d9b104c9fd4dea4ceaf054cf46cb3c77a619ffe963acc9bfcfad0447591ccd32cdd1fccb1fe7080ad75cca2e17f695ce0095a774327123f21e2839773506a9f2d896bde87dc5e35512ad733aa408f8a49e9018d1013cc32f550c968a03308cdbc73ab444f0a79a13450d4de906369da4c6a675d7e338f738358dc238be4f047579c8ba7a60448da541cb9e57f22bfcb8c26280a59b77edd0f5a009a3ef1e2958d6d3c3372840dc6a0c6ab1fe86aeb7590137feacbfdc7da57c77595b8572b45c4677836ec86fd8c4ca8ac351397aaa3aa298d752754507e1cc514d41c3f1ae0a692179218141f65bccb9acf6244730c6d00829455d21371972745b3665f930cf2aa9f0abebe6f7b89094aeb4dbdf7bbbe794f134b6284e289c995ef2929fc1bd39b259259950de29e57cdec15c4a7d33ef6e689596a6ce23301d25c2ace77fe699d90c2329da4d0f471bc093563dc735ac2fdb32c6995606a67bc953534939ed1236003c004d3b47590beabf39a1e4d5d1b00898496e9effda68433da17d1ab3a32aefa3681aeac116c5705077552649153ed15e9d704e67d8819579feb02d91db0d3533182ff43ee5648f5cc9a595ded4772d61e77bd9bffd6f29fc1f478dea44c32d5ce3118bc8860b254fb0bb1e85223bf709a7c0b9a52fd3914f1b1f295fd246bcb568388dee43a32df45e3c798068608a102143b5511746903255b98238003eed68776b46bb0e64af6c9118ecf9896709aaaabefbc1f58bf45b45768345b560ae2cdbe4d7da497736da8013c4098addb4258cafe7823bdbdd715250b707b155248d39fc6773639e4de3b201fd3cdfa1526c4149ee7d15bbee680c956fbdea844b1470a287d430c5c7e2d7b51fa756720397bbe214c19df3399a989958732d93979e361f7266e53a59bcef695435db67cd8749d258e7d582726e1bcad1395e68d7848849fb6d74451a53ae6e8989c64701102959f7fedc6a5cf8352e218396f9181f33037ca74886fae6e57460bbcb71cbe4cbb3d3a81e2090434eb1d6d5baeee4ede251952ad88001ce047279cfe435a4afe97847f798d84ad79a11bd44f09222d2f3b7fdcc47ff8a4c61f40c4629a0f603193e0aa2164579a05726e547c9081abcc0087907f8034469f740a020e19623fad42e9cea64068abb3d6ff2f6680da328061c200e1f646816a5083786ae5b71728a0e5cee14d7a942379c389fa9dbc7afe7e7ae075c061df11e4587bc90f92f1b077c091c43a25e7b3e870ad852c2883aba2632063c4ff74a857ef7267816317f823a8bc5dcda311b513be3a40e6bdeb89210bece50a608e624f00c9d063e0c8878884e45527f50a3ab4447a9a01652322700f087b6f96ddbe96a68ef98656800eda6563015a6d3c0eb1b6a9b21cccd58cdcdd074b73e40a098a980210ef831ec9e881cb42ee07519fbdfa52d9c62766a2046dee7752f880dc9082ed7f050b49ed8d14307b1b811bd87b6db2419418e49885d20fd7ca8fb45a11a1da17ac2304393734b552b5d02a303ddc72d1f456697a287851f207054c18a6262f5349348c806841d21e11fd4e4ed9c01fce1688483e009930079f7d2045a34f98ed83256dec66400a783d58c61619e6e42f6e2c6e6fc69e76651b96aabfe643ac69681955ce595f4696b80dadd1f3910061be6ed0840d47e928dd93e7c3d6932d3ead820d06e2539d9a604a6b53db6bb599da851de7cc060faa9af76d708a9aaf371dbc3eff0fdb99702504c3006f789a49feb730cabe40745837e2c8c17c77f999333798431231b337357637a5efd1eeed891fb7475f2c9f960e67578adf50241287bc5599ee08d0237f08c86ed9b75b62d612a9353e48cb4cb022d78f73fba1fab7f794a5ff64c97e6c91ec464847a81e5a5253989a1ee54a41bcd9b4b77bae6e72421471a7ddf0136edc59b72402d57e542916ee47fb3988b7123c6e8debddff2df171d4ce61e83c3d41f36143c9df97f2f68639f1bfc2a9d1fe175fe9f45e17e5cfebb330d3f06e15e3cf58acaff09ea576d896359a3f06985765824bc499319384e4c458d4326db801c564b0b503552bdbec60752b670d82cc8fce9028ff24ade3e805b81a72701b37d4ccedd72118b20d792739e035bbacc4893ded88619a6c499f246311947e48684a35406c4ef279c71ab2a74f6e5313f7900080f19aec3a39109d4aa41c930c66c84cd2163f4cdd59fe84a86cd8bb6468bce45a56d09490e032da844e6d90b436dd874c1cd32a75d1ae1d3e86d8a2ef948649eb56dd7b360f55ba5dc34a12f9279945436c6fb83d1ed57ba4ae1d9342a3dc2df9baa82fc9fee927c13439ba5bd2ff9f3e6f577b8d2df731db14c51db8a14bb15bf3e125f1ca4cb2fe856c5a576cf995db5010687d0799581c5e76d400c1855bb46680a631cc582f51c589a831",
+ "823d0cd34e7450550da9716c1f456ce0cbc79431483a6214939266581b0e899e4c95719a09c1ef166a618289a6ee6971b6fea3fe380512cb977823b387ac51d341c26d4a835c61eebde37764d2e1d588df7886177e98e3151106c898b3196bf4dbd83f5f",
+ "a4639c22fc7f370d8500a53819102df5e86c541c0ca10e8f6564e50b90c28f34",
+ "34a04df283c45655a52bdd84",
+ "cd8d1b2e5f65ddb3c0da8f12096134da22ad4d541444964077610aafc1f77f8da5ffc75bee807541cb6eb0526e78d57fd88fa9d9608914cf391ae7ccb8eedb0aa711889f9b6192601163b271c90df5d69fef487b6c05a24fc667469cf16cbd5afd58fc830119fc9f61b26dd50a96ed84c96825a615a3aee84ea4c950152323b20884346b25c9e2a6be3a93505ba059fbb114c224bed8f05f54eab76b2c9c23a0fd942eef9696ff67484b542c8347f1b1fd7df7242872b3528c9e45030447b2bc85eaf191963291e4223b75778335e5f1256618ff87bbd68b5a9e5cbd2ca1dc8aff4625c834edf8fb0d879b1f75ba9b85895a6bb4d7569a41bb3be6cdd020065bcc69b44a8fa335d9418ea2d090d8061e042e8e1a6ac03a6d5525079f14274079734ed42c5c9ab9986f0fee6bc9ee6c485e233e9b4d6de70664902529a135a5675ae129353eb2c00b73f226e84fe8c594272d6eceaca28b6da30492c92074250ec80beddb7208f9b5418944305b0864009b3bbb3dfbfb4cc2bba3313f8f7c6c19860f1dc0f5d7aa06e3b551adfc63dddac980a79d72bd2225d54a87a93717291c7b78bdfc5521f7f3239d5564fe9c9559dfefe76b77efc2e75991f31a0134529a6611ab9ef076491f2d2d81ffc5774ba8f8009dd7e5881e09ddf5116fcb5a44e576aef6cea91ebf52c56c742049639392cfb8b280dc2229252e04d8d394ffafa539290acdd8118656e7e1a4f7bfc0bb689448379e8cedff7590a09a3f5a29bf819fd87297b96ca07431a29a07ae126eb9d65e21824c16707db89868e127f17614a536de6ed268b1600a8b02aac2bca54a09b7cccf8e184448df334f95b9f0221187d56da7bd422f09b4d94228098b563df53414a5a86728962a2ea63023d8c3f03847b36db7cd189ccfef3e623b14842b8cccb18b4f80f01b32a4cec48f3009b98ffa25dbad76089c8700e90848da74aeca81d01f4dab2b7e844a3e48bef21f33c92734b821ab382bdf6d0b1048a9866e676b78ac9398678ff626d5c173a15a0a7514b2544405dd54eccaa2791605c87d7117bc9f8c0ad84623a9d3a2b1733304b492d4dec38f7981db9361b03a2837a95fe937976c7f4341a802dbf583366fbe368a3af3f92618046bb55696cf7af1f465a5a57ec5908621f431ffc762f35abe892f772a60a3f75ad8401321f67981e90083fdd1cce40903ce56a629120d6e13c8871523c4d848664331966298c8b31a5bc8174a8c14f61cbe98ae7ee3e90bc832b04318864d19a9b8b6d49a260f42bb120cef9afbe704faecf0f428d917ead9f020f5e9d772bc8f29600f8a7623d8971c1e3c5f1a3b094191e497bd70f85de124137cc4b9fe0617cb73cd44b89aada072625e25976e7aaa5a8fe9d9e3f32db47d1565aaef0e84d256bfce6aedfa1a2dce5a94976a2bb9a0da95941fb7ed444990b0e0e87627e35f3235a998019650a5e5cae804ecab8cf729a5c712f1e7d17486082dd50cbeb2ee1b0be6a7bf08a66ab3cf1fe9f49c7083f5b8ad183f32fb35fb8a41230e4041bcf0e5ef54bc3d21ecc1fceb08d95d745a997e8f2fc3c0f6b1b6c1c02e03ff02ae0d879d13eedd42d9f9949ca7ebb785764162ceb6c6f9944dcb3927b2f4eab23ab566b2b2bcc0c7d77b82579e88203602264064ce98b5b1ed992c1bb13edce579ae7f5e11697b493749f308b33e47512533350df5c07c3dadff656197884f359cdfcb736d29231aea1524b56e06c92f5a98ea663543f67e44003f5b41907a951dd792468c84c5e0e1b46149a5c9751295e153990b78c0cc712889a21b299b0315150dc50aa3b4f7fb0079ddd39d263a754b1dcc595c76ea9fea6c120384afb38d4bd40491c4689b1afc9dd096dd0327c84802bda6bb6b7a8830bc6c06b308ae9665a8666a5551ec954eb72adb827ef38f036c51698a28c92dc1c9e25c267532da2c04c1bf27f5b683ac750c3ef53a8460dc186331549bf82868f9327422c09afe1cd15e161bc41a70cab2f973efcfc8f01a380b86a432e1ae540e09d404d93d22a20dd5f685a52f0acb863dadea236288b1714700f23d1c19e40e219e8ed21f6a393e541abba850ffbbd4030e5f6567b7202fb66d86cc2a0beabd495814f6a50690e8d74cb8b093e4d43261fff80e7a67ca06dfe808899cbef84c09ece01414baac740cbe4c656b17991868e2a136f4785a0de311aeb18cc95ed33fbece22aaed8cc1e47f58cf6c09a6f92c96f37d2d2485b369093506f5e9f8534f8569655277d0399ddd3d33861bd40c71ac53a44d1981cd744d79202322d47a0228356c0e27efa2ff1009cf2a416fb6e8844eb76b8077a4a3961ff193e1c95b222e72688ba48be82ec5da498e58861ea613782ed1ab50a95b5cc236834af98e61528ab18453c20ff978551b81e1bcc0ff4b7092bdd9ab0b946b7324b7361ef05e1f7d7f6a336281b4bb2c671a95a6ab84be6bef1b9c8c3d2536edb8d79b40637e16d7281ec5243016232d7c9fc07ed9dfcf555055d8ae65f12ad150da81f62f2e1e82b3adacf6d623ee4759ad61a09038905bcf1dbbab671dd28fc1d10a0b7eaaef73a5862ab449bd84c8698d061e79fbe52a86739ba945a01353e0f3916667bd7b4356cc65451c7003927f2aa738d98245760550156dda529be741ce3ae1afdea0de35ada26ac241fcb5d518e6ee7f9930baf88bacf8bdaccbecfdb920f3b26285439912a8902ae029b07f28c1dbcfde780cd2bee6c6e5f4520c5c7ff3ab5448ec86cfb270c39586f80041f3764b5dc77dc5ced0695c89671cf90ed34c4067b4bd938b1493c7902dd94be824810a00bbde4915d138fcc7584790bb0b6682fc0799cd415441ac90c1caa008c7fde3ab4a3aae478c64991ebe07e6c4587d3046c9ebb8e125e795f0be9266bcee5a4e4355a2830c5b34e583b0355b34b89c08011db6f6b8371de003074704e8cdda37ce42c7e395b6a37bae3dfbe67bcfd1f125c9a262d56883ddc028773988270aa30c6dd326cbffee589f38286533e1d5c9486011170be591beab5e0ce98837cf91f0a58d69d872e364aa88daf9cfa71bad167129420282d99ed5884a1276dfffb2c4100c74a8b863b063c07937f2e9c12523deac4ea16178863d975e3a5be5efb5ffbea994d07f7ddc5326bed1f5c9415c1d4ee1667e3a581499bb573595158636ad94d84f7c6e4b8efc2b141f2bfab7932a050fd88a8c7b21877cddd488543db5b11138cc808e1248b6e2ef492faa8a32f9d93e3c060b5cec10f03794248f9662ed8c283a8e0eb493824e2750ec75b3b1292d80ce002083a3c64cc487afc31b20f84a778f386b012ef7bef46e638d0f1cd75487ea46e05621d608482637b3e642a9a2c5371bead4386eff968b3e007fc263086d8a930dc76a8431a4e6907ae35c7b3291075d1c723f02e4895714803c0e97d65b04c0f27d01d5d68001bdb3bbd44dfee1eff1754fe8c182cd9bc6ee273beb2a444ca1766f747d86f36cd8cef6eb1dafe0c38b9327a8cac6e83e076099188f02721cc4de3d940c3ef19d9b067be07b890c798a79ee8c44d96c5e05ee5d5202d941a674378386233a83bc85134dc8c46a7531b2b952fb277d8089cfb13e882bcf7545f0605271fe38bf4754f98dfa13fe6b635a62bcf962553882a8f28a9a5fc0b3f85509b702d4a7555d40c4f7d10fbe80d48b4826995fda7d15f14aa9b95fc6526101cf09c97fd74baca6bd26b4fce8a57b0726e0f68118969ec067e9ca39b2ba59fb0d78eb5cec5b872613b1b76763b3217d859bd6d991bbb5448bd4e49dd6597ddec9e46afb3f71d254aba828c91de51904139ab19138e36e6996a207da80323d96077c97a3e8994296376d4dcb602f1e77371efe8b020b7b6f6f7bd2bd733ad9c06c45b77a2893d73b4a8a57707969af74ba06b2fe7d4079bcad1cfeb3689ab95c8b1215fe0a855eb431f67df4ea589dadbf055086924e42cb142c9031e25b81e8e1167a54008ba1ad7fec6794f203b27f3092dd72bb766c9653a72b2e25c965f53487cf3baf74eb7742702380303af8c0a61cca3eec78d4b709e35e2cc5bd586263d9f56fc12454547bc6165e3f070ce7b2bcace5c8cbf52f987568dd90237cf190dabd4ee7a80494692a5379b013611f4eebeef8e1ab9a9c5ba61926095545e19c3dd61b7b404230729aff7d82b6bbbed6b4a926f6e49189e3bccb578fcb3537951fe9c78ac842350ddd80133275ac0bce3a669183776fee8288f874d29190b452d65bb7d8edfedc6fa0ae147102b92041af6dd8a566932e016763b60a5b9b1e3667f228cab075f966d1c525ac19d12046c6409345799adfd7154b6d8b51eeb1eab3a132ac6a2e08acd1a34bbbbdd019195af9f8a93c6ed5463765173e669cb0d42b6cffee1a4b45987853d43c02f920819f45a4fe0905d8c65aca182b4bf56fa0dc51cb53c642fef003d92c13ef4bc1bac571cbe2ba3673a49694f6311b7dfc17a4069759177930b179748d4403c7259e10a5d221cd0a6b745966e598f894e607b779dd5289fbdae0b4348141ad373a62c76aa454b35b39a7be875598bb30007fc300606ee2537cfcd7c22b6149880fb3cd8eb53054d698a0d20f26a5c3ce468255737a68706784",
+ },
+ {
+ "5622aa8d2f308dd468a7e4959ccc01f0e80d91f79df65b8201eb44911f6abc758c6703bb97908fff377395d33f96c328a4541f414b7ac34c6607dd85729afbfe01feba988e4997c6bd2c99fcc35d2467b143a8fcbe6b49247226a9e4c0a4e3c1a29d5931e6f1f7a31d90a0e0edc4479f08ef9bc65ae4eacd0b93b1cb38948dda31e60b18d702bbf5935bd580201d1f280cbbee679fd834aa6be576a37a037eabe989c3c18c7fb61fda8b9ffaa8bf22b57a101c19e850c454353af7af3d755b26ff1ee78b9d9daa78294972d108958682a5a29c8ef260e2289ad9d7d74f32fd4e51e5d9ee828366abccd97dd56e035713a6f3a1985383c0ed5d98c4accac2fa1ba7d30a295670d5224952f7b7554fcbfb426c9496f054834dec48f9b70af3d2b1c6dcda1c4daf3e9601364e57851952c785e65d753be1c22729bbde33aeb1e4748dbe90da6ecf716f05bfc68ad819515dffafd33a909562b95140ecfff1d0747f8e0459fcd3ca6cd8893262614bb4bf4b639285f327e7ac782898781968ec98f6f0f2f3c4bc5f9c4691ffa7ddb3662816f8ad092095b598bd4d10d6b5fc6fabed619eb11dfd4d638f4c0b6cff7194156a411e8ad6d3229320336ad52fd9811c3a1fcd571d1bbbac67c6186737ac7ca1ed9b2bc46e4e578f81c164b09ae5cdd4059a2c22b5e7ce1dade684e49200867f9bb1430aff9b99805cfd31f7e3fecbe898f70a4eded86b8bbeef7050eff6cf8ba71395a7ae2e270a2b58010e56cdf6efc4003da3d8a82e96979ee68694b6113cc9a6e377d40a810063830eb95005a81405e5b7de8de67424845bab1911bc55da6338513742d237a555465fa54b07ba50ed712e7a57a39fdcfe4af50f064ae969823aa1c40cd86a621ec90769d0c1babd33e8388a8bd76689215b9827a5819127bb32ecc80a562a291f3192eff34cad2635e5b0c0bc174add72e2041864953f1fc72be7d28111fba0438d9036da3d5c0f220ccfde2319bb96fcbfae6055ed7f1c1967ee9a78e93bbb77cbf151084d602a5a2f087d49c3134582c1a5d7af24f4c88be26204cc9dbf4368b19470fef49a5823a2d66c65e9b1e8ab56bf5a7bb3220696840a6222caa58a7b39fb792d95d25038a8bd9d916e853cc5459640f8b8468e3d51f05f1b95e996cee40ffb7ae14cb289094f1b77d5573c1aee7c12a6c3a1e31491422f272cc5f510d4f18ab63d3c3f468c5abd61b2fa7ba0768d46392e2a4dc06c7ce79841dca916cd33cc0a700b50fc660e5d1808d8b87e65feb89428055495823b2dc317d6d9e50aa5ef7ab14076174ed32f56abe7d410e58ca40e92f8a31433d0d74ba7b130b1561f2b075fa11ead744d031f34d82f1a64d428f6cccb0a009be24b42937bf3e99a1ef1fabf0fa7335dab52918382abe756d3de229ee8223aca6d7c5de87047838e387d4e472481a4cfd4365256e13aacb518ce5300f18dcb5e0a28477a6fca08a74756ef6bd8933bacc98d02abc7ae60df7cb3e06d41abcc4bd313c543ddcdea2424d98ffc6dcaa83658aae11f5841ffd4f5df42368a0e815d2146a0fe138b223764b133d17cdb08d485e9f3dd2bf2b220d1f4565b02d7b9231d592130e4436849f49b1a70772244fc0c38da372a8c57fc80ad57828410a5a16ac6d14e093997fdd5b26e4cd4b248e0ea221715ae6e112e1b68b09f795540e31b1231244bc922207b906c4f42b5302dd7474286b653b4d1bb657134bab117d6c349fa0f121c2f8dac9cdcef510c1c28545eae0ab163db6cc84ca182feb858c10153d0136f00a01c9c7d0bed892715dd85c4e73627c3a2ef0f43710dfccacffd1d9f118c9fb1a83b2eb328b8da3e955f027d95294038184f7b895d77532c7570cb86fd6b37a5a66659cf1e330db3930f302838706050c0dcd91d532d49c89d144e9a7f864026ec99f50acc02bd5f11ee88495ee8991ec4723b189f84e03d992fd718b5173ea1b033ab7d3568dc4656648fb54d28d3119b0f293a930a772c394f45ee66838f17b73a94eca27033f9d5c2ae22eb813386905dc024673850a087958eed191d04d05798bcf909eff2deb2a0009d223323b290e3d6f71b2797a2bc2590d54294a5992d629336518514032614a04847c3fad8a7d1cfc2f86765b48cf58acf892f68b691fbece38100e6a71487ef5c4ae934f1ba03b4b26a1967f70ef1c697202e4eb22a3a95ab3b7b524f0241ab4d2adf3ee5e3f2974d0bfe4419ef0ab11039ffc26339570e74d260c4d5a16f22cb4f60b03253487f5e46c47836ce29460728086a615f78d631d89a06790928455889f58adc3d0a3a84ceb2ba9cdb00a403080e6567873b985fd59fd9dec71e375013c12c51cb67d599198f36f58fdaf897e85dfe6f9896cf6d35a84cfdc6834dd9447a2a10e1ffa9fa8edfef1db9e8b4a245b211de49e04b7e88977b4e1ac9285f43526f2452181ee0f80efeb1f6b2533b656519ae45652ccefca81c17714476b497e5d8e9fdf6c9f504c7a7fa7afa36df5f4f8da5b4b973b1618fc8d2d43e866b235e5420551d1659e5bd545fb78a3e17d9cbbc8e842f3fe6be07b892453ffd689d5188f26f9e4c545ba0b3132af12a03bce6914015d026d3d7df661c1e6384bbb50dae24abfa78079a2b1ac41c44c7d82a59183f293f12011e781d3cdca2f791afa5b55a9f2d6139587bfd74bfc54ce91e642847a33b48c1b366fd8f08f520b79ad5113a0273735aee71ceae361a97547fc09b22fbe4e4ae4ae13e52d65e0971341aab368d1e917c8f5f2ac57ac119f981b51b7c99ff2be3e16935b7c73e28fb58d332e6f2c36281228c479c4d6095cf15b14baeb0769191dfc649a70471a25d45d4433797a5b8ba31ff567e60ec4d759d99244d0fb5dfef7c2896809938ddde0d2015a4c5ce5ef6cdb5752da1c2a33e5bc78b6b7c6a5af892f0792c28560a357720da3cee3833bbeda8e98e6a8cccc6535831cfc28bc8557b4181a3978bd90eabb34b99eb7e55d9263e6790ca34561d8c87ec4e12b4a38df524318db00a9b5bbde6f5a8644a818a88e91b521d716fa9f95bf70b109b9905bfca926fd42ecb9114c039790abb0392a41ee4c190536a89ae6194befc2dc4bcf7562bcb84f65c99b69612c0511552f53436b6c489204d3881e1f67e0fba3a061165d2955c2e2e12c440d31556250a8a5cc04ee5e09b1d627c14e08bce1a92df7f6475db92a3ee57e4c16c3ae677c44237122818ad457a29595ab528744707f3ab7ccf3d20bd94047e013e647802a7af14cfc7c11441ea6e9b9f960fe69d03911ad2cf3a8f633e0d647c71dc7e188c92e75353fc953d6a30dd0040c39d4355b71524f1a4872fb1ecab22c8293b54bb22a80e1e3d4c886d2988adec26f041dd0565cfa9edfe5ad9aa7da1d3b8f68fda9e9df9dbe98148120af6ff30e6400deca6dc9593dbf06c856d0d582503e7ffa185f87c6e7ac58184bb80b4a1c0c18d669e23f9791365fe807356a5763ea418c39d94311759b29b14324fb6f3104359ae66532779b825f92b7c9ea2ba43ba7de04eaef7a86192bc93e17286f1b6e0a01c33c796ebed8f17692eb9237173a051c14e4869afda2643bb98c9ac4ea94c6bdc1401c80190df6abe988d2f0b2d80cc7bc8362ba25c6e5df4370a43e156aebd6aaf856b3f64d5fefc622d078faed40b760a361966a4765adb809dbcd74b7a41faffad3a64823860e5656874133c7f8a46b5a3ac591906359aa4f171ef6bb2ea6b5f24cfe25c2fc7c1973bd5d3bb5f197002c5ca1bccffb570f0265f5cd949c7386d961ac9c5e18b5d1d6030d8bf4a48c10f12dcdb11924b02b8ab5e91f425ca62bbe42b80c6b6dde3160ebbd55803966716734327058e29bd39874f2eac199067fdbbe8c372c5a688d3615e2b65f4937b67d6a26c64cc2a9e5379cc00925c678f174f538915f912e85b7014c064a73bcc7ddd38e1a9627ffddb4bfd6da764fdbfb45048c9495ab1a4cac5642f6c9ffbe97d33cb26964a23719620df3d85dcfc392c4502759fb31a6a797e99e51e94cf9bc79ac15de4e5cf7a05aeb88a8ab4c3b6f9c52b99794503f2c49cd7e230a67df7403e552523249f29d257b35c0c7712053c3d9eb583a1a7473d7f296d25a66566e4ba8b08de2a31b082e40c8e5b1e93985b324dded3f52511744e7e99f4e3ffd99d8ae17bb5122b37f637c5525558eab18a378f5e2cb56fa003ed3af8d139d16ec4b2ea79c415b0ba4d750ca2cdf653582ee3b65a9825fb9b123593e36e645232163cabda515b959ed0a1419e9894f6c677ac200fd11babe3503ec7bfa319f1b9559d94a6f82945c9ca8667621a5d28920949a1da644cbdb58b84742e9d65e7f2027b99fba4dec46f642bd17e88fa109143b26ba7fe285c89add0b74a369f3d381ad633bfb4f72e1822ff96aaf9a73b3c59a6e457cf40e17c1198c64737037f52d9b3118daa3fa5cd3e3c7738e3b3743c595893289974a4aa0d6bf1446e70964823a7d5cee67b9b25b7125d9ac5d1d61f2a6947c3deec6deb575e2fc5cec60df26de3c0545e5b79156dd6af33a78552d1ee9994cc8501b7dc5fe7a22eadaf201a92e06ef03be705a8bdb4db65392d3628c7cbf44cccac292c93cb5a407a7a5a0d5ac9fd95b0033d6eb719d3f14609190dd40d5aa1b983cd4c4e278cc8a1e7d5fbb0d39060d6cdce8de6a17e2dab973a7fa594205e17edab6514372eb51e03b0ced6402fac0efd3af49fb8214a505cc9f5f0ea5308d7fe6dec369ba154",
+ "9f522375925222a04f5c95ee14b6386412025903ecad0bc3ab78afe1145136b3a3592835ab4ad6faa66be9",
+ "d1ba82b3ced3e9817642aaacedf482e79bedd0560ef2754215ee792514bbf8e6",
+ "bb21211f342379370f2642d3",
+ "1a6683805d3f478ca1c1512b9846468378f83be27393db63956e151ec408368b47334afe610249182f54c4d0a01b704db2aa90a9755b8feb67ef9301f0715d7d6bdfa5cc4497cef1142a43eeb42f7c413e8f489af30d742a706d05a40a0c4a5991f9e2cc5d9fbca6ad3767682e20c146ac35aef38dfb2a77388b738fa022158d5c802e5f0761096bb45b50815ebf09172759521b5c5d459703ebe9ff669ee4d14a86e5d0650b597f4a082ba0aef366a924ea378b91c3262d99f48189eea19c76c0f644079f8415c11033cf24d30d6c149ab13ca5c29deafdc816e457257361c1af4b915da312d2e6c7fc712faa27be3e67c893f9005a0e2c28369991c1dab22d38961d1abd6d94c4d549cf491aa1f8d522be3ffa6d214825a5fde3c94c4e35c29b8d05b2627eb12c9d94f450a85eec6bc963a279a37c2344ca36eb604c4bd11c2bf2ecc0dc16c2c365bbbcad3541bd54f8d0bdbb3ca4a087b62fc19fcc1c13984eab807d2a6a1386643d90d412d027bcd0a638765498cdbb1f4cc1b91b69bd241eab3645f225ece85a56e5008d6094041f8cca6b9a0ae3b15585de6fe0695d79d348f8619431ece40e736957a7627224fe92bbe30df5124f476d97e36b5b08b3787e8e00f0c10013068eb156f82f3494a35d6edd5f7048d1e91954f1013ede22eca8b4ba41699ee08decedde87139180a567c6d169b672af0f12aa09ce20e9cac4e78b8067d31ba4f63606c00d1d787b868cf7643fbb170f8074667c9f7584d36af80b4e6557724013618c28d0dd40bfe9d4b25761b3c99558af528c2d290d04b09821bd7f992c044dd61dde9395bd0c9ddec6d0bf6e044ddf0b4b2d6753f5acf2e9c904caa4e9f310578527b85e6738803758da646919989f735b09c9a5744e63fed2c3982e59fd29d2baeb9771316bf8d29213a4956b66c78d5654436ffdd82d0d572530fd09507b988d13fd743f35333237681f8abbb301a8ea870159f802a57760659094d0e4902036c5a62c563f1fc86c4238e1ce89f5176ecaea194ca112fbdeefbef4fa7c203678cafd34486fe58b2af04f84a1cb620c6e123bfd96301e0a5e5e5abcc95d28b852d0cee2f51faa73e42f22fc335f50de4c3812ee14038633a195083f3944284c1086c34995832c3cceb7d385b4ce86af10685c16005495121105272d1d739c584a07ec7801c3667bb280987a8aa41f9537e9d1812a5dba5b385a0b71d2e9573c6f3e9ebf0bf7267528946a6aa6f43efce908d32525cdc3b825bb11c7239f1de412704d24c17455b9382fd6a873180f0d5d44dc449320973d5cd0d4e67e83946b6ef47e5fc3dabadd80751f1421404e56b1bce748b7bde63c6975ca81f3eaf52586a55242c9745dee3f7c796d4508e818eaa4fa50490c1a79624561b98d2e1139a328806414c905372356a22393ea0da51c83957029edd8c2dfcf46d9564264d74c1c0497034ec018b1dd4c14acebc34b6d2c1a616937c37b8b4a0ee5dcdf787a0de1173798ab929b72e0fa83a6c9b9a99d8024328d9c236a8f57550a4f83e8071eac76adb55939f85f5b5f514174b670a3e8dc2b54656f6201940a81fe4953d2680ae4ec58635ba74d15efab3e06dca6ac269711ef2d4dd49f731e24a92a3b935ebbb3fe8d001cd4062669ae4baa62c2947033afcfaca227d88a11769f87456d5cd1bb6606891e71d63aff9cd5a7d23263a78768ac2ac54ece1441fd37d096cd27e916e68891137fc3cca427febd1947cfb4d7ccfad75b2ec5e809c132111eadf25a73043d68333139bd2435de9941bbc61c5c509897cfc19a21645019eaaccb6d06371e3d0570c09c7556e41a727e44d9bd672fccd1f89cc7d58761c16df8fb75fb8a1dde2caaf088f02dad91b6489114398740e6798f3ea8c7b0cfd974e160a0106d703d9589ab09aae79108e3212f19cb950ea9c0798a1532bc2a065d5900a12054395c0545b0878ac0b1d461f553dccfc2a22bf254ced88dcb538e3889549960b77ba6237ab1458e158f4f46606372e797ec9d9ecc6534acaa1218e7540eef11030bb9c3e5a7816f3b33a590d970619bdd2dc04d5c6f4ec38b7cb4d525234b836eab57f65dd045e02367eede9049e219b8712b8d6fe178080c5f77b821f1a475259ae571a5578eb3b48863162d45486f71a28ecbcedb35b320e5b6401f9e7870aa5418449bf47502626e1f42abf481b48d5a6819c640bfdb64f873d583fc4e40187940a6c3373ea7b47195270a8657898f55568985018abcea9bce1c155d95b426f91a734b2a14ec2c7ca2011a4d30019fd9b3ef63a804e9c30c3de2651c4213e90285a4ba100b31ee402e8a7f23cf9d4dba003bbf982526bc63be5af102dca34e7d362d6fbf6f56046160d7af33b364f2a86074d1c0fdd54aae89b19480efde2a9caef9de7c0f9491e1cf43a48752cef405a0ff16b0fc67bbe433a3c1b9661406c3726092efdc076febd60c436476f24dab1b0b8f8893986d951ed72282990e8b1526f4dcf539b22c01c6a7eb5577cd540a16a81296ebeeb7ddda72e60fcf2840c5b42c5cba30eaea5402f267d1d04bc80da5ef0dd2bf3c7a2be986507617c9bdbc96c6273a0c9e586a0c48c98b4552113149c6f79557fc8ace0b1a512fec3aa09ef191f95c2163113ac5cdd940f0c2120509bc53c3ea493c54703effb902ef752c830c61e85636ca95429bf16937bf6786b3eae1b277bf08dcd69f521a0078d633beb33c9aa0cb33b238e1021ca67df122a403a3698452740bdcac81d22ccfe4ab5f835d1961708d1faf6d40f115f16c6094ea37a7ff15e0534f62c19a6f4ded0967be337cdbdd2a7c58ba16ba2e4c3686e9d075c6fa7d29b2a0335ab4940d2a95c4500295f4db84ae65e46c54b7300909cc5411c725a31fd962d239aa0e2007c285586b4c778e2ac7afec42cd8409a63d7cd9c677031f43f4aaf04258dcf1270c02a4764177aa66db2d8f860eeb1fd06d0b27587537410bcb641f90aaa7bfc6f12bd143f66e7c933a0f3ce6b5048913e1b2d79eaa6c19e7255d5eabd24d5f12426339541a22d600cdfd1781a1a3894740887840aa82e5a461fc324285b0223ac9b95c3eb88160353f168b3d4ae8a2e87b7715b5fd2671f66e6eaaf9365b3d9e3acd9a749faefba6009783771177aa4dc91f72fed7a5bf6b1b7738b84ac0a07b4a5a3f0a9134a39e1e7e3e2f9a92d5644295f31c5a356092bf07c709b4c34305ebf50e857a4f593dd1cce0439d3fd125c1ede1a48f583bbbe0eec7058345129ef78868a96f8a76ba7fbfd1c5eebf75f3e0eeeb9db87474b96f321b87fffc02433513fb467fb74e2fc8feb498d51530c753e9a173e95e0edc5ba9802641a45db281b2e2d87d409057b4fb1925e834e90fa5619ae3a9237d5b104e7ac67c2bdc31001eedb4ec7064b2f72e0379bf8780f67ec4b195db014a2d130e77b1778efe3dc703f1310a566a6d3b5c9b12b1d4e25815493ed1510a516a31ced3b64ca49a783ad63ea71a57290727fa31386d2fbfe41f12d36a618c6c28d8f10405eb3e0a33e8ac2e4133ba75c688c8c9a2bb33c8fa032eaf3ea0d2c27bf89269c4aec55f8232b292e7fa9fc24527184f19187d9d8a3f52335e2feb5dc6d997b9b773a79a31db832b752e5738963ee5d61a1b426414975693f986e165e52d46cb059fdd4f48f008e96d4c1a48306b7c002fd0c861721656074cf11173ca65cbdb694c79f58a3f3365e872b24670b691682c10261eb1ffb2b65da031d070e31542f49704b77970a78bcfb4c4ca517b4c966a4e8e27664704f633e90cb7d7917dc1d3a8b8b7fcf59ea3a8a81305761923cb182cebdd59255803a14ca8a75fd007670d79a25eacda1138d67a0fd1da981529dbf182fc4d7a700ba498e4476a1d415381c9e2ffa3bd46201cf2e454c4aaedbbe3893bb4121a6de02cbecc1f319155eb8c99d1030103bb6194bee51e74fa01f28dbe16092955b9599d5c1f1c3f356e26d48fcad7c4cdf0eef25c25273dd62171785c9d2c5a01b1f3da9b4786b1b399d890e2049b73c12de2fb7177f2bc3d9c645398111ebcfd83b73119897bb994f998f4a6fae1b3d6361e171059dba0bf9de9af7a5a1b21641790baf82a36278945d649cf5d310f3792fdefe8c58986a48118fd94647b786e47733ae703701e18992bc1b143b1da6110a98030bb9895c14d7b8eae1a155a550e219a5b6301b6d26d7956ecfe4c7023eec1ff62538b3606ebc7906a1243bf8357f593b6cfff32e3fc6b51f6a0ffaecb658d526f7a5e9faa6294e4808b779f4832318cc184e49e8957b72bea0d67366e040cf76a85889fc6b04e84afab0d02947d0d83e0de19f12966fa8372f6e82ff402bd7a69195eb1a7864a3375aa9e23736fa4d4b0224647e416474c01f72b7d4af240d7f43395b5b04c8fdef1165ce1d56ee8ba0e350e6ada893e0594facbfb5f0d8829ae203929525951584c21371b86deb0f76ef5daad5e847135a6488b35ea33e3a165fea502975d6421d4567a229bf3ce94605885453610eb9c82f9ea743bee9e14776bc3076a29af268cc72d9092a492d9ff08c345dc2eb2f8003b561d9912ae1198c58107f8b37a08b35075af9863110e6770425e9d59c2dfff9d9942c8bc3bf7904c2a952bcd573706caf1ee14420564ffc433c0f5871c4bda916f2530ac75819ade49fa1de21edacbbf6b7075dba21a84989411c566b7c356b81803c7215ab0f326a6b8910dbc62c1bee3af51f105fcdebc0dbc56a50b22cf81eda563bf8c2eff98b476e8",
+ },
+ {
+ "99444e82c6c4c47070b164f298ffdf6955ee5bcb3070b9aa95ce658db4db084d2056cfe61a93568b44ba7ddcba5d450f4ba0da7b119425a6628b3416663c638692326cacc5c237097db5e537122b465dcb21d8dcb5fe831789b72deff3907685c2e23187a56990221e755930a09f8d6cc065487563cb8cec82b9dc754952fa0b342c92d99522fbb39854e338f470a4b4d5ed2a39b8b6253b7001b0b953abc588d757616c7a5d1f12b1024aa572ef5a47dc8480943aa6cfaaa78064fb2b29830280e46efa418d0cf38f57980146f2482276c9b6b16f865b1606bf1131e894336979a163ba2e70adbdc746be0d38062fafcfe5603e6bbb55717b66a263fbd5cc7476302ea4a0dc6167221f745a26a309f5886934f4258965a0ef0803eaddd05e54008df8a0695a078b797be59f1eef95a658c99a7d52001d4108212ce5f18a39f1173291808c980b0513f1a531e03ad7380372b65572d3967af4c25fe54d99d664cb67e557fff05c12e10143c13b1bfa3e8db093ff832a7978ecd85d3971349e3c9b83939b73f0ad55f1f1162d0c106b99c0ff98442911bc15e9194f5b4ded97e9702b84e31b31380c224f392e5fa5c720a45f64cd7020e25a3931b5871e4c708e77f4729225aa9f48f9d876597d3e79219dddee0efdd16836021dbd21692dafe121217347cc128fc5eb051e6843978ae17478ef714957a84c74656ddd931cbeb43e32fb0a448acf2f90ee98d38522b4fa9aa36be4fa13306e799d4c0cb90ac0f73cbc018146d1b0d6bf48aa446a5e3e0502aae9fcbd196b36b6b7426fc10367febf687f05392fdcf878863de2e47be7e625d0e3e3e94e199f055c0fc65f76c41ede43231873ff10eb854dcd6ac9b550ee8533d16f81eb0e86471d4da69311c47255e78ac8e79ab36ce880d6b135279fbb5a712adc5c3862a356af49e9c10d5b16f4e5dedb80914868111e194745b802a0292c7c8564de28ba8e71a44f7eff6573e5434e65d496cde5b5e62cfa9e2e9ac85a164dbff5767983e71dd2661d37d9027a27674ebe3433731a606db88e0880e91ecea8134421962b3f68915c9f6a5e1992c56750f99bc313fb30cb89384c72571a1a6a5e3c01897b691bd70985352217fa8a67f3252a06205bd1a9931d1cea3736559572561fedbf3ac4c8bff9ebd7f3753ee69a69ecbac4be6357db7f4213b697a828edc716ac01da75c1d46098c7d5d6ae6f3f9a2903588c5b340c9d47c234efea21b700cdb8db4279afa2117677e824e627bf0f2b179c864ba823926a57825478395545f130886bdf2a7c55a2647a888c3998b750343d9cdc602e46b7b09a2fe9ef74db1ffc46fe27c254c927ce51b307e96a571da7f3f907223fbed2daedbcc96197e95edde7859f3b4ec6099f791089e368a68a5ba0917ddf4f50b93c0c839ea36cfc8053811f8fcfe6986e5fa9f743119ecd6c3e5fea1dae3ad7eb465a89e9c68569190688a8d56e4143ceea3b11fbd9de67173d5134ec8b0bd7d16560ba2be52345ebacedc01a2e03e8183ef91317d87b2e15cc6301586ed829d438e4ff1d074408b332c8ce60ccb6790ab08c228807509dd4b39f2c227755f6b039f5cd413ad6f46c9ec2cc6a79457529d297b1d9e74ead9bedd9bd652fb31568a8e2a9e2b89e4e57601bc1d960360232cdb30cb502b950ef930d54c2c0692a684cd44b0472995bd2b41dac1553ae47216253d6640d2653a033a862f3118c5b5d60a662d240bda5f4da51092eff514f61a425c5b14b19517ec1b371d240cc30a0739273b34f18a72a69b1586802a7caa6cc8f5817a8a995695d063c9dd26c3d45feb0f84dc8a0773151cf9a537664f942f351599cfbee0558f441f5c7ad320cabe305f9aba570ddf6407749b6db42f9ce94526a8f4170e735b1dcfc5f0e090af10e039db3747aa9b4f1f26acc34639ac8b60557f7753e2c261a29852932901a4093b7f307319cbb228e26eec289898b3f8ee236032163293b8caf64be3f7ffed236f1da688d958a1bbb79dd45026884904bbb936c1ebca7aa6b0c68aa8b667dc1575729e4ecb4ffa82ddced2f4571bf902c52fc4a0ea3f47aaf5c243ac2a1fc19f825fde5d9fc8d06d97a351eebf4ae1846aa62554d57cffdb3f3377695338f8d598d723289ff3962796e8065632e7da9d8dffe2636cd23eac15a60568eefe3e77c561906555268cfc1e9342417b1cdf090cc16c79939b15a9311b0210094087dea22833f74eb0e35d44259ecf327dc84f3f24b8c2bfce7be0d97e00d2be88a150a0d557ff963b4cda60eb99935951d288768b4b2649b717133517f5e3909744417c9c3102c77ddd285976cba2c89e2b4f297665632d7c8652847c4625038a6670169772de0550066ec6c2018f503cce79a333ecc0a0632334df6959d2e3b052fa47c5c84d15ceabdc80bd6be0ea2a5a8d5e374e0e9a613369ca8d4cae3d9f98755560b27b2f6e47b01ba390f5ddeb732c22b12abd225e26ecdb639b08f3237e488430b3b39f0b63aaaef4907cd003a8f2b4c3bfd721d6c3fd3a5f062d72746606a529ba34251ddec4026f40d262e9d527ad84fecf5bb2cc8601c2a38437098aec2335104842ff1c455e5d17c136ece8d461d7a3bd9a60339c22d71059e09b3603c0565c0345684893b56054ec4d3db0bf15546cafb4a03bd7775c3157e7676bb7bdb7baf3100396c563eba1a12952503eb6ccde6b6d0a42d456743c4ddb97f5994fa08c5fa41315080eb6b928090956bfc6252b232f6e0785d233c3adcbb9370b59c35b0dd66005d516befd1fc843df8e68fab19858b91e2aecd1c8a88b0fa3d4c2fed2995ee87e65976b755fbf44ee183f9fa08848bea325807bce0b7b61e03e50b2c7af9b360532a17a8250cf6068fef0198738c82a5e58961c54017e343fcef7076e823d63b4deee472fada7989ca7a213d06a4e3eb2d44b16e5c94b1588321cf6c45a5a792938b058d667e1730f8386dfedc50ea0a959b78f12f2949b34b181f90bec622515227dfb8a5f6e89d2e559c0ba686153b218d2c50b67503018e22914ce9b49d3bdb7cf38172db1ea130baacd640c111614e3db204b3b50641d8978dc14b2afc27a7efa819cac6bafa8166d1c127e2237520d57ad38a80146217a12363cb1f8a720e328cd8f846d379ada43bd4865e4aa633c479bd448d205b2e43befa63486c717af84a733f1dececc127c047850aeeb8ce677612f5966e23d92c1d3c758aaeef82f862c1154fadd6766e1dfc780bb447732a5968c0c78b9af4a9d669338458b57cbb77910a24678092857c0b903152035bab6b1c73f7b667a08cd0d31128888de3ff1fed24866eb60beac19c1b139f77bf0b9332024999a2d56975e691fd7475fd93622119d0d725bb99c1d6ac604d6b6be09d6d29360fff9f84e5318259a67fec08a006d9772b9410ec6abd4cb828b898c625c2fc35c19cb9a6cd3b0073baec7b5af254d21de8e209539f560bc80ea38e33658a68262622cdf35dcd6618b9e272ac3644c91f27d372c6297d8e37201c6a86a7d3accdf579c15246276a0009ddac4021755f4848d10f714e9da86eba13f461e6a12edb1aef2d6117986120750d609682bfdfcb90ee3cde8be54d45f841a6dee2d5b9fdc4e65edb7ebffcf3cc5c8a4e1c6919ac57568be23bd8283319ce11fca3caf968b057432f163f22e29cac30b8154a646ca0ef4fdbc7770ee1451fdde9e9d651992d94c843d4eb2570975528ad9f8c193f7c681a43df28242547010e30d75fca04f39247c77d6c3715c25fc261ecdba16844bbab23e4d0482bd1565ca9b526ada9b8f5703661a84b23070d85f3e8265b2ce10750c5d798f1a8ef4d51a473ff4d2bf4be615566ac796db9fe61a224bcce05c31ecb9ab7bc43a609944a7c9398a7875609ddbcb556296f548a117847df7d0afe48a5b504e85b0d7ca589103d3197933a744fefca795e1e036f964a4f14554d5cfa0261e25d6e5e02f86e402906d3637a2352459cb1639f20faea6f0e3fbc6a39becb1b1b3a791e32e85e5bee31be685410adf0c11190e20b7a5119b90e83f2cc4f0de8898606bb6e64165c95d4c5eae472daa6836a888ee4d9a79de72b8fb47a9c9c0323a2be9106d4ee9ba8b3858c256032a9caba37af94df4c7b0adc2f8478cb879b6d452d73191b0fc1ce944df3f4809cbf3ad46eceb3ba4abd9679410f45c8aab20dd72626f235e7c0c934b4beb4507def24ebbdd7a507943c81d54bc69df578aacd9ed0bfd3b7809dec345ba084d88fa9c34d80685415a4d5eaef9b88e51432b2b2037186baf123a6257e47aa56d6531923d38178e8264dd315e95bfafd8dacaf901e354b0f58f135d638df2c0f32453205c7aaeeedf8c102e11cfddea9a98d3ac7c385d71b760cf2afeb1ebe1d64f0222b9b101893d11a74ed175297c1dfd188a2565fbecc6bb07b56ce3973322a965dc5a675587890cc65a71efc68fdcdf1a023505ef0bc0e6b12dca5860fcf1c6c94c2e2ec3a72b8a019d69c82d36a73738dc3d17d7fdfe992bc8e18cb5d3437f1f619dd318b95d1a56b6d273ed79ab2655d83e2dd63cb6f1f5987eab6bb21a7b13b84e2c619b36b842192c3f82c755d8af840675b0bd67a655d641b1886c3c9c147ac87615ff3e58085a879b21dd63c1616a3712279ec87d650a2eed665b797ad631f0ec312f343979cbc49b99385cfa92841cba12d52777df565545a1deb07800a15431c0987b4a543fd5ed6832e80ab6f4b4d9c9ec419932a6ded4759f5c7630a0b80139234b8d53117acb4452c60b477ad50157169a89bd796e2308baa9395b513a94747611c7978c82dbdf48d716c3ac181ac2b2a4702c02a324bd4c5e089d989d020ebec9963b5c721a95492158f54973b7fc1828181acb3cc8078ac095136d97221c60b847bd2a52427383ab68cd1f10b92738c13203fdfa0b78baa09c1837be2498667c459",
+ "0ce980442336d0f427db869a6799baa6785b5e030567c588e2a7d2680e96c11b7f415fa27730969e0b1c3973b5f3192d4e773153def6dcc09dae29ac44eac7c42c2666a356fd4262197bd5cf6eeefcbd662d104423ec05c19a2e6ddf1834a3445a09e8b1062a1320a5e8ef13d6ebd03c19e1813ccd86fd68b46a",
+ "1ac8a509db7bf4acb80d8d394a5abf47c273b2093f50f35049e749f3e16cb0fb",
+ "47cc9eea11f9f3f9aafa23bd",
+ "088888333340b3a057b05491fb2402301c8654948aa6d5ee1ec75eb045858c22056fef0873d6675f897126052923a47a30675b266ffb6181cbd29ce2da3720e36a227e4c6e53328d789913c0d9cd149a6e49293996b1be7d6c513b24d876445a950e723ade3efc36907c840b9b8cfdb1503811b4044d931a0009b381fd60a5bf1e73d16348cb57eea672709875fb9d56908dbc729d5d7d322a17a41d0f62c9af9a013ab1e19fb7b6c6e7fa0c0b18bec5e3d3e92546c77e3753193389e5fcdb6a6a1896cba461343e71ef7a156b136b27ae6f45be9368301cfade203e9b53824d70f07de9abfea1968b8ff8489b9804422ba05ac3c3adf23ba0848817fa51febab5e9b5500100310479e710b663f064c1ef101c9a5320367cd8bc6e52081a32f070e7d3fd6f4210cdffdb9fcab1de4af5b06a7c6d191dcc12b25b3053e58952bfd1f723afbf570796946c1df9579ad14ea9c8c30389c1de4d1e845c764fec5eb8faaf4c558c5eb5113018c6a21ef653ac7d7f5b6c7e1a8fd48c6f423e9913436202da176a86731287db7331db055508acc94168888040ee37b3c119c8a0d88360241d68745825fe480324a944d56e7cd0375d4d33a5fe7a3863c2aaa899b2d24f65b70bd804039116fe959c32442c9f0b5470463523eb4336985b71125fe5235cbca0c88a6f92416d038e144de5ff8ef6ca749a9e239f02db505bff8e16fad1cba8b1500445f067a674142b6413e9dc0f432242d8301879bfc11fa86d1ac9992ab12319fea8b703e10a13bfd4b017496222be26b56af3ef67610f904f0ca8a3e7cc249ca8122735a542b289f13922904ff23dd197f8883c7ac77150d7331316ef94e0cf13b6ad95070420513599100b0a6d117640b781c622ed7ef7ead29476b3c835bd9dbda2203930bcee7ac01c3b9c89da405ee436ee652ddcc3e96c7f1a94e200eec9a4a226f3cf7ae5725068916e73b61149497d11dd85157f895669f51978d1bea8fd2afabb18d082365daba2682ef623109988b7d0e27ae57bc14d86603f93b5ac040ae52d8db404ee27e6c34cd4246f40eccf9d3f8637a4615a4006918b01d34709bcbebd02ea72958d54db3e87d69e6d783de2f1841029d6975eb11f9b076c247108797d5368c656f888092b82aa81aa26e164e038b359bd68801c22fc107e4083a9d85fc254b002ece9d4545310b0cb22ec1af04a7ee31d210ede4b605dbdbcb70e4301989422ef46edf63f9c96de9cb3f70638b51df5c0abe79b7af8cd97148f2b7bf394bea0f7bbbf6925f83b901b87a6079f2c3b38a98fe1a86dc7f48bf97553701834f557451df4b41e7db984a34432823585380b45c1b84813d6aa21107cae252923fb4673cf660a541e65610ac0127d238285f53bf329b62169f3e42d5efe268dea62578e97da59a58a1314a1bd46cf7a7cae772814130b51411082e30062fdbda1c9e14d6b2bfff89d0379d32461f3b8e833b105f6a89532ae748b5fb43f283fc86450404e8befb8442b65e338aa0408303a70e9c27a1d923d9f2a06e7c6159c50bf2e3ba5b035420ecbd9d0b5fae478eb1ab72fa714f99d00188bb10e60380fa3a3a318c2d359ea3805c2fa0dde17ee52a504f70d6b466bd38d1dd4196be336a9ab4a9e573d1bc6404018a119f688c1dc2a8ed1433e8a8ebf455ce3808c245f0220f0c12d28c771757763bd111ab829294e2429a6f7a59858dfa1fe0b806e986d40aaff934589fefd75ab91097a979f26bc9352267efb2d82c4738e4e6c451b0d5adc398f546c646b9e6b8fc84e91651a1252d5b805a857c7798d102d1e6f90749252bc53588348ecec0897c79f514442fe3b27608c95d0cba999a7e0fbd7f601689b4dc63ecb9ff553ff12eca3e9b26e3eccbde28770bb6aff7c864ad6be77fc09f81f90df6efd0c4025d0916ab5197ab846dfe6121c462761d9cc87112ebbca197b0a222fd34a15b824b7eda06a56a6ffda760fae5f0b527e2798f01e205a3f47947a4bd190f6abfb1dab2e3a53131af95d593bb57e4f4af506440cf20636d9fccc449d9565bf43dec8b6877337ca5a43900c1dc600c877b290342914e909aad8c5f0755bc25652781535c057ed5ab2ff8ad4322a8edf3fc1b5311dae6361a7395919725f4cd87ce0ccba37c64eb3618f9c5a53644ada569b90cd07184fc048f1b589eb29852909e75e7116ef96a268ea85c2bd257cefdde9222d7eda875a2a3abcd3a02a1fb470ba967b20beb54914b8b0c6ed464ba978088d7f8b30d098966b0bde82a8f1210f5d0c3405c9bc73f703134d0b6ee13326f65fa0b8154f4e30808997d4afbd060285942ca1dededc3410a099881492b5730ab7bdc2a4cfd0068f67766d60b5d4945f121459d2083334ac878d067bef644b9ee427bbbd6c9351d7b019bfc051c05ac301ff3792a1c687546dbf6a07a0cf56717374bfa1191c22b7753f6ae02392f8aac9207d1ad0fcd57c5c8b35817574b7dd90a00cab75f508f8a234eabce6618305f94746cb6a8573389d336bb67e1b0d2b6e9bd3959ef344e1eb245b522c35222813b8c6e82df48987436b5592025e9786ca63b6d1a064223bfacf59ada713c2a3116611393aa8446ea79b3cb21e96d13b659ada2d6524686fd46ec66c1b4d8f5ae7831840c9e3db64d528f83a1cef1e0a586a783f8306cb261ed9c2905493e74d35883fcb39cfc5745c282104cc3ce804999231d13e1bc6f2c022f05999fb57575bbdaf00d7a990e17dd2f8b9dfe66a637b42f58ee49ba60f2dd9718d09d7025b6061b2087bc35f0a8c884f5b67a5e18c2b4e857d3b48b79dc7cab6b72f572d22987566238a7153ed6264578424f1ce091fd05b7f14563fe12c76104d3373367af3ed3aca694a21127b5912c0b7eb1ddf9d4a9f03f660d49f7a7f0fb42797fd112414c3eba2b75a04282dcb9645191fd3dbe376e7f60ab40bb7ca1e991053a1912854a68d7dcf854201d1f2c26c6cfaea32e29d80847e6288274713d2ca973b91dab97884326b280c6f06c65b8fd25d314be29139961051a1d8699467d02b67991baabc9b05629660c243ca3b0477362d5e6bf9eaa33beeb52cf399846c77fcae11a89cbfdb2058e443ddd44fe202a3ba5c2efce937d78b9639781b8b2b99077b433189cf3b0733ed73b59bb194c9a98c5aa0cba6e71d1c5522f193defb9e31fd2cd60f22bedaf7008c2fb0b55a8dd52731dfa2bc69b40f835ae95db040cda6a4a1588a5ba4769edfeb7369c1e9a3b1cda293255b4942881d94d771b7b82460004875e71be64c582f2830c5e80dd6de421a311c5852f4912bea1451b0328d01c7029867cf9af99284cdfc1e1f0aa0d8c19ba9bc035dc270b45724247137da5d3fc4daa09e7014fe1439889968eb23fe124f067825d5f7b304f17a983580e009e0e51630ea0006dbc74a30b512cd9eb4d0b315a0ffdbfb581609ea9661b0007cd234ce43c17c92269a7519bfe99c2ca94b5cd3e7654946e67b37d4270a369266db6804336a446022677a024d44cc02cb04108292dc12f790578a0d61cb6fada738902eed3afdf1850bafcb279f18b5798d7466752c6368a594533baff5dbd17974638ecc41753b184845206c79bbab84dfef148eb7f1390f8cb7346a14c88caf540c241cad11ce8869be3bec85d029ef490fc5edacf94fa962be39a33c8efefcbb6b43960d5bc35f8fb72038af3801466aed141b50e9ac7dcf1921f7a6abaf320ff02ac34bbfac265e05e27495e6e027e673a48a874e6f0c33827a050fa21c2efa789c1e3df2ecda95fc52ca7be35dbf17ff6c73f37cb236e5131542e002913d177ffb21ac450e2542e24b894650007c36c52d90f83731009a7c3239ccf11829cf0fb6510d9924e927f14d6a06f8dc772fc9b028a8bbd2d3388985f3e2609abbd08434c46642b97240c9380a831bbafdc5db77be63a1400cc9a4f7362a689b07a77162022c6ba7a1bb9f0446a0b6b460ebdd9111132694fa5f1b29da39be66c5179849ae9720b2da0a012d4bdfd1b18b8fbef0d5c32b92c351dcf2c599f069c3b53f622fc8e904f27584b2d97d43f779abcde6dc1413c0a677dd187b28cfbcf7fa6316f0967b53977432d45944ce8ebd2e265c0bf6b2870c75ae808fed52aa35421ef55667ecd6f9d279c9b91c9314bd9411bce267d6ad52b1d910b3e65147c3eb6021a0af98707408e66bb11ca5abf5e34b2bc85b144fd06ea56f5d7f8939fe0cfa4862e7f306de069cf85f4aa7aa97c6848594f5a6dbcc718d2af77497f4b9d5ffa217fc301127071e9bc9c2c9222ba90e286506e384f321e622f05d81c114953d0f7e9626b74f4a6bea8cfb86ceb4575e5cf4fb84e9efac8291d1f4153ad3cd9a34ce0ffcfbe30b6829c0f986a4f85d63b602ab99ff3934b1e0c46e55d56eb479b79ca0729beb59aed783e9a3ccd55db8d884733dbd93f9fd7a7209fb92fcc49826b2d4356ca676f01b0981637897b3d2f90f37bfd73b214a398a8e4e2f9e5abec01d8192ca690191255dd8304a2d95a69331288bce00385f462e942f4d694dc3560a263c8ac2b5cd1d2c63b90ec67c32eaf5bd947bd8ac730da9c09ebc6888b0b4f3bead157aa9d31c2802df8ff0e4d69b7abfed6f184bf35a16ffb5677ddfc4682322128932d57fe4c32f21e190e1147d8e673ae407b1dbbca31331310b299e9f3db08ebfd2dad3158562c2e47addcbcc831cef0194ac8ba9778d0103c2955c886d439967bf788eae688f2a7459b0ef3bd16808e8d768b8962a24588d918ceb2cd1cd611b504019f65216beca212f44600cb7fac77216b7645c49f18064a3acdc01399315084dc9ea151ee28534fb31628d190bc540ac6b6aba572ba51aee89544015e6fbca2b3c2330f2ac1f68849e99e1a1f7f523599eaee22720392ea52259e26f1101614d4edae481b3783af4e99082d75dcca549049290731bbadd1ec0a93789ad5c9afe8bae44e35b3e59e562362964",
+ },
+ {
+ "0410d1f8bc890649c250a3819766f4496f339a6384e34acdd72b3a87266edd2a7eae223a372883f978277a108d6e59fca1f35f25d7a9f3aed42d35fa9b12241ac04754f76fd8f0e8ff6af88cd851887a45e89f1c9192ca66bfff605b128575d2ccc9ca3ba1ba23a0251b2cfd6db577b29d17ce2ea998946997f5c4a97a397c46024681a400a54425c071232d269adfc3b1adf15b4586c4dd7b8886f5c1023bc348bc674961ac6e221d914f432c2f06dddcf738227dfcfff88485ed45882809d0e57019461c88683919b87c45e78223c37a5be5f758e4f0dc6add22f2062bc2eb9bdc31b8649af17d526ec339f0e6fc6a41e26299c65276302f982235c3e5205ec1521625ec08a23e766577664b73d18d5533261c859c4cb4346feaf7540a56155c6c3a4874dc86ea42fd518d71221ac65541e2dadd2f8e129e7809f2835f07dfcc4128401dae2b5fac7ced1d9e07e3f348c6cd26f55b3893d4418557a18c366dcd5eadea0dd84ab95437d6f23eb9e5877fb2ad740ee507e2268c39c7186f34e5cee2d0dbba1a940f516a018f23e716a399c317a7a81f89cfabc296c432cba900ad79db67936f76e4d97874fc5f8a9ff84eb7a0f6d629c581ec5c451e27ef1ed468f93bfc68b2e0412a543d89dfdd812d9421236a4be9eb374531556c207340886c7b84d42d651557b952e0982f62c5c383e92dced21905174a5a836acdc3f2393e770d6cdc22c39575a42ea406f36889dc9558aeae5dc5f8b84862850b55bf4accccb6a8ef793d641d6b08235f70ad3b0605eab462afad1af80fa003645f4d302b03d81a7d167e9a8187bee0f76b1cfd7006b2d2b55fedad6e8db1d3ecfe031702dc327ff2b0197337d7542f42702cb276de852b3d72d9acff8a7feb8882028a5e340950e523c41cfa184b3d8878effe56742994e60240e58cbfd01541d39fa007a9f0ecccb409c6cc540354ccf35223677cb74e7ef7330bb60420f7d7bf97de6888cb343cd4fb0928fe5df5f1b018592ccfa7aac6dab57cded573b5950b94fd935f32cf332dd85b2b36501de6687612371dbcfdf77279d647ed8bdcf81fda8b7e0c5ab139330d64695d814fc6f761fd141dfb0c8f74e2d7616db3598d8de40b993fbdd272ca37db27b82aedb08bebc4a8e6d0385ab20fbc20c215ad50fab8e93975bcab3ff38667abb0545b3b3f20e325f01b80a32a3cc3ed51703d4b2826849ee22fddd5b544816599dca0d8fc84feed9f7e90caba53b70bc3f457eb1adb89fd0b67d2c0ab53264430c61d2c4a1b19ea99a9b453fc6b5ebf5fb5ab799134769c9b495c479c828bcc49a8f993c3127d5cbc31afb89c0e78fbc323755457ebf0f3344d3ad1cfc59d186e96ac31a9298e655b3d1df74b95f30fb868631053540388a13d597002f689708d35a2365e309bb96db8b1b94ea4c8060c2b165f7f19e72056409159371ac9c44f6bfaad9b9567094d18c29bbc8aa2c8b5b82735d20f55284fe68186004b4a4fb644fd52d9645b277c1dc238a764005c1d2791ef36e71786cd990ccee4571d9a9b1aec757e479cfa645e320bc33268e05af9cf90e0e616ae7f237c637a99fe15b4ea8a3232262d96855fa248920a28ec03f77ce4dd93925db60ec030a7be455ba9d08edbf6bb717b1a13c3ac1deb9821e21505c0a8971d5ea5dd8e4c9cd3a845a336209af191150ba5d9b8c2c450e3a765e8670d7f846b2461f971fdcd1942704f620a40f4204b99f9035bbd543f64b927cbc7a74f32cbb12c3caef955f169a45374e4479430e08d333c4a877baf41a27a0849ca3a157b6651295fa71ac94b6e3d30b5d160965e93d2a81b4d575cefd264399c9e4e17059f4064465b2d92c96ac27e3b221499b5e642d033992c236b905c072faa1e34495f9890bac6228330e4016c061605bbfc478c30e1b8534c49af54785972aca2d144328b0a540e3b3810a73e26acfa22f48652d53ea521875475ffade8ab50b9f08245fad753350f63dc4e898948ac7dcefe520ca47394f8e993a6d13ff68a2f78cf294f235f5f863bad10c4f5bc41c3ba93cf5e076357f0f7fdc136f34b656b1b8ebb3eed1ac429c7d4edbc902f7f4bc24ea9c9b200b9a9fd7adff0c6445ce1d2171fc031e3e9f8b8d6b448053393c8813d91333d4bdc3bc5bb2b8bff876cd29e8b92cf6f7bc727517b6f57ae031f3040b0637dfb40b8c1fbe44cfb6bb9cd0a445fd9b3daa1da2b1c4a82cb4da1fb8d525e0a4d9ec30e9aa75b951214621c58c1f60c9b97e6c6b330497e7dea790a3cd8158a76d898107ff3a5910707ae60c8a46c633b522aee83736d005de60b9abe202435f8bc4577b0eb08b7f2b617bb5a831e95d6488459bbf15919d764b39684d7cb7c9310f343fbfcfbeeb212a90d96c7a26c1026c5cb171ee4ef839785076e5084026077455c73404a2653f333e9bad555cafc1a9613387a02bb1287c380d7478238bec8943208de585bd18b448b6099565cb3ec70ec6672a778fa6af9d1b17b0970439da24c7bfaa74c85ecd8e5852e42391ab2258024ccf91e37f2f0e86df958b197fafd12f4a45f7990375f1665a14f7f5374ff7740f89677ea8660587fb80916b30629a7aa88213bbf80512421a0a37414a2eb549b81cc85072cdd87e4e69d97ecc63f974e60d20de0233101c3d475d777602b12e2f797e9237570085b0e9f48d4dedf233eb1301ed4621f9736946eadf599bfd79157c0b4cc31bc273f5c6f133a4e3679ff6797d3c9b76aff4bd8ad40726c1703c3d8b78f0974b748d0265b0a75928374f91b48c2d2b2c11d8b6e5efddb75009e4db72e562be59efb0bfa06808c89f585a43d4776ef08947a77f277526777f0b52f1e0b5a03aa560fa45c8f30e584b58ac1fc00b104942b7b86a3cdee1abea349dcaea4e058faeffc567e2c3b03e1c5c4ddc675e25aa15de1442bcf5ee972a8c5204ca5794694759c13a2d716839dda61635043bdf1a09e35cb6d93b4df3b7a00871f79cdb4ee69c79041dd14deb7754107b8fef8589d2d240ac1d8eafc52ea847263512651bbede2fccaf6da816b1b892319817bb6af9fc17078ab6cca95f03cf8426249fd4f2bf91921d39b8cee24af07a52bbe54ca7fc4422a310dbf2149b763ac0060fb2c59154d2cb0da1ad4892279b4e0ce7f5f92c189c3ce48e518ff48c4ffa9bf2b02d4792f84534958dc6bd2914ba010aa32d133f6a07bdbb87a237c7acc3ba5cf101efe947147ed4eb3bfdffe5fefa991c0dc8760586218d286944c52d0f221e0101f74826761d01a20af187f9ec1115e9e98bff6fbd7c8816c15d33c07f51c171490997bf269951218ae92b66fa3150d3bd40336abccb717e18b53e8806fff94009910f202a5041b5396d1c339e6d075bad4ab66a0637d81eed1696e4068024001123204b8371f0bcdf0ce07d79f7c917327f7138a75947846fde68665e9c767fbf96bb3308abffe7a8d05512c81e39fa8dab2334f46ab9543921ca97be31076dc7b2a0d05e90b7f7610d1a391b442398ef56cde3b18737faa8f282572389b4fb3c55cb8ae6737257708c808bc0a414bffae293bc69cba702ce2959e1a30edcdf64985a4b0bcc927c5912f819c71cc9b1ff5d6e5929055be72ea5c8c1a4a591093deb5449b7e6b60109be1ac0cae472ba31e1035ae65f3214f50ad699a077a2de52f7180addde0bd78c2698470b1af13cfbf497d243c9e738c4cdc265356543885c5b933a299f01a5b5a9ecb0b4ddfda0c28573064f6a3f142801795d66bcd5c31868fd3207fee7bd98c47e4da26bee64e1617b20cbaa34e3abbe31126b06d5737fc2b577b19d255a519397f3ff8668d0e7d401a37e368729e4b83c5fbf01c32ec478967605cbc0675f685b5eeeb42fc688216a0667e1204c995c9c485e6f7712d80d88edc9594528b1907790549756dcc8b0d32091f36d2b4009639e68daa130e83a1ea18353ca34f431c548d91c1591ccf8b25eec1f7a3c18ddca71b87bb290a5c13229250c5e193e1352072f6798ec504b3b4c6aa578737332f52baea7bc4468fe6d8dfabb9728cee93fee50c8caa113f5ed7e9b55e21e98d73a377ef68be7e4e965dfa50cf863e6285236f11ce80512c573ae2b55bcb43cf6ebabed6783c250f991f5f68a59dcb2ac13a3c8fba8dbb11c79dc6236809f2d7c4b0ad3cecd24b85f1aaed9748b8c109f2fd98ac8a53bd52f18475598d67305117de8e03b0d988a2847539cc2efad520f86dcd82c08ad4b10e490b9cb03bedc7197bcaca55526cd9c8a5a5f69f7a1697e7e31aa76eee597c386418e89f06b0b9817a83d6cdefaf9594548b33cea1cbb585e55df3d3b66f0b1a88f4b98ea4720f1ef5e6ebe4958078ea0bacb8ad776e325ccb252f81943b9b1c2f54aad3c7baf1bca0dda1355d191f69c5d8163c464898116dc89201032d1e3281c8054882f60522d3a65831bf779a854fb0c195f85aa66522386625658457e74d5c2fcf5234f226da4a579ac1f11f11a1e0a6993a4dfe5c856481ebe9d8d2363401058736f7ad104104aa03f5c91496aaba2fe4072d418d91c2787a9b4ab0cf4bb65681ad0392ef073cf2fc060692b0c0c194c8eed5558098cdfa3317ab02626159e40e5c76fd64b2ef60b8f5f368b6b4fd7ea3d2d3236aa01d9db7c8a01929f9fd38557335b926251ade1a0d47d0c1444e6416218781c1a51e786dbe9297b78fcf0d0304c62929e00744ed4e14af926313a9849b2a464048bead075044bee013cbe318920c4172138560629a0ff4fd229d81bdc7c7fd1086ab17d6efd5b603a1991b33a55ca5b9e2051b7c140f7937adfaf474c2f284489d9b1e8c71d58f126eaa451407eacde9f0e86504f7de3ba4d830199a229de2bf39014baad6dbbc448501588ceb2575db0ddae005b81ba9914bc22b6d600e2c990f7843e553ff29d8008265eba7dac7b5b5a7ba6dc263fe0e262a7b8638a81f4720622c7361554b61d7b04c7f8b133440baeead7d51ac8b77d606fd0eae1c55ce7e8141dfd68d40ae3d8d2dc8a061085b4fb6d8a06263183869154618329be6b01c2890f2b5d0a0f25dcdbbfe2ec3597d79311edb943613fd4b59157df4fc2e1024be03d98ea3cbec7186ea9f4a431dc3743b9f0871b205bc0c1b3a001768",
+ "113b261414b4b7dfa028668ac8b0cde5734120124991c54f4dd16a87d181efe2bc15f6d0caaeaf6ad615f59ec5c2833904a34b4d34109c82e10609b387f995430e8c13d83ac34310d838af9efa32d7fed6224c0a33",
+ "cd762390b93369f1e207eb15deeaeb0036f5331e82480d180f84a76c3e44550b",
+ "e88c14ef96c7768f5dba9de9",
+ "8d6aaa27892a76fb05a2e96cef9a9b4b7ae0670a12cff95f7b076372456889fbd3b9b4fb5fd98b3bd85b247f15009be2f4e7a0329dd118b6872199b314e159618ede0381dd97db28743461ace1a694c0383d8458150a501d6c45f4b50d5b1bd47e61a51f9ed4929bf2e564f201ed0e6825170027d93e482c1ce268459d2f81cab41f0e7ff281430c16b34a29b5c76630dba72ab9e751bae41122b26121d91f2af271a23e818263f46e05fdd52f319d58330bcabf66637a368c0a8aeeb20cad1916d966e5e0b0de74cc67ebe57e3d1fe01e9743d42a931cb4b98bb762ea43ab937d1e5c42eb08fd56e70e911bdcc1ca4ca0604a329c5364b262ce2de282b4732ea657b89300cc7b7127ba4a2d08c13f581f024fd093ac09c2bc245be60c80e102405597fa8082f4d28cc954a93217edffaba3d2a397bb59ee89c8cc0f33eded78f21183bd1acdce64a923dd609a0620d2911f61e81fb2c8ccad8ad9d81157223253a121ea2bc60d6a3670c563fe06bd75688572b3be83cd31dfeac6b17cf8455267b481219c42034b2252977f32b8e6588fb05166498fa37d17c2b002a655b5711bbc21175348225fdcca041b1f97fae48fb1e222c5bb46b5202191c00666b7e1b2d84aca3edbee7a97dc0f6d1330e929226f8a76c155e973c1ab62c867e1f87be37788754e51825ba31af9f4722b5782ef782fbb70c391a664f252d14e49a805e94790135ff6bd881a687f98b42da96fd34bf240eae4914488af739ec15f13f048a7eb5fa94af14e8b6ac5fae714cbef6268b114813ca2a3920a7a9d5eb506a2ca211758de292047eefdb5a97e18530dcd8410495fc42abed91b1204d9b8ba9d6aed11d2d0fa0d931d46f93f2c1a560ef9f5f7cee1497be770d3cb07c534215cec12c1458bb57aab4d95cf4a15a5e3a3bf8e650206d5cac4af3193d169f1a57638d9a50f6b7c6985d42f7138b9226451670d7359351c2affbca65680557693d03458341198b8e13d0ea6abb7496edea3cd4dee2eb93695e668c7c0901c6809b8ef434e88b85a8b22cab6508b9560fae62900056b7c5c29a8c899bed45a2b5159a1d4929476ef350101317f77f02d48a039cf4cf01c56319cbba16fe908c49ed6f3face88867c0ad3703452baa7b86fe58a00ab8f740b4e8055164b0385dd3fa44502ffbb99cdd843bc3287ea468aafe4cc298a3fc180f284dbf78aa09e0a2f7d8593356eab016ad8dc505420edd376b66598a3d0aaa848fd68c4e07419b8b50e40febe2b6b17ad07726fae1f87e86abd01490a0ce24fb57b533c765504ee0a9ca154187bcf5e6828e3addc7597532643cfd992558d63b1acd00e7aa41b9765094217480c08c43f4f0b3f0127120699b7f2a5ac07c655b6143e467777cdad4bc21d4b57da4d8f9b9a7e4523d8c6fba3614b7f7281e80ff0f9004577adcff1b79fe443c80ca9655ecc102d5df6aab2ff6c3401f344b77666c59ac7d5b92bf4f1e2322f74b75e6ef2bf43ad9e018f164ae76a91451e5221bdf5b65a4fbbaa8dc31e6063b451edbbf4965307f8e65bfae87b15f2453083bea8484017228a9cdc6edab1a28834eed8ce07430f776b916b3bdd2340798955ce9ffcf114c3f6a88bcc4c7b6f2e3842426488c340d00f2c4d2d6fd3b6263dcf7a57f5cea6c77efba7013297bd3320accf033acc0833aaa8e8f95cecba469704214f54a1ed581349878a591f9993371f1daf92e55b2a4faf8f952cf785c687a59b3c258daef1b6d7bf9f904123c7384a859933c3ac31e33edf648a1be4d6264ffade860915bd118f0b9aaec2eb8e16b2015fc25e68caac77a3accea53b9b178f6cf48d15029fac12963b4277df037b7a494cb29b1d9e6d2148531a1f7360519cba5657c080254f130a1cc3ccaadb4298d7ea0223897e63d798b4f4909577cf9b491a82de0275a246bb1211bc4144574c8ef176b382262c0e087975cbef33cc616d32e0131a9efdbe8ad3d9cb5f935d3f4f409852acca22ae2a6e7450e9a426ec3b9183f93b4b7f89d850e1c7053c661936e0cde23e831a261b319b430da45772f0fc0113679d06f025983bbf37ecfba35eeca28de5ff4815a490570491266e92faaf8d0ad4ac8df106faff8fe3c8d050ae9dfc03a01ad177c21d7b653509a80369a668a97eaa532dc9867c32aebaf89ed36586e1ebbe1045347766a354a86ec1e8b2f30c8fdfbb6c5d549e7a84db81b73fb828499c5c4be0d4b2b7ffb197133a0ee18abb5a4e371be0ec0a6535507029316f8decde30833ca47493ffcab781d028edfb91c138609baf1054ad52a5d8ccb98b3ca5b138f253d99bd556afd80f71b39f36e0d96fba4e0cbdb18926894968aa825392f12d98b6497ff85a0e4a91c97f37ba1dcad30fe688b54008b925805104a61dc22b712685202ecdb073fad9b10b5b9ee2ff781f23fd41ecdec87f85b369a304b85bd2af126d08f79d8a9e2bff0b18607a95c4efe35941c5493c94e3f2f3902e79f4cfe84c138b83c7f32d7c5a125b28c6107921e8ac92f1af7da015b46a2f9169369cede770292eee8a5f40d080ea1c267c33cb7d4187093d486dc3911bb2d6cae036cb508e81ca783ab5e95cec751e39f3038003081a252eefa7cd913baf136d4e27076251da9cbf0c7d2586fe02b62ec786790ef08fb3ff3d79bd06868eb1abd9875920e14fccf6dc144e898f578b7295fb5f4e84cbf683722ce3597aafe3195e194736fc317ed03ebbb00d956ce89f7a41a334020e1a88da355d3b47d5bd3965a290f6fbf5dfdc8c8e6347b4eb85151e53a960311582235f3b546ca80a670dcb628fef572dfae0c101bc08c80f78d5630a793bdfe402592c316227f2333b386839a67e6ee8d9396fabc9648ea656a407670efaf80966034958f4a70fe7b920c79dea3d5a0ff05f3ed0516537d51a686efcb258520936fdd415345251c9ac1143a41be295cf12da5d4319e78e1c57ce20507490e5213ca7be92afca8ec8b6a07b33571afe6940daa2afb0dd4dcc1c329474ff8e13d740488e5ced552074fff695a04fc1b70755245895a1e9c387fd9514261dbb0f600ae03f4896e795d1e72f421d8572543243d662f6811eb9402b6a3b8dbb0f32de95bb1ac01b1287663d3b6a3f52339a4f6b27789e15519b2b59f2f4fc8fd33ad1a6e4d02cf0ddf8499f45746da424ee78e72847e3cd3833551b6e6fd6b1aa98c688252b57a1d97660ff006ea1b970a0b8fc7d2e313ffd0b0b85299ded47b60cd2fe9bdd7ebace4b0c1072cdf67231a475045990b35ec761e1dc1dfbd0c402296566eb4b9462979d33c9d652a9295ae70943f38adb212b48bd8ebe82722b1712ab6a3be6060297e2aa54e7d0158e4aba6975237e7c7a1e22b29560b8d262125ff2a6e5c1332acd0f6b5ba15b4a82d3631891a01530321830aa8f2e8ab6b41bc5b5356957a4d0c3bc3eab04df7700305a95d0f9cd18d486c675c963876b25b1a0f78e245deb40dedd14dafdaa9d614fb06eb2538c5411e13be116c76fbd3377ff212eb07c5c035612e4cd7a1de2ceafe95832eff88a9bdb3595cc19287fa40b8d244afe9bd24dca40db49893602a59640d7a1b8e7475825b09cb0cee111864deba9d3d1beac03664279910accb9fac534ef099e398d7f6e3235cef7685fd1ae46e47da093135741894273c0c3486197c26057044b10faa57244721328b47e611633d16d3e4776d90309d68ce4a60d3ecda26c9f39c1c6da67ff79fde4977efc5653d79ad86c3b53090003bb72e78aeedcf4c8107185d9aa65221df4e2104640a1a083845c01000370371fea2a6bc8ae43fbe290949da4e559d3867c16df16b143fdc807616f51ebce8d05bb03c2b0bd587b95e3f6a15d907aa9a5b11622ddf4c81ff9fda4bb49d3e9577551bae649cf64ac0cfd646b02f6f16cdefde09a55e77afd16c74e8a3d777d80b7cc42c51f618a3c467968631119f11ca4385f0f5713e37ab1133b692de475db1d44fbfe9d274b9a09e673dac88aea74ba88cde8db3c831e9b5a0f1e40261281e5aea9d4dfd48c5d9e173f4d9cd56fe7fd610909c838bcbe1d6c729e151ecb4caef511a36a14b03cca7ec5d0feacb4647ea5212a11d18cbcbedf78443127680ac0b1bb65120b4197570288226830e2a92b380e32387bbcd3be2c77d6c7722054d849be9de459cc1832ec3ac8e7f60fba9c81cf5fbad37d228eba137a23227d56cd24970340f2b7599aada9d2424cdba8b50c2b97244dc83f7391e2ceba5bc0a11ba547c142126c791265b33a3db6238321a5f3273ffb01e42adee17b898153e41818b91413ec4f6386ab3dd48db875afe659db9eac94d16f850ac179d087d93784d607349e8711f5f96fd514e8d096de8b4a74122ba914520e93a11fa4adf006700e122e2531e1f39340cccbab4862708d69c117d3efbebabc14a0231916ae1ee8285727c9fc980051360346d53dfc76aa5a11fb1fc8f36f95f741e913bd2cd1031e508b320abd2d3a62baa400dc439969eb44e6abf8223b29d4025c3d1ca08d2dbdbbf9927c625270543e8c0cb5ac5bb5d504d224e66a1895719e4f975d819a95e54cecfa59ec8e385aaacbb023772fdddbe093afaf5a75e63a62d51926254e5b47da1e9b05851196644b9180734d05810dcf3502747c4ece652b67674c02aae74f20d07de2ad5993b3a68d10207eab6be5be34e52ada655aa96c1d82df9b24c2acec35e8f0bec9131c20d0ad8936880af87215611b80d07d7a741a12d8145bd05066c6ac171afd8684b92f72237bb0e4ca4aec1ec280e39f36928852d5d8d02fe463acbad8ecefc103083fd4298f399bb254e7bfa166638460b760ccf2b0f5fec0e3875206bdc8ce096274643824acfad71ba06441c74788356caebdd2208f6f077b056fa9d85aa4357e93bf064a776f5f3b0f288d0afdc51558c8f25cbee17247364c2bb24637dd69017f92bbb43024d9c773439626a02bd0cd44136a642c9c5ae593f32eada790c31a6704030f2e07f1173cbc0dabc410bf9864214c298a6283b3631acbf94b8371681ba81eed1aa81ccf258252d7f90fe733ac770b9744d0170cb554b39e6c72e05919cc237f8f4d7f3545f4d2732f4c9473c77401dcba04c0fd33efc73219f31c08dfab26abee9a7cd4ad3584730768fae899fc",
+ },
+ {
+ "9c73ac05648e0c50a3ea3a8eea70841e8e06669c1e7520c5e25e093769c4b005375c0a9cea16ec8e00261ceb96a00924a66fc0c4e4e089c63e93fea857aead8e0ab82af4ce1682cf3c9fbad23fc3f7e632b7aa169834ddd6c7db7e1e892cac93e4d787b2ed0a812aa93bfce8fef3ce30ab794743ad241974ff989288c43e1ba815a25a03acdc2d5517293e161d0c46c8858d0b32b124a6b0bc3838807753288cf6838fa25fbcf876e6368c0342d3cbc860d6fa12faa1c2b7d9fb37504e60dd44e36ce74229dfb80f1545125718dd1f78b31a8aadbb4d6494489ce596fcc2dbdf2ec22157a1d966b61e780d36552daf084739b602861a96ceb67b65b23d40916c02b2c3a38c2a59aaa266e1f8939000dac9b6dc50d1731e87ee833a2cc3cb98c57e5b680a85c1b428289520bb252096efd7723fa8e55d2fd4e16900a435986ab3f3d2bd799471a1bc07c1772ce10d1bb8805a6065b8903999f9393d2ed1a7e1c57a9e3e0e10dfca17a04143814f5f3acfb99a34712a6e0a24a7485279ef343e69d27c77e25b41f9fb833d7cd29cb6a15551d5c77b43d19feb19f2640926a272f81eeadb792bd474ae11f080ada72103f8f7ca733a9b1325b50589be2b2b3023491afec246d336f4e4277592ce9695c68d5f39c8fa4cedaf51776d7ca29ea0ecb89eaefe71e5f3560c68e8dafe7da08cdcd954d626418677b8f3f45b9194474a32f548a4da3bfae6a3e2c0a25f602e3b3a821160c397d77c8bcbd71c5f1e669213af36eeea30d48e12953071f55eac2fe0bd8fa355671fe032f6fc9214632428125a16fc8aea8a9c7fba0d7518b9a4f876349ccb9bbbabcdb2a85fc60b83ee1ddd041967efa4036e5e10e377c9886f40bc0b0b57c7b724795f843f6a072e87e532a04c21445090a360731a2afb896ab795750e5c2c33d58bb714f5be427ca3751df09661402604a09a1eca95a8344d3daa5b99d68e6e6245825704c5d4a73af197d052d7f75778917542261d77735a21cff3f75d6159a3e4b1a7a9854ee376e6b3c8bdaa1f353b957862b2efd50d10a40007026261a546124cef979ad20d8085d53e30f5736b8aebcd3cdaa349ea474af249ac53eef2653ae1fcd5b3095538de9368d307d45df2a19acd44e3b78c2da9d5d9fcc4cb61feac5dd35f66299845bc0018c3d476b6761083baf33a4621e41cfae0e0c642de729fb2d206db6a4b976a635b3fd911b5e9946fddceb6feb2d2f893b2bed590317442037a1d6dc5b5d72910160221cbecb53bc983f1c736c3bfc9757e9e05af1248b28d651f521af67b2a0d7e4bd86a0013338404fabac7b9833c372142e6338a98c0efb7130aae8e34bb0c80937680a7a904aba3be735d41af9462f17b967b13566bcb697579f8a9340429c77baa6e24ae1ac86d8d25ae3cb9112e34a7a948fd141367898c5f33c0635c87de06f603b510cb229df0d0d9a9e107de88b12686c539ed4fc54c8285afde0c8ee502919a125cbcaf4c8c89f56e90d3f641f97c07326956f7b5d87c65b689f39b8b84359ee0f14d2c7ed621ec67f5e2a8ee5faf21c805187edd95e3941ed62fa95a65473a569566d46b87c0d27ca37b6b022a8cca30a4480d392ba15701d1015b3648958cddfb614983211bffc4966ac6c1f691f19bd9fed405a02c06712d62a775f73353f3949c76b6b7757a4ee0410fd6d20071abfe46b09e72b70f9f19b61410ea67037e037934bbefaf09cff018a5c218176d165d1eb5cfd5c46eee7b82fe65ea02e3ed7b18a86ac7b139b7c9df79e1f6e6f85304ad22d97190c7ec12c651fcc835ea434d92ae1444e7cb0dc644efbc2ae70f2f94310805c1d0f2d49643d05e78baa1c54d4fd99137a49efde88dba1374c94208fb4a0ebc1a0090b043610ebc1bb08168ff5bf936ff9834e825eefb9ab73da2b287b06fa2b0ff52f46061b07c1131e4108cde478c767b749b696f3520acd8d3338842d53941282da289dd1e9a0e02aa9be0f127566c9bf2d50a27f6b6ffc9e9880bbfc14ce7eeee70cb0c0ad90fb474efa69b46123638e8405fdef65fa7e0e7b29fa8fe8696edf661f9003a08b4aff85a4a3e6d817655c1d533b834da981b8c37c38abd5977b3ba71b3f57967a471c2eeaf2f6f258431fbb7e92f91814b1db80ea775681f282290db170942bb7b04aa2a331950b74a4b6e337affb4c51c6cd4c4e13ce3095e73e4767c2731f72bdb225ff572163fbd8573378427fda194d165750d487f6bbb63e1378a132fb6ee5115e3c32b2380b096b735bdb4d651853bc7928346fe3ea9df7534f2a4eae1f5ffc4b82ae738db7df0103ba4e68c2a2153bca499bae2439a57778cfc616df16032aa8a19e26597d275d2775b5ea17cb25d204b18028eb25a053e5666ac47c6def151f7d4b68ea62c601d87bfbe04711c24bc34274be6815024d7b7d01e7dae10cea6e485348ab195a83854663cc5826181b688cc9c091dc1e0d491fe51400e20e6f2a51a7d56af258e038bcbc80e2c4ac4b41661bd33229d07b39b59f3aa79d99c1ef41974a33e02a7cacd6fd8f9b99cadd0fd6a031f070bd3a364c64ddda0e9fb94036f374171de0b3f4ee3380780e6d77d50db9d58e670fb4a364827d631226a3491a27602808141ce657ad6e560ad62b088ff086e6f03b8a64bdf7c7d01e7b19289279509a9d6d80e50aef3b05b5561e4556952c46d0b6ab8eae735eccee77e570e1360b7ea38c53ae6b8eb420e4c2663b57827228392db6e79105a47f7d89e06ecfebdd63783101d3bfb5f494785acfdfed41f8166faefdf0b49260222c4080ec2c6e4f949f41784f076ce37fc7a34fa4e547bb44e6b9359b4b95cd67d64e4402ac83973bd50f8adc7c6e4c34019bd8f6d3843bba3d7155890712e0ed5134e00db877398d86b459f312a6272431f01b057446bfb1b8053acf181bac79408c7708f3a0867a64e06d7786849bb874a6bdf8fd6daaa572d5648ae100f4318d6b3a811bb0fb709168e817ed83c0622a7e5b17ebf5cd5ecb21d9ac32ddddb039083144c93cb55a95ad72732132d54bb120639d1620ebd142b58d75835b35cc6367012c93c6772963e9ac852c71c0dda2246ab845469997fc170d8f62334bc5aa4ce23e036967674303ec6f75bd3d17d197d026de69beda70bc59d2ff95a899d28ac7e5e42f4d37233996a8e6d3b0b86b80df49ea8e145b4a6e3e39f3d6c3c6518bac45baf97cde23037709d737b242b8918ca31f90fe59ff2c83e2f347a954d3559a8e4f075c620ad36be20b1e24b3afa156cf3255192171ad0474e4adc9b7f35436325b92945665f038611e5d14bdfe7b7d20c09642323346a717f460dfe7b5062a0098be66febe9f5fccfc747aeaeff81ba08e5dd2b1a489c998ea9970afaf9aa03859073707a686c492fb3f7ddb27897ba5e75e578bd82114b2ba85525a2002927909c970a04035334b64b1169c3a923211e0999db8baa26b6537cdcf57c051c0ca1b317a5b66ad96cb5ebd57994f99ab202348d8ddeb343312f1f26ab2442b8c5f5cf6bab394418ef2fed68c3e60275e836027515b6b946e5d86d91fdaf49c2a5182d5051726840a156a8653cabda25e1dd9af693533d782caa09295952ebfe6a194fbc8bb7fc2c0da5914a506c6f31490928dc5d6554890f5eb268b09d671bb6b6d7416dd36e7b78ffc5c86b34fab43d22909a87e5239643d5fef373650e291be56b89b9d90431d8c9fa44fdf4f83a1689d59d6ef833b1ce31a44197b36ab298d53b51ae3f8387087dcb0571c340874c1524ba0d576bdb88101c1fc387d25b5c0dad0b4d309255ad5d5b1e209ba56db0c927bd209399a8a3b5c8663c9ac199a76ea4f49e364a4b93a569b3400e20f0d748adf7db46a07efc68e43802a5d1a914759eb2abe8fe3e8d67f2cd7612bd4d5a6a4535b1e5b3ad4d97e54f3db7f8512c9603d87e01160b6908d8df1b952c750071abb1565e5ea3f643f233faeb84278187ff0089150bf21ee4d13979fdae796f592ac5b88869aecc5be1c64665edc8ececc87502d36720b73859313607aaa561d56a195dd3c7292fa8f0750ddd3df9ca056fccd9d6ec900f45c1454c6ceaad4154c69e288dc85735b8cc42950a3c5f0fab2be8811779905c3ad5a9a6bf56e7141d863caa4e93e0065f229b695efb790926618b3eda1b9a15f143bbb09aa3c4b72900617793417df364185cc213d5cc3a375778117212266356e214f085d8a7aed908256c4aa25faebabc70ce913c08c89380da06920069e8e27dd867567f152f883a9bd2dcfb8097b7f065482d6d11c0edebc67feb3068cead403503c04b324885ce1a62c99af9808a5ec8b7cbd978b8c43e37b06e9f7e1ce0b31fa0fe52e8842002e6e99cdf69263d31de080b56c0cf94f77f0397fd1f77b13e17af90ff33b00119999df802c33534a13d3ff7fd0e8cf58e8f8c8bae033cec1aec7d191f2d1a39c7b731c97a67fd1ca43c13a24b9f97d92e2364dc26a1c9408d4659ac7373e53a2a1704a47e01c0223ed4c489735b62a27ec67ea46747e4f48d3da101b0863bda9d3f7f1b413f3e7f130208875e6a29dc30a78198ef658c7ca32d7d53b4b92e51f8ad6d39ecabb800adc0870b2ab0e85b5769f346ce7fc371ad40c561f9f3b2f2a01f2b8ccae48c78a41383cfc36b2a1bd41d61a39c24144965d9aa5ecc5d506c7c7cf9476085bf049942d35caefd77821ad925b7fd3a006213abc1e008114c848d45cbedcb8af264cdc5c07bc338fddd1123940e5d95717040325048439dccd1e298bead22b011ef76d26a390a68161b8bab29e8409a5880cca9c8104694e1282c9fd64f50e73ec6b9a9ffc31115de9cc0088400a2dc806f85487fcbdd60f409ffca584fb197156b40142e512a0dedea1571ebb74d6b26d3b4a59e9105929a055cf3540e8a6a79ca7ea71ba8b40893c9797e81c6e9a7999d4d382e52cac95727bcac354616ae1094552b3d0a33d0d3ac4e547237fc0cd54944039b0eccf335889f6aceb518de496e0986783c564be8a4a05bdc9c67b1e5abb480b98173ef091259d8c772b611e0c09758fceea3e59243406edfa71fc452d4450b55b8fa5ecb543692c6eda3a6ad3bfea929a18ebbe5ce2ac4754989c71dced37286cdd1512107e4e7f4878da1c28b4beb2dd9a712a8d1d61d1a5fe5382db8aab4857b05a783e98e77711c1933a7641fd43dc6e6e597bd03b11ce8e94aa094fe250f03cc92ed5b0a5e7723911e87b0f3c476d9aa0d96adbfb395a8fd353cfb5a4cfe27deeb82e849f90bdb17928b0a5702e4010f7aaece2d43772a78b325d2ff24f9de0f7bc65974d2348c64",
+ "bf96bbc17abcd1f56a9f22ad164d25ca72f8c996f1a7a66d6effe140336da4f20460b47e1c8573872496343be35a055552ceec437692b0e4919224c4ffc8b603286a8245eff5cc148b004f6e5a54c4ac22b0f09842a07cd332a09732694d3591b8b7d6a7ada2bb38a30aa7fd5e6baa811b9a195d3a96306d",
+ "aa2f714d3a184a9883f4199e8e33fbc9c92b36fff2d59f07a9d0d335d7476e81",
+ "36c79f9f14d431cc8c077439",
+ "873d0617c986dc9d83e9cdfc50b1f916626a9d9e1c595dc7ccd99d1e993d25d89b04a893c89e205952eef8f1733054bbb55fa5e1b07135787d4fcfae226737b50cafa2c11276e8708451be9b4d7f662e98ef6b705c5c4fc64588728eab1dfee22a0a92bae61828a7394977b0ae8a3b6d0126a23583fec025becf0a72a28891391ac1495732a7a4a1d43a63ed8eb37b280b6d886096fbc4f77aadbc5e441e996334d0e10cd7f3dbba9bb7efb147297986509a07735385c681e0543186dc166291edc3b4664f5c8ffb0965c85bc30ff5e7769a69609c69ebb68f35d104bafe3dbd3e2a40e13865f19bca3612e48592aa930eaee29440b4ebc1c0a59f1c54519857c929709b086bfddd6d4a30940b592be48e0067976099efe71f45f956182dbb300e8076e1207baa32d59c1afef7f34171bd66099d2d7f07b39d16d0f8b085185bf2554c6ad66bcd656f07979e8f19575a116f5c4fb9700ec3b46a3254f28afa1ed51348c1af6dba26fd398098a76d7bfa2ff195eebab41330ef290bf75205a2ee570a2fa46bbaa74aa6ba68a0e63e2731dc1974eb44794f3c89ba58cf96f7a070fcca678185711d97cd9d7d8202351ed589e0b05a7a190e60ae4aa109254a7bcf7013f8addd07a64145e21226795ff7c7b1c225f40ed7c3552da8eb18b9bc9bc70c2e7ecb10c8b20c54f04b6e27b5044a7a67b558407eb330f2083444375c022565c45fe817dc00c7d24c23db320d15949b0b64fbbaedd310e73e423fcebe6e1e98a5cd232d97e6466642e5e3b23f06525ac1cdf8688650cd366b1b7ba2a9033e62d836b14bb73717757b76b9673671bd3d3b2a56628f5a309f3b86ad32abac0590c50f7c5a22e0a920d88dc9fbcb3add08b900a2a2fae4178aa100a0e645ab428e0e79bd90baf4af2755e48262b64838a6fbc21226e323c0a1ba5703e30738fc7b5a7df9eabec6199df5ff6ad58f9df5a734ccd6509e53ecb3de1c881732e26e52ab848a0335b04b25f2254aaf8c130c78b0c9a40b60d402673ac7ec7311d0b00c45bd176bc73ad81c2478611804f59e3c145110aacce922e473ef346f8acaabdbb9f313dd3f8d0a937d0c048e5af789e2e09a816146f9ea28170909caf2572a2f6e2d0d511242909de2815e9ec586b2d12183ddbeb7dd70f32424097e2ec28b4ba62cf78f547e2057a4c050cccdf6b582172343742ec8c85e2847efb1595bccf89ece3b3ebba824d2f097b1987ec26c6e5710544739d54a714060fa91b7995cff0161415eaf55758078772c0271d9d282354e47a25b673eb11497a6ed8db82267d65ad47412300ed525af96f943c5336b1de88676dc346e7339230032463d305b0442f934018bdf0242768511d20474c6ecc82fd752c0c0ca5cee1f3e06e679fa5835540f97870d47ccc6bab233290be7a3bbd4a73f1dc7682049bf7b3cbfb6687479c18d246e3c07161df5c889ee95d39cccd989625a8c9e80f951f8b1832f6378e05daa8566477d7fe547e49ae6e822a68de4df9fc4d6500d5219c3d3bd8887bd7f695151ba378da17c2e750399f7482973510a386721c59683a86003edb9f0ce1ea89bd7bb8a25c222df7ebedcc1b56c8ce18f367b2cae720e0591b477f6ffb498c3d7ce59cabb1b01d7cba84d7180b4b2a165d4b889a6ac361720e768f2913aa50b0b5c88e55c35bb4df4fbc4460338809605f1fd445a2bcd97ec1d2f269b5e779a18c8f215bbc5555c745424484ee5436119eb8754f5e9e91f51fe715353596baa1fbb0a690e99691636e6027cbd4b7be752bc278661e2677070ddc12dccc262d3dd47160345de51359ee8dcf2f61044f95dfdaf323881b2bbff68af6572348f786f6e52d1309cff871ad58148307d7eaedc93ef037922b6092ac62171433adc4934884efdee3052ebd60ee115f76f9dbd0eab7c4c0a77b4ce8078209d23d81d957335f331965b556ebd54732327b5aacc899f9ed0edacad9eb98cb845867f249efb0e1a5fa2483227f78decbf7f1f32d060ab0c01eb985d83920b2cc24b5f9a0d5d869e980129d3b78277fb87e5cda61e340a729d86b6617b8828dffc7c37d4c38080ef3515c2784935973dd184e0a8160f84bb78bcd8a5e691760be4a4d41ed6512ee436ce24650c0e17e7d74b5e01cc39b21e21514a84db262d673f24a82cfd5dfe2a162976171c538b24af16429bf8ed5fa8e37f89ec6e7d63ea1d83ac1087cf89e8f43161f225108889e922493d973e36b510074533cb1cb22174d21c4076959e4191a5df880a8b868b95a9cb5151a7ad47375fcd87725660cc0b59c88ceb86984941268493c49b8aa2baa8c531ecf497853ffc3d26b926a379e72188e246d42073041fbca453bd558f328881c8f8d9e099e898a912530c4be499f2b32229c359ea10e0befe6d94cba5ddafe51d164898166e890b22fd1eebd5724451511dce1f8f7431d712a3f1e50fa5f609da686253311af255b84b2106b09b803e94b51729cfa0826869945d46b9606547e7e33fd9961cf15b400d0f5e01d8fd4d92a83ae526934059d4514b9e0005317a70466aa0b6086d5fcfed201d958a0de55fd23f0919ea29b8aa02440031a9fc206b9feef362a73430a4204869354ec81b6fff92eca97e7f1bb12d25228eae466b8137b4806895ce34b57dc14bdcd107fe160776b0e5daab150ba06976eb884eaa574da393af4de355381c7caa4f611a2ee70a0c78df93a4276f55e6281997b4aeb36888a6d9638cc95444047e5202f41f8bdd787f1ff44a648cc7d39f05e49e5d6989fedb194c526780709763da81a780db0d1534a466cce57e11dd3a4c0e273d9873af1040d52a90e20101e1f80ef296d45769d204cd5417a84e022b6b336675d36d9cbdb16b0cbb08f5e240012967c8067c92f97f981cd19d449084400d76adfb7c610abb73bf21e161db04debe6665fca79d71c8cc50adc3ecf0e52d07773478ca97b8e9821a5704dc58acc647a5bc618d2b681f17942c46c266c73ec211ca403a7d47e42e12c775b370cd500d70a4aac7124f5f6d2d4ca78e1c17a96426c326bb60379ceb0c84a86200f3b450e5e9aaa11f45440f5260eee7675a8b9c47fbc58cf18a651a1dc7b39a911442504f12c103054bb50f15381e512dc6e3af7b414b3db26fe767d83a2a53d7181fec8f6b196c7874befd6628b31797ee3c9260c7b7853b137893e36696e2a47277add98462ea9a0edeb7d2d3c0f2805fd7db64c2c7eff353ff2b36f4de862a42779ffd4dbe77b6a79bc9f4ea3e909474ead915fa3fa990bc82b83a670b163e79300b627fb91c4502e96bb9dde00f716ae6ad14dac647c9f7c2e5b2e505708b5fee996b8e9113a8f4f2caaf414061ee72e76b8bf47ec4f781bd7c589adebc2c267448247e30d659998d8037783494a1fdadcc819d7ad7ea2674f75e10639c3d3055046a00814ddda0e463185454a4455d60b9780250183d591c3db6f27373cd2ce4f02f206ae10a8c32d71226e7cb8d5b05909445977164983c0073434d6c0f2bb62bda66a16792d6e53a49ccb5ac3e285a6baba935f30e9d1ddb812a018ce04f29e2009ad678ba72b6a7112d6e7cfcd3ee7b058ec954a6fd7fd01018a6eba6209687c3130de58147b07bcfa02ec1caf30b59daf87db4618b4a5fad34cbc8014a7529b9458e05eccb9a77ef1621aa95513c6fa4003b0877ffa6d48805e7867dcf53447caf348228ce926233f65d553146584d6ff3dc3ed3296db9bfe69dec6a07add13037b3aade118b2ac3c52350b9691a6cb32356ad93377059fb8ceab68de38d96876d6d383db01f3cf620e47cbfd471bf6dd1f601210482f7c3bdd4c3bd37dd0a7507e1f0fe515151634813dd4ecefe97b52eda28e7a7129993b0af311abd3a07bc463f3cbbcb4fb0eb265a5835663fdbab0d8b8b5a73837ac98ced6582348fdeb41ac8ea9e36f9818ab9c0a41bac1389a6b518ea17df043dd50550f32471645791bf59855ed695b84919aa5cb688e569122786660f06e3a919ef9cf18c355bb397b86710c367362cddb0239aa1d32d489328e4bf92b3abdc3d0dacd76ef1a1efa28fdb848e708aed6780e2d8efb19a2e26fea56b4440dc3eafd796896d73fd150bbd967871f5e6ee5db58995f2f85cc2a15077d7d472bec2e30430af6891193ef03dfc7761e2b3b3b54a72d4f1084a8fc541526fdeb0633dcba14e9485b43065aee8750397ea88d9ff13417149e0fa145be666e6f4afdabe7ad8e4864e777c20ee7a2842db44dedee22f3ce2f97d72919b9ff6059352083be816a7515c48c5140a99af8e81b9e18b10074dc73dab55fae66261421629c8e323d8134f08beefbda555660a51e4b55a9ba4573bdf0396cc413145a941c4175aa672586f7676027f9fe211db87fe07a23962f5b1ad8f566f0d5b13c5146457276f307a02e1e13d00c5032a06d225248215e4bc4be1b672f1eaff16ca95da42513fc4315c7a6663f9101aba80224acbf0c87fd3a2ee9dedd1808c1247c5bebf3cb8d77377a508ddb484ed91203a438ef5ed3ca14e087102bc5f3828d8c3437ecf5c92eeec0331ed93ae33520740abae9b7bfc45f097da70adbb9b9b879e46a7d655dbf75d89773f737b66fd8a8c13506cff7b44bd85dee279ea7053f3ed8447fe79c400cf23726fae800449d27af5e342ecf776378e2eb449a3af27a40fe4a9806487b81c942bfe1a4b0fc146c971a13f83669e0189e337cc9fa2024864436189a9165ade6b864698ecb797ea05fed0d60f0ab4b92cbae36c72ccb5aa45337cc02dd086afed9e5522ecdb75ccf389fcd63c5a4abbf60908e39cb3268c76a08687588be67a856a841eeaaee8ed016f6640ef0f5acce12ab8bb58dda380696e3fb22d0bae0788c4fb79d00cfa5ae3e479dcf7d08b45f4592c2d2a7f8081d5a9398659613ba4932ebfd7382d516b2648ec4ff4477648069b9b2e4decc89547c16ab82a0ad9cf293fee5adb17cea4c95ab7b8e386dcae6acac63ad0d1d13656dfd97d5623dbe45230de597751321bbe5a03c879c303fd7a0d837d48141decb6df4f0865717628c85dbfda29df9a8a69b2c956c75fc66e45c08960c23bbbc706e48395057f989dfe675305067b3ed8d046db339e504d5b2bc978ab4dc261d8afb325c5e794ec79d63d8db53f9dd24b623fbcc202679fae8f7d39f7f7e0667b142c714b6a723996e5254ad2ebafd63c3577f8909981ce6b3eb1a6ad67a4e93c45ac3b34587d153ec5ab67a2697a9741610d5a176cb9b5856bdccb98f69421061c84811dd6660495d9f30548efaa69e36ead246d997c95bad0ca3fdc1a08b4be31b12daf211d3e29d585cdac48af8f2268ec304bb35d",
+ },
+ {
+ "ceb1f819497c0d631a9c9616655f419b5e3470fd3b19cd0e4fa556bd26cd9df57e960ec7121b2a2cb7c0421c1f84b77eb8277bf341490190ee574d1424eb09a281176a933394bfea5502077486bef23ee66e3127b732b7a58a04b9aeefc35170dabb030d4fc3f8a4c5ff194bbd0b89a379baca30ec81d576868f25755276e62c31e93a80ac322571313ebcee494592c3ff5cf3ecdec962645887d9aafdbfd62ea910af5542d4c7731283625bc9f41ec85012b42edb1792339e6cdd9c2bb3cad4c4792a064df17a5f74dcbb3dd0d90620ebba4fc6d1e1f9704dd60c798ad64d4e5077549d68cefdddaab81a7a91209b7ddbea43accb3d1c191328929dffdfeb4f5740ecbf0ee99cb9a1b73333d7ceb0b2b8f35f84307b9d44a42fe1a30ecdf2650dde251bc8c1d46978089c50d64c028f40611370ddb0b481df9624ed63165370f4788bbc396026b268c2023e0f04cd4f66e0bf439074c46f0ae85d6dfeb0ddf22868af61c8d5133097156fa61a3cf5801db5c3ad29871d336f7aa06d2a7d5f52e50eb3aee3c7de7bdc4d21f68a1776a7cc3954f5c071282febc89c1545fc672a0a1bd8eee2b769be048ab58ea12b356d658a6225fb8a55e752f1fc97ed64c2f87f9ae661514f1f56d9d4e47b001ae865a44b8a9fd5df8628d183bfbee781b6661c9cc76debe6c3c5bba840bbc228206673aa05498a8c715b0f3019f6b2d05cce6c233b5809ff1dc4a75d7f69859fcff94ad442d460b32f6fe348659518c16385e49fddee9efab2455732aedcd17dd51b5117efb2ca1e21ae6787437f48a7042d46e11be4dbcd2932ffd70fd154e4eca5fcdc57c6fa79746100b8e1485fe575a5c79089a25eb2d55d89e42eddc81b82c4f7da8bf153ff5353b7349b161911bbe0a14483fff6585d7f3c8b5c04a6dfc99db9548f0c53e25f0b16fa212f0bdd10ad2193ac18eb09972795f42b3bd3f4d98c4868989c4af7a760f1c88ffda59faac73256df1d607644f56a70303d6409c9ad716149bb58f01b4ab8ab475e4af1257d47049aa77adf9ce54fcd22b3d6ec60484da903a6991ff052ca37b01428d5916fd92c17530bb3385a805b0d57476e9f9417a23ab1c12a038b61b3a0898831f9615d10b468c3edc24448d09b8f3e3a2355dc5e069e880929eabcc97344fb6ca5587c5ac1404783848f531f1e915941e7359fedd328f7fd12b3c685f8c1f29d1a6ef7dbae3e5e32cdb251eb43aa2d2ae0cc18b3f40fb006c2778cba387e5852ec4f2d9b8e8ccd5b3e1f4781c974aca940c45d35d30d3b9584c750bd45a80f32f73dcd85c99ae107b92888839c342cdcf88911cb974d611b14b1d85a59e88c502559d6eef3b7f5addf7d307bb25c57aae669767db6d798ca887124e159b0317e09076cfdbe61aa9ddeda189036703b1cd9b1998f88325910a37ef1fc2e227a382ae635e847df8625b99eb6ef0ef10ce7a2a5762ad7d03a7a4e2b767c4df0b477d6e9601dc8e6438184f97193ea7d7a8c22f1b6fac1f0740f1beb8b68db40e0b22940cff2261273aa0be43df561b88184a9377e6a27f27942dd04abb9448b6b6ecb3a60f14dd39b58b8d94e1991cf9d3a071ba42e0e1d71eb211ca466a70fd4724a34639707feefbfd73dd9680d76a214924642a063b38b85cf30eb763fbfe889f34b20fa4a10ba214d938a5a092c6e9b73b13bd664c75b34f746aa360593c0f8dee0f328f0ad4a3e40d498490007e573b8204a1ce7a550deecfb15f18ed5ea6cb5dd95a68adfe4cab37c13b383f8273b1971580016a8df02a3f4f431c9de9e7ebb33244512080fc5852278081b9f4434109c3427441329e8071d19d0fbb74fb6ea73fbfc7c0ac1012d3a0948d94d7ceae9b0112ec43a16cb582f9c53e7eb0ad15e05ceda108fdb3dc9e585a332018d1cb19e4a75d86041308fdd8476c88e4826931601a3a5dce06fc16512f4669f10183d5a8d15bace4649abcac07358089aeb1e9b8fc3776f3239d5442d3be33d532097e13651af7c9a5b465ace9e626889800318447b8876b45dbbe1989e1eecbfb5cdf5067c71a0d7b7fba6555d0edede12f7228d7f9841dc532274f24060b1f52da6fbaa179b81ce962723f43601d248f8f4d5778c1653e038c8d27828836d562968004003810e9aa9318edf3260272b54fca2e012f6c04abe92c2e6152f3c3e973c7e9abe8c3467bdc246f0226d1b7669bd577bb317c571aa8758bfb694fe4dd17ce78f091cf6c6de3cb601a9d177128fce8d42e652b490d90c4f8fa04ddc71cac300d3dff699be3250bfdb2136edb0057af3ebcca77ba5b3ca34531810c5e2d4c5b5b3bc4e71ee9e30cac067b7706c326357fe0ad2a4bd9cd811b4e9d696bd9b4b70579ae246381210f879c769e5f9cc3cf8d70e9c94ab74a55f5d7bf61a17418b6edb6db4147fc40cf98c75de85421b7d192919add48e5334ebce2a06e56b915447fe085b7dcd677659dd55de1f705c389975e56e0338a2ef07ccf5ec3786407e8449d9011641786f1ecd4d3d3da975d61f5a442293e6119ab20686ea8cc7681010421226838a95a157e2de948c536aabadafcd4095dfda48e5613272289a8238dc945e5f1ef30075d5de096131740cdf23da1fb8b9fa009e5b321083cd93bba9271909460c09bbe1e8c54319394ff85c291814e21215816d4791f01424abbe4cc4c792d0d04db1b812f4d24b44caa76de2bc50f4d1d1611862512d87fcebd3c0b2659082b2423bc5360d107ad7b8e8ba7438ae4509105d6b618af25e75c51e272aafaaddf1e5a227f2b2a2c96a8a83dec23223cb428136a30b290181ee20a819cf52f6c03798e7294a89f3b5137693d5a8b7a0ea38d78e43008fc4eeaf6d077ebffd3ef7952620e0af1395c38a289832df391d1710ab5b103a1ffeea8c06684c03a74399cd63797c770e3f0136d8331611502d21fb883136a82f2034358880392fc3d2fc274b799e59b89f8f90d2a5a123d3c21e5bf3540323743858fdb8912c7c6329a3aea241075ae097ebb23c8cd50f4ff46b42486e65bda6beba5f4fe6dbb30f7e61b1bf690c9f00f7513c83274cd21bb71563257a20cc38da2b88c1063bd0849c8243058ee205853342085a8edb7545f0d96a6af936a3d4612b95676665eb02e72e0875100dfa444f039eddde1422ceed8d38e6c3dbba25064f8c6cb5786f9ca67712b7840cfbd40f99b1edadd4bb9a61f48124cf3b49d68bd642404eb1dcf428eeabadfba6810a4032f8ed06b38867a7098c7744d54dcfab8f0ff941ecee69da9916d54097e080cad86dd08bf53833fec4aa4399f7124586223ec70e2c31e8c647be06df9e86a976f37901e9b134e775de2a0fd53d545c5f92236dbf5455859c138b7bb1112427049d29ed4f5dd5c43cffd3113c276d9bba910879e55efe817189fc239a204a9ebe738c0dd161d10d60a51e9dcc8c38861d41ff029ffd841086803320a17ebf5ff14b6cc2ac3dcf0ce2eea9af7ae23597233599c2321dd2b99e06d93f84989e75e30a388f47079c2af545d96f270e064a43a00c76bddf2f5be5089a69a138de844216148a1eb0b413f58d831d9b8967df297455e7538442388cdda12d157fb25896c6e2b47696c76b234a88bed4f09dfd64f2e4b77627ef03049030190fe271a5a853591ee9218a0c6b12cb3f02683d665b211dd1480cd44c9c0566ace7d751902babae14cc3821374bec774d54b4b4afd5d1811ede556a7a5ad02642a878d2d32380e7efb9082604f49d51495105f827d77945b5cfaf2f2980566b28ce3dfbf1bee2e077eb067bdfa4cc28f5d2211ca99a615e69118d9391e3feb9b13cb4a2fa9682718189ec612db889228aaa3f3345a091aeb11f41420240fbb47caf567646d9e7c762d3288f8bb2b1165cf049a191db5042fa9185fcd180b04d3007c376e0aa3d427d66d10918821f74736816044366463df7cb3ac94cea167cf1daf2d1842f130295e40bad672a22da9238ded69e241395f04d5e3c3875b8294faafbd3d90ed56ff3e01c5a0a3e349d761273143686aa26d408620c7d1a35ccc430a09e3f750d3256298c6068c0fdded270f308f79d2fcba591d723ac0cef703d8f0e7c051bae5b453abbadfab98bcc297ed4201b03ebc195c2e441cfd3b10c63c08868db36c320707ecd6a37593661d70a81f30e6db4a32f98e4fe6b950ace55923631c8f95138781fa2af78d8104fe39242f1fff6942e8e782dfa0d37c863caff9492f8e5cb70046d207c4630cc29c20e1ac105aef093261d8d335456961e552ab14d107cbe14e9de912f0e5d58d16b729270208204469f917af4e710123c3bc38a4b3f485f2926f058344db105b9239829441a2d8ababf04aea615c0e350846d9bc3b5faecdbeb450f38f615f119ad1b5dc748e88107ec2fae01f0915174feec37b3e7248ed2699d0a5fb2fc785f17d6275fbea867aad815acc8a6fd3ca4ea7357d197e5a30082ad5f35a9d894c0aebb206c6487163c9cc20442c040e6aab33d7b4b221e4ba4cbabd975836e353129559d8ddcb3c97876cdba360da0e0c1dd5b0cff7957a444027db985ebefb6154453a221076c997d3954b347f49308d2ee14d1676b75ab6ef365f3de54aaf398fd96b9040253813ba734829bc78a6db59e3f1c0ab4c878a72d6b8681157919130fd3171126994dcdcdcf68955ad64af8156702c92f7a715ce6f7ddfb70f60e80c92691efbfdebc8cae252108fb6c0010d303d9027d4a5e63413b5fb2316d32fb93c3ea52a2a7df50cc0058c76c58d73f5bb041d9fb9f3c3cda9bee0c0920079ce4f1ef8698ced664ce2e2b3b86027ae2b3bcbbae5bf7ea3693d9429cf94938dd3a2763d3f53937c46763ffee6579d018358bc69182b1c7158a09b18352ea618c11c45f07fe97cb65faca535f43237879ae3e0a31efd14679daf8fd2ce25eb8f32218fa20afc586a98fd908d3fd804cabbf56dcae272328011b252dfd83e5f0a5fdebc6acb04c5540255e1322de5fce9db5aa4cdccd74dde8990ae51cefd6c1edc1879971d3efb1f94dc41b2b23e9c9d89415b46189914a229b2f3e8b05ff78c68711385a00e9534dae6f79d15842aaec575e4ee0f098028bc74016cd3f8e93c6a0cb21a0b574ee63e367343ca9de28003d76e02d0ee2b8d622cfa3615d3628fd02499eb7bd8c1aa1f34edd9c2d059c6a7c7c978a5e4f60801e03e17c3a09793c5217f310a30db1965b8e328893cef20f4a899aa8d9fa28f7fe0a733813ed7466046776a874273ecfb57158483f4a588ad4f232adec5ba4ea651822780596de09fd54b1717bf04130619979a0e3d12ab7c35d64afb8099a1d21bc952653742f50c8e1c244d10374329cedd27fbefd37815a9b3112a4cb2fc587c4ebda381b2b01fced45cdf0b9ff8ca7d10b65ce42e728de183a82e369486a2e3345664e70674a5dac174d6616d90de8e472b62759df057119875483cfbfb103041751747f9cd12bb31e91caf79eb2db1168026a4707dc618f30",
+ "e45eef9561f3acb3672b4f38570256e8cc4d877e2998e72b022e33de8fc20f7320fe0882f2b53559e084923786e8205336a7d15f3fb88a41e7bd20767f2feaa02df2221fa7577988db0bbf61f3dfb429868688c53e130725d0279c505686f083",
+ "475a44cde0cc931edf9a44b0c1e0001766f09ade023dfe6b59a6af800e549b55",
+ "7812a320691ca8442767a51a",
+ "eaa577bd67fe79ce4586f43355c94528e306c1678946e4f7a907d2a8ee7f4281270502522119a8b09b6f05d864921cb515fddf6a1000fc2f67b52d0627998591e2acf5b6faf71c278e5754b2703662ce670dd049da8d6e280c2b84d6a9b29ce28980563c40e03381a49c54608b72faec9b272ef05cfa41957d9eaf3e944b22610c725d8efea90aaac6e782848d368ffc08784d7fe37ea1effbbbb34952def29fc511fb10a1282bb0b6334328e4d00529a44de3259b522553a07d524dc75f431cc9670127c15670c0df419826617cfb5ebdd8788d5f528a9eb1e61324eac5c1746f339aae2e2e2fae598642a389da671482128acf2d69814258d83de98f186468136868b729aa5f0874fef2ff2575a1f87439d64e049e4d0637e9c99ecb7275417af654541306615f30b75a6caaa563e4790dfb28fe9f0e7881ea2d885eefdba99efa7f878925ce7d33e86d888154a1b03189429fe20af8fa3a68d65ced9b690a709031121425cfcd7e1890ed9614f9dc3ecbd0e38c6c84e453e3204978ddc1ef8d7fc6cae28c61a472d8e089e23209f0c36e80c994af771e6505e72ba90e5543f6bad6dcd31fdd468b13533a0254e44797825764ac1f63747d8d6ca019ff16fa732068ee94be382c46b168050ba725379df31a98ab81ec8eb266a3c3f2e1cd95e5f12b3bc79b8b435e4d94098c6184631cec57e9d8913458889223a2a4541f34d2f9df380f34c3e541fc587f0a6cf08c82e99476060eb84709a292f4c7a8551bda3a9eb6735787dbb9d7f1e83937c2e0e49f2cf6e0ab0ad84c40fbafc3c7e61886a8629bea816972fa0afd0f617b6340b1af19e341875e97565c8eb0b25fcf68696ee674d2abdc29396bfd0f282543d2b72a239c6470f76d3b5bff6d1d064e6e2d06f9deef2aae8a259c034373efc820f9a2fdbce36cc27f35dd6386de3b49509d0c305757257f8674d958c580a09e768c0f6ef237416fd53c31511badb2e7cdfee636508482f01899e72052b46b5d844799cf94708520178cfec2b61c8980fa7dfaad8915b0b75ce6eb57ed4a01edcb4a35c1dfcdf8d60f3191bbcdfd522a0e321ea41c2cd87a303522d0f98b82dcbe53232ecbf0e2528de7e1be75569584bf2ec574687fde67ffe9827ebbe78f2e5bc4fb368f3c9b0f588c97f7a139bd82fe86eb605b8e29cee75d07b510da1b24fd62cd2fb366f1621e7dbf268b15937f7f7ea4acf6e615775a32c90733769996dd2c5aebe08ecba73e0bc4781d33971992b2764c1b08aa972859cb61b003406479423254a01ea85a348ef249d408157cc0962d1e24cd9c426e6e6a3784dec6fe935be1f6730b01e8683d97e21d8774b2e2655f85db7149e930a44524d4f86004cd687d8a528b6ceadd890707458cab62809110ee28f61a7277ed79dc41e573fd4a59fabf15393ed4c21bf4d5138ac843e80bbf5e1c39ac2d7f2147f35996eb51a9e835db63faaa196b8aef1823ad72523fbfcb35b5560582a48a25ab770e7528e4b3ef291e6f62f5fac916e2162b3b56304287e46839858daf322b0de083d1691d6bda44d66d085ef0d0ad364eebacdd0a43a4456035e58910d0b2dacce45b1c0beabc784f3620a3e4390c345df6117b86d4fc386523b7ceeaecc21233a2865ec6b63bffba6689fb3323402119db8f0665a4730b2e26ca6411db04f1bcc78ce6272159ed2665a286f1ad7758d6d90090a6fd320e697dafbdfef575077e282b825bd64a4dbcf92d1fc0c6f795154e8466ee4b318f2d44b6f81c52523ab68ff8367e01090c2623e00b4008e784049df873a35c29e0abcfae7acbf27236adba0b913d19a15b4af4996669aba4c656c317084347ca962ac8df15cd2f849f522016eb92de4de62944b917d88200ef9aa2def0d13e5f4ae09d2eb4a2d0800af1d704cb01975f6d59768a2b50e39e78116147fd6dcdfbc08354c1b4033bf6772fa127856a4072556a9f07bd7516d01ef41bcb519005c0a3b2a04400427ec033f1b52fe5fdc1aed8e2521fd0fff663e203defc39d7546281a98a502b8a470af16cc62a6581c9985d7ca516864b799fcc55a803ce80711484f6b81591d2402bb1499c95dfb1dee9846679c22853be87c84b4547138dc4fd46b4e79ad12773a5392540a595954112f0cb1d9be4d4eb3aaa4286b6c01520558d58587d9d7f0df3a0282011ce01c9c17111d10ad61b3675b1826c1ad37fc562bdde951b43f890555d6f74ac4fbdb9abbe8bc1e80bb6d52c13de8960a3ff8f65201265e82981dbe39e0d65cf3f1fb6c56e11f9786210383d0150a5e0cbbdb52ca8b2bc45c12fb572657380df369082685b3de9847d5014beaeef815d63e203cc911061eb53d89a312d187f9f02760bfa71083fb643f5d8c324c410070b7ebde250a185e7359837899bb1568a43fa3418f39c12feb03b148b924bfb98b99352b1fbad3f07ac8e4302f85d1fe9ee4bf7507972670ff8beca105cdeb037f1cc4f944d6ca869d0281653de5ee93a7362420fdba8b01a375ff08fe27873655953ec1c00f53613c6ab8b244e2fc1b6babdca5311428d06f57aa4882dc870165deff75ba877dd2a04d1799f26ebfac97a1be53a83ab77dbc2cd4aa45bd779f61b1283eae1a1866ec8a9c150dd0a4deceb2ddea1bc0f4206cd435600a8f190b999b952337d9eb2bdeb3aba2cb2e7000319056629dc1f00901f0880278509417223a3ea0919fcdcf12bff0771c7cc725bdca292068478ccb2e1f35ae8964e0601789a73e7e7c1769ba53f865910fc3d0085c922d7f7849d27b6e7503d521371351f9d7dfd5afc5df0effdf6ac49617fa228501ad72154a73e07781dc4b07765dbfa721d95cf1dc41e161cbd34fc7883a25e3ba6b03e504b2c3b98c8b12ff629b965c2aefc26d74faff7f784baf09c3fc38c487a9d1f5818261162f97e9dff70cf42eb5dbcd7bebb66d68f26d917ddf2a3efc0db1e3372b170b4cd18da507e44c467943f73648dba74db1053b53f989e481c3054bac22c6342fca2c26d30a859a1312e9c353bf921f68136de2b1589747bc765153927c31ebe749dcdff98b5da84c4b66085451b4c87fe1ba2142f98636bcb268c33f7b8c2b96a6525298814578377aa189dd73d5bb27ec5cd2110d8751c18a3110273df2595d4c3a00809bdeda70d86c4a8169b7010c9cdeabfbc3dd3266518226d0ade9bcc4825f18198c854de329fb8fe456dd3bf35d89bd9d2384f3f3282f6872351a18a2f852bf173ea4426de6d01b3ef4b4685aa82df7dc45b99617a8b8c8a0c65a2237b3eaae8267e1f6c453f485432529d973924a080f6a1cc2cc18f804f53209383ce3601ad9361afc331707be1c88b4370404cb7fe0bc538df04adc5c8d9ced94b4c474b19619a53dca3fddb434cac09ce10c0293fea04e8e1b19fd3ff3d174baa988d91cb604fadc59ac0b61f4f87bfd07eee20f7f3ffd96766dd6f3555cd48da7ecd71d2fef34ab082678bfc4dd007669b3fc7a937a5a46269baa7e4e4e43eff1b2b847ea70b6c6c23905d6fb2fbccd944251087ac00c35c2eedba30641797d36ef9d3cb1afc0e3e8930f5b605a847ee77106995bd44047294d04350194369c5a7bf246d1108e1d18d9a638be0c051f695ce86579db613cd8922e86c683c91800b9a34fe6339e0dd79472daa662f78f04f0151a3acd18f11faa4e1216222843b521fb998c8490ab8bab27fde36395b456501307d07b484b453b189fa339282a634af30fea99c9af8f877e61871fe743238b2cee6cb69dbd17d574b5106ebe4b0fde4ef42fab469a5ba7d62c23b67d857f1af6ac981c320db70cdbb6be41bbca60bb7a159ee1c85cb82e0a220064359c06c660b75de6b49839eea68c80283b75d9d627aa4500c0c0f21edafe4a2cf7ee079d5310479da06ba58b142614fe69cb236c51447d63db31cdff91485b46325c26d40dc6d608d46a5e2fb01df06064a022ddf6d5cce0147d5b2a5aba5f9fadc5e778010a924e00a13e21daeea2cd330f45536ef4f42c2e77be00bb53b3f9a93d3eb327dbf30baccee5d26849cfad654ff3ef2b035b78dd3ef42de3302e5514551a968a205b823dffb040ac9452ae3efb43219b02436d0761ca11470405510e534d56caeaacc40eaf9c47a39475adad266f5ddc813e71223800dd46fa7c02b078353f870049806ed7ba57b40b7c3c6272296667500c4b97dd2d7026698b6bc4985bc01be99e0097013a2632c71740888ffaf902a02bf644b38cf9a42528880d9dd142de967cc2ad3e1f1737f0cb8dc5c59c252496e8cfe4e53c82f4a28d9ba2bfa62b6415ba3e5e09040d7f3e3abfeba53e46575e8817ac5eca806ec8a84c7cf77c9fa86c9dd2940f5b96b25a92d4a8f894d4717c8f80a62a35a51d8511f1e822fd79e6fc27cc3f3097d9e3272447de6f223971657ded9e660ee4f8836359742ce7616fd0ca2de6656c71b212b34b8edc71ff36bc84ac4af58eb1adcba4b2c0cb31468dbd2c2b7ee6752981ee1d152c4e4a9b25b2ce87796820def34b662381806d2e4fc77f0b69d7a87de43d94d62a6a6526a7f8c588392890e96f9c51bb58b4f438eb5d197477ce9b160d1c898c89ab408b3c1d648be93b531a5bb4988592c5a8999ae3acbe586d947fe6dd507cddb92dff4974ae17ab99aad5aec9d07b96bd29489876f51afa67570e86b69321d9e565d86001514638403f86666dbf93f18e0a62bf65db333bb85a3ae12d8411aa3c2a423a29bacbbfeebb8a5bafd90436bfded16f992232360211086a3084d9fd1980dd96631820a2cf25c3ac5c19d164cf5ab9a852399491962100ca4fd640146b7ea5460b4fb9e46bf8d23d508a4eeb8a3e9fad8249ece3648c2ec7705a7414eb8e8d602549204cb437f589161fe40de1447d14efa4d738b775d0333526c845cef5ffcbaf5c957df1d8022176b56eeb198e7ad2dfc3d7ea46b125ed432cd04c77efc011a2dad8573345080d7c3cdf5cc160fbc86c4ee1959ee1b8258056b0f3d9343c22dbb2f7858c5f162f08cffdca1acc866aa68e5f1c00b74f66544e8a61e429335adf6f73e32fa87e48e1adf15bb6c7aeacc93713dbc31cdccc9b0e52f922842679494039c395cc1d95eb97ae4df3bb8aba9a2584d97a236f87cb22f00c0a078b045044a5c456e22b2b94a76a559de2672c880660f9785b76bcc2aaed780e05212415c6e73880ca110654ed155a1004af45d5f15ae8e5bfd4817440c5d3d5589eea2c6c344ca0d85d91460638b37f877ea4cbbed35ea75678ef2335a5922cc8541987cc256c8f58045028d33a1c4899cc32265c619ac782ff998a478996be6a0c5b102a664831b395a884f18e77885d860d6b236c52a8066d2ced25432bce79a31b23117f405ef4ebdf3517de98d288f8c3baf04b63b6817c46c14b646308e9f97170b7dbbf9d1a36480338d8eb7466df56feb6baef42cba75512954fd7e33961d247b7393726e46c6e94e156d5776a89ad3e288554470ca0bc4cf4d2d2b0c01ae4fcafcb65ccd6ead03df1d4d6577bb",
+ },
+ {
+ "228eabb5ad8b4ff13b10d13b27372bc2152dff149859ba47d9c89b741d4a5340d8fff5858a4576c55547007d7e2b3f94583ea8f0976237712bd2e5481c3988f5387e7ac2c3f18718388795b7b2d44b0a13f3faaa55311b800301c9203a511572cf8f349280bbabb9424070f415bbfe28aef8d20329ee842cef4d4c299e619b6ef1cf00718aab2accec9ac00155be2903b6fb07dfe98b0bd8d8580176b99ce4aa6be51cf59046c17ce1817d363fa63af5a241d48bcce064a438651af102ff9c6de4b86374fe24f1dfa66e16e51550dbb791af425d8fa601c70c1bb90e1a557bfe0dde730b0364eba9d2018ee751699ee219e13fa8874070935b29a1767e1d748bfbe796fe4b81a71e823605d39fa4b5b885f4610c34d1a090fa4106785e7a035a629958ad1b00cb9d36d171d575268efa1bef064fc0a6dfbae8e532466035a0c2cef96fe9f93b872f0cf804811e927b39818189412868fb104e2d56ae62f77031f0df1ae91aa11826991ca7b8af22f130a47a72cce36ddc319b32dffd294f2e192e490249ea1a6f8437173ce6392d16dda888a98bf685bc91b89b8ee1eabdfb1806fd61f018d1744fe8b03521de4bff86d4a811ca2ecd5be668e9c752a6c26aacc0cc9dd89d112785c25ca6a0a7a5267b4e37457c04a0626c8a29be30ec28ddacf47a84918bab164d07bdedae62132ab04a6f2c4e108eba9ab878caa4a1a7509521d427ad7f3dfa86fae8345dfb5e0d46ce3a94dec84f7880c7422468ea74fe0b4825b8c762b34d5d9b82ba96e0c7dcae01718ccac0044a87476ff031e3ee3c2c13f5f375a841d243c38cd9a354b6525527de1fe7e36a6e2ad95e5bbc4c97e85f8cdcd5341da777e03451838807d5dd2eb4fd15976783c140e21cfc2eb3e58e40c16374de0aecbe3e3d41c64417a472cba18762080a2348ec3f441bf229a932ea0ca7c816938655d0c81b14dfbf86aa600d0c68172fb0046ef51f601ec89309d43ad1eacd583f9d205bb1ff1a37a97b44b5e35be4945f52897eb2a74645b01a7f82054cda44e9fa9f9af9bad1a235155718713bacd08d354f3fdd95858db0040fb551e9f93ae399d5dc53a67e88bcd5a02d104dfd9d824cdd5fe262ed9266fc47b7e640f2c9d9c7a62c6d24b429fa55560aa254a824a0858482e771144d6d5b05539cf71d75bec3a22be75655e1ababec4dff9472a019f6220067374dd49252282e4945a407084633ef9c88d14833bd95335107d36afdf56a642cb739bf0a61ed53a6915baed78e9d74166ebc492b517c7c594fe6564550bb7108f43012551e65fbafc0a9874e46fb64b5b7aee0082a5d617a43b8bf9473309c6761aebc7f13b72ed460b522a6b0875b67353c705f99d1d9dc899870fcc90c632aba1fa9ced6d7a2368dc4dd3d4b38a5807415e00de6b9ea70525a6c1b67d04521efeeefc6c591fc5256d990a1123522864a029430bb7ea00dd80d283fdd6d61cc5b509221e28f73386803d97a38fb0182fd95b3b91353c6eb60ef2b3d5c8c0ab8dc9cd9be2b4cf69450d00e88cb0f0bc9a4be82b71148a37237ceaf945ab94c365625f58171eb15c1bb244a87335550d813d28f241a3296520046e65aff3291555786d7c871ec8a2d10d4b44429041c3cd6ab60f0def742de3d28393c5aca92b150697ac15504ee66d8a2aa01a6c63d7c719d6d4f94af2ed1d8670e3231a0e481095e425e6231c43ad36e3b7a3478f6a61563f5aa13237beb8a891dbb29013c325f7f91c1b055fb83c436fdf8aef49ec457946e6ab7e955427373fd9c743acfd4b9609569b591ec79c7ea7276de103a35a4a8a05c91f59e04689ba1ddd570b18ed046f785d7e4ff9fce7115ac814fe126f781828877208ddfbb2ebc919e6d1f6eb417f38bfbf22ac9633f75e58e560b85d88d0e4fad9b2e68c9ebf9675819d50c30c8982bbbc2f41e02690390bf0e16979b24e648bf15b18800aaef58c3c465f38cfd1e47bf1266c17b69523b7868d2138cb95c4bce0dd3ceb7c2267b868b6e12888d5a489fc0091b295b56a1c328b54fe1119aaf1e6d7dd52fa450b52fbfc8b84c2200ebe209060b655cad288562786673121691809366af37b76567762d1fc24f1fad3128b43c8d10e9b6954b2efcbe40124fc0a5b670dd6dd544e30263a551825282aa06be3817a8eeacf31ca8b25cba011d60b78d3d2462810764e4acb566ff371005f5481c9d36c991527143af2c44cc8cfc59c920bb4a281f2ed4d494d30ba4d900edf59e23be2f763072255cb6f1e8b24ab1d305fbfb2429cff8bda303617c034e71a17230d0e860420dbcf9fea4ab48557e4d50797179496936ec6c97686fe6d9115809e14069244d251d4bc9c8931e47e06ec051e709ba1df526b55d959b37a6f3408833aaac80cfc9cb99915eb7d83e26998f0da2492b986fe0f5047b2cab6e6d33a117df21e6a8ec7f394a3712885dab176a4d6095e5cf75dbd3f0077e5e74b1ff8b902072380cf172562884de852ff5f07c55856224fb3df8eb44764ab9284944b86ab6f176a863cdd0e7ab5616a14692f6cbf41bc63113b27689fc2fb145736aaf2a5b26d2bef3a2a59ef8bb3f3e4d360a4251d0736482e9ed7e189fc48c0973b6649988228c2ac72b23826a61cfa06b11f13c8555be6e433d87e20113eb74c94f0e51719a7b38c59eba300089d06b9bc2a72017668e5aa3153ca4282718f1762642e7c1be1f865cd9b65c6387c8fe496f1e60d5acbb78c2f71cea1f35dc955b1e7d1cdc9ca339765995d9e05dd729cdf58aa2a1451b633c374e5b6c2af1c8486ee4250a875e80e1f359c15130eb1e2575c0c7badb2af61378527fa24347ebb12c10bbb36e3c94619556b2c641d0ebb691b2706cdd667f55b8fff8fb46e3ac72f3682661a4bac2391075ff5145eb07d69d77437adec2d096c1c89208ab3e7a9ea6a0ff4a5bc1846b3683bd7c6ec4520c3c95861a5856b0191e4221c9819c67273c66729728f6035e79c0dae8842df4c0c27ada1ad18b34efcd55b94ef120762e87e8c5afdec80d5788e83f0d1533cdd7aea8f27f33266e007b274f6d48c59bcfad607e8b298be2b17322be88558c60033452826778f167f318b660607bfb2f285cadb385399636acb8f5350d819511b5e7931c5f8483529d3ab3fdb5ae2dde0ada918f1327c6c0dfbbf5ed3c8afef171910dd0169022b3cad5b08084dd5e8eb8ef1ecb17e48bf69f80e3db0ae1cc7b73d94b89696e3c3443ecb4c7ca12568201744d1858d90ff759f2d264d49edf47772bd0e0990c14dcf8c8a4c2dafa44dc6e92f4c66b03bdc4f68f28ca2d0811a433e184cced99a8e5614ca83c46ec18b47e0c7ae91037ae06c6d6d0f3dee19711c21cddafb5869416d23c5219296acda7774891877f3f8d46155d39f43ed10500ede3afa26943b83b800b54a9752250ec6ae173e920002f365d692a9b3a2f9b27124ac97b8e81b70e8c0bb7022d07ee97e962810962b03fc019695b5399f77aab414327cfc5dedd51e99453179c42ae85a42f8e06e0cec6f937224dd019c77c5a0ba32ad08107216a9c758138b730bd5b5f4b613f192839514a8621634d9dbd5840e728c1ef4a2c8bbfadc376dd80d13dcb327ce55ab536a43b570789f5c5e135ac0af79b54232613d0e989ae695aeb358c671ae71d508b58a793e19c58c3d204cdc9a021ecc634bcb0bd6a1917554ea3bd688adab8163260a914fc01d7ce05a497a5c5836cf9401cb6aa35cd008470bdecfb97a511c905badd01bbb4d0c05867661debd2162beeccd52399d5a70a929405293916f33ed0d03f8b850f4bdd77b1fb6283118d71de629577383c81cad086f4099ce7476cb787f73c96431a0df4156f7826fce9045f7e7c97bbfd618b845595203cdc8df4638430fac74a07bc5f773486731d8ad29c06695704cbe2882077a85d543551b7ba81b181ccb93d2b3071b1a38f3c762b42df8246aa64cecbdc772830ac79e766fa99e8c65225f28297a32526df9b51227bd368253737f013ae18435a912bc18cc4a95216ce449865e8bd8bc759dce9d4af52f9e789eafa37023e91946952202dfb7243cab7db2f9f98bb66f19750c547a2bf2e2ba92862ab66f33fcf465ffc41d23f0b891a3b28b3f68ea48dde6ad4802902abd22b0d7d9101bd61471c5d88ee9d9477b7cf9f6ac52e0f520c79278da22938745446f1e647ae478ecba416b941aa31f979d0633efe72910bebb8988de1d0013616f31c5da163eb6c07022649ac57422627a5642618f53103adc9918f9992c5b085e10d2744f9934bfbb994a710d6cd387c325e94278f97d5582864f1bb29a1400aaf674ea8fb99a3b42e4ac50418fd804a5b1471eaac4642d4aa338fd3d5d0dd84372b2c32c5cfe7f319acf731a9787b048cedee3833300dde639cb1386c8fbca4bae8d67fb7bd72d1696a0212e27e166e6b04a79e34b47c98502ed0bdbd8d61777537f72df569fe5ed30071b57e8724e98ccb88c07f0458cf32298cefb6ed672b255e581ac756789b57e950d57174bffd3f47bdbe4b168e7e3f1a6df508d4202d327947facfbf9526a9e5fc1a5abb179902d4584deae6cb2900391e080d3f3540b87c3a873ccfaee5b4aaff0e6516a867ea00b4d5e680fee6b91defc65c240614a1409bdd0f49c2c4f3c1d258d77abfc17a749660f49547adb236730e5a7a22fbbabdd8ca079a8efa5b605332db12f455868ab67a1ffd27d1339bdf8d150189cfbf6199c6fc27c05788138a63267eb8ac086e27286b4ef99ee9d92cfedab5ce9916675f128f206a1733f47a597232067aa12da20c7b9cab6575d7634f8c31e9a29948b528681f3f9c13b9f585ebfbff8c28a299a43e4409b31b6c02a79eeb493734fe5f9c1d9e3830572eb54229b5cf525768f695acff48c76b4a6e0936b7406ab69f06d33d3f04946db9d7966ea6e8c50ede5abadda28149edef5223a6938d5c32933070d234043feddbd65c81be218f9d7c497a1ecac30bb9162e60a9bbbcdb4fec4b212050610e2b376aadf58b3c9207860d2650d0310ae6606a8f1b266b6a13b68c3306ed413224abdf19371bac3ea1b964f28996fc70f666ff118c6a7c9f2108d327f5145919c03832f754de35f5979ae72130e39126499037d6fbb3751cbb4843b05d9dc91dd5fc1429da491f72e3069313ea243933b47109af247fcbe0c70f9024ac5a41815655ab309fcaa282d03596ba59cfee0e40f7bd657689453e98d562442fa4c585f970b6983a581b0b8eb1c5e780b3f5c1abb326213c6b5fd440c2187066ddf55f4eabf88804139392c45979440c6f05b7222bd95e963832d7fa4a4760273cc075e8b8feeccb917e8feaf7d3f766d9ae880487e69bc01872ba62b91b8af5dbffdd93fdc95e8f47ed793fc070a5991f2e9ea61439662dab218f643c1959171937aa160008a548f51f87b58f2c4fae5aed556f26bb9cd1dc2b3518458e2f5ec5d974c6e11a0ed639958cc8c1db771cc8cc8bee8727bf6452f47c9782acf548856a0e67841c3dbdb1c98572a4fc8e6cc8195a504019b4930d302a90dc20d8628ae6c90e0206cbb3d05025744db4e115cd3b650e5519a1624acbf226ebca8875b05183b2584e65289f8b9cec3f7d010cb9671a0e80bb70ca8763f1722d79e8decb6b9023baf64b5981e745c06546cc1e",
+ "ade72c2ea29cf829ffe99c2d63840b2eef9b51a9919c02128347d2e88e9f063b86326928cf6252ce4beefbae7206dc61a22d0b33c90d464d551835e3b73c1e3d6e88663deab80c35a607e4180ec079b0ee84e3b7922904e7423acaf976e837",
+ "43348cf32211d7daa300de8a4218543c8e3c7373ad10950765c39760f80b733c",
+ "e4709d225a552e90fb357413",
+ "562050bfb40451f27b1181c389508550a0f46b53d14ca73143da9dae3d3d2b466e9618db39e3219675d2b6eadded7dd9c741d7c9bf3c5619a521189607acbcf6b3964d469d966fa134444aa06d80749c873f0f976e0c5efc5be8d00a2729f03eda6a7b8630575df8b3a19388ff88daf0d00bb3e7c35a525ded90a4511ce815fe6c8904406cf72d7bfa14ca533566f7b54268835285c5402e22a63f98b5d90c86dae0a76d65eacc1ba85b3f5a1499d5f3432dd5455fab9e8bfbd266e99283c2bddf9b556410956b2f061603d1fc91194766f90da841699ba7da3d53ed5abdd8e98034f8fe734446d92b458a731aa4c578552ec1ac5d1baaccc4153a67b48a290602d5f955d61a08436b27cfb0786a80afef76e1266310a42d90feeb3bcc40ae5c4506432dcc92f7e5758ceaf277255401f5c5f4b10df93a249e38edd9effe7bacdf7fecc451d3b2cea77c9bab0403450c41929775b8c0ace46f6928f4d9cf3adf86832d298ea32b236d3201464e2ff506ef01da0e1e389e26e2b3ddc553b369b48d1aa5dd43edd5cab065e276aeff72a4c43206063fc7eea3bcc783ba2221f5b615a7a43a75cecda6bca5aa159e9208bf66af61e2e465c2daee630c4c62077ea6ef0e8b4b4e272d4e93a5f5284f9da463e1a60f815a8a31698ecdc09dff2b62f00e37aea5fd4b07a110cef27e12466c1814d3b10017cb9b8e12f2f38f10cbe31296de2570d5662b16639fcdc05db81e0d48178d055ef873501148d00903ec771400fa4873c5579dc3265028f531538f6dab1e5607a15c8b90cbfa4835107cba6f453bbdc71d08c7e423f58b44be38a9c8a610469f2551ee6177edf639cde35fe8e02f76b7ed106d691a876a4fda3b42d8ace3e0d3d4e026206c5d7d4d56fdda9dcd30fd7b74217fab3c617903f1aeffb8363443ed128af94c391810e327704d6f655e57dece97658d41e074029823850ddf7c5937af41c64465046d8544bba65c691ac69121bd272107f7eef8cfdb6a25da5da16d1033cede09129d51f6abfe63905a6fba9a64d7832fa35825447150595a60163af848eea878fb31a5fb97b1859efbfcc8586eebce8cfe64386461a9b88aa5efc1db43c64dfd5d4a45aa74803fd178f9e16a3f59acfb6e13a564d645cedd73890d0a82fb6dffeef527694a7cf2a89aed9750c3675a67505bff77de8d046087bd39a85c90aedb085e99baf04c7e3bf92e350b332da1b8af85550a00d68904ca426da61add864496d6ff442bb0b848e9aa463bb0c2085cff1a83a47d6f702bd184cfb5c139752754c8978d27b58d364bd88722b9097ee3a6ae28eabb14ca7c31e40461101e92448dbbc63b55cfe56efd078d0058c5e6146c73bcd949c4b3ec9f881b9a5f7b41ca83301261e0c674f2d35d96761baa00ce0675c082bf73dc52dc726a3e605067569a372d2bb47fc8fe1e74f00078ce6f352a6d9d97fd2834670ba3a45aa6751eafc7ed6694e1e07542860c8ea516f296ee901a3ee16b00b40419c74bf6db12c7230325e85a918f412bc2f6469c1a13a5aa77f028e327749efd05b91053f49d9f1edf49aa552c58c68257233a168db60ac55b4086ddaea275b078869cda7b69493c4b371b4e9c8361357a7ac7d3d3bbb464c960addfa8df2b208b21b090d540c440241598212d33273203d484e0930e22469c2a8e866579a4a2b3db8f8344dbf8baa1b97be0c4d976f6aaf14cc09ec52630139b894b2b6f4dad3a205a7b286253f1522b1d6e43bfa37beaf06f831c6f0945cefb2593b9b298da13b0d910582086c5d7e256ed4067bfb476dbe01bcddb437d46ba716d6ace2ff9912c8e460ad33ab3d8f97b7b08dd4ba9e01968d1949ff85b4b9d5b8da291fc0f90ab1eab1d246f67d76092b7a37528ceb388dd76f8a8f0aabb7490f02a2c8bc6498cb26350d859c466dd611bf0ceb81a8b7899c67742c22697ccee21c4963acb003d15c1a2078112bab05595917584e417db3872a0ff0a29138bbca7314449b19827525340370d7e48fdf9f7c6b4a280e78d00775a291081a5e78e7a00ff915015dd5af5f0a45690baba8b1b503bf85f326c23136f4424be4a559aed03fbc81400ac27a33dadb2155d1704950d98043dcd86df1eee78f3f266c4d14deb8126708f74b59aa15e8b497c6a52924a473f999aaf0abd3d148fee8503a1568efec7bfb0bd463402f563e4019cc9c9e1eb498aa54dcb659f43b86df0a34de4e51ec558bbbade3d69511d3fea2baf44f67e85ada7398d7f72ecadcd9e981f82b0743ed74bd33088ba4cbc85b0c99dc5382c599706dd2d51aa9f470c25a98e7e8248dec216a155495630662bf6ba0b7a4baa2cdad30e9ce3e1a65e3c23d69d5f946606ee8504dd70830aa5a8ddd84f10e064695469727d2efeb46186c9d3b7a170057636f05b9ec4c2de7d935fba504a1e7eddf7a5a95226b253b0b9eccec976ca3c57599850db40c27a51ae755c1f30d392467cb74e5c8235861d11d0f8461b0e1d84f5718d64ea92da62f4de184a6499dba473e82b3d197305de0e494f118a263237c7b4c0652327977edb427ccded35552c00a5804b9557ccf2bca2484d9da2c33f6c1bbf2c666ea10b4644a21e3905e5c4eb417ac3572e783428d23dd7222e75c356b99e8183d033034e29e618c90e66ec2f1e9fca47d82c1cffda8ad14c96045159d9437e91ecef41d24cff89009ff57e18c1a422860aa9cd31dd2a85b07422c72a5decc614a9742e62a4988f394421b6918e51c2412d749bb53b1e8fed7b2ef0873ffe14fa77bc366bbd5fa1432be465f5e25266c6c12b55df1f19b1a491acfc5c9019f122c422243d751d8eaa8ff721397915171556e999b34425f7d3ad6f6c3323b8133b4618c65ac16cb5941edc979472734bdccafc73c08939c0b1e306ae3015faa9cfa09ed6560269a1dc54c2c046a12a178144f4381f7b6fd3fd2d28f778d444d9f7a0dae00ea96c6969b78ef326a962d23275f1518f0e6a2469440612f3710b53538fe99a6179471be8c5b2d682ab3e9a5126e41ed6de000cd9e92fec3974e0f4cb2d2245d03d6ee80d6a793b16efa829d75c796f34d4e918250f457703559bb48ff78f0896be1bda403b7f1fd6a319d68478ff70d88238f2b8afc7d20e51757bb9db3bffb35a8040fc0db913c4f03d48619af7fd24cb8986b3e139058be3cc253b3de9b3bb3f8dab7b8818638279b2e6a0c29cfe16fa7250d3c74362ffa07e2977cf562140fe28afba8f61d81f7c73bdd4a2faddb00752bb049d0a57d05c6475c7387e6716ee31974169930c9fd830cef138659cf56f2212de185186c3d683fc6b7fd36e7821f69d0de041a569765066dc4a1934870a7b80f174e8f9e484942e62404a42b21658467873865ef94fc262c231527f39e82dfec91215947b99567daf75c6a28073ee4e67d4307e4b35b46f85433abd9812f35438b34598ff3b6dbd60b60747ad64565391df45ac80b272d0141702ab807fa27c6a6ba2f42c3facfae0c773940cb2943bb1353b41298258bc0d07542b69483e17ab9ce709e4160b80a0968dae9af8fc7c0324c753ca4a11a6df32dfa79a87b445c988154bb3c503e6884cf6d8f5e062a16b4ff230fbda109a6127d35e3bf2b29bfd3b18ba275af773b1981d603300035e046ef023d51874aa105d136bfcc9c7323bd0513a6b2b397ffea71afb7a8d4695411d86164917099eef504f6cff3c5cefb88f23f56c4ae3e2b09a3f353fa55630f45f06c29e8912e8c3c4f493f25eda781680585580595bba43dca9cfd400d9eaf5081d2c6697da59e012dfd0b875336b88fe16609c2e9876737b9afb868ed52417ed0c6b359d582d585ff82d98edd4e63c6b65cf43d4f69eee2af4819157b8a433966953862d1ff2c6d0cba382644a1b0033ddb7be3d1fa9a204042d7b821b293bd659dca980c108ad1db740800b9bd2fc1a163f9b4066f7604f160a7910bd947cb48ce6c81e680fc6571ff0cd12a3ded9c8cd560970ca5cb480a70a8322d5072edcd257604eba8dcf55f9ec97ea2b14fdcc72fbf615131836fb14e42b8d7171d0a06d2fb3caec2e0759e86b0d8f21e312d9211ed7fe0b48669934ffb892baf1db9aa457c07820723e5446420334bf6479f2099e01ef8adf273adfdd9ed0b741931284515d69c211cc2efead8339e450b13be71b35c36c1f00c2b8ed0cfa9792e422912e14b5b1455ef6abdbbec0035480c6cb69d21321d12ee19d528dd48f43b142cf0502eae5304ce52b7fb827552db9ab885b93e83d56a33346135aef11b7e48efca7cd52e2499a7edab0bd0562862187ff4599b2446bff11c37181092fbb05d0e05220ca6bc37f529d6599e8c29acb9f25616c27df291d4fb07430188e6470df7002f73cfe5fe6907dab0b4f90bb58130fe90241c29c6063a22c9f45d032b282eb92c93736692bd5cbde2a17552e942b595b08e6ba0c91a03b9079e9117fbba8f26ce6c5d0500c69bb6e22e3562a50baece49109c2d42b6714250665afd0f0a7e951182012f21aef4b917cd434d9ca22661437608e32666497516be34652500def6c28ef8f56f2273de5416142ce9606faf7df92ab779ed6aa74cb99bb1bfe758ffd344e1d31f479807326d1a7b98f6811e275545d69198707b0fbf027dc6a5e4815d62ef191535569a452c27c4e25ecf139df949d70dd5935bddc04f33b2f0bcf5073c51fc51c15067963a20569b5659f0e7413b347d6d5ee38a92b7e6e656c199149f07ebafe5281db6b1b2ecd9e0384b6f5a8e27ecea9a0249c61b16564964054f5f9621471a98de132e102f518c1419829e2ae2c8c5fffd1270f0a0b33a383437b0034783d50bce8bd7420c059d16364eecbd55b6ac8df8a70382734d8127f4f5895cc9e508b13c000ea053ab59b87ee639745418ffc566ceebad37a17b842d24d3423ac3f086142c622eceaadc4106f8c90c5dae1f52f407fa0bf1e6bf9385cbcbf3b61006ea3b1e66b693ce704577ca9598587f41e05d36d1de424e0e51290a5f2e2f99f1960c0253a046a49b19eef249ca2dda2af1e8dd78411088eff1e9c23c31bd20abd4fc9e7eab19500827d202f76270fe9f90e95309516343e0fca48e5a12182e91c78ebf2cdd4644629afdc90bbccb77546cd765135910ba1cd8a3e3c00fa77e585865e898bfecd06c01a0a4d7be483801099c61941c4967154af5620b171b426cf229df59d2944ba50754140c3f305c16956953be376fe6e7cf31a2e9c276bb09cc24c4b86b2b26f039b0d8511853adcb7feb8502e7641a34e3242bf2c538006bb1983345ec3cacbf219ef10efc1681d52e6e1b1c60bb556b6b8a63d1d1f6869077841d1b816f3165a35833e33d39a8c6e62a2f7c482c395768fc6a0e3cbfc7a1a6d64da53adad66c8016f76eaa73df1b8ef83012ecbe75c92a8e39b48169433f951a539b28a034d5fdd00639a5e3e17ef14dafe869064d130c90c68be4d5ceddabed1bc94e97e2cdf7313f780cd6e175a9e3eba3eaed896fe464073fcf07ae7b5bd41d58c3160f66ac95a76fdaa7a8cbaebb304fe3c8f03cef927a1182ac2281c3b32378813b24bb99e42cb0774331ad78b74d46b8ce48bbf4ef8431a82d4240edfd61b910c38570ba0bfbd4a41665117e6d5f5a97908462e62d0b76160d06aa56cc6e17aaf4607ba8263648f2a0077e306c25486f5f39a75",
+ },
+ {
+ "2f6210063cb3071b3d49339185c2cef8357b08ca826d8d1acd852540c16540f1c850f70404fe1f414853d3cd15a1c64a1cce149e3ca1b80926de4ae8438ad90bdad010decf2f201782f3e49794aae1b079f54eb59607bebde508a528927e346d4e444b1d736b34f65e198df2c36fa23c64f1f1fbf8b0b8ddb85d054bdb39b8297d0347f16f7be7cd9474c058e36294485386434b36fb28ee582e393367f15ce5f5a3d6641fbd31b331f10b1554a05da726a0f35c9b1b4af3498426b17582966a266cce452900f85af1046f45a4ccedca6ce02607fb70fa45f420f66aa38cd4c9f8a30e21a3067b940aebdaaeb7c77824a79e2ba20f26e70346dd6de96942b261e5c08288c7fe1cd1e9f680a0bdf8c46497f007a616eea95ccc17463559f8973eb919c68017e25100d9d1a196ca65fb615502076bf0b0c8bcc70ef22006895ebfa2243fba0791bae0625b762cc1718d1673948264454a200c58122d5e9b8b1e3eb05df8b7eeb297510e0d7dcf7f0be5f29f6756e4b177f109891e6825a9866359e35b10d20da7231bb5a0ea34abd0264b377d2fe9f420f27d3e5aa2e8e00541c46052966ef9b989ae5974e2054409507b867f647aa057f7deb19ac6929f0856005aec6e53a5f702fe6be403afed532b73d38fed73e6e551987f182a1e20801e7a6c8ccd1184cf0fefb4139fa166ca15395902ac40e7fed8661602853682a3b0ee307dffb44d0ea3012142a2880cb7c166ba6ea6a16c7e0882808db8023068f060e5ef1432fdb8331ffad6a7078d686d47d613e94291f1c4117e7c13aee4030fcaf223fcefdb300ed606b5dd931e4adbf45dc437eeb5fbff337812e15c15f026071423f6ef5305c559baa2ecd8ecc7cd498b043740ff3673774855d45d45fa64591d5b4970600ec91ab1b6f39d7dc0e709c41e49c355bd3b9d120ffb57095fb127bafa971a086135b917285794e83e9dac5ce76fb1a4aa4fb6b94a0dc3a9beea64b8817ec1e2b37af9dbd18ec30f2b6f6c12df1db6896c6c43b67a066038f0c4f17142b254f62c4dd1fedb950d07047919e397d06d033cb0bab6b61aefa6dee01720926b16beb9e8bc947dca9b8143b565da85d2dec182987838b267de9047f5b0d961c7971aaf54ae2c1e4aad61ff123c84e41a4566b2bd9e64247cf46b72a444d36bdced1a309b464ee5f4afe406eb68eb05ae51b76bf01b906c0ffbdeb440b11f1c9e3a4c3a809a1f7449047b356c663a1ab7f286a70d16141d11f2d151a4f06d422ab97cab539c1f9da09ad20c000c27b8fead5f0cc37329d466fa260aea934c154dc9c0a065df3d057a0f117a1c38321ae59226a8054f7d6b49a3753436c249838b0924f0e861f5627106dd8d3f0fa724a1cecda71d4a1267ed889b234ae4a7d5edcbc5d52cba389dc0152aff24d224c6a0f16dbd3b7f242807bf4b51a3f22690bdeb66eaa59e8766b3b265d784899d247a0ae1b58a06dd91c529e3691b09f9d9f55fc39afd4a00b0fc668880ef25a46a30861fba8cfd4b51262eba4138b41a2d13ddc71128c8c1242e49a51d6f49879fcfa7595ba4a4adcad3670b0b1b26382f03ff402bc70150f54bf513ba3e9a590e41b269e55616af297ebb3499e16cc8e46c0810330a602955553c0f93d668a1181a0bfd7021ad9a9f68ce39493b012da70a3dda149d0369f23f788616e0272efa322b6a54d804f340d32c890e2eb7b538f48f4c9293b584d22d0ae80d321607644271b81a76ac5b49d8e457069b0c3e909b8a222e3fa6016cb1e979e300804742f2005c68acb7b1849c088b3714c9c7af54e9de9390df0041c87924c8fa6b0aec6b6754171e059cba0d27f221f0b9d044a3aed8338dd8745651981e4b0329376f908b86ae9022699d495bbe3a148f7eb73d56eacb2e5e2180f63fcbfa680369f88eefa71f1210bc5b6b7b957f0a1437476a2112998033197673e470dbe7d9d476c97b95db8b5136f6cccc75d6e0ac1e4ace30e34e64fcc4d7e135b2c80e863ed701d3b28c25e982f1b5f8c895a4e6df7216c3c07abf8551a0ba0469c88aa7a08c7b5218a03b9b91f0935985373f65aa56286ad0e7ef2288a926f172b098123c136455b3a0f04590839e16bade7b6434a3cf048abe2612684c03dafd9cec39af508e63f07ea881014697bc24122058b5ef5d3fae835216d055f0cdf1dc06a12c95041d13ac9e15f235d11747f16ffce1cc3b8f508da520e395edd471f3759d8879ba9c2558b1188d822fd4739ed0546b0ce3bb9988db7c1dc8518ebbc62c4440e6e0653f917dcc13aca1864b71dbb67dbe7117474c936414e4f3cfab1f13eb05f3504484ce11977ab21ec523f97ba1b7ecb8fe384b634c30561cdb752fc67a2316bfa7e4d03f5f825d24a556a0460d8cfe0cc54a6f117ac52d553a5d1bb48031732716436675c5c3996b1939b127c6b0338bfaa29c7467cac9a127e455a715c9ce2b0c35a0d2f83a3d1273ee39399e6cc4980e610c752bd51652b96bf9cf34c7fa41fc9b13f5d55007483e4082ddac4675baa7822fd257452411b01de0e5e5da26e17539d64a89dd93c71d15a4c95b1a83039cb2d5f3f7fa04a817e48dfcbfb3de34ecb47f7592123caf27e17982fbfc8597af5b8aa6558f4e6c73db69328e47677afbe6ef8df82c3d1f0db6a108b2279f61822908d7b856432c32ac5ec0f3c53befab2a7ca356b9c2636f646b228b0a830d348be4ece2271814d477d4c73c0fb6e83a338b90ec4ef45cb25f7e3d6a014a9e8d2e8a6f55a383291a57f15667a73ea1daca31c7182523ca85a107efa2518d2f7f179ed4ba21fed479ef2be09669817133b2384bd85b155dfc1c4c9e6dd9ceecf06cc1ab8ebf7f07aeaae7441468b5471aed93f248a84f44c59be33274b11f651de010ab9f8fb24d3a99914e0147951c34280e7dd15ec196f9a4c86e55e7d373c7e31e6672d1b3ac6a45fa6c8c9088c0b8963d89f4ff1feea3e85cf9cf2f6c97128afd845bb131c6f62b3282bbba42745080fd457f1d3322058f1bd4be876bd01269546d1a853310b165926c1fd4e07054deb5d3fbe8f6007711d435994005aba95918c3df4cd390b165fcd139dd418ebbf661b6de57b655698a8a02ca8fad73e8c536c7110957c36e5494a831d536eccb97a2a9ef58fe58e2885aad170720ffcc57c7de601ea1cf723577a30aad8fd544317e33897c8b6c04e5191bec391ab990e197f10038c0726d371677e4a54c28d7ca5c6046e7cc4acde565b91f7f72af6109a0614160d3ae97e9257b8f71a4663b00c681e793cbb478306e97b0e04711eae7722b4845dadf2fff5bbe71ff24acffea2ee67df99bf62a098ddae9d4ebd3bc5dff04a2d9e3d1d83e8f493db3f63c9e24231b1dbe1147c79f21b0730c842f6983330c5c17dd34556d7e932074cfbe98f2dab5b0ebfd778a1e28fe2bac2d942f61a08b787ebfcdeb3d600bb130ca4922a4ffd38ffc4a1a1a7218451e45da4da67ad81ef898ece3d54cef877cb9d09f5dcf72eccbbc06e62f1e2b4d64059b0a807329780b155ce1614b68de04387d6108ef4dd3ab54b9da72e528d6eac3e16a360ae3421f3f23808a8b5e8ec3dbefcbca3c9f76905850033d78d9283bba9272c475b4e3b4d7643e62c2cc259ebbf168f890de88e82f8b26a7654ee31fe055e45609c70ae02b4942ee15678cd158f4c9e8d351d102ddf7a942458c6125e1457bea0d86ca38cf0c26e474b2b5cca77eb57ad0867cad7d25efc2b250e79396637ea3e948dbb855029cc9b452955bd04ad5a0d0514d4d773c0f298df7bc235a3ac64383a1fbd8a397a158e936b3ba81895a51daa89f51e4ae7a71a53794ff715a42f4fc3dcc9fd56df7bea4ab782534d3760e7b15605fc4dad16911656983c0ab77bce9445bbeb1537c55fef57a32c8f1404306a0a2ca7b73348cd99d0f9948875531cbb0ef7c036cd201614c33293d746c44140e0e8f82421c5bdf2bf428b249597df949fafdb5ccfe1618323f56a6ab9abab9a84a3beb6696ca918af244d34cc1cd95bbca4a87c860a0fa9ff6a04a905b0338a53f230bd5ee9c60e0e0332ca200c15dca0be5936b858d0a7b2e540b8958432e9767396c55d5cc35b60062580023b5cb2f9a5e9a1feba59a19f9a5a251e9d0e8500955a5df21da95213ced2260a2ed8f3d4b295c36cef750c89cf21985c302d5cc577aab7855409a912dbcf1d0a9800df4aa692a78607a40fd6d5a82305c58fcb3d2a82b27e8c5b91681aae62a2bf31ed55c494dbdc38eba30e83c6044945df76705228eede8470369f2e9941ddcb2f239fb3ff6bfcdb0efb5ec50f981adf0e8b213769ffbbea364b08cf8cd69abbfa2a6fe9865cc48558134a57bb5526b9d047e14a379d246de82d3d64f3c810ede280c768dd8bee25af287d5a8d94045ddbf5981382bc716ad9aedfcd66e0ab496172a24efe80649db8e1e83675fc8451e22c6564d8d6dfb285af7fec802b35f19dd8308c68952a11770247fcfecc4ed0e8a445c17b1573f0b4e3ed350f13269ceb572943fc435563459d5044699f1542335b03be6077af156b8c5a6a9f71078ad820cec4642427a9b187ee1b17036d5a5e6108cee8a7d444342eaec3afa64e77c71d3c2b3153d4e2dbb30df2b66b4d14cc45d3a4eda7e911d697e5763e23ee05311a20626df55549b8533c6ebe79737abf472f9cff08bec590943bdeb819d3f923f45b81f9a0cba1f3f800a261842d10cb4cbdba456c7fe5f0abb4a8b58891d97cfd6b669e2708922f1934809d51a1589e5f12e3bb82c9ac3e7e44e3f6e6cd63d428da624fd2f46eec38ff798a90d228efe50c9b67c63796347c8a2b53478f27605999a03c8e1f18b70e92419f646a7f49670aa12d324751aec17d0208fc296955b3098241189af8172d39a6819415cafb107c1842b369f174d6f37dd31cd728dfd0ab10f93609006342b6e4d6ccbfd1ed2bea2fdf5411442b04b1fe218916f159b20242f80b535b4e0a3024c6eff6a40bd0d3db24e51f5ff9c14e1b4a650ca4170ee70f0a3a5a58349a7d0b7a63af86347351696870b95231f76d8c5c6a20736907726341dcbb76672871d18c2157c094b929fd29d34f5bcaacd82706f89a60000cd341d98eb830b73a12335b69f3e0131ded3ce12c98bbd960d2d0696d40696a13ab43925374498d868cd8f070c9039ea6407fc2d92b9c39fe7c935bbcfcc5c0980952fb7dac79042951f49a1af828b138a87401c4104bc28cdf1e39dbd3fa63dd4d5f5ae9d85f032a43ad353bc5e6746e5a76326ab1f4e79103116ce70bc0b459200f32f85e461291e347dda92e421778b849e37a3ecb0b31ec6818e828dd3148dc74313aba43cc9d8b9a36a9dc4e229488060eb6c109f8ad6201958adec6d3bb3b04e5e558a272d44cb98e18f7a0ad8fa6ac3667a62f150830aa930f6166baac6b9081b44304988fbe1698a5b746255de26bb5988aca90bb6523cad68a7572f615f4aa58f932d8a749615cf0a7724e99de042268ceb31433e6df0a61547d576a6201b36b348c028ded5f7e94d1cd2eafc141088ff42cb3dafbbe4c402b93aa9d955df8d9d9fb57c75ac65c2c837acc44bbd4d4aff1888aed46c73d625ad7fff035e8ca0fe411c73ed8135b6b8e17a039ec74e9de0d64cb442bf8a676c0a666f68f21066332cd921ae0ed766f0516a8e19b82cf98e78add0373737a3419e13aa902310c44feae5fdf8bc64e80dce772686a31f141bcce452041bf545b908ef4a2b000e7beaf378e2afdccbbcaa42e330e5024400cf2852d3444718",
+ "fd5008477b0855f6f2486fd4f74b9fb4f6e19726c6996bc66893183bd76054d5b05c1c2b64722256ba912ab2dcca66d2abfdf972966438fff7513acfb18ea461eac08c4e32aea4ed3fcf9f1c9905ee4402e7b6984bef974340d212f160b6524b76de99a98d3e96cc0d35e8a63ad7ea3cbea1d40a906c4dd03e5fc19e1513e9",
+ "390a5e75c9ff4ad38fb6205ff47f209294337c1f25ff54a3c01eee8e1e220257",
+ "8bf183347ec1ca4bceff3374",
+ "19fa2641519e21293094e9d767ee1237f9e0715dc57172794867c3bbe2cb647f9b28a8d3f85c0ff557b91bad66f5ea16e0107757b0277fdd3ca05bf47c19bcb92a958a57e8c142a51af29bddb20af84377b6db65f77494e0dc4d2634a776b3a5d777319873bc0dacbbd4b9ebccfae849fa7e9769cdf54660ecca0d5cf4fa5190713726d54d02b3a3f21857125b8a808c0ca2f99d11dc430ed5113ee49ff8f00bcc08f0370dd510e8100e1285659a7b2c7457a6049f2af7786c4db1471ce5bd164e11c7a2165e83e03a135ae2b3429f82f677de044a067e99e0bda2d65a7270d629c00e1d528212d3aeb2896e58ee5145a93ed06a9c00705ad5c5988d3a192304c1d17661d45257c5d16799ef70771964435b12e3b2ee9d5b467c3b1992f45b7a59871b40d8daa1c280747ecb3d170257b91df1f549ce6d66455b5b6f60b7c6e95c92a67e20cffe8599ceb183de53f1dedfe19bae836447af8e053ba419660e0912cad064d6125b9e978e8d0d5f28f8a4e43ca3cdf2d4c0e9a11221d8184e9eb6c90761b0beac82d0d22793279aedb1c7db3632adbee323bc3bbde4801152694831abf5676979af26af7dcbadfba1cad1306b635840cbca76c558b37db0803b4c12befa27d16f21506b07ade4a838d6beba1816eb29ed5e3c4f132a752fc747bd9ba879156e87e6c1584e911da9f796e1fa4a055e427272559e4bd6d0f54b8257100f8a55d84c27b702bb1fe2f995425c85fd48b0a0610db5b39f7a5031407a12dae9f508b21b1378f14952d1beb2dea81d016b2d9b7f1a67b814569b69c0e619adea02a8683242d63a11d3317d060e5b4d85df5ad73127541ba5314715d187990735aa81f438f8b94070ec506ba536274d98b766c1694e54367891a602b99e370425b47a70b819277a249fa429c5bbd0530267f987e6022f25030c30f3baeedc0d13c95f3d5e4b2b87465d179a3a23b9f9e76a42ceea55226ce072f9488392f40621289124d786109d2498e74fb37e2ef466fe8bf3016d96e34204c32978775765aa80461cac48518157f86d59f6187bad4ee62fba1ddbe166b29452f4a59af1e057300c353440644a8e40ae8171ea028be2fa315804abf518847c7945e8228b7766cfdb08d3a3116b59aab8e94b6d8c8c9ef442c2dc7f923bc2cd3e5c663baca7dded976bf191fe36da16948c89c385fe71434f4aa5dd15fe0e925d2459e3b068b9d82a9cc8b8f9786bd9f5fef9baaaf2d67027d9bfd58bb2c58ec7c746b747ab62f9242e4b53ed14d6fc75f5280eca0de23717c97a2293826e19cc8eb47f946421516c349dc4ba49225b91e4e868874bdebd373700df1f3792aaa140597e58b88f90e163397dbad3941705b53d754e3e0c9003df836a7fb8d23f40362fcb5f3947a4281b24240be4ee89aa8e917b194f94345eeca224df0adc15f22a617b6427f29410bc48ea3f92216163785723efc36301d23ed52780c6fd7924bcfaa03269b13582b7c7ea9c0e4a451f38a469fbdb585dcb7c81452da77945ebe27eb26ff6e8c7b2decea289aac5af74746dc257c9bea44a0847f02c4f586e1d76f39d5bf952355a0875f177a666d1d354ad86ce5ec0aba2c2b20cab050eaffd31095395132f5af80a2d2d53b77bda49f948bbb37bdf31c8a690476488e14e542ff6841e7fbfc2eb84795696562d079dc1612274b6dff362567084f793f0bc2dd8de23392d05aeeeeac6991c9f74387153a4b7da94790375e336a00c8293bad0fcef2dd1880e7094e2e53f738247c860780ebe308410ca02ae409ae720e841f48c9677acc6e7d4ccd18c219c400f8b7e1257f692e09eaef96802b17a1cb7d93eb81d3bfcbc7af4cdf05b98e22556b3d1a8b56d6d83bb5f5724696f8f329839dbe477483ec3c09fa2e0628faeba1bf285c224bea3f6cdc7bbd768133c6ef1da14f248cc3b819b196588811b073a7291817bd1e89c65760435d8d17cbf9423744a92143e0f956e2977b39c54fdead5a57f3a04a0facca01bbf44d3b1fb9c4fa83ae1046985e3f26aa0a437999004dd8adc04c5111759849f919b93558dbc559173a23b069b59f800096d9fcf077c7640f59170bb9a6fffe64778bac272365d27ea62aa956559e90edd3f6393cc8775597bcf7d91990ab9511973d948324a27261059e93f4b5dd2f70caf12e1a08e0493cb05588618764391f355379578cf94dd33e616136eea997ec11c0d4ff064ff51a767e5558433a2e3a9a74c232d8e187f47b8cca010709eb9fea0dac8f1ea53bf18822e154ecd929c83b0eac366e30fffbd5ba6a46d734f58d26e7f5df538e18b3d827884aa857a680823131bcf30a76f1a555bcabb17b02b53aefad96fe76f7312da69719434c580d3ff1bcdcd594e6375935003d5d732cc577e11ea2abb1d04259f50aed4c3af9866e8c4a52a09809046ee330f05c4403acbc297a9416c5208fadb31ed4eb7a3b01b87bf08c75cf44c2b0df84df30872d021d6567ea649859268e5e1b5b6405e1b41e350a32c1af13722959c17c01b52c42241313b26b25995a1c89a53e248488724d280647226195746901929501df36d1e94815d7fe6c4ca2731f3181293217f71b9d7f59c2474856972013924ae4796db4cbd22d8905a6043c959941ca6b556c53d1688c439036c715d33a47a7dfc2fe40e53424c5093020d2e85e4b04aa4c704ea5bfe5a2384878da38319c59d41d66b6add2a443d9ea11edd8d18fa41004251653857733b388b453943eb33df93dcd5d549757fa2967ef0f9a5105836c48826c47fcccb2d9bc349032b286962136b848632bdcf186a08cbeaa52d195efcfc3a440bac154971d11ff4994f293b14fb8c3214ebe7ab8b3d0f2fe0b03ed7b145fafd7730a173e3cc1847f0cdf2cf629f5ea81a07bef716b1a67dd9e3b7a52fea1aaa7a393f53b5bdb5988df78a57a9dad19a8253316835acab8a6b9a9fb42d97bf29b2443322f46de386fd82bd3453ed68e2370c6eac4497b1bde7b42d569c452f377bd38bd50fa5a6792ef5c9ec6c647001149b86fedb3e2f18d4271e9cc4801aa16ecddb31b6a795fecabc613bfbc8e4f5636d71e74595c841fd11b6a6bc7f169317c1added56b82a71fc36d774bb4d661685363e9da5fd2e1f357006dc5b5bbf8b42ee3f869e75a541586fba558a8f490d641b78c27368b9b4c2db046354e9358ae9140e91cd95ebeffc6c0d2676a3ff4ab10d463bf32bed97023a80a79df191ab9858c43537a03072a17c30b1bd99efbd361590ed6b7d5b0ec4e2326fa35904ab9a48596f44491cbbc0112890f9386ed04dec30126be359a05e99b2b77fa2c8f6b7460a6cd590d71c73b2a1b23312ff89306b6e41c76ddc0a099bfa79498e36ae5cf0c560b8854dff32d2b690ce0ac4aabfa723ac6f2e97ad1083235196b464ad67fdd649aec01695d55c8b4bb198f30630ca635aa5a1915f3718341bcfd8b522f764015fa5479004d28eceea7fe67df7ee24a97a9708d528b89589f1899f13242a0d00f7464c3cdfce213699340e754533b934f4a8410224e111f31cf8e54d7b5e90cd8c68bf96edbc8d183894deefdf4fcc1a83162a3f6341dcd9a9aecf171c0df28257a68b1af1b67c54c43c3cff27fed89cc64bc46e23a49ec74a9efbab7981d9f0a018247441e4f0f5b5f68ba9325582f92de4cca4a5f878a0c5c387581e64324e3246d8f3205c838a29f1abeea24446e496421f0e742d411adb55f70272ae4a992e825a3d327e44b8b3762b25aa451d07eb4eac0322b431fa676462632daba2aba7bdeee1b438f051d21d4b1897e2ac2f95ee7c23f9996a805de8fffb3b30b855cd6c5b84c011accf4bf94d304d944079f04b5cadf8fcd6751c22a0f9165ab98998b2d89e6514641f1f3b91b8c0bf057d69c3d893fc4e041e06a2229e2ee58082ffb58cb920972ede58483287d0ace94c1becef26a410b93e4ff402e61dcc574b790d49679f18f4e2004f8b7cc357faba34a80e56821bb5b883d1a8b49c6605002152f270bbc36bc79095644e29ab08cc988deda765d67e4fff12b726d5de135ff9d0cbd9d5f9d440e548836633b93a38330d638468b59a32642da3375cdf70b062d14b46a78569c24a706e179baa2058dcae5c61fb6cadd9e015b017f26e9dbe3e6366cf5f1ec839aa3bbb21dd6c9b8e910245fa95b09b7d6cbf08a4c6c84bef257a70389be962dad14d97a893c128b73bf6580689e540d004f21edf8403f36b1ad7c9a2e83ffceb141af59700c316c8c1e3347187f24819c2ff0c9f9a2360dce354f3374374eab1643d2d8831310a8e3ca6768200ea7759822b82f7027cd450479fcc7f6d04802b15735a137ad489f1e1ee78434a253a9dd16684ad58fc91960cde6754f82e8b38edd5e798fdbbbf8fc2e2380a4e21dd94f8c1c063b18f29d8cd8d89f65deac5640799d4ca2caa29c1e72ad8bc417490d11e4051d94956fbc74289857e5f8e9e87b9a2d83074a994de0b10bc7782f6650cfbdb8c835c81cd88bdce5f04ca939b3c5cd010d4dc5d51224fcacbca9851694b8bf55b22dead859d023eee5a7ad3436a912c3fc0284456d5d72ea5f1afa8545c856676ac2dd9a057028bd3ca0f50e7070fa74152f13997c95c1834c3e67504f1a4165d2b49a96919b88f72caed60f56ca7ab5a3204fb12ad3592c725fdebb048732fc189c7dfed185c6c184a626e07d7356860d00389862d5b9701eaa4e5f7889e6db0f54633369b8d26805c08471de8fc3f8fa1fb0b0711d9e015add5373f7f8b64abaddbac3399c756244b1b07c579d33e4967e5e0cf16de29cb8a7efad07ff9039ca305772a6e45c76bd9b77e24949556766a8b8425c5e595efb431bde4ee222f9eb3fc2d002a1e2d14db2b23135266c942eea33bffd30eb0218405373240e0cd3040436ca895093bf056fd001c00ba59d90502042e6e6c0167105051628895c8164c9ab959400898309cabafdef12be53604fa57df44e0a90a81bd63c331291a93bffefe809e80db0679568f6e94e0d8e2edec0087c35bcb3c4f4725e6013bcf197156cd9d90612423348123383e45c14d27d8833f56ddb04083c069fd6e282fe69c940840f5f747dfb72ad72fd8cf9f3ded15c9e2f4727fd60b4f40e95dbe77a89b47dde7d5326942600554905d9dade9d145ab6da802643f2081678392609c2fdd1b79dd8caec137cbed315374c6f05c0758070f3bb17e23d81ccc39c6aa89913897e487fde889c5aacd422278f8571641cc4f0a93d9768aef9e45d6bd187d1ba637ce0fbd3c573d6778cf7bf5188c00dcdf13be3fd599143952b376220283e34e014e83b214bd5f64eb0ecb098ae8bef883949907cc36e22ece60b893b963cfa73d120513e285aaf70ce5add34edbdac60b3aa7b385b90e339058fb9b3cf984b06f79788016035c5ce490f2de7995b98a8c1c9c80f29603ae2b7fc41886663163e604275cb085f8453b27f4d795b9bad19ade2f98a1c99b43a7581bd991e5d0e5e1a6e713acc522ba9fe8302658a9782558e35436e714ac6bc85ad1d3cd008f24106901fa954f5fefb61210d6f8dc9ff35c480f1d14e59c0e501917a31ee9d00c6bdb06a00af5a8b08c3928cc5f37476248223627cb77eaf0e96213cb0a13e97d3fe9b9814d462690e8d68d02655a32fc271ee73db4f88a33386ea88a5857e15a28d9b3e3a96f00c7cd85aa53f9282ab8c8ca6d6a8afed43aa87fe7fc1ad59b0f0db2dd25c20af96e8c282c19fc883ef01a4060398926a1c82f07bcd3bc314580d7636b623b7bad8ddba05850291a6344df0f346fa4a321a85ee3e9c",
+ },
+ {
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b",
+ "0942e506c433afcda3847f2dad",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff4b4086fbbd1b6cec23e45481eac5a25d",
+ },
+ {
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314",
+ "d3d934f75ea0f210a8f6059401",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f685eb7731024bbf6794c3f4c7c5a1cf925",
+ },
+ {
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314",
+ "d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc07cbb",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68a12d0f1cc99e132db9014100d9668c91",
+ },
+ {
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9b",
+ "bc",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32d4d00a24b826b6efb16013ef54cbe170",
+ },
+ {
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525cf08f5e9e25e5360aad2b2d085fa54d835e8d466826498d9a8877565705a8a3f62802944de7ca5894e5759d351adac869580ec17e485f18c0c66f17cc0",
+ "7cbb22fce466da610b63af62bc83b4692f3affaf271693ac071fb86d11342d",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb37d04f8272e741da2802c54a9d9aaf8ecf38b36fc9ad0079523f6a4abd5281a22697a3180bc02662a7c13ee23599d18e5c48300dbb831509df4c172f53e524b3c15124a87ac73e5028cde6c94d8d",
+ },
+ {
+ "67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea90870d4b28a2954489a0abcd50e18a844ac5bf38e4cd72d9b0942e506c433afcda3847f2dadd47647de321cec4ac430f62023856cfbb20704f4ec0bb920ba86c33e05f1ecd96733b79950a3e314d3d934f75ea0f210a8f6059401beb4bc4478fa4969e623d01ada696a7e4c7e5125b34884533a94fb319990325744ee9bbce9e525",
+ "",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "588e1356fb8fa32410dad99cf7922aae47b4042502c92f3afe33dc22c1c2e90caf22bc37a254f8dd62a09582c70194f9616982639415178e9fe95740c0f1d497a69b69d4924a7a15290187f9c8acf09cf5b3b3188ecde2d2807207f5bb6a6d3504314b1b47684cf8ba8807eb9a3c497c79ebe1e4c1eca2aa90328563e201425227fca8ee05dcc05fd6c98128626c1e71d2fb3a21860567093db1012dfabe13055c48219d2a301c8a5a49033a811d8d9413bafbb2eefc177226fe578e93c2ef1f309416dc98843bfac387debb1b610b1d2366178ce7212a7312057a3d058357a629f18c78e129e60979a2310455a76207be5611e8b4b840629564020c17f5c9446882e23f610e931246ec434e62de765bf22954cfae02b2ff7c59dfe246e4bb2d6a8afcebdc2beeaabf2a3f43f95a5ea639853f38719875ecdd2bbc0d81bb2a5ed59553b1e76b6365b74f618f68d1f05b5662cd6e04de896d3ef5dae4149485a5a2093ff4ec74b20b5e5bf8e61b5c65515938c202beab3eea5a498d2f32c38dbb370a9bbc3187cc260ddac991f94ce4f0d5",
+ },
+ {
+ "0fb826ddb2eb5e708de203d0438be12cf708d635ebdbae56278be09077009586b9bc646ba7c2db35a5de05e86ae71461efea96dac64430edcf117d461113cccacf303576f310ab98efb180599894ba877e50614494923163a3afa9b4c2757f91a6b40799c5b331b464b10dfc45c783c317e408ab76390e19e8b7ceaa2c4d3bd201436bc6f69c7a5a4d8756924ed95665bd5e1034971e4d80d51b2a",
+ "026866d46aa940309fdcabf92a324fbc",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "30f05cf8189bb7b8b4f560e746e228c4cc7e86e8f2fa66e1afe212d1855db51070acd5eb34ce80b2e223957df50fde4c2531d97fc9e573725e7a5e47f0dfc4da1942620320bb2deaf8b17937bae4218d04db8e76f6efe84a117292159507c9f8a09fb2c17921d7762510dbf1dac7b62b1bd7572e3e2cf008d01c445c7fa78833235034281ae180e051451c6a64f22ca9708634bd0d604e4cfcd971b13742efa5b6363e662a875daccb2b00",
+ },
+ {
+ "c7d4f8790e4c47d4daecbddf5939973521ddbf3b832e564afc66f03b5583c41c58bd956609dc3ae3c8f7c2213059575236168dba44e3044049f47c9e7840bbd0fd5036062d70e9f567ac1797056ee93c8476f6c959fa09a3ee854166c6fc36c34d6cca7adcb36f435f86db65f4c4a1793b974294914b377fd179e697751c5ac289243c65d8aca93732849c27483da083d4e218652d4fe5fec8cb953ee7f00070143dd6ece97f241b03c0424bfee2cfd2c4e738f2361df0ffe8863dcf763d408a7a167763959b7f985bc1e359a4b22c6899645ad0814bcf69d10c38474978d1c48e482723e3a6bb3f689f980c51c474eb28cfbba91a8a12eb964b32dfc303a3524ccb752f71316ed9d007e521cb5a0cf429c79d4351b02ee7fb60c7be636a10af3586dfa7b74d80875466a820c0b514e97cb12cce615ab55cba7c1b1de72bcd1cb1acc368f944ef4eaa986e6a4d8253c9337f9795d94df193c90cb0b0387dcde929905223d441717ed9dfe826613bf094ba872993d41b269e27d74e5f541b497eac9ba180dc12ffb6f1e7dc5223cce6dd541071282b97c6526e15b2c330fb41dc96e25d72f45c28e543053766d11d44252db54e584c14abbb295d7e5a58bf36eea1936095ef897a338eb1995fcedd85fc92d354dfe7ff9a115c186bb4d7a1a27835030d248c87571a38f17906cefe0261d15740b9",
+ "56",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "f89c825ca43cae1ce3fbdee85c505edd1aabefe69a0f9efd740f027aa7dee48a91ad24e69ad061648f0a52b4afb19d7ffccdc21f4b4247dfd89f5f9f998cb3c02b226173fedb6f8770aceef9271e7236fefd19fb3b87d08a5c587ac7918e80aa4b477f22602189811e270d686bc4949137a41d11d95ec96ee9d26c6126f6e923ab37638b34d1538d2e46d6df6216da4f193a3cecb731e632e109ced643056a1673059355d2d1314df35ded8364efed7de490201090a6f2d1751748585f64d26041637ba3723cbc4b60e226f10a19699d223075bc1f27d82e7f560c0db630ea670b3f8a70a8950894af4d1c7b3f674a3fa00d19ee4cc2b6174c1d259a297424bf2c3943a29a16a9830ce11abaa79cd2eb77b53a02b365b1838e7bfd5ae1bd044ffc885c61c6b2186a357e8b8f732b7ab96517969aeb70c7b493bbaca9462a61815a3c6135c748bf9c8487ac0631807aa69243fa09cd3b8efb63f8d4e090ad30b6c2f08bf4e82f191cedfa5cbe2b42268d67ecd105918181e44fc9879efd642d20be84e6f74717e03fb94fcbaa6ed3b307431d2a9384b8a2b3e5825ffce8d99af48f177e43bb4272226d8a5edd37d53807f768feb9e0733b437a1d0f84779ab68a1804e92a5eecca56364f0fa6dca152203b249fdc8fbd950fdc37c1887596308a90ba3a5751c7096bfbd1cb177bb17847b33c4379b43938a67674459cd9a06e3017ccac5b",
+ },
+ {
+ "135a28170fe89066da7bcff3a9ccc1b27dfe942a6f47b23835ef746aaea63dc10066d90f4e697528e5451b8e11dd408fdbd4b94a1c6c82515bf7bc099df9cb9d5fa4acad0d22d5f267f18078cec107a995c1f3b12d7603886dbf910ab85ca7180053c50e759b00dc8c81555a425c03d71df6894a6c8cd2d94b64e303c08a1bc1dee1cf537ccf300850856292e1656aff5bf349c87f1ca1ca8085cd400fe901edcad04146a0714ef0f6b083d715edd670e020385f3cda29bc5ff6fc6edffe5ca9ce9def6e0e3d5f04ede2db02cfb2",
+ "73afd2ab0e0e8537cae42dc6530dc4afb6934ca6",
+ "a5117e70953568bf750862df9e6f92af81677c3a188e847917a4a915bda7792e",
+ "129039b5572e8a7a8131f76a",
+ "2c125232a59879aee36cacc4aca5085a4688c4f776667a8fbd86862b5cfb1d57c976688fdd652eafa2b88b1b8e358aa2110ff6ef13cdc1ceca9c9f087c35c38d89d6fbd8de89538070f17916ecb19ca3ef4a1c834f0bdaa1df62aaabef2e117106787056c909e61ecd208357dd5c363f11c5d6cf24992cc873cf69f59360a820fcf290bd90b2cab24c47286acb4e1033962b6d41e562a206a94796a8ab1c6b8bade804ff9bdf5ba6062d2c1f8fe0f4dfc05720bd9a612b92c26789f9f6a7ce43f5e8e3aee99a9cd7d6c11eaa611983c36935b0dda57d898a60a0ab7c4b54",
+ },
+}
diff --git a/libgo/go/golang_org/x/crypto/chacha20poly1305/internal/chacha20/chacha_generic.go b/libgo/go/golang_org/x/crypto/chacha20poly1305/internal/chacha20/chacha_generic.go
new file mode 100644
index 00000000000..f9e8a3a2fe8
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/chacha20poly1305/internal/chacha20/chacha_generic.go
@@ -0,0 +1,199 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package ChaCha20 implements the core ChaCha20 function as specified in https://tools.ietf.org/html/rfc7539#section-2.3.
+package chacha20
+
+import "encoding/binary"
+
+const rounds = 20
+
+// core applies the ChaCha20 core function to 16-byte input in, 32-byte key k,
+// and 16-byte constant c, and puts the result into 64-byte array out.
+func core(out *[64]byte, in *[16]byte, k *[32]byte) {
+ j0 := uint32(0x61707865)
+ j1 := uint32(0x3320646e)
+ j2 := uint32(0x79622d32)
+ j3 := uint32(0x6b206574)
+ j4 := binary.LittleEndian.Uint32(k[0:4])
+ j5 := binary.LittleEndian.Uint32(k[4:8])
+ j6 := binary.LittleEndian.Uint32(k[8:12])
+ j7 := binary.LittleEndian.Uint32(k[12:16])
+ j8 := binary.LittleEndian.Uint32(k[16:20])
+ j9 := binary.LittleEndian.Uint32(k[20:24])
+ j10 := binary.LittleEndian.Uint32(k[24:28])
+ j11 := binary.LittleEndian.Uint32(k[28:32])
+ j12 := binary.LittleEndian.Uint32(in[0:4])
+ j13 := binary.LittleEndian.Uint32(in[4:8])
+ j14 := binary.LittleEndian.Uint32(in[8:12])
+ j15 := binary.LittleEndian.Uint32(in[12:16])
+
+ x0, x1, x2, x3, x4, x5, x6, x7 := j0, j1, j2, j3, j4, j5, j6, j7
+ x8, x9, x10, x11, x12, x13, x14, x15 := j8, j9, j10, j11, j12, j13, j14, j15
+
+ for i := 0; i < rounds; i += 2 {
+ x0 += x4
+ x12 ^= x0
+ x12 = (x12 << 16) | (x12 >> (16))
+ x8 += x12
+ x4 ^= x8
+ x4 = (x4 << 12) | (x4 >> (20))
+ x0 += x4
+ x12 ^= x0
+ x12 = (x12 << 8) | (x12 >> (24))
+ x8 += x12
+ x4 ^= x8
+ x4 = (x4 << 7) | (x4 >> (25))
+ x1 += x5
+ x13 ^= x1
+ x13 = (x13 << 16) | (x13 >> 16)
+ x9 += x13
+ x5 ^= x9
+ x5 = (x5 << 12) | (x5 >> 20)
+ x1 += x5
+ x13 ^= x1
+ x13 = (x13 << 8) | (x13 >> 24)
+ x9 += x13
+ x5 ^= x9
+ x5 = (x5 << 7) | (x5 >> 25)
+ x2 += x6
+ x14 ^= x2
+ x14 = (x14 << 16) | (x14 >> 16)
+ x10 += x14
+ x6 ^= x10
+ x6 = (x6 << 12) | (x6 >> 20)
+ x2 += x6
+ x14 ^= x2
+ x14 = (x14 << 8) | (x14 >> 24)
+ x10 += x14
+ x6 ^= x10
+ x6 = (x6 << 7) | (x6 >> 25)
+ x3 += x7
+ x15 ^= x3
+ x15 = (x15 << 16) | (x15 >> 16)
+ x11 += x15
+ x7 ^= x11
+ x7 = (x7 << 12) | (x7 >> 20)
+ x3 += x7
+ x15 ^= x3
+ x15 = (x15 << 8) | (x15 >> 24)
+ x11 += x15
+ x7 ^= x11
+ x7 = (x7 << 7) | (x7 >> 25)
+ x0 += x5
+ x15 ^= x0
+ x15 = (x15 << 16) | (x15 >> 16)
+ x10 += x15
+ x5 ^= x10
+ x5 = (x5 << 12) | (x5 >> 20)
+ x0 += x5
+ x15 ^= x0
+ x15 = (x15 << 8) | (x15 >> 24)
+ x10 += x15
+ x5 ^= x10
+ x5 = (x5 << 7) | (x5 >> 25)
+ x1 += x6
+ x12 ^= x1
+ x12 = (x12 << 16) | (x12 >> 16)
+ x11 += x12
+ x6 ^= x11
+ x6 = (x6 << 12) | (x6 >> 20)
+ x1 += x6
+ x12 ^= x1
+ x12 = (x12 << 8) | (x12 >> 24)
+ x11 += x12
+ x6 ^= x11
+ x6 = (x6 << 7) | (x6 >> 25)
+ x2 += x7
+ x13 ^= x2
+ x13 = (x13 << 16) | (x13 >> 16)
+ x8 += x13
+ x7 ^= x8
+ x7 = (x7 << 12) | (x7 >> 20)
+ x2 += x7
+ x13 ^= x2
+ x13 = (x13 << 8) | (x13 >> 24)
+ x8 += x13
+ x7 ^= x8
+ x7 = (x7 << 7) | (x7 >> 25)
+ x3 += x4
+ x14 ^= x3
+ x14 = (x14 << 16) | (x14 >> 16)
+ x9 += x14
+ x4 ^= x9
+ x4 = (x4 << 12) | (x4 >> 20)
+ x3 += x4
+ x14 ^= x3
+ x14 = (x14 << 8) | (x14 >> 24)
+ x9 += x14
+ x4 ^= x9
+ x4 = (x4 << 7) | (x4 >> 25)
+ }
+
+ x0 += j0
+ x1 += j1
+ x2 += j2
+ x3 += j3
+ x4 += j4
+ x5 += j5
+ x6 += j6
+ x7 += j7
+ x8 += j8
+ x9 += j9
+ x10 += j10
+ x11 += j11
+ x12 += j12
+ x13 += j13
+ x14 += j14
+ x15 += j15
+
+ binary.LittleEndian.PutUint32(out[0:4], x0)
+ binary.LittleEndian.PutUint32(out[4:8], x1)
+ binary.LittleEndian.PutUint32(out[8:12], x2)
+ binary.LittleEndian.PutUint32(out[12:16], x3)
+ binary.LittleEndian.PutUint32(out[16:20], x4)
+ binary.LittleEndian.PutUint32(out[20:24], x5)
+ binary.LittleEndian.PutUint32(out[24:28], x6)
+ binary.LittleEndian.PutUint32(out[28:32], x7)
+ binary.LittleEndian.PutUint32(out[32:36], x8)
+ binary.LittleEndian.PutUint32(out[36:40], x9)
+ binary.LittleEndian.PutUint32(out[40:44], x10)
+ binary.LittleEndian.PutUint32(out[44:48], x11)
+ binary.LittleEndian.PutUint32(out[48:52], x12)
+ binary.LittleEndian.PutUint32(out[52:56], x13)
+ binary.LittleEndian.PutUint32(out[56:60], x14)
+ binary.LittleEndian.PutUint32(out[60:64], x15)
+}
+
+// XORKeyStream crypts bytes from in to out using the given key and counters.
+// In and out may be the same slice but otherwise should not overlap. Counter
+// contains the raw ChaCha20 counter bytes (i.e. block counter followed by
+// nonce).
+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
+ var block [64]byte
+ var counterCopy [16]byte
+ copy(counterCopy[:], counter[:])
+
+ for len(in) >= 64 {
+ core(&block, &counterCopy, key)
+ for i, x := range block {
+ out[i] = in[i] ^ x
+ }
+ u := uint32(1)
+ for i := 0; i < 4; i++ {
+ u += uint32(counterCopy[i])
+ counterCopy[i] = byte(u)
+ u >>= 8
+ }
+ in = in[64:]
+ out = out[64:]
+ }
+
+ if len(in) > 0 {
+ core(&block, &counterCopy, key)
+ for i, v := range in {
+ out[i] = v ^ block[i]
+ }
+ }
+}
diff --git a/libgo/go/golang_org/x/crypto/chacha20poly1305/internal/chacha20/chacha_test.go b/libgo/go/golang_org/x/crypto/chacha20poly1305/internal/chacha20/chacha_test.go
new file mode 100644
index 00000000000..ca9663f52c7
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/chacha20poly1305/internal/chacha20/chacha_test.go
@@ -0,0 +1,29 @@
+package chacha20
+
+import (
+ "encoding/hex"
+ "testing"
+)
+
+func TestCore(t *testing.T) {
+ // This is just a smoke test that checks the example from
+ // https://tools.ietf.org/html/rfc7539#section-2.3.2. The
+ // chacha20poly1305 package contains much more extensive tests of this
+ // code.
+ var key [32]byte
+ for i := range key {
+ key[i] = byte(i)
+ }
+
+ var input [16]byte
+ input[0] = 1
+ input[7] = 9
+ input[11] = 0x4a
+
+ var out [64]byte
+ XORKeyStream(out[:], out[:], &input, &key)
+ const expected = "10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4ed2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e"
+ if result := hex.EncodeToString(out[:]); result != expected {
+ t.Errorf("wanted %x but got %x", expected, result)
+ }
+}
diff --git a/libgo/go/golang_org/x/crypto/curve25519/curve25519.go b/libgo/go/golang_org/x/crypto/curve25519/curve25519.go
new file mode 100644
index 00000000000..6918c47fc2e
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/curve25519/curve25519.go
@@ -0,0 +1,841 @@
+// 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.
+
+// We have a implementation in amd64 assembly so this code is only run on
+// non-amd64 platforms. The amd64 assembly does not support gccgo.
+// +build !amd64 gccgo appengine
+
+package curve25519
+
+// This code is a port of the public domain, "ref10" implementation of
+// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
+
+// fieldElement represents an element of the field GF(2^255 - 19). An element
+// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
+// context.
+type fieldElement [10]int32
+
+func feZero(fe *fieldElement) {
+ for i := range fe {
+ fe[i] = 0
+ }
+}
+
+func feOne(fe *fieldElement) {
+ feZero(fe)
+ fe[0] = 1
+}
+
+func feAdd(dst, a, b *fieldElement) {
+ for i := range dst {
+ dst[i] = a[i] + b[i]
+ }
+}
+
+func feSub(dst, a, b *fieldElement) {
+ for i := range dst {
+ dst[i] = a[i] - b[i]
+ }
+}
+
+func feCopy(dst, src *fieldElement) {
+ for i := range dst {
+ dst[i] = src[i]
+ }
+}
+
+// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0.
+//
+// Preconditions: b in {0,1}.
+func feCSwap(f, g *fieldElement, b int32) {
+ var x fieldElement
+ b = -b
+ for i := range x {
+ x[i] = b & (f[i] ^ g[i])
+ }
+
+ for i := range f {
+ f[i] ^= x[i]
+ }
+ for i := range g {
+ g[i] ^= x[i]
+ }
+}
+
+// load3 reads a 24-bit, little-endian value from in.
+func load3(in []byte) int64 {
+ var r int64
+ r = int64(in[0])
+ r |= int64(in[1]) << 8
+ r |= int64(in[2]) << 16
+ return r
+}
+
+// load4 reads a 32-bit, little-endian value from in.
+func load4(in []byte) int64 {
+ var r int64
+ r = int64(in[0])
+ r |= int64(in[1]) << 8
+ r |= int64(in[2]) << 16
+ r |= int64(in[3]) << 24
+ return r
+}
+
+func feFromBytes(dst *fieldElement, src *[32]byte) {
+ h0 := load4(src[:])
+ h1 := load3(src[4:]) << 6
+ h2 := load3(src[7:]) << 5
+ h3 := load3(src[10:]) << 3
+ h4 := load3(src[13:]) << 2
+ h5 := load4(src[16:])
+ h6 := load3(src[20:]) << 7
+ h7 := load3(src[23:]) << 5
+ h8 := load3(src[26:]) << 4
+ h9 := load3(src[29:]) << 2
+
+ var carry [10]int64
+ carry[9] = (h9 + 1<<24) >> 25
+ h0 += carry[9] * 19
+ h9 -= carry[9] << 25
+ carry[1] = (h1 + 1<<24) >> 25
+ h2 += carry[1]
+ h1 -= carry[1] << 25
+ carry[3] = (h3 + 1<<24) >> 25
+ h4 += carry[3]
+ h3 -= carry[3] << 25
+ carry[5] = (h5 + 1<<24) >> 25
+ h6 += carry[5]
+ h5 -= carry[5] << 25
+ carry[7] = (h7 + 1<<24) >> 25
+ h8 += carry[7]
+ h7 -= carry[7] << 25
+
+ carry[0] = (h0 + 1<<25) >> 26
+ h1 += carry[0]
+ h0 -= carry[0] << 26
+ carry[2] = (h2 + 1<<25) >> 26
+ h3 += carry[2]
+ h2 -= carry[2] << 26
+ carry[4] = (h4 + 1<<25) >> 26
+ h5 += carry[4]
+ h4 -= carry[4] << 26
+ carry[6] = (h6 + 1<<25) >> 26
+ h7 += carry[6]
+ h6 -= carry[6] << 26
+ carry[8] = (h8 + 1<<25) >> 26
+ h9 += carry[8]
+ h8 -= carry[8] << 26
+
+ dst[0] = int32(h0)
+ dst[1] = int32(h1)
+ dst[2] = int32(h2)
+ dst[3] = int32(h3)
+ dst[4] = int32(h4)
+ dst[5] = int32(h5)
+ dst[6] = int32(h6)
+ dst[7] = int32(h7)
+ dst[8] = int32(h8)
+ dst[9] = int32(h9)
+}
+
+// feToBytes marshals h to s.
+// Preconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Write p=2^255-19; q=floor(h/p).
+// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
+//
+// Proof:
+// Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
+// Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
+//
+// Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
+// Then 0<y<1.
+//
+// Write r=h-pq.
+// Have 0<=r<=p-1=2^255-20.
+// Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
+//
+// Write x=r+19(2^-255)r+y.
+// Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
+//
+// Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
+// so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
+func feToBytes(s *[32]byte, h *fieldElement) {
+ var carry [10]int32
+
+ q := (19*h[9] + (1 << 24)) >> 25
+ q = (h[0] + q) >> 26
+ q = (h[1] + q) >> 25
+ q = (h[2] + q) >> 26
+ q = (h[3] + q) >> 25
+ q = (h[4] + q) >> 26
+ q = (h[5] + q) >> 25
+ q = (h[6] + q) >> 26
+ q = (h[7] + q) >> 25
+ q = (h[8] + q) >> 26
+ q = (h[9] + q) >> 25
+
+ // Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
+ h[0] += 19 * q
+ // Goal: Output h-2^255 q, which is between 0 and 2^255-20.
+
+ carry[0] = h[0] >> 26
+ h[1] += carry[0]
+ h[0] -= carry[0] << 26
+ carry[1] = h[1] >> 25
+ h[2] += carry[1]
+ h[1] -= carry[1] << 25
+ carry[2] = h[2] >> 26
+ h[3] += carry[2]
+ h[2] -= carry[2] << 26
+ carry[3] = h[3] >> 25
+ h[4] += carry[3]
+ h[3] -= carry[3] << 25
+ carry[4] = h[4] >> 26
+ h[5] += carry[4]
+ h[4] -= carry[4] << 26
+ carry[5] = h[5] >> 25
+ h[6] += carry[5]
+ h[5] -= carry[5] << 25
+ carry[6] = h[6] >> 26
+ h[7] += carry[6]
+ h[6] -= carry[6] << 26
+ carry[7] = h[7] >> 25
+ h[8] += carry[7]
+ h[7] -= carry[7] << 25
+ carry[8] = h[8] >> 26
+ h[9] += carry[8]
+ h[8] -= carry[8] << 26
+ carry[9] = h[9] >> 25
+ h[9] -= carry[9] << 25
+ // h10 = carry9
+
+ // Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
+ // Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
+ // evidently 2^255 h10-2^255 q = 0.
+ // Goal: Output h[0]+...+2^230 h[9].
+
+ s[0] = byte(h[0] >> 0)
+ s[1] = byte(h[0] >> 8)
+ s[2] = byte(h[0] >> 16)
+ s[3] = byte((h[0] >> 24) | (h[1] << 2))
+ s[4] = byte(h[1] >> 6)
+ s[5] = byte(h[1] >> 14)
+ s[6] = byte((h[1] >> 22) | (h[2] << 3))
+ s[7] = byte(h[2] >> 5)
+ s[8] = byte(h[2] >> 13)
+ s[9] = byte((h[2] >> 21) | (h[3] << 5))
+ s[10] = byte(h[3] >> 3)
+ s[11] = byte(h[3] >> 11)
+ s[12] = byte((h[3] >> 19) | (h[4] << 6))
+ s[13] = byte(h[4] >> 2)
+ s[14] = byte(h[4] >> 10)
+ s[15] = byte(h[4] >> 18)
+ s[16] = byte(h[5] >> 0)
+ s[17] = byte(h[5] >> 8)
+ s[18] = byte(h[5] >> 16)
+ s[19] = byte((h[5] >> 24) | (h[6] << 1))
+ s[20] = byte(h[6] >> 7)
+ s[21] = byte(h[6] >> 15)
+ s[22] = byte((h[6] >> 23) | (h[7] << 3))
+ s[23] = byte(h[7] >> 5)
+ s[24] = byte(h[7] >> 13)
+ s[25] = byte((h[7] >> 21) | (h[8] << 4))
+ s[26] = byte(h[8] >> 4)
+ s[27] = byte(h[8] >> 12)
+ s[28] = byte((h[8] >> 20) | (h[9] << 6))
+ s[29] = byte(h[9] >> 2)
+ s[30] = byte(h[9] >> 10)
+ s[31] = byte(h[9] >> 18)
+}
+
+// feMul calculates h = f * g
+// Can overlap h with f or g.
+//
+// Preconditions:
+// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+// |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+//
+// Notes on implementation strategy:
+//
+// Using schoolbook multiplication.
+// Karatsuba would save a little in some cost models.
+//
+// Most multiplications by 2 and 19 are 32-bit precomputations;
+// cheaper than 64-bit postcomputations.
+//
+// There is one remaining multiplication by 19 in the carry chain;
+// one *19 precomputation can be merged into this,
+// but the resulting data flow is considerably less clean.
+//
+// There are 12 carries below.
+// 10 of them are 2-way parallelizable and vectorizable.
+// Can get away with 11 carries, but then data flow is much deeper.
+//
+// With tighter constraints on inputs can squeeze carries into int32.
+func feMul(h, f, g *fieldElement) {
+ f0 := f[0]
+ f1 := f[1]
+ f2 := f[2]
+ f3 := f[3]
+ f4 := f[4]
+ f5 := f[5]
+ f6 := f[6]
+ f7 := f[7]
+ f8 := f[8]
+ f9 := f[9]
+ g0 := g[0]
+ g1 := g[1]
+ g2 := g[2]
+ g3 := g[3]
+ g4 := g[4]
+ g5 := g[5]
+ g6 := g[6]
+ g7 := g[7]
+ g8 := g[8]
+ g9 := g[9]
+ g1_19 := 19 * g1 // 1.4*2^29
+ g2_19 := 19 * g2 // 1.4*2^30; still ok
+ g3_19 := 19 * g3
+ g4_19 := 19 * g4
+ g5_19 := 19 * g5
+ g6_19 := 19 * g6
+ g7_19 := 19 * g7
+ g8_19 := 19 * g8
+ g9_19 := 19 * g9
+ f1_2 := 2 * f1
+ f3_2 := 2 * f3
+ f5_2 := 2 * f5
+ f7_2 := 2 * f7
+ f9_2 := 2 * f9
+ f0g0 := int64(f0) * int64(g0)
+ f0g1 := int64(f0) * int64(g1)
+ f0g2 := int64(f0) * int64(g2)
+ f0g3 := int64(f0) * int64(g3)
+ f0g4 := int64(f0) * int64(g4)
+ f0g5 := int64(f0) * int64(g5)
+ f0g6 := int64(f0) * int64(g6)
+ f0g7 := int64(f0) * int64(g7)
+ f0g8 := int64(f0) * int64(g8)
+ f0g9 := int64(f0) * int64(g9)
+ f1g0 := int64(f1) * int64(g0)
+ f1g1_2 := int64(f1_2) * int64(g1)
+ f1g2 := int64(f1) * int64(g2)
+ f1g3_2 := int64(f1_2) * int64(g3)
+ f1g4 := int64(f1) * int64(g4)
+ f1g5_2 := int64(f1_2) * int64(g5)
+ f1g6 := int64(f1) * int64(g6)
+ f1g7_2 := int64(f1_2) * int64(g7)
+ f1g8 := int64(f1) * int64(g8)
+ f1g9_38 := int64(f1_2) * int64(g9_19)
+ f2g0 := int64(f2) * int64(g0)
+ f2g1 := int64(f2) * int64(g1)
+ f2g2 := int64(f2) * int64(g2)
+ f2g3 := int64(f2) * int64(g3)
+ f2g4 := int64(f2) * int64(g4)
+ f2g5 := int64(f2) * int64(g5)
+ f2g6 := int64(f2) * int64(g6)
+ f2g7 := int64(f2) * int64(g7)
+ f2g8_19 := int64(f2) * int64(g8_19)
+ f2g9_19 := int64(f2) * int64(g9_19)
+ f3g0 := int64(f3) * int64(g0)
+ f3g1_2 := int64(f3_2) * int64(g1)
+ f3g2 := int64(f3) * int64(g2)
+ f3g3_2 := int64(f3_2) * int64(g3)
+ f3g4 := int64(f3) * int64(g4)
+ f3g5_2 := int64(f3_2) * int64(g5)
+ f3g6 := int64(f3) * int64(g6)
+ f3g7_38 := int64(f3_2) * int64(g7_19)
+ f3g8_19 := int64(f3) * int64(g8_19)
+ f3g9_38 := int64(f3_2) * int64(g9_19)
+ f4g0 := int64(f4) * int64(g0)
+ f4g1 := int64(f4) * int64(g1)
+ f4g2 := int64(f4) * int64(g2)
+ f4g3 := int64(f4) * int64(g3)
+ f4g4 := int64(f4) * int64(g4)
+ f4g5 := int64(f4) * int64(g5)
+ f4g6_19 := int64(f4) * int64(g6_19)
+ f4g7_19 := int64(f4) * int64(g7_19)
+ f4g8_19 := int64(f4) * int64(g8_19)
+ f4g9_19 := int64(f4) * int64(g9_19)
+ f5g0 := int64(f5) * int64(g0)
+ f5g1_2 := int64(f5_2) * int64(g1)
+ f5g2 := int64(f5) * int64(g2)
+ f5g3_2 := int64(f5_2) * int64(g3)
+ f5g4 := int64(f5) * int64(g4)
+ f5g5_38 := int64(f5_2) * int64(g5_19)
+ f5g6_19 := int64(f5) * int64(g6_19)
+ f5g7_38 := int64(f5_2) * int64(g7_19)
+ f5g8_19 := int64(f5) * int64(g8_19)
+ f5g9_38 := int64(f5_2) * int64(g9_19)
+ f6g0 := int64(f6) * int64(g0)
+ f6g1 := int64(f6) * int64(g1)
+ f6g2 := int64(f6) * int64(g2)
+ f6g3 := int64(f6) * int64(g3)
+ f6g4_19 := int64(f6) * int64(g4_19)
+ f6g5_19 := int64(f6) * int64(g5_19)
+ f6g6_19 := int64(f6) * int64(g6_19)
+ f6g7_19 := int64(f6) * int64(g7_19)
+ f6g8_19 := int64(f6) * int64(g8_19)
+ f6g9_19 := int64(f6) * int64(g9_19)
+ f7g0 := int64(f7) * int64(g0)
+ f7g1_2 := int64(f7_2) * int64(g1)
+ f7g2 := int64(f7) * int64(g2)
+ f7g3_38 := int64(f7_2) * int64(g3_19)
+ f7g4_19 := int64(f7) * int64(g4_19)
+ f7g5_38 := int64(f7_2) * int64(g5_19)
+ f7g6_19 := int64(f7) * int64(g6_19)
+ f7g7_38 := int64(f7_2) * int64(g7_19)
+ f7g8_19 := int64(f7) * int64(g8_19)
+ f7g9_38 := int64(f7_2) * int64(g9_19)
+ f8g0 := int64(f8) * int64(g0)
+ f8g1 := int64(f8) * int64(g1)
+ f8g2_19 := int64(f8) * int64(g2_19)
+ f8g3_19 := int64(f8) * int64(g3_19)
+ f8g4_19 := int64(f8) * int64(g4_19)
+ f8g5_19 := int64(f8) * int64(g5_19)
+ f8g6_19 := int64(f8) * int64(g6_19)
+ f8g7_19 := int64(f8) * int64(g7_19)
+ f8g8_19 := int64(f8) * int64(g8_19)
+ f8g9_19 := int64(f8) * int64(g9_19)
+ f9g0 := int64(f9) * int64(g0)
+ f9g1_38 := int64(f9_2) * int64(g1_19)
+ f9g2_19 := int64(f9) * int64(g2_19)
+ f9g3_38 := int64(f9_2) * int64(g3_19)
+ f9g4_19 := int64(f9) * int64(g4_19)
+ f9g5_38 := int64(f9_2) * int64(g5_19)
+ f9g6_19 := int64(f9) * int64(g6_19)
+ f9g7_38 := int64(f9_2) * int64(g7_19)
+ f9g8_19 := int64(f9) * int64(g8_19)
+ f9g9_38 := int64(f9_2) * int64(g9_19)
+ h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38
+ h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19
+ h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38
+ h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19
+ h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38
+ h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19
+ h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38
+ h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19
+ h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38
+ h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0
+ var carry [10]int64
+
+ // |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
+ // i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
+ // |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
+ // i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
+
+ carry[0] = (h0 + (1 << 25)) >> 26
+ h1 += carry[0]
+ h0 -= carry[0] << 26
+ carry[4] = (h4 + (1 << 25)) >> 26
+ h5 += carry[4]
+ h4 -= carry[4] << 26
+ // |h0| <= 2^25
+ // |h4| <= 2^25
+ // |h1| <= 1.51*2^58
+ // |h5| <= 1.51*2^58
+
+ carry[1] = (h1 + (1 << 24)) >> 25
+ h2 += carry[1]
+ h1 -= carry[1] << 25
+ carry[5] = (h5 + (1 << 24)) >> 25
+ h6 += carry[5]
+ h5 -= carry[5] << 25
+ // |h1| <= 2^24; from now on fits into int32
+ // |h5| <= 2^24; from now on fits into int32
+ // |h2| <= 1.21*2^59
+ // |h6| <= 1.21*2^59
+
+ carry[2] = (h2 + (1 << 25)) >> 26
+ h3 += carry[2]
+ h2 -= carry[2] << 26
+ carry[6] = (h6 + (1 << 25)) >> 26
+ h7 += carry[6]
+ h6 -= carry[6] << 26
+ // |h2| <= 2^25; from now on fits into int32 unchanged
+ // |h6| <= 2^25; from now on fits into int32 unchanged
+ // |h3| <= 1.51*2^58
+ // |h7| <= 1.51*2^58
+
+ carry[3] = (h3 + (1 << 24)) >> 25
+ h4 += carry[3]
+ h3 -= carry[3] << 25
+ carry[7] = (h7 + (1 << 24)) >> 25
+ h8 += carry[7]
+ h7 -= carry[7] << 25
+ // |h3| <= 2^24; from now on fits into int32 unchanged
+ // |h7| <= 2^24; from now on fits into int32 unchanged
+ // |h4| <= 1.52*2^33
+ // |h8| <= 1.52*2^33
+
+ carry[4] = (h4 + (1 << 25)) >> 26
+ h5 += carry[4]
+ h4 -= carry[4] << 26
+ carry[8] = (h8 + (1 << 25)) >> 26
+ h9 += carry[8]
+ h8 -= carry[8] << 26
+ // |h4| <= 2^25; from now on fits into int32 unchanged
+ // |h8| <= 2^25; from now on fits into int32 unchanged
+ // |h5| <= 1.01*2^24
+ // |h9| <= 1.51*2^58
+
+ carry[9] = (h9 + (1 << 24)) >> 25
+ h0 += carry[9] * 19
+ h9 -= carry[9] << 25
+ // |h9| <= 2^24; from now on fits into int32 unchanged
+ // |h0| <= 1.8*2^37
+
+ carry[0] = (h0 + (1 << 25)) >> 26
+ h1 += carry[0]
+ h0 -= carry[0] << 26
+ // |h0| <= 2^25; from now on fits into int32 unchanged
+ // |h1| <= 1.01*2^24
+
+ h[0] = int32(h0)
+ h[1] = int32(h1)
+ h[2] = int32(h2)
+ h[3] = int32(h3)
+ h[4] = int32(h4)
+ h[5] = int32(h5)
+ h[6] = int32(h6)
+ h[7] = int32(h7)
+ h[8] = int32(h8)
+ h[9] = int32(h9)
+}
+
+// feSquare calculates h = f*f. Can overlap h with f.
+//
+// Preconditions:
+// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func feSquare(h, f *fieldElement) {
+ f0 := f[0]
+ f1 := f[1]
+ f2 := f[2]
+ f3 := f[3]
+ f4 := f[4]
+ f5 := f[5]
+ f6 := f[6]
+ f7 := f[7]
+ f8 := f[8]
+ f9 := f[9]
+ f0_2 := 2 * f0
+ f1_2 := 2 * f1
+ f2_2 := 2 * f2
+ f3_2 := 2 * f3
+ f4_2 := 2 * f4
+ f5_2 := 2 * f5
+ f6_2 := 2 * f6
+ f7_2 := 2 * f7
+ f5_38 := 38 * f5 // 1.31*2^30
+ f6_19 := 19 * f6 // 1.31*2^30
+ f7_38 := 38 * f7 // 1.31*2^30
+ f8_19 := 19 * f8 // 1.31*2^30
+ f9_38 := 38 * f9 // 1.31*2^30
+ f0f0 := int64(f0) * int64(f0)
+ f0f1_2 := int64(f0_2) * int64(f1)
+ f0f2_2 := int64(f0_2) * int64(f2)
+ f0f3_2 := int64(f0_2) * int64(f3)
+ f0f4_2 := int64(f0_2) * int64(f4)
+ f0f5_2 := int64(f0_2) * int64(f5)
+ f0f6_2 := int64(f0_2) * int64(f6)
+ f0f7_2 := int64(f0_2) * int64(f7)
+ f0f8_2 := int64(f0_2) * int64(f8)
+ f0f9_2 := int64(f0_2) * int64(f9)
+ f1f1_2 := int64(f1_2) * int64(f1)
+ f1f2_2 := int64(f1_2) * int64(f2)
+ f1f3_4 := int64(f1_2) * int64(f3_2)
+ f1f4_2 := int64(f1_2) * int64(f4)
+ f1f5_4 := int64(f1_2) * int64(f5_2)
+ f1f6_2 := int64(f1_2) * int64(f6)
+ f1f7_4 := int64(f1_2) * int64(f7_2)
+ f1f8_2 := int64(f1_2) * int64(f8)
+ f1f9_76 := int64(f1_2) * int64(f9_38)
+ f2f2 := int64(f2) * int64(f2)
+ f2f3_2 := int64(f2_2) * int64(f3)
+ f2f4_2 := int64(f2_2) * int64(f4)
+ f2f5_2 := int64(f2_2) * int64(f5)
+ f2f6_2 := int64(f2_2) * int64(f6)
+ f2f7_2 := int64(f2_2) * int64(f7)
+ f2f8_38 := int64(f2_2) * int64(f8_19)
+ f2f9_38 := int64(f2) * int64(f9_38)
+ f3f3_2 := int64(f3_2) * int64(f3)
+ f3f4_2 := int64(f3_2) * int64(f4)
+ f3f5_4 := int64(f3_2) * int64(f5_2)
+ f3f6_2 := int64(f3_2) * int64(f6)
+ f3f7_76 := int64(f3_2) * int64(f7_38)
+ f3f8_38 := int64(f3_2) * int64(f8_19)
+ f3f9_76 := int64(f3_2) * int64(f9_38)
+ f4f4 := int64(f4) * int64(f4)
+ f4f5_2 := int64(f4_2) * int64(f5)
+ f4f6_38 := int64(f4_2) * int64(f6_19)
+ f4f7_38 := int64(f4) * int64(f7_38)
+ f4f8_38 := int64(f4_2) * int64(f8_19)
+ f4f9_38 := int64(f4) * int64(f9_38)
+ f5f5_38 := int64(f5) * int64(f5_38)
+ f5f6_38 := int64(f5_2) * int64(f6_19)
+ f5f7_76 := int64(f5_2) * int64(f7_38)
+ f5f8_38 := int64(f5_2) * int64(f8_19)
+ f5f9_76 := int64(f5_2) * int64(f9_38)
+ f6f6_19 := int64(f6) * int64(f6_19)
+ f6f7_38 := int64(f6) * int64(f7_38)
+ f6f8_38 := int64(f6_2) * int64(f8_19)
+ f6f9_38 := int64(f6) * int64(f9_38)
+ f7f7_38 := int64(f7) * int64(f7_38)
+ f7f8_38 := int64(f7_2) * int64(f8_19)
+ f7f9_76 := int64(f7_2) * int64(f9_38)
+ f8f8_19 := int64(f8) * int64(f8_19)
+ f8f9_38 := int64(f8) * int64(f9_38)
+ f9f9_38 := int64(f9) * int64(f9_38)
+ h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
+ h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
+ h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
+ h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
+ h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
+ h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
+ h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
+ h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
+ h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
+ h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
+ var carry [10]int64
+
+ carry[0] = (h0 + (1 << 25)) >> 26
+ h1 += carry[0]
+ h0 -= carry[0] << 26
+ carry[4] = (h4 + (1 << 25)) >> 26
+ h5 += carry[4]
+ h4 -= carry[4] << 26
+
+ carry[1] = (h1 + (1 << 24)) >> 25
+ h2 += carry[1]
+ h1 -= carry[1] << 25
+ carry[5] = (h5 + (1 << 24)) >> 25
+ h6 += carry[5]
+ h5 -= carry[5] << 25
+
+ carry[2] = (h2 + (1 << 25)) >> 26
+ h3 += carry[2]
+ h2 -= carry[2] << 26
+ carry[6] = (h6 + (1 << 25)) >> 26
+ h7 += carry[6]
+ h6 -= carry[6] << 26
+
+ carry[3] = (h3 + (1 << 24)) >> 25
+ h4 += carry[3]
+ h3 -= carry[3] << 25
+ carry[7] = (h7 + (1 << 24)) >> 25
+ h8 += carry[7]
+ h7 -= carry[7] << 25
+
+ carry[4] = (h4 + (1 << 25)) >> 26
+ h5 += carry[4]
+ h4 -= carry[4] << 26
+ carry[8] = (h8 + (1 << 25)) >> 26
+ h9 += carry[8]
+ h8 -= carry[8] << 26
+
+ carry[9] = (h9 + (1 << 24)) >> 25
+ h0 += carry[9] * 19
+ h9 -= carry[9] << 25
+
+ carry[0] = (h0 + (1 << 25)) >> 26
+ h1 += carry[0]
+ h0 -= carry[0] << 26
+
+ h[0] = int32(h0)
+ h[1] = int32(h1)
+ h[2] = int32(h2)
+ h[3] = int32(h3)
+ h[4] = int32(h4)
+ h[5] = int32(h5)
+ h[6] = int32(h6)
+ h[7] = int32(h7)
+ h[8] = int32(h8)
+ h[9] = int32(h9)
+}
+
+// feMul121666 calculates h = f * 121666. Can overlap h with f.
+//
+// Preconditions:
+// |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+//
+// Postconditions:
+// |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+func feMul121666(h, f *fieldElement) {
+ h0 := int64(f[0]) * 121666
+ h1 := int64(f[1]) * 121666
+ h2 := int64(f[2]) * 121666
+ h3 := int64(f[3]) * 121666
+ h4 := int64(f[4]) * 121666
+ h5 := int64(f[5]) * 121666
+ h6 := int64(f[6]) * 121666
+ h7 := int64(f[7]) * 121666
+ h8 := int64(f[8]) * 121666
+ h9 := int64(f[9]) * 121666
+ var carry [10]int64
+
+ carry[9] = (h9 + (1 << 24)) >> 25
+ h0 += carry[9] * 19
+ h9 -= carry[9] << 25
+ carry[1] = (h1 + (1 << 24)) >> 25
+ h2 += carry[1]
+ h1 -= carry[1] << 25
+ carry[3] = (h3 + (1 << 24)) >> 25
+ h4 += carry[3]
+ h3 -= carry[3] << 25
+ carry[5] = (h5 + (1 << 24)) >> 25
+ h6 += carry[5]
+ h5 -= carry[5] << 25
+ carry[7] = (h7 + (1 << 24)) >> 25
+ h8 += carry[7]
+ h7 -= carry[7] << 25
+
+ carry[0] = (h0 + (1 << 25)) >> 26
+ h1 += carry[0]
+ h0 -= carry[0] << 26
+ carry[2] = (h2 + (1 << 25)) >> 26
+ h3 += carry[2]
+ h2 -= carry[2] << 26
+ carry[4] = (h4 + (1 << 25)) >> 26
+ h5 += carry[4]
+ h4 -= carry[4] << 26
+ carry[6] = (h6 + (1 << 25)) >> 26
+ h7 += carry[6]
+ h6 -= carry[6] << 26
+ carry[8] = (h8 + (1 << 25)) >> 26
+ h9 += carry[8]
+ h8 -= carry[8] << 26
+
+ h[0] = int32(h0)
+ h[1] = int32(h1)
+ h[2] = int32(h2)
+ h[3] = int32(h3)
+ h[4] = int32(h4)
+ h[5] = int32(h5)
+ h[6] = int32(h6)
+ h[7] = int32(h7)
+ h[8] = int32(h8)
+ h[9] = int32(h9)
+}
+
+// feInvert sets out = z^-1.
+func feInvert(out, z *fieldElement) {
+ var t0, t1, t2, t3 fieldElement
+ var i int
+
+ feSquare(&t0, z)
+ for i = 1; i < 1; i++ {
+ feSquare(&t0, &t0)
+ }
+ feSquare(&t1, &t0)
+ for i = 1; i < 2; i++ {
+ feSquare(&t1, &t1)
+ }
+ feMul(&t1, z, &t1)
+ feMul(&t0, &t0, &t1)
+ feSquare(&t2, &t0)
+ for i = 1; i < 1; i++ {
+ feSquare(&t2, &t2)
+ }
+ feMul(&t1, &t1, &t2)
+ feSquare(&t2, &t1)
+ for i = 1; i < 5; i++ {
+ feSquare(&t2, &t2)
+ }
+ feMul(&t1, &t2, &t1)
+ feSquare(&t2, &t1)
+ for i = 1; i < 10; i++ {
+ feSquare(&t2, &t2)
+ }
+ feMul(&t2, &t2, &t1)
+ feSquare(&t3, &t2)
+ for i = 1; i < 20; i++ {
+ feSquare(&t3, &t3)
+ }
+ feMul(&t2, &t3, &t2)
+ feSquare(&t2, &t2)
+ for i = 1; i < 10; i++ {
+ feSquare(&t2, &t2)
+ }
+ feMul(&t1, &t2, &t1)
+ feSquare(&t2, &t1)
+ for i = 1; i < 50; i++ {
+ feSquare(&t2, &t2)
+ }
+ feMul(&t2, &t2, &t1)
+ feSquare(&t3, &t2)
+ for i = 1; i < 100; i++ {
+ feSquare(&t3, &t3)
+ }
+ feMul(&t2, &t3, &t2)
+ feSquare(&t2, &t2)
+ for i = 1; i < 50; i++ {
+ feSquare(&t2, &t2)
+ }
+ feMul(&t1, &t2, &t1)
+ feSquare(&t1, &t1)
+ for i = 1; i < 5; i++ {
+ feSquare(&t1, &t1)
+ }
+ feMul(out, &t1, &t0)
+}
+
+func scalarMult(out, in, base *[32]byte) {
+ var e [32]byte
+
+ copy(e[:], in[:])
+ e[0] &= 248
+ e[31] &= 127
+ e[31] |= 64
+
+ var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement
+ feFromBytes(&x1, base)
+ feOne(&x2)
+ feCopy(&x3, &x1)
+ feOne(&z3)
+
+ swap := int32(0)
+ for pos := 254; pos >= 0; pos-- {
+ b := e[pos/8] >> uint(pos&7)
+ b &= 1
+ swap ^= int32(b)
+ feCSwap(&x2, &x3, swap)
+ feCSwap(&z2, &z3, swap)
+ swap = int32(b)
+
+ feSub(&tmp0, &x3, &z3)
+ feSub(&tmp1, &x2, &z2)
+ feAdd(&x2, &x2, &z2)
+ feAdd(&z2, &x3, &z3)
+ feMul(&z3, &tmp0, &x2)
+ feMul(&z2, &z2, &tmp1)
+ feSquare(&tmp0, &tmp1)
+ feSquare(&tmp1, &x2)
+ feAdd(&x3, &z3, &z2)
+ feSub(&z2, &z3, &z2)
+ feMul(&x2, &tmp1, &tmp0)
+ feSub(&tmp1, &tmp1, &tmp0)
+ feSquare(&z2, &z2)
+ feMul121666(&z3, &tmp1)
+ feSquare(&x3, &x3)
+ feAdd(&tmp0, &tmp0, &z3)
+ feMul(&z3, &x1, &z2)
+ feMul(&z2, &tmp1, &tmp0)
+ }
+
+ feCSwap(&x2, &x3, swap)
+ feCSwap(&z2, &z3, swap)
+
+ feInvert(&z2, &z2)
+ feMul(&x2, &x2, &z2)
+ feToBytes(out, &x2)
+}
diff --git a/libgo/go/golang_org/x/crypto/curve25519/curve25519_test.go b/libgo/go/golang_org/x/crypto/curve25519/curve25519_test.go
new file mode 100644
index 00000000000..14b0ee87cdd
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/curve25519/curve25519_test.go
@@ -0,0 +1,29 @@
+// 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 curve25519
+
+import (
+ "fmt"
+ "testing"
+)
+
+const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a"
+
+func TestBaseScalarMult(t *testing.T) {
+ var a, b [32]byte
+ in := &a
+ out := &b
+ a[0] = 1
+
+ for i := 0; i < 200; i++ {
+ ScalarBaseMult(out, in)
+ in, out = out, in
+ }
+
+ result := fmt.Sprintf("%x", in[:])
+ if result != expectedHex {
+ t.Errorf("incorrect result: got %s, want %s", result, expectedHex)
+ }
+}
diff --git a/libgo/go/golang_org/x/crypto/curve25519/doc.go b/libgo/go/golang_org/x/crypto/curve25519/doc.go
new file mode 100644
index 00000000000..ebeea3c2d6a
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/curve25519/doc.go
@@ -0,0 +1,23 @@
+// 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 curve25519 provides an implementation of scalar multiplication on
+// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html
+package curve25519 // import "golang.org/x/crypto/curve25519"
+
+// basePoint is the x coordinate of the generator of the curve.
+var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+// ScalarMult sets dst to the product in*base where dst and base are the x
+// coordinates of group points and all values are in little-endian form.
+func ScalarMult(dst, in, base *[32]byte) {
+ scalarMult(dst, in, base)
+}
+
+// ScalarBaseMult sets dst to the product in*base where dst and base are the x
+// coordinates of group points, base is the standard generator and all values
+// are in little-endian form.
+func ScalarBaseMult(dst, in *[32]byte) {
+ ScalarMult(dst, in, &basePoint)
+}
diff --git a/libgo/go/golang_org/x/crypto/curve25519/mont25519_amd64.go b/libgo/go/golang_org/x/crypto/curve25519/mont25519_amd64.go
new file mode 100644
index 00000000000..5822bd53383
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/curve25519/mont25519_amd64.go
@@ -0,0 +1,240 @@
+// 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 amd64,!gccgo,!appengine
+
+package curve25519
+
+// These functions are implemented in the .s files. The names of the functions
+// in the rest of the file are also taken from the SUPERCOP sources to help
+// people following along.
+
+//go:noescape
+
+func cswap(inout *[5]uint64, v uint64)
+
+//go:noescape
+
+func ladderstep(inout *[5][5]uint64)
+
+//go:noescape
+
+func freeze(inout *[5]uint64)
+
+//go:noescape
+
+func mul(dest, a, b *[5]uint64)
+
+//go:noescape
+
+func square(out, in *[5]uint64)
+
+// mladder uses a Montgomery ladder to calculate (xr/zr) *= s.
+func mladder(xr, zr *[5]uint64, s *[32]byte) {
+ var work [5][5]uint64
+
+ work[0] = *xr
+ setint(&work[1], 1)
+ setint(&work[2], 0)
+ work[3] = *xr
+ setint(&work[4], 1)
+
+ j := uint(6)
+ var prevbit byte
+
+ for i := 31; i >= 0; i-- {
+ for j < 8 {
+ bit := ((*s)[i] >> j) & 1
+ swap := bit ^ prevbit
+ prevbit = bit
+ cswap(&work[1], uint64(swap))
+ ladderstep(&work)
+ j--
+ }
+ j = 7
+ }
+
+ *xr = work[1]
+ *zr = work[2]
+}
+
+func scalarMult(out, in, base *[32]byte) {
+ var e [32]byte
+ copy(e[:], (*in)[:])
+ e[0] &= 248
+ e[31] &= 127
+ e[31] |= 64
+
+ var t, z [5]uint64
+ unpack(&t, base)
+ mladder(&t, &z, &e)
+ invert(&z, &z)
+ mul(&t, &t, &z)
+ pack(out, &t)
+}
+
+func setint(r *[5]uint64, v uint64) {
+ r[0] = v
+ r[1] = 0
+ r[2] = 0
+ r[3] = 0
+ r[4] = 0
+}
+
+// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian
+// order.
+func unpack(r *[5]uint64, x *[32]byte) {
+ r[0] = uint64(x[0]) |
+ uint64(x[1])<<8 |
+ uint64(x[2])<<16 |
+ uint64(x[3])<<24 |
+ uint64(x[4])<<32 |
+ uint64(x[5])<<40 |
+ uint64(x[6]&7)<<48
+
+ r[1] = uint64(x[6])>>3 |
+ uint64(x[7])<<5 |
+ uint64(x[8])<<13 |
+ uint64(x[9])<<21 |
+ uint64(x[10])<<29 |
+ uint64(x[11])<<37 |
+ uint64(x[12]&63)<<45
+
+ r[2] = uint64(x[12])>>6 |
+ uint64(x[13])<<2 |
+ uint64(x[14])<<10 |
+ uint64(x[15])<<18 |
+ uint64(x[16])<<26 |
+ uint64(x[17])<<34 |
+ uint64(x[18])<<42 |
+ uint64(x[19]&1)<<50
+
+ r[3] = uint64(x[19])>>1 |
+ uint64(x[20])<<7 |
+ uint64(x[21])<<15 |
+ uint64(x[22])<<23 |
+ uint64(x[23])<<31 |
+ uint64(x[24])<<39 |
+ uint64(x[25]&15)<<47
+
+ r[4] = uint64(x[25])>>4 |
+ uint64(x[26])<<4 |
+ uint64(x[27])<<12 |
+ uint64(x[28])<<20 |
+ uint64(x[29])<<28 |
+ uint64(x[30])<<36 |
+ uint64(x[31]&127)<<44
+}
+
+// pack sets out = x where out is the usual, little-endian form of the 5,
+// 51-bit limbs in x.
+func pack(out *[32]byte, x *[5]uint64) {
+ t := *x
+ freeze(&t)
+
+ out[0] = byte(t[0])
+ out[1] = byte(t[0] >> 8)
+ out[2] = byte(t[0] >> 16)
+ out[3] = byte(t[0] >> 24)
+ out[4] = byte(t[0] >> 32)
+ out[5] = byte(t[0] >> 40)
+ out[6] = byte(t[0] >> 48)
+
+ out[6] ^= byte(t[1]<<3) & 0xf8
+ out[7] = byte(t[1] >> 5)
+ out[8] = byte(t[1] >> 13)
+ out[9] = byte(t[1] >> 21)
+ out[10] = byte(t[1] >> 29)
+ out[11] = byte(t[1] >> 37)
+ out[12] = byte(t[1] >> 45)
+
+ out[12] ^= byte(t[2]<<6) & 0xc0
+ out[13] = byte(t[2] >> 2)
+ out[14] = byte(t[2] >> 10)
+ out[15] = byte(t[2] >> 18)
+ out[16] = byte(t[2] >> 26)
+ out[17] = byte(t[2] >> 34)
+ out[18] = byte(t[2] >> 42)
+ out[19] = byte(t[2] >> 50)
+
+ out[19] ^= byte(t[3]<<1) & 0xfe
+ out[20] = byte(t[3] >> 7)
+ out[21] = byte(t[3] >> 15)
+ out[22] = byte(t[3] >> 23)
+ out[23] = byte(t[3] >> 31)
+ out[24] = byte(t[3] >> 39)
+ out[25] = byte(t[3] >> 47)
+
+ out[25] ^= byte(t[4]<<4) & 0xf0
+ out[26] = byte(t[4] >> 4)
+ out[27] = byte(t[4] >> 12)
+ out[28] = byte(t[4] >> 20)
+ out[29] = byte(t[4] >> 28)
+ out[30] = byte(t[4] >> 36)
+ out[31] = byte(t[4] >> 44)
+}
+
+// invert calculates r = x^-1 mod p using Fermat's little theorem.
+func invert(r *[5]uint64, x *[5]uint64) {
+ var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64
+
+ square(&z2, x) /* 2 */
+ square(&t, &z2) /* 4 */
+ square(&t, &t) /* 8 */
+ mul(&z9, &t, x) /* 9 */
+ mul(&z11, &z9, &z2) /* 11 */
+ square(&t, &z11) /* 22 */
+ mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */
+
+ square(&t, &z2_5_0) /* 2^6 - 2^1 */
+ for i := 1; i < 5; i++ { /* 2^20 - 2^10 */
+ square(&t, &t)
+ }
+ mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */
+
+ square(&t, &z2_10_0) /* 2^11 - 2^1 */
+ for i := 1; i < 10; i++ { /* 2^20 - 2^10 */
+ square(&t, &t)
+ }
+ mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */
+
+ square(&t, &z2_20_0) /* 2^21 - 2^1 */
+ for i := 1; i < 20; i++ { /* 2^40 - 2^20 */
+ square(&t, &t)
+ }
+ mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */
+
+ square(&t, &t) /* 2^41 - 2^1 */
+ for i := 1; i < 10; i++ { /* 2^50 - 2^10 */
+ square(&t, &t)
+ }
+ mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */
+
+ square(&t, &z2_50_0) /* 2^51 - 2^1 */
+ for i := 1; i < 50; i++ { /* 2^100 - 2^50 */
+ square(&t, &t)
+ }
+ mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */
+
+ square(&t, &z2_100_0) /* 2^101 - 2^1 */
+ for i := 1; i < 100; i++ { /* 2^200 - 2^100 */
+ square(&t, &t)
+ }
+ mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */
+
+ square(&t, &t) /* 2^201 - 2^1 */
+ for i := 1; i < 50; i++ { /* 2^250 - 2^50 */
+ square(&t, &t)
+ }
+ mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */
+
+ square(&t, &t) /* 2^251 - 2^1 */
+ square(&t, &t) /* 2^252 - 2^2 */
+ square(&t, &t) /* 2^253 - 2^3 */
+
+ square(&t, &t) /* 2^254 - 2^4 */
+
+ square(&t, &t) /* 2^255 - 2^5 */
+ mul(r, &t, &z11) /* 2^255 - 21 */
+}
diff --git a/libgo/go/golang_org/x/crypto/poly1305/poly1305.go b/libgo/go/golang_org/x/crypto/poly1305/poly1305.go
new file mode 100644
index 00000000000..4a5f826f7a6
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/poly1305/poly1305.go
@@ -0,0 +1,32 @@
+// 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 poly1305 implements Poly1305 one-time message authentication code as specified in http://cr.yp.to/mac/poly1305-20050329.pdf.
+
+Poly1305 is a fast, one-time authentication function. It is infeasible for an
+attacker to generate an authenticator for a message without the key. However, a
+key must only be used for a single message. Authenticating two different
+messages with the same key allows an attacker to forge authenticators for other
+messages with the same key.
+
+Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was
+used with a fixed key in order to generate one-time keys from an nonce.
+However, in this package AES isn't used and the one-time key is specified
+directly.
+*/
+package poly1305 // import "golang.org/x/crypto/poly1305"
+
+import "crypto/subtle"
+
+// TagSize is the size, in bytes, of a poly1305 authenticator.
+const TagSize = 16
+
+// Verify returns true if mac is a valid authenticator for m with the given
+// key.
+func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
+ var tmp [16]byte
+ Sum(&tmp, m, key)
+ return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
+}
diff --git a/libgo/go/golang_org/x/crypto/poly1305/poly1305_test.go b/libgo/go/golang_org/x/crypto/poly1305/poly1305_test.go
new file mode 100644
index 00000000000..91b8e2b496f
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/poly1305/poly1305_test.go
@@ -0,0 +1,92 @@
+// 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 poly1305
+
+import (
+ "bytes"
+ "testing"
+ "unsafe"
+)
+
+var testData = []struct {
+ in, k, correct []byte
+}{
+ {
+ []byte("Hello world!"),
+ []byte("this is 32-byte key for Poly1305"),
+ []byte{0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0},
+ },
+ {
+ make([]byte, 32),
+ []byte("this is 32-byte key for Poly1305"),
+ []byte{0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07},
+ },
+ {
+ make([]byte, 2007),
+ []byte("this is 32-byte key for Poly1305"),
+ []byte{0xda, 0x84, 0xbc, 0xab, 0x02, 0x67, 0x6c, 0x38, 0xcd, 0xb0, 0x15, 0x60, 0x42, 0x74, 0xc2, 0xaa},
+ },
+ {
+ make([]byte, 2007),
+ make([]byte, 32),
+ make([]byte, 16),
+ },
+ {
+ // This test triggers an edge-case. See https://go-review.googlesource.com/#/c/30101/.
+ []byte{0x81, 0xd8, 0xb2, 0xe4, 0x6a, 0x25, 0x21, 0x3b, 0x58, 0xfe, 0xe4, 0x21, 0x3a, 0x2a, 0x28, 0xe9, 0x21, 0xc1, 0x2a, 0x96, 0x32, 0x51, 0x6d, 0x3b, 0x73, 0x27, 0x27, 0x27, 0xbe, 0xcf, 0x21, 0x29},
+ []byte{0x3b, 0x3a, 0x29, 0xe9, 0x3b, 0x21, 0x3a, 0x5c, 0x5c, 0x3b, 0x3b, 0x05, 0x3a, 0x3a, 0x8c, 0x0d},
+ []byte{0x6d, 0xc1, 0x8b, 0x8c, 0x34, 0x4c, 0xd7, 0x99, 0x27, 0x11, 0x8b, 0xbe, 0x84, 0xb7, 0xf3, 0x14},
+ },
+}
+
+func testSum(t *testing.T, unaligned bool) {
+ var out [16]byte
+ var key [32]byte
+
+ for i, v := range testData {
+ in := v.in
+ if unaligned {
+ in = unalignBytes(in)
+ }
+ copy(key[:], v.k)
+ Sum(&out, in, &key)
+ if !bytes.Equal(out[:], v.correct) {
+ t.Errorf("%d: expected %x, got %x", i, v.correct, out[:])
+ }
+ }
+}
+
+func TestSum(t *testing.T) { testSum(t, false) }
+func TestSumUnaligned(t *testing.T) { testSum(t, true) }
+
+func benchmark(b *testing.B, size int, unaligned bool) {
+ var out [16]byte
+ var key [32]byte
+ in := make([]byte, size)
+ if unaligned {
+ in = unalignBytes(in)
+ }
+ b.SetBytes(int64(len(in)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ Sum(&out, in, &key)
+ }
+}
+
+func Benchmark64(b *testing.B) { benchmark(b, 64, false) }
+func Benchmark1K(b *testing.B) { benchmark(b, 1024, false) }
+func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) }
+func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) }
+
+func unalignBytes(in []byte) []byte {
+ out := make([]byte, len(in)+1)
+ if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
+ out = out[1:]
+ } else {
+ out = out[:len(in)]
+ }
+ copy(out, in)
+ return out
+}
diff --git a/libgo/go/golang_org/x/crypto/poly1305/sum_amd64.go b/libgo/go/golang_org/x/crypto/poly1305/sum_amd64.go
new file mode 100644
index 00000000000..4dd72fe799b
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/poly1305/sum_amd64.go
@@ -0,0 +1,22 @@
+// 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 amd64,!gccgo,!appengine
+
+package poly1305
+
+// This function is implemented in sum_amd64.s
+//go:noescape
+func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
+
+// Sum generates an authenticator for m using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
+ var mPtr *byte
+ if len(m) > 0 {
+ mPtr = &m[0]
+ }
+ poly1305(out, mPtr, uint64(len(m)), key)
+}
diff --git a/libgo/go/golang_org/x/crypto/poly1305/sum_arm.go b/libgo/go/golang_org/x/crypto/poly1305/sum_arm.go
new file mode 100644
index 00000000000..5dc321c2f39
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/poly1305/sum_arm.go
@@ -0,0 +1,22 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build arm,!gccgo,!appengine,!nacl
+
+package poly1305
+
+// This function is implemented in sum_arm.s
+//go:noescape
+func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte)
+
+// Sum generates an authenticator for m using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
+ var mPtr *byte
+ if len(m) > 0 {
+ mPtr = &m[0]
+ }
+ poly1305_auth_armv6(out, mPtr, uint32(len(m)), key)
+}
diff --git a/libgo/go/golang_org/x/crypto/poly1305/sum_ref.go b/libgo/go/golang_org/x/crypto/poly1305/sum_ref.go
new file mode 100644
index 00000000000..dbe50e78a0d
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/poly1305/sum_ref.go
@@ -0,0 +1,1531 @@
+// 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 !amd64,!arm gccgo appengine nacl
+
+package poly1305
+
+// Based on original, public domain implementation from NaCl by D. J.
+// Bernstein.
+
+import "math"
+
+const (
+ alpham80 = 0.00000000558793544769287109375
+ alpham48 = 24.0
+ alpham16 = 103079215104.0
+ alpha0 = 6755399441055744.0
+ alpha18 = 1770887431076116955136.0
+ alpha32 = 29014219670751100192948224.0
+ alpha50 = 7605903601369376408980219232256.0
+ alpha64 = 124615124604835863084731911901282304.0
+ alpha82 = 32667107224410092492483962313449748299776.0
+ alpha96 = 535217884764734955396857238543560676143529984.0
+ alpha112 = 35076039295941670036888435985190792471742381031424.0
+ alpha130 = 9194973245195333150150082162901855101712434733101613056.0
+ scale = 0.0000000000000000000000000000000000000036734198463196484624023016788195177431833298649127735047148490821200539357960224151611328125
+ offset0 = 6755408030990331.0
+ offset1 = 29014256564239239022116864.0
+ offset2 = 124615283061160854719918951570079744.0
+ offset3 = 535219245894202480694386063513315216128475136.0
+)
+
+// Sum generates an authenticator for m using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
+ r := key
+ s := key[16:]
+ var (
+ y7 float64
+ y6 float64
+ y1 float64
+ y0 float64
+ y5 float64
+ y4 float64
+ x7 float64
+ x6 float64
+ x1 float64
+ x0 float64
+ y3 float64
+ y2 float64
+ x5 float64
+ r3lowx0 float64
+ x4 float64
+ r0lowx6 float64
+ x3 float64
+ r3highx0 float64
+ x2 float64
+ r0highx6 float64
+ r0lowx0 float64
+ sr1lowx6 float64
+ r0highx0 float64
+ sr1highx6 float64
+ sr3low float64
+ r1lowx0 float64
+ sr2lowx6 float64
+ r1highx0 float64
+ sr2highx6 float64
+ r2lowx0 float64
+ sr3lowx6 float64
+ r2highx0 float64
+ sr3highx6 float64
+ r1highx4 float64
+ r1lowx4 float64
+ r0highx4 float64
+ r0lowx4 float64
+ sr3highx4 float64
+ sr3lowx4 float64
+ sr2highx4 float64
+ sr2lowx4 float64
+ r0lowx2 float64
+ r0highx2 float64
+ r1lowx2 float64
+ r1highx2 float64
+ r2lowx2 float64
+ r2highx2 float64
+ sr3lowx2 float64
+ sr3highx2 float64
+ z0 float64
+ z1 float64
+ z2 float64
+ z3 float64
+ m0 int64
+ m1 int64
+ m2 int64
+ m3 int64
+ m00 uint32
+ m01 uint32
+ m02 uint32
+ m03 uint32
+ m10 uint32
+ m11 uint32
+ m12 uint32
+ m13 uint32
+ m20 uint32
+ m21 uint32
+ m22 uint32
+ m23 uint32
+ m30 uint32
+ m31 uint32
+ m32 uint32
+ m33 uint64
+ lbelow2 int32
+ lbelow3 int32
+ lbelow4 int32
+ lbelow5 int32
+ lbelow6 int32
+ lbelow7 int32
+ lbelow8 int32
+ lbelow9 int32
+ lbelow10 int32
+ lbelow11 int32
+ lbelow12 int32
+ lbelow13 int32
+ lbelow14 int32
+ lbelow15 int32
+ s00 uint32
+ s01 uint32
+ s02 uint32
+ s03 uint32
+ s10 uint32
+ s11 uint32
+ s12 uint32
+ s13 uint32
+ s20 uint32
+ s21 uint32
+ s22 uint32
+ s23 uint32
+ s30 uint32
+ s31 uint32
+ s32 uint32
+ s33 uint32
+ bits32 uint64
+ f uint64
+ f0 uint64
+ f1 uint64
+ f2 uint64
+ f3 uint64
+ f4 uint64
+ g uint64
+ g0 uint64
+ g1 uint64
+ g2 uint64
+ g3 uint64
+ g4 uint64
+ )
+
+ var p int32
+
+ l := int32(len(m))
+
+ r00 := uint32(r[0])
+
+ r01 := uint32(r[1])
+
+ r02 := uint32(r[2])
+ r0 := int64(2151)
+
+ r03 := uint32(r[3])
+ r03 &= 15
+ r0 <<= 51
+
+ r10 := uint32(r[4])
+ r10 &= 252
+ r01 <<= 8
+ r0 += int64(r00)
+
+ r11 := uint32(r[5])
+ r02 <<= 16
+ r0 += int64(r01)
+
+ r12 := uint32(r[6])
+ r03 <<= 24
+ r0 += int64(r02)
+
+ r13 := uint32(r[7])
+ r13 &= 15
+ r1 := int64(2215)
+ r0 += int64(r03)
+
+ d0 := r0
+ r1 <<= 51
+ r2 := int64(2279)
+
+ r20 := uint32(r[8])
+ r20 &= 252
+ r11 <<= 8
+ r1 += int64(r10)
+
+ r21 := uint32(r[9])
+ r12 <<= 16
+ r1 += int64(r11)
+
+ r22 := uint32(r[10])
+ r13 <<= 24
+ r1 += int64(r12)
+
+ r23 := uint32(r[11])
+ r23 &= 15
+ r2 <<= 51
+ r1 += int64(r13)
+
+ d1 := r1
+ r21 <<= 8
+ r2 += int64(r20)
+
+ r30 := uint32(r[12])
+ r30 &= 252
+ r22 <<= 16
+ r2 += int64(r21)
+
+ r31 := uint32(r[13])
+ r23 <<= 24
+ r2 += int64(r22)
+
+ r32 := uint32(r[14])
+ r2 += int64(r23)
+ r3 := int64(2343)
+
+ d2 := r2
+ r3 <<= 51
+
+ r33 := uint32(r[15])
+ r33 &= 15
+ r31 <<= 8
+ r3 += int64(r30)
+
+ r32 <<= 16
+ r3 += int64(r31)
+
+ r33 <<= 24
+ r3 += int64(r32)
+
+ r3 += int64(r33)
+ h0 := alpha32 - alpha32
+
+ d3 := r3
+ h1 := alpha32 - alpha32
+
+ h2 := alpha32 - alpha32
+
+ h3 := alpha32 - alpha32
+
+ h4 := alpha32 - alpha32
+
+ r0low := math.Float64frombits(uint64(d0))
+ h5 := alpha32 - alpha32
+
+ r1low := math.Float64frombits(uint64(d1))
+ h6 := alpha32 - alpha32
+
+ r2low := math.Float64frombits(uint64(d2))
+ h7 := alpha32 - alpha32
+
+ r0low -= alpha0
+
+ r1low -= alpha32
+
+ r2low -= alpha64
+
+ r0high := r0low + alpha18
+
+ r3low := math.Float64frombits(uint64(d3))
+
+ r1high := r1low + alpha50
+ sr1low := scale * r1low
+
+ r2high := r2low + alpha82
+ sr2low := scale * r2low
+
+ r0high -= alpha18
+ r0high_stack := r0high
+
+ r3low -= alpha96
+
+ r1high -= alpha50
+ r1high_stack := r1high
+
+ sr1high := sr1low + alpham80
+
+ r0low -= r0high
+
+ r2high -= alpha82
+ sr3low = scale * r3low
+
+ sr2high := sr2low + alpham48
+
+ r1low -= r1high
+ r1low_stack := r1low
+
+ sr1high -= alpham80
+ sr1high_stack := sr1high
+
+ r2low -= r2high
+ r2low_stack := r2low
+
+ sr2high -= alpham48
+ sr2high_stack := sr2high
+
+ r3high := r3low + alpha112
+ r0low_stack := r0low
+
+ sr1low -= sr1high
+ sr1low_stack := sr1low
+
+ sr3high := sr3low + alpham16
+ r2high_stack := r2high
+
+ sr2low -= sr2high
+ sr2low_stack := sr2low
+
+ r3high -= alpha112
+ r3high_stack := r3high
+
+ sr3high -= alpham16
+ sr3high_stack := sr3high
+
+ r3low -= r3high
+ r3low_stack := r3low
+
+ sr3low -= sr3high
+ sr3low_stack := sr3low
+
+ if l < 16 {
+ goto addatmost15bytes
+ }
+
+ m00 = uint32(m[p+0])
+ m0 = 2151
+
+ m0 <<= 51
+ m1 = 2215
+ m01 = uint32(m[p+1])
+
+ m1 <<= 51
+ m2 = 2279
+ m02 = uint32(m[p+2])
+
+ m2 <<= 51
+ m3 = 2343
+ m03 = uint32(m[p+3])
+
+ m10 = uint32(m[p+4])
+ m01 <<= 8
+ m0 += int64(m00)
+
+ m11 = uint32(m[p+5])
+ m02 <<= 16
+ m0 += int64(m01)
+
+ m12 = uint32(m[p+6])
+ m03 <<= 24
+ m0 += int64(m02)
+
+ m13 = uint32(m[p+7])
+ m3 <<= 51
+ m0 += int64(m03)
+
+ m20 = uint32(m[p+8])
+ m11 <<= 8
+ m1 += int64(m10)
+
+ m21 = uint32(m[p+9])
+ m12 <<= 16
+ m1 += int64(m11)
+
+ m22 = uint32(m[p+10])
+ m13 <<= 24
+ m1 += int64(m12)
+
+ m23 = uint32(m[p+11])
+ m1 += int64(m13)
+
+ m30 = uint32(m[p+12])
+ m21 <<= 8
+ m2 += int64(m20)
+
+ m31 = uint32(m[p+13])
+ m22 <<= 16
+ m2 += int64(m21)
+
+ m32 = uint32(m[p+14])
+ m23 <<= 24
+ m2 += int64(m22)
+
+ m33 = uint64(m[p+15])
+ m2 += int64(m23)
+
+ d0 = m0
+ m31 <<= 8
+ m3 += int64(m30)
+
+ d1 = m1
+ m32 <<= 16
+ m3 += int64(m31)
+
+ d2 = m2
+ m33 += 256
+
+ m33 <<= 24
+ m3 += int64(m32)
+
+ m3 += int64(m33)
+ d3 = m3
+
+ p += 16
+ l -= 16
+
+ z0 = math.Float64frombits(uint64(d0))
+
+ z1 = math.Float64frombits(uint64(d1))
+
+ z2 = math.Float64frombits(uint64(d2))
+
+ z3 = math.Float64frombits(uint64(d3))
+
+ z0 -= alpha0
+
+ z1 -= alpha32
+
+ z2 -= alpha64
+
+ z3 -= alpha96
+
+ h0 += z0
+
+ h1 += z1
+
+ h3 += z2
+
+ h5 += z3
+
+ if l < 16 {
+ goto multiplyaddatmost15bytes
+ }
+
+multiplyaddatleast16bytes:
+
+ m2 = 2279
+ m20 = uint32(m[p+8])
+ y7 = h7 + alpha130
+
+ m2 <<= 51
+ m3 = 2343
+ m21 = uint32(m[p+9])
+ y6 = h6 + alpha130
+
+ m3 <<= 51
+ m0 = 2151
+ m22 = uint32(m[p+10])
+ y1 = h1 + alpha32
+
+ m0 <<= 51
+ m1 = 2215
+ m23 = uint32(m[p+11])
+ y0 = h0 + alpha32
+
+ m1 <<= 51
+ m30 = uint32(m[p+12])
+ y7 -= alpha130
+
+ m21 <<= 8
+ m2 += int64(m20)
+ m31 = uint32(m[p+13])
+ y6 -= alpha130
+
+ m22 <<= 16
+ m2 += int64(m21)
+ m32 = uint32(m[p+14])
+ y1 -= alpha32
+
+ m23 <<= 24
+ m2 += int64(m22)
+ m33 = uint64(m[p+15])
+ y0 -= alpha32
+
+ m2 += int64(m23)
+ m00 = uint32(m[p+0])
+ y5 = h5 + alpha96
+
+ m31 <<= 8
+ m3 += int64(m30)
+ m01 = uint32(m[p+1])
+ y4 = h4 + alpha96
+
+ m32 <<= 16
+ m02 = uint32(m[p+2])
+ x7 = h7 - y7
+ y7 *= scale
+
+ m33 += 256
+ m03 = uint32(m[p+3])
+ x6 = h6 - y6
+ y6 *= scale
+
+ m33 <<= 24
+ m3 += int64(m31)
+ m10 = uint32(m[p+4])
+ x1 = h1 - y1
+
+ m01 <<= 8
+ m3 += int64(m32)
+ m11 = uint32(m[p+5])
+ x0 = h0 - y0
+
+ m3 += int64(m33)
+ m0 += int64(m00)
+ m12 = uint32(m[p+6])
+ y5 -= alpha96
+
+ m02 <<= 16
+ m0 += int64(m01)
+ m13 = uint32(m[p+7])
+ y4 -= alpha96
+
+ m03 <<= 24
+ m0 += int64(m02)
+ d2 = m2
+ x1 += y7
+
+ m0 += int64(m03)
+ d3 = m3
+ x0 += y6
+
+ m11 <<= 8
+ m1 += int64(m10)
+ d0 = m0
+ x7 += y5
+
+ m12 <<= 16
+ m1 += int64(m11)
+ x6 += y4
+
+ m13 <<= 24
+ m1 += int64(m12)
+ y3 = h3 + alpha64
+
+ m1 += int64(m13)
+ d1 = m1
+ y2 = h2 + alpha64
+
+ x0 += x1
+
+ x6 += x7
+
+ y3 -= alpha64
+ r3low = r3low_stack
+
+ y2 -= alpha64
+ r0low = r0low_stack
+
+ x5 = h5 - y5
+ r3lowx0 = r3low * x0
+ r3high = r3high_stack
+
+ x4 = h4 - y4
+ r0lowx6 = r0low * x6
+ r0high = r0high_stack
+
+ x3 = h3 - y3
+ r3highx0 = r3high * x0
+ sr1low = sr1low_stack
+
+ x2 = h2 - y2
+ r0highx6 = r0high * x6
+ sr1high = sr1high_stack
+
+ x5 += y3
+ r0lowx0 = r0low * x0
+ r1low = r1low_stack
+
+ h6 = r3lowx0 + r0lowx6
+ sr1lowx6 = sr1low * x6
+ r1high = r1high_stack
+
+ x4 += y2
+ r0highx0 = r0high * x0
+ sr2low = sr2low_stack
+
+ h7 = r3highx0 + r0highx6
+ sr1highx6 = sr1high * x6
+ sr2high = sr2high_stack
+
+ x3 += y1
+ r1lowx0 = r1low * x0
+ r2low = r2low_stack
+
+ h0 = r0lowx0 + sr1lowx6
+ sr2lowx6 = sr2low * x6
+ r2high = r2high_stack
+
+ x2 += y0
+ r1highx0 = r1high * x0
+ sr3low = sr3low_stack
+
+ h1 = r0highx0 + sr1highx6
+ sr2highx6 = sr2high * x6
+ sr3high = sr3high_stack
+
+ x4 += x5
+ r2lowx0 = r2low * x0
+ z2 = math.Float64frombits(uint64(d2))
+
+ h2 = r1lowx0 + sr2lowx6
+ sr3lowx6 = sr3low * x6
+
+ x2 += x3
+ r2highx0 = r2high * x0
+ z3 = math.Float64frombits(uint64(d3))
+
+ h3 = r1highx0 + sr2highx6
+ sr3highx6 = sr3high * x6
+
+ r1highx4 = r1high * x4
+ z2 -= alpha64
+
+ h4 = r2lowx0 + sr3lowx6
+ r1lowx4 = r1low * x4
+
+ r0highx4 = r0high * x4
+ z3 -= alpha96
+
+ h5 = r2highx0 + sr3highx6
+ r0lowx4 = r0low * x4
+
+ h7 += r1highx4
+ sr3highx4 = sr3high * x4
+
+ h6 += r1lowx4
+ sr3lowx4 = sr3low * x4
+
+ h5 += r0highx4
+ sr2highx4 = sr2high * x4
+
+ h4 += r0lowx4
+ sr2lowx4 = sr2low * x4
+
+ h3 += sr3highx4
+ r0lowx2 = r0low * x2
+
+ h2 += sr3lowx4
+ r0highx2 = r0high * x2
+
+ h1 += sr2highx4
+ r1lowx2 = r1low * x2
+
+ h0 += sr2lowx4
+ r1highx2 = r1high * x2
+
+ h2 += r0lowx2
+ r2lowx2 = r2low * x2
+
+ h3 += r0highx2
+ r2highx2 = r2high * x2
+
+ h4 += r1lowx2
+ sr3lowx2 = sr3low * x2
+
+ h5 += r1highx2
+ sr3highx2 = sr3high * x2
+
+ p += 16
+ l -= 16
+ h6 += r2lowx2
+
+ h7 += r2highx2
+
+ z1 = math.Float64frombits(uint64(d1))
+ h0 += sr3lowx2
+
+ z0 = math.Float64frombits(uint64(d0))
+ h1 += sr3highx2
+
+ z1 -= alpha32
+
+ z0 -= alpha0
+
+ h5 += z3
+
+ h3 += z2
+
+ h1 += z1
+
+ h0 += z0
+
+ if l >= 16 {
+ goto multiplyaddatleast16bytes
+ }
+
+multiplyaddatmost15bytes:
+
+ y7 = h7 + alpha130
+
+ y6 = h6 + alpha130
+
+ y1 = h1 + alpha32
+
+ y0 = h0 + alpha32
+
+ y7 -= alpha130
+
+ y6 -= alpha130
+
+ y1 -= alpha32
+
+ y0 -= alpha32
+
+ y5 = h5 + alpha96
+
+ y4 = h4 + alpha96
+
+ x7 = h7 - y7
+ y7 *= scale
+
+ x6 = h6 - y6
+ y6 *= scale
+
+ x1 = h1 - y1
+
+ x0 = h0 - y0
+
+ y5 -= alpha96
+
+ y4 -= alpha96
+
+ x1 += y7
+
+ x0 += y6
+
+ x7 += y5
+
+ x6 += y4
+
+ y3 = h3 + alpha64
+
+ y2 = h2 + alpha64
+
+ x0 += x1
+
+ x6 += x7
+
+ y3 -= alpha64
+ r3low = r3low_stack
+
+ y2 -= alpha64
+ r0low = r0low_stack
+
+ x5 = h5 - y5
+ r3lowx0 = r3low * x0
+ r3high = r3high_stack
+
+ x4 = h4 - y4
+ r0lowx6 = r0low * x6
+ r0high = r0high_stack
+
+ x3 = h3 - y3
+ r3highx0 = r3high * x0
+ sr1low = sr1low_stack
+
+ x2 = h2 - y2
+ r0highx6 = r0high * x6
+ sr1high = sr1high_stack
+
+ x5 += y3
+ r0lowx0 = r0low * x0
+ r1low = r1low_stack
+
+ h6 = r3lowx0 + r0lowx6
+ sr1lowx6 = sr1low * x6
+ r1high = r1high_stack
+
+ x4 += y2
+ r0highx0 = r0high * x0
+ sr2low = sr2low_stack
+
+ h7 = r3highx0 + r0highx6
+ sr1highx6 = sr1high * x6
+ sr2high = sr2high_stack
+
+ x3 += y1
+ r1lowx0 = r1low * x0
+ r2low = r2low_stack
+
+ h0 = r0lowx0 + sr1lowx6
+ sr2lowx6 = sr2low * x6
+ r2high = r2high_stack
+
+ x2 += y0
+ r1highx0 = r1high * x0
+ sr3low = sr3low_stack
+
+ h1 = r0highx0 + sr1highx6
+ sr2highx6 = sr2high * x6
+ sr3high = sr3high_stack
+
+ x4 += x5
+ r2lowx0 = r2low * x0
+
+ h2 = r1lowx0 + sr2lowx6
+ sr3lowx6 = sr3low * x6
+
+ x2 += x3
+ r2highx0 = r2high * x0
+
+ h3 = r1highx0 + sr2highx6
+ sr3highx6 = sr3high * x6
+
+ r1highx4 = r1high * x4
+
+ h4 = r2lowx0 + sr3lowx6
+ r1lowx4 = r1low * x4
+
+ r0highx4 = r0high * x4
+
+ h5 = r2highx0 + sr3highx6
+ r0lowx4 = r0low * x4
+
+ h7 += r1highx4
+ sr3highx4 = sr3high * x4
+
+ h6 += r1lowx4
+ sr3lowx4 = sr3low * x4
+
+ h5 += r0highx4
+ sr2highx4 = sr2high * x4
+
+ h4 += r0lowx4
+ sr2lowx4 = sr2low * x4
+
+ h3 += sr3highx4
+ r0lowx2 = r0low * x2
+
+ h2 += sr3lowx4
+ r0highx2 = r0high * x2
+
+ h1 += sr2highx4
+ r1lowx2 = r1low * x2
+
+ h0 += sr2lowx4
+ r1highx2 = r1high * x2
+
+ h2 += r0lowx2
+ r2lowx2 = r2low * x2
+
+ h3 += r0highx2
+ r2highx2 = r2high * x2
+
+ h4 += r1lowx2
+ sr3lowx2 = sr3low * x2
+
+ h5 += r1highx2
+ sr3highx2 = sr3high * x2
+
+ h6 += r2lowx2
+
+ h7 += r2highx2
+
+ h0 += sr3lowx2
+
+ h1 += sr3highx2
+
+addatmost15bytes:
+
+ if l == 0 {
+ goto nomorebytes
+ }
+
+ lbelow2 = l - 2
+
+ lbelow3 = l - 3
+
+ lbelow2 >>= 31
+ lbelow4 = l - 4
+
+ m00 = uint32(m[p+0])
+ lbelow3 >>= 31
+ p += lbelow2
+
+ m01 = uint32(m[p+1])
+ lbelow4 >>= 31
+ p += lbelow3
+
+ m02 = uint32(m[p+2])
+ p += lbelow4
+ m0 = 2151
+
+ m03 = uint32(m[p+3])
+ m0 <<= 51
+ m1 = 2215
+
+ m0 += int64(m00)
+ m01 &^= uint32(lbelow2)
+
+ m02 &^= uint32(lbelow3)
+ m01 -= uint32(lbelow2)
+
+ m01 <<= 8
+ m03 &^= uint32(lbelow4)
+
+ m0 += int64(m01)
+ lbelow2 -= lbelow3
+
+ m02 += uint32(lbelow2)
+ lbelow3 -= lbelow4
+
+ m02 <<= 16
+ m03 += uint32(lbelow3)
+
+ m03 <<= 24
+ m0 += int64(m02)
+
+ m0 += int64(m03)
+ lbelow5 = l - 5
+
+ lbelow6 = l - 6
+ lbelow7 = l - 7
+
+ lbelow5 >>= 31
+ lbelow8 = l - 8
+
+ lbelow6 >>= 31
+ p += lbelow5
+
+ m10 = uint32(m[p+4])
+ lbelow7 >>= 31
+ p += lbelow6
+
+ m11 = uint32(m[p+5])
+ lbelow8 >>= 31
+ p += lbelow7
+
+ m12 = uint32(m[p+6])
+ m1 <<= 51
+ p += lbelow8
+
+ m13 = uint32(m[p+7])
+ m10 &^= uint32(lbelow5)
+ lbelow4 -= lbelow5
+
+ m10 += uint32(lbelow4)
+ lbelow5 -= lbelow6
+
+ m11 &^= uint32(lbelow6)
+ m11 += uint32(lbelow5)
+
+ m11 <<= 8
+ m1 += int64(m10)
+
+ m1 += int64(m11)
+ m12 &^= uint32(lbelow7)
+
+ lbelow6 -= lbelow7
+ m13 &^= uint32(lbelow8)
+
+ m12 += uint32(lbelow6)
+ lbelow7 -= lbelow8
+
+ m12 <<= 16
+ m13 += uint32(lbelow7)
+
+ m13 <<= 24
+ m1 += int64(m12)
+
+ m1 += int64(m13)
+ m2 = 2279
+
+ lbelow9 = l - 9
+ m3 = 2343
+
+ lbelow10 = l - 10
+ lbelow11 = l - 11
+
+ lbelow9 >>= 31
+ lbelow12 = l - 12
+
+ lbelow10 >>= 31
+ p += lbelow9
+
+ m20 = uint32(m[p+8])
+ lbelow11 >>= 31
+ p += lbelow10
+
+ m21 = uint32(m[p+9])
+ lbelow12 >>= 31
+ p += lbelow11
+
+ m22 = uint32(m[p+10])
+ m2 <<= 51
+ p += lbelow12
+
+ m23 = uint32(m[p+11])
+ m20 &^= uint32(lbelow9)
+ lbelow8 -= lbelow9
+
+ m20 += uint32(lbelow8)
+ lbelow9 -= lbelow10
+
+ m21 &^= uint32(lbelow10)
+ m21 += uint32(lbelow9)
+
+ m21 <<= 8
+ m2 += int64(m20)
+
+ m2 += int64(m21)
+ m22 &^= uint32(lbelow11)
+
+ lbelow10 -= lbelow11
+ m23 &^= uint32(lbelow12)
+
+ m22 += uint32(lbelow10)
+ lbelow11 -= lbelow12
+
+ m22 <<= 16
+ m23 += uint32(lbelow11)
+
+ m23 <<= 24
+ m2 += int64(m22)
+
+ m3 <<= 51
+ lbelow13 = l - 13
+
+ lbelow13 >>= 31
+ lbelow14 = l - 14
+
+ lbelow14 >>= 31
+ p += lbelow13
+ lbelow15 = l - 15
+
+ m30 = uint32(m[p+12])
+ lbelow15 >>= 31
+ p += lbelow14
+
+ m31 = uint32(m[p+13])
+ p += lbelow15
+ m2 += int64(m23)
+
+ m32 = uint32(m[p+14])
+ m30 &^= uint32(lbelow13)
+ lbelow12 -= lbelow13
+
+ m30 += uint32(lbelow12)
+ lbelow13 -= lbelow14
+
+ m3 += int64(m30)
+ m31 &^= uint32(lbelow14)
+
+ m31 += uint32(lbelow13)
+ m32 &^= uint32(lbelow15)
+
+ m31 <<= 8
+ lbelow14 -= lbelow15
+
+ m3 += int64(m31)
+ m32 += uint32(lbelow14)
+ d0 = m0
+
+ m32 <<= 16
+ m33 = uint64(lbelow15 + 1)
+ d1 = m1
+
+ m33 <<= 24
+ m3 += int64(m32)
+ d2 = m2
+
+ m3 += int64(m33)
+ d3 = m3
+
+ z3 = math.Float64frombits(uint64(d3))
+
+ z2 = math.Float64frombits(uint64(d2))
+
+ z1 = math.Float64frombits(uint64(d1))
+
+ z0 = math.Float64frombits(uint64(d0))
+
+ z3 -= alpha96
+
+ z2 -= alpha64
+
+ z1 -= alpha32
+
+ z0 -= alpha0
+
+ h5 += z3
+
+ h3 += z2
+
+ h1 += z1
+
+ h0 += z0
+
+ y7 = h7 + alpha130
+
+ y6 = h6 + alpha130
+
+ y1 = h1 + alpha32
+
+ y0 = h0 + alpha32
+
+ y7 -= alpha130
+
+ y6 -= alpha130
+
+ y1 -= alpha32
+
+ y0 -= alpha32
+
+ y5 = h5 + alpha96
+
+ y4 = h4 + alpha96
+
+ x7 = h7 - y7
+ y7 *= scale
+
+ x6 = h6 - y6
+ y6 *= scale
+
+ x1 = h1 - y1
+
+ x0 = h0 - y0
+
+ y5 -= alpha96
+
+ y4 -= alpha96
+
+ x1 += y7
+
+ x0 += y6
+
+ x7 += y5
+
+ x6 += y4
+
+ y3 = h3 + alpha64
+
+ y2 = h2 + alpha64
+
+ x0 += x1
+
+ x6 += x7
+
+ y3 -= alpha64
+ r3low = r3low_stack
+
+ y2 -= alpha64
+ r0low = r0low_stack
+
+ x5 = h5 - y5
+ r3lowx0 = r3low * x0
+ r3high = r3high_stack
+
+ x4 = h4 - y4
+ r0lowx6 = r0low * x6
+ r0high = r0high_stack
+
+ x3 = h3 - y3
+ r3highx0 = r3high * x0
+ sr1low = sr1low_stack
+
+ x2 = h2 - y2
+ r0highx6 = r0high * x6
+ sr1high = sr1high_stack
+
+ x5 += y3
+ r0lowx0 = r0low * x0
+ r1low = r1low_stack
+
+ h6 = r3lowx0 + r0lowx6
+ sr1lowx6 = sr1low * x6
+ r1high = r1high_stack
+
+ x4 += y2
+ r0highx0 = r0high * x0
+ sr2low = sr2low_stack
+
+ h7 = r3highx0 + r0highx6
+ sr1highx6 = sr1high * x6
+ sr2high = sr2high_stack
+
+ x3 += y1
+ r1lowx0 = r1low * x0
+ r2low = r2low_stack
+
+ h0 = r0lowx0 + sr1lowx6
+ sr2lowx6 = sr2low * x6
+ r2high = r2high_stack
+
+ x2 += y0
+ r1highx0 = r1high * x0
+ sr3low = sr3low_stack
+
+ h1 = r0highx0 + sr1highx6
+ sr2highx6 = sr2high * x6
+ sr3high = sr3high_stack
+
+ x4 += x5
+ r2lowx0 = r2low * x0
+
+ h2 = r1lowx0 + sr2lowx6
+ sr3lowx6 = sr3low * x6
+
+ x2 += x3
+ r2highx0 = r2high * x0
+
+ h3 = r1highx0 + sr2highx6
+ sr3highx6 = sr3high * x6
+
+ r1highx4 = r1high * x4
+
+ h4 = r2lowx0 + sr3lowx6
+ r1lowx4 = r1low * x4
+
+ r0highx4 = r0high * x4
+
+ h5 = r2highx0 + sr3highx6
+ r0lowx4 = r0low * x4
+
+ h7 += r1highx4
+ sr3highx4 = sr3high * x4
+
+ h6 += r1lowx4
+ sr3lowx4 = sr3low * x4
+
+ h5 += r0highx4
+ sr2highx4 = sr2high * x4
+
+ h4 += r0lowx4
+ sr2lowx4 = sr2low * x4
+
+ h3 += sr3highx4
+ r0lowx2 = r0low * x2
+
+ h2 += sr3lowx4
+ r0highx2 = r0high * x2
+
+ h1 += sr2highx4
+ r1lowx2 = r1low * x2
+
+ h0 += sr2lowx4
+ r1highx2 = r1high * x2
+
+ h2 += r0lowx2
+ r2lowx2 = r2low * x2
+
+ h3 += r0highx2
+ r2highx2 = r2high * x2
+
+ h4 += r1lowx2
+ sr3lowx2 = sr3low * x2
+
+ h5 += r1highx2
+ sr3highx2 = sr3high * x2
+
+ h6 += r2lowx2
+
+ h7 += r2highx2
+
+ h0 += sr3lowx2
+
+ h1 += sr3highx2
+
+nomorebytes:
+
+ y7 = h7 + alpha130
+
+ y0 = h0 + alpha32
+
+ y1 = h1 + alpha32
+
+ y2 = h2 + alpha64
+
+ y7 -= alpha130
+
+ y3 = h3 + alpha64
+
+ y4 = h4 + alpha96
+
+ y5 = h5 + alpha96
+
+ x7 = h7 - y7
+ y7 *= scale
+
+ y0 -= alpha32
+
+ y1 -= alpha32
+
+ y2 -= alpha64
+
+ h6 += x7
+
+ y3 -= alpha64
+
+ y4 -= alpha96
+
+ y5 -= alpha96
+
+ y6 = h6 + alpha130
+
+ x0 = h0 - y0
+
+ x1 = h1 - y1
+
+ x2 = h2 - y2
+
+ y6 -= alpha130
+
+ x0 += y7
+
+ x3 = h3 - y3
+
+ x4 = h4 - y4
+
+ x5 = h5 - y5
+
+ x6 = h6 - y6
+
+ y6 *= scale
+
+ x2 += y0
+
+ x3 += y1
+
+ x4 += y2
+
+ x0 += y6
+
+ x5 += y3
+
+ x6 += y4
+
+ x2 += x3
+
+ x0 += x1
+
+ x4 += x5
+
+ x6 += y5
+
+ x2 += offset1
+ d1 = int64(math.Float64bits(x2))
+
+ x0 += offset0
+ d0 = int64(math.Float64bits(x0))
+
+ x4 += offset2
+ d2 = int64(math.Float64bits(x4))
+
+ x6 += offset3
+ d3 = int64(math.Float64bits(x6))
+
+ f0 = uint64(d0)
+
+ f1 = uint64(d1)
+ bits32 = math.MaxUint64
+
+ f2 = uint64(d2)
+ bits32 >>= 32
+
+ f3 = uint64(d3)
+ f = f0 >> 32
+
+ f0 &= bits32
+ f &= 255
+
+ f1 += f
+ g0 = f0 + 5
+
+ g = g0 >> 32
+ g0 &= bits32
+
+ f = f1 >> 32
+ f1 &= bits32
+
+ f &= 255
+ g1 = f1 + g
+
+ g = g1 >> 32
+ f2 += f
+
+ f = f2 >> 32
+ g1 &= bits32
+
+ f2 &= bits32
+ f &= 255
+
+ f3 += f
+ g2 = f2 + g
+
+ g = g2 >> 32
+ g2 &= bits32
+
+ f4 = f3 >> 32
+ f3 &= bits32
+
+ f4 &= 255
+ g3 = f3 + g
+
+ g = g3 >> 32
+ g3 &= bits32
+
+ g4 = f4 + g
+
+ g4 = g4 - 4
+ s00 = uint32(s[0])
+
+ f = uint64(int64(g4) >> 63)
+ s01 = uint32(s[1])
+
+ f0 &= f
+ g0 &^= f
+ s02 = uint32(s[2])
+
+ f1 &= f
+ f0 |= g0
+ s03 = uint32(s[3])
+
+ g1 &^= f
+ f2 &= f
+ s10 = uint32(s[4])
+
+ f3 &= f
+ g2 &^= f
+ s11 = uint32(s[5])
+
+ g3 &^= f
+ f1 |= g1
+ s12 = uint32(s[6])
+
+ f2 |= g2
+ f3 |= g3
+ s13 = uint32(s[7])
+
+ s01 <<= 8
+ f0 += uint64(s00)
+ s20 = uint32(s[8])
+
+ s02 <<= 16
+ f0 += uint64(s01)
+ s21 = uint32(s[9])
+
+ s03 <<= 24
+ f0 += uint64(s02)
+ s22 = uint32(s[10])
+
+ s11 <<= 8
+ f1 += uint64(s10)
+ s23 = uint32(s[11])
+
+ s12 <<= 16
+ f1 += uint64(s11)
+ s30 = uint32(s[12])
+
+ s13 <<= 24
+ f1 += uint64(s12)
+ s31 = uint32(s[13])
+
+ f0 += uint64(s03)
+ f1 += uint64(s13)
+ s32 = uint32(s[14])
+
+ s21 <<= 8
+ f2 += uint64(s20)
+ s33 = uint32(s[15])
+
+ s22 <<= 16
+ f2 += uint64(s21)
+
+ s23 <<= 24
+ f2 += uint64(s22)
+
+ s31 <<= 8
+ f3 += uint64(s30)
+
+ s32 <<= 16
+ f3 += uint64(s31)
+
+ s33 <<= 24
+ f3 += uint64(s32)
+
+ f2 += uint64(s23)
+ f3 += uint64(s33)
+
+ out[0] = byte(f0)
+ f0 >>= 8
+ out[1] = byte(f0)
+ f0 >>= 8
+ out[2] = byte(f0)
+ f0 >>= 8
+ out[3] = byte(f0)
+ f0 >>= 8
+ f1 += f0
+
+ out[4] = byte(f1)
+ f1 >>= 8
+ out[5] = byte(f1)
+ f1 >>= 8
+ out[6] = byte(f1)
+ f1 >>= 8
+ out[7] = byte(f1)
+ f1 >>= 8
+ f2 += f1
+
+ out[8] = byte(f2)
+ f2 >>= 8
+ out[9] = byte(f2)
+ f2 >>= 8
+ out[10] = byte(f2)
+ f2 >>= 8
+ out[11] = byte(f2)
+ f2 >>= 8
+ f3 += f2
+
+ out[12] = byte(f3)
+ f3 >>= 8
+ out[13] = byte(f3)
+ f3 >>= 8
+ out[14] = byte(f3)
+ f3 >>= 8
+ out[15] = byte(f3)
+}
diff --git a/libgo/go/golang_org/x/net/idna/idna.go b/libgo/go/golang_org/x/net/idna/idna.go
new file mode 100644
index 00000000000..3daa8979e1d
--- /dev/null
+++ b/libgo/go/golang_org/x/net/idna/idna.go
@@ -0,0 +1,68 @@
+// 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 idna implements IDNA2008 (Internationalized Domain Names for
+// Applications), defined in RFC 5890, RFC 5891, RFC 5892, RFC 5893 and
+// RFC 5894.
+package idna // import "golang.org/x/net/idna"
+
+import (
+ "strings"
+ "unicode/utf8"
+)
+
+// TODO(nigeltao): specify when errors occur. For example, is ToASCII(".") or
+// ToASCII("foo\x00") an error? See also http://www.unicode.org/faq/idn.html#11
+
+// acePrefix is the ASCII Compatible Encoding prefix.
+const acePrefix = "xn--"
+
+// ToASCII converts a domain or domain label to its ASCII form. For example,
+// ToASCII("bücher.example.com") is "xn--bcher-kva.example.com", and
+// ToASCII("golang") is "golang".
+func ToASCII(s string) (string, error) {
+ if ascii(s) {
+ return s, nil
+ }
+ labels := strings.Split(s, ".")
+ for i, label := range labels {
+ if !ascii(label) {
+ a, err := encode(acePrefix, label)
+ if err != nil {
+ return "", err
+ }
+ labels[i] = a
+ }
+ }
+ return strings.Join(labels, "."), nil
+}
+
+// ToUnicode converts a domain or domain label to its Unicode form. For example,
+// ToUnicode("xn--bcher-kva.example.com") is "bücher.example.com", and
+// ToUnicode("golang") is "golang".
+func ToUnicode(s string) (string, error) {
+ if !strings.Contains(s, acePrefix) {
+ return s, nil
+ }
+ labels := strings.Split(s, ".")
+ for i, label := range labels {
+ if strings.HasPrefix(label, acePrefix) {
+ u, err := decode(label[len(acePrefix):])
+ if err != nil {
+ return "", err
+ }
+ labels[i] = u
+ }
+ }
+ return strings.Join(labels, "."), nil
+}
+
+func ascii(s string) bool {
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ return false
+ }
+ }
+ return true
+}
diff --git a/libgo/go/golang_org/x/net/idna/idna_test.go b/libgo/go/golang_org/x/net/idna/idna_test.go
new file mode 100644
index 00000000000..b1bc6fa225c
--- /dev/null
+++ b/libgo/go/golang_org/x/net/idna/idna_test.go
@@ -0,0 +1,43 @@
+// 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 idna
+
+import (
+ "testing"
+)
+
+var idnaTestCases = [...]struct {
+ ascii, unicode string
+}{
+ // Labels.
+ {"books", "books"},
+ {"xn--bcher-kva", "bücher"},
+
+ // Domains.
+ {"foo--xn--bar.org", "foo--xn--bar.org"},
+ {"golang.org", "golang.org"},
+ {"example.xn--p1ai", "example.рф"},
+ {"xn--czrw28b.tw", "商業.tw"},
+ {"www.xn--mller-kva.de", "www.müller.de"},
+}
+
+func TestIDNA(t *testing.T) {
+ for _, tc := range idnaTestCases {
+ if a, err := ToASCII(tc.unicode); err != nil {
+ t.Errorf("ToASCII(%q): %v", tc.unicode, err)
+ } else if a != tc.ascii {
+ t.Errorf("ToASCII(%q): got %q, want %q", tc.unicode, a, tc.ascii)
+ }
+
+ if u, err := ToUnicode(tc.ascii); err != nil {
+ t.Errorf("ToUnicode(%q): %v", tc.ascii, err)
+ } else if u != tc.unicode {
+ t.Errorf("ToUnicode(%q): got %q, want %q", tc.ascii, u, tc.unicode)
+ }
+ }
+}
+
+// TODO(nigeltao): test errors, once we've specified when ToASCII and ToUnicode
+// return errors.
diff --git a/libgo/go/golang_org/x/net/idna/punycode.go b/libgo/go/golang_org/x/net/idna/punycode.go
new file mode 100644
index 00000000000..92e733f6a7b
--- /dev/null
+++ b/libgo/go/golang_org/x/net/idna/punycode.go
@@ -0,0 +1,200 @@
+// 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 idna
+
+// This file implements the Punycode algorithm from RFC 3492.
+
+import (
+ "fmt"
+ "math"
+ "strings"
+ "unicode/utf8"
+)
+
+// These parameter values are specified in section 5.
+//
+// All computation is done with int32s, so that overflow behavior is identical
+// regardless of whether int is 32-bit or 64-bit.
+const (
+ base int32 = 36
+ damp int32 = 700
+ initialBias int32 = 72
+ initialN int32 = 128
+ skew int32 = 38
+ tmax int32 = 26
+ tmin int32 = 1
+)
+
+// decode decodes a string as specified in section 6.2.
+func decode(encoded string) (string, error) {
+ if encoded == "" {
+ return "", nil
+ }
+ pos := 1 + strings.LastIndex(encoded, "-")
+ if pos == 1 {
+ return "", fmt.Errorf("idna: invalid label %q", encoded)
+ }
+ if pos == len(encoded) {
+ return encoded[:len(encoded)-1], nil
+ }
+ output := make([]rune, 0, len(encoded))
+ if pos != 0 {
+ for _, r := range encoded[:pos-1] {
+ output = append(output, r)
+ }
+ }
+ i, n, bias := int32(0), initialN, initialBias
+ for pos < len(encoded) {
+ oldI, w := i, int32(1)
+ for k := base; ; k += base {
+ if pos == len(encoded) {
+ return "", fmt.Errorf("idna: invalid label %q", encoded)
+ }
+ digit, ok := decodeDigit(encoded[pos])
+ if !ok {
+ return "", fmt.Errorf("idna: invalid label %q", encoded)
+ }
+ pos++
+ i += digit * w
+ if i < 0 {
+ return "", fmt.Errorf("idna: invalid label %q", encoded)
+ }
+ t := k - bias
+ if t < tmin {
+ t = tmin
+ } else if t > tmax {
+ t = tmax
+ }
+ if digit < t {
+ break
+ }
+ w *= base - t
+ if w >= math.MaxInt32/base {
+ return "", fmt.Errorf("idna: invalid label %q", encoded)
+ }
+ }
+ x := int32(len(output) + 1)
+ bias = adapt(i-oldI, x, oldI == 0)
+ n += i / x
+ i %= x
+ if n > utf8.MaxRune || len(output) >= 1024 {
+ return "", fmt.Errorf("idna: invalid label %q", encoded)
+ }
+ output = append(output, 0)
+ copy(output[i+1:], output[i:])
+ output[i] = n
+ i++
+ }
+ return string(output), nil
+}
+
+// encode encodes a string as specified in section 6.3 and prepends prefix to
+// the result.
+//
+// The "while h < length(input)" line in the specification becomes "for
+// remaining != 0" in the Go code, because len(s) in Go is in bytes, not runes.
+func encode(prefix, s string) (string, error) {
+ output := make([]byte, len(prefix), len(prefix)+1+2*len(s))
+ copy(output, prefix)
+ delta, n, bias := int32(0), initialN, initialBias
+ b, remaining := int32(0), int32(0)
+ for _, r := range s {
+ if r < 0x80 {
+ b++
+ output = append(output, byte(r))
+ } else {
+ remaining++
+ }
+ }
+ h := b
+ if b > 0 {
+ output = append(output, '-')
+ }
+ for remaining != 0 {
+ m := int32(0x7fffffff)
+ for _, r := range s {
+ if m > r && r >= n {
+ m = r
+ }
+ }
+ delta += (m - n) * (h + 1)
+ if delta < 0 {
+ return "", fmt.Errorf("idna: invalid label %q", s)
+ }
+ n = m
+ for _, r := range s {
+ if r < n {
+ delta++
+ if delta < 0 {
+ return "", fmt.Errorf("idna: invalid label %q", s)
+ }
+ continue
+ }
+ if r > n {
+ continue
+ }
+ q := delta
+ for k := base; ; k += base {
+ t := k - bias
+ if t < tmin {
+ t = tmin
+ } else if t > tmax {
+ t = tmax
+ }
+ if q < t {
+ break
+ }
+ output = append(output, encodeDigit(t+(q-t)%(base-t)))
+ q = (q - t) / (base - t)
+ }
+ output = append(output, encodeDigit(q))
+ bias = adapt(delta, h+1, h == b)
+ delta = 0
+ h++
+ remaining--
+ }
+ delta++
+ n++
+ }
+ return string(output), nil
+}
+
+func decodeDigit(x byte) (digit int32, ok bool) {
+ switch {
+ case '0' <= x && x <= '9':
+ return int32(x - ('0' - 26)), true
+ case 'A' <= x && x <= 'Z':
+ return int32(x - 'A'), true
+ case 'a' <= x && x <= 'z':
+ return int32(x - 'a'), true
+ }
+ return 0, false
+}
+
+func encodeDigit(digit int32) byte {
+ switch {
+ case 0 <= digit && digit < 26:
+ return byte(digit + 'a')
+ case 26 <= digit && digit < 36:
+ return byte(digit + ('0' - 26))
+ }
+ panic("idna: internal error in punycode encoding")
+}
+
+// adapt is the bias adaptation function specified in section 6.1.
+func adapt(delta, numPoints int32, firstTime bool) int32 {
+ if firstTime {
+ delta /= damp
+ } else {
+ delta /= 2
+ }
+ delta += delta / numPoints
+ k := int32(0)
+ for delta > ((base-tmin)*tmax)/2 {
+ delta /= base - tmin
+ k += base
+ }
+ return k + (base-tmin+1)*delta/(delta+skew)
+}
diff --git a/libgo/go/golang_org/x/net/idna/punycode_test.go b/libgo/go/golang_org/x/net/idna/punycode_test.go
new file mode 100644
index 00000000000..bfec81decd0
--- /dev/null
+++ b/libgo/go/golang_org/x/net/idna/punycode_test.go
@@ -0,0 +1,198 @@
+// 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 idna
+
+import (
+ "strings"
+ "testing"
+)
+
+var punycodeTestCases = [...]struct {
+ s, encoded string
+}{
+ {"", ""},
+ {"-", "--"},
+ {"-a", "-a-"},
+ {"-a-", "-a--"},
+ {"a", "a-"},
+ {"a-", "a--"},
+ {"a-b", "a-b-"},
+ {"books", "books-"},
+ {"bücher", "bcher-kva"},
+ {"Hello世界", "Hello-ck1hg65u"},
+ {"ü", "tda"},
+ {"üý", "tdac"},
+
+ // The test cases below come from RFC 3492 section 7.1 with Errata 3026.
+ {
+ // (A) Arabic (Egyptian).
+ "\u0644\u064A\u0647\u0645\u0627\u0628\u062A\u0643\u0644" +
+ "\u0645\u0648\u0634\u0639\u0631\u0628\u064A\u061F",
+ "egbpdaj6bu4bxfgehfvwxn",
+ },
+ {
+ // (B) Chinese (simplified).
+ "\u4ED6\u4EEC\u4E3A\u4EC0\u4E48\u4E0D\u8BF4\u4E2D\u6587",
+ "ihqwcrb4cv8a8dqg056pqjye",
+ },
+ {
+ // (C) Chinese (traditional).
+ "\u4ED6\u5011\u7232\u4EC0\u9EBD\u4E0D\u8AAA\u4E2D\u6587",
+ "ihqwctvzc91f659drss3x8bo0yb",
+ },
+ {
+ // (D) Czech.
+ "\u0050\u0072\u006F\u010D\u0070\u0072\u006F\u0073\u0074" +
+ "\u011B\u006E\u0065\u006D\u006C\u0075\u0076\u00ED\u010D" +
+ "\u0065\u0073\u006B\u0079",
+ "Proprostnemluvesky-uyb24dma41a",
+ },
+ {
+ // (E) Hebrew.
+ "\u05DC\u05DE\u05D4\u05D4\u05DD\u05E4\u05E9\u05D5\u05D8" +
+ "\u05DC\u05D0\u05DE\u05D3\u05D1\u05E8\u05D9\u05DD\u05E2" +
+ "\u05D1\u05E8\u05D9\u05EA",
+ "4dbcagdahymbxekheh6e0a7fei0b",
+ },
+ {
+ // (F) Hindi (Devanagari).
+ "\u092F\u0939\u0932\u094B\u0917\u0939\u093F\u0928\u094D" +
+ "\u0926\u0940\u0915\u094D\u092F\u094B\u0902\u0928\u0939" +
+ "\u0940\u0902\u092C\u094B\u0932\u0938\u0915\u0924\u0947" +
+ "\u0939\u0948\u0902",
+ "i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd",
+ },
+ {
+ // (G) Japanese (kanji and hiragana).
+ "\u306A\u305C\u307F\u3093\u306A\u65E5\u672C\u8A9E\u3092" +
+ "\u8A71\u3057\u3066\u304F\u308C\u306A\u3044\u306E\u304B",
+ "n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa",
+ },
+ {
+ // (H) Korean (Hangul syllables).
+ "\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774" +
+ "\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74" +
+ "\uC5BC\uB9C8\uB098\uC88B\uC744\uAE4C",
+ "989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5j" +
+ "psd879ccm6fea98c",
+ },
+ {
+ // (I) Russian (Cyrillic).
+ "\u043F\u043E\u0447\u0435\u043C\u0443\u0436\u0435\u043E" +
+ "\u043D\u0438\u043D\u0435\u0433\u043E\u0432\u043E\u0440" +
+ "\u044F\u0442\u043F\u043E\u0440\u0443\u0441\u0441\u043A" +
+ "\u0438",
+ "b1abfaaepdrnnbgefbadotcwatmq2g4l",
+ },
+ {
+ // (J) Spanish.
+ "\u0050\u006F\u0072\u0071\u0075\u00E9\u006E\u006F\u0070" +
+ "\u0075\u0065\u0064\u0065\u006E\u0073\u0069\u006D\u0070" +
+ "\u006C\u0065\u006D\u0065\u006E\u0074\u0065\u0068\u0061" +
+ "\u0062\u006C\u0061\u0072\u0065\u006E\u0045\u0073\u0070" +
+ "\u0061\u00F1\u006F\u006C",
+ "PorqunopuedensimplementehablarenEspaol-fmd56a",
+ },
+ {
+ // (K) Vietnamese.
+ "\u0054\u1EA1\u0069\u0073\u0061\u006F\u0068\u1ECD\u006B" +
+ "\u0068\u00F4\u006E\u0067\u0074\u0068\u1EC3\u0063\u0068" +
+ "\u1EC9\u006E\u00F3\u0069\u0074\u0069\u1EBF\u006E\u0067" +
+ "\u0056\u0069\u1EC7\u0074",
+ "TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g",
+ },
+ {
+ // (L) 3<nen>B<gumi><kinpachi><sensei>.
+ "\u0033\u5E74\u0042\u7D44\u91D1\u516B\u5148\u751F",
+ "3B-ww4c5e180e575a65lsy2b",
+ },
+ {
+ // (M) <amuro><namie>-with-SUPER-MONKEYS.
+ "\u5B89\u5BA4\u5948\u7F8E\u6075\u002D\u0077\u0069\u0074" +
+ "\u0068\u002D\u0053\u0055\u0050\u0045\u0052\u002D\u004D" +
+ "\u004F\u004E\u004B\u0045\u0059\u0053",
+ "-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n",
+ },
+ {
+ // (N) Hello-Another-Way-<sorezore><no><basho>.
+ "\u0048\u0065\u006C\u006C\u006F\u002D\u0041\u006E\u006F" +
+ "\u0074\u0068\u0065\u0072\u002D\u0057\u0061\u0079\u002D" +
+ "\u305D\u308C\u305E\u308C\u306E\u5834\u6240",
+ "Hello-Another-Way--fc4qua05auwb3674vfr0b",
+ },
+ {
+ // (O) <hitotsu><yane><no><shita>2.
+ "\u3072\u3068\u3064\u5C4B\u6839\u306E\u4E0B\u0032",
+ "2-u9tlzr9756bt3uc0v",
+ },
+ {
+ // (P) Maji<de>Koi<suru>5<byou><mae>
+ "\u004D\u0061\u006A\u0069\u3067\u004B\u006F\u0069\u3059" +
+ "\u308B\u0035\u79D2\u524D",
+ "MajiKoi5-783gue6qz075azm5e",
+ },
+ {
+ // (Q) <pafii>de<runba>
+ "\u30D1\u30D5\u30A3\u30FC\u0064\u0065\u30EB\u30F3\u30D0",
+ "de-jg4avhby1noc0d",
+ },
+ {
+ // (R) <sono><supiido><de>
+ "\u305D\u306E\u30B9\u30D4\u30FC\u30C9\u3067",
+ "d9juau41awczczp",
+ },
+ {
+ // (S) -> $1.00 <-
+ "\u002D\u003E\u0020\u0024\u0031\u002E\u0030\u0030\u0020" +
+ "\u003C\u002D",
+ "-> $1.00 <--",
+ },
+}
+
+func TestPunycode(t *testing.T) {
+ for _, tc := range punycodeTestCases {
+ if got, err := decode(tc.encoded); err != nil {
+ t.Errorf("decode(%q): %v", tc.encoded, err)
+ } else if got != tc.s {
+ t.Errorf("decode(%q): got %q, want %q", tc.encoded, got, tc.s)
+ }
+
+ if got, err := encode("", tc.s); err != nil {
+ t.Errorf(`encode("", %q): %v`, tc.s, err)
+ } else if got != tc.encoded {
+ t.Errorf(`encode("", %q): got %q, want %q`, tc.s, got, tc.encoded)
+ }
+ }
+}
+
+var punycodeErrorTestCases = [...]string{
+ "decode -", // A sole '-' is invalid.
+ "decode foo\x00bar", // '\x00' is not in [0-9A-Za-z].
+ "decode foo#bar", // '#' is not in [0-9A-Za-z].
+ "decode foo\u00A3bar", // '\u00A3' is not in [0-9A-Za-z].
+ "decode 9", // "9a" decodes to codepoint \u00A3; "9" is truncated.
+ "decode 99999a", // "99999a" decodes to codepoint \U0048A3C1, which is > \U0010FFFF.
+ "decode 9999999999a", // "9999999999a" overflows the int32 calculation.
+
+ "encode " + strings.Repeat("x", 65536) + "\uff00", // int32 overflow.
+}
+
+func TestPunycodeErrors(t *testing.T) {
+ for _, tc := range punycodeErrorTestCases {
+ var err error
+ switch {
+ case strings.HasPrefix(tc, "decode "):
+ _, err = decode(tc[7:])
+ case strings.HasPrefix(tc, "encode "):
+ _, err = encode("", tc[7:])
+ }
+ if err == nil {
+ if len(tc) > 256 {
+ tc = tc[:100] + "..." + tc[len(tc)-100:]
+ }
+ t.Errorf("no error for %s", tc)
+ }
+ }
+}
diff --git a/libgo/go/golang_org/x/net/lex/httplex/httplex.go b/libgo/go/golang_org/x/net/lex/httplex/httplex.go
index bd0ec24f444..b6493f045a2 100644
--- a/libgo/go/golang_org/x/net/lex/httplex/httplex.go
+++ b/libgo/go/golang_org/x/net/lex/httplex/httplex.go
@@ -10,8 +10,11 @@
package httplex
import (
+ "net"
"strings"
"unicode/utf8"
+
+ "golang_org/x/net/idna"
)
var isTokenTable = [127]bool{
@@ -310,3 +313,39 @@ func ValidHeaderFieldValue(v string) bool {
}
return true
}
+
+func isASCII(s string) bool {
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ return false
+ }
+ }
+ return true
+}
+
+// PunycodeHostPort returns the IDNA Punycode version
+// of the provided "host" or "host:port" string.
+func PunycodeHostPort(v string) (string, error) {
+ if isASCII(v) {
+ return v, nil
+ }
+
+ host, port, err := net.SplitHostPort(v)
+ if err != nil {
+ // The input 'v' argument was just a "host" argument,
+ // without a port. This error should not be returned
+ // to the caller.
+ host = v
+ port = ""
+ }
+ host, err = idna.ToASCII(host)
+ if err != nil {
+ // Non-UTF-8? Not representable in Punycode, in any
+ // case.
+ return "", err
+ }
+ if port == "" {
+ return host, nil
+ }
+ return net.JoinHostPort(host, port), nil
+}
diff --git a/libgo/go/golang_org/x/net/lex/httplex/httplex_test.go b/libgo/go/golang_org/x/net/lex/httplex/httplex_test.go
index c4ace1991b3..f47adc939fe 100644
--- a/libgo/go/golang_org/x/net/lex/httplex/httplex_test.go
+++ b/libgo/go/golang_org/x/net/lex/httplex/httplex_test.go
@@ -99,3 +99,21 @@ func TestHeaderValuesContainsToken(t *testing.T) {
}
}
}
+
+func TestPunycodeHostPort(t *testing.T) {
+ tests := []struct {
+ in, want string
+ }{
+ {"www.google.com", "www.google.com"},
+ {"гофер.рф", "xn--c1ae0ajs.xn--p1ai"},
+ {"bücher.de", "xn--bcher-kva.de"},
+ {"bücher.de:8080", "xn--bcher-kva.de:8080"},
+ {"[1::6]:8080", "[1::6]:8080"},
+ }
+ for _, tt := range tests {
+ got, err := PunycodeHostPort(tt.in)
+ if tt.want != got || err != nil {
+ t.Errorf("PunycodeHostPort(%q) = %q, %v, want %q, nil", tt.in, got, err, tt.want)
+ }
+ }
+}
diff --git a/libgo/go/golang_org/x/net/lif/address.go b/libgo/go/golang_org/x/net/lif/address.go
new file mode 100644
index 00000000000..f9b34aed03e
--- /dev/null
+++ b/libgo/go/golang_org/x/net/lif/address.go
@@ -0,0 +1,105 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build solaris
+
+package lif
+
+import (
+ "errors"
+ "unsafe"
+)
+
+// An Addr represents an address associated with packet routing.
+type Addr interface {
+ // Family returns an address family.
+ Family() int
+}
+
+// An Inet4Addr represents an internet address for IPv4.
+type Inet4Addr struct {
+ IP [4]byte // IP address
+ PrefixLen int // address prefix length
+}
+
+// Family implements the Family method of Addr interface.
+func (a *Inet4Addr) Family() int { return sysAF_INET }
+
+// An Inet6Addr represents an internet address for IPv6.
+type Inet6Addr struct {
+ IP [16]byte // IP address
+ PrefixLen int // address prefix length
+ ZoneID int // zone identifier
+}
+
+// Family implements the Family method of Addr interface.
+func (a *Inet6Addr) Family() int { return sysAF_INET6 }
+
+// Addrs returns a list of interface addresses.
+//
+// The provided af must be an address family and name must be a data
+// link name. The zero value of af or name means a wildcard.
+func Addrs(af int, name string) ([]Addr, error) {
+ eps, err := newEndpoints(af)
+ if len(eps) == 0 {
+ return nil, err
+ }
+ defer func() {
+ for _, ep := range eps {
+ ep.close()
+ }
+ }()
+ lls, err := links(eps, name)
+ if len(lls) == 0 {
+ return nil, err
+ }
+ var as []Addr
+ for _, ll := range lls {
+ var lifr lifreq
+ for i := 0; i < len(ll.Name); i++ {
+ lifr.Name[i] = int8(ll.Name[i])
+ }
+ for _, ep := range eps {
+ ioc := int64(sysSIOCGLIFADDR)
+ err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifr))
+ if err != nil {
+ continue
+ }
+ sa := (*sockaddrStorage)(unsafe.Pointer(&lifr.Lifru[0]))
+ l := int(littleEndian.Uint32(lifr.Lifru1[:4]))
+ if l == 0 {
+ continue
+ }
+ switch sa.Family {
+ case sysAF_INET:
+ a := &Inet4Addr{PrefixLen: l}
+ copy(a.IP[:], lifr.Lifru[4:8])
+ as = append(as, a)
+ case sysAF_INET6:
+ a := &Inet6Addr{PrefixLen: l, ZoneID: int(littleEndian.Uint32(lifr.Lifru[24:28]))}
+ copy(a.IP[:], lifr.Lifru[8:24])
+ as = append(as, a)
+ }
+ }
+ }
+ return as, nil
+}
+
+func parseLinkAddr(b []byte) ([]byte, error) {
+ nlen, alen, slen := int(b[1]), int(b[2]), int(b[3])
+ l := 4 + nlen + alen + slen
+ if len(b) < l {
+ return nil, errors.New("invalid address")
+ }
+ b = b[4:]
+ var addr []byte
+ if nlen > 0 {
+ b = b[nlen:]
+ }
+ if alen > 0 {
+ addr = make([]byte, alen)
+ copy(addr, b[:alen])
+ }
+ return addr, nil
+}
diff --git a/libgo/go/golang_org/x/net/lif/address_test.go b/libgo/go/golang_org/x/net/lif/address_test.go
new file mode 100644
index 00000000000..f62ed934713
--- /dev/null
+++ b/libgo/go/golang_org/x/net/lif/address_test.go
@@ -0,0 +1,121 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build solaris
+
+package lif
+
+import (
+ "fmt"
+ "testing"
+)
+
+type addrFamily int
+
+func (af addrFamily) String() string {
+ switch af {
+ case sysAF_UNSPEC:
+ return "unspec"
+ case sysAF_INET:
+ return "inet4"
+ case sysAF_INET6:
+ return "inet6"
+ default:
+ return fmt.Sprintf("%d", af)
+ }
+}
+
+const hexDigit = "0123456789abcdef"
+
+type llAddr []byte
+
+func (a llAddr) String() string {
+ if len(a) == 0 {
+ return ""
+ }
+ buf := make([]byte, 0, len(a)*3-1)
+ for i, b := range a {
+ if i > 0 {
+ buf = append(buf, ':')
+ }
+ buf = append(buf, hexDigit[b>>4])
+ buf = append(buf, hexDigit[b&0xF])
+ }
+ return string(buf)
+}
+
+type ipAddr []byte
+
+func (a ipAddr) String() string {
+ if len(a) == 0 {
+ return "<nil>"
+ }
+ if len(a) == 4 {
+ return fmt.Sprintf("%d.%d.%d.%d", a[0], a[1], a[2], a[3])
+ }
+ if len(a) == 16 {
+ return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15])
+ }
+ s := make([]byte, len(a)*2)
+ for i, tn := range a {
+ s[i*2], s[i*2+1] = hexDigit[tn>>4], hexDigit[tn&0xf]
+ }
+ return string(s)
+}
+
+func (a *Inet4Addr) String() string {
+ return fmt.Sprintf("(%s %s %d)", addrFamily(a.Family()), ipAddr(a.IP[:]), a.PrefixLen)
+}
+
+func (a *Inet6Addr) String() string {
+ return fmt.Sprintf("(%s %s %d %d)", addrFamily(a.Family()), ipAddr(a.IP[:]), a.PrefixLen, a.ZoneID)
+}
+
+type addrPack struct {
+ af int
+ as []Addr
+}
+
+func addrPacks() ([]addrPack, error) {
+ var aps []addrPack
+ for _, af := range [...]int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
+ as, err := Addrs(af, "")
+ if err != nil {
+ return nil, err
+ }
+ aps = append(aps, addrPack{af: af, as: as})
+ }
+ return aps, nil
+}
+
+func TestAddrs(t *testing.T) {
+ aps, err := addrPacks()
+ if len(aps) == 0 && err != nil {
+ t.Fatal(err)
+ }
+ lps, err := linkPacks()
+ if len(lps) == 0 && err != nil {
+ t.Fatal(err)
+ }
+ for _, lp := range lps {
+ n := 0
+ for _, ll := range lp.lls {
+ as, err := Addrs(lp.af, ll.Name)
+ if err != nil {
+ t.Fatal(lp.af, ll.Name, err)
+ }
+ t.Logf("af=%s name=%s %v", addrFamily(lp.af), ll.Name, as)
+ n += len(as)
+ }
+ for _, ap := range aps {
+ if ap.af != lp.af {
+ continue
+ }
+ if n != len(ap.as) {
+ t.Errorf("af=%s got %d; want %d", addrFamily(lp.af), n, len(ap.as))
+ continue
+ }
+ }
+ }
+}
diff --git a/libgo/go/golang_org/x/net/lif/binary.go b/libgo/go/golang_org/x/net/lif/binary.go
new file mode 100644
index 00000000000..aade9eafa25
--- /dev/null
+++ b/libgo/go/golang_org/x/net/lif/binary.go
@@ -0,0 +1,68 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build solaris
+
+package lif
+
+// This file contains duplicates of encoding/binary package.
+//
+// This package is supposed to be used by the net package of standard
+// library. Therefore the package set used in the package must be the
+// same as net package.
+
+var littleEndian binaryLittleEndian
+
+type binaryByteOrder interface {
+ Uint16([]byte) uint16
+ Uint32([]byte) uint32
+ Uint64([]byte) uint64
+ PutUint16([]byte, uint16)
+ PutUint32([]byte, uint32)
+ PutUint64([]byte, uint64)
+}
+
+type binaryLittleEndian struct{}
+
+func (binaryLittleEndian) Uint16(b []byte) uint16 {
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint16(b[0]) | uint16(b[1])<<8
+}
+
+func (binaryLittleEndian) PutUint16(b []byte, v uint16) {
+ _ = b[1] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+}
+
+func (binaryLittleEndian) Uint32(b []byte) uint32 {
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+}
+
+func (binaryLittleEndian) PutUint32(b []byte, v uint32) {
+ _ = b[3] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ b[2] = byte(v >> 16)
+ b[3] = byte(v >> 24)
+}
+
+func (binaryLittleEndian) Uint64(b []byte) uint64 {
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
+ uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+}
+
+func (binaryLittleEndian) PutUint64(b []byte, v uint64) {
+ _ = b[7] // early bounds check to guarantee safety of writes below
+ b[0] = byte(v)
+ b[1] = byte(v >> 8)
+ b[2] = byte(v >> 16)
+ b[3] = byte(v >> 24)
+ b[4] = byte(v >> 32)
+ b[5] = byte(v >> 40)
+ b[6] = byte(v >> 48)
+ b[7] = byte(v >> 56)
+}
diff --git a/libgo/go/golang_org/x/net/lif/defs_solaris.go b/libgo/go/golang_org/x/net/lif/defs_solaris.go
new file mode 100644
index 00000000000..8b84ba5e33f
--- /dev/null
+++ b/libgo/go/golang_org/x/net/lif/defs_solaris.go
@@ -0,0 +1,90 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// +godefs map struct_in_addr [4]byte /* in_addr */
+// +godefs map struct_in6_addr [16]byte /* in6_addr */
+
+package lif
+
+/*
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+*/
+import "C"
+
+const (
+ sysAF_UNSPEC = C.AF_UNSPEC
+ sysAF_INET = C.AF_INET
+ sysAF_INET6 = C.AF_INET6
+
+ sysSOCK_DGRAM = C.SOCK_DGRAM
+)
+
+type sockaddrStorage C.struct_sockaddr_storage
+
+const (
+ sysLIFC_NOXMIT = C.LIFC_NOXMIT
+ sysLIFC_EXTERNAL_SOURCE = C.LIFC_EXTERNAL_SOURCE
+ sysLIFC_TEMPORARY = C.LIFC_TEMPORARY
+ sysLIFC_ALLZONES = C.LIFC_ALLZONES
+ sysLIFC_UNDER_IPMP = C.LIFC_UNDER_IPMP
+ sysLIFC_ENABLED = C.LIFC_ENABLED
+
+ sysSIOCGLIFADDR = C.SIOCGLIFADDR
+ sysSIOCGLIFDSTADDR = C.SIOCGLIFDSTADDR
+ sysSIOCGLIFFLAGS = C.SIOCGLIFFLAGS
+ sysSIOCGLIFMTU = C.SIOCGLIFMTU
+ sysSIOCGLIFNETMASK = C.SIOCGLIFNETMASK
+ sysSIOCGLIFMETRIC = C.SIOCGLIFMETRIC
+ sysSIOCGLIFNUM = C.SIOCGLIFNUM
+ sysSIOCGLIFINDEX = C.SIOCGLIFINDEX
+ sysSIOCGLIFSUBNET = C.SIOCGLIFSUBNET
+ sysSIOCGLIFLNKINFO = C.SIOCGLIFLNKINFO
+ sysSIOCGLIFCONF = C.SIOCGLIFCONF
+ sysSIOCGLIFHWADDR = C.SIOCGLIFHWADDR
+)
+
+const (
+ sysIFF_UP = C.IFF_UP
+ sysIFF_BROADCAST = C.IFF_BROADCAST
+ sysIFF_DEBUG = C.IFF_DEBUG
+ sysIFF_LOOPBACK = C.IFF_LOOPBACK
+ sysIFF_POINTOPOINT = C.IFF_POINTOPOINT
+ sysIFF_NOTRAILERS = C.IFF_NOTRAILERS
+ sysIFF_RUNNING = C.IFF_RUNNING
+ sysIFF_NOARP = C.IFF_NOARP
+ sysIFF_PROMISC = C.IFF_PROMISC
+ sysIFF_ALLMULTI = C.IFF_ALLMULTI
+ sysIFF_INTELLIGENT = C.IFF_INTELLIGENT
+ sysIFF_MULTICAST = C.IFF_MULTICAST
+ sysIFF_MULTI_BCAST = C.IFF_MULTI_BCAST
+ sysIFF_UNNUMBERED = C.IFF_UNNUMBERED
+ sysIFF_PRIVATE = C.IFF_PRIVATE
+)
+
+const (
+ sizeofLifnum = C.sizeof_struct_lifnum
+ sizeofLifreq = C.sizeof_struct_lifreq
+ sizeofLifconf = C.sizeof_struct_lifconf
+ sizeofLifIfinfoReq = C.sizeof_struct_lif_ifinfo_req
+)
+
+type sysLifnum C.struct_lifnum
+
+type lifreq C.struct_lifreq
+
+type lifconf C.struct_lifconf
+
+type lifIfinfoReq C.struct_lif_ifinfo_req
+
+const (
+ sysIFT_IPV4 = C.IFT_IPV4
+ sysIFT_IPV6 = C.IFT_IPV6
+ sysIFT_6TO4 = C.IFT_6TO4
+)
diff --git a/libgo/go/golang_org/x/net/lif/lif.go b/libgo/go/golang_org/x/net/lif/lif.go
new file mode 100644
index 00000000000..6e81f81f1c2
--- /dev/null
+++ b/libgo/go/golang_org/x/net/lif/lif.go
@@ -0,0 +1,43 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build solaris
+
+// Package lif provides basic functions for the manipulation of
+// logical network interfaces and interface addresses on Solaris.
+//
+// The package supports Solaris 11 or above.
+package lif
+
+import "syscall"
+
+type endpoint struct {
+ af int
+ s uintptr
+}
+
+func (ep *endpoint) close() error {
+ return syscall.Close(int(ep.s))
+}
+
+func newEndpoints(af int) ([]endpoint, error) {
+ var lastErr error
+ var eps []endpoint
+ afs := []int{sysAF_INET, sysAF_INET6}
+ if af != sysAF_UNSPEC {
+ afs = []int{af}
+ }
+ for _, af := range afs {
+ s, err := syscall.Socket(af, sysSOCK_DGRAM, 0)
+ if err != nil {
+ lastErr = err
+ continue
+ }
+ eps = append(eps, endpoint{af: af, s: uintptr(s)})
+ }
+ if len(eps) == 0 {
+ return nil, lastErr
+ }
+ return eps, nil
+}
diff --git a/libgo/go/golang_org/x/net/lif/link.go b/libgo/go/golang_org/x/net/lif/link.go
new file mode 100644
index 00000000000..76fa6c68756
--- /dev/null
+++ b/libgo/go/golang_org/x/net/lif/link.go
@@ -0,0 +1,122 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build solaris
+
+package lif
+
+import "unsafe"
+
+// A Link represents logical data link information.
+//
+// It also represents base information for logical network interface.
+// On Solaris, each logical network interface represents network layer
+// adjacency information and the interface has a only single network
+// address or address pair for tunneling. It's usual that multiple
+// logical network interfaces share the same logical data link.
+type Link struct {
+ Name string // name, equivalent to IP interface name
+ Index int // index, equivalent to IP interface index
+ Type int // type
+ Flags int // flags
+ MTU int // maximum transmission unit, basically link MTU but may differ between IP address families
+ Addr []byte // address
+}
+
+func (ll *Link) fetch(s uintptr) {
+ var lifr lifreq
+ for i := 0; i < len(ll.Name); i++ {
+ lifr.Name[i] = int8(ll.Name[i])
+ }
+ ioc := int64(sysSIOCGLIFINDEX)
+ if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
+ ll.Index = int(littleEndian.Uint32(lifr.Lifru[:4]))
+ }
+ ioc = int64(sysSIOCGLIFFLAGS)
+ if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
+ ll.Flags = int(littleEndian.Uint64(lifr.Lifru[:8]))
+ }
+ ioc = int64(sysSIOCGLIFMTU)
+ if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
+ ll.MTU = int(littleEndian.Uint32(lifr.Lifru[:4]))
+ }
+ switch ll.Type {
+ case sysIFT_IPV4, sysIFT_IPV6, sysIFT_6TO4:
+ default:
+ ioc = int64(sysSIOCGLIFHWADDR)
+ if err := ioctl(s, uintptr(ioc), unsafe.Pointer(&lifr)); err == nil {
+ ll.Addr, _ = parseLinkAddr(lifr.Lifru[4:])
+ }
+ }
+}
+
+// Links returns a list of logical data links.
+//
+// The provided af must be an address family and name must be a data
+// link name. The zero value of af or name means a wildcard.
+func Links(af int, name string) ([]Link, error) {
+ eps, err := newEndpoints(af)
+ if len(eps) == 0 {
+ return nil, err
+ }
+ defer func() {
+ for _, ep := range eps {
+ ep.close()
+ }
+ }()
+ return links(eps, name)
+}
+
+func links(eps []endpoint, name string) ([]Link, error) {
+ var lls []Link
+ lifn := sysLifnum{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
+ lifc := lifconf{Flags: sysLIFC_NOXMIT | sysLIFC_TEMPORARY | sysLIFC_ALLZONES | sysLIFC_UNDER_IPMP}
+ for _, ep := range eps {
+ lifn.Family = uint16(ep.af)
+ ioc := int64(sysSIOCGLIFNUM)
+ if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifn)); err != nil {
+ continue
+ }
+ if lifn.Count == 0 {
+ continue
+ }
+ b := make([]byte, lifn.Count*sizeofLifreq)
+ lifc.Family = uint16(ep.af)
+ lifc.Len = lifn.Count * sizeofLifreq
+ littleEndian.PutUint64(lifc.Lifcu[:], uint64(uintptr(unsafe.Pointer(&b[0]))))
+ ioc = int64(sysSIOCGLIFCONF)
+ if err := ioctl(ep.s, uintptr(ioc), unsafe.Pointer(&lifc)); err != nil {
+ continue
+ }
+ nb := make([]byte, 32) // see LIFNAMSIZ in net/if.h
+ for i := 0; i < int(lifn.Count); i++ {
+ lifr := (*lifreq)(unsafe.Pointer(&b[i*sizeofLifreq]))
+ for i := 0; i < 32; i++ {
+ if lifr.Name[i] == 0 {
+ nb = nb[:i]
+ break
+ }
+ nb[i] = byte(lifr.Name[i])
+ }
+ llname := string(nb)
+ nb = nb[:32]
+ if isDupLink(lls, llname) || name != "" && name != llname {
+ continue
+ }
+ ll := Link{Name: llname, Type: int(lifr.Type)}
+ ll.fetch(ep.s)
+ lls = append(lls, ll)
+ }
+ }
+ return lls, nil
+}
+
+func isDupLink(lls []Link, name string) bool {
+ for _, ll := range lls {
+ if ll.Name == name {
+ return true
+ }
+ }
+ return false
+}
diff --git a/libgo/go/golang_org/x/net/lif/link_test.go b/libgo/go/golang_org/x/net/lif/link_test.go
new file mode 100644
index 00000000000..8fb2bf6f345
--- /dev/null
+++ b/libgo/go/golang_org/x/net/lif/link_test.go
@@ -0,0 +1,61 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build solaris
+
+package lif
+
+import (
+ "fmt"
+ "testing"
+)
+
+func (ll *Link) String() string {
+ return fmt.Sprintf("name=%s index=%d type=%d flags=%#x mtu=%d addr=%v", ll.Name, ll.Index, ll.Type, ll.Flags, ll.MTU, llAddr(ll.Addr))
+}
+
+type linkPack struct {
+ af int
+ lls []Link
+}
+
+func linkPacks() ([]linkPack, error) {
+ var lps []linkPack
+ for _, af := range [...]int{sysAF_UNSPEC, sysAF_INET, sysAF_INET6} {
+ lls, err := Links(af, "")
+ if err != nil {
+ return nil, err
+ }
+ lps = append(lps, linkPack{af: af, lls: lls})
+ }
+ return lps, nil
+}
+
+func TestLinks(t *testing.T) {
+ lps, err := linkPacks()
+ if len(lps) == 0 && err != nil {
+ t.Fatal(err)
+ }
+ for _, lp := range lps {
+ n := 0
+ for _, sll := range lp.lls {
+ lls, err := Links(lp.af, sll.Name)
+ if err != nil {
+ t.Fatal(lp.af, sll.Name, err)
+ }
+ for _, ll := range lls {
+ if ll.Name != sll.Name || ll.Index != sll.Index {
+ t.Errorf("af=%s got %v; want %v", addrFamily(lp.af), &ll, &sll)
+ continue
+ }
+ t.Logf("af=%s name=%s %v", addrFamily(lp.af), sll.Name, &ll)
+ n++
+ }
+ }
+ if n != len(lp.lls) {
+ t.Errorf("af=%s got %d; want %d", addrFamily(lp.af), n, len(lp.lls))
+ continue
+ }
+ }
+}
diff --git a/libgo/go/golang_org/x/net/lif/syscall.go b/libgo/go/golang_org/x/net/lif/syscall.go
new file mode 100644
index 00000000000..5fe073620a4
--- /dev/null
+++ b/libgo/go/golang_org/x/net/lif/syscall.go
@@ -0,0 +1,33 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build solaris
+
+package lif
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+//go:cgo_import_dynamic libc_ioctl ioctl "libc.so"
+
+//go:linkname procIoctl libc_ioctl
+
+var procIoctl uintptr
+
+func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (uintptr, uintptr, syscall.Errno)
+
+// TODO: replace with runtime.KeepAlive when available
+//go:noescape
+func keepAlive(p unsafe.Pointer)
+
+func ioctl(s, ioc uintptr, arg unsafe.Pointer) error {
+ _, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procIoctl)), 3, s, ioc, uintptr(arg), 0, 0, 0)
+ keepAlive(arg)
+ if errno != 0 {
+ return error(errno)
+ }
+ return nil
+}
diff --git a/libgo/go/golang_org/x/net/lif/zsys_solaris_amd64.go b/libgo/go/golang_org/x/net/lif/zsys_solaris_amd64.go
new file mode 100644
index 00000000000..94231c49c96
--- /dev/null
+++ b/libgo/go/golang_org/x/net/lif/zsys_solaris_amd64.go
@@ -0,0 +1,103 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs defs_solaris.go
+
+package lif
+
+const (
+ sysAF_UNSPEC = 0x0
+ sysAF_INET = 0x2
+ sysAF_INET6 = 0x1a
+
+ sysSOCK_DGRAM = 0x1
+)
+
+type sockaddrStorage struct {
+ Family uint16
+ X_ss_pad1 [6]int8
+ X_ss_align float64
+ X_ss_pad2 [240]int8
+}
+
+const (
+ sysLIFC_NOXMIT = 0x1
+ sysLIFC_EXTERNAL_SOURCE = 0x2
+ sysLIFC_TEMPORARY = 0x4
+ sysLIFC_ALLZONES = 0x8
+ sysLIFC_UNDER_IPMP = 0x10
+ sysLIFC_ENABLED = 0x20
+
+ sysSIOCGLIFADDR = -0x3f87968f
+ sysSIOCGLIFDSTADDR = -0x3f87968d
+ sysSIOCGLIFFLAGS = -0x3f87968b
+ sysSIOCGLIFMTU = -0x3f879686
+ sysSIOCGLIFNETMASK = -0x3f879683
+ sysSIOCGLIFMETRIC = -0x3f879681
+ sysSIOCGLIFNUM = -0x3ff3967e
+ sysSIOCGLIFINDEX = -0x3f87967b
+ sysSIOCGLIFSUBNET = -0x3f879676
+ sysSIOCGLIFLNKINFO = -0x3f879674
+ sysSIOCGLIFCONF = -0x3fef965b
+ sysSIOCGLIFHWADDR = -0x3f879640
+)
+
+const (
+ sysIFF_UP = 0x1
+ sysIFF_BROADCAST = 0x2
+ sysIFF_DEBUG = 0x4
+ sysIFF_LOOPBACK = 0x8
+ sysIFF_POINTOPOINT = 0x10
+ sysIFF_NOTRAILERS = 0x20
+ sysIFF_RUNNING = 0x40
+ sysIFF_NOARP = 0x80
+ sysIFF_PROMISC = 0x100
+ sysIFF_ALLMULTI = 0x200
+ sysIFF_INTELLIGENT = 0x400
+ sysIFF_MULTICAST = 0x800
+ sysIFF_MULTI_BCAST = 0x1000
+ sysIFF_UNNUMBERED = 0x2000
+ sysIFF_PRIVATE = 0x8000
+)
+
+const (
+ sizeofLifnum = 0xc
+ sizeofLifreq = 0x178
+ sizeofLifconf = 0x18
+ sizeofLifIfinfoReq = 0x10
+)
+
+type sysLifnum struct {
+ Family uint16
+ Pad_cgo_0 [2]byte
+ Flags int32
+ Count int32
+}
+
+type lifreq struct {
+ Name [32]int8
+ Lifru1 [4]byte
+ Type uint32
+ Lifru [336]byte
+}
+
+type lifconf struct {
+ Family uint16
+ Pad_cgo_0 [2]byte
+ Flags int32
+ Len int32
+ Pad_cgo_1 [4]byte
+ Lifcu [8]byte
+}
+
+type lifIfinfoReq struct {
+ Maxhops uint8
+ Pad_cgo_0 [3]byte
+ Reachtime uint32
+ Reachretrans uint32
+ Maxmtu uint32
+}
+
+const (
+ sysIFT_IPV4 = 0xc8
+ sysIFT_IPV6 = 0xc9
+ sysIFT_6TO4 = 0xca
+)
diff --git a/libgo/go/golang_org/x/net/route/address.go b/libgo/go/golang_org/x/net/route/address.go
index 206a8371d43..a56909c105b 100644
--- a/libgo/go/golang_org/x/net/route/address.go
+++ b/libgo/go/golang_org/x/net/route/address.go
@@ -234,7 +234,11 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) (
return nil, err
}
as[i] = a
- b = b[roundup(int(b[0])):]
+ l := roundup(int(b[0]))
+ if len(b) < l {
+ return nil, errMessageTooShort
+ }
+ b = b[l:]
case sysAF_INET, sysAF_INET6:
af = int(b[1])
a, err := parseInetAddr(af, b)
@@ -242,7 +246,11 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) (
return nil, err
}
as[i] = a
- b = b[roundup(int(b[0])):]
+ l := roundup(int(b[0]))
+ if len(b) < l {
+ return nil, errMessageTooShort
+ }
+ b = b[l:]
default:
l, a, err := fn(af, b)
if err != nil {
@@ -262,7 +270,11 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) (
return nil, err
}
as[i] = a
- b = b[roundup(int(b[0])):]
+ l := roundup(int(b[0]))
+ if len(b) < l {
+ return nil, errMessageTooShort
+ }
+ b = b[l:]
}
}
return as[:], nil
diff --git a/libgo/go/golang_org/x/net/route/interface_freebsd.go b/libgo/go/golang_org/x/net/route/interface_freebsd.go
index c83053915da..9f6f50c00fe 100644
--- a/libgo/go/golang_org/x/net/route/interface_freebsd.go
+++ b/libgo/go/golang_org/x/net/route/interface_freebsd.go
@@ -13,12 +13,12 @@ func (w *wireFormat) parseInterfaceMessage(typ RIBType, b []byte) (Message, erro
extOff = int(nativeEndian.Uint16(b[18:20]))
bodyOff = int(nativeEndian.Uint16(b[16:18]))
} else {
- if len(b) < w.bodyOff {
- return nil, errMessageTooShort
- }
extOff = w.extOff
bodyOff = w.bodyOff
}
+ if len(b) < extOff || len(b) < bodyOff {
+ return nil, errInvalidMessage
+ }
l := int(nativeEndian.Uint16(b[:2]))
if len(b) < l {
return nil, errInvalidMessage
@@ -53,11 +53,11 @@ func (w *wireFormat) parseInterfaceAddrMessage(typ RIBType, b []byte) (Message,
}
bodyOff = int(nativeEndian.Uint16(b[16:18]))
} else {
- if len(b) < w.bodyOff {
- return nil, errMessageTooShort
- }
bodyOff = w.bodyOff
}
+ if len(b) < bodyOff {
+ return nil, errInvalidMessage
+ }
l := int(nativeEndian.Uint16(b[:2]))
if len(b) < l {
return nil, errInvalidMessage
diff --git a/libgo/go/golang_org/x/net/route/interface_openbsd.go b/libgo/go/golang_org/x/net/route/interface_openbsd.go
index 24451d8ca12..e4a143c1c73 100644
--- a/libgo/go/golang_org/x/net/route/interface_openbsd.go
+++ b/libgo/go/golang_org/x/net/route/interface_openbsd.go
@@ -24,7 +24,11 @@ func (*wireFormat) parseInterfaceMessage(_ RIBType, b []byte) (Message, error) {
Addrs: make([]Addr, sysRTAX_MAX),
raw: b[:l],
}
- a, err := parseLinkAddr(b[int(nativeEndian.Uint16(b[4:6])):])
+ ll := int(nativeEndian.Uint16(b[4:6]))
+ if len(b) < ll {
+ return nil, errInvalidMessage
+ }
+ a, err := parseLinkAddr(b[ll:])
if err != nil {
return nil, err
}
@@ -42,6 +46,9 @@ func (*wireFormat) parseInterfaceAddrMessage(_ RIBType, b []byte) (Message, erro
return nil, errInvalidMessage
}
bodyOff := int(nativeEndian.Uint16(b[4:6]))
+ if len(b) < bodyOff {
+ return nil, errInvalidMessage
+ }
m := &InterfaceAddrMessage{
Version: int(b[2]),
Type: int(b[3]),
diff --git a/libgo/go/golang_org/x/net/route/message.go b/libgo/go/golang_org/x/net/route/message.go
index 27cbf6b77ac..d7ae0eb50fc 100644
--- a/libgo/go/golang_org/x/net/route/message.go
+++ b/libgo/go/golang_org/x/net/route/message.go
@@ -42,6 +42,12 @@ func ParseRIB(typ RIBType, b []byte) ([]Message, error) {
for len(b) > 4 {
nmsgs++
l := int(nativeEndian.Uint16(b[:2]))
+ if l == 0 {
+ return nil, errInvalidMessage
+ }
+ if len(b) < l {
+ return nil, errMessageTooShort
+ }
if b[2] != sysRTM_VERSION {
b = b[l:]
continue
diff --git a/libgo/go/golang_org/x/net/route/message_test.go b/libgo/go/golang_org/x/net/route/message_test.go
index a1263d8f25e..c0c7c57a9a5 100644
--- a/libgo/go/golang_org/x/net/route/message_test.go
+++ b/libgo/go/golang_org/x/net/route/message_test.go
@@ -93,3 +93,26 @@ func TestMonitorAndParseRIB(t *testing.T) {
time.Sleep(200 * time.Millisecond)
}
}
+
+func TestParseRIBWithFuzz(t *testing.T) {
+ for _, fuzz := range []string{
+ "0\x00\x05\x050000000000000000" +
+ "00000000000000000000" +
+ "00000000000000000000" +
+ "00000000000000000000" +
+ "0000000000000\x02000000" +
+ "00000000",
+ "\x02\x00\x05\f0000000000000000" +
+ "0\x0200000000000000",
+ "\x02\x00\x05\x100000000000000\x1200" +
+ "0\x00\xff\x00",
+ "\x02\x00\x05\f0000000000000000" +
+ "0\x12000\x00\x02\x0000",
+ "\x00\x00\x00\x01\x00",
+ "00000",
+ } {
+ for typ := RIBType(0); typ < 256; typ++ {
+ ParseRIB(typ, []byte(fuzz))
+ }
+ }
+}
diff --git a/libgo/go/golang_org/x/net/route/route_openbsd.go b/libgo/go/golang_org/x/net/route/route_openbsd.go
index b07862f04d3..76eae40d806 100644
--- a/libgo/go/golang_org/x/net/route/route_openbsd.go
+++ b/libgo/go/golang_org/x/net/route/route_openbsd.go
@@ -19,7 +19,11 @@ func (*wireFormat) parseRouteMessage(_ RIBType, b []byte) (Message, error) {
Index: int(nativeEndian.Uint16(b[6:8])),
raw: b[:l],
}
- as, err := parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[int(nativeEndian.Uint16(b[4:6])):])
+ ll := int(nativeEndian.Uint16(b[4:6]))
+ if len(b) < ll {
+ return nil, errInvalidMessage
+ }
+ as, err := parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[ll:])
if err != nil {
return nil, err
}
diff --git a/libgo/go/golang_org/x/net/route/route_test.go b/libgo/go/golang_org/x/net/route/route_test.go
index 99f57b712d9..63fd8c5618a 100644
--- a/libgo/go/golang_org/x/net/route/route_test.go
+++ b/libgo/go/golang_org/x/net/route/route_test.go
@@ -235,7 +235,7 @@ func (a *LinkAddr) String() string {
return fmt.Sprintf("(%v %d %s %s)", addrFamily(a.Family()), a.Index, name, lla)
}
-func (a Inet4Addr) String() string {
+func (a *Inet4Addr) String() string {
return fmt.Sprintf("(%v %v)", addrFamily(a.Family()), ipAddr(a.IP[:]))
}
@@ -325,6 +325,7 @@ func fetchAndParseRIB(af int, typ RIBType) ([]Message, error) {
return ms, nil
}
+// propVirtual is a proprietary virtual network interface.
type propVirtual struct {
name string
addr, mask string
@@ -332,18 +333,18 @@ type propVirtual struct {
teardownCmds []*exec.Cmd
}
-func (ti *propVirtual) setup() error {
- for _, cmd := range ti.setupCmds {
+func (pv *propVirtual) setup() error {
+ for _, cmd := range pv.setupCmds {
if err := cmd.Run(); err != nil {
- ti.teardown()
+ pv.teardown()
return err
}
}
return nil
}
-func (ti *propVirtual) teardown() error {
- for _, cmd := range ti.teardownCmds {
+func (pv *propVirtual) teardown() error {
+ for _, cmd := range pv.teardownCmds {
if err := cmd.Run(); err != nil {
return err
}
@@ -351,35 +352,35 @@ func (ti *propVirtual) teardown() error {
return nil
}
-func (ti *propVirtual) configure(suffix int) error {
+func (pv *propVirtual) configure(suffix int) error {
if runtime.GOOS == "openbsd" {
- ti.name = fmt.Sprintf("vether%d", suffix)
+ pv.name = fmt.Sprintf("vether%d", suffix)
} else {
- ti.name = fmt.Sprintf("vlan%d", suffix)
+ pv.name = fmt.Sprintf("vlan%d", suffix)
}
xname, err := exec.LookPath("ifconfig")
if err != nil {
return err
}
- ti.setupCmds = append(ti.setupCmds, &exec.Cmd{
+ pv.setupCmds = append(pv.setupCmds, &exec.Cmd{
Path: xname,
- Args: []string{"ifconfig", ti.name, "create"},
+ Args: []string{"ifconfig", pv.name, "create"},
})
if runtime.GOOS == "netbsd" {
// NetBSD requires an underlying dot1Q-capable network
// interface.
- ti.setupCmds = append(ti.setupCmds, &exec.Cmd{
+ pv.setupCmds = append(pv.setupCmds, &exec.Cmd{
Path: xname,
- Args: []string{"ifconfig", ti.name, "vlan", fmt.Sprintf("%d", suffix&0xfff), "vlanif", "wm0"},
+ Args: []string{"ifconfig", pv.name, "vlan", fmt.Sprintf("%d", suffix&0xfff), "vlanif", "wm0"},
})
}
- ti.setupCmds = append(ti.setupCmds, &exec.Cmd{
+ pv.setupCmds = append(pv.setupCmds, &exec.Cmd{
Path: xname,
- Args: []string{"ifconfig", ti.name, "inet", ti.addr, "netmask", ti.mask},
+ Args: []string{"ifconfig", pv.name, "inet", pv.addr, "netmask", pv.mask},
})
- ti.teardownCmds = append(ti.teardownCmds, &exec.Cmd{
+ pv.teardownCmds = append(pv.teardownCmds, &exec.Cmd{
Path: xname,
- Args: []string{"ifconfig", ti.name, "destroy"},
+ Args: []string{"ifconfig", pv.name, "destroy"},
})
return nil
}
diff --git a/libgo/go/golang_org/x/text/transform/transform.go b/libgo/go/golang_org/x/text/transform/transform.go
new file mode 100644
index 00000000000..fe47b9b35f0
--- /dev/null
+++ b/libgo/go/golang_org/x/text/transform/transform.go
@@ -0,0 +1,705 @@
+// 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 transform provides reader and writer wrappers that transform the
+// bytes passing through as well as various transformations. Example
+// transformations provided by other packages include normalization and
+// conversion between character sets.
+package transform // import "golang.org/x/text/transform"
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "unicode/utf8"
+)
+
+var (
+ // ErrShortDst means that the destination buffer was too short to
+ // receive all of the transformed bytes.
+ ErrShortDst = errors.New("transform: short destination buffer")
+
+ // ErrShortSrc means that the source buffer has insufficient data to
+ // complete the transformation.
+ ErrShortSrc = errors.New("transform: short source buffer")
+
+ // ErrEndOfSpan means that the input and output (the transformed input)
+ // are not identical.
+ ErrEndOfSpan = errors.New("transform: input and output are not identical")
+
+ // errInconsistentByteCount means that Transform returned success (nil
+ // error) but also returned nSrc inconsistent with the src argument.
+ errInconsistentByteCount = errors.New("transform: inconsistent byte count returned")
+
+ // errShortInternal means that an internal buffer is not large enough
+ // to make progress and the Transform operation must be aborted.
+ errShortInternal = errors.New("transform: short internal buffer")
+)
+
+// Transformer transforms bytes.
+type Transformer interface {
+ // Transform writes to dst the transformed bytes read from src, and
+ // returns the number of dst bytes written and src bytes read. The
+ // atEOF argument tells whether src represents the last bytes of the
+ // input.
+ //
+ // Callers should always process the nDst bytes produced and account
+ // for the nSrc bytes consumed before considering the error err.
+ //
+ // A nil error means that all of the transformed bytes (whether freshly
+ // transformed from src or left over from previous Transform calls)
+ // were written to dst. A nil error can be returned regardless of
+ // whether atEOF is true. If err is nil then nSrc must equal len(src);
+ // the converse is not necessarily true.
+ //
+ // ErrShortDst means that dst was too short to receive all of the
+ // transformed bytes. ErrShortSrc means that src had insufficient data
+ // to complete the transformation. If both conditions apply, then
+ // either error may be returned. Other than the error conditions listed
+ // here, implementations are free to report other errors that arise.
+ Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error)
+
+ // Reset resets the state and allows a Transformer to be reused.
+ Reset()
+}
+
+// SpanningTransformer extends the Transformer interface with a Span method
+// that determines how much of the input already conforms to the Transformer.
+type SpanningTransformer interface {
+ Transformer
+
+ // Span returns a position in src such that transforming src[:n] results in
+ // identical output src[:n] for these bytes. It does not necessarily return
+ // the largest such n. The atEOF argument tells whether src represents the
+ // last bytes of the input.
+ //
+ // Callers should always account for the n bytes consumed before
+ // considering the error err.
+ //
+ // A nil error means that all input bytes are known to be identical to the
+ // output produced by the Transformer. A nil error can be be returned
+ // regardless of whether atEOF is true. If err is nil, then then n must
+ // equal len(src); the converse is not necessarily true.
+ //
+ // ErrEndOfSpan means that the Transformer output may differ from the
+ // input after n bytes. Note that n may be len(src), meaning that the output
+ // would contain additional bytes after otherwise identical output.
+ // ErrShortSrc means that src had insufficient data to determine whether the
+ // remaining bytes would change. Other than the error conditions listed
+ // here, implementations are free to report other errors that arise.
+ //
+ // Calling Span can modify the Transformer state as a side effect. In
+ // effect, it does the transformation just as calling Transform would, only
+ // without copying to a destination buffer and only up to a point it can
+ // determine the input and output bytes are the same. This is obviously more
+ // limited than calling Transform, but can be more efficient in terms of
+ // copying and allocating buffers. Calls to Span and Transform may be
+ // interleaved.
+ Span(src []byte, atEOF bool) (n int, err error)
+}
+
+// NopResetter can be embedded by implementations of Transformer to add a nop
+// Reset method.
+type NopResetter struct{}
+
+// Reset implements the Reset method of the Transformer interface.
+func (NopResetter) Reset() {}
+
+// Reader wraps another io.Reader by transforming the bytes read.
+type Reader struct {
+ r io.Reader
+ t Transformer
+ err error
+
+ // dst[dst0:dst1] contains bytes that have been transformed by t but
+ // not yet copied out via Read.
+ dst []byte
+ dst0, dst1 int
+
+ // src[src0:src1] contains bytes that have been read from r but not
+ // yet transformed through t.
+ src []byte
+ src0, src1 int
+
+ // transformComplete is whether the transformation is complete,
+ // regardless of whether or not it was successful.
+ transformComplete bool
+}
+
+const defaultBufSize = 4096
+
+// NewReader returns a new Reader that wraps r by transforming the bytes read
+// via t. It calls Reset on t.
+func NewReader(r io.Reader, t Transformer) *Reader {
+ t.Reset()
+ return &Reader{
+ r: r,
+ t: t,
+ dst: make([]byte, defaultBufSize),
+ src: make([]byte, defaultBufSize),
+ }
+}
+
+// Read implements the io.Reader interface.
+func (r *Reader) Read(p []byte) (int, error) {
+ n, err := 0, error(nil)
+ for {
+ // Copy out any transformed bytes and return the final error if we are done.
+ if r.dst0 != r.dst1 {
+ n = copy(p, r.dst[r.dst0:r.dst1])
+ r.dst0 += n
+ if r.dst0 == r.dst1 && r.transformComplete {
+ return n, r.err
+ }
+ return n, nil
+ } else if r.transformComplete {
+ return 0, r.err
+ }
+
+ // Try to transform some source bytes, or to flush the transformer if we
+ // are out of source bytes. We do this even if r.r.Read returned an error.
+ // As the io.Reader documentation says, "process the n > 0 bytes returned
+ // before considering the error".
+ if r.src0 != r.src1 || r.err != nil {
+ r.dst0 = 0
+ r.dst1, n, err = r.t.Transform(r.dst, r.src[r.src0:r.src1], r.err == io.EOF)
+ r.src0 += n
+
+ switch {
+ case err == nil:
+ if r.src0 != r.src1 {
+ r.err = errInconsistentByteCount
+ }
+ // The Transform call was successful; we are complete if we
+ // cannot read more bytes into src.
+ r.transformComplete = r.err != nil
+ continue
+ case err == ErrShortDst && (r.dst1 != 0 || n != 0):
+ // Make room in dst by copying out, and try again.
+ continue
+ case err == ErrShortSrc && r.src1-r.src0 != len(r.src) && r.err == nil:
+ // Read more bytes into src via the code below, and try again.
+ default:
+ r.transformComplete = true
+ // The reader error (r.err) takes precedence over the
+ // transformer error (err) unless r.err is nil or io.EOF.
+ if r.err == nil || r.err == io.EOF {
+ r.err = err
+ }
+ continue
+ }
+ }
+
+ // Move any untransformed source bytes to the start of the buffer
+ // and read more bytes.
+ if r.src0 != 0 {
+ r.src0, r.src1 = 0, copy(r.src, r.src[r.src0:r.src1])
+ }
+ n, r.err = r.r.Read(r.src[r.src1:])
+ r.src1 += n
+ }
+}
+
+// TODO: implement ReadByte (and ReadRune??).
+
+// Writer wraps another io.Writer by transforming the bytes read.
+// The user needs to call Close to flush unwritten bytes that may
+// be buffered.
+type Writer struct {
+ w io.Writer
+ t Transformer
+ dst []byte
+
+ // src[:n] contains bytes that have not yet passed through t.
+ src []byte
+ n int
+}
+
+// NewWriter returns a new Writer that wraps w by transforming the bytes written
+// via t. It calls Reset on t.
+func NewWriter(w io.Writer, t Transformer) *Writer {
+ t.Reset()
+ return &Writer{
+ w: w,
+ t: t,
+ dst: make([]byte, defaultBufSize),
+ src: make([]byte, defaultBufSize),
+ }
+}
+
+// Write implements the io.Writer interface. If there are not enough
+// bytes available to complete a Transform, the bytes will be buffered
+// for the next write. Call Close to convert the remaining bytes.
+func (w *Writer) Write(data []byte) (n int, err error) {
+ src := data
+ if w.n > 0 {
+ // Append bytes from data to the last remainder.
+ // TODO: limit the amount copied on first try.
+ n = copy(w.src[w.n:], data)
+ w.n += n
+ src = w.src[:w.n]
+ }
+ for {
+ nDst, nSrc, err := w.t.Transform(w.dst, src, false)
+ if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
+ return n, werr
+ }
+ src = src[nSrc:]
+ if w.n == 0 {
+ n += nSrc
+ } else if len(src) <= n {
+ // Enough bytes from w.src have been consumed. We make src point
+ // to data instead to reduce the copying.
+ w.n = 0
+ n -= len(src)
+ src = data[n:]
+ if n < len(data) && (err == nil || err == ErrShortSrc) {
+ continue
+ }
+ }
+ switch err {
+ case ErrShortDst:
+ // This error is okay as long as we are making progress.
+ if nDst > 0 || nSrc > 0 {
+ continue
+ }
+ case ErrShortSrc:
+ if len(src) < len(w.src) {
+ m := copy(w.src, src)
+ // If w.n > 0, bytes from data were already copied to w.src and n
+ // was already set to the number of bytes consumed.
+ if w.n == 0 {
+ n += m
+ }
+ w.n = m
+ err = nil
+ } else if nDst > 0 || nSrc > 0 {
+ // Not enough buffer to store the remainder. Keep processing as
+ // long as there is progress. Without this case, transforms that
+ // require a lookahead larger than the buffer may result in an
+ // error. This is not something one may expect to be common in
+ // practice, but it may occur when buffers are set to small
+ // sizes during testing.
+ continue
+ }
+ case nil:
+ if w.n > 0 {
+ err = errInconsistentByteCount
+ }
+ }
+ return n, err
+ }
+}
+
+// Close implements the io.Closer interface.
+func (w *Writer) Close() error {
+ src := w.src[:w.n]
+ for {
+ nDst, nSrc, err := w.t.Transform(w.dst, src, true)
+ if _, werr := w.w.Write(w.dst[:nDst]); werr != nil {
+ return werr
+ }
+ if err != ErrShortDst {
+ return err
+ }
+ src = src[nSrc:]
+ }
+}
+
+type nop struct{ NopResetter }
+
+func (nop) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ n := copy(dst, src)
+ if n < len(src) {
+ err = ErrShortDst
+ }
+ return n, n, err
+}
+
+func (nop) Span(src []byte, atEOF bool) (n int, err error) {
+ return len(src), nil
+}
+
+type discard struct{ NopResetter }
+
+func (discard) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ return 0, len(src), nil
+}
+
+var (
+ // Discard is a Transformer for which all Transform calls succeed
+ // by consuming all bytes and writing nothing.
+ Discard Transformer = discard{}
+
+ // Nop is a SpanningTransformer that copies src to dst.
+ Nop SpanningTransformer = nop{}
+)
+
+// chain is a sequence of links. A chain with N Transformers has N+1 links and
+// N+1 buffers. Of those N+1 buffers, the first and last are the src and dst
+// buffers given to chain.Transform and the middle N-1 buffers are intermediate
+// buffers owned by the chain. The i'th link transforms bytes from the i'th
+// buffer chain.link[i].b at read offset chain.link[i].p to the i+1'th buffer
+// chain.link[i+1].b at write offset chain.link[i+1].n, for i in [0, N).
+type chain struct {
+ link []link
+ err error
+ // errStart is the index at which the error occurred plus 1. Processing
+ // errStart at this level at the next call to Transform. As long as
+ // errStart > 0, chain will not consume any more source bytes.
+ errStart int
+}
+
+func (c *chain) fatalError(errIndex int, err error) {
+ if i := errIndex + 1; i > c.errStart {
+ c.errStart = i
+ c.err = err
+ }
+}
+
+type link struct {
+ t Transformer
+ // b[p:n] holds the bytes to be transformed by t.
+ b []byte
+ p int
+ n int
+}
+
+func (l *link) src() []byte {
+ return l.b[l.p:l.n]
+}
+
+func (l *link) dst() []byte {
+ return l.b[l.n:]
+}
+
+// Chain returns a Transformer that applies t in sequence.
+func Chain(t ...Transformer) Transformer {
+ if len(t) == 0 {
+ return nop{}
+ }
+ c := &chain{link: make([]link, len(t)+1)}
+ for i, tt := range t {
+ c.link[i].t = tt
+ }
+ // Allocate intermediate buffers.
+ b := make([][defaultBufSize]byte, len(t)-1)
+ for i := range b {
+ c.link[i+1].b = b[i][:]
+ }
+ return c
+}
+
+// Reset resets the state of Chain. It calls Reset on all the Transformers.
+func (c *chain) Reset() {
+ for i, l := range c.link {
+ if l.t != nil {
+ l.t.Reset()
+ }
+ c.link[i].p, c.link[i].n = 0, 0
+ }
+}
+
+// TODO: make chain use Span (is going to be fun to implement!)
+
+// Transform applies the transformers of c in sequence.
+func (c *chain) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ // Set up src and dst in the chain.
+ srcL := &c.link[0]
+ dstL := &c.link[len(c.link)-1]
+ srcL.b, srcL.p, srcL.n = src, 0, len(src)
+ dstL.b, dstL.n = dst, 0
+ var lastFull, needProgress bool // for detecting progress
+
+ // i is the index of the next Transformer to apply, for i in [low, high].
+ // low is the lowest index for which c.link[low] may still produce bytes.
+ // high is the highest index for which c.link[high] has a Transformer.
+ // The error returned by Transform determines whether to increase or
+ // decrease i. We try to completely fill a buffer before converting it.
+ for low, i, high := c.errStart, c.errStart, len(c.link)-2; low <= i && i <= high; {
+ in, out := &c.link[i], &c.link[i+1]
+ nDst, nSrc, err0 := in.t.Transform(out.dst(), in.src(), atEOF && low == i)
+ out.n += nDst
+ in.p += nSrc
+ if i > 0 && in.p == in.n {
+ in.p, in.n = 0, 0
+ }
+ needProgress, lastFull = lastFull, false
+ switch err0 {
+ case ErrShortDst:
+ // Process the destination buffer next. Return if we are already
+ // at the high index.
+ if i == high {
+ return dstL.n, srcL.p, ErrShortDst
+ }
+ if out.n != 0 {
+ i++
+ // If the Transformer at the next index is not able to process any
+ // source bytes there is nothing that can be done to make progress
+ // and the bytes will remain unprocessed. lastFull is used to
+ // detect this and break out of the loop with a fatal error.
+ lastFull = true
+ continue
+ }
+ // The destination buffer was too small, but is completely empty.
+ // Return a fatal error as this transformation can never complete.
+ c.fatalError(i, errShortInternal)
+ case ErrShortSrc:
+ if i == 0 {
+ // Save ErrShortSrc in err. All other errors take precedence.
+ err = ErrShortSrc
+ break
+ }
+ // Source bytes were depleted before filling up the destination buffer.
+ // Verify we made some progress, move the remaining bytes to the errStart
+ // and try to get more source bytes.
+ if needProgress && nSrc == 0 || in.n-in.p == len(in.b) {
+ // There were not enough source bytes to proceed while the source
+ // buffer cannot hold any more bytes. Return a fatal error as this
+ // transformation can never complete.
+ c.fatalError(i, errShortInternal)
+ break
+ }
+ // in.b is an internal buffer and we can make progress.
+ in.p, in.n = 0, copy(in.b, in.src())
+ fallthrough
+ case nil:
+ // if i == low, we have depleted the bytes at index i or any lower levels.
+ // In that case we increase low and i. In all other cases we decrease i to
+ // fetch more bytes before proceeding to the next index.
+ if i > low {
+ i--
+ continue
+ }
+ default:
+ c.fatalError(i, err0)
+ }
+ // Exhausted level low or fatal error: increase low and continue
+ // to process the bytes accepted so far.
+ i++
+ low = i
+ }
+
+ // If c.errStart > 0, this means we found a fatal error. We will clear
+ // all upstream buffers. At this point, no more progress can be made
+ // downstream, as Transform would have bailed while handling ErrShortDst.
+ if c.errStart > 0 {
+ for i := 1; i < c.errStart; i++ {
+ c.link[i].p, c.link[i].n = 0, 0
+ }
+ err, c.errStart, c.err = c.err, 0, nil
+ }
+ return dstL.n, srcL.p, err
+}
+
+// Deprecated: use runes.Remove instead.
+func RemoveFunc(f func(r rune) bool) Transformer {
+ return removeF(f)
+}
+
+type removeF func(r rune) bool
+
+func (removeF) Reset() {}
+
+// Transform implements the Transformer interface.
+func (t removeF) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ for r, sz := rune(0), 0; len(src) > 0; src = src[sz:] {
+
+ if r = rune(src[0]); r < utf8.RuneSelf {
+ sz = 1
+ } else {
+ r, sz = utf8.DecodeRune(src)
+
+ if sz == 1 {
+ // Invalid rune.
+ if !atEOF && !utf8.FullRune(src) {
+ err = ErrShortSrc
+ break
+ }
+ // We replace illegal bytes with RuneError. Not doing so might
+ // otherwise turn a sequence of invalid UTF-8 into valid UTF-8.
+ // The resulting byte sequence may subsequently contain runes
+ // for which t(r) is true that were passed unnoticed.
+ if !t(r) {
+ if nDst+3 > len(dst) {
+ err = ErrShortDst
+ break
+ }
+ nDst += copy(dst[nDst:], "\uFFFD")
+ }
+ nSrc++
+ continue
+ }
+ }
+
+ if !t(r) {
+ if nDst+sz > len(dst) {
+ err = ErrShortDst
+ break
+ }
+ nDst += copy(dst[nDst:], src[:sz])
+ }
+ nSrc += sz
+ }
+ return
+}
+
+// grow returns a new []byte that is longer than b, and copies the first n bytes
+// of b to the start of the new slice.
+func grow(b []byte, n int) []byte {
+ m := len(b)
+ if m <= 32 {
+ m = 64
+ } else if m <= 256 {
+ m *= 2
+ } else {
+ m += m >> 1
+ }
+ buf := make([]byte, m)
+ copy(buf, b[:n])
+ return buf
+}
+
+const initialBufSize = 128
+
+// String returns a string with the result of converting s[:n] using t, where
+// n <= len(s). If err == nil, n will be len(s). It calls Reset on t.
+func String(t Transformer, s string) (result string, n int, err error) {
+ t.Reset()
+ if s == "" {
+ // Fast path for the common case for empty input. Results in about a
+ // 86% reduction of running time for BenchmarkStringLowerEmpty.
+ if _, _, err := t.Transform(nil, nil, true); err == nil {
+ return "", 0, nil
+ }
+ }
+
+ // Allocate only once. Note that both dst and src escape when passed to
+ // Transform.
+ buf := [2 * initialBufSize]byte{}
+ dst := buf[:initialBufSize:initialBufSize]
+ src := buf[initialBufSize : 2*initialBufSize]
+
+ // The input string s is transformed in multiple chunks (starting with a
+ // chunk size of initialBufSize). nDst and nSrc are per-chunk (or
+ // per-Transform-call) indexes, pDst and pSrc are overall indexes.
+ nDst, nSrc := 0, 0
+ pDst, pSrc := 0, 0
+
+ // pPrefix is the length of a common prefix: the first pPrefix bytes of the
+ // result will equal the first pPrefix bytes of s. It is not guaranteed to
+ // be the largest such value, but if pPrefix, len(result) and len(s) are
+ // all equal after the final transform (i.e. calling Transform with atEOF
+ // being true returned nil error) then we don't need to allocate a new
+ // result string.
+ pPrefix := 0
+ for {
+ // Invariant: pDst == pPrefix && pSrc == pPrefix.
+
+ n := copy(src, s[pSrc:])
+ nDst, nSrc, err = t.Transform(dst, src[:n], pSrc+n == len(s))
+ pDst += nDst
+ pSrc += nSrc
+
+ // TODO: let transformers implement an optional Spanner interface, akin
+ // to norm's QuickSpan. This would even allow us to avoid any allocation.
+ if !bytes.Equal(dst[:nDst], src[:nSrc]) {
+ break
+ }
+ pPrefix = pSrc
+ if err == ErrShortDst {
+ // A buffer can only be short if a transformer modifies its input.
+ break
+ } else if err == ErrShortSrc {
+ if nSrc == 0 {
+ // No progress was made.
+ break
+ }
+ // Equal so far and !atEOF, so continue checking.
+ } else if err != nil || pPrefix == len(s) {
+ return string(s[:pPrefix]), pPrefix, err
+ }
+ }
+ // Post-condition: pDst == pPrefix + nDst && pSrc == pPrefix + nSrc.
+
+ // We have transformed the first pSrc bytes of the input s to become pDst
+ // transformed bytes. Those transformed bytes are discontiguous: the first
+ // pPrefix of them equal s[:pPrefix] and the last nDst of them equal
+ // dst[:nDst]. We copy them around, into a new dst buffer if necessary, so
+ // that they become one contiguous slice: dst[:pDst].
+ if pPrefix != 0 {
+ newDst := dst
+ if pDst > len(newDst) {
+ newDst = make([]byte, len(s)+nDst-nSrc)
+ }
+ copy(newDst[pPrefix:pDst], dst[:nDst])
+ copy(newDst[:pPrefix], s[:pPrefix])
+ dst = newDst
+ }
+
+ // Prevent duplicate Transform calls with atEOF being true at the end of
+ // the input. Also return if we have an unrecoverable error.
+ if (err == nil && pSrc == len(s)) ||
+ (err != nil && err != ErrShortDst && err != ErrShortSrc) {
+ return string(dst[:pDst]), pSrc, err
+ }
+
+ // Transform the remaining input, growing dst and src buffers as necessary.
+ for {
+ n := copy(src, s[pSrc:])
+ nDst, nSrc, err := t.Transform(dst[pDst:], src[:n], pSrc+n == len(s))
+ pDst += nDst
+ pSrc += nSrc
+
+ // If we got ErrShortDst or ErrShortSrc, do not grow as long as we can
+ // make progress. This may avoid excessive allocations.
+ if err == ErrShortDst {
+ if nDst == 0 {
+ dst = grow(dst, pDst)
+ }
+ } else if err == ErrShortSrc {
+ if nSrc == 0 {
+ src = grow(src, 0)
+ }
+ } else if err != nil || pSrc == len(s) {
+ return string(dst[:pDst]), pSrc, err
+ }
+ }
+}
+
+// Bytes returns a new byte slice with the result of converting b[:n] using t,
+// where n <= len(b). If err == nil, n will be len(b). It calls Reset on t.
+func Bytes(t Transformer, b []byte) (result []byte, n int, err error) {
+ return doAppend(t, 0, make([]byte, len(b)), b)
+}
+
+// Append appends the result of converting src[:n] using t to dst, where
+// n <= len(src), If err == nil, n will be len(src). It calls Reset on t.
+func Append(t Transformer, dst, src []byte) (result []byte, n int, err error) {
+ if len(dst) == cap(dst) {
+ n := len(src) + len(dst) // It is okay for this to be 0.
+ b := make([]byte, n)
+ dst = b[:copy(b, dst)]
+ }
+ return doAppend(t, len(dst), dst[:cap(dst)], src)
+}
+
+func doAppend(t Transformer, pDst int, dst, src []byte) (result []byte, n int, err error) {
+ t.Reset()
+ pSrc := 0
+ for {
+ nDst, nSrc, err := t.Transform(dst[pDst:], src[pSrc:], true)
+ pDst += nDst
+ pSrc += nSrc
+ if err != ErrShortDst {
+ return dst[:pDst], pSrc, err
+ }
+
+ // Grow the destination buffer, but do not grow as long as we can make
+ // progress. This may avoid excessive allocations.
+ if nDst == 0 {
+ dst = grow(dst, pDst)
+ }
+ }
+}
diff --git a/libgo/go/golang_org/x/text/unicode/norm/composition.go b/libgo/go/golang_org/x/text/unicode/norm/composition.go
new file mode 100644
index 00000000000..d17b278adc3
--- /dev/null
+++ b/libgo/go/golang_org/x/text/unicode/norm/composition.go
@@ -0,0 +1,514 @@
+// 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 norm
+
+import "unicode/utf8"
+
+const (
+ maxNonStarters = 30
+ // The maximum number of characters needed for a buffer is
+ // maxNonStarters + 1 for the starter + 1 for the GCJ
+ maxBufferSize = maxNonStarters + 2
+ maxNFCExpansion = 3 // NFC(0x1D160)
+ maxNFKCExpansion = 18 // NFKC(0xFDFA)
+
+ maxByteBufferSize = utf8.UTFMax * maxBufferSize // 128
+)
+
+// ssState is used for reporting the segment state after inserting a rune.
+// It is returned by streamSafe.next.
+type ssState int
+
+const (
+ // Indicates a rune was successfully added to the segment.
+ ssSuccess ssState = iota
+ // Indicates a rune starts a new segment and should not be added.
+ ssStarter
+ // Indicates a rune caused a segment overflow and a CGJ should be inserted.
+ ssOverflow
+)
+
+// streamSafe implements the policy of when a CGJ should be inserted.
+type streamSafe uint8
+
+// mkStreamSafe is a shorthand for declaring a streamSafe var and calling
+// first on it.
+func mkStreamSafe(p Properties) streamSafe {
+ return streamSafe(p.nTrailingNonStarters())
+}
+
+// first inserts the first rune of a segment.
+func (ss *streamSafe) first(p Properties) {
+ if *ss != 0 {
+ panic("!= 0")
+ }
+ *ss = streamSafe(p.nTrailingNonStarters())
+}
+
+// insert returns a ssState value to indicate whether a rune represented by p
+// can be inserted.
+func (ss *streamSafe) next(p Properties) ssState {
+ if *ss > maxNonStarters {
+ panic("streamSafe was not reset")
+ }
+ n := p.nLeadingNonStarters()
+ if *ss += streamSafe(n); *ss > maxNonStarters {
+ *ss = 0
+ return ssOverflow
+ }
+ // The Stream-Safe Text Processing prescribes that the counting can stop
+ // as soon as a starter is encountered. However, there are some starters,
+ // like Jamo V and T, that can combine with other runes, leaving their
+ // successive non-starters appended to the previous, possibly causing an
+ // overflow. We will therefore consider any rune with a non-zero nLead to
+ // be a non-starter. Note that it always hold that if nLead > 0 then
+ // nLead == nTrail.
+ if n == 0 {
+ *ss = 0
+ return ssStarter
+ }
+ return ssSuccess
+}
+
+// backwards is used for checking for overflow and segment starts
+// when traversing a string backwards. Users do not need to call first
+// for the first rune. The state of the streamSafe retains the count of
+// the non-starters loaded.
+func (ss *streamSafe) backwards(p Properties) ssState {
+ if *ss > maxNonStarters {
+ panic("streamSafe was not reset")
+ }
+ c := *ss + streamSafe(p.nTrailingNonStarters())
+ if c > maxNonStarters {
+ return ssOverflow
+ }
+ *ss = c
+ if p.nLeadingNonStarters() == 0 {
+ return ssStarter
+ }
+ return ssSuccess
+}
+
+func (ss streamSafe) isMax() bool {
+ return ss == maxNonStarters
+}
+
+// GraphemeJoiner is inserted after maxNonStarters non-starter runes.
+const GraphemeJoiner = "\u034F"
+
+// reorderBuffer is used to normalize a single segment. Characters inserted with
+// insert are decomposed and reordered based on CCC. The compose method can
+// be used to recombine characters. Note that the byte buffer does not hold
+// the UTF-8 characters in order. Only the rune array is maintained in sorted
+// order. flush writes the resulting segment to a byte array.
+type reorderBuffer struct {
+ rune [maxBufferSize]Properties // Per character info.
+ byte [maxByteBufferSize]byte // UTF-8 buffer. Referenced by runeInfo.pos.
+ nbyte uint8 // Number or bytes.
+ ss streamSafe // For limiting length of non-starter sequence.
+ nrune int // Number of runeInfos.
+ f formInfo
+
+ src input
+ nsrc int
+ tmpBytes input
+
+ out []byte
+ flushF func(*reorderBuffer) bool
+}
+
+func (rb *reorderBuffer) init(f Form, src []byte) {
+ rb.f = *formTable[f]
+ rb.src.setBytes(src)
+ rb.nsrc = len(src)
+ rb.ss = 0
+}
+
+func (rb *reorderBuffer) initString(f Form, src string) {
+ rb.f = *formTable[f]
+ rb.src.setString(src)
+ rb.nsrc = len(src)
+ rb.ss = 0
+}
+
+func (rb *reorderBuffer) setFlusher(out []byte, f func(*reorderBuffer) bool) {
+ rb.out = out
+ rb.flushF = f
+}
+
+// reset discards all characters from the buffer.
+func (rb *reorderBuffer) reset() {
+ rb.nrune = 0
+ rb.nbyte = 0
+ rb.ss = 0
+}
+
+func (rb *reorderBuffer) doFlush() bool {
+ if rb.f.composing {
+ rb.compose()
+ }
+ res := rb.flushF(rb)
+ rb.reset()
+ return res
+}
+
+// appendFlush appends the normalized segment to rb.out.
+func appendFlush(rb *reorderBuffer) bool {
+ for i := 0; i < rb.nrune; i++ {
+ start := rb.rune[i].pos
+ end := start + rb.rune[i].size
+ rb.out = append(rb.out, rb.byte[start:end]...)
+ }
+ return true
+}
+
+// flush appends the normalized segment to out and resets rb.
+func (rb *reorderBuffer) flush(out []byte) []byte {
+ for i := 0; i < rb.nrune; i++ {
+ start := rb.rune[i].pos
+ end := start + rb.rune[i].size
+ out = append(out, rb.byte[start:end]...)
+ }
+ rb.reset()
+ return out
+}
+
+// flushCopy copies the normalized segment to buf and resets rb.
+// It returns the number of bytes written to buf.
+func (rb *reorderBuffer) flushCopy(buf []byte) int {
+ p := 0
+ for i := 0; i < rb.nrune; i++ {
+ runep := rb.rune[i]
+ p += copy(buf[p:], rb.byte[runep.pos:runep.pos+runep.size])
+ }
+ rb.reset()
+ return p
+}
+
+// insertOrdered inserts a rune in the buffer, ordered by Canonical Combining Class.
+// It returns false if the buffer is not large enough to hold the rune.
+// It is used internally by insert and insertString only.
+func (rb *reorderBuffer) insertOrdered(info Properties) {
+ n := rb.nrune
+ b := rb.rune[:]
+ cc := info.ccc
+ if cc > 0 {
+ // Find insertion position + move elements to make room.
+ for ; n > 0; n-- {
+ if b[n-1].ccc <= cc {
+ break
+ }
+ b[n] = b[n-1]
+ }
+ }
+ rb.nrune += 1
+ pos := uint8(rb.nbyte)
+ rb.nbyte += utf8.UTFMax
+ info.pos = pos
+ b[n] = info
+}
+
+// insertErr is an error code returned by insert. Using this type instead
+// of error improves performance up to 20% for many of the benchmarks.
+type insertErr int
+
+const (
+ iSuccess insertErr = -iota
+ iShortDst
+ iShortSrc
+)
+
+// insertFlush inserts the given rune in the buffer ordered by CCC.
+// If a decomposition with multiple segments are encountered, they leading
+// ones are flushed.
+// It returns a non-zero error code if the rune was not inserted.
+func (rb *reorderBuffer) insertFlush(src input, i int, info Properties) insertErr {
+ if rune := src.hangul(i); rune != 0 {
+ rb.decomposeHangul(rune)
+ return iSuccess
+ }
+ if info.hasDecomposition() {
+ return rb.insertDecomposed(info.Decomposition())
+ }
+ rb.insertSingle(src, i, info)
+ return iSuccess
+}
+
+// insertUnsafe inserts the given rune in the buffer ordered by CCC.
+// It is assumed there is sufficient space to hold the runes. It is the
+// responsibility of the caller to ensure this. This can be done by checking
+// the state returned by the streamSafe type.
+func (rb *reorderBuffer) insertUnsafe(src input, i int, info Properties) {
+ if rune := src.hangul(i); rune != 0 {
+ rb.decomposeHangul(rune)
+ }
+ if info.hasDecomposition() {
+ // TODO: inline.
+ rb.insertDecomposed(info.Decomposition())
+ } else {
+ rb.insertSingle(src, i, info)
+ }
+}
+
+// insertDecomposed inserts an entry in to the reorderBuffer for each rune
+// in dcomp. dcomp must be a sequence of decomposed UTF-8-encoded runes.
+// It flushes the buffer on each new segment start.
+func (rb *reorderBuffer) insertDecomposed(dcomp []byte) insertErr {
+ rb.tmpBytes.setBytes(dcomp)
+ for i := 0; i < len(dcomp); {
+ info := rb.f.info(rb.tmpBytes, i)
+ if info.BoundaryBefore() && rb.nrune > 0 && !rb.doFlush() {
+ return iShortDst
+ }
+ i += copy(rb.byte[rb.nbyte:], dcomp[i:i+int(info.size)])
+ rb.insertOrdered(info)
+ }
+ return iSuccess
+}
+
+// insertSingle inserts an entry in the reorderBuffer for the rune at
+// position i. info is the runeInfo for the rune at position i.
+func (rb *reorderBuffer) insertSingle(src input, i int, info Properties) {
+ src.copySlice(rb.byte[rb.nbyte:], i, i+int(info.size))
+ rb.insertOrdered(info)
+}
+
+// insertCGJ inserts a Combining Grapheme Joiner (0x034f) into rb.
+func (rb *reorderBuffer) insertCGJ() {
+ rb.insertSingle(input{str: GraphemeJoiner}, 0, Properties{size: uint8(len(GraphemeJoiner))})
+}
+
+// appendRune inserts a rune at the end of the buffer. It is used for Hangul.
+func (rb *reorderBuffer) appendRune(r rune) {
+ bn := rb.nbyte
+ sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
+ rb.nbyte += utf8.UTFMax
+ rb.rune[rb.nrune] = Properties{pos: bn, size: uint8(sz)}
+ rb.nrune++
+}
+
+// assignRune sets a rune at position pos. It is used for Hangul and recomposition.
+func (rb *reorderBuffer) assignRune(pos int, r rune) {
+ bn := rb.rune[pos].pos
+ sz := utf8.EncodeRune(rb.byte[bn:], rune(r))
+ rb.rune[pos] = Properties{pos: bn, size: uint8(sz)}
+}
+
+// runeAt returns the rune at position n. It is used for Hangul and recomposition.
+func (rb *reorderBuffer) runeAt(n int) rune {
+ inf := rb.rune[n]
+ r, _ := utf8.DecodeRune(rb.byte[inf.pos : inf.pos+inf.size])
+ return r
+}
+
+// bytesAt returns the UTF-8 encoding of the rune at position n.
+// It is used for Hangul and recomposition.
+func (rb *reorderBuffer) bytesAt(n int) []byte {
+ inf := rb.rune[n]
+ return rb.byte[inf.pos : int(inf.pos)+int(inf.size)]
+}
+
+// For Hangul we combine algorithmically, instead of using tables.
+const (
+ hangulBase = 0xAC00 // UTF-8(hangulBase) -> EA B0 80
+ hangulBase0 = 0xEA
+ hangulBase1 = 0xB0
+ hangulBase2 = 0x80
+
+ hangulEnd = hangulBase + jamoLVTCount // UTF-8(0xD7A4) -> ED 9E A4
+ hangulEnd0 = 0xED
+ hangulEnd1 = 0x9E
+ hangulEnd2 = 0xA4
+
+ jamoLBase = 0x1100 // UTF-8(jamoLBase) -> E1 84 00
+ jamoLBase0 = 0xE1
+ jamoLBase1 = 0x84
+ jamoLEnd = 0x1113
+ jamoVBase = 0x1161
+ jamoVEnd = 0x1176
+ jamoTBase = 0x11A7
+ jamoTEnd = 0x11C3
+
+ jamoTCount = 28
+ jamoVCount = 21
+ jamoVTCount = 21 * 28
+ jamoLVTCount = 19 * 21 * 28
+)
+
+const hangulUTF8Size = 3
+
+func isHangul(b []byte) bool {
+ if len(b) < hangulUTF8Size {
+ return false
+ }
+ b0 := b[0]
+ if b0 < hangulBase0 {
+ return false
+ }
+ b1 := b[1]
+ switch {
+ case b0 == hangulBase0:
+ return b1 >= hangulBase1
+ case b0 < hangulEnd0:
+ return true
+ case b0 > hangulEnd0:
+ return false
+ case b1 < hangulEnd1:
+ return true
+ }
+ return b1 == hangulEnd1 && b[2] < hangulEnd2
+}
+
+func isHangulString(b string) bool {
+ if len(b) < hangulUTF8Size {
+ return false
+ }
+ b0 := b[0]
+ if b0 < hangulBase0 {
+ return false
+ }
+ b1 := b[1]
+ switch {
+ case b0 == hangulBase0:
+ return b1 >= hangulBase1
+ case b0 < hangulEnd0:
+ return true
+ case b0 > hangulEnd0:
+ return false
+ case b1 < hangulEnd1:
+ return true
+ }
+ return b1 == hangulEnd1 && b[2] < hangulEnd2
+}
+
+// Caller must ensure len(b) >= 2.
+func isJamoVT(b []byte) bool {
+ // True if (rune & 0xff00) == jamoLBase
+ return b[0] == jamoLBase0 && (b[1]&0xFC) == jamoLBase1
+}
+
+func isHangulWithoutJamoT(b []byte) bool {
+ c, _ := utf8.DecodeRune(b)
+ c -= hangulBase
+ return c < jamoLVTCount && c%jamoTCount == 0
+}
+
+// decomposeHangul writes the decomposed Hangul to buf and returns the number
+// of bytes written. len(buf) should be at least 9.
+func decomposeHangul(buf []byte, r rune) int {
+ const JamoUTF8Len = 3
+ r -= hangulBase
+ x := r % jamoTCount
+ r /= jamoTCount
+ utf8.EncodeRune(buf, jamoLBase+r/jamoVCount)
+ utf8.EncodeRune(buf[JamoUTF8Len:], jamoVBase+r%jamoVCount)
+ if x != 0 {
+ utf8.EncodeRune(buf[2*JamoUTF8Len:], jamoTBase+x)
+ return 3 * JamoUTF8Len
+ }
+ return 2 * JamoUTF8Len
+}
+
+// decomposeHangul algorithmically decomposes a Hangul rune into
+// its Jamo components.
+// See http://unicode.org/reports/tr15/#Hangul for details on decomposing Hangul.
+func (rb *reorderBuffer) decomposeHangul(r rune) {
+ r -= hangulBase
+ x := r % jamoTCount
+ r /= jamoTCount
+ rb.appendRune(jamoLBase + r/jamoVCount)
+ rb.appendRune(jamoVBase + r%jamoVCount)
+ if x != 0 {
+ rb.appendRune(jamoTBase + x)
+ }
+}
+
+// combineHangul algorithmically combines Jamo character components into Hangul.
+// See http://unicode.org/reports/tr15/#Hangul for details on combining Hangul.
+func (rb *reorderBuffer) combineHangul(s, i, k int) {
+ b := rb.rune[:]
+ bn := rb.nrune
+ for ; i < bn; i++ {
+ cccB := b[k-1].ccc
+ cccC := b[i].ccc
+ if cccB == 0 {
+ s = k - 1
+ }
+ if s != k-1 && cccB >= cccC {
+ // b[i] is blocked by greater-equal cccX below it
+ b[k] = b[i]
+ k++
+ } else {
+ l := rb.runeAt(s) // also used to compare to hangulBase
+ v := rb.runeAt(i) // also used to compare to jamoT
+ switch {
+ case jamoLBase <= l && l < jamoLEnd &&
+ jamoVBase <= v && v < jamoVEnd:
+ // 11xx plus 116x to LV
+ rb.assignRune(s, hangulBase+
+ (l-jamoLBase)*jamoVTCount+(v-jamoVBase)*jamoTCount)
+ case hangulBase <= l && l < hangulEnd &&
+ jamoTBase < v && v < jamoTEnd &&
+ ((l-hangulBase)%jamoTCount) == 0:
+ // ACxx plus 11Ax to LVT
+ rb.assignRune(s, l+v-jamoTBase)
+ default:
+ b[k] = b[i]
+ k++
+ }
+ }
+ }
+ rb.nrune = k
+}
+
+// compose recombines the runes in the buffer.
+// It should only be used to recompose a single segment, as it will not
+// handle alternations between Hangul and non-Hangul characters correctly.
+func (rb *reorderBuffer) compose() {
+ // UAX #15, section X5 , including Corrigendum #5
+ // "In any character sequence beginning with starter S, a character C is
+ // blocked from S if and only if there is some character B between S
+ // and C, and either B is a starter or it has the same or higher
+ // combining class as C."
+ bn := rb.nrune
+ if bn == 0 {
+ return
+ }
+ k := 1
+ b := rb.rune[:]
+ for s, i := 0, 1; i < bn; i++ {
+ if isJamoVT(rb.bytesAt(i)) {
+ // Redo from start in Hangul mode. Necessary to support
+ // U+320E..U+321E in NFKC mode.
+ rb.combineHangul(s, i, k)
+ return
+ }
+ ii := b[i]
+ // We can only use combineForward as a filter if we later
+ // get the info for the combined character. This is more
+ // expensive than using the filter. Using combinesBackward()
+ // is safe.
+ if ii.combinesBackward() {
+ cccB := b[k-1].ccc
+ cccC := ii.ccc
+ blocked := false // b[i] blocked by starter or greater or equal CCC?
+ if cccB == 0 {
+ s = k - 1
+ } else {
+ blocked = s != k-1 && cccB >= cccC
+ }
+ if !blocked {
+ combined := combine(rb.runeAt(s), rb.runeAt(i))
+ if combined != 0 {
+ rb.assignRune(s, combined)
+ continue
+ }
+ }
+ }
+ b[k] = b[i]
+ k++
+ }
+ rb.nrune = k
+}
diff --git a/libgo/go/golang_org/x/text/unicode/norm/forminfo.go b/libgo/go/golang_org/x/text/unicode/norm/forminfo.go
new file mode 100644
index 00000000000..15a67c653a3
--- /dev/null
+++ b/libgo/go/golang_org/x/text/unicode/norm/forminfo.go
@@ -0,0 +1,256 @@
+// 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 norm
+
+// This file contains Form-specific logic and wrappers for data in tables.go.
+
+// Rune info is stored in a separate trie per composing form. A composing form
+// and its corresponding decomposing form share the same trie. Each trie maps
+// a rune to a uint16. The values take two forms. For v >= 0x8000:
+// bits
+// 15: 1 (inverse of NFD_QD bit of qcInfo)
+// 13..7: qcInfo (see below). isYesD is always true (no decompostion).
+// 6..0: ccc (compressed CCC value).
+// For v < 0x8000, the respective rune has a decomposition and v is an index
+// into a byte array of UTF-8 decomposition sequences and additional info and
+// has the form:
+// <header> <decomp_byte>* [<tccc> [<lccc>]]
+// The header contains the number of bytes in the decomposition (excluding this
+// length byte). The two most significant bits of this length byte correspond
+// to bit 5 and 4 of qcInfo (see below). The byte sequence itself starts at v+1.
+// The byte sequence is followed by a trailing and leading CCC if the values
+// for these are not zero. The value of v determines which ccc are appended
+// to the sequences. For v < firstCCC, there are none, for v >= firstCCC,
+// the sequence is followed by a trailing ccc, and for v >= firstLeadingCC
+// there is an additional leading ccc. The value of tccc itself is the
+// trailing CCC shifted left 2 bits. The two least-significant bits of tccc
+// are the number of trailing non-starters.
+
+const (
+ qcInfoMask = 0x3F // to clear all but the relevant bits in a qcInfo
+ headerLenMask = 0x3F // extract the length value from the header byte
+ headerFlagsMask = 0xC0 // extract the qcInfo bits from the header byte
+)
+
+// Properties provides access to normalization properties of a rune.
+type Properties struct {
+ pos uint8 // start position in reorderBuffer; used in composition.go
+ size uint8 // length of UTF-8 encoding of this rune
+ ccc uint8 // leading canonical combining class (ccc if not decomposition)
+ tccc uint8 // trailing canonical combining class (ccc if not decomposition)
+ nLead uint8 // number of leading non-starters.
+ flags qcInfo // quick check flags
+ index uint16
+}
+
+// functions dispatchable per form
+type lookupFunc func(b input, i int) Properties
+
+// formInfo holds Form-specific functions and tables.
+type formInfo struct {
+ form Form
+ composing, compatibility bool // form type
+ info lookupFunc
+ nextMain iterFunc
+}
+
+var formTable []*formInfo
+
+func init() {
+ formTable = make([]*formInfo, 4)
+
+ for i := range formTable {
+ f := &formInfo{}
+ formTable[i] = f
+ f.form = Form(i)
+ if Form(i) == NFKD || Form(i) == NFKC {
+ f.compatibility = true
+ f.info = lookupInfoNFKC
+ } else {
+ f.info = lookupInfoNFC
+ }
+ f.nextMain = nextDecomposed
+ if Form(i) == NFC || Form(i) == NFKC {
+ f.nextMain = nextComposed
+ f.composing = true
+ }
+ }
+}
+
+// We do not distinguish between boundaries for NFC, NFD, etc. to avoid
+// unexpected behavior for the user. For example, in NFD, there is a boundary
+// after 'a'. However, 'a' might combine with modifiers, so from the application's
+// perspective it is not a good boundary. We will therefore always use the
+// boundaries for the combining variants.
+
+// BoundaryBefore returns true if this rune starts a new segment and
+// cannot combine with any rune on the left.
+func (p Properties) BoundaryBefore() bool {
+ if p.ccc == 0 && !p.combinesBackward() {
+ return true
+ }
+ // We assume that the CCC of the first character in a decomposition
+ // is always non-zero if different from info.ccc and that we can return
+ // false at this point. This is verified by maketables.
+ return false
+}
+
+// BoundaryAfter returns true if runes cannot combine with or otherwise
+// interact with this or previous runes.
+func (p Properties) BoundaryAfter() bool {
+ // TODO: loosen these conditions.
+ return p.isInert()
+}
+
+// We pack quick check data in 4 bits:
+// 5: Combines forward (0 == false, 1 == true)
+// 4..3: NFC_QC Yes(00), No (10), or Maybe (11)
+// 2: NFD_QC Yes (0) or No (1). No also means there is a decomposition.
+// 1..0: Number of trailing non-starters.
+//
+// When all 4 bits are zero, the character is inert, meaning it is never
+// influenced by normalization.
+type qcInfo uint8
+
+func (p Properties) isYesC() bool { return p.flags&0x10 == 0 }
+func (p Properties) isYesD() bool { return p.flags&0x4 == 0 }
+
+func (p Properties) combinesForward() bool { return p.flags&0x20 != 0 }
+func (p Properties) combinesBackward() bool { return p.flags&0x8 != 0 } // == isMaybe
+func (p Properties) hasDecomposition() bool { return p.flags&0x4 != 0 } // == isNoD
+
+func (p Properties) isInert() bool {
+ return p.flags&qcInfoMask == 0 && p.ccc == 0
+}
+
+func (p Properties) multiSegment() bool {
+ return p.index >= firstMulti && p.index < endMulti
+}
+
+func (p Properties) nLeadingNonStarters() uint8 {
+ return p.nLead
+}
+
+func (p Properties) nTrailingNonStarters() uint8 {
+ return uint8(p.flags & 0x03)
+}
+
+// Decomposition returns the decomposition for the underlying rune
+// or nil if there is none.
+func (p Properties) Decomposition() []byte {
+ // TODO: create the decomposition for Hangul?
+ if p.index == 0 {
+ return nil
+ }
+ i := p.index
+ n := decomps[i] & headerLenMask
+ i++
+ return decomps[i : i+uint16(n)]
+}
+
+// Size returns the length of UTF-8 encoding of the rune.
+func (p Properties) Size() int {
+ return int(p.size)
+}
+
+// CCC returns the canonical combining class of the underlying rune.
+func (p Properties) CCC() uint8 {
+ if p.index >= firstCCCZeroExcept {
+ return 0
+ }
+ return ccc[p.ccc]
+}
+
+// LeadCCC returns the CCC of the first rune in the decomposition.
+// If there is no decomposition, LeadCCC equals CCC.
+func (p Properties) LeadCCC() uint8 {
+ return ccc[p.ccc]
+}
+
+// TrailCCC returns the CCC of the last rune in the decomposition.
+// If there is no decomposition, TrailCCC equals CCC.
+func (p Properties) TrailCCC() uint8 {
+ return ccc[p.tccc]
+}
+
+// Recomposition
+// We use 32-bit keys instead of 64-bit for the two codepoint keys.
+// This clips off the bits of three entries, but we know this will not
+// result in a collision. In the unlikely event that changes to
+// UnicodeData.txt introduce collisions, the compiler will catch it.
+// Note that the recomposition map for NFC and NFKC are identical.
+
+// combine returns the combined rune or 0 if it doesn't exist.
+func combine(a, b rune) rune {
+ key := uint32(uint16(a))<<16 + uint32(uint16(b))
+ return recompMap[key]
+}
+
+func lookupInfoNFC(b input, i int) Properties {
+ v, sz := b.charinfoNFC(i)
+ return compInfo(v, sz)
+}
+
+func lookupInfoNFKC(b input, i int) Properties {
+ v, sz := b.charinfoNFKC(i)
+ return compInfo(v, sz)
+}
+
+// Properties returns properties for the first rune in s.
+func (f Form) Properties(s []byte) Properties {
+ if f == NFC || f == NFD {
+ return compInfo(nfcData.lookup(s))
+ }
+ return compInfo(nfkcData.lookup(s))
+}
+
+// PropertiesString returns properties for the first rune in s.
+func (f Form) PropertiesString(s string) Properties {
+ if f == NFC || f == NFD {
+ return compInfo(nfcData.lookupString(s))
+ }
+ return compInfo(nfkcData.lookupString(s))
+}
+
+// compInfo converts the information contained in v and sz
+// to a Properties. See the comment at the top of the file
+// for more information on the format.
+func compInfo(v uint16, sz int) Properties {
+ if v == 0 {
+ return Properties{size: uint8(sz)}
+ } else if v >= 0x8000 {
+ p := Properties{
+ size: uint8(sz),
+ ccc: uint8(v),
+ tccc: uint8(v),
+ flags: qcInfo(v >> 8),
+ }
+ if p.ccc > 0 || p.combinesBackward() {
+ p.nLead = uint8(p.flags & 0x3)
+ }
+ return p
+ }
+ // has decomposition
+ h := decomps[v]
+ f := (qcInfo(h&headerFlagsMask) >> 2) | 0x4
+ p := Properties{size: uint8(sz), flags: f, index: v}
+ if v >= firstCCC {
+ v += uint16(h&headerLenMask) + 1
+ c := decomps[v]
+ p.tccc = c >> 2
+ p.flags |= qcInfo(c & 0x3)
+ if v >= firstLeadingCCC {
+ p.nLead = c & 0x3
+ if v >= firstStarterWithNLead {
+ // We were tricked. Remove the decomposition.
+ p.flags &= 0x03
+ p.index = 0
+ return p
+ }
+ p.ccc = decomps[v+1]
+ }
+ }
+ return p
+}
diff --git a/libgo/go/golang_org/x/text/unicode/norm/input.go b/libgo/go/golang_org/x/text/unicode/norm/input.go
new file mode 100644
index 00000000000..045d4ccce2e
--- /dev/null
+++ b/libgo/go/golang_org/x/text/unicode/norm/input.go
@@ -0,0 +1,105 @@
+// 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 norm
+
+import "unicode/utf8"
+
+type input struct {
+ str string
+ bytes []byte
+}
+
+func inputBytes(str []byte) input {
+ return input{bytes: str}
+}
+
+func inputString(str string) input {
+ return input{str: str}
+}
+
+func (in *input) setBytes(str []byte) {
+ in.str = ""
+ in.bytes = str
+}
+
+func (in *input) setString(str string) {
+ in.str = str
+ in.bytes = nil
+}
+
+func (in *input) _byte(p int) byte {
+ if in.bytes == nil {
+ return in.str[p]
+ }
+ return in.bytes[p]
+}
+
+func (in *input) skipASCII(p, max int) int {
+ if in.bytes == nil {
+ for ; p < max && in.str[p] < utf8.RuneSelf; p++ {
+ }
+ } else {
+ for ; p < max && in.bytes[p] < utf8.RuneSelf; p++ {
+ }
+ }
+ return p
+}
+
+func (in *input) skipContinuationBytes(p int) int {
+ if in.bytes == nil {
+ for ; p < len(in.str) && !utf8.RuneStart(in.str[p]); p++ {
+ }
+ } else {
+ for ; p < len(in.bytes) && !utf8.RuneStart(in.bytes[p]); p++ {
+ }
+ }
+ return p
+}
+
+func (in *input) appendSlice(buf []byte, b, e int) []byte {
+ if in.bytes != nil {
+ return append(buf, in.bytes[b:e]...)
+ }
+ for i := b; i < e; i++ {
+ buf = append(buf, in.str[i])
+ }
+ return buf
+}
+
+func (in *input) copySlice(buf []byte, b, e int) int {
+ if in.bytes == nil {
+ return copy(buf, in.str[b:e])
+ }
+ return copy(buf, in.bytes[b:e])
+}
+
+func (in *input) charinfoNFC(p int) (uint16, int) {
+ if in.bytes == nil {
+ return nfcData.lookupString(in.str[p:])
+ }
+ return nfcData.lookup(in.bytes[p:])
+}
+
+func (in *input) charinfoNFKC(p int) (uint16, int) {
+ if in.bytes == nil {
+ return nfkcData.lookupString(in.str[p:])
+ }
+ return nfkcData.lookup(in.bytes[p:])
+}
+
+func (in *input) hangul(p int) (r rune) {
+ if in.bytes == nil {
+ if !isHangulString(in.str[p:]) {
+ return 0
+ }
+ r, _ = utf8.DecodeRuneInString(in.str[p:])
+ } else {
+ if !isHangul(in.bytes[p:]) {
+ return 0
+ }
+ r, _ = utf8.DecodeRune(in.bytes[p:])
+ }
+ return r
+}
diff --git a/libgo/go/golang_org/x/text/unicode/norm/iter.go b/libgo/go/golang_org/x/text/unicode/norm/iter.go
new file mode 100644
index 00000000000..0a42a72de81
--- /dev/null
+++ b/libgo/go/golang_org/x/text/unicode/norm/iter.go
@@ -0,0 +1,450 @@
+// 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 norm
+
+import (
+ "fmt"
+ "unicode/utf8"
+)
+
+// MaxSegmentSize is the maximum size of a byte buffer needed to consider any
+// sequence of starter and non-starter runes for the purpose of normalization.
+const MaxSegmentSize = maxByteBufferSize
+
+// An Iter iterates over a string or byte slice, while normalizing it
+// to a given Form.
+type Iter struct {
+ rb reorderBuffer
+ buf [maxByteBufferSize]byte
+ info Properties // first character saved from previous iteration
+ next iterFunc // implementation of next depends on form
+ asciiF iterFunc
+
+ p int // current position in input source
+ multiSeg []byte // remainder of multi-segment decomposition
+}
+
+type iterFunc func(*Iter) []byte
+
+// Init initializes i to iterate over src after normalizing it to Form f.
+func (i *Iter) Init(f Form, src []byte) {
+ i.p = 0
+ if len(src) == 0 {
+ i.setDone()
+ i.rb.nsrc = 0
+ return
+ }
+ i.multiSeg = nil
+ i.rb.init(f, src)
+ i.next = i.rb.f.nextMain
+ i.asciiF = nextASCIIBytes
+ i.info = i.rb.f.info(i.rb.src, i.p)
+}
+
+// InitString initializes i to iterate over src after normalizing it to Form f.
+func (i *Iter) InitString(f Form, src string) {
+ i.p = 0
+ if len(src) == 0 {
+ i.setDone()
+ i.rb.nsrc = 0
+ return
+ }
+ i.multiSeg = nil
+ i.rb.initString(f, src)
+ i.next = i.rb.f.nextMain
+ i.asciiF = nextASCIIString
+ i.info = i.rb.f.info(i.rb.src, i.p)
+}
+
+// Seek sets the segment to be returned by the next call to Next to start
+// at position p. It is the responsibility of the caller to set p to the
+// start of a UTF8 rune.
+func (i *Iter) Seek(offset int64, whence int) (int64, error) {
+ var abs int64
+ switch whence {
+ case 0:
+ abs = offset
+ case 1:
+ abs = int64(i.p) + offset
+ case 2:
+ abs = int64(i.rb.nsrc) + offset
+ default:
+ return 0, fmt.Errorf("norm: invalid whence")
+ }
+ if abs < 0 {
+ return 0, fmt.Errorf("norm: negative position")
+ }
+ if int(abs) >= i.rb.nsrc {
+ i.setDone()
+ return int64(i.p), nil
+ }
+ i.p = int(abs)
+ i.multiSeg = nil
+ i.next = i.rb.f.nextMain
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ return abs, nil
+}
+
+// returnSlice returns a slice of the underlying input type as a byte slice.
+// If the underlying is of type []byte, it will simply return a slice.
+// If the underlying is of type string, it will copy the slice to the buffer
+// and return that.
+func (i *Iter) returnSlice(a, b int) []byte {
+ if i.rb.src.bytes == nil {
+ return i.buf[:copy(i.buf[:], i.rb.src.str[a:b])]
+ }
+ return i.rb.src.bytes[a:b]
+}
+
+// Pos returns the byte position at which the next call to Next will commence processing.
+func (i *Iter) Pos() int {
+ return i.p
+}
+
+func (i *Iter) setDone() {
+ i.next = nextDone
+ i.p = i.rb.nsrc
+}
+
+// Done returns true if there is no more input to process.
+func (i *Iter) Done() bool {
+ return i.p >= i.rb.nsrc
+}
+
+// Next returns f(i.input[i.Pos():n]), where n is a boundary of i.input.
+// For any input a and b for which f(a) == f(b), subsequent calls
+// to Next will return the same segments.
+// Modifying runes are grouped together with the preceding starter, if such a starter exists.
+// Although not guaranteed, n will typically be the smallest possible n.
+func (i *Iter) Next() []byte {
+ return i.next(i)
+}
+
+func nextASCIIBytes(i *Iter) []byte {
+ p := i.p + 1
+ if p >= i.rb.nsrc {
+ i.setDone()
+ return i.rb.src.bytes[i.p:p]
+ }
+ if i.rb.src.bytes[p] < utf8.RuneSelf {
+ p0 := i.p
+ i.p = p
+ return i.rb.src.bytes[p0:p]
+ }
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ i.next = i.rb.f.nextMain
+ return i.next(i)
+}
+
+func nextASCIIString(i *Iter) []byte {
+ p := i.p + 1
+ if p >= i.rb.nsrc {
+ i.buf[0] = i.rb.src.str[i.p]
+ i.setDone()
+ return i.buf[:1]
+ }
+ if i.rb.src.str[p] < utf8.RuneSelf {
+ i.buf[0] = i.rb.src.str[i.p]
+ i.p = p
+ return i.buf[:1]
+ }
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ i.next = i.rb.f.nextMain
+ return i.next(i)
+}
+
+func nextHangul(i *Iter) []byte {
+ p := i.p
+ next := p + hangulUTF8Size
+ if next >= i.rb.nsrc {
+ i.setDone()
+ } else if i.rb.src.hangul(next) == 0 {
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ i.next = i.rb.f.nextMain
+ return i.next(i)
+ }
+ i.p = next
+ return i.buf[:decomposeHangul(i.buf[:], i.rb.src.hangul(p))]
+}
+
+func nextDone(i *Iter) []byte {
+ return nil
+}
+
+// nextMulti is used for iterating over multi-segment decompositions
+// for decomposing normal forms.
+func nextMulti(i *Iter) []byte {
+ j := 0
+ d := i.multiSeg
+ // skip first rune
+ for j = 1; j < len(d) && !utf8.RuneStart(d[j]); j++ {
+ }
+ for j < len(d) {
+ info := i.rb.f.info(input{bytes: d}, j)
+ if info.BoundaryBefore() {
+ i.multiSeg = d[j:]
+ return d[:j]
+ }
+ j += int(info.size)
+ }
+ // treat last segment as normal decomposition
+ i.next = i.rb.f.nextMain
+ return i.next(i)
+}
+
+// nextMultiNorm is used for iterating over multi-segment decompositions
+// for composing normal forms.
+func nextMultiNorm(i *Iter) []byte {
+ j := 0
+ d := i.multiSeg
+ for j < len(d) {
+ info := i.rb.f.info(input{bytes: d}, j)
+ if info.BoundaryBefore() {
+ i.rb.compose()
+ seg := i.buf[:i.rb.flushCopy(i.buf[:])]
+ i.rb.ss.first(info)
+ i.rb.insertUnsafe(input{bytes: d}, j, info)
+ i.multiSeg = d[j+int(info.size):]
+ return seg
+ }
+ i.rb.ss.next(info)
+ i.rb.insertUnsafe(input{bytes: d}, j, info)
+ j += int(info.size)
+ }
+ i.multiSeg = nil
+ i.next = nextComposed
+ return doNormComposed(i)
+}
+
+// nextDecomposed is the implementation of Next for forms NFD and NFKD.
+func nextDecomposed(i *Iter) (next []byte) {
+ outp := 0
+ inCopyStart, outCopyStart := i.p, 0
+ ss := mkStreamSafe(i.info)
+ for {
+ if sz := int(i.info.size); sz <= 1 {
+ p := i.p
+ i.p++ // ASCII or illegal byte. Either way, advance by 1.
+ if i.p >= i.rb.nsrc {
+ i.setDone()
+ return i.returnSlice(p, i.p)
+ } else if i.rb.src._byte(i.p) < utf8.RuneSelf {
+ i.next = i.asciiF
+ return i.returnSlice(p, i.p)
+ }
+ outp++
+ } else if d := i.info.Decomposition(); d != nil {
+ // Note: If leading CCC != 0, then len(d) == 2 and last is also non-zero.
+ // Case 1: there is a leftover to copy. In this case the decomposition
+ // must begin with a modifier and should always be appended.
+ // Case 2: no leftover. Simply return d if followed by a ccc == 0 value.
+ p := outp + len(d)
+ if outp > 0 {
+ i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
+ if p > len(i.buf) {
+ return i.buf[:outp]
+ }
+ } else if i.info.multiSegment() {
+ // outp must be 0 as multi-segment decompositions always
+ // start a new segment.
+ if i.multiSeg == nil {
+ i.multiSeg = d
+ i.next = nextMulti
+ return nextMulti(i)
+ }
+ // We are in the last segment. Treat as normal decomposition.
+ d = i.multiSeg
+ i.multiSeg = nil
+ p = len(d)
+ }
+ prevCC := i.info.tccc
+ if i.p += sz; i.p >= i.rb.nsrc {
+ i.setDone()
+ i.info = Properties{} // Force BoundaryBefore to succeed.
+ } else {
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ }
+ switch ss.next(i.info) {
+ case ssOverflow:
+ i.next = nextCGJDecompose
+ fallthrough
+ case ssStarter:
+ if outp > 0 {
+ copy(i.buf[outp:], d)
+ return i.buf[:p]
+ }
+ return d
+ }
+ copy(i.buf[outp:], d)
+ outp = p
+ inCopyStart, outCopyStart = i.p, outp
+ if i.info.ccc < prevCC {
+ goto doNorm
+ }
+ continue
+ } else if r := i.rb.src.hangul(i.p); r != 0 {
+ outp = decomposeHangul(i.buf[:], r)
+ i.p += hangulUTF8Size
+ inCopyStart, outCopyStart = i.p, outp
+ if i.p >= i.rb.nsrc {
+ i.setDone()
+ break
+ } else if i.rb.src.hangul(i.p) != 0 {
+ i.next = nextHangul
+ return i.buf[:outp]
+ }
+ } else {
+ p := outp + sz
+ if p > len(i.buf) {
+ break
+ }
+ outp = p
+ i.p += sz
+ }
+ if i.p >= i.rb.nsrc {
+ i.setDone()
+ break
+ }
+ prevCC := i.info.tccc
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ if v := ss.next(i.info); v == ssStarter {
+ break
+ } else if v == ssOverflow {
+ i.next = nextCGJDecompose
+ break
+ }
+ if i.info.ccc < prevCC {
+ goto doNorm
+ }
+ }
+ if outCopyStart == 0 {
+ return i.returnSlice(inCopyStart, i.p)
+ } else if inCopyStart < i.p {
+ i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
+ }
+ return i.buf[:outp]
+doNorm:
+ // Insert what we have decomposed so far in the reorderBuffer.
+ // As we will only reorder, there will always be enough room.
+ i.rb.src.copySlice(i.buf[outCopyStart:], inCopyStart, i.p)
+ i.rb.insertDecomposed(i.buf[0:outp])
+ return doNormDecomposed(i)
+}
+
+func doNormDecomposed(i *Iter) []byte {
+ for {
+ if s := i.rb.ss.next(i.info); s == ssOverflow {
+ i.next = nextCGJDecompose
+ break
+ }
+ i.rb.insertUnsafe(i.rb.src, i.p, i.info)
+ if i.p += int(i.info.size); i.p >= i.rb.nsrc {
+ i.setDone()
+ break
+ }
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ if i.info.ccc == 0 {
+ break
+ }
+ }
+ // new segment or too many combining characters: exit normalization
+ return i.buf[:i.rb.flushCopy(i.buf[:])]
+}
+
+func nextCGJDecompose(i *Iter) []byte {
+ i.rb.ss = 0
+ i.rb.insertCGJ()
+ i.next = nextDecomposed
+ buf := doNormDecomposed(i)
+ return buf
+}
+
+// nextComposed is the implementation of Next for forms NFC and NFKC.
+func nextComposed(i *Iter) []byte {
+ outp, startp := 0, i.p
+ var prevCC uint8
+ ss := mkStreamSafe(i.info)
+ for {
+ if !i.info.isYesC() {
+ goto doNorm
+ }
+ prevCC = i.info.tccc
+ sz := int(i.info.size)
+ if sz == 0 {
+ sz = 1 // illegal rune: copy byte-by-byte
+ }
+ p := outp + sz
+ if p > len(i.buf) {
+ break
+ }
+ outp = p
+ i.p += sz
+ if i.p >= i.rb.nsrc {
+ i.setDone()
+ break
+ } else if i.rb.src._byte(i.p) < utf8.RuneSelf {
+ i.next = i.asciiF
+ break
+ }
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ if v := ss.next(i.info); v == ssStarter {
+ break
+ } else if v == ssOverflow {
+ i.next = nextCGJCompose
+ break
+ }
+ if i.info.ccc < prevCC {
+ goto doNorm
+ }
+ }
+ return i.returnSlice(startp, i.p)
+doNorm:
+ i.p = startp
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ if i.info.multiSegment() {
+ d := i.info.Decomposition()
+ info := i.rb.f.info(input{bytes: d}, 0)
+ i.rb.insertUnsafe(input{bytes: d}, 0, info)
+ i.multiSeg = d[int(info.size):]
+ i.next = nextMultiNorm
+ return nextMultiNorm(i)
+ }
+ i.rb.ss.first(i.info)
+ i.rb.insertUnsafe(i.rb.src, i.p, i.info)
+ return doNormComposed(i)
+}
+
+func doNormComposed(i *Iter) []byte {
+ // First rune should already be inserted.
+ for {
+ if i.p += int(i.info.size); i.p >= i.rb.nsrc {
+ i.setDone()
+ break
+ }
+ i.info = i.rb.f.info(i.rb.src, i.p)
+ if s := i.rb.ss.next(i.info); s == ssStarter {
+ break
+ } else if s == ssOverflow {
+ i.next = nextCGJCompose
+ break
+ }
+ i.rb.insertUnsafe(i.rb.src, i.p, i.info)
+ }
+ i.rb.compose()
+ seg := i.buf[:i.rb.flushCopy(i.buf[:])]
+ return seg
+}
+
+func nextCGJCompose(i *Iter) []byte {
+ i.rb.ss = 0 // instead of first
+ i.rb.insertCGJ()
+ i.next = nextComposed
+ // Note that we treat any rune with nLeadingNonStarters > 0 as a non-starter,
+ // even if they are not. This is particularly dubious for U+FF9E and UFF9A.
+ // If we ever change that, insert a check here.
+ i.rb.ss.first(i.info)
+ i.rb.insertUnsafe(i.rb.src, i.p, i.info)
+ return doNormComposed(i)
+}
diff --git a/libgo/go/golang_org/x/text/unicode/norm/normalize.go b/libgo/go/golang_org/x/text/unicode/norm/normalize.go
new file mode 100644
index 00000000000..15c962e2e9f
--- /dev/null
+++ b/libgo/go/golang_org/x/text/unicode/norm/normalize.go
@@ -0,0 +1,608 @@
+// 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.
+
+//go:generate go run maketables.go triegen.go
+//go:generate go run maketables.go triegen.go -test
+
+// Package norm contains types and functions for normalizing Unicode strings.
+package norm // import "golang.org/x/text/unicode/norm"
+
+import (
+ "unicode/utf8"
+
+ "golang_org/x/text/transform"
+)
+
+// A Form denotes a canonical representation of Unicode code points.
+// The Unicode-defined normalization and equivalence forms are:
+//
+// NFC Unicode Normalization Form C
+// NFD Unicode Normalization Form D
+// NFKC Unicode Normalization Form KC
+// NFKD Unicode Normalization Form KD
+//
+// For a Form f, this documentation uses the notation f(x) to mean
+// the bytes or string x converted to the given form.
+// A position n in x is called a boundary if conversion to the form can
+// proceed independently on both sides:
+// f(x) == append(f(x[0:n]), f(x[n:])...)
+//
+// References: http://unicode.org/reports/tr15/ and
+// http://unicode.org/notes/tn5/.
+type Form int
+
+const (
+ NFC Form = iota
+ NFD
+ NFKC
+ NFKD
+)
+
+// Bytes returns f(b). May return b if f(b) = b.
+func (f Form) Bytes(b []byte) []byte {
+ src := inputBytes(b)
+ ft := formTable[f]
+ n, ok := ft.quickSpan(src, 0, len(b), true)
+ if ok {
+ return b
+ }
+ out := make([]byte, n, len(b))
+ copy(out, b[0:n])
+ rb := reorderBuffer{f: *ft, src: src, nsrc: len(b), out: out, flushF: appendFlush}
+ return doAppendInner(&rb, n)
+}
+
+// String returns f(s).
+func (f Form) String(s string) string {
+ src := inputString(s)
+ ft := formTable[f]
+ n, ok := ft.quickSpan(src, 0, len(s), true)
+ if ok {
+ return s
+ }
+ out := make([]byte, n, len(s))
+ copy(out, s[0:n])
+ rb := reorderBuffer{f: *ft, src: src, nsrc: len(s), out: out, flushF: appendFlush}
+ return string(doAppendInner(&rb, n))
+}
+
+// IsNormal returns true if b == f(b).
+func (f Form) IsNormal(b []byte) bool {
+ src := inputBytes(b)
+ ft := formTable[f]
+ bp, ok := ft.quickSpan(src, 0, len(b), true)
+ if ok {
+ return true
+ }
+ rb := reorderBuffer{f: *ft, src: src, nsrc: len(b)}
+ rb.setFlusher(nil, cmpNormalBytes)
+ for bp < len(b) {
+ rb.out = b[bp:]
+ if bp = decomposeSegment(&rb, bp, true); bp < 0 {
+ return false
+ }
+ bp, _ = rb.f.quickSpan(rb.src, bp, len(b), true)
+ }
+ return true
+}
+
+func cmpNormalBytes(rb *reorderBuffer) bool {
+ b := rb.out
+ for i := 0; i < rb.nrune; i++ {
+ info := rb.rune[i]
+ if int(info.size) > len(b) {
+ return false
+ }
+ p := info.pos
+ pe := p + info.size
+ for ; p < pe; p++ {
+ if b[0] != rb.byte[p] {
+ return false
+ }
+ b = b[1:]
+ }
+ }
+ return true
+}
+
+// IsNormalString returns true if s == f(s).
+func (f Form) IsNormalString(s string) bool {
+ src := inputString(s)
+ ft := formTable[f]
+ bp, ok := ft.quickSpan(src, 0, len(s), true)
+ if ok {
+ return true
+ }
+ rb := reorderBuffer{f: *ft, src: src, nsrc: len(s)}
+ rb.setFlusher(nil, func(rb *reorderBuffer) bool {
+ for i := 0; i < rb.nrune; i++ {
+ info := rb.rune[i]
+ if bp+int(info.size) > len(s) {
+ return false
+ }
+ p := info.pos
+ pe := p + info.size
+ for ; p < pe; p++ {
+ if s[bp] != rb.byte[p] {
+ return false
+ }
+ bp++
+ }
+ }
+ return true
+ })
+ for bp < len(s) {
+ if bp = decomposeSegment(&rb, bp, true); bp < 0 {
+ return false
+ }
+ bp, _ = rb.f.quickSpan(rb.src, bp, len(s), true)
+ }
+ return true
+}
+
+// patchTail fixes a case where a rune may be incorrectly normalized
+// if it is followed by illegal continuation bytes. It returns the
+// patched buffer and whether the decomposition is still in progress.
+func patchTail(rb *reorderBuffer) bool {
+ info, p := lastRuneStart(&rb.f, rb.out)
+ if p == -1 || info.size == 0 {
+ return true
+ }
+ end := p + int(info.size)
+ extra := len(rb.out) - end
+ if extra > 0 {
+ // Potentially allocating memory. However, this only
+ // happens with ill-formed UTF-8.
+ x := make([]byte, 0)
+ x = append(x, rb.out[len(rb.out)-extra:]...)
+ rb.out = rb.out[:end]
+ decomposeToLastBoundary(rb)
+ rb.doFlush()
+ rb.out = append(rb.out, x...)
+ return false
+ }
+ buf := rb.out[p:]
+ rb.out = rb.out[:p]
+ decomposeToLastBoundary(rb)
+ if s := rb.ss.next(info); s == ssStarter {
+ rb.doFlush()
+ rb.ss.first(info)
+ } else if s == ssOverflow {
+ rb.doFlush()
+ rb.insertCGJ()
+ rb.ss = 0
+ }
+ rb.insertUnsafe(inputBytes(buf), 0, info)
+ return true
+}
+
+func appendQuick(rb *reorderBuffer, i int) int {
+ if rb.nsrc == i {
+ return i
+ }
+ end, _ := rb.f.quickSpan(rb.src, i, rb.nsrc, true)
+ rb.out = rb.src.appendSlice(rb.out, i, end)
+ return end
+}
+
+// Append returns f(append(out, b...)).
+// The buffer out must be nil, empty, or equal to f(out).
+func (f Form) Append(out []byte, src ...byte) []byte {
+ return f.doAppend(out, inputBytes(src), len(src))
+}
+
+func (f Form) doAppend(out []byte, src input, n int) []byte {
+ if n == 0 {
+ return out
+ }
+ ft := formTable[f]
+ // Attempt to do a quickSpan first so we can avoid initializing the reorderBuffer.
+ if len(out) == 0 {
+ p, _ := ft.quickSpan(src, 0, n, true)
+ out = src.appendSlice(out, 0, p)
+ if p == n {
+ return out
+ }
+ rb := reorderBuffer{f: *ft, src: src, nsrc: n, out: out, flushF: appendFlush}
+ return doAppendInner(&rb, p)
+ }
+ rb := reorderBuffer{f: *ft, src: src, nsrc: n}
+ return doAppend(&rb, out, 0)
+}
+
+func doAppend(rb *reorderBuffer, out []byte, p int) []byte {
+ rb.setFlusher(out, appendFlush)
+ src, n := rb.src, rb.nsrc
+ doMerge := len(out) > 0
+ if q := src.skipContinuationBytes(p); q > p {
+ // Move leading non-starters to destination.
+ rb.out = src.appendSlice(rb.out, p, q)
+ p = q
+ doMerge = patchTail(rb)
+ }
+ fd := &rb.f
+ if doMerge {
+ var info Properties
+ if p < n {
+ info = fd.info(src, p)
+ if !info.BoundaryBefore() || info.nLeadingNonStarters() > 0 {
+ if p == 0 {
+ decomposeToLastBoundary(rb)
+ }
+ p = decomposeSegment(rb, p, true)
+ }
+ }
+ if info.size == 0 {
+ rb.doFlush()
+ // Append incomplete UTF-8 encoding.
+ return src.appendSlice(rb.out, p, n)
+ }
+ if rb.nrune > 0 {
+ return doAppendInner(rb, p)
+ }
+ }
+ p = appendQuick(rb, p)
+ return doAppendInner(rb, p)
+}
+
+func doAppendInner(rb *reorderBuffer, p int) []byte {
+ for n := rb.nsrc; p < n; {
+ p = decomposeSegment(rb, p, true)
+ p = appendQuick(rb, p)
+ }
+ return rb.out
+}
+
+// AppendString returns f(append(out, []byte(s))).
+// The buffer out must be nil, empty, or equal to f(out).
+func (f Form) AppendString(out []byte, src string) []byte {
+ return f.doAppend(out, inputString(src), len(src))
+}
+
+// QuickSpan returns a boundary n such that b[0:n] == f(b[0:n]).
+// It is not guaranteed to return the largest such n.
+func (f Form) QuickSpan(b []byte) int {
+ n, _ := formTable[f].quickSpan(inputBytes(b), 0, len(b), true)
+ return n
+}
+
+// Span implements transform.SpanningTransformer. It returns a boundary n such
+// that b[0:n] == f(b[0:n]). It is not guaranteed to return the largest such n.
+func (f Form) Span(b []byte, atEOF bool) (n int, err error) {
+ n, ok := formTable[f].quickSpan(inputBytes(b), 0, len(b), atEOF)
+ if n < len(b) {
+ if !ok {
+ err = transform.ErrEndOfSpan
+ } else {
+ err = transform.ErrShortSrc
+ }
+ }
+ return n, err
+}
+
+// SpanString returns a boundary n such that s[0:n] == f(s[0:n]).
+// It is not guaranteed to return the largest such n.
+func (f Form) SpanString(s string, atEOF bool) (n int, err error) {
+ n, ok := formTable[f].quickSpan(inputString(s), 0, len(s), atEOF)
+ if n < len(s) {
+ if !ok {
+ err = transform.ErrEndOfSpan
+ } else {
+ err = transform.ErrShortSrc
+ }
+ }
+ return n, err
+}
+
+// quickSpan returns a boundary n such that src[0:n] == f(src[0:n]) and
+// whether any non-normalized parts were found. If atEOF is false, n will
+// not point past the last segment if this segment might be become
+// non-normalized by appending other runes.
+func (f *formInfo) quickSpan(src input, i, end int, atEOF bool) (n int, ok bool) {
+ var lastCC uint8
+ ss := streamSafe(0)
+ lastSegStart := i
+ for n = end; i < n; {
+ if j := src.skipASCII(i, n); i != j {
+ i = j
+ lastSegStart = i - 1
+ lastCC = 0
+ ss = 0
+ continue
+ }
+ info := f.info(src, i)
+ if info.size == 0 {
+ if atEOF {
+ // include incomplete runes
+ return n, true
+ }
+ return lastSegStart, true
+ }
+ // This block needs to be before the next, because it is possible to
+ // have an overflow for runes that are starters (e.g. with U+FF9E).
+ switch ss.next(info) {
+ case ssStarter:
+ ss.first(info)
+ lastSegStart = i
+ case ssOverflow:
+ return lastSegStart, false
+ case ssSuccess:
+ if lastCC > info.ccc {
+ return lastSegStart, false
+ }
+ }
+ if f.composing {
+ if !info.isYesC() {
+ break
+ }
+ } else {
+ if !info.isYesD() {
+ break
+ }
+ }
+ lastCC = info.ccc
+ i += int(info.size)
+ }
+ if i == n {
+ if !atEOF {
+ n = lastSegStart
+ }
+ return n, true
+ }
+ return lastSegStart, false
+}
+
+// QuickSpanString returns a boundary n such that s[0:n] == f(s[0:n]).
+// It is not guaranteed to return the largest such n.
+func (f Form) QuickSpanString(s string) int {
+ n, _ := formTable[f].quickSpan(inputString(s), 0, len(s), true)
+ return n
+}
+
+// FirstBoundary returns the position i of the first boundary in b
+// or -1 if b contains no boundary.
+func (f Form) FirstBoundary(b []byte) int {
+ return f.firstBoundary(inputBytes(b), len(b))
+}
+
+func (f Form) firstBoundary(src input, nsrc int) int {
+ i := src.skipContinuationBytes(0)
+ if i >= nsrc {
+ return -1
+ }
+ fd := formTable[f]
+ ss := streamSafe(0)
+ // We should call ss.first here, but we can't as the first rune is
+ // skipped already. This means FirstBoundary can't really determine
+ // CGJ insertion points correctly. Luckily it doesn't have to.
+ for {
+ info := fd.info(src, i)
+ if info.size == 0 {
+ return -1
+ }
+ if s := ss.next(info); s != ssSuccess {
+ return i
+ }
+ i += int(info.size)
+ if i >= nsrc {
+ if !info.BoundaryAfter() && !ss.isMax() {
+ return -1
+ }
+ return nsrc
+ }
+ }
+}
+
+// FirstBoundaryInString returns the position i of the first boundary in s
+// or -1 if s contains no boundary.
+func (f Form) FirstBoundaryInString(s string) int {
+ return f.firstBoundary(inputString(s), len(s))
+}
+
+// NextBoundary reports the index of the boundary between the first and next
+// segment in b or -1 if atEOF is false and there are not enough bytes to
+// determine this boundary.
+func (f Form) NextBoundary(b []byte, atEOF bool) int {
+ return f.nextBoundary(inputBytes(b), len(b), atEOF)
+}
+
+// NextBoundaryInString reports the index of the boundary between the first and
+// next segment in b or -1 if atEOF is false and there are not enough bytes to
+// determine this boundary.
+func (f Form) NextBoundaryInString(s string, atEOF bool) int {
+ return f.nextBoundary(inputString(s), len(s), atEOF)
+}
+
+func (f Form) nextBoundary(src input, nsrc int, atEOF bool) int {
+ if nsrc == 0 {
+ if atEOF {
+ return 0
+ }
+ return -1
+ }
+ fd := formTable[f]
+ info := fd.info(src, 0)
+ if info.size == 0 {
+ if atEOF {
+ return 1
+ }
+ return -1
+ }
+ ss := streamSafe(0)
+ ss.first(info)
+
+ for i := int(info.size); i < nsrc; i += int(info.size) {
+ info = fd.info(src, i)
+ if info.size == 0 {
+ if atEOF {
+ return i
+ }
+ return -1
+ }
+ if s := ss.next(info); s != ssSuccess {
+ return i
+ }
+ }
+ if !atEOF && !info.BoundaryAfter() && !ss.isMax() {
+ return -1
+ }
+ return nsrc
+}
+
+// LastBoundary returns the position i of the last boundary in b
+// or -1 if b contains no boundary.
+func (f Form) LastBoundary(b []byte) int {
+ return lastBoundary(formTable[f], b)
+}
+
+func lastBoundary(fd *formInfo, b []byte) int {
+ i := len(b)
+ info, p := lastRuneStart(fd, b)
+ if p == -1 {
+ return -1
+ }
+ if info.size == 0 { // ends with incomplete rune
+ if p == 0 { // starts with incomplete rune
+ return -1
+ }
+ i = p
+ info, p = lastRuneStart(fd, b[:i])
+ if p == -1 { // incomplete UTF-8 encoding or non-starter bytes without a starter
+ return i
+ }
+ }
+ if p+int(info.size) != i { // trailing non-starter bytes: illegal UTF-8
+ return i
+ }
+ if info.BoundaryAfter() {
+ return i
+ }
+ ss := streamSafe(0)
+ v := ss.backwards(info)
+ for i = p; i >= 0 && v != ssStarter; i = p {
+ info, p = lastRuneStart(fd, b[:i])
+ if v = ss.backwards(info); v == ssOverflow {
+ break
+ }
+ if p+int(info.size) != i {
+ if p == -1 { // no boundary found
+ return -1
+ }
+ return i // boundary after an illegal UTF-8 encoding
+ }
+ }
+ return i
+}
+
+// decomposeSegment scans the first segment in src into rb. It inserts 0x034f
+// (Grapheme Joiner) when it encounters a sequence of more than 30 non-starters
+// and returns the number of bytes consumed from src or iShortDst or iShortSrc.
+func decomposeSegment(rb *reorderBuffer, sp int, atEOF bool) int {
+ // Force one character to be consumed.
+ info := rb.f.info(rb.src, sp)
+ if info.size == 0 {
+ return 0
+ }
+ if rb.nrune > 0 {
+ if s := rb.ss.next(info); s == ssStarter {
+ goto end
+ } else if s == ssOverflow {
+ rb.insertCGJ()
+ goto end
+ }
+ } else {
+ rb.ss.first(info)
+ }
+ if err := rb.insertFlush(rb.src, sp, info); err != iSuccess {
+ return int(err)
+ }
+ for {
+ sp += int(info.size)
+ if sp >= rb.nsrc {
+ if !atEOF && !info.BoundaryAfter() {
+ return int(iShortSrc)
+ }
+ break
+ }
+ info = rb.f.info(rb.src, sp)
+ if info.size == 0 {
+ if !atEOF {
+ return int(iShortSrc)
+ }
+ break
+ }
+ if s := rb.ss.next(info); s == ssStarter {
+ break
+ } else if s == ssOverflow {
+ rb.insertCGJ()
+ break
+ }
+ if err := rb.insertFlush(rb.src, sp, info); err != iSuccess {
+ return int(err)
+ }
+ }
+end:
+ if !rb.doFlush() {
+ return int(iShortDst)
+ }
+ return sp
+}
+
+// lastRuneStart returns the runeInfo and position of the last
+// rune in buf or the zero runeInfo and -1 if no rune was found.
+func lastRuneStart(fd *formInfo, buf []byte) (Properties, int) {
+ p := len(buf) - 1
+ for ; p >= 0 && !utf8.RuneStart(buf[p]); p-- {
+ }
+ if p < 0 {
+ return Properties{}, -1
+ }
+ return fd.info(inputBytes(buf), p), p
+}
+
+// decomposeToLastBoundary finds an open segment at the end of the buffer
+// and scans it into rb. Returns the buffer minus the last segment.
+func decomposeToLastBoundary(rb *reorderBuffer) {
+ fd := &rb.f
+ info, i := lastRuneStart(fd, rb.out)
+ if int(info.size) != len(rb.out)-i {
+ // illegal trailing continuation bytes
+ return
+ }
+ if info.BoundaryAfter() {
+ return
+ }
+ var add [maxNonStarters + 1]Properties // stores runeInfo in reverse order
+ padd := 0
+ ss := streamSafe(0)
+ p := len(rb.out)
+ for {
+ add[padd] = info
+ v := ss.backwards(info)
+ if v == ssOverflow {
+ // Note that if we have an overflow, it the string we are appending to
+ // is not correctly normalized. In this case the behavior is undefined.
+ break
+ }
+ padd++
+ p -= int(info.size)
+ if v == ssStarter || p < 0 {
+ break
+ }
+ info, i = lastRuneStart(fd, rb.out[:p])
+ if int(info.size) != p-i {
+ break
+ }
+ }
+ rb.ss = ss
+ // Copy bytes for insertion as we may need to overwrite rb.out.
+ var buf [maxBufferSize * utf8.UTFMax]byte
+ cp := buf[:copy(buf[:], rb.out[p:])]
+ rb.out = rb.out[:p]
+ for padd--; padd >= 0; padd-- {
+ info = add[padd]
+ rb.insertUnsafe(inputBytes(cp), 0, info)
+ cp = cp[info.size:]
+ }
+}
diff --git a/libgo/go/golang_org/x/text/unicode/norm/readwriter.go b/libgo/go/golang_org/x/text/unicode/norm/readwriter.go
new file mode 100644
index 00000000000..d926ee903e5
--- /dev/null
+++ b/libgo/go/golang_org/x/text/unicode/norm/readwriter.go
@@ -0,0 +1,125 @@
+// 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 norm
+
+import "io"
+
+type normWriter struct {
+ rb reorderBuffer
+ w io.Writer
+ buf []byte
+}
+
+// Write implements the standard write interface. If the last characters are
+// not at a normalization boundary, the bytes will be buffered for the next
+// write. The remaining bytes will be written on close.
+func (w *normWriter) Write(data []byte) (n int, err error) {
+ // Process data in pieces to keep w.buf size bounded.
+ const chunk = 4000
+
+ for len(data) > 0 {
+ // Normalize into w.buf.
+ m := len(data)
+ if m > chunk {
+ m = chunk
+ }
+ w.rb.src = inputBytes(data[:m])
+ w.rb.nsrc = m
+ w.buf = doAppend(&w.rb, w.buf, 0)
+ data = data[m:]
+ n += m
+
+ // Write out complete prefix, save remainder.
+ // Note that lastBoundary looks back at most 31 runes.
+ i := lastBoundary(&w.rb.f, w.buf)
+ if i == -1 {
+ i = 0
+ }
+ if i > 0 {
+ if _, err = w.w.Write(w.buf[:i]); err != nil {
+ break
+ }
+ bn := copy(w.buf, w.buf[i:])
+ w.buf = w.buf[:bn]
+ }
+ }
+ return n, err
+}
+
+// Close forces data that remains in the buffer to be written.
+func (w *normWriter) Close() error {
+ if len(w.buf) > 0 {
+ _, err := w.w.Write(w.buf)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Writer returns a new writer that implements Write(b)
+// by writing f(b) to w. The returned writer may use an
+// an internal buffer to maintain state across Write calls.
+// Calling its Close method writes any buffered data to w.
+func (f Form) Writer(w io.Writer) io.WriteCloser {
+ wr := &normWriter{rb: reorderBuffer{}, w: w}
+ wr.rb.init(f, nil)
+ return wr
+}
+
+type normReader struct {
+ rb reorderBuffer
+ r io.Reader
+ inbuf []byte
+ outbuf []byte
+ bufStart int
+ lastBoundary int
+ err error
+}
+
+// Read implements the standard read interface.
+func (r *normReader) Read(p []byte) (int, error) {
+ for {
+ if r.lastBoundary-r.bufStart > 0 {
+ n := copy(p, r.outbuf[r.bufStart:r.lastBoundary])
+ r.bufStart += n
+ if r.lastBoundary-r.bufStart > 0 {
+ return n, nil
+ }
+ return n, r.err
+ }
+ if r.err != nil {
+ return 0, r.err
+ }
+ outn := copy(r.outbuf, r.outbuf[r.lastBoundary:])
+ r.outbuf = r.outbuf[0:outn]
+ r.bufStart = 0
+
+ n, err := r.r.Read(r.inbuf)
+ r.rb.src = inputBytes(r.inbuf[0:n])
+ r.rb.nsrc, r.err = n, err
+ if n > 0 {
+ r.outbuf = doAppend(&r.rb, r.outbuf, 0)
+ }
+ if err == io.EOF {
+ r.lastBoundary = len(r.outbuf)
+ } else {
+ r.lastBoundary = lastBoundary(&r.rb.f, r.outbuf)
+ if r.lastBoundary == -1 {
+ r.lastBoundary = 0
+ }
+ }
+ }
+}
+
+// Reader returns a new reader that implements Read
+// by reading data from r and returning f(data).
+func (f Form) Reader(r io.Reader) io.Reader {
+ const chunk = 4000
+ buf := make([]byte, chunk)
+ rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf}
+ rr.rb.init(f, buf)
+ return rr
+}
diff --git a/libgo/go/golang_org/x/text/unicode/norm/tables.go b/libgo/go/golang_org/x/text/unicode/norm/tables.go
new file mode 100644
index 00000000000..a56697b571b
--- /dev/null
+++ b/libgo/go/golang_org/x/text/unicode/norm/tables.go
@@ -0,0 +1,7627 @@
+// This file was generated by go generate; DO NOT EDIT
+
+package norm
+
+const (
+ // Version is the Unicode edition from which the tables are derived.
+ Version = "9.0.0"
+
+ // MaxTransformChunkSize indicates the maximum number of bytes that Transform
+ // may need to write atomically for any Form. Making a destination buffer at
+ // least this size ensures that Transform can always make progress and that
+ // the user does not need to grow the buffer on an ErrShortDst.
+ MaxTransformChunkSize = 35 + maxNonStarters*4
+)
+
+var ccc = [55]uint8{
+ 0, 1, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36,
+ 84, 91, 103, 107, 118, 122, 129, 130,
+ 132, 202, 214, 216, 218, 220, 222, 224,
+ 226, 228, 230, 232, 233, 234, 240,
+}
+
+const (
+ firstMulti = 0x186D
+ firstCCC = 0x2C9E
+ endMulti = 0x2F60
+ firstLeadingCCC = 0x4A44
+ firstCCCZeroExcept = 0x4A5A
+ firstStarterWithNLead = 0x4A81
+ lastDecomp = 0x4A83
+ maxDecomp = 0x8000
+)
+
+// decomps: 19075 bytes
+var decomps = [...]byte{
+ // Bytes 0 - 3f
+ 0x00, 0x41, 0x20, 0x41, 0x21, 0x41, 0x22, 0x41,
+ 0x23, 0x41, 0x24, 0x41, 0x25, 0x41, 0x26, 0x41,
+ 0x27, 0x41, 0x28, 0x41, 0x29, 0x41, 0x2A, 0x41,
+ 0x2B, 0x41, 0x2C, 0x41, 0x2D, 0x41, 0x2E, 0x41,
+ 0x2F, 0x41, 0x30, 0x41, 0x31, 0x41, 0x32, 0x41,
+ 0x33, 0x41, 0x34, 0x41, 0x35, 0x41, 0x36, 0x41,
+ 0x37, 0x41, 0x38, 0x41, 0x39, 0x41, 0x3A, 0x41,
+ 0x3B, 0x41, 0x3C, 0x41, 0x3D, 0x41, 0x3E, 0x41,
+ // Bytes 40 - 7f
+ 0x3F, 0x41, 0x40, 0x41, 0x41, 0x41, 0x42, 0x41,
+ 0x43, 0x41, 0x44, 0x41, 0x45, 0x41, 0x46, 0x41,
+ 0x47, 0x41, 0x48, 0x41, 0x49, 0x41, 0x4A, 0x41,
+ 0x4B, 0x41, 0x4C, 0x41, 0x4D, 0x41, 0x4E, 0x41,
+ 0x4F, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41,
+ 0x53, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41,
+ 0x57, 0x41, 0x58, 0x41, 0x59, 0x41, 0x5A, 0x41,
+ 0x5B, 0x41, 0x5C, 0x41, 0x5D, 0x41, 0x5E, 0x41,
+ // Bytes 80 - bf
+ 0x5F, 0x41, 0x60, 0x41, 0x61, 0x41, 0x62, 0x41,
+ 0x63, 0x41, 0x64, 0x41, 0x65, 0x41, 0x66, 0x41,
+ 0x67, 0x41, 0x68, 0x41, 0x69, 0x41, 0x6A, 0x41,
+ 0x6B, 0x41, 0x6C, 0x41, 0x6D, 0x41, 0x6E, 0x41,
+ 0x6F, 0x41, 0x70, 0x41, 0x71, 0x41, 0x72, 0x41,
+ 0x73, 0x41, 0x74, 0x41, 0x75, 0x41, 0x76, 0x41,
+ 0x77, 0x41, 0x78, 0x41, 0x79, 0x41, 0x7A, 0x41,
+ 0x7B, 0x41, 0x7C, 0x41, 0x7D, 0x41, 0x7E, 0x42,
+ // Bytes c0 - ff
+ 0xC2, 0xA2, 0x42, 0xC2, 0xA3, 0x42, 0xC2, 0xA5,
+ 0x42, 0xC2, 0xA6, 0x42, 0xC2, 0xAC, 0x42, 0xC2,
+ 0xB7, 0x42, 0xC3, 0x86, 0x42, 0xC3, 0xB0, 0x42,
+ 0xC4, 0xA6, 0x42, 0xC4, 0xA7, 0x42, 0xC4, 0xB1,
+ 0x42, 0xC5, 0x8B, 0x42, 0xC5, 0x93, 0x42, 0xC6,
+ 0x8E, 0x42, 0xC6, 0x90, 0x42, 0xC6, 0xAB, 0x42,
+ 0xC8, 0xA2, 0x42, 0xC8, 0xB7, 0x42, 0xC9, 0x90,
+ 0x42, 0xC9, 0x91, 0x42, 0xC9, 0x92, 0x42, 0xC9,
+ // Bytes 100 - 13f
+ 0x94, 0x42, 0xC9, 0x95, 0x42, 0xC9, 0x99, 0x42,
+ 0xC9, 0x9B, 0x42, 0xC9, 0x9C, 0x42, 0xC9, 0x9F,
+ 0x42, 0xC9, 0xA1, 0x42, 0xC9, 0xA3, 0x42, 0xC9,
+ 0xA5, 0x42, 0xC9, 0xA6, 0x42, 0xC9, 0xA8, 0x42,
+ 0xC9, 0xA9, 0x42, 0xC9, 0xAA, 0x42, 0xC9, 0xAB,
+ 0x42, 0xC9, 0xAD, 0x42, 0xC9, 0xAF, 0x42, 0xC9,
+ 0xB0, 0x42, 0xC9, 0xB1, 0x42, 0xC9, 0xB2, 0x42,
+ 0xC9, 0xB3, 0x42, 0xC9, 0xB4, 0x42, 0xC9, 0xB5,
+ // Bytes 140 - 17f
+ 0x42, 0xC9, 0xB8, 0x42, 0xC9, 0xB9, 0x42, 0xC9,
+ 0xBB, 0x42, 0xCA, 0x81, 0x42, 0xCA, 0x82, 0x42,
+ 0xCA, 0x83, 0x42, 0xCA, 0x89, 0x42, 0xCA, 0x8A,
+ 0x42, 0xCA, 0x8B, 0x42, 0xCA, 0x8C, 0x42, 0xCA,
+ 0x90, 0x42, 0xCA, 0x91, 0x42, 0xCA, 0x92, 0x42,
+ 0xCA, 0x95, 0x42, 0xCA, 0x9D, 0x42, 0xCA, 0x9F,
+ 0x42, 0xCA, 0xB9, 0x42, 0xCE, 0x91, 0x42, 0xCE,
+ 0x92, 0x42, 0xCE, 0x93, 0x42, 0xCE, 0x94, 0x42,
+ // Bytes 180 - 1bf
+ 0xCE, 0x95, 0x42, 0xCE, 0x96, 0x42, 0xCE, 0x97,
+ 0x42, 0xCE, 0x98, 0x42, 0xCE, 0x99, 0x42, 0xCE,
+ 0x9A, 0x42, 0xCE, 0x9B, 0x42, 0xCE, 0x9C, 0x42,
+ 0xCE, 0x9D, 0x42, 0xCE, 0x9E, 0x42, 0xCE, 0x9F,
+ 0x42, 0xCE, 0xA0, 0x42, 0xCE, 0xA1, 0x42, 0xCE,
+ 0xA3, 0x42, 0xCE, 0xA4, 0x42, 0xCE, 0xA5, 0x42,
+ 0xCE, 0xA6, 0x42, 0xCE, 0xA7, 0x42, 0xCE, 0xA8,
+ 0x42, 0xCE, 0xA9, 0x42, 0xCE, 0xB1, 0x42, 0xCE,
+ // Bytes 1c0 - 1ff
+ 0xB2, 0x42, 0xCE, 0xB3, 0x42, 0xCE, 0xB4, 0x42,
+ 0xCE, 0xB5, 0x42, 0xCE, 0xB6, 0x42, 0xCE, 0xB7,
+ 0x42, 0xCE, 0xB8, 0x42, 0xCE, 0xB9, 0x42, 0xCE,
+ 0xBA, 0x42, 0xCE, 0xBB, 0x42, 0xCE, 0xBC, 0x42,
+ 0xCE, 0xBD, 0x42, 0xCE, 0xBE, 0x42, 0xCE, 0xBF,
+ 0x42, 0xCF, 0x80, 0x42, 0xCF, 0x81, 0x42, 0xCF,
+ 0x82, 0x42, 0xCF, 0x83, 0x42, 0xCF, 0x84, 0x42,
+ 0xCF, 0x85, 0x42, 0xCF, 0x86, 0x42, 0xCF, 0x87,
+ // Bytes 200 - 23f
+ 0x42, 0xCF, 0x88, 0x42, 0xCF, 0x89, 0x42, 0xCF,
+ 0x9C, 0x42, 0xCF, 0x9D, 0x42, 0xD0, 0xBD, 0x42,
+ 0xD1, 0x8A, 0x42, 0xD1, 0x8C, 0x42, 0xD7, 0x90,
+ 0x42, 0xD7, 0x91, 0x42, 0xD7, 0x92, 0x42, 0xD7,
+ 0x93, 0x42, 0xD7, 0x94, 0x42, 0xD7, 0x9B, 0x42,
+ 0xD7, 0x9C, 0x42, 0xD7, 0x9D, 0x42, 0xD7, 0xA2,
+ 0x42, 0xD7, 0xA8, 0x42, 0xD7, 0xAA, 0x42, 0xD8,
+ 0xA1, 0x42, 0xD8, 0xA7, 0x42, 0xD8, 0xA8, 0x42,
+ // Bytes 240 - 27f
+ 0xD8, 0xA9, 0x42, 0xD8, 0xAA, 0x42, 0xD8, 0xAB,
+ 0x42, 0xD8, 0xAC, 0x42, 0xD8, 0xAD, 0x42, 0xD8,
+ 0xAE, 0x42, 0xD8, 0xAF, 0x42, 0xD8, 0xB0, 0x42,
+ 0xD8, 0xB1, 0x42, 0xD8, 0xB2, 0x42, 0xD8, 0xB3,
+ 0x42, 0xD8, 0xB4, 0x42, 0xD8, 0xB5, 0x42, 0xD8,
+ 0xB6, 0x42, 0xD8, 0xB7, 0x42, 0xD8, 0xB8, 0x42,
+ 0xD8, 0xB9, 0x42, 0xD8, 0xBA, 0x42, 0xD9, 0x81,
+ 0x42, 0xD9, 0x82, 0x42, 0xD9, 0x83, 0x42, 0xD9,
+ // Bytes 280 - 2bf
+ 0x84, 0x42, 0xD9, 0x85, 0x42, 0xD9, 0x86, 0x42,
+ 0xD9, 0x87, 0x42, 0xD9, 0x88, 0x42, 0xD9, 0x89,
+ 0x42, 0xD9, 0x8A, 0x42, 0xD9, 0xAE, 0x42, 0xD9,
+ 0xAF, 0x42, 0xD9, 0xB1, 0x42, 0xD9, 0xB9, 0x42,
+ 0xD9, 0xBA, 0x42, 0xD9, 0xBB, 0x42, 0xD9, 0xBE,
+ 0x42, 0xD9, 0xBF, 0x42, 0xDA, 0x80, 0x42, 0xDA,
+ 0x83, 0x42, 0xDA, 0x84, 0x42, 0xDA, 0x86, 0x42,
+ 0xDA, 0x87, 0x42, 0xDA, 0x88, 0x42, 0xDA, 0x8C,
+ // Bytes 2c0 - 2ff
+ 0x42, 0xDA, 0x8D, 0x42, 0xDA, 0x8E, 0x42, 0xDA,
+ 0x91, 0x42, 0xDA, 0x98, 0x42, 0xDA, 0xA1, 0x42,
+ 0xDA, 0xA4, 0x42, 0xDA, 0xA6, 0x42, 0xDA, 0xA9,
+ 0x42, 0xDA, 0xAD, 0x42, 0xDA, 0xAF, 0x42, 0xDA,
+ 0xB1, 0x42, 0xDA, 0xB3, 0x42, 0xDA, 0xBA, 0x42,
+ 0xDA, 0xBB, 0x42, 0xDA, 0xBE, 0x42, 0xDB, 0x81,
+ 0x42, 0xDB, 0x85, 0x42, 0xDB, 0x86, 0x42, 0xDB,
+ 0x87, 0x42, 0xDB, 0x88, 0x42, 0xDB, 0x89, 0x42,
+ // Bytes 300 - 33f
+ 0xDB, 0x8B, 0x42, 0xDB, 0x8C, 0x42, 0xDB, 0x90,
+ 0x42, 0xDB, 0x92, 0x43, 0xE0, 0xBC, 0x8B, 0x43,
+ 0xE1, 0x83, 0x9C, 0x43, 0xE1, 0x84, 0x80, 0x43,
+ 0xE1, 0x84, 0x81, 0x43, 0xE1, 0x84, 0x82, 0x43,
+ 0xE1, 0x84, 0x83, 0x43, 0xE1, 0x84, 0x84, 0x43,
+ 0xE1, 0x84, 0x85, 0x43, 0xE1, 0x84, 0x86, 0x43,
+ 0xE1, 0x84, 0x87, 0x43, 0xE1, 0x84, 0x88, 0x43,
+ 0xE1, 0x84, 0x89, 0x43, 0xE1, 0x84, 0x8A, 0x43,
+ // Bytes 340 - 37f
+ 0xE1, 0x84, 0x8B, 0x43, 0xE1, 0x84, 0x8C, 0x43,
+ 0xE1, 0x84, 0x8D, 0x43, 0xE1, 0x84, 0x8E, 0x43,
+ 0xE1, 0x84, 0x8F, 0x43, 0xE1, 0x84, 0x90, 0x43,
+ 0xE1, 0x84, 0x91, 0x43, 0xE1, 0x84, 0x92, 0x43,
+ 0xE1, 0x84, 0x94, 0x43, 0xE1, 0x84, 0x95, 0x43,
+ 0xE1, 0x84, 0x9A, 0x43, 0xE1, 0x84, 0x9C, 0x43,
+ 0xE1, 0x84, 0x9D, 0x43, 0xE1, 0x84, 0x9E, 0x43,
+ 0xE1, 0x84, 0xA0, 0x43, 0xE1, 0x84, 0xA1, 0x43,
+ // Bytes 380 - 3bf
+ 0xE1, 0x84, 0xA2, 0x43, 0xE1, 0x84, 0xA3, 0x43,
+ 0xE1, 0x84, 0xA7, 0x43, 0xE1, 0x84, 0xA9, 0x43,
+ 0xE1, 0x84, 0xAB, 0x43, 0xE1, 0x84, 0xAC, 0x43,
+ 0xE1, 0x84, 0xAD, 0x43, 0xE1, 0x84, 0xAE, 0x43,
+ 0xE1, 0x84, 0xAF, 0x43, 0xE1, 0x84, 0xB2, 0x43,
+ 0xE1, 0x84, 0xB6, 0x43, 0xE1, 0x85, 0x80, 0x43,
+ 0xE1, 0x85, 0x87, 0x43, 0xE1, 0x85, 0x8C, 0x43,
+ 0xE1, 0x85, 0x97, 0x43, 0xE1, 0x85, 0x98, 0x43,
+ // Bytes 3c0 - 3ff
+ 0xE1, 0x85, 0x99, 0x43, 0xE1, 0x85, 0xA0, 0x43,
+ 0xE1, 0x86, 0x84, 0x43, 0xE1, 0x86, 0x85, 0x43,
+ 0xE1, 0x86, 0x88, 0x43, 0xE1, 0x86, 0x91, 0x43,
+ 0xE1, 0x86, 0x92, 0x43, 0xE1, 0x86, 0x94, 0x43,
+ 0xE1, 0x86, 0x9E, 0x43, 0xE1, 0x86, 0xA1, 0x43,
+ 0xE1, 0x87, 0x87, 0x43, 0xE1, 0x87, 0x88, 0x43,
+ 0xE1, 0x87, 0x8C, 0x43, 0xE1, 0x87, 0x8E, 0x43,
+ 0xE1, 0x87, 0x93, 0x43, 0xE1, 0x87, 0x97, 0x43,
+ // Bytes 400 - 43f
+ 0xE1, 0x87, 0x99, 0x43, 0xE1, 0x87, 0x9D, 0x43,
+ 0xE1, 0x87, 0x9F, 0x43, 0xE1, 0x87, 0xB1, 0x43,
+ 0xE1, 0x87, 0xB2, 0x43, 0xE1, 0xB4, 0x82, 0x43,
+ 0xE1, 0xB4, 0x96, 0x43, 0xE1, 0xB4, 0x97, 0x43,
+ 0xE1, 0xB4, 0x9C, 0x43, 0xE1, 0xB4, 0x9D, 0x43,
+ 0xE1, 0xB4, 0xA5, 0x43, 0xE1, 0xB5, 0xBB, 0x43,
+ 0xE1, 0xB6, 0x85, 0x43, 0xE2, 0x80, 0x82, 0x43,
+ 0xE2, 0x80, 0x83, 0x43, 0xE2, 0x80, 0x90, 0x43,
+ // Bytes 440 - 47f
+ 0xE2, 0x80, 0x93, 0x43, 0xE2, 0x80, 0x94, 0x43,
+ 0xE2, 0x82, 0xA9, 0x43, 0xE2, 0x86, 0x90, 0x43,
+ 0xE2, 0x86, 0x91, 0x43, 0xE2, 0x86, 0x92, 0x43,
+ 0xE2, 0x86, 0x93, 0x43, 0xE2, 0x88, 0x82, 0x43,
+ 0xE2, 0x88, 0x87, 0x43, 0xE2, 0x88, 0x91, 0x43,
+ 0xE2, 0x88, 0x92, 0x43, 0xE2, 0x94, 0x82, 0x43,
+ 0xE2, 0x96, 0xA0, 0x43, 0xE2, 0x97, 0x8B, 0x43,
+ 0xE2, 0xA6, 0x85, 0x43, 0xE2, 0xA6, 0x86, 0x43,
+ // Bytes 480 - 4bf
+ 0xE2, 0xB5, 0xA1, 0x43, 0xE3, 0x80, 0x81, 0x43,
+ 0xE3, 0x80, 0x82, 0x43, 0xE3, 0x80, 0x88, 0x43,
+ 0xE3, 0x80, 0x89, 0x43, 0xE3, 0x80, 0x8A, 0x43,
+ 0xE3, 0x80, 0x8B, 0x43, 0xE3, 0x80, 0x8C, 0x43,
+ 0xE3, 0x80, 0x8D, 0x43, 0xE3, 0x80, 0x8E, 0x43,
+ 0xE3, 0x80, 0x8F, 0x43, 0xE3, 0x80, 0x90, 0x43,
+ 0xE3, 0x80, 0x91, 0x43, 0xE3, 0x80, 0x92, 0x43,
+ 0xE3, 0x80, 0x94, 0x43, 0xE3, 0x80, 0x95, 0x43,
+ // Bytes 4c0 - 4ff
+ 0xE3, 0x80, 0x96, 0x43, 0xE3, 0x80, 0x97, 0x43,
+ 0xE3, 0x82, 0xA1, 0x43, 0xE3, 0x82, 0xA2, 0x43,
+ 0xE3, 0x82, 0xA3, 0x43, 0xE3, 0x82, 0xA4, 0x43,
+ 0xE3, 0x82, 0xA5, 0x43, 0xE3, 0x82, 0xA6, 0x43,
+ 0xE3, 0x82, 0xA7, 0x43, 0xE3, 0x82, 0xA8, 0x43,
+ 0xE3, 0x82, 0xA9, 0x43, 0xE3, 0x82, 0xAA, 0x43,
+ 0xE3, 0x82, 0xAB, 0x43, 0xE3, 0x82, 0xAD, 0x43,
+ 0xE3, 0x82, 0xAF, 0x43, 0xE3, 0x82, 0xB1, 0x43,
+ // Bytes 500 - 53f
+ 0xE3, 0x82, 0xB3, 0x43, 0xE3, 0x82, 0xB5, 0x43,
+ 0xE3, 0x82, 0xB7, 0x43, 0xE3, 0x82, 0xB9, 0x43,
+ 0xE3, 0x82, 0xBB, 0x43, 0xE3, 0x82, 0xBD, 0x43,
+ 0xE3, 0x82, 0xBF, 0x43, 0xE3, 0x83, 0x81, 0x43,
+ 0xE3, 0x83, 0x83, 0x43, 0xE3, 0x83, 0x84, 0x43,
+ 0xE3, 0x83, 0x86, 0x43, 0xE3, 0x83, 0x88, 0x43,
+ 0xE3, 0x83, 0x8A, 0x43, 0xE3, 0x83, 0x8B, 0x43,
+ 0xE3, 0x83, 0x8C, 0x43, 0xE3, 0x83, 0x8D, 0x43,
+ // Bytes 540 - 57f
+ 0xE3, 0x83, 0x8E, 0x43, 0xE3, 0x83, 0x8F, 0x43,
+ 0xE3, 0x83, 0x92, 0x43, 0xE3, 0x83, 0x95, 0x43,
+ 0xE3, 0x83, 0x98, 0x43, 0xE3, 0x83, 0x9B, 0x43,
+ 0xE3, 0x83, 0x9E, 0x43, 0xE3, 0x83, 0x9F, 0x43,
+ 0xE3, 0x83, 0xA0, 0x43, 0xE3, 0x83, 0xA1, 0x43,
+ 0xE3, 0x83, 0xA2, 0x43, 0xE3, 0x83, 0xA3, 0x43,
+ 0xE3, 0x83, 0xA4, 0x43, 0xE3, 0x83, 0xA5, 0x43,
+ 0xE3, 0x83, 0xA6, 0x43, 0xE3, 0x83, 0xA7, 0x43,
+ // Bytes 580 - 5bf
+ 0xE3, 0x83, 0xA8, 0x43, 0xE3, 0x83, 0xA9, 0x43,
+ 0xE3, 0x83, 0xAA, 0x43, 0xE3, 0x83, 0xAB, 0x43,
+ 0xE3, 0x83, 0xAC, 0x43, 0xE3, 0x83, 0xAD, 0x43,
+ 0xE3, 0x83, 0xAF, 0x43, 0xE3, 0x83, 0xB0, 0x43,
+ 0xE3, 0x83, 0xB1, 0x43, 0xE3, 0x83, 0xB2, 0x43,
+ 0xE3, 0x83, 0xB3, 0x43, 0xE3, 0x83, 0xBB, 0x43,
+ 0xE3, 0x83, 0xBC, 0x43, 0xE3, 0x92, 0x9E, 0x43,
+ 0xE3, 0x92, 0xB9, 0x43, 0xE3, 0x92, 0xBB, 0x43,
+ // Bytes 5c0 - 5ff
+ 0xE3, 0x93, 0x9F, 0x43, 0xE3, 0x94, 0x95, 0x43,
+ 0xE3, 0x9B, 0xAE, 0x43, 0xE3, 0x9B, 0xBC, 0x43,
+ 0xE3, 0x9E, 0x81, 0x43, 0xE3, 0xA0, 0xAF, 0x43,
+ 0xE3, 0xA1, 0xA2, 0x43, 0xE3, 0xA1, 0xBC, 0x43,
+ 0xE3, 0xA3, 0x87, 0x43, 0xE3, 0xA3, 0xA3, 0x43,
+ 0xE3, 0xA4, 0x9C, 0x43, 0xE3, 0xA4, 0xBA, 0x43,
+ 0xE3, 0xA8, 0xAE, 0x43, 0xE3, 0xA9, 0xAC, 0x43,
+ 0xE3, 0xAB, 0xA4, 0x43, 0xE3, 0xAC, 0x88, 0x43,
+ // Bytes 600 - 63f
+ 0xE3, 0xAC, 0x99, 0x43, 0xE3, 0xAD, 0x89, 0x43,
+ 0xE3, 0xAE, 0x9D, 0x43, 0xE3, 0xB0, 0x98, 0x43,
+ 0xE3, 0xB1, 0x8E, 0x43, 0xE3, 0xB4, 0xB3, 0x43,
+ 0xE3, 0xB6, 0x96, 0x43, 0xE3, 0xBA, 0xAC, 0x43,
+ 0xE3, 0xBA, 0xB8, 0x43, 0xE3, 0xBC, 0x9B, 0x43,
+ 0xE3, 0xBF, 0xBC, 0x43, 0xE4, 0x80, 0x88, 0x43,
+ 0xE4, 0x80, 0x98, 0x43, 0xE4, 0x80, 0xB9, 0x43,
+ 0xE4, 0x81, 0x86, 0x43, 0xE4, 0x82, 0x96, 0x43,
+ // Bytes 640 - 67f
+ 0xE4, 0x83, 0xA3, 0x43, 0xE4, 0x84, 0xAF, 0x43,
+ 0xE4, 0x88, 0x82, 0x43, 0xE4, 0x88, 0xA7, 0x43,
+ 0xE4, 0x8A, 0xA0, 0x43, 0xE4, 0x8C, 0x81, 0x43,
+ 0xE4, 0x8C, 0xB4, 0x43, 0xE4, 0x8D, 0x99, 0x43,
+ 0xE4, 0x8F, 0x95, 0x43, 0xE4, 0x8F, 0x99, 0x43,
+ 0xE4, 0x90, 0x8B, 0x43, 0xE4, 0x91, 0xAB, 0x43,
+ 0xE4, 0x94, 0xAB, 0x43, 0xE4, 0x95, 0x9D, 0x43,
+ 0xE4, 0x95, 0xA1, 0x43, 0xE4, 0x95, 0xAB, 0x43,
+ // Bytes 680 - 6bf
+ 0xE4, 0x97, 0x97, 0x43, 0xE4, 0x97, 0xB9, 0x43,
+ 0xE4, 0x98, 0xB5, 0x43, 0xE4, 0x9A, 0xBE, 0x43,
+ 0xE4, 0x9B, 0x87, 0x43, 0xE4, 0xA6, 0x95, 0x43,
+ 0xE4, 0xA7, 0xA6, 0x43, 0xE4, 0xA9, 0xAE, 0x43,
+ 0xE4, 0xA9, 0xB6, 0x43, 0xE4, 0xAA, 0xB2, 0x43,
+ 0xE4, 0xAC, 0xB3, 0x43, 0xE4, 0xAF, 0x8E, 0x43,
+ 0xE4, 0xB3, 0x8E, 0x43, 0xE4, 0xB3, 0xAD, 0x43,
+ 0xE4, 0xB3, 0xB8, 0x43, 0xE4, 0xB5, 0x96, 0x43,
+ // Bytes 6c0 - 6ff
+ 0xE4, 0xB8, 0x80, 0x43, 0xE4, 0xB8, 0x81, 0x43,
+ 0xE4, 0xB8, 0x83, 0x43, 0xE4, 0xB8, 0x89, 0x43,
+ 0xE4, 0xB8, 0x8A, 0x43, 0xE4, 0xB8, 0x8B, 0x43,
+ 0xE4, 0xB8, 0x8D, 0x43, 0xE4, 0xB8, 0x99, 0x43,
+ 0xE4, 0xB8, 0xA6, 0x43, 0xE4, 0xB8, 0xA8, 0x43,
+ 0xE4, 0xB8, 0xAD, 0x43, 0xE4, 0xB8, 0xB2, 0x43,
+ 0xE4, 0xB8, 0xB6, 0x43, 0xE4, 0xB8, 0xB8, 0x43,
+ 0xE4, 0xB8, 0xB9, 0x43, 0xE4, 0xB8, 0xBD, 0x43,
+ // Bytes 700 - 73f
+ 0xE4, 0xB8, 0xBF, 0x43, 0xE4, 0xB9, 0x81, 0x43,
+ 0xE4, 0xB9, 0x99, 0x43, 0xE4, 0xB9, 0x9D, 0x43,
+ 0xE4, 0xBA, 0x82, 0x43, 0xE4, 0xBA, 0x85, 0x43,
+ 0xE4, 0xBA, 0x86, 0x43, 0xE4, 0xBA, 0x8C, 0x43,
+ 0xE4, 0xBA, 0x94, 0x43, 0xE4, 0xBA, 0xA0, 0x43,
+ 0xE4, 0xBA, 0xA4, 0x43, 0xE4, 0xBA, 0xAE, 0x43,
+ 0xE4, 0xBA, 0xBA, 0x43, 0xE4, 0xBB, 0x80, 0x43,
+ 0xE4, 0xBB, 0x8C, 0x43, 0xE4, 0xBB, 0xA4, 0x43,
+ // Bytes 740 - 77f
+ 0xE4, 0xBC, 0x81, 0x43, 0xE4, 0xBC, 0x91, 0x43,
+ 0xE4, 0xBD, 0xA0, 0x43, 0xE4, 0xBE, 0x80, 0x43,
+ 0xE4, 0xBE, 0x86, 0x43, 0xE4, 0xBE, 0x8B, 0x43,
+ 0xE4, 0xBE, 0xAE, 0x43, 0xE4, 0xBE, 0xBB, 0x43,
+ 0xE4, 0xBE, 0xBF, 0x43, 0xE5, 0x80, 0x82, 0x43,
+ 0xE5, 0x80, 0xAB, 0x43, 0xE5, 0x81, 0xBA, 0x43,
+ 0xE5, 0x82, 0x99, 0x43, 0xE5, 0x83, 0x8F, 0x43,
+ 0xE5, 0x83, 0x9A, 0x43, 0xE5, 0x83, 0xA7, 0x43,
+ // Bytes 780 - 7bf
+ 0xE5, 0x84, 0xAA, 0x43, 0xE5, 0x84, 0xBF, 0x43,
+ 0xE5, 0x85, 0x80, 0x43, 0xE5, 0x85, 0x85, 0x43,
+ 0xE5, 0x85, 0x8D, 0x43, 0xE5, 0x85, 0x94, 0x43,
+ 0xE5, 0x85, 0xA4, 0x43, 0xE5, 0x85, 0xA5, 0x43,
+ 0xE5, 0x85, 0xA7, 0x43, 0xE5, 0x85, 0xA8, 0x43,
+ 0xE5, 0x85, 0xA9, 0x43, 0xE5, 0x85, 0xAB, 0x43,
+ 0xE5, 0x85, 0xAD, 0x43, 0xE5, 0x85, 0xB7, 0x43,
+ 0xE5, 0x86, 0x80, 0x43, 0xE5, 0x86, 0x82, 0x43,
+ // Bytes 7c0 - 7ff
+ 0xE5, 0x86, 0x8D, 0x43, 0xE5, 0x86, 0x92, 0x43,
+ 0xE5, 0x86, 0x95, 0x43, 0xE5, 0x86, 0x96, 0x43,
+ 0xE5, 0x86, 0x97, 0x43, 0xE5, 0x86, 0x99, 0x43,
+ 0xE5, 0x86, 0xA4, 0x43, 0xE5, 0x86, 0xAB, 0x43,
+ 0xE5, 0x86, 0xAC, 0x43, 0xE5, 0x86, 0xB5, 0x43,
+ 0xE5, 0x86, 0xB7, 0x43, 0xE5, 0x87, 0x89, 0x43,
+ 0xE5, 0x87, 0x8C, 0x43, 0xE5, 0x87, 0x9C, 0x43,
+ 0xE5, 0x87, 0x9E, 0x43, 0xE5, 0x87, 0xA0, 0x43,
+ // Bytes 800 - 83f
+ 0xE5, 0x87, 0xB5, 0x43, 0xE5, 0x88, 0x80, 0x43,
+ 0xE5, 0x88, 0x83, 0x43, 0xE5, 0x88, 0x87, 0x43,
+ 0xE5, 0x88, 0x97, 0x43, 0xE5, 0x88, 0x9D, 0x43,
+ 0xE5, 0x88, 0xA9, 0x43, 0xE5, 0x88, 0xBA, 0x43,
+ 0xE5, 0x88, 0xBB, 0x43, 0xE5, 0x89, 0x86, 0x43,
+ 0xE5, 0x89, 0x8D, 0x43, 0xE5, 0x89, 0xB2, 0x43,
+ 0xE5, 0x89, 0xB7, 0x43, 0xE5, 0x8A, 0x89, 0x43,
+ 0xE5, 0x8A, 0x9B, 0x43, 0xE5, 0x8A, 0xA3, 0x43,
+ // Bytes 840 - 87f
+ 0xE5, 0x8A, 0xB3, 0x43, 0xE5, 0x8A, 0xB4, 0x43,
+ 0xE5, 0x8B, 0x87, 0x43, 0xE5, 0x8B, 0x89, 0x43,
+ 0xE5, 0x8B, 0x92, 0x43, 0xE5, 0x8B, 0x9E, 0x43,
+ 0xE5, 0x8B, 0xA4, 0x43, 0xE5, 0x8B, 0xB5, 0x43,
+ 0xE5, 0x8B, 0xB9, 0x43, 0xE5, 0x8B, 0xBA, 0x43,
+ 0xE5, 0x8C, 0x85, 0x43, 0xE5, 0x8C, 0x86, 0x43,
+ 0xE5, 0x8C, 0x95, 0x43, 0xE5, 0x8C, 0x97, 0x43,
+ 0xE5, 0x8C, 0x9A, 0x43, 0xE5, 0x8C, 0xB8, 0x43,
+ // Bytes 880 - 8bf
+ 0xE5, 0x8C, 0xBB, 0x43, 0xE5, 0x8C, 0xBF, 0x43,
+ 0xE5, 0x8D, 0x81, 0x43, 0xE5, 0x8D, 0x84, 0x43,
+ 0xE5, 0x8D, 0x85, 0x43, 0xE5, 0x8D, 0x89, 0x43,
+ 0xE5, 0x8D, 0x91, 0x43, 0xE5, 0x8D, 0x94, 0x43,
+ 0xE5, 0x8D, 0x9A, 0x43, 0xE5, 0x8D, 0x9C, 0x43,
+ 0xE5, 0x8D, 0xA9, 0x43, 0xE5, 0x8D, 0xB0, 0x43,
+ 0xE5, 0x8D, 0xB3, 0x43, 0xE5, 0x8D, 0xB5, 0x43,
+ 0xE5, 0x8D, 0xBD, 0x43, 0xE5, 0x8D, 0xBF, 0x43,
+ // Bytes 8c0 - 8ff
+ 0xE5, 0x8E, 0x82, 0x43, 0xE5, 0x8E, 0xB6, 0x43,
+ 0xE5, 0x8F, 0x83, 0x43, 0xE5, 0x8F, 0x88, 0x43,
+ 0xE5, 0x8F, 0x8A, 0x43, 0xE5, 0x8F, 0x8C, 0x43,
+ 0xE5, 0x8F, 0x9F, 0x43, 0xE5, 0x8F, 0xA3, 0x43,
+ 0xE5, 0x8F, 0xA5, 0x43, 0xE5, 0x8F, 0xAB, 0x43,
+ 0xE5, 0x8F, 0xAF, 0x43, 0xE5, 0x8F, 0xB1, 0x43,
+ 0xE5, 0x8F, 0xB3, 0x43, 0xE5, 0x90, 0x86, 0x43,
+ 0xE5, 0x90, 0x88, 0x43, 0xE5, 0x90, 0x8D, 0x43,
+ // Bytes 900 - 93f
+ 0xE5, 0x90, 0x8F, 0x43, 0xE5, 0x90, 0x9D, 0x43,
+ 0xE5, 0x90, 0xB8, 0x43, 0xE5, 0x90, 0xB9, 0x43,
+ 0xE5, 0x91, 0x82, 0x43, 0xE5, 0x91, 0x88, 0x43,
+ 0xE5, 0x91, 0xA8, 0x43, 0xE5, 0x92, 0x9E, 0x43,
+ 0xE5, 0x92, 0xA2, 0x43, 0xE5, 0x92, 0xBD, 0x43,
+ 0xE5, 0x93, 0xB6, 0x43, 0xE5, 0x94, 0x90, 0x43,
+ 0xE5, 0x95, 0x8F, 0x43, 0xE5, 0x95, 0x93, 0x43,
+ 0xE5, 0x95, 0x95, 0x43, 0xE5, 0x95, 0xA3, 0x43,
+ // Bytes 940 - 97f
+ 0xE5, 0x96, 0x84, 0x43, 0xE5, 0x96, 0x87, 0x43,
+ 0xE5, 0x96, 0x99, 0x43, 0xE5, 0x96, 0x9D, 0x43,
+ 0xE5, 0x96, 0xAB, 0x43, 0xE5, 0x96, 0xB3, 0x43,
+ 0xE5, 0x96, 0xB6, 0x43, 0xE5, 0x97, 0x80, 0x43,
+ 0xE5, 0x97, 0x82, 0x43, 0xE5, 0x97, 0xA2, 0x43,
+ 0xE5, 0x98, 0x86, 0x43, 0xE5, 0x99, 0x91, 0x43,
+ 0xE5, 0x99, 0xA8, 0x43, 0xE5, 0x99, 0xB4, 0x43,
+ 0xE5, 0x9B, 0x97, 0x43, 0xE5, 0x9B, 0x9B, 0x43,
+ // Bytes 980 - 9bf
+ 0xE5, 0x9B, 0xB9, 0x43, 0xE5, 0x9C, 0x96, 0x43,
+ 0xE5, 0x9C, 0x97, 0x43, 0xE5, 0x9C, 0x9F, 0x43,
+ 0xE5, 0x9C, 0xB0, 0x43, 0xE5, 0x9E, 0x8B, 0x43,
+ 0xE5, 0x9F, 0x8E, 0x43, 0xE5, 0x9F, 0xB4, 0x43,
+ 0xE5, 0xA0, 0x8D, 0x43, 0xE5, 0xA0, 0xB1, 0x43,
+ 0xE5, 0xA0, 0xB2, 0x43, 0xE5, 0xA1, 0x80, 0x43,
+ 0xE5, 0xA1, 0x9A, 0x43, 0xE5, 0xA1, 0x9E, 0x43,
+ 0xE5, 0xA2, 0xA8, 0x43, 0xE5, 0xA2, 0xAC, 0x43,
+ // Bytes 9c0 - 9ff
+ 0xE5, 0xA2, 0xB3, 0x43, 0xE5, 0xA3, 0x98, 0x43,
+ 0xE5, 0xA3, 0x9F, 0x43, 0xE5, 0xA3, 0xAB, 0x43,
+ 0xE5, 0xA3, 0xAE, 0x43, 0xE5, 0xA3, 0xB0, 0x43,
+ 0xE5, 0xA3, 0xB2, 0x43, 0xE5, 0xA3, 0xB7, 0x43,
+ 0xE5, 0xA4, 0x82, 0x43, 0xE5, 0xA4, 0x86, 0x43,
+ 0xE5, 0xA4, 0x8A, 0x43, 0xE5, 0xA4, 0x95, 0x43,
+ 0xE5, 0xA4, 0x9A, 0x43, 0xE5, 0xA4, 0x9C, 0x43,
+ 0xE5, 0xA4, 0xA2, 0x43, 0xE5, 0xA4, 0xA7, 0x43,
+ // Bytes a00 - a3f
+ 0xE5, 0xA4, 0xA9, 0x43, 0xE5, 0xA5, 0x84, 0x43,
+ 0xE5, 0xA5, 0x88, 0x43, 0xE5, 0xA5, 0x91, 0x43,
+ 0xE5, 0xA5, 0x94, 0x43, 0xE5, 0xA5, 0xA2, 0x43,
+ 0xE5, 0xA5, 0xB3, 0x43, 0xE5, 0xA7, 0x98, 0x43,
+ 0xE5, 0xA7, 0xAC, 0x43, 0xE5, 0xA8, 0x9B, 0x43,
+ 0xE5, 0xA8, 0xA7, 0x43, 0xE5, 0xA9, 0xA2, 0x43,
+ 0xE5, 0xA9, 0xA6, 0x43, 0xE5, 0xAA, 0xB5, 0x43,
+ 0xE5, 0xAC, 0x88, 0x43, 0xE5, 0xAC, 0xA8, 0x43,
+ // Bytes a40 - a7f
+ 0xE5, 0xAC, 0xBE, 0x43, 0xE5, 0xAD, 0x90, 0x43,
+ 0xE5, 0xAD, 0x97, 0x43, 0xE5, 0xAD, 0xA6, 0x43,
+ 0xE5, 0xAE, 0x80, 0x43, 0xE5, 0xAE, 0x85, 0x43,
+ 0xE5, 0xAE, 0x97, 0x43, 0xE5, 0xAF, 0x83, 0x43,
+ 0xE5, 0xAF, 0x98, 0x43, 0xE5, 0xAF, 0xA7, 0x43,
+ 0xE5, 0xAF, 0xAE, 0x43, 0xE5, 0xAF, 0xB3, 0x43,
+ 0xE5, 0xAF, 0xB8, 0x43, 0xE5, 0xAF, 0xBF, 0x43,
+ 0xE5, 0xB0, 0x86, 0x43, 0xE5, 0xB0, 0x8F, 0x43,
+ // Bytes a80 - abf
+ 0xE5, 0xB0, 0xA2, 0x43, 0xE5, 0xB0, 0xB8, 0x43,
+ 0xE5, 0xB0, 0xBF, 0x43, 0xE5, 0xB1, 0xA0, 0x43,
+ 0xE5, 0xB1, 0xA2, 0x43, 0xE5, 0xB1, 0xA4, 0x43,
+ 0xE5, 0xB1, 0xA5, 0x43, 0xE5, 0xB1, 0xAE, 0x43,
+ 0xE5, 0xB1, 0xB1, 0x43, 0xE5, 0xB2, 0x8D, 0x43,
+ 0xE5, 0xB3, 0x80, 0x43, 0xE5, 0xB4, 0x99, 0x43,
+ 0xE5, 0xB5, 0x83, 0x43, 0xE5, 0xB5, 0x90, 0x43,
+ 0xE5, 0xB5, 0xAB, 0x43, 0xE5, 0xB5, 0xAE, 0x43,
+ // Bytes ac0 - aff
+ 0xE5, 0xB5, 0xBC, 0x43, 0xE5, 0xB6, 0xB2, 0x43,
+ 0xE5, 0xB6, 0xBA, 0x43, 0xE5, 0xB7, 0x9B, 0x43,
+ 0xE5, 0xB7, 0xA1, 0x43, 0xE5, 0xB7, 0xA2, 0x43,
+ 0xE5, 0xB7, 0xA5, 0x43, 0xE5, 0xB7, 0xA6, 0x43,
+ 0xE5, 0xB7, 0xB1, 0x43, 0xE5, 0xB7, 0xBD, 0x43,
+ 0xE5, 0xB7, 0xBE, 0x43, 0xE5, 0xB8, 0xA8, 0x43,
+ 0xE5, 0xB8, 0xBD, 0x43, 0xE5, 0xB9, 0xA9, 0x43,
+ 0xE5, 0xB9, 0xB2, 0x43, 0xE5, 0xB9, 0xB4, 0x43,
+ // Bytes b00 - b3f
+ 0xE5, 0xB9, 0xBA, 0x43, 0xE5, 0xB9, 0xBC, 0x43,
+ 0xE5, 0xB9, 0xBF, 0x43, 0xE5, 0xBA, 0xA6, 0x43,
+ 0xE5, 0xBA, 0xB0, 0x43, 0xE5, 0xBA, 0xB3, 0x43,
+ 0xE5, 0xBA, 0xB6, 0x43, 0xE5, 0xBB, 0x89, 0x43,
+ 0xE5, 0xBB, 0x8A, 0x43, 0xE5, 0xBB, 0x92, 0x43,
+ 0xE5, 0xBB, 0x93, 0x43, 0xE5, 0xBB, 0x99, 0x43,
+ 0xE5, 0xBB, 0xAC, 0x43, 0xE5, 0xBB, 0xB4, 0x43,
+ 0xE5, 0xBB, 0xBE, 0x43, 0xE5, 0xBC, 0x84, 0x43,
+ // Bytes b40 - b7f
+ 0xE5, 0xBC, 0x8B, 0x43, 0xE5, 0xBC, 0x93, 0x43,
+ 0xE5, 0xBC, 0xA2, 0x43, 0xE5, 0xBD, 0x90, 0x43,
+ 0xE5, 0xBD, 0x93, 0x43, 0xE5, 0xBD, 0xA1, 0x43,
+ 0xE5, 0xBD, 0xA2, 0x43, 0xE5, 0xBD, 0xA9, 0x43,
+ 0xE5, 0xBD, 0xAB, 0x43, 0xE5, 0xBD, 0xB3, 0x43,
+ 0xE5, 0xBE, 0x8B, 0x43, 0xE5, 0xBE, 0x8C, 0x43,
+ 0xE5, 0xBE, 0x97, 0x43, 0xE5, 0xBE, 0x9A, 0x43,
+ 0xE5, 0xBE, 0xA9, 0x43, 0xE5, 0xBE, 0xAD, 0x43,
+ // Bytes b80 - bbf
+ 0xE5, 0xBF, 0x83, 0x43, 0xE5, 0xBF, 0x8D, 0x43,
+ 0xE5, 0xBF, 0x97, 0x43, 0xE5, 0xBF, 0xB5, 0x43,
+ 0xE5, 0xBF, 0xB9, 0x43, 0xE6, 0x80, 0x92, 0x43,
+ 0xE6, 0x80, 0x9C, 0x43, 0xE6, 0x81, 0xB5, 0x43,
+ 0xE6, 0x82, 0x81, 0x43, 0xE6, 0x82, 0x94, 0x43,
+ 0xE6, 0x83, 0x87, 0x43, 0xE6, 0x83, 0x98, 0x43,
+ 0xE6, 0x83, 0xA1, 0x43, 0xE6, 0x84, 0x88, 0x43,
+ 0xE6, 0x85, 0x84, 0x43, 0xE6, 0x85, 0x88, 0x43,
+ // Bytes bc0 - bff
+ 0xE6, 0x85, 0x8C, 0x43, 0xE6, 0x85, 0x8E, 0x43,
+ 0xE6, 0x85, 0xA0, 0x43, 0xE6, 0x85, 0xA8, 0x43,
+ 0xE6, 0x85, 0xBA, 0x43, 0xE6, 0x86, 0x8E, 0x43,
+ 0xE6, 0x86, 0x90, 0x43, 0xE6, 0x86, 0xA4, 0x43,
+ 0xE6, 0x86, 0xAF, 0x43, 0xE6, 0x86, 0xB2, 0x43,
+ 0xE6, 0x87, 0x9E, 0x43, 0xE6, 0x87, 0xB2, 0x43,
+ 0xE6, 0x87, 0xB6, 0x43, 0xE6, 0x88, 0x80, 0x43,
+ 0xE6, 0x88, 0x88, 0x43, 0xE6, 0x88, 0x90, 0x43,
+ // Bytes c00 - c3f
+ 0xE6, 0x88, 0x9B, 0x43, 0xE6, 0x88, 0xAE, 0x43,
+ 0xE6, 0x88, 0xB4, 0x43, 0xE6, 0x88, 0xB6, 0x43,
+ 0xE6, 0x89, 0x8B, 0x43, 0xE6, 0x89, 0x93, 0x43,
+ 0xE6, 0x89, 0x9D, 0x43, 0xE6, 0x8A, 0x95, 0x43,
+ 0xE6, 0x8A, 0xB1, 0x43, 0xE6, 0x8B, 0x89, 0x43,
+ 0xE6, 0x8B, 0x8F, 0x43, 0xE6, 0x8B, 0x93, 0x43,
+ 0xE6, 0x8B, 0x94, 0x43, 0xE6, 0x8B, 0xBC, 0x43,
+ 0xE6, 0x8B, 0xBE, 0x43, 0xE6, 0x8C, 0x87, 0x43,
+ // Bytes c40 - c7f
+ 0xE6, 0x8C, 0xBD, 0x43, 0xE6, 0x8D, 0x90, 0x43,
+ 0xE6, 0x8D, 0x95, 0x43, 0xE6, 0x8D, 0xA8, 0x43,
+ 0xE6, 0x8D, 0xBB, 0x43, 0xE6, 0x8E, 0x83, 0x43,
+ 0xE6, 0x8E, 0xA0, 0x43, 0xE6, 0x8E, 0xA9, 0x43,
+ 0xE6, 0x8F, 0x84, 0x43, 0xE6, 0x8F, 0x85, 0x43,
+ 0xE6, 0x8F, 0xA4, 0x43, 0xE6, 0x90, 0x9C, 0x43,
+ 0xE6, 0x90, 0xA2, 0x43, 0xE6, 0x91, 0x92, 0x43,
+ 0xE6, 0x91, 0xA9, 0x43, 0xE6, 0x91, 0xB7, 0x43,
+ // Bytes c80 - cbf
+ 0xE6, 0x91, 0xBE, 0x43, 0xE6, 0x92, 0x9A, 0x43,
+ 0xE6, 0x92, 0x9D, 0x43, 0xE6, 0x93, 0x84, 0x43,
+ 0xE6, 0x94, 0xAF, 0x43, 0xE6, 0x94, 0xB4, 0x43,
+ 0xE6, 0x95, 0x8F, 0x43, 0xE6, 0x95, 0x96, 0x43,
+ 0xE6, 0x95, 0xAC, 0x43, 0xE6, 0x95, 0xB8, 0x43,
+ 0xE6, 0x96, 0x87, 0x43, 0xE6, 0x96, 0x97, 0x43,
+ 0xE6, 0x96, 0x99, 0x43, 0xE6, 0x96, 0xA4, 0x43,
+ 0xE6, 0x96, 0xB0, 0x43, 0xE6, 0x96, 0xB9, 0x43,
+ // Bytes cc0 - cff
+ 0xE6, 0x97, 0x85, 0x43, 0xE6, 0x97, 0xA0, 0x43,
+ 0xE6, 0x97, 0xA2, 0x43, 0xE6, 0x97, 0xA3, 0x43,
+ 0xE6, 0x97, 0xA5, 0x43, 0xE6, 0x98, 0x93, 0x43,
+ 0xE6, 0x98, 0xA0, 0x43, 0xE6, 0x99, 0x89, 0x43,
+ 0xE6, 0x99, 0xB4, 0x43, 0xE6, 0x9A, 0x88, 0x43,
+ 0xE6, 0x9A, 0x91, 0x43, 0xE6, 0x9A, 0x9C, 0x43,
+ 0xE6, 0x9A, 0xB4, 0x43, 0xE6, 0x9B, 0x86, 0x43,
+ 0xE6, 0x9B, 0xB0, 0x43, 0xE6, 0x9B, 0xB4, 0x43,
+ // Bytes d00 - d3f
+ 0xE6, 0x9B, 0xB8, 0x43, 0xE6, 0x9C, 0x80, 0x43,
+ 0xE6, 0x9C, 0x88, 0x43, 0xE6, 0x9C, 0x89, 0x43,
+ 0xE6, 0x9C, 0x97, 0x43, 0xE6, 0x9C, 0x9B, 0x43,
+ 0xE6, 0x9C, 0xA1, 0x43, 0xE6, 0x9C, 0xA8, 0x43,
+ 0xE6, 0x9D, 0x8E, 0x43, 0xE6, 0x9D, 0x93, 0x43,
+ 0xE6, 0x9D, 0x96, 0x43, 0xE6, 0x9D, 0x9E, 0x43,
+ 0xE6, 0x9D, 0xBB, 0x43, 0xE6, 0x9E, 0x85, 0x43,
+ 0xE6, 0x9E, 0x97, 0x43, 0xE6, 0x9F, 0xB3, 0x43,
+ // Bytes d40 - d7f
+ 0xE6, 0x9F, 0xBA, 0x43, 0xE6, 0xA0, 0x97, 0x43,
+ 0xE6, 0xA0, 0x9F, 0x43, 0xE6, 0xA0, 0xAA, 0x43,
+ 0xE6, 0xA1, 0x92, 0x43, 0xE6, 0xA2, 0x81, 0x43,
+ 0xE6, 0xA2, 0x85, 0x43, 0xE6, 0xA2, 0x8E, 0x43,
+ 0xE6, 0xA2, 0xA8, 0x43, 0xE6, 0xA4, 0x94, 0x43,
+ 0xE6, 0xA5, 0x82, 0x43, 0xE6, 0xA6, 0xA3, 0x43,
+ 0xE6, 0xA7, 0xAA, 0x43, 0xE6, 0xA8, 0x82, 0x43,
+ 0xE6, 0xA8, 0x93, 0x43, 0xE6, 0xAA, 0xA8, 0x43,
+ // Bytes d80 - dbf
+ 0xE6, 0xAB, 0x93, 0x43, 0xE6, 0xAB, 0x9B, 0x43,
+ 0xE6, 0xAC, 0x84, 0x43, 0xE6, 0xAC, 0xA0, 0x43,
+ 0xE6, 0xAC, 0xA1, 0x43, 0xE6, 0xAD, 0x94, 0x43,
+ 0xE6, 0xAD, 0xA2, 0x43, 0xE6, 0xAD, 0xA3, 0x43,
+ 0xE6, 0xAD, 0xB2, 0x43, 0xE6, 0xAD, 0xB7, 0x43,
+ 0xE6, 0xAD, 0xB9, 0x43, 0xE6, 0xAE, 0x9F, 0x43,
+ 0xE6, 0xAE, 0xAE, 0x43, 0xE6, 0xAE, 0xB3, 0x43,
+ 0xE6, 0xAE, 0xBA, 0x43, 0xE6, 0xAE, 0xBB, 0x43,
+ // Bytes dc0 - dff
+ 0xE6, 0xAF, 0x8B, 0x43, 0xE6, 0xAF, 0x8D, 0x43,
+ 0xE6, 0xAF, 0x94, 0x43, 0xE6, 0xAF, 0x9B, 0x43,
+ 0xE6, 0xB0, 0x8F, 0x43, 0xE6, 0xB0, 0x94, 0x43,
+ 0xE6, 0xB0, 0xB4, 0x43, 0xE6, 0xB1, 0x8E, 0x43,
+ 0xE6, 0xB1, 0xA7, 0x43, 0xE6, 0xB2, 0x88, 0x43,
+ 0xE6, 0xB2, 0xBF, 0x43, 0xE6, 0xB3, 0x8C, 0x43,
+ 0xE6, 0xB3, 0x8D, 0x43, 0xE6, 0xB3, 0xA5, 0x43,
+ 0xE6, 0xB3, 0xA8, 0x43, 0xE6, 0xB4, 0x96, 0x43,
+ // Bytes e00 - e3f
+ 0xE6, 0xB4, 0x9B, 0x43, 0xE6, 0xB4, 0x9E, 0x43,
+ 0xE6, 0xB4, 0xB4, 0x43, 0xE6, 0xB4, 0xBE, 0x43,
+ 0xE6, 0xB5, 0x81, 0x43, 0xE6, 0xB5, 0xA9, 0x43,
+ 0xE6, 0xB5, 0xAA, 0x43, 0xE6, 0xB5, 0xB7, 0x43,
+ 0xE6, 0xB5, 0xB8, 0x43, 0xE6, 0xB6, 0x85, 0x43,
+ 0xE6, 0xB7, 0x8B, 0x43, 0xE6, 0xB7, 0x9A, 0x43,
+ 0xE6, 0xB7, 0xAA, 0x43, 0xE6, 0xB7, 0xB9, 0x43,
+ 0xE6, 0xB8, 0x9A, 0x43, 0xE6, 0xB8, 0xAF, 0x43,
+ // Bytes e40 - e7f
+ 0xE6, 0xB9, 0xAE, 0x43, 0xE6, 0xBA, 0x80, 0x43,
+ 0xE6, 0xBA, 0x9C, 0x43, 0xE6, 0xBA, 0xBA, 0x43,
+ 0xE6, 0xBB, 0x87, 0x43, 0xE6, 0xBB, 0x8B, 0x43,
+ 0xE6, 0xBB, 0x91, 0x43, 0xE6, 0xBB, 0x9B, 0x43,
+ 0xE6, 0xBC, 0x8F, 0x43, 0xE6, 0xBC, 0x94, 0x43,
+ 0xE6, 0xBC, 0xA2, 0x43, 0xE6, 0xBC, 0xA3, 0x43,
+ 0xE6, 0xBD, 0xAE, 0x43, 0xE6, 0xBF, 0x86, 0x43,
+ 0xE6, 0xBF, 0xAB, 0x43, 0xE6, 0xBF, 0xBE, 0x43,
+ // Bytes e80 - ebf
+ 0xE7, 0x80, 0x9B, 0x43, 0xE7, 0x80, 0x9E, 0x43,
+ 0xE7, 0x80, 0xB9, 0x43, 0xE7, 0x81, 0x8A, 0x43,
+ 0xE7, 0x81, 0xAB, 0x43, 0xE7, 0x81, 0xB0, 0x43,
+ 0xE7, 0x81, 0xB7, 0x43, 0xE7, 0x81, 0xBD, 0x43,
+ 0xE7, 0x82, 0x99, 0x43, 0xE7, 0x82, 0xAD, 0x43,
+ 0xE7, 0x83, 0x88, 0x43, 0xE7, 0x83, 0x99, 0x43,
+ 0xE7, 0x84, 0xA1, 0x43, 0xE7, 0x85, 0x85, 0x43,
+ 0xE7, 0x85, 0x89, 0x43, 0xE7, 0x85, 0xAE, 0x43,
+ // Bytes ec0 - eff
+ 0xE7, 0x86, 0x9C, 0x43, 0xE7, 0x87, 0x8E, 0x43,
+ 0xE7, 0x87, 0x90, 0x43, 0xE7, 0x88, 0x90, 0x43,
+ 0xE7, 0x88, 0x9B, 0x43, 0xE7, 0x88, 0xA8, 0x43,
+ 0xE7, 0x88, 0xAA, 0x43, 0xE7, 0x88, 0xAB, 0x43,
+ 0xE7, 0x88, 0xB5, 0x43, 0xE7, 0x88, 0xB6, 0x43,
+ 0xE7, 0x88, 0xBB, 0x43, 0xE7, 0x88, 0xBF, 0x43,
+ 0xE7, 0x89, 0x87, 0x43, 0xE7, 0x89, 0x90, 0x43,
+ 0xE7, 0x89, 0x99, 0x43, 0xE7, 0x89, 0x9B, 0x43,
+ // Bytes f00 - f3f
+ 0xE7, 0x89, 0xA2, 0x43, 0xE7, 0x89, 0xB9, 0x43,
+ 0xE7, 0x8A, 0x80, 0x43, 0xE7, 0x8A, 0x95, 0x43,
+ 0xE7, 0x8A, 0xAC, 0x43, 0xE7, 0x8A, 0xAF, 0x43,
+ 0xE7, 0x8B, 0x80, 0x43, 0xE7, 0x8B, 0xBC, 0x43,
+ 0xE7, 0x8C, 0xAA, 0x43, 0xE7, 0x8D, 0xB5, 0x43,
+ 0xE7, 0x8D, 0xBA, 0x43, 0xE7, 0x8E, 0x84, 0x43,
+ 0xE7, 0x8E, 0x87, 0x43, 0xE7, 0x8E, 0x89, 0x43,
+ 0xE7, 0x8E, 0x8B, 0x43, 0xE7, 0x8E, 0xA5, 0x43,
+ // Bytes f40 - f7f
+ 0xE7, 0x8E, 0xB2, 0x43, 0xE7, 0x8F, 0x9E, 0x43,
+ 0xE7, 0x90, 0x86, 0x43, 0xE7, 0x90, 0x89, 0x43,
+ 0xE7, 0x90, 0xA2, 0x43, 0xE7, 0x91, 0x87, 0x43,
+ 0xE7, 0x91, 0x9C, 0x43, 0xE7, 0x91, 0xA9, 0x43,
+ 0xE7, 0x91, 0xB1, 0x43, 0xE7, 0x92, 0x85, 0x43,
+ 0xE7, 0x92, 0x89, 0x43, 0xE7, 0x92, 0x98, 0x43,
+ 0xE7, 0x93, 0x8A, 0x43, 0xE7, 0x93, 0x9C, 0x43,
+ 0xE7, 0x93, 0xA6, 0x43, 0xE7, 0x94, 0x86, 0x43,
+ // Bytes f80 - fbf
+ 0xE7, 0x94, 0x98, 0x43, 0xE7, 0x94, 0x9F, 0x43,
+ 0xE7, 0x94, 0xA4, 0x43, 0xE7, 0x94, 0xA8, 0x43,
+ 0xE7, 0x94, 0xB0, 0x43, 0xE7, 0x94, 0xB2, 0x43,
+ 0xE7, 0x94, 0xB3, 0x43, 0xE7, 0x94, 0xB7, 0x43,
+ 0xE7, 0x94, 0xBB, 0x43, 0xE7, 0x94, 0xBE, 0x43,
+ 0xE7, 0x95, 0x99, 0x43, 0xE7, 0x95, 0xA5, 0x43,
+ 0xE7, 0x95, 0xB0, 0x43, 0xE7, 0x96, 0x8B, 0x43,
+ 0xE7, 0x96, 0x92, 0x43, 0xE7, 0x97, 0xA2, 0x43,
+ // Bytes fc0 - fff
+ 0xE7, 0x98, 0x90, 0x43, 0xE7, 0x98, 0x9D, 0x43,
+ 0xE7, 0x98, 0x9F, 0x43, 0xE7, 0x99, 0x82, 0x43,
+ 0xE7, 0x99, 0xA9, 0x43, 0xE7, 0x99, 0xB6, 0x43,
+ 0xE7, 0x99, 0xBD, 0x43, 0xE7, 0x9A, 0xAE, 0x43,
+ 0xE7, 0x9A, 0xBF, 0x43, 0xE7, 0x9B, 0x8A, 0x43,
+ 0xE7, 0x9B, 0x9B, 0x43, 0xE7, 0x9B, 0xA3, 0x43,
+ 0xE7, 0x9B, 0xA7, 0x43, 0xE7, 0x9B, 0xAE, 0x43,
+ 0xE7, 0x9B, 0xB4, 0x43, 0xE7, 0x9C, 0x81, 0x43,
+ // Bytes 1000 - 103f
+ 0xE7, 0x9C, 0x9E, 0x43, 0xE7, 0x9C, 0x9F, 0x43,
+ 0xE7, 0x9D, 0x80, 0x43, 0xE7, 0x9D, 0x8A, 0x43,
+ 0xE7, 0x9E, 0x8B, 0x43, 0xE7, 0x9E, 0xA7, 0x43,
+ 0xE7, 0x9F, 0x9B, 0x43, 0xE7, 0x9F, 0xA2, 0x43,
+ 0xE7, 0x9F, 0xB3, 0x43, 0xE7, 0xA1, 0x8E, 0x43,
+ 0xE7, 0xA1, 0xAB, 0x43, 0xE7, 0xA2, 0x8C, 0x43,
+ 0xE7, 0xA2, 0x91, 0x43, 0xE7, 0xA3, 0x8A, 0x43,
+ 0xE7, 0xA3, 0x8C, 0x43, 0xE7, 0xA3, 0xBB, 0x43,
+ // Bytes 1040 - 107f
+ 0xE7, 0xA4, 0xAA, 0x43, 0xE7, 0xA4, 0xBA, 0x43,
+ 0xE7, 0xA4, 0xBC, 0x43, 0xE7, 0xA4, 0xBE, 0x43,
+ 0xE7, 0xA5, 0x88, 0x43, 0xE7, 0xA5, 0x89, 0x43,
+ 0xE7, 0xA5, 0x90, 0x43, 0xE7, 0xA5, 0x96, 0x43,
+ 0xE7, 0xA5, 0x9D, 0x43, 0xE7, 0xA5, 0x9E, 0x43,
+ 0xE7, 0xA5, 0xA5, 0x43, 0xE7, 0xA5, 0xBF, 0x43,
+ 0xE7, 0xA6, 0x81, 0x43, 0xE7, 0xA6, 0x8D, 0x43,
+ 0xE7, 0xA6, 0x8E, 0x43, 0xE7, 0xA6, 0x8F, 0x43,
+ // Bytes 1080 - 10bf
+ 0xE7, 0xA6, 0xAE, 0x43, 0xE7, 0xA6, 0xB8, 0x43,
+ 0xE7, 0xA6, 0xBE, 0x43, 0xE7, 0xA7, 0x8A, 0x43,
+ 0xE7, 0xA7, 0x98, 0x43, 0xE7, 0xA7, 0xAB, 0x43,
+ 0xE7, 0xA8, 0x9C, 0x43, 0xE7, 0xA9, 0x80, 0x43,
+ 0xE7, 0xA9, 0x8A, 0x43, 0xE7, 0xA9, 0x8F, 0x43,
+ 0xE7, 0xA9, 0xB4, 0x43, 0xE7, 0xA9, 0xBA, 0x43,
+ 0xE7, 0xAA, 0x81, 0x43, 0xE7, 0xAA, 0xB1, 0x43,
+ 0xE7, 0xAB, 0x8B, 0x43, 0xE7, 0xAB, 0xAE, 0x43,
+ // Bytes 10c0 - 10ff
+ 0xE7, 0xAB, 0xB9, 0x43, 0xE7, 0xAC, 0xA0, 0x43,
+ 0xE7, 0xAE, 0x8F, 0x43, 0xE7, 0xAF, 0x80, 0x43,
+ 0xE7, 0xAF, 0x86, 0x43, 0xE7, 0xAF, 0x89, 0x43,
+ 0xE7, 0xB0, 0xBE, 0x43, 0xE7, 0xB1, 0xA0, 0x43,
+ 0xE7, 0xB1, 0xB3, 0x43, 0xE7, 0xB1, 0xBB, 0x43,
+ 0xE7, 0xB2, 0x92, 0x43, 0xE7, 0xB2, 0xBE, 0x43,
+ 0xE7, 0xB3, 0x92, 0x43, 0xE7, 0xB3, 0x96, 0x43,
+ 0xE7, 0xB3, 0xA3, 0x43, 0xE7, 0xB3, 0xA7, 0x43,
+ // Bytes 1100 - 113f
+ 0xE7, 0xB3, 0xA8, 0x43, 0xE7, 0xB3, 0xB8, 0x43,
+ 0xE7, 0xB4, 0x80, 0x43, 0xE7, 0xB4, 0x90, 0x43,
+ 0xE7, 0xB4, 0xA2, 0x43, 0xE7, 0xB4, 0xAF, 0x43,
+ 0xE7, 0xB5, 0x82, 0x43, 0xE7, 0xB5, 0x9B, 0x43,
+ 0xE7, 0xB5, 0xA3, 0x43, 0xE7, 0xB6, 0xA0, 0x43,
+ 0xE7, 0xB6, 0xBE, 0x43, 0xE7, 0xB7, 0x87, 0x43,
+ 0xE7, 0xB7, 0xB4, 0x43, 0xE7, 0xB8, 0x82, 0x43,
+ 0xE7, 0xB8, 0x89, 0x43, 0xE7, 0xB8, 0xB7, 0x43,
+ // Bytes 1140 - 117f
+ 0xE7, 0xB9, 0x81, 0x43, 0xE7, 0xB9, 0x85, 0x43,
+ 0xE7, 0xBC, 0xB6, 0x43, 0xE7, 0xBC, 0xBE, 0x43,
+ 0xE7, 0xBD, 0x91, 0x43, 0xE7, 0xBD, 0xB2, 0x43,
+ 0xE7, 0xBD, 0xB9, 0x43, 0xE7, 0xBD, 0xBA, 0x43,
+ 0xE7, 0xBE, 0x85, 0x43, 0xE7, 0xBE, 0x8A, 0x43,
+ 0xE7, 0xBE, 0x95, 0x43, 0xE7, 0xBE, 0x9A, 0x43,
+ 0xE7, 0xBE, 0xBD, 0x43, 0xE7, 0xBF, 0xBA, 0x43,
+ 0xE8, 0x80, 0x81, 0x43, 0xE8, 0x80, 0x85, 0x43,
+ // Bytes 1180 - 11bf
+ 0xE8, 0x80, 0x8C, 0x43, 0xE8, 0x80, 0x92, 0x43,
+ 0xE8, 0x80, 0xB3, 0x43, 0xE8, 0x81, 0x86, 0x43,
+ 0xE8, 0x81, 0xA0, 0x43, 0xE8, 0x81, 0xAF, 0x43,
+ 0xE8, 0x81, 0xB0, 0x43, 0xE8, 0x81, 0xBE, 0x43,
+ 0xE8, 0x81, 0xBF, 0x43, 0xE8, 0x82, 0x89, 0x43,
+ 0xE8, 0x82, 0x8B, 0x43, 0xE8, 0x82, 0xAD, 0x43,
+ 0xE8, 0x82, 0xB2, 0x43, 0xE8, 0x84, 0x83, 0x43,
+ 0xE8, 0x84, 0xBE, 0x43, 0xE8, 0x87, 0x98, 0x43,
+ // Bytes 11c0 - 11ff
+ 0xE8, 0x87, 0xA3, 0x43, 0xE8, 0x87, 0xA8, 0x43,
+ 0xE8, 0x87, 0xAA, 0x43, 0xE8, 0x87, 0xAD, 0x43,
+ 0xE8, 0x87, 0xB3, 0x43, 0xE8, 0x87, 0xBC, 0x43,
+ 0xE8, 0x88, 0x81, 0x43, 0xE8, 0x88, 0x84, 0x43,
+ 0xE8, 0x88, 0x8C, 0x43, 0xE8, 0x88, 0x98, 0x43,
+ 0xE8, 0x88, 0x9B, 0x43, 0xE8, 0x88, 0x9F, 0x43,
+ 0xE8, 0x89, 0xAE, 0x43, 0xE8, 0x89, 0xAF, 0x43,
+ 0xE8, 0x89, 0xB2, 0x43, 0xE8, 0x89, 0xB8, 0x43,
+ // Bytes 1200 - 123f
+ 0xE8, 0x89, 0xB9, 0x43, 0xE8, 0x8A, 0x8B, 0x43,
+ 0xE8, 0x8A, 0x91, 0x43, 0xE8, 0x8A, 0x9D, 0x43,
+ 0xE8, 0x8A, 0xB1, 0x43, 0xE8, 0x8A, 0xB3, 0x43,
+ 0xE8, 0x8A, 0xBD, 0x43, 0xE8, 0x8B, 0xA5, 0x43,
+ 0xE8, 0x8B, 0xA6, 0x43, 0xE8, 0x8C, 0x9D, 0x43,
+ 0xE8, 0x8C, 0xA3, 0x43, 0xE8, 0x8C, 0xB6, 0x43,
+ 0xE8, 0x8D, 0x92, 0x43, 0xE8, 0x8D, 0x93, 0x43,
+ 0xE8, 0x8D, 0xA3, 0x43, 0xE8, 0x8E, 0xAD, 0x43,
+ // Bytes 1240 - 127f
+ 0xE8, 0x8E, 0xBD, 0x43, 0xE8, 0x8F, 0x89, 0x43,
+ 0xE8, 0x8F, 0x8A, 0x43, 0xE8, 0x8F, 0x8C, 0x43,
+ 0xE8, 0x8F, 0x9C, 0x43, 0xE8, 0x8F, 0xA7, 0x43,
+ 0xE8, 0x8F, 0xAF, 0x43, 0xE8, 0x8F, 0xB1, 0x43,
+ 0xE8, 0x90, 0xBD, 0x43, 0xE8, 0x91, 0x89, 0x43,
+ 0xE8, 0x91, 0x97, 0x43, 0xE8, 0x93, 0xAE, 0x43,
+ 0xE8, 0x93, 0xB1, 0x43, 0xE8, 0x93, 0xB3, 0x43,
+ 0xE8, 0x93, 0xBC, 0x43, 0xE8, 0x94, 0x96, 0x43,
+ // Bytes 1280 - 12bf
+ 0xE8, 0x95, 0xA4, 0x43, 0xE8, 0x97, 0x8D, 0x43,
+ 0xE8, 0x97, 0xBA, 0x43, 0xE8, 0x98, 0x86, 0x43,
+ 0xE8, 0x98, 0x92, 0x43, 0xE8, 0x98, 0xAD, 0x43,
+ 0xE8, 0x98, 0xBF, 0x43, 0xE8, 0x99, 0x8D, 0x43,
+ 0xE8, 0x99, 0x90, 0x43, 0xE8, 0x99, 0x9C, 0x43,
+ 0xE8, 0x99, 0xA7, 0x43, 0xE8, 0x99, 0xA9, 0x43,
+ 0xE8, 0x99, 0xAB, 0x43, 0xE8, 0x9A, 0x88, 0x43,
+ 0xE8, 0x9A, 0xA9, 0x43, 0xE8, 0x9B, 0xA2, 0x43,
+ // Bytes 12c0 - 12ff
+ 0xE8, 0x9C, 0x8E, 0x43, 0xE8, 0x9C, 0xA8, 0x43,
+ 0xE8, 0x9D, 0xAB, 0x43, 0xE8, 0x9D, 0xB9, 0x43,
+ 0xE8, 0x9E, 0x86, 0x43, 0xE8, 0x9E, 0xBA, 0x43,
+ 0xE8, 0x9F, 0xA1, 0x43, 0xE8, 0xA0, 0x81, 0x43,
+ 0xE8, 0xA0, 0x9F, 0x43, 0xE8, 0xA1, 0x80, 0x43,
+ 0xE8, 0xA1, 0x8C, 0x43, 0xE8, 0xA1, 0xA0, 0x43,
+ 0xE8, 0xA1, 0xA3, 0x43, 0xE8, 0xA3, 0x82, 0x43,
+ 0xE8, 0xA3, 0x8F, 0x43, 0xE8, 0xA3, 0x97, 0x43,
+ // Bytes 1300 - 133f
+ 0xE8, 0xA3, 0x9E, 0x43, 0xE8, 0xA3, 0xA1, 0x43,
+ 0xE8, 0xA3, 0xB8, 0x43, 0xE8, 0xA3, 0xBA, 0x43,
+ 0xE8, 0xA4, 0x90, 0x43, 0xE8, 0xA5, 0x81, 0x43,
+ 0xE8, 0xA5, 0xA4, 0x43, 0xE8, 0xA5, 0xBE, 0x43,
+ 0xE8, 0xA6, 0x86, 0x43, 0xE8, 0xA6, 0x8B, 0x43,
+ 0xE8, 0xA6, 0x96, 0x43, 0xE8, 0xA7, 0x92, 0x43,
+ 0xE8, 0xA7, 0xA3, 0x43, 0xE8, 0xA8, 0x80, 0x43,
+ 0xE8, 0xAA, 0xA0, 0x43, 0xE8, 0xAA, 0xAA, 0x43,
+ // Bytes 1340 - 137f
+ 0xE8, 0xAA, 0xBF, 0x43, 0xE8, 0xAB, 0x8B, 0x43,
+ 0xE8, 0xAB, 0x92, 0x43, 0xE8, 0xAB, 0x96, 0x43,
+ 0xE8, 0xAB, 0xAD, 0x43, 0xE8, 0xAB, 0xB8, 0x43,
+ 0xE8, 0xAB, 0xBE, 0x43, 0xE8, 0xAC, 0x81, 0x43,
+ 0xE8, 0xAC, 0xB9, 0x43, 0xE8, 0xAD, 0x98, 0x43,
+ 0xE8, 0xAE, 0x80, 0x43, 0xE8, 0xAE, 0x8A, 0x43,
+ 0xE8, 0xB0, 0xB7, 0x43, 0xE8, 0xB1, 0x86, 0x43,
+ 0xE8, 0xB1, 0x88, 0x43, 0xE8, 0xB1, 0x95, 0x43,
+ // Bytes 1380 - 13bf
+ 0xE8, 0xB1, 0xB8, 0x43, 0xE8, 0xB2, 0x9D, 0x43,
+ 0xE8, 0xB2, 0xA1, 0x43, 0xE8, 0xB2, 0xA9, 0x43,
+ 0xE8, 0xB2, 0xAB, 0x43, 0xE8, 0xB3, 0x81, 0x43,
+ 0xE8, 0xB3, 0x82, 0x43, 0xE8, 0xB3, 0x87, 0x43,
+ 0xE8, 0xB3, 0x88, 0x43, 0xE8, 0xB3, 0x93, 0x43,
+ 0xE8, 0xB4, 0x88, 0x43, 0xE8, 0xB4, 0x9B, 0x43,
+ 0xE8, 0xB5, 0xA4, 0x43, 0xE8, 0xB5, 0xB0, 0x43,
+ 0xE8, 0xB5, 0xB7, 0x43, 0xE8, 0xB6, 0xB3, 0x43,
+ // Bytes 13c0 - 13ff
+ 0xE8, 0xB6, 0xBC, 0x43, 0xE8, 0xB7, 0x8B, 0x43,
+ 0xE8, 0xB7, 0xAF, 0x43, 0xE8, 0xB7, 0xB0, 0x43,
+ 0xE8, 0xBA, 0xAB, 0x43, 0xE8, 0xBB, 0x8A, 0x43,
+ 0xE8, 0xBB, 0x94, 0x43, 0xE8, 0xBC, 0xA6, 0x43,
+ 0xE8, 0xBC, 0xAA, 0x43, 0xE8, 0xBC, 0xB8, 0x43,
+ 0xE8, 0xBC, 0xBB, 0x43, 0xE8, 0xBD, 0xA2, 0x43,
+ 0xE8, 0xBE, 0x9B, 0x43, 0xE8, 0xBE, 0x9E, 0x43,
+ 0xE8, 0xBE, 0xB0, 0x43, 0xE8, 0xBE, 0xB5, 0x43,
+ // Bytes 1400 - 143f
+ 0xE8, 0xBE, 0xB6, 0x43, 0xE9, 0x80, 0xA3, 0x43,
+ 0xE9, 0x80, 0xB8, 0x43, 0xE9, 0x81, 0x8A, 0x43,
+ 0xE9, 0x81, 0xA9, 0x43, 0xE9, 0x81, 0xB2, 0x43,
+ 0xE9, 0x81, 0xBC, 0x43, 0xE9, 0x82, 0x8F, 0x43,
+ 0xE9, 0x82, 0x91, 0x43, 0xE9, 0x82, 0x94, 0x43,
+ 0xE9, 0x83, 0x8E, 0x43, 0xE9, 0x83, 0x9E, 0x43,
+ 0xE9, 0x83, 0xB1, 0x43, 0xE9, 0x83, 0xBD, 0x43,
+ 0xE9, 0x84, 0x91, 0x43, 0xE9, 0x84, 0x9B, 0x43,
+ // Bytes 1440 - 147f
+ 0xE9, 0x85, 0x89, 0x43, 0xE9, 0x85, 0x8D, 0x43,
+ 0xE9, 0x85, 0xAA, 0x43, 0xE9, 0x86, 0x99, 0x43,
+ 0xE9, 0x86, 0xB4, 0x43, 0xE9, 0x87, 0x86, 0x43,
+ 0xE9, 0x87, 0x8C, 0x43, 0xE9, 0x87, 0x8F, 0x43,
+ 0xE9, 0x87, 0x91, 0x43, 0xE9, 0x88, 0xB4, 0x43,
+ 0xE9, 0x88, 0xB8, 0x43, 0xE9, 0x89, 0xB6, 0x43,
+ 0xE9, 0x89, 0xBC, 0x43, 0xE9, 0x8B, 0x97, 0x43,
+ 0xE9, 0x8B, 0x98, 0x43, 0xE9, 0x8C, 0x84, 0x43,
+ // Bytes 1480 - 14bf
+ 0xE9, 0x8D, 0x8A, 0x43, 0xE9, 0x8F, 0xB9, 0x43,
+ 0xE9, 0x90, 0x95, 0x43, 0xE9, 0x95, 0xB7, 0x43,
+ 0xE9, 0x96, 0x80, 0x43, 0xE9, 0x96, 0x8B, 0x43,
+ 0xE9, 0x96, 0xAD, 0x43, 0xE9, 0x96, 0xB7, 0x43,
+ 0xE9, 0x98, 0x9C, 0x43, 0xE9, 0x98, 0xAE, 0x43,
+ 0xE9, 0x99, 0x8B, 0x43, 0xE9, 0x99, 0x8D, 0x43,
+ 0xE9, 0x99, 0xB5, 0x43, 0xE9, 0x99, 0xB8, 0x43,
+ 0xE9, 0x99, 0xBC, 0x43, 0xE9, 0x9A, 0x86, 0x43,
+ // Bytes 14c0 - 14ff
+ 0xE9, 0x9A, 0xA3, 0x43, 0xE9, 0x9A, 0xB6, 0x43,
+ 0xE9, 0x9A, 0xB7, 0x43, 0xE9, 0x9A, 0xB8, 0x43,
+ 0xE9, 0x9A, 0xB9, 0x43, 0xE9, 0x9B, 0x83, 0x43,
+ 0xE9, 0x9B, 0xA2, 0x43, 0xE9, 0x9B, 0xA3, 0x43,
+ 0xE9, 0x9B, 0xA8, 0x43, 0xE9, 0x9B, 0xB6, 0x43,
+ 0xE9, 0x9B, 0xB7, 0x43, 0xE9, 0x9C, 0xA3, 0x43,
+ 0xE9, 0x9C, 0xB2, 0x43, 0xE9, 0x9D, 0x88, 0x43,
+ 0xE9, 0x9D, 0x91, 0x43, 0xE9, 0x9D, 0x96, 0x43,
+ // Bytes 1500 - 153f
+ 0xE9, 0x9D, 0x9E, 0x43, 0xE9, 0x9D, 0xA2, 0x43,
+ 0xE9, 0x9D, 0xA9, 0x43, 0xE9, 0x9F, 0x8B, 0x43,
+ 0xE9, 0x9F, 0x9B, 0x43, 0xE9, 0x9F, 0xA0, 0x43,
+ 0xE9, 0x9F, 0xAD, 0x43, 0xE9, 0x9F, 0xB3, 0x43,
+ 0xE9, 0x9F, 0xBF, 0x43, 0xE9, 0xA0, 0x81, 0x43,
+ 0xE9, 0xA0, 0x85, 0x43, 0xE9, 0xA0, 0x8B, 0x43,
+ 0xE9, 0xA0, 0x98, 0x43, 0xE9, 0xA0, 0xA9, 0x43,
+ 0xE9, 0xA0, 0xBB, 0x43, 0xE9, 0xA1, 0x9E, 0x43,
+ // Bytes 1540 - 157f
+ 0xE9, 0xA2, 0xA8, 0x43, 0xE9, 0xA3, 0x9B, 0x43,
+ 0xE9, 0xA3, 0x9F, 0x43, 0xE9, 0xA3, 0xA2, 0x43,
+ 0xE9, 0xA3, 0xAF, 0x43, 0xE9, 0xA3, 0xBC, 0x43,
+ 0xE9, 0xA4, 0xA8, 0x43, 0xE9, 0xA4, 0xA9, 0x43,
+ 0xE9, 0xA6, 0x96, 0x43, 0xE9, 0xA6, 0x99, 0x43,
+ 0xE9, 0xA6, 0xA7, 0x43, 0xE9, 0xA6, 0xAC, 0x43,
+ 0xE9, 0xA7, 0x82, 0x43, 0xE9, 0xA7, 0xB1, 0x43,
+ 0xE9, 0xA7, 0xBE, 0x43, 0xE9, 0xA9, 0xAA, 0x43,
+ // Bytes 1580 - 15bf
+ 0xE9, 0xAA, 0xA8, 0x43, 0xE9, 0xAB, 0x98, 0x43,
+ 0xE9, 0xAB, 0x9F, 0x43, 0xE9, 0xAC, 0x92, 0x43,
+ 0xE9, 0xAC, 0xA5, 0x43, 0xE9, 0xAC, 0xAF, 0x43,
+ 0xE9, 0xAC, 0xB2, 0x43, 0xE9, 0xAC, 0xBC, 0x43,
+ 0xE9, 0xAD, 0x9A, 0x43, 0xE9, 0xAD, 0xAF, 0x43,
+ 0xE9, 0xB1, 0x80, 0x43, 0xE9, 0xB1, 0x97, 0x43,
+ 0xE9, 0xB3, 0xA5, 0x43, 0xE9, 0xB3, 0xBD, 0x43,
+ 0xE9, 0xB5, 0xA7, 0x43, 0xE9, 0xB6, 0xB4, 0x43,
+ // Bytes 15c0 - 15ff
+ 0xE9, 0xB7, 0xBA, 0x43, 0xE9, 0xB8, 0x9E, 0x43,
+ 0xE9, 0xB9, 0xB5, 0x43, 0xE9, 0xB9, 0xBF, 0x43,
+ 0xE9, 0xBA, 0x97, 0x43, 0xE9, 0xBA, 0x9F, 0x43,
+ 0xE9, 0xBA, 0xA5, 0x43, 0xE9, 0xBA, 0xBB, 0x43,
+ 0xE9, 0xBB, 0x83, 0x43, 0xE9, 0xBB, 0x8D, 0x43,
+ 0xE9, 0xBB, 0x8E, 0x43, 0xE9, 0xBB, 0x91, 0x43,
+ 0xE9, 0xBB, 0xB9, 0x43, 0xE9, 0xBB, 0xBD, 0x43,
+ 0xE9, 0xBB, 0xBE, 0x43, 0xE9, 0xBC, 0x85, 0x43,
+ // Bytes 1600 - 163f
+ 0xE9, 0xBC, 0x8E, 0x43, 0xE9, 0xBC, 0x8F, 0x43,
+ 0xE9, 0xBC, 0x93, 0x43, 0xE9, 0xBC, 0x96, 0x43,
+ 0xE9, 0xBC, 0xA0, 0x43, 0xE9, 0xBC, 0xBB, 0x43,
+ 0xE9, 0xBD, 0x83, 0x43, 0xE9, 0xBD, 0x8A, 0x43,
+ 0xE9, 0xBD, 0x92, 0x43, 0xE9, 0xBE, 0x8D, 0x43,
+ 0xE9, 0xBE, 0x8E, 0x43, 0xE9, 0xBE, 0x9C, 0x43,
+ 0xE9, 0xBE, 0x9F, 0x43, 0xE9, 0xBE, 0xA0, 0x43,
+ 0xEA, 0x9C, 0xA7, 0x43, 0xEA, 0x9D, 0xAF, 0x43,
+ // Bytes 1640 - 167f
+ 0xEA, 0xAC, 0xB7, 0x43, 0xEA, 0xAD, 0x92, 0x44,
+ 0xF0, 0xA0, 0x84, 0xA2, 0x44, 0xF0, 0xA0, 0x94,
+ 0x9C, 0x44, 0xF0, 0xA0, 0x94, 0xA5, 0x44, 0xF0,
+ 0xA0, 0x95, 0x8B, 0x44, 0xF0, 0xA0, 0x98, 0xBA,
+ 0x44, 0xF0, 0xA0, 0xA0, 0x84, 0x44, 0xF0, 0xA0,
+ 0xA3, 0x9E, 0x44, 0xF0, 0xA0, 0xA8, 0xAC, 0x44,
+ 0xF0, 0xA0, 0xAD, 0xA3, 0x44, 0xF0, 0xA1, 0x93,
+ 0xA4, 0x44, 0xF0, 0xA1, 0x9A, 0xA8, 0x44, 0xF0,
+ // Bytes 1680 - 16bf
+ 0xA1, 0x9B, 0xAA, 0x44, 0xF0, 0xA1, 0xA7, 0x88,
+ 0x44, 0xF0, 0xA1, 0xAC, 0x98, 0x44, 0xF0, 0xA1,
+ 0xB4, 0x8B, 0x44, 0xF0, 0xA1, 0xB7, 0xA4, 0x44,
+ 0xF0, 0xA1, 0xB7, 0xA6, 0x44, 0xF0, 0xA2, 0x86,
+ 0x83, 0x44, 0xF0, 0xA2, 0x86, 0x9F, 0x44, 0xF0,
+ 0xA2, 0x8C, 0xB1, 0x44, 0xF0, 0xA2, 0x9B, 0x94,
+ 0x44, 0xF0, 0xA2, 0xA1, 0x84, 0x44, 0xF0, 0xA2,
+ 0xA1, 0x8A, 0x44, 0xF0, 0xA2, 0xAC, 0x8C, 0x44,
+ // Bytes 16c0 - 16ff
+ 0xF0, 0xA2, 0xAF, 0xB1, 0x44, 0xF0, 0xA3, 0x80,
+ 0x8A, 0x44, 0xF0, 0xA3, 0x8A, 0xB8, 0x44, 0xF0,
+ 0xA3, 0x8D, 0x9F, 0x44, 0xF0, 0xA3, 0x8E, 0x93,
+ 0x44, 0xF0, 0xA3, 0x8E, 0x9C, 0x44, 0xF0, 0xA3,
+ 0x8F, 0x83, 0x44, 0xF0, 0xA3, 0x8F, 0x95, 0x44,
+ 0xF0, 0xA3, 0x91, 0xAD, 0x44, 0xF0, 0xA3, 0x9A,
+ 0xA3, 0x44, 0xF0, 0xA3, 0xA2, 0xA7, 0x44, 0xF0,
+ 0xA3, 0xAA, 0x8D, 0x44, 0xF0, 0xA3, 0xAB, 0xBA,
+ // Bytes 1700 - 173f
+ 0x44, 0xF0, 0xA3, 0xB2, 0xBC, 0x44, 0xF0, 0xA3,
+ 0xB4, 0x9E, 0x44, 0xF0, 0xA3, 0xBB, 0x91, 0x44,
+ 0xF0, 0xA3, 0xBD, 0x9E, 0x44, 0xF0, 0xA3, 0xBE,
+ 0x8E, 0x44, 0xF0, 0xA4, 0x89, 0xA3, 0x44, 0xF0,
+ 0xA4, 0x8B, 0xAE, 0x44, 0xF0, 0xA4, 0x8E, 0xAB,
+ 0x44, 0xF0, 0xA4, 0x98, 0x88, 0x44, 0xF0, 0xA4,
+ 0x9C, 0xB5, 0x44, 0xF0, 0xA4, 0xA0, 0x94, 0x44,
+ 0xF0, 0xA4, 0xB0, 0xB6, 0x44, 0xF0, 0xA4, 0xB2,
+ // Bytes 1740 - 177f
+ 0x92, 0x44, 0xF0, 0xA4, 0xBE, 0xA1, 0x44, 0xF0,
+ 0xA4, 0xBE, 0xB8, 0x44, 0xF0, 0xA5, 0x81, 0x84,
+ 0x44, 0xF0, 0xA5, 0x83, 0xB2, 0x44, 0xF0, 0xA5,
+ 0x83, 0xB3, 0x44, 0xF0, 0xA5, 0x84, 0x99, 0x44,
+ 0xF0, 0xA5, 0x84, 0xB3, 0x44, 0xF0, 0xA5, 0x89,
+ 0x89, 0x44, 0xF0, 0xA5, 0x90, 0x9D, 0x44, 0xF0,
+ 0xA5, 0x98, 0xA6, 0x44, 0xF0, 0xA5, 0x9A, 0x9A,
+ 0x44, 0xF0, 0xA5, 0x9B, 0x85, 0x44, 0xF0, 0xA5,
+ // Bytes 1780 - 17bf
+ 0xA5, 0xBC, 0x44, 0xF0, 0xA5, 0xAA, 0xA7, 0x44,
+ 0xF0, 0xA5, 0xAE, 0xAB, 0x44, 0xF0, 0xA5, 0xB2,
+ 0x80, 0x44, 0xF0, 0xA5, 0xB3, 0x90, 0x44, 0xF0,
+ 0xA5, 0xBE, 0x86, 0x44, 0xF0, 0xA6, 0x87, 0x9A,
+ 0x44, 0xF0, 0xA6, 0x88, 0xA8, 0x44, 0xF0, 0xA6,
+ 0x89, 0x87, 0x44, 0xF0, 0xA6, 0x8B, 0x99, 0x44,
+ 0xF0, 0xA6, 0x8C, 0xBE, 0x44, 0xF0, 0xA6, 0x93,
+ 0x9A, 0x44, 0xF0, 0xA6, 0x94, 0xA3, 0x44, 0xF0,
+ // Bytes 17c0 - 17ff
+ 0xA6, 0x96, 0xA8, 0x44, 0xF0, 0xA6, 0x9E, 0xA7,
+ 0x44, 0xF0, 0xA6, 0x9E, 0xB5, 0x44, 0xF0, 0xA6,
+ 0xAC, 0xBC, 0x44, 0xF0, 0xA6, 0xB0, 0xB6, 0x44,
+ 0xF0, 0xA6, 0xB3, 0x95, 0x44, 0xF0, 0xA6, 0xB5,
+ 0xAB, 0x44, 0xF0, 0xA6, 0xBC, 0xAC, 0x44, 0xF0,
+ 0xA6, 0xBE, 0xB1, 0x44, 0xF0, 0xA7, 0x83, 0x92,
+ 0x44, 0xF0, 0xA7, 0x8F, 0x8A, 0x44, 0xF0, 0xA7,
+ 0x99, 0xA7, 0x44, 0xF0, 0xA7, 0xA2, 0xAE, 0x44,
+ // Bytes 1800 - 183f
+ 0xF0, 0xA7, 0xA5, 0xA6, 0x44, 0xF0, 0xA7, 0xB2,
+ 0xA8, 0x44, 0xF0, 0xA7, 0xBB, 0x93, 0x44, 0xF0,
+ 0xA7, 0xBC, 0xAF, 0x44, 0xF0, 0xA8, 0x97, 0x92,
+ 0x44, 0xF0, 0xA8, 0x97, 0xAD, 0x44, 0xF0, 0xA8,
+ 0x9C, 0xAE, 0x44, 0xF0, 0xA8, 0xAF, 0xBA, 0x44,
+ 0xF0, 0xA8, 0xB5, 0xB7, 0x44, 0xF0, 0xA9, 0x85,
+ 0x85, 0x44, 0xF0, 0xA9, 0x87, 0x9F, 0x44, 0xF0,
+ 0xA9, 0x88, 0x9A, 0x44, 0xF0, 0xA9, 0x90, 0x8A,
+ // Bytes 1840 - 187f
+ 0x44, 0xF0, 0xA9, 0x92, 0x96, 0x44, 0xF0, 0xA9,
+ 0x96, 0xB6, 0x44, 0xF0, 0xA9, 0xAC, 0xB0, 0x44,
+ 0xF0, 0xAA, 0x83, 0x8E, 0x44, 0xF0, 0xAA, 0x84,
+ 0x85, 0x44, 0xF0, 0xAA, 0x88, 0x8E, 0x44, 0xF0,
+ 0xAA, 0x8A, 0x91, 0x44, 0xF0, 0xAA, 0x8E, 0x92,
+ 0x44, 0xF0, 0xAA, 0x98, 0x80, 0x42, 0x21, 0x21,
+ 0x42, 0x21, 0x3F, 0x42, 0x2E, 0x2E, 0x42, 0x30,
+ 0x2C, 0x42, 0x30, 0x2E, 0x42, 0x31, 0x2C, 0x42,
+ // Bytes 1880 - 18bf
+ 0x31, 0x2E, 0x42, 0x31, 0x30, 0x42, 0x31, 0x31,
+ 0x42, 0x31, 0x32, 0x42, 0x31, 0x33, 0x42, 0x31,
+ 0x34, 0x42, 0x31, 0x35, 0x42, 0x31, 0x36, 0x42,
+ 0x31, 0x37, 0x42, 0x31, 0x38, 0x42, 0x31, 0x39,
+ 0x42, 0x32, 0x2C, 0x42, 0x32, 0x2E, 0x42, 0x32,
+ 0x30, 0x42, 0x32, 0x31, 0x42, 0x32, 0x32, 0x42,
+ 0x32, 0x33, 0x42, 0x32, 0x34, 0x42, 0x32, 0x35,
+ 0x42, 0x32, 0x36, 0x42, 0x32, 0x37, 0x42, 0x32,
+ // Bytes 18c0 - 18ff
+ 0x38, 0x42, 0x32, 0x39, 0x42, 0x33, 0x2C, 0x42,
+ 0x33, 0x2E, 0x42, 0x33, 0x30, 0x42, 0x33, 0x31,
+ 0x42, 0x33, 0x32, 0x42, 0x33, 0x33, 0x42, 0x33,
+ 0x34, 0x42, 0x33, 0x35, 0x42, 0x33, 0x36, 0x42,
+ 0x33, 0x37, 0x42, 0x33, 0x38, 0x42, 0x33, 0x39,
+ 0x42, 0x34, 0x2C, 0x42, 0x34, 0x2E, 0x42, 0x34,
+ 0x30, 0x42, 0x34, 0x31, 0x42, 0x34, 0x32, 0x42,
+ 0x34, 0x33, 0x42, 0x34, 0x34, 0x42, 0x34, 0x35,
+ // Bytes 1900 - 193f
+ 0x42, 0x34, 0x36, 0x42, 0x34, 0x37, 0x42, 0x34,
+ 0x38, 0x42, 0x34, 0x39, 0x42, 0x35, 0x2C, 0x42,
+ 0x35, 0x2E, 0x42, 0x35, 0x30, 0x42, 0x36, 0x2C,
+ 0x42, 0x36, 0x2E, 0x42, 0x37, 0x2C, 0x42, 0x37,
+ 0x2E, 0x42, 0x38, 0x2C, 0x42, 0x38, 0x2E, 0x42,
+ 0x39, 0x2C, 0x42, 0x39, 0x2E, 0x42, 0x3D, 0x3D,
+ 0x42, 0x3F, 0x21, 0x42, 0x3F, 0x3F, 0x42, 0x41,
+ 0x55, 0x42, 0x42, 0x71, 0x42, 0x43, 0x44, 0x42,
+ // Bytes 1940 - 197f
+ 0x44, 0x4A, 0x42, 0x44, 0x5A, 0x42, 0x44, 0x7A,
+ 0x42, 0x47, 0x42, 0x42, 0x47, 0x79, 0x42, 0x48,
+ 0x50, 0x42, 0x48, 0x56, 0x42, 0x48, 0x67, 0x42,
+ 0x48, 0x7A, 0x42, 0x49, 0x49, 0x42, 0x49, 0x4A,
+ 0x42, 0x49, 0x55, 0x42, 0x49, 0x56, 0x42, 0x49,
+ 0x58, 0x42, 0x4B, 0x42, 0x42, 0x4B, 0x4B, 0x42,
+ 0x4B, 0x4D, 0x42, 0x4C, 0x4A, 0x42, 0x4C, 0x6A,
+ 0x42, 0x4D, 0x42, 0x42, 0x4D, 0x43, 0x42, 0x4D,
+ // Bytes 1980 - 19bf
+ 0x44, 0x42, 0x4D, 0x56, 0x42, 0x4D, 0x57, 0x42,
+ 0x4E, 0x4A, 0x42, 0x4E, 0x6A, 0x42, 0x4E, 0x6F,
+ 0x42, 0x50, 0x48, 0x42, 0x50, 0x52, 0x42, 0x50,
+ 0x61, 0x42, 0x52, 0x73, 0x42, 0x53, 0x44, 0x42,
+ 0x53, 0x4D, 0x42, 0x53, 0x53, 0x42, 0x53, 0x76,
+ 0x42, 0x54, 0x4D, 0x42, 0x56, 0x49, 0x42, 0x57,
+ 0x43, 0x42, 0x57, 0x5A, 0x42, 0x57, 0x62, 0x42,
+ 0x58, 0x49, 0x42, 0x63, 0x63, 0x42, 0x63, 0x64,
+ // Bytes 19c0 - 19ff
+ 0x42, 0x63, 0x6D, 0x42, 0x64, 0x42, 0x42, 0x64,
+ 0x61, 0x42, 0x64, 0x6C, 0x42, 0x64, 0x6D, 0x42,
+ 0x64, 0x7A, 0x42, 0x65, 0x56, 0x42, 0x66, 0x66,
+ 0x42, 0x66, 0x69, 0x42, 0x66, 0x6C, 0x42, 0x66,
+ 0x6D, 0x42, 0x68, 0x61, 0x42, 0x69, 0x69, 0x42,
+ 0x69, 0x6A, 0x42, 0x69, 0x6E, 0x42, 0x69, 0x76,
+ 0x42, 0x69, 0x78, 0x42, 0x6B, 0x41, 0x42, 0x6B,
+ 0x56, 0x42, 0x6B, 0x57, 0x42, 0x6B, 0x67, 0x42,
+ // Bytes 1a00 - 1a3f
+ 0x6B, 0x6C, 0x42, 0x6B, 0x6D, 0x42, 0x6B, 0x74,
+ 0x42, 0x6C, 0x6A, 0x42, 0x6C, 0x6D, 0x42, 0x6C,
+ 0x6E, 0x42, 0x6C, 0x78, 0x42, 0x6D, 0x32, 0x42,
+ 0x6D, 0x33, 0x42, 0x6D, 0x41, 0x42, 0x6D, 0x56,
+ 0x42, 0x6D, 0x57, 0x42, 0x6D, 0x62, 0x42, 0x6D,
+ 0x67, 0x42, 0x6D, 0x6C, 0x42, 0x6D, 0x6D, 0x42,
+ 0x6D, 0x73, 0x42, 0x6E, 0x41, 0x42, 0x6E, 0x46,
+ 0x42, 0x6E, 0x56, 0x42, 0x6E, 0x57, 0x42, 0x6E,
+ // Bytes 1a40 - 1a7f
+ 0x6A, 0x42, 0x6E, 0x6D, 0x42, 0x6E, 0x73, 0x42,
+ 0x6F, 0x56, 0x42, 0x70, 0x41, 0x42, 0x70, 0x46,
+ 0x42, 0x70, 0x56, 0x42, 0x70, 0x57, 0x42, 0x70,
+ 0x63, 0x42, 0x70, 0x73, 0x42, 0x73, 0x72, 0x42,
+ 0x73, 0x74, 0x42, 0x76, 0x69, 0x42, 0x78, 0x69,
+ 0x43, 0x28, 0x31, 0x29, 0x43, 0x28, 0x32, 0x29,
+ 0x43, 0x28, 0x33, 0x29, 0x43, 0x28, 0x34, 0x29,
+ 0x43, 0x28, 0x35, 0x29, 0x43, 0x28, 0x36, 0x29,
+ // Bytes 1a80 - 1abf
+ 0x43, 0x28, 0x37, 0x29, 0x43, 0x28, 0x38, 0x29,
+ 0x43, 0x28, 0x39, 0x29, 0x43, 0x28, 0x41, 0x29,
+ 0x43, 0x28, 0x42, 0x29, 0x43, 0x28, 0x43, 0x29,
+ 0x43, 0x28, 0x44, 0x29, 0x43, 0x28, 0x45, 0x29,
+ 0x43, 0x28, 0x46, 0x29, 0x43, 0x28, 0x47, 0x29,
+ 0x43, 0x28, 0x48, 0x29, 0x43, 0x28, 0x49, 0x29,
+ 0x43, 0x28, 0x4A, 0x29, 0x43, 0x28, 0x4B, 0x29,
+ 0x43, 0x28, 0x4C, 0x29, 0x43, 0x28, 0x4D, 0x29,
+ // Bytes 1ac0 - 1aff
+ 0x43, 0x28, 0x4E, 0x29, 0x43, 0x28, 0x4F, 0x29,
+ 0x43, 0x28, 0x50, 0x29, 0x43, 0x28, 0x51, 0x29,
+ 0x43, 0x28, 0x52, 0x29, 0x43, 0x28, 0x53, 0x29,
+ 0x43, 0x28, 0x54, 0x29, 0x43, 0x28, 0x55, 0x29,
+ 0x43, 0x28, 0x56, 0x29, 0x43, 0x28, 0x57, 0x29,
+ 0x43, 0x28, 0x58, 0x29, 0x43, 0x28, 0x59, 0x29,
+ 0x43, 0x28, 0x5A, 0x29, 0x43, 0x28, 0x61, 0x29,
+ 0x43, 0x28, 0x62, 0x29, 0x43, 0x28, 0x63, 0x29,
+ // Bytes 1b00 - 1b3f
+ 0x43, 0x28, 0x64, 0x29, 0x43, 0x28, 0x65, 0x29,
+ 0x43, 0x28, 0x66, 0x29, 0x43, 0x28, 0x67, 0x29,
+ 0x43, 0x28, 0x68, 0x29, 0x43, 0x28, 0x69, 0x29,
+ 0x43, 0x28, 0x6A, 0x29, 0x43, 0x28, 0x6B, 0x29,
+ 0x43, 0x28, 0x6C, 0x29, 0x43, 0x28, 0x6D, 0x29,
+ 0x43, 0x28, 0x6E, 0x29, 0x43, 0x28, 0x6F, 0x29,
+ 0x43, 0x28, 0x70, 0x29, 0x43, 0x28, 0x71, 0x29,
+ 0x43, 0x28, 0x72, 0x29, 0x43, 0x28, 0x73, 0x29,
+ // Bytes 1b40 - 1b7f
+ 0x43, 0x28, 0x74, 0x29, 0x43, 0x28, 0x75, 0x29,
+ 0x43, 0x28, 0x76, 0x29, 0x43, 0x28, 0x77, 0x29,
+ 0x43, 0x28, 0x78, 0x29, 0x43, 0x28, 0x79, 0x29,
+ 0x43, 0x28, 0x7A, 0x29, 0x43, 0x2E, 0x2E, 0x2E,
+ 0x43, 0x31, 0x30, 0x2E, 0x43, 0x31, 0x31, 0x2E,
+ 0x43, 0x31, 0x32, 0x2E, 0x43, 0x31, 0x33, 0x2E,
+ 0x43, 0x31, 0x34, 0x2E, 0x43, 0x31, 0x35, 0x2E,
+ 0x43, 0x31, 0x36, 0x2E, 0x43, 0x31, 0x37, 0x2E,
+ // Bytes 1b80 - 1bbf
+ 0x43, 0x31, 0x38, 0x2E, 0x43, 0x31, 0x39, 0x2E,
+ 0x43, 0x32, 0x30, 0x2E, 0x43, 0x3A, 0x3A, 0x3D,
+ 0x43, 0x3D, 0x3D, 0x3D, 0x43, 0x43, 0x6F, 0x2E,
+ 0x43, 0x46, 0x41, 0x58, 0x43, 0x47, 0x48, 0x7A,
+ 0x43, 0x47, 0x50, 0x61, 0x43, 0x49, 0x49, 0x49,
+ 0x43, 0x4C, 0x54, 0x44, 0x43, 0x4C, 0xC2, 0xB7,
+ 0x43, 0x4D, 0x48, 0x7A, 0x43, 0x4D, 0x50, 0x61,
+ 0x43, 0x4D, 0xCE, 0xA9, 0x43, 0x50, 0x50, 0x4D,
+ // Bytes 1bc0 - 1bff
+ 0x43, 0x50, 0x50, 0x56, 0x43, 0x50, 0x54, 0x45,
+ 0x43, 0x54, 0x45, 0x4C, 0x43, 0x54, 0x48, 0x7A,
+ 0x43, 0x56, 0x49, 0x49, 0x43, 0x58, 0x49, 0x49,
+ 0x43, 0x61, 0x2F, 0x63, 0x43, 0x61, 0x2F, 0x73,
+ 0x43, 0x61, 0xCA, 0xBE, 0x43, 0x62, 0x61, 0x72,
+ 0x43, 0x63, 0x2F, 0x6F, 0x43, 0x63, 0x2F, 0x75,
+ 0x43, 0x63, 0x61, 0x6C, 0x43, 0x63, 0x6D, 0x32,
+ 0x43, 0x63, 0x6D, 0x33, 0x43, 0x64, 0x6D, 0x32,
+ // Bytes 1c00 - 1c3f
+ 0x43, 0x64, 0x6D, 0x33, 0x43, 0x65, 0x72, 0x67,
+ 0x43, 0x66, 0x66, 0x69, 0x43, 0x66, 0x66, 0x6C,
+ 0x43, 0x67, 0x61, 0x6C, 0x43, 0x68, 0x50, 0x61,
+ 0x43, 0x69, 0x69, 0x69, 0x43, 0x6B, 0x48, 0x7A,
+ 0x43, 0x6B, 0x50, 0x61, 0x43, 0x6B, 0x6D, 0x32,
+ 0x43, 0x6B, 0x6D, 0x33, 0x43, 0x6B, 0xCE, 0xA9,
+ 0x43, 0x6C, 0x6F, 0x67, 0x43, 0x6C, 0xC2, 0xB7,
+ 0x43, 0x6D, 0x69, 0x6C, 0x43, 0x6D, 0x6D, 0x32,
+ // Bytes 1c40 - 1c7f
+ 0x43, 0x6D, 0x6D, 0x33, 0x43, 0x6D, 0x6F, 0x6C,
+ 0x43, 0x72, 0x61, 0x64, 0x43, 0x76, 0x69, 0x69,
+ 0x43, 0x78, 0x69, 0x69, 0x43, 0xC2, 0xB0, 0x43,
+ 0x43, 0xC2, 0xB0, 0x46, 0x43, 0xCA, 0xBC, 0x6E,
+ 0x43, 0xCE, 0xBC, 0x41, 0x43, 0xCE, 0xBC, 0x46,
+ 0x43, 0xCE, 0xBC, 0x56, 0x43, 0xCE, 0xBC, 0x57,
+ 0x43, 0xCE, 0xBC, 0x67, 0x43, 0xCE, 0xBC, 0x6C,
+ 0x43, 0xCE, 0xBC, 0x6D, 0x43, 0xCE, 0xBC, 0x73,
+ // Bytes 1c80 - 1cbf
+ 0x44, 0x28, 0x31, 0x30, 0x29, 0x44, 0x28, 0x31,
+ 0x31, 0x29, 0x44, 0x28, 0x31, 0x32, 0x29, 0x44,
+ 0x28, 0x31, 0x33, 0x29, 0x44, 0x28, 0x31, 0x34,
+ 0x29, 0x44, 0x28, 0x31, 0x35, 0x29, 0x44, 0x28,
+ 0x31, 0x36, 0x29, 0x44, 0x28, 0x31, 0x37, 0x29,
+ 0x44, 0x28, 0x31, 0x38, 0x29, 0x44, 0x28, 0x31,
+ 0x39, 0x29, 0x44, 0x28, 0x32, 0x30, 0x29, 0x44,
+ 0x30, 0xE7, 0x82, 0xB9, 0x44, 0x31, 0xE2, 0x81,
+ // Bytes 1cc0 - 1cff
+ 0x84, 0x44, 0x31, 0xE6, 0x97, 0xA5, 0x44, 0x31,
+ 0xE6, 0x9C, 0x88, 0x44, 0x31, 0xE7, 0x82, 0xB9,
+ 0x44, 0x32, 0xE6, 0x97, 0xA5, 0x44, 0x32, 0xE6,
+ 0x9C, 0x88, 0x44, 0x32, 0xE7, 0x82, 0xB9, 0x44,
+ 0x33, 0xE6, 0x97, 0xA5, 0x44, 0x33, 0xE6, 0x9C,
+ 0x88, 0x44, 0x33, 0xE7, 0x82, 0xB9, 0x44, 0x34,
+ 0xE6, 0x97, 0xA5, 0x44, 0x34, 0xE6, 0x9C, 0x88,
+ 0x44, 0x34, 0xE7, 0x82, 0xB9, 0x44, 0x35, 0xE6,
+ // Bytes 1d00 - 1d3f
+ 0x97, 0xA5, 0x44, 0x35, 0xE6, 0x9C, 0x88, 0x44,
+ 0x35, 0xE7, 0x82, 0xB9, 0x44, 0x36, 0xE6, 0x97,
+ 0xA5, 0x44, 0x36, 0xE6, 0x9C, 0x88, 0x44, 0x36,
+ 0xE7, 0x82, 0xB9, 0x44, 0x37, 0xE6, 0x97, 0xA5,
+ 0x44, 0x37, 0xE6, 0x9C, 0x88, 0x44, 0x37, 0xE7,
+ 0x82, 0xB9, 0x44, 0x38, 0xE6, 0x97, 0xA5, 0x44,
+ 0x38, 0xE6, 0x9C, 0x88, 0x44, 0x38, 0xE7, 0x82,
+ 0xB9, 0x44, 0x39, 0xE6, 0x97, 0xA5, 0x44, 0x39,
+ // Bytes 1d40 - 1d7f
+ 0xE6, 0x9C, 0x88, 0x44, 0x39, 0xE7, 0x82, 0xB9,
+ 0x44, 0x56, 0x49, 0x49, 0x49, 0x44, 0x61, 0x2E,
+ 0x6D, 0x2E, 0x44, 0x6B, 0x63, 0x61, 0x6C, 0x44,
+ 0x70, 0x2E, 0x6D, 0x2E, 0x44, 0x76, 0x69, 0x69,
+ 0x69, 0x44, 0xD5, 0xA5, 0xD6, 0x82, 0x44, 0xD5,
+ 0xB4, 0xD5, 0xA5, 0x44, 0xD5, 0xB4, 0xD5, 0xAB,
+ 0x44, 0xD5, 0xB4, 0xD5, 0xAD, 0x44, 0xD5, 0xB4,
+ 0xD5, 0xB6, 0x44, 0xD5, 0xBE, 0xD5, 0xB6, 0x44,
+ // Bytes 1d80 - 1dbf
+ 0xD7, 0x90, 0xD7, 0x9C, 0x44, 0xD8, 0xA7, 0xD9,
+ 0xB4, 0x44, 0xD8, 0xA8, 0xD8, 0xAC, 0x44, 0xD8,
+ 0xA8, 0xD8, 0xAD, 0x44, 0xD8, 0xA8, 0xD8, 0xAE,
+ 0x44, 0xD8, 0xA8, 0xD8, 0xB1, 0x44, 0xD8, 0xA8,
+ 0xD8, 0xB2, 0x44, 0xD8, 0xA8, 0xD9, 0x85, 0x44,
+ 0xD8, 0xA8, 0xD9, 0x86, 0x44, 0xD8, 0xA8, 0xD9,
+ 0x87, 0x44, 0xD8, 0xA8, 0xD9, 0x89, 0x44, 0xD8,
+ 0xA8, 0xD9, 0x8A, 0x44, 0xD8, 0xAA, 0xD8, 0xAC,
+ // Bytes 1dc0 - 1dff
+ 0x44, 0xD8, 0xAA, 0xD8, 0xAD, 0x44, 0xD8, 0xAA,
+ 0xD8, 0xAE, 0x44, 0xD8, 0xAA, 0xD8, 0xB1, 0x44,
+ 0xD8, 0xAA, 0xD8, 0xB2, 0x44, 0xD8, 0xAA, 0xD9,
+ 0x85, 0x44, 0xD8, 0xAA, 0xD9, 0x86, 0x44, 0xD8,
+ 0xAA, 0xD9, 0x87, 0x44, 0xD8, 0xAA, 0xD9, 0x89,
+ 0x44, 0xD8, 0xAA, 0xD9, 0x8A, 0x44, 0xD8, 0xAB,
+ 0xD8, 0xAC, 0x44, 0xD8, 0xAB, 0xD8, 0xB1, 0x44,
+ 0xD8, 0xAB, 0xD8, 0xB2, 0x44, 0xD8, 0xAB, 0xD9,
+ // Bytes 1e00 - 1e3f
+ 0x85, 0x44, 0xD8, 0xAB, 0xD9, 0x86, 0x44, 0xD8,
+ 0xAB, 0xD9, 0x87, 0x44, 0xD8, 0xAB, 0xD9, 0x89,
+ 0x44, 0xD8, 0xAB, 0xD9, 0x8A, 0x44, 0xD8, 0xAC,
+ 0xD8, 0xAD, 0x44, 0xD8, 0xAC, 0xD9, 0x85, 0x44,
+ 0xD8, 0xAC, 0xD9, 0x89, 0x44, 0xD8, 0xAC, 0xD9,
+ 0x8A, 0x44, 0xD8, 0xAD, 0xD8, 0xAC, 0x44, 0xD8,
+ 0xAD, 0xD9, 0x85, 0x44, 0xD8, 0xAD, 0xD9, 0x89,
+ 0x44, 0xD8, 0xAD, 0xD9, 0x8A, 0x44, 0xD8, 0xAE,
+ // Bytes 1e40 - 1e7f
+ 0xD8, 0xAC, 0x44, 0xD8, 0xAE, 0xD8, 0xAD, 0x44,
+ 0xD8, 0xAE, 0xD9, 0x85, 0x44, 0xD8, 0xAE, 0xD9,
+ 0x89, 0x44, 0xD8, 0xAE, 0xD9, 0x8A, 0x44, 0xD8,
+ 0xB3, 0xD8, 0xAC, 0x44, 0xD8, 0xB3, 0xD8, 0xAD,
+ 0x44, 0xD8, 0xB3, 0xD8, 0xAE, 0x44, 0xD8, 0xB3,
+ 0xD8, 0xB1, 0x44, 0xD8, 0xB3, 0xD9, 0x85, 0x44,
+ 0xD8, 0xB3, 0xD9, 0x87, 0x44, 0xD8, 0xB3, 0xD9,
+ 0x89, 0x44, 0xD8, 0xB3, 0xD9, 0x8A, 0x44, 0xD8,
+ // Bytes 1e80 - 1ebf
+ 0xB4, 0xD8, 0xAC, 0x44, 0xD8, 0xB4, 0xD8, 0xAD,
+ 0x44, 0xD8, 0xB4, 0xD8, 0xAE, 0x44, 0xD8, 0xB4,
+ 0xD8, 0xB1, 0x44, 0xD8, 0xB4, 0xD9, 0x85, 0x44,
+ 0xD8, 0xB4, 0xD9, 0x87, 0x44, 0xD8, 0xB4, 0xD9,
+ 0x89, 0x44, 0xD8, 0xB4, 0xD9, 0x8A, 0x44, 0xD8,
+ 0xB5, 0xD8, 0xAD, 0x44, 0xD8, 0xB5, 0xD8, 0xAE,
+ 0x44, 0xD8, 0xB5, 0xD8, 0xB1, 0x44, 0xD8, 0xB5,
+ 0xD9, 0x85, 0x44, 0xD8, 0xB5, 0xD9, 0x89, 0x44,
+ // Bytes 1ec0 - 1eff
+ 0xD8, 0xB5, 0xD9, 0x8A, 0x44, 0xD8, 0xB6, 0xD8,
+ 0xAC, 0x44, 0xD8, 0xB6, 0xD8, 0xAD, 0x44, 0xD8,
+ 0xB6, 0xD8, 0xAE, 0x44, 0xD8, 0xB6, 0xD8, 0xB1,
+ 0x44, 0xD8, 0xB6, 0xD9, 0x85, 0x44, 0xD8, 0xB6,
+ 0xD9, 0x89, 0x44, 0xD8, 0xB6, 0xD9, 0x8A, 0x44,
+ 0xD8, 0xB7, 0xD8, 0xAD, 0x44, 0xD8, 0xB7, 0xD9,
+ 0x85, 0x44, 0xD8, 0xB7, 0xD9, 0x89, 0x44, 0xD8,
+ 0xB7, 0xD9, 0x8A, 0x44, 0xD8, 0xB8, 0xD9, 0x85,
+ // Bytes 1f00 - 1f3f
+ 0x44, 0xD8, 0xB9, 0xD8, 0xAC, 0x44, 0xD8, 0xB9,
+ 0xD9, 0x85, 0x44, 0xD8, 0xB9, 0xD9, 0x89, 0x44,
+ 0xD8, 0xB9, 0xD9, 0x8A, 0x44, 0xD8, 0xBA, 0xD8,
+ 0xAC, 0x44, 0xD8, 0xBA, 0xD9, 0x85, 0x44, 0xD8,
+ 0xBA, 0xD9, 0x89, 0x44, 0xD8, 0xBA, 0xD9, 0x8A,
+ 0x44, 0xD9, 0x81, 0xD8, 0xAC, 0x44, 0xD9, 0x81,
+ 0xD8, 0xAD, 0x44, 0xD9, 0x81, 0xD8, 0xAE, 0x44,
+ 0xD9, 0x81, 0xD9, 0x85, 0x44, 0xD9, 0x81, 0xD9,
+ // Bytes 1f40 - 1f7f
+ 0x89, 0x44, 0xD9, 0x81, 0xD9, 0x8A, 0x44, 0xD9,
+ 0x82, 0xD8, 0xAD, 0x44, 0xD9, 0x82, 0xD9, 0x85,
+ 0x44, 0xD9, 0x82, 0xD9, 0x89, 0x44, 0xD9, 0x82,
+ 0xD9, 0x8A, 0x44, 0xD9, 0x83, 0xD8, 0xA7, 0x44,
+ 0xD9, 0x83, 0xD8, 0xAC, 0x44, 0xD9, 0x83, 0xD8,
+ 0xAD, 0x44, 0xD9, 0x83, 0xD8, 0xAE, 0x44, 0xD9,
+ 0x83, 0xD9, 0x84, 0x44, 0xD9, 0x83, 0xD9, 0x85,
+ 0x44, 0xD9, 0x83, 0xD9, 0x89, 0x44, 0xD9, 0x83,
+ // Bytes 1f80 - 1fbf
+ 0xD9, 0x8A, 0x44, 0xD9, 0x84, 0xD8, 0xA7, 0x44,
+ 0xD9, 0x84, 0xD8, 0xAC, 0x44, 0xD9, 0x84, 0xD8,
+ 0xAD, 0x44, 0xD9, 0x84, 0xD8, 0xAE, 0x44, 0xD9,
+ 0x84, 0xD9, 0x85, 0x44, 0xD9, 0x84, 0xD9, 0x87,
+ 0x44, 0xD9, 0x84, 0xD9, 0x89, 0x44, 0xD9, 0x84,
+ 0xD9, 0x8A, 0x44, 0xD9, 0x85, 0xD8, 0xA7, 0x44,
+ 0xD9, 0x85, 0xD8, 0xAC, 0x44, 0xD9, 0x85, 0xD8,
+ 0xAD, 0x44, 0xD9, 0x85, 0xD8, 0xAE, 0x44, 0xD9,
+ // Bytes 1fc0 - 1fff
+ 0x85, 0xD9, 0x85, 0x44, 0xD9, 0x85, 0xD9, 0x89,
+ 0x44, 0xD9, 0x85, 0xD9, 0x8A, 0x44, 0xD9, 0x86,
+ 0xD8, 0xAC, 0x44, 0xD9, 0x86, 0xD8, 0xAD, 0x44,
+ 0xD9, 0x86, 0xD8, 0xAE, 0x44, 0xD9, 0x86, 0xD8,
+ 0xB1, 0x44, 0xD9, 0x86, 0xD8, 0xB2, 0x44, 0xD9,
+ 0x86, 0xD9, 0x85, 0x44, 0xD9, 0x86, 0xD9, 0x86,
+ 0x44, 0xD9, 0x86, 0xD9, 0x87, 0x44, 0xD9, 0x86,
+ 0xD9, 0x89, 0x44, 0xD9, 0x86, 0xD9, 0x8A, 0x44,
+ // Bytes 2000 - 203f
+ 0xD9, 0x87, 0xD8, 0xAC, 0x44, 0xD9, 0x87, 0xD9,
+ 0x85, 0x44, 0xD9, 0x87, 0xD9, 0x89, 0x44, 0xD9,
+ 0x87, 0xD9, 0x8A, 0x44, 0xD9, 0x88, 0xD9, 0xB4,
+ 0x44, 0xD9, 0x8A, 0xD8, 0xAC, 0x44, 0xD9, 0x8A,
+ 0xD8, 0xAD, 0x44, 0xD9, 0x8A, 0xD8, 0xAE, 0x44,
+ 0xD9, 0x8A, 0xD8, 0xB1, 0x44, 0xD9, 0x8A, 0xD8,
+ 0xB2, 0x44, 0xD9, 0x8A, 0xD9, 0x85, 0x44, 0xD9,
+ 0x8A, 0xD9, 0x86, 0x44, 0xD9, 0x8A, 0xD9, 0x87,
+ // Bytes 2040 - 207f
+ 0x44, 0xD9, 0x8A, 0xD9, 0x89, 0x44, 0xD9, 0x8A,
+ 0xD9, 0x8A, 0x44, 0xD9, 0x8A, 0xD9, 0xB4, 0x44,
+ 0xDB, 0x87, 0xD9, 0xB4, 0x45, 0x28, 0xE1, 0x84,
+ 0x80, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x82, 0x29,
+ 0x45, 0x28, 0xE1, 0x84, 0x83, 0x29, 0x45, 0x28,
+ 0xE1, 0x84, 0x85, 0x29, 0x45, 0x28, 0xE1, 0x84,
+ 0x86, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x87, 0x29,
+ 0x45, 0x28, 0xE1, 0x84, 0x89, 0x29, 0x45, 0x28,
+ // Bytes 2080 - 20bf
+ 0xE1, 0x84, 0x8B, 0x29, 0x45, 0x28, 0xE1, 0x84,
+ 0x8C, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x8E, 0x29,
+ 0x45, 0x28, 0xE1, 0x84, 0x8F, 0x29, 0x45, 0x28,
+ 0xE1, 0x84, 0x90, 0x29, 0x45, 0x28, 0xE1, 0x84,
+ 0x91, 0x29, 0x45, 0x28, 0xE1, 0x84, 0x92, 0x29,
+ 0x45, 0x28, 0xE4, 0xB8, 0x80, 0x29, 0x45, 0x28,
+ 0xE4, 0xB8, 0x83, 0x29, 0x45, 0x28, 0xE4, 0xB8,
+ 0x89, 0x29, 0x45, 0x28, 0xE4, 0xB9, 0x9D, 0x29,
+ // Bytes 20c0 - 20ff
+ 0x45, 0x28, 0xE4, 0xBA, 0x8C, 0x29, 0x45, 0x28,
+ 0xE4, 0xBA, 0x94, 0x29, 0x45, 0x28, 0xE4, 0xBB,
+ 0xA3, 0x29, 0x45, 0x28, 0xE4, 0xBC, 0x81, 0x29,
+ 0x45, 0x28, 0xE4, 0xBC, 0x91, 0x29, 0x45, 0x28,
+ 0xE5, 0x85, 0xAB, 0x29, 0x45, 0x28, 0xE5, 0x85,
+ 0xAD, 0x29, 0x45, 0x28, 0xE5, 0x8A, 0xB4, 0x29,
+ 0x45, 0x28, 0xE5, 0x8D, 0x81, 0x29, 0x45, 0x28,
+ 0xE5, 0x8D, 0x94, 0x29, 0x45, 0x28, 0xE5, 0x90,
+ // Bytes 2100 - 213f
+ 0x8D, 0x29, 0x45, 0x28, 0xE5, 0x91, 0xBC, 0x29,
+ 0x45, 0x28, 0xE5, 0x9B, 0x9B, 0x29, 0x45, 0x28,
+ 0xE5, 0x9C, 0x9F, 0x29, 0x45, 0x28, 0xE5, 0xAD,
+ 0xA6, 0x29, 0x45, 0x28, 0xE6, 0x97, 0xA5, 0x29,
+ 0x45, 0x28, 0xE6, 0x9C, 0x88, 0x29, 0x45, 0x28,
+ 0xE6, 0x9C, 0x89, 0x29, 0x45, 0x28, 0xE6, 0x9C,
+ 0xA8, 0x29, 0x45, 0x28, 0xE6, 0xA0, 0xAA, 0x29,
+ 0x45, 0x28, 0xE6, 0xB0, 0xB4, 0x29, 0x45, 0x28,
+ // Bytes 2140 - 217f
+ 0xE7, 0x81, 0xAB, 0x29, 0x45, 0x28, 0xE7, 0x89,
+ 0xB9, 0x29, 0x45, 0x28, 0xE7, 0x9B, 0xA3, 0x29,
+ 0x45, 0x28, 0xE7, 0xA4, 0xBE, 0x29, 0x45, 0x28,
+ 0xE7, 0xA5, 0x9D, 0x29, 0x45, 0x28, 0xE7, 0xA5,
+ 0xAD, 0x29, 0x45, 0x28, 0xE8, 0x87, 0xAA, 0x29,
+ 0x45, 0x28, 0xE8, 0x87, 0xB3, 0x29, 0x45, 0x28,
+ 0xE8, 0xB2, 0xA1, 0x29, 0x45, 0x28, 0xE8, 0xB3,
+ 0x87, 0x29, 0x45, 0x28, 0xE9, 0x87, 0x91, 0x29,
+ // Bytes 2180 - 21bf
+ 0x45, 0x30, 0xE2, 0x81, 0x84, 0x33, 0x45, 0x31,
+ 0x30, 0xE6, 0x97, 0xA5, 0x45, 0x31, 0x30, 0xE6,
+ 0x9C, 0x88, 0x45, 0x31, 0x30, 0xE7, 0x82, 0xB9,
+ 0x45, 0x31, 0x31, 0xE6, 0x97, 0xA5, 0x45, 0x31,
+ 0x31, 0xE6, 0x9C, 0x88, 0x45, 0x31, 0x31, 0xE7,
+ 0x82, 0xB9, 0x45, 0x31, 0x32, 0xE6, 0x97, 0xA5,
+ 0x45, 0x31, 0x32, 0xE6, 0x9C, 0x88, 0x45, 0x31,
+ 0x32, 0xE7, 0x82, 0xB9, 0x45, 0x31, 0x33, 0xE6,
+ // Bytes 21c0 - 21ff
+ 0x97, 0xA5, 0x45, 0x31, 0x33, 0xE7, 0x82, 0xB9,
+ 0x45, 0x31, 0x34, 0xE6, 0x97, 0xA5, 0x45, 0x31,
+ 0x34, 0xE7, 0x82, 0xB9, 0x45, 0x31, 0x35, 0xE6,
+ 0x97, 0xA5, 0x45, 0x31, 0x35, 0xE7, 0x82, 0xB9,
+ 0x45, 0x31, 0x36, 0xE6, 0x97, 0xA5, 0x45, 0x31,
+ 0x36, 0xE7, 0x82, 0xB9, 0x45, 0x31, 0x37, 0xE6,
+ 0x97, 0xA5, 0x45, 0x31, 0x37, 0xE7, 0x82, 0xB9,
+ 0x45, 0x31, 0x38, 0xE6, 0x97, 0xA5, 0x45, 0x31,
+ // Bytes 2200 - 223f
+ 0x38, 0xE7, 0x82, 0xB9, 0x45, 0x31, 0x39, 0xE6,
+ 0x97, 0xA5, 0x45, 0x31, 0x39, 0xE7, 0x82, 0xB9,
+ 0x45, 0x31, 0xE2, 0x81, 0x84, 0x32, 0x45, 0x31,
+ 0xE2, 0x81, 0x84, 0x33, 0x45, 0x31, 0xE2, 0x81,
+ 0x84, 0x34, 0x45, 0x31, 0xE2, 0x81, 0x84, 0x35,
+ 0x45, 0x31, 0xE2, 0x81, 0x84, 0x36, 0x45, 0x31,
+ 0xE2, 0x81, 0x84, 0x37, 0x45, 0x31, 0xE2, 0x81,
+ 0x84, 0x38, 0x45, 0x31, 0xE2, 0x81, 0x84, 0x39,
+ // Bytes 2240 - 227f
+ 0x45, 0x32, 0x30, 0xE6, 0x97, 0xA5, 0x45, 0x32,
+ 0x30, 0xE7, 0x82, 0xB9, 0x45, 0x32, 0x31, 0xE6,
+ 0x97, 0xA5, 0x45, 0x32, 0x31, 0xE7, 0x82, 0xB9,
+ 0x45, 0x32, 0x32, 0xE6, 0x97, 0xA5, 0x45, 0x32,
+ 0x32, 0xE7, 0x82, 0xB9, 0x45, 0x32, 0x33, 0xE6,
+ 0x97, 0xA5, 0x45, 0x32, 0x33, 0xE7, 0x82, 0xB9,
+ 0x45, 0x32, 0x34, 0xE6, 0x97, 0xA5, 0x45, 0x32,
+ 0x34, 0xE7, 0x82, 0xB9, 0x45, 0x32, 0x35, 0xE6,
+ // Bytes 2280 - 22bf
+ 0x97, 0xA5, 0x45, 0x32, 0x36, 0xE6, 0x97, 0xA5,
+ 0x45, 0x32, 0x37, 0xE6, 0x97, 0xA5, 0x45, 0x32,
+ 0x38, 0xE6, 0x97, 0xA5, 0x45, 0x32, 0x39, 0xE6,
+ 0x97, 0xA5, 0x45, 0x32, 0xE2, 0x81, 0x84, 0x33,
+ 0x45, 0x32, 0xE2, 0x81, 0x84, 0x35, 0x45, 0x33,
+ 0x30, 0xE6, 0x97, 0xA5, 0x45, 0x33, 0x31, 0xE6,
+ 0x97, 0xA5, 0x45, 0x33, 0xE2, 0x81, 0x84, 0x34,
+ 0x45, 0x33, 0xE2, 0x81, 0x84, 0x35, 0x45, 0x33,
+ // Bytes 22c0 - 22ff
+ 0xE2, 0x81, 0x84, 0x38, 0x45, 0x34, 0xE2, 0x81,
+ 0x84, 0x35, 0x45, 0x35, 0xE2, 0x81, 0x84, 0x36,
+ 0x45, 0x35, 0xE2, 0x81, 0x84, 0x38, 0x45, 0x37,
+ 0xE2, 0x81, 0x84, 0x38, 0x45, 0x41, 0xE2, 0x88,
+ 0x95, 0x6D, 0x45, 0x56, 0xE2, 0x88, 0x95, 0x6D,
+ 0x45, 0x6D, 0xE2, 0x88, 0x95, 0x73, 0x46, 0x31,
+ 0xE2, 0x81, 0x84, 0x31, 0x30, 0x46, 0x43, 0xE2,
+ 0x88, 0x95, 0x6B, 0x67, 0x46, 0x6D, 0xE2, 0x88,
+ // Bytes 2300 - 233f
+ 0x95, 0x73, 0x32, 0x46, 0xD8, 0xA8, 0xD8, 0xAD,
+ 0xD9, 0x8A, 0x46, 0xD8, 0xA8, 0xD8, 0xAE, 0xD9,
+ 0x8A, 0x46, 0xD8, 0xAA, 0xD8, 0xAC, 0xD9, 0x85,
+ 0x46, 0xD8, 0xAA, 0xD8, 0xAC, 0xD9, 0x89, 0x46,
+ 0xD8, 0xAA, 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD8,
+ 0xAA, 0xD8, 0xAD, 0xD8, 0xAC, 0x46, 0xD8, 0xAA,
+ 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD8, 0xAA, 0xD8,
+ 0xAE, 0xD9, 0x85, 0x46, 0xD8, 0xAA, 0xD8, 0xAE,
+ // Bytes 2340 - 237f
+ 0xD9, 0x89, 0x46, 0xD8, 0xAA, 0xD8, 0xAE, 0xD9,
+ 0x8A, 0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD8, 0xAC,
+ 0x46, 0xD8, 0xAA, 0xD9, 0x85, 0xD8, 0xAD, 0x46,
+ 0xD8, 0xAA, 0xD9, 0x85, 0xD8, 0xAE, 0x46, 0xD8,
+ 0xAA, 0xD9, 0x85, 0xD9, 0x89, 0x46, 0xD8, 0xAA,
+ 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD8, 0xAC, 0xD8,
+ 0xAD, 0xD9, 0x89, 0x46, 0xD8, 0xAC, 0xD8, 0xAD,
+ 0xD9, 0x8A, 0x46, 0xD8, 0xAC, 0xD9, 0x85, 0xD8,
+ // Bytes 2380 - 23bf
+ 0xAD, 0x46, 0xD8, 0xAC, 0xD9, 0x85, 0xD9, 0x89,
+ 0x46, 0xD8, 0xAC, 0xD9, 0x85, 0xD9, 0x8A, 0x46,
+ 0xD8, 0xAD, 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD8,
+ 0xAD, 0xD9, 0x85, 0xD9, 0x89, 0x46, 0xD8, 0xAD,
+ 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD8, 0xB3, 0xD8,
+ 0xAC, 0xD8, 0xAD, 0x46, 0xD8, 0xB3, 0xD8, 0xAC,
+ 0xD9, 0x89, 0x46, 0xD8, 0xB3, 0xD8, 0xAD, 0xD8,
+ 0xAC, 0x46, 0xD8, 0xB3, 0xD8, 0xAE, 0xD9, 0x89,
+ // Bytes 23c0 - 23ff
+ 0x46, 0xD8, 0xB3, 0xD8, 0xAE, 0xD9, 0x8A, 0x46,
+ 0xD8, 0xB3, 0xD9, 0x85, 0xD8, 0xAC, 0x46, 0xD8,
+ 0xB3, 0xD9, 0x85, 0xD8, 0xAD, 0x46, 0xD8, 0xB3,
+ 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD8, 0xB4, 0xD8,
+ 0xAC, 0xD9, 0x8A, 0x46, 0xD8, 0xB4, 0xD8, 0xAD,
+ 0xD9, 0x85, 0x46, 0xD8, 0xB4, 0xD8, 0xAD, 0xD9,
+ 0x8A, 0x46, 0xD8, 0xB4, 0xD9, 0x85, 0xD8, 0xAE,
+ 0x46, 0xD8, 0xB4, 0xD9, 0x85, 0xD9, 0x85, 0x46,
+ // Bytes 2400 - 243f
+ 0xD8, 0xB5, 0xD8, 0xAD, 0xD8, 0xAD, 0x46, 0xD8,
+ 0xB5, 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD8, 0xB5,
+ 0xD9, 0x84, 0xD9, 0x89, 0x46, 0xD8, 0xB5, 0xD9,
+ 0x84, 0xDB, 0x92, 0x46, 0xD8, 0xB5, 0xD9, 0x85,
+ 0xD9, 0x85, 0x46, 0xD8, 0xB6, 0xD8, 0xAD, 0xD9,
+ 0x89, 0x46, 0xD8, 0xB6, 0xD8, 0xAD, 0xD9, 0x8A,
+ 0x46, 0xD8, 0xB6, 0xD8, 0xAE, 0xD9, 0x85, 0x46,
+ 0xD8, 0xB7, 0xD9, 0x85, 0xD8, 0xAD, 0x46, 0xD8,
+ // Bytes 2440 - 247f
+ 0xB7, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD8, 0xB7,
+ 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD8, 0xB9, 0xD8,
+ 0xAC, 0xD9, 0x85, 0x46, 0xD8, 0xB9, 0xD9, 0x85,
+ 0xD9, 0x85, 0x46, 0xD8, 0xB9, 0xD9, 0x85, 0xD9,
+ 0x89, 0x46, 0xD8, 0xB9, 0xD9, 0x85, 0xD9, 0x8A,
+ 0x46, 0xD8, 0xBA, 0xD9, 0x85, 0xD9, 0x85, 0x46,
+ 0xD8, 0xBA, 0xD9, 0x85, 0xD9, 0x89, 0x46, 0xD8,
+ 0xBA, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x81,
+ // Bytes 2480 - 24bf
+ 0xD8, 0xAE, 0xD9, 0x85, 0x46, 0xD9, 0x81, 0xD9,
+ 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x82, 0xD9, 0x84,
+ 0xDB, 0x92, 0x46, 0xD9, 0x82, 0xD9, 0x85, 0xD8,
+ 0xAD, 0x46, 0xD9, 0x82, 0xD9, 0x85, 0xD9, 0x85,
+ 0x46, 0xD9, 0x82, 0xD9, 0x85, 0xD9, 0x8A, 0x46,
+ 0xD9, 0x83, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD9,
+ 0x83, 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x84,
+ 0xD8, 0xAC, 0xD8, 0xAC, 0x46, 0xD9, 0x84, 0xD8,
+ // Bytes 24c0 - 24ff
+ 0xAC, 0xD9, 0x85, 0x46, 0xD9, 0x84, 0xD8, 0xAC,
+ 0xD9, 0x8A, 0x46, 0xD9, 0x84, 0xD8, 0xAD, 0xD9,
+ 0x85, 0x46, 0xD9, 0x84, 0xD8, 0xAD, 0xD9, 0x89,
+ 0x46, 0xD9, 0x84, 0xD8, 0xAD, 0xD9, 0x8A, 0x46,
+ 0xD9, 0x84, 0xD8, 0xAE, 0xD9, 0x85, 0x46, 0xD9,
+ 0x84, 0xD9, 0x85, 0xD8, 0xAD, 0x46, 0xD9, 0x84,
+ 0xD9, 0x85, 0xD9, 0x8A, 0x46, 0xD9, 0x85, 0xD8,
+ 0xAC, 0xD8, 0xAD, 0x46, 0xD9, 0x85, 0xD8, 0xAC,
+ // Bytes 2500 - 253f
+ 0xD8, 0xAE, 0x46, 0xD9, 0x85, 0xD8, 0xAC, 0xD9,
+ 0x85, 0x46, 0xD9, 0x85, 0xD8, 0xAC, 0xD9, 0x8A,
+ 0x46, 0xD9, 0x85, 0xD8, 0xAD, 0xD8, 0xAC, 0x46,
+ 0xD9, 0x85, 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD9,
+ 0x85, 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD9, 0x85,
+ 0xD8, 0xAE, 0xD8, 0xAC, 0x46, 0xD9, 0x85, 0xD8,
+ 0xAE, 0xD9, 0x85, 0x46, 0xD9, 0x85, 0xD8, 0xAE,
+ 0xD9, 0x8A, 0x46, 0xD9, 0x85, 0xD9, 0x85, 0xD9,
+ // Bytes 2540 - 257f
+ 0x8A, 0x46, 0xD9, 0x86, 0xD8, 0xAC, 0xD8, 0xAD,
+ 0x46, 0xD9, 0x86, 0xD8, 0xAC, 0xD9, 0x85, 0x46,
+ 0xD9, 0x86, 0xD8, 0xAC, 0xD9, 0x89, 0x46, 0xD9,
+ 0x86, 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD9, 0x86,
+ 0xD8, 0xAD, 0xD9, 0x85, 0x46, 0xD9, 0x86, 0xD8,
+ 0xAD, 0xD9, 0x89, 0x46, 0xD9, 0x86, 0xD8, 0xAD,
+ 0xD9, 0x8A, 0x46, 0xD9, 0x86, 0xD9, 0x85, 0xD9,
+ 0x89, 0x46, 0xD9, 0x86, 0xD9, 0x85, 0xD9, 0x8A,
+ // Bytes 2580 - 25bf
+ 0x46, 0xD9, 0x87, 0xD9, 0x85, 0xD8, 0xAC, 0x46,
+ 0xD9, 0x87, 0xD9, 0x85, 0xD9, 0x85, 0x46, 0xD9,
+ 0x8A, 0xD8, 0xAC, 0xD9, 0x8A, 0x46, 0xD9, 0x8A,
+ 0xD8, 0xAD, 0xD9, 0x8A, 0x46, 0xD9, 0x8A, 0xD9,
+ 0x85, 0xD9, 0x85, 0x46, 0xD9, 0x8A, 0xD9, 0x85,
+ 0xD9, 0x8A, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8,
+ 0xA7, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xAC,
+ 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xAD, 0x46,
+ // Bytes 25c0 - 25ff
+ 0xD9, 0x8A, 0xD9, 0x94, 0xD8, 0xAE, 0x46, 0xD9,
+ 0x8A, 0xD9, 0x94, 0xD8, 0xB1, 0x46, 0xD9, 0x8A,
+ 0xD9, 0x94, 0xD8, 0xB2, 0x46, 0xD9, 0x8A, 0xD9,
+ 0x94, 0xD9, 0x85, 0x46, 0xD9, 0x8A, 0xD9, 0x94,
+ 0xD9, 0x86, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD9,
+ 0x87, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD9, 0x88,
+ 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xD9, 0x89, 0x46,
+ 0xD9, 0x8A, 0xD9, 0x94, 0xD9, 0x8A, 0x46, 0xD9,
+ // Bytes 2600 - 263f
+ 0x8A, 0xD9, 0x94, 0xDB, 0x86, 0x46, 0xD9, 0x8A,
+ 0xD9, 0x94, 0xDB, 0x87, 0x46, 0xD9, 0x8A, 0xD9,
+ 0x94, 0xDB, 0x88, 0x46, 0xD9, 0x8A, 0xD9, 0x94,
+ 0xDB, 0x90, 0x46, 0xD9, 0x8A, 0xD9, 0x94, 0xDB,
+ 0x95, 0x46, 0xE0, 0xB9, 0x8D, 0xE0, 0xB8, 0xB2,
+ 0x46, 0xE0, 0xBA, 0xAB, 0xE0, 0xBA, 0x99, 0x46,
+ 0xE0, 0xBA, 0xAB, 0xE0, 0xBA, 0xA1, 0x46, 0xE0,
+ 0xBB, 0x8D, 0xE0, 0xBA, 0xB2, 0x46, 0xE0, 0xBD,
+ // Bytes 2640 - 267f
+ 0x80, 0xE0, 0xBE, 0xB5, 0x46, 0xE0, 0xBD, 0x82,
+ 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBD, 0x8C, 0xE0,
+ 0xBE, 0xB7, 0x46, 0xE0, 0xBD, 0x91, 0xE0, 0xBE,
+ 0xB7, 0x46, 0xE0, 0xBD, 0x96, 0xE0, 0xBE, 0xB7,
+ 0x46, 0xE0, 0xBD, 0x9B, 0xE0, 0xBE, 0xB7, 0x46,
+ 0xE0, 0xBE, 0x90, 0xE0, 0xBE, 0xB5, 0x46, 0xE0,
+ 0xBE, 0x92, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE,
+ 0x9C, 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE, 0xA1,
+ // Bytes 2680 - 26bf
+ 0xE0, 0xBE, 0xB7, 0x46, 0xE0, 0xBE, 0xA6, 0xE0,
+ 0xBE, 0xB7, 0x46, 0xE0, 0xBE, 0xAB, 0xE0, 0xBE,
+ 0xB7, 0x46, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2,
+ 0x46, 0xE2, 0x80, 0xB5, 0xE2, 0x80, 0xB5, 0x46,
+ 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB, 0x46, 0xE2,
+ 0x88, 0xAE, 0xE2, 0x88, 0xAE, 0x46, 0xE3, 0x81,
+ 0xBB, 0xE3, 0x81, 0x8B, 0x46, 0xE3, 0x82, 0x88,
+ 0xE3, 0x82, 0x8A, 0x46, 0xE3, 0x82, 0xAD, 0xE3,
+ // Bytes 26c0 - 26ff
+ 0x83, 0xAD, 0x46, 0xE3, 0x82, 0xB3, 0xE3, 0x82,
+ 0xB3, 0x46, 0xE3, 0x82, 0xB3, 0xE3, 0x83, 0x88,
+ 0x46, 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xB3, 0x46,
+ 0xE3, 0x83, 0x8A, 0xE3, 0x83, 0x8E, 0x46, 0xE3,
+ 0x83, 0x9B, 0xE3, 0x83, 0xB3, 0x46, 0xE3, 0x83,
+ 0x9F, 0xE3, 0x83, 0xAA, 0x46, 0xE3, 0x83, 0xAA,
+ 0xE3, 0x83, 0xA9, 0x46, 0xE3, 0x83, 0xAC, 0xE3,
+ 0x83, 0xA0, 0x46, 0xE5, 0xA4, 0xA7, 0xE6, 0xAD,
+ // Bytes 2700 - 273f
+ 0xA3, 0x46, 0xE5, 0xB9, 0xB3, 0xE6, 0x88, 0x90,
+ 0x46, 0xE6, 0x98, 0x8E, 0xE6, 0xB2, 0xBB, 0x46,
+ 0xE6, 0x98, 0xAD, 0xE5, 0x92, 0x8C, 0x47, 0x72,
+ 0x61, 0x64, 0xE2, 0x88, 0x95, 0x73, 0x47, 0xE3,
+ 0x80, 0x94, 0x53, 0xE3, 0x80, 0x95, 0x48, 0x28,
+ 0xE1, 0x84, 0x80, 0xE1, 0x85, 0xA1, 0x29, 0x48,
+ 0x28, 0xE1, 0x84, 0x82, 0xE1, 0x85, 0xA1, 0x29,
+ 0x48, 0x28, 0xE1, 0x84, 0x83, 0xE1, 0x85, 0xA1,
+ // Bytes 2740 - 277f
+ 0x29, 0x48, 0x28, 0xE1, 0x84, 0x85, 0xE1, 0x85,
+ 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x86, 0xE1,
+ 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x87,
+ 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84,
+ 0x89, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1,
+ 0x84, 0x8B, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28,
+ 0xE1, 0x84, 0x8C, 0xE1, 0x85, 0xA1, 0x29, 0x48,
+ 0x28, 0xE1, 0x84, 0x8C, 0xE1, 0x85, 0xAE, 0x29,
+ // Bytes 2780 - 27bf
+ 0x48, 0x28, 0xE1, 0x84, 0x8E, 0xE1, 0x85, 0xA1,
+ 0x29, 0x48, 0x28, 0xE1, 0x84, 0x8F, 0xE1, 0x85,
+ 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x90, 0xE1,
+ 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84, 0x91,
+ 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x28, 0xE1, 0x84,
+ 0x92, 0xE1, 0x85, 0xA1, 0x29, 0x48, 0x72, 0x61,
+ 0x64, 0xE2, 0x88, 0x95, 0x73, 0x32, 0x48, 0xD8,
+ 0xA7, 0xD9, 0x83, 0xD8, 0xA8, 0xD8, 0xB1, 0x48,
+ // Bytes 27c0 - 27ff
+ 0xD8, 0xA7, 0xD9, 0x84, 0xD9, 0x84, 0xD9, 0x87,
+ 0x48, 0xD8, 0xB1, 0xD8, 0xB3, 0xD9, 0x88, 0xD9,
+ 0x84, 0x48, 0xD8, 0xB1, 0xDB, 0x8C, 0xD8, 0xA7,
+ 0xD9, 0x84, 0x48, 0xD8, 0xB5, 0xD9, 0x84, 0xD8,
+ 0xB9, 0xD9, 0x85, 0x48, 0xD8, 0xB9, 0xD9, 0x84,
+ 0xD9, 0x8A, 0xD9, 0x87, 0x48, 0xD9, 0x85, 0xD8,
+ 0xAD, 0xD9, 0x85, 0xD8, 0xAF, 0x48, 0xD9, 0x88,
+ 0xD8, 0xB3, 0xD9, 0x84, 0xD9, 0x85, 0x49, 0xE2,
+ // Bytes 2800 - 283f
+ 0x80, 0xB2, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2,
+ 0x49, 0xE2, 0x80, 0xB5, 0xE2, 0x80, 0xB5, 0xE2,
+ 0x80, 0xB5, 0x49, 0xE2, 0x88, 0xAB, 0xE2, 0x88,
+ 0xAB, 0xE2, 0x88, 0xAB, 0x49, 0xE2, 0x88, 0xAE,
+ 0xE2, 0x88, 0xAE, 0xE2, 0x88, 0xAE, 0x49, 0xE3,
+ 0x80, 0x94, 0xE4, 0xB8, 0x89, 0xE3, 0x80, 0x95,
+ 0x49, 0xE3, 0x80, 0x94, 0xE4, 0xBA, 0x8C, 0xE3,
+ 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94, 0xE5, 0x8B,
+ // Bytes 2840 - 287f
+ 0x9D, 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94,
+ 0xE5, 0xAE, 0x89, 0xE3, 0x80, 0x95, 0x49, 0xE3,
+ 0x80, 0x94, 0xE6, 0x89, 0x93, 0xE3, 0x80, 0x95,
+ 0x49, 0xE3, 0x80, 0x94, 0xE6, 0x95, 0x97, 0xE3,
+ 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94, 0xE6, 0x9C,
+ 0xAC, 0xE3, 0x80, 0x95, 0x49, 0xE3, 0x80, 0x94,
+ 0xE7, 0x82, 0xB9, 0xE3, 0x80, 0x95, 0x49, 0xE3,
+ 0x80, 0x94, 0xE7, 0x9B, 0x97, 0xE3, 0x80, 0x95,
+ // Bytes 2880 - 28bf
+ 0x49, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0xBC, 0xE3,
+ 0x83, 0xAB, 0x49, 0xE3, 0x82, 0xA4, 0xE3, 0x83,
+ 0xB3, 0xE3, 0x83, 0x81, 0x49, 0xE3, 0x82, 0xA6,
+ 0xE3, 0x82, 0xA9, 0xE3, 0x83, 0xB3, 0x49, 0xE3,
+ 0x82, 0xAA, 0xE3, 0x83, 0xB3, 0xE3, 0x82, 0xB9,
+ 0x49, 0xE3, 0x82, 0xAA, 0xE3, 0x83, 0xBC, 0xE3,
+ 0x83, 0xA0, 0x49, 0xE3, 0x82, 0xAB, 0xE3, 0x82,
+ 0xA4, 0xE3, 0x83, 0xAA, 0x49, 0xE3, 0x82, 0xB1,
+ // Bytes 28c0 - 28ff
+ 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xB9, 0x49, 0xE3,
+ 0x82, 0xB3, 0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x8A,
+ 0x49, 0xE3, 0x82, 0xBB, 0xE3, 0x83, 0xB3, 0xE3,
+ 0x83, 0x81, 0x49, 0xE3, 0x82, 0xBB, 0xE3, 0x83,
+ 0xB3, 0xE3, 0x83, 0x88, 0x49, 0xE3, 0x83, 0x86,
+ 0xE3, 0x82, 0x99, 0xE3, 0x82, 0xB7, 0x49, 0xE3,
+ 0x83, 0x88, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xAB,
+ 0x49, 0xE3, 0x83, 0x8E, 0xE3, 0x83, 0x83, 0xE3,
+ // Bytes 2900 - 293f
+ 0x83, 0x88, 0x49, 0xE3, 0x83, 0x8F, 0xE3, 0x82,
+ 0xA4, 0xE3, 0x83, 0x84, 0x49, 0xE3, 0x83, 0x92,
+ 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xAB, 0x49, 0xE3,
+ 0x83, 0x92, 0xE3, 0x82, 0x9A, 0xE3, 0x82, 0xB3,
+ 0x49, 0xE3, 0x83, 0x95, 0xE3, 0x83, 0xA9, 0xE3,
+ 0x83, 0xB3, 0x49, 0xE3, 0x83, 0x98, 0xE3, 0x82,
+ 0x9A, 0xE3, 0x82, 0xBD, 0x49, 0xE3, 0x83, 0x98,
+ 0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x84, 0x49, 0xE3,
+ // Bytes 2940 - 297f
+ 0x83, 0x9B, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0xAB,
+ 0x49, 0xE3, 0x83, 0x9B, 0xE3, 0x83, 0xBC, 0xE3,
+ 0x83, 0xB3, 0x49, 0xE3, 0x83, 0x9E, 0xE3, 0x82,
+ 0xA4, 0xE3, 0x83, 0xAB, 0x49, 0xE3, 0x83, 0x9E,
+ 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x8F, 0x49, 0xE3,
+ 0x83, 0x9E, 0xE3, 0x83, 0xAB, 0xE3, 0x82, 0xAF,
+ 0x49, 0xE3, 0x83, 0xA4, 0xE3, 0x83, 0xBC, 0xE3,
+ 0x83, 0xAB, 0x49, 0xE3, 0x83, 0xA6, 0xE3, 0x82,
+ // Bytes 2980 - 29bf
+ 0xA2, 0xE3, 0x83, 0xB3, 0x49, 0xE3, 0x83, 0xAF,
+ 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88, 0x4C, 0xE2,
+ 0x80, 0xB2, 0xE2, 0x80, 0xB2, 0xE2, 0x80, 0xB2,
+ 0xE2, 0x80, 0xB2, 0x4C, 0xE2, 0x88, 0xAB, 0xE2,
+ 0x88, 0xAB, 0xE2, 0x88, 0xAB, 0xE2, 0x88, 0xAB,
+ 0x4C, 0xE3, 0x82, 0xA2, 0xE3, 0x83, 0xAB, 0xE3,
+ 0x83, 0x95, 0xE3, 0x82, 0xA1, 0x4C, 0xE3, 0x82,
+ 0xA8, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xAB, 0xE3,
+ // Bytes 29c0 - 29ff
+ 0x83, 0xBC, 0x4C, 0xE3, 0x82, 0xAB, 0xE3, 0x82,
+ 0x99, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xB3, 0x4C,
+ 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ 0xB3, 0xE3, 0x83, 0x9E, 0x4C, 0xE3, 0x82, 0xAB,
+ 0xE3, 0x83, 0xA9, 0xE3, 0x83, 0x83, 0xE3, 0x83,
+ 0x88, 0x4C, 0xE3, 0x82, 0xAB, 0xE3, 0x83, 0xAD,
+ 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xBC, 0x4C, 0xE3,
+ 0x82, 0xAD, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0x8B,
+ // Bytes 2a00 - 2a3f
+ 0xE3, 0x83, 0xBC, 0x4C, 0xE3, 0x82, 0xAD, 0xE3,
+ 0x83, 0xA5, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xBC,
+ 0x4C, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3,
+ 0x83, 0xA9, 0xE3, 0x83, 0xA0, 0x4C, 0xE3, 0x82,
+ 0xAF, 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xBC, 0xE3,
+ 0x83, 0x8D, 0x4C, 0xE3, 0x82, 0xB5, 0xE3, 0x82,
+ 0xA4, 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAB, 0x4C,
+ 0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ // Bytes 2a40 - 2a7f
+ 0xBC, 0xE3, 0x82, 0xB9, 0x4C, 0xE3, 0x83, 0x8F,
+ 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
+ 0x84, 0x4C, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A,
+ 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAB, 0x4C, 0xE3,
+ 0x83, 0x95, 0xE3, 0x82, 0xA3, 0xE3, 0x83, 0xBC,
+ 0xE3, 0x83, 0x88, 0x4C, 0xE3, 0x83, 0x98, 0xE3,
+ 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x82, 0xBF,
+ 0x4C, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x9A, 0xE3,
+ // Bytes 2a80 - 2abf
+ 0x83, 0x8B, 0xE3, 0x83, 0x92, 0x4C, 0xE3, 0x83,
+ 0x98, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xB3, 0xE3,
+ 0x82, 0xB9, 0x4C, 0xE3, 0x83, 0x9B, 0xE3, 0x82,
+ 0x99, 0xE3, 0x83, 0xAB, 0xE3, 0x83, 0x88, 0x4C,
+ 0xE3, 0x83, 0x9E, 0xE3, 0x82, 0xA4, 0xE3, 0x82,
+ 0xAF, 0xE3, 0x83, 0xAD, 0x4C, 0xE3, 0x83, 0x9F,
+ 0xE3, 0x82, 0xAF, 0xE3, 0x83, 0xAD, 0xE3, 0x83,
+ 0xB3, 0x4C, 0xE3, 0x83, 0xA1, 0xE3, 0x83, 0xBC,
+ // Bytes 2ac0 - 2aff
+ 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB, 0x4C, 0xE3,
+ 0x83, 0xAA, 0xE3, 0x83, 0x83, 0xE3, 0x83, 0x88,
+ 0xE3, 0x83, 0xAB, 0x4C, 0xE3, 0x83, 0xAB, 0xE3,
+ 0x83, 0x92, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC,
+ 0x4C, 0xE6, 0xA0, 0xAA, 0xE5, 0xBC, 0x8F, 0xE4,
+ 0xBC, 0x9A, 0xE7, 0xA4, 0xBE, 0x4E, 0x28, 0xE1,
+ 0x84, 0x8B, 0xE1, 0x85, 0xA9, 0xE1, 0x84, 0x92,
+ 0xE1, 0x85, 0xAE, 0x29, 0x4F, 0xD8, 0xAC, 0xD9,
+ // Bytes 2b00 - 2b3f
+ 0x84, 0x20, 0xD8, 0xAC, 0xD9, 0x84, 0xD8, 0xA7,
+ 0xD9, 0x84, 0xD9, 0x87, 0x4F, 0xE3, 0x82, 0xA2,
+ 0xE3, 0x83, 0x8F, 0xE3, 0x82, 0x9A, 0xE3, 0x83,
+ 0xBC, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x82, 0xA2,
+ 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x98, 0xE3, 0x82,
+ 0x9A, 0xE3, 0x82, 0xA2, 0x4F, 0xE3, 0x82, 0xAD,
+ 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xAF, 0xE3, 0x83,
+ 0x83, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x82, 0xB5,
+ // Bytes 2b40 - 2b7f
+ 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x81, 0xE3, 0x83,
+ 0xBC, 0xE3, 0x83, 0xA0, 0x4F, 0xE3, 0x83, 0x8F,
+ 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
+ 0xAC, 0xE3, 0x83, 0xAB, 0x4F, 0xE3, 0x83, 0x98,
+ 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0xBF, 0xE3, 0x83,
+ 0xBC, 0xE3, 0x83, 0xAB, 0x4F, 0xE3, 0x83, 0x9B,
+ 0xE3, 0x82, 0x9A, 0xE3, 0x82, 0xA4, 0xE3, 0x83,
+ 0xB3, 0xE3, 0x83, 0x88, 0x4F, 0xE3, 0x83, 0x9E,
+ // Bytes 2b80 - 2bbf
+ 0xE3, 0x83, 0xB3, 0xE3, 0x82, 0xB7, 0xE3, 0x83,
+ 0xA7, 0xE3, 0x83, 0xB3, 0x4F, 0xE3, 0x83, 0xA1,
+ 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ 0x88, 0xE3, 0x83, 0xB3, 0x4F, 0xE3, 0x83, 0xAB,
+ 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x95, 0xE3, 0x82,
+ 0x99, 0xE3, 0x83, 0xAB, 0x51, 0x28, 0xE1, 0x84,
+ 0x8B, 0xE1, 0x85, 0xA9, 0xE1, 0x84, 0x8C, 0xE1,
+ 0x85, 0xA5, 0xE1, 0x86, 0xAB, 0x29, 0x52, 0xE3,
+ // Bytes 2bc0 - 2bff
+ 0x82, 0xAD, 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xAB,
+ 0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ 0xBC, 0x52, 0xE3, 0x82, 0xAD, 0xE3, 0x83, 0xAD,
+ 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ 0xA9, 0xE3, 0x83, 0xA0, 0x52, 0xE3, 0x82, 0xAD,
+ 0xE3, 0x83, 0xAD, 0xE3, 0x83, 0xA1, 0xE3, 0x83,
+ 0xBC, 0xE3, 0x83, 0x88, 0xE3, 0x83, 0xAB, 0x52,
+ 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0xE3, 0x83,
+ // Bytes 2c00 - 2c3f
+ 0xA9, 0xE3, 0x83, 0xA0, 0xE3, 0x83, 0x88, 0xE3,
+ 0x83, 0xB3, 0x52, 0xE3, 0x82, 0xAF, 0xE3, 0x83,
+ 0xAB, 0xE3, 0x82, 0xBB, 0xE3, 0x82, 0x99, 0xE3,
+ 0x82, 0xA4, 0xE3, 0x83, 0xAD, 0x52, 0xE3, 0x83,
+ 0x8F, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC, 0xE3,
+ 0x82, 0xBB, 0xE3, 0x83, 0xB3, 0xE3, 0x83, 0x88,
+ 0x52, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A, 0xE3,
+ 0x82, 0xA2, 0xE3, 0x82, 0xB9, 0xE3, 0x83, 0x88,
+ // Bytes 2c40 - 2c7f
+ 0xE3, 0x83, 0xAB, 0x52, 0xE3, 0x83, 0x95, 0xE3,
+ 0x82, 0x99, 0xE3, 0x83, 0x83, 0xE3, 0x82, 0xB7,
+ 0xE3, 0x82, 0xA7, 0xE3, 0x83, 0xAB, 0x52, 0xE3,
+ 0x83, 0x9F, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0x8F,
+ 0xE3, 0x82, 0x99, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
+ 0xAB, 0x52, 0xE3, 0x83, 0xAC, 0xE3, 0x83, 0xB3,
+ 0xE3, 0x83, 0x88, 0xE3, 0x82, 0xB1, 0xE3, 0x82,
+ 0x99, 0xE3, 0x83, 0xB3, 0x61, 0xD8, 0xB5, 0xD9,
+ // Bytes 2c80 - 2cbf
+ 0x84, 0xD9, 0x89, 0x20, 0xD8, 0xA7, 0xD9, 0x84,
+ 0xD9, 0x84, 0xD9, 0x87, 0x20, 0xD8, 0xB9, 0xD9,
+ 0x84, 0xD9, 0x8A, 0xD9, 0x87, 0x20, 0xD9, 0x88,
+ 0xD8, 0xB3, 0xD9, 0x84, 0xD9, 0x85, 0x06, 0xE0,
+ 0xA7, 0x87, 0xE0, 0xA6, 0xBE, 0x01, 0x06, 0xE0,
+ 0xA7, 0x87, 0xE0, 0xA7, 0x97, 0x01, 0x06, 0xE0,
+ 0xAD, 0x87, 0xE0, 0xAC, 0xBE, 0x01, 0x06, 0xE0,
+ 0xAD, 0x87, 0xE0, 0xAD, 0x96, 0x01, 0x06, 0xE0,
+ // Bytes 2cc0 - 2cff
+ 0xAD, 0x87, 0xE0, 0xAD, 0x97, 0x01, 0x06, 0xE0,
+ 0xAE, 0x92, 0xE0, 0xAF, 0x97, 0x01, 0x06, 0xE0,
+ 0xAF, 0x86, 0xE0, 0xAE, 0xBE, 0x01, 0x06, 0xE0,
+ 0xAF, 0x86, 0xE0, 0xAF, 0x97, 0x01, 0x06, 0xE0,
+ 0xAF, 0x87, 0xE0, 0xAE, 0xBE, 0x01, 0x06, 0xE0,
+ 0xB2, 0xBF, 0xE0, 0xB3, 0x95, 0x01, 0x06, 0xE0,
+ 0xB3, 0x86, 0xE0, 0xB3, 0x95, 0x01, 0x06, 0xE0,
+ 0xB3, 0x86, 0xE0, 0xB3, 0x96, 0x01, 0x06, 0xE0,
+ // Bytes 2d00 - 2d3f
+ 0xB5, 0x86, 0xE0, 0xB4, 0xBE, 0x01, 0x06, 0xE0,
+ 0xB5, 0x86, 0xE0, 0xB5, 0x97, 0x01, 0x06, 0xE0,
+ 0xB5, 0x87, 0xE0, 0xB4, 0xBE, 0x01, 0x06, 0xE0,
+ 0xB7, 0x99, 0xE0, 0xB7, 0x9F, 0x01, 0x06, 0xE1,
+ 0x80, 0xA5, 0xE1, 0x80, 0xAE, 0x01, 0x06, 0xE1,
+ 0xAC, 0x85, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0x87, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0x89, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ // Bytes 2d40 - 2d7f
+ 0xAC, 0x8B, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0x8D, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0x91, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0xBA, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0xBC, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0xBE, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAC, 0xBF, 0xE1, 0xAC, 0xB5, 0x01, 0x06, 0xE1,
+ 0xAD, 0x82, 0xE1, 0xAC, 0xB5, 0x01, 0x08, 0xF0,
+ // Bytes 2d80 - 2dbf
+ 0x91, 0x84, 0xB1, 0xF0, 0x91, 0x84, 0xA7, 0x01,
+ 0x08, 0xF0, 0x91, 0x84, 0xB2, 0xF0, 0x91, 0x84,
+ 0xA7, 0x01, 0x08, 0xF0, 0x91, 0x8D, 0x87, 0xF0,
+ 0x91, 0x8C, 0xBE, 0x01, 0x08, 0xF0, 0x91, 0x8D,
+ 0x87, 0xF0, 0x91, 0x8D, 0x97, 0x01, 0x08, 0xF0,
+ 0x91, 0x92, 0xB9, 0xF0, 0x91, 0x92, 0xB0, 0x01,
+ 0x08, 0xF0, 0x91, 0x92, 0xB9, 0xF0, 0x91, 0x92,
+ 0xBA, 0x01, 0x08, 0xF0, 0x91, 0x92, 0xB9, 0xF0,
+ // Bytes 2dc0 - 2dff
+ 0x91, 0x92, 0xBD, 0x01, 0x08, 0xF0, 0x91, 0x96,
+ 0xB8, 0xF0, 0x91, 0x96, 0xAF, 0x01, 0x08, 0xF0,
+ 0x91, 0x96, 0xB9, 0xF0, 0x91, 0x96, 0xAF, 0x01,
+ 0x09, 0xE0, 0xB3, 0x86, 0xE0, 0xB3, 0x82, 0xE0,
+ 0xB3, 0x95, 0x02, 0x09, 0xE0, 0xB7, 0x99, 0xE0,
+ 0xB7, 0x8F, 0xE0, 0xB7, 0x8A, 0x12, 0x44, 0x44,
+ 0x5A, 0xCC, 0x8C, 0xC9, 0x44, 0x44, 0x7A, 0xCC,
+ 0x8C, 0xC9, 0x44, 0x64, 0x7A, 0xCC, 0x8C, 0xC9,
+ // Bytes 2e00 - 2e3f
+ 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x93, 0xC9,
+ 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x94, 0xC9,
+ 0x46, 0xD9, 0x84, 0xD8, 0xA7, 0xD9, 0x95, 0xB5,
+ 0x46, 0xE1, 0x84, 0x80, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x82, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x83, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x85, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x86, 0xE1, 0x85, 0xA1, 0x01,
+ // Bytes 2e40 - 2e7f
+ 0x46, 0xE1, 0x84, 0x87, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x89, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xAE, 0x01,
+ 0x46, 0xE1, 0x84, 0x8C, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x8E, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x8F, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x90, 0xE1, 0x85, 0xA1, 0x01,
+ // Bytes 2e80 - 2ebf
+ 0x46, 0xE1, 0x84, 0x91, 0xE1, 0x85, 0xA1, 0x01,
+ 0x46, 0xE1, 0x84, 0x92, 0xE1, 0x85, 0xA1, 0x01,
+ 0x49, 0xE3, 0x83, 0xA1, 0xE3, 0x82, 0xAB, 0xE3,
+ 0x82, 0x99, 0x0D, 0x4C, 0xE1, 0x84, 0x8C, 0xE1,
+ 0x85, 0xAE, 0xE1, 0x84, 0x8B, 0xE1, 0x85, 0xB4,
+ 0x01, 0x4C, 0xE3, 0x82, 0xAD, 0xE3, 0x82, 0x99,
+ 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0x0D, 0x4C,
+ 0xE3, 0x82, 0xB3, 0xE3, 0x83, 0xBC, 0xE3, 0x83,
+ // Bytes 2ec0 - 2eff
+ 0x9B, 0xE3, 0x82, 0x9A, 0x0D, 0x4C, 0xE3, 0x83,
+ 0xA4, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x88, 0xE3,
+ 0x82, 0x99, 0x0D, 0x4F, 0xE1, 0x84, 0x8E, 0xE1,
+ 0x85, 0xA1, 0xE1, 0x86, 0xB7, 0xE1, 0x84, 0x80,
+ 0xE1, 0x85, 0xA9, 0x01, 0x4F, 0xE3, 0x82, 0xA4,
+ 0xE3, 0x83, 0x8B, 0xE3, 0x83, 0xB3, 0xE3, 0x82,
+ 0xAF, 0xE3, 0x82, 0x99, 0x0D, 0x4F, 0xE3, 0x82,
+ 0xB7, 0xE3, 0x83, 0xAA, 0xE3, 0x83, 0xB3, 0xE3,
+ // Bytes 2f00 - 2f3f
+ 0x82, 0xAF, 0xE3, 0x82, 0x99, 0x0D, 0x4F, 0xE3,
+ 0x83, 0x98, 0xE3, 0x82, 0x9A, 0xE3, 0x83, 0xBC,
+ 0xE3, 0x82, 0xB7, 0xE3, 0x82, 0x99, 0x0D, 0x4F,
+ 0xE3, 0x83, 0x9B, 0xE3, 0x82, 0x9A, 0xE3, 0x83,
+ 0xB3, 0xE3, 0x83, 0x88, 0xE3, 0x82, 0x99, 0x0D,
+ 0x52, 0xE3, 0x82, 0xA8, 0xE3, 0x82, 0xB9, 0xE3,
+ 0x82, 0xAF, 0xE3, 0x83, 0xBC, 0xE3, 0x83, 0x88,
+ 0xE3, 0x82, 0x99, 0x0D, 0x52, 0xE3, 0x83, 0x95,
+ // Bytes 2f40 - 2f7f
+ 0xE3, 0x82, 0xA1, 0xE3, 0x83, 0xA9, 0xE3, 0x83,
+ 0x83, 0xE3, 0x83, 0x88, 0xE3, 0x82, 0x99, 0x0D,
+ 0x86, 0xE0, 0xB3, 0x86, 0xE0, 0xB3, 0x82, 0x01,
+ 0x86, 0xE0, 0xB7, 0x99, 0xE0, 0xB7, 0x8F, 0x01,
+ 0x03, 0x3C, 0xCC, 0xB8, 0x05, 0x03, 0x3D, 0xCC,
+ 0xB8, 0x05, 0x03, 0x3E, 0xCC, 0xB8, 0x05, 0x03,
+ 0x41, 0xCC, 0x80, 0xC9, 0x03, 0x41, 0xCC, 0x81,
+ 0xC9, 0x03, 0x41, 0xCC, 0x83, 0xC9, 0x03, 0x41,
+ // Bytes 2f80 - 2fbf
+ 0xCC, 0x84, 0xC9, 0x03, 0x41, 0xCC, 0x89, 0xC9,
+ 0x03, 0x41, 0xCC, 0x8C, 0xC9, 0x03, 0x41, 0xCC,
+ 0x8F, 0xC9, 0x03, 0x41, 0xCC, 0x91, 0xC9, 0x03,
+ 0x41, 0xCC, 0xA5, 0xB5, 0x03, 0x41, 0xCC, 0xA8,
+ 0xA5, 0x03, 0x42, 0xCC, 0x87, 0xC9, 0x03, 0x42,
+ 0xCC, 0xA3, 0xB5, 0x03, 0x42, 0xCC, 0xB1, 0xB5,
+ 0x03, 0x43, 0xCC, 0x81, 0xC9, 0x03, 0x43, 0xCC,
+ 0x82, 0xC9, 0x03, 0x43, 0xCC, 0x87, 0xC9, 0x03,
+ // Bytes 2fc0 - 2fff
+ 0x43, 0xCC, 0x8C, 0xC9, 0x03, 0x44, 0xCC, 0x87,
+ 0xC9, 0x03, 0x44, 0xCC, 0x8C, 0xC9, 0x03, 0x44,
+ 0xCC, 0xA3, 0xB5, 0x03, 0x44, 0xCC, 0xA7, 0xA5,
+ 0x03, 0x44, 0xCC, 0xAD, 0xB5, 0x03, 0x44, 0xCC,
+ 0xB1, 0xB5, 0x03, 0x45, 0xCC, 0x80, 0xC9, 0x03,
+ 0x45, 0xCC, 0x81, 0xC9, 0x03, 0x45, 0xCC, 0x83,
+ 0xC9, 0x03, 0x45, 0xCC, 0x86, 0xC9, 0x03, 0x45,
+ 0xCC, 0x87, 0xC9, 0x03, 0x45, 0xCC, 0x88, 0xC9,
+ // Bytes 3000 - 303f
+ 0x03, 0x45, 0xCC, 0x89, 0xC9, 0x03, 0x45, 0xCC,
+ 0x8C, 0xC9, 0x03, 0x45, 0xCC, 0x8F, 0xC9, 0x03,
+ 0x45, 0xCC, 0x91, 0xC9, 0x03, 0x45, 0xCC, 0xA8,
+ 0xA5, 0x03, 0x45, 0xCC, 0xAD, 0xB5, 0x03, 0x45,
+ 0xCC, 0xB0, 0xB5, 0x03, 0x46, 0xCC, 0x87, 0xC9,
+ 0x03, 0x47, 0xCC, 0x81, 0xC9, 0x03, 0x47, 0xCC,
+ 0x82, 0xC9, 0x03, 0x47, 0xCC, 0x84, 0xC9, 0x03,
+ 0x47, 0xCC, 0x86, 0xC9, 0x03, 0x47, 0xCC, 0x87,
+ // Bytes 3040 - 307f
+ 0xC9, 0x03, 0x47, 0xCC, 0x8C, 0xC9, 0x03, 0x47,
+ 0xCC, 0xA7, 0xA5, 0x03, 0x48, 0xCC, 0x82, 0xC9,
+ 0x03, 0x48, 0xCC, 0x87, 0xC9, 0x03, 0x48, 0xCC,
+ 0x88, 0xC9, 0x03, 0x48, 0xCC, 0x8C, 0xC9, 0x03,
+ 0x48, 0xCC, 0xA3, 0xB5, 0x03, 0x48, 0xCC, 0xA7,
+ 0xA5, 0x03, 0x48, 0xCC, 0xAE, 0xB5, 0x03, 0x49,
+ 0xCC, 0x80, 0xC9, 0x03, 0x49, 0xCC, 0x81, 0xC9,
+ 0x03, 0x49, 0xCC, 0x82, 0xC9, 0x03, 0x49, 0xCC,
+ // Bytes 3080 - 30bf
+ 0x83, 0xC9, 0x03, 0x49, 0xCC, 0x84, 0xC9, 0x03,
+ 0x49, 0xCC, 0x86, 0xC9, 0x03, 0x49, 0xCC, 0x87,
+ 0xC9, 0x03, 0x49, 0xCC, 0x89, 0xC9, 0x03, 0x49,
+ 0xCC, 0x8C, 0xC9, 0x03, 0x49, 0xCC, 0x8F, 0xC9,
+ 0x03, 0x49, 0xCC, 0x91, 0xC9, 0x03, 0x49, 0xCC,
+ 0xA3, 0xB5, 0x03, 0x49, 0xCC, 0xA8, 0xA5, 0x03,
+ 0x49, 0xCC, 0xB0, 0xB5, 0x03, 0x4A, 0xCC, 0x82,
+ 0xC9, 0x03, 0x4B, 0xCC, 0x81, 0xC9, 0x03, 0x4B,
+ // Bytes 30c0 - 30ff
+ 0xCC, 0x8C, 0xC9, 0x03, 0x4B, 0xCC, 0xA3, 0xB5,
+ 0x03, 0x4B, 0xCC, 0xA7, 0xA5, 0x03, 0x4B, 0xCC,
+ 0xB1, 0xB5, 0x03, 0x4C, 0xCC, 0x81, 0xC9, 0x03,
+ 0x4C, 0xCC, 0x8C, 0xC9, 0x03, 0x4C, 0xCC, 0xA7,
+ 0xA5, 0x03, 0x4C, 0xCC, 0xAD, 0xB5, 0x03, 0x4C,
+ 0xCC, 0xB1, 0xB5, 0x03, 0x4D, 0xCC, 0x81, 0xC9,
+ 0x03, 0x4D, 0xCC, 0x87, 0xC9, 0x03, 0x4D, 0xCC,
+ 0xA3, 0xB5, 0x03, 0x4E, 0xCC, 0x80, 0xC9, 0x03,
+ // Bytes 3100 - 313f
+ 0x4E, 0xCC, 0x81, 0xC9, 0x03, 0x4E, 0xCC, 0x83,
+ 0xC9, 0x03, 0x4E, 0xCC, 0x87, 0xC9, 0x03, 0x4E,
+ 0xCC, 0x8C, 0xC9, 0x03, 0x4E, 0xCC, 0xA3, 0xB5,
+ 0x03, 0x4E, 0xCC, 0xA7, 0xA5, 0x03, 0x4E, 0xCC,
+ 0xAD, 0xB5, 0x03, 0x4E, 0xCC, 0xB1, 0xB5, 0x03,
+ 0x4F, 0xCC, 0x80, 0xC9, 0x03, 0x4F, 0xCC, 0x81,
+ 0xC9, 0x03, 0x4F, 0xCC, 0x86, 0xC9, 0x03, 0x4F,
+ 0xCC, 0x89, 0xC9, 0x03, 0x4F, 0xCC, 0x8B, 0xC9,
+ // Bytes 3140 - 317f
+ 0x03, 0x4F, 0xCC, 0x8C, 0xC9, 0x03, 0x4F, 0xCC,
+ 0x8F, 0xC9, 0x03, 0x4F, 0xCC, 0x91, 0xC9, 0x03,
+ 0x50, 0xCC, 0x81, 0xC9, 0x03, 0x50, 0xCC, 0x87,
+ 0xC9, 0x03, 0x52, 0xCC, 0x81, 0xC9, 0x03, 0x52,
+ 0xCC, 0x87, 0xC9, 0x03, 0x52, 0xCC, 0x8C, 0xC9,
+ 0x03, 0x52, 0xCC, 0x8F, 0xC9, 0x03, 0x52, 0xCC,
+ 0x91, 0xC9, 0x03, 0x52, 0xCC, 0xA7, 0xA5, 0x03,
+ 0x52, 0xCC, 0xB1, 0xB5, 0x03, 0x53, 0xCC, 0x82,
+ // Bytes 3180 - 31bf
+ 0xC9, 0x03, 0x53, 0xCC, 0x87, 0xC9, 0x03, 0x53,
+ 0xCC, 0xA6, 0xB5, 0x03, 0x53, 0xCC, 0xA7, 0xA5,
+ 0x03, 0x54, 0xCC, 0x87, 0xC9, 0x03, 0x54, 0xCC,
+ 0x8C, 0xC9, 0x03, 0x54, 0xCC, 0xA3, 0xB5, 0x03,
+ 0x54, 0xCC, 0xA6, 0xB5, 0x03, 0x54, 0xCC, 0xA7,
+ 0xA5, 0x03, 0x54, 0xCC, 0xAD, 0xB5, 0x03, 0x54,
+ 0xCC, 0xB1, 0xB5, 0x03, 0x55, 0xCC, 0x80, 0xC9,
+ 0x03, 0x55, 0xCC, 0x81, 0xC9, 0x03, 0x55, 0xCC,
+ // Bytes 31c0 - 31ff
+ 0x82, 0xC9, 0x03, 0x55, 0xCC, 0x86, 0xC9, 0x03,
+ 0x55, 0xCC, 0x89, 0xC9, 0x03, 0x55, 0xCC, 0x8A,
+ 0xC9, 0x03, 0x55, 0xCC, 0x8B, 0xC9, 0x03, 0x55,
+ 0xCC, 0x8C, 0xC9, 0x03, 0x55, 0xCC, 0x8F, 0xC9,
+ 0x03, 0x55, 0xCC, 0x91, 0xC9, 0x03, 0x55, 0xCC,
+ 0xA3, 0xB5, 0x03, 0x55, 0xCC, 0xA4, 0xB5, 0x03,
+ 0x55, 0xCC, 0xA8, 0xA5, 0x03, 0x55, 0xCC, 0xAD,
+ 0xB5, 0x03, 0x55, 0xCC, 0xB0, 0xB5, 0x03, 0x56,
+ // Bytes 3200 - 323f
+ 0xCC, 0x83, 0xC9, 0x03, 0x56, 0xCC, 0xA3, 0xB5,
+ 0x03, 0x57, 0xCC, 0x80, 0xC9, 0x03, 0x57, 0xCC,
+ 0x81, 0xC9, 0x03, 0x57, 0xCC, 0x82, 0xC9, 0x03,
+ 0x57, 0xCC, 0x87, 0xC9, 0x03, 0x57, 0xCC, 0x88,
+ 0xC9, 0x03, 0x57, 0xCC, 0xA3, 0xB5, 0x03, 0x58,
+ 0xCC, 0x87, 0xC9, 0x03, 0x58, 0xCC, 0x88, 0xC9,
+ 0x03, 0x59, 0xCC, 0x80, 0xC9, 0x03, 0x59, 0xCC,
+ 0x81, 0xC9, 0x03, 0x59, 0xCC, 0x82, 0xC9, 0x03,
+ // Bytes 3240 - 327f
+ 0x59, 0xCC, 0x83, 0xC9, 0x03, 0x59, 0xCC, 0x84,
+ 0xC9, 0x03, 0x59, 0xCC, 0x87, 0xC9, 0x03, 0x59,
+ 0xCC, 0x88, 0xC9, 0x03, 0x59, 0xCC, 0x89, 0xC9,
+ 0x03, 0x59, 0xCC, 0xA3, 0xB5, 0x03, 0x5A, 0xCC,
+ 0x81, 0xC9, 0x03, 0x5A, 0xCC, 0x82, 0xC9, 0x03,
+ 0x5A, 0xCC, 0x87, 0xC9, 0x03, 0x5A, 0xCC, 0x8C,
+ 0xC9, 0x03, 0x5A, 0xCC, 0xA3, 0xB5, 0x03, 0x5A,
+ 0xCC, 0xB1, 0xB5, 0x03, 0x61, 0xCC, 0x80, 0xC9,
+ // Bytes 3280 - 32bf
+ 0x03, 0x61, 0xCC, 0x81, 0xC9, 0x03, 0x61, 0xCC,
+ 0x83, 0xC9, 0x03, 0x61, 0xCC, 0x84, 0xC9, 0x03,
+ 0x61, 0xCC, 0x89, 0xC9, 0x03, 0x61, 0xCC, 0x8C,
+ 0xC9, 0x03, 0x61, 0xCC, 0x8F, 0xC9, 0x03, 0x61,
+ 0xCC, 0x91, 0xC9, 0x03, 0x61, 0xCC, 0xA5, 0xB5,
+ 0x03, 0x61, 0xCC, 0xA8, 0xA5, 0x03, 0x62, 0xCC,
+ 0x87, 0xC9, 0x03, 0x62, 0xCC, 0xA3, 0xB5, 0x03,
+ 0x62, 0xCC, 0xB1, 0xB5, 0x03, 0x63, 0xCC, 0x81,
+ // Bytes 32c0 - 32ff
+ 0xC9, 0x03, 0x63, 0xCC, 0x82, 0xC9, 0x03, 0x63,
+ 0xCC, 0x87, 0xC9, 0x03, 0x63, 0xCC, 0x8C, 0xC9,
+ 0x03, 0x64, 0xCC, 0x87, 0xC9, 0x03, 0x64, 0xCC,
+ 0x8C, 0xC9, 0x03, 0x64, 0xCC, 0xA3, 0xB5, 0x03,
+ 0x64, 0xCC, 0xA7, 0xA5, 0x03, 0x64, 0xCC, 0xAD,
+ 0xB5, 0x03, 0x64, 0xCC, 0xB1, 0xB5, 0x03, 0x65,
+ 0xCC, 0x80, 0xC9, 0x03, 0x65, 0xCC, 0x81, 0xC9,
+ 0x03, 0x65, 0xCC, 0x83, 0xC9, 0x03, 0x65, 0xCC,
+ // Bytes 3300 - 333f
+ 0x86, 0xC9, 0x03, 0x65, 0xCC, 0x87, 0xC9, 0x03,
+ 0x65, 0xCC, 0x88, 0xC9, 0x03, 0x65, 0xCC, 0x89,
+ 0xC9, 0x03, 0x65, 0xCC, 0x8C, 0xC9, 0x03, 0x65,
+ 0xCC, 0x8F, 0xC9, 0x03, 0x65, 0xCC, 0x91, 0xC9,
+ 0x03, 0x65, 0xCC, 0xA8, 0xA5, 0x03, 0x65, 0xCC,
+ 0xAD, 0xB5, 0x03, 0x65, 0xCC, 0xB0, 0xB5, 0x03,
+ 0x66, 0xCC, 0x87, 0xC9, 0x03, 0x67, 0xCC, 0x81,
+ 0xC9, 0x03, 0x67, 0xCC, 0x82, 0xC9, 0x03, 0x67,
+ // Bytes 3340 - 337f
+ 0xCC, 0x84, 0xC9, 0x03, 0x67, 0xCC, 0x86, 0xC9,
+ 0x03, 0x67, 0xCC, 0x87, 0xC9, 0x03, 0x67, 0xCC,
+ 0x8C, 0xC9, 0x03, 0x67, 0xCC, 0xA7, 0xA5, 0x03,
+ 0x68, 0xCC, 0x82, 0xC9, 0x03, 0x68, 0xCC, 0x87,
+ 0xC9, 0x03, 0x68, 0xCC, 0x88, 0xC9, 0x03, 0x68,
+ 0xCC, 0x8C, 0xC9, 0x03, 0x68, 0xCC, 0xA3, 0xB5,
+ 0x03, 0x68, 0xCC, 0xA7, 0xA5, 0x03, 0x68, 0xCC,
+ 0xAE, 0xB5, 0x03, 0x68, 0xCC, 0xB1, 0xB5, 0x03,
+ // Bytes 3380 - 33bf
+ 0x69, 0xCC, 0x80, 0xC9, 0x03, 0x69, 0xCC, 0x81,
+ 0xC9, 0x03, 0x69, 0xCC, 0x82, 0xC9, 0x03, 0x69,
+ 0xCC, 0x83, 0xC9, 0x03, 0x69, 0xCC, 0x84, 0xC9,
+ 0x03, 0x69, 0xCC, 0x86, 0xC9, 0x03, 0x69, 0xCC,
+ 0x89, 0xC9, 0x03, 0x69, 0xCC, 0x8C, 0xC9, 0x03,
+ 0x69, 0xCC, 0x8F, 0xC9, 0x03, 0x69, 0xCC, 0x91,
+ 0xC9, 0x03, 0x69, 0xCC, 0xA3, 0xB5, 0x03, 0x69,
+ 0xCC, 0xA8, 0xA5, 0x03, 0x69, 0xCC, 0xB0, 0xB5,
+ // Bytes 33c0 - 33ff
+ 0x03, 0x6A, 0xCC, 0x82, 0xC9, 0x03, 0x6A, 0xCC,
+ 0x8C, 0xC9, 0x03, 0x6B, 0xCC, 0x81, 0xC9, 0x03,
+ 0x6B, 0xCC, 0x8C, 0xC9, 0x03, 0x6B, 0xCC, 0xA3,
+ 0xB5, 0x03, 0x6B, 0xCC, 0xA7, 0xA5, 0x03, 0x6B,
+ 0xCC, 0xB1, 0xB5, 0x03, 0x6C, 0xCC, 0x81, 0xC9,
+ 0x03, 0x6C, 0xCC, 0x8C, 0xC9, 0x03, 0x6C, 0xCC,
+ 0xA7, 0xA5, 0x03, 0x6C, 0xCC, 0xAD, 0xB5, 0x03,
+ 0x6C, 0xCC, 0xB1, 0xB5, 0x03, 0x6D, 0xCC, 0x81,
+ // Bytes 3400 - 343f
+ 0xC9, 0x03, 0x6D, 0xCC, 0x87, 0xC9, 0x03, 0x6D,
+ 0xCC, 0xA3, 0xB5, 0x03, 0x6E, 0xCC, 0x80, 0xC9,
+ 0x03, 0x6E, 0xCC, 0x81, 0xC9, 0x03, 0x6E, 0xCC,
+ 0x83, 0xC9, 0x03, 0x6E, 0xCC, 0x87, 0xC9, 0x03,
+ 0x6E, 0xCC, 0x8C, 0xC9, 0x03, 0x6E, 0xCC, 0xA3,
+ 0xB5, 0x03, 0x6E, 0xCC, 0xA7, 0xA5, 0x03, 0x6E,
+ 0xCC, 0xAD, 0xB5, 0x03, 0x6E, 0xCC, 0xB1, 0xB5,
+ 0x03, 0x6F, 0xCC, 0x80, 0xC9, 0x03, 0x6F, 0xCC,
+ // Bytes 3440 - 347f
+ 0x81, 0xC9, 0x03, 0x6F, 0xCC, 0x86, 0xC9, 0x03,
+ 0x6F, 0xCC, 0x89, 0xC9, 0x03, 0x6F, 0xCC, 0x8B,
+ 0xC9, 0x03, 0x6F, 0xCC, 0x8C, 0xC9, 0x03, 0x6F,
+ 0xCC, 0x8F, 0xC9, 0x03, 0x6F, 0xCC, 0x91, 0xC9,
+ 0x03, 0x70, 0xCC, 0x81, 0xC9, 0x03, 0x70, 0xCC,
+ 0x87, 0xC9, 0x03, 0x72, 0xCC, 0x81, 0xC9, 0x03,
+ 0x72, 0xCC, 0x87, 0xC9, 0x03, 0x72, 0xCC, 0x8C,
+ 0xC9, 0x03, 0x72, 0xCC, 0x8F, 0xC9, 0x03, 0x72,
+ // Bytes 3480 - 34bf
+ 0xCC, 0x91, 0xC9, 0x03, 0x72, 0xCC, 0xA7, 0xA5,
+ 0x03, 0x72, 0xCC, 0xB1, 0xB5, 0x03, 0x73, 0xCC,
+ 0x82, 0xC9, 0x03, 0x73, 0xCC, 0x87, 0xC9, 0x03,
+ 0x73, 0xCC, 0xA6, 0xB5, 0x03, 0x73, 0xCC, 0xA7,
+ 0xA5, 0x03, 0x74, 0xCC, 0x87, 0xC9, 0x03, 0x74,
+ 0xCC, 0x88, 0xC9, 0x03, 0x74, 0xCC, 0x8C, 0xC9,
+ 0x03, 0x74, 0xCC, 0xA3, 0xB5, 0x03, 0x74, 0xCC,
+ 0xA6, 0xB5, 0x03, 0x74, 0xCC, 0xA7, 0xA5, 0x03,
+ // Bytes 34c0 - 34ff
+ 0x74, 0xCC, 0xAD, 0xB5, 0x03, 0x74, 0xCC, 0xB1,
+ 0xB5, 0x03, 0x75, 0xCC, 0x80, 0xC9, 0x03, 0x75,
+ 0xCC, 0x81, 0xC9, 0x03, 0x75, 0xCC, 0x82, 0xC9,
+ 0x03, 0x75, 0xCC, 0x86, 0xC9, 0x03, 0x75, 0xCC,
+ 0x89, 0xC9, 0x03, 0x75, 0xCC, 0x8A, 0xC9, 0x03,
+ 0x75, 0xCC, 0x8B, 0xC9, 0x03, 0x75, 0xCC, 0x8C,
+ 0xC9, 0x03, 0x75, 0xCC, 0x8F, 0xC9, 0x03, 0x75,
+ 0xCC, 0x91, 0xC9, 0x03, 0x75, 0xCC, 0xA3, 0xB5,
+ // Bytes 3500 - 353f
+ 0x03, 0x75, 0xCC, 0xA4, 0xB5, 0x03, 0x75, 0xCC,
+ 0xA8, 0xA5, 0x03, 0x75, 0xCC, 0xAD, 0xB5, 0x03,
+ 0x75, 0xCC, 0xB0, 0xB5, 0x03, 0x76, 0xCC, 0x83,
+ 0xC9, 0x03, 0x76, 0xCC, 0xA3, 0xB5, 0x03, 0x77,
+ 0xCC, 0x80, 0xC9, 0x03, 0x77, 0xCC, 0x81, 0xC9,
+ 0x03, 0x77, 0xCC, 0x82, 0xC9, 0x03, 0x77, 0xCC,
+ 0x87, 0xC9, 0x03, 0x77, 0xCC, 0x88, 0xC9, 0x03,
+ 0x77, 0xCC, 0x8A, 0xC9, 0x03, 0x77, 0xCC, 0xA3,
+ // Bytes 3540 - 357f
+ 0xB5, 0x03, 0x78, 0xCC, 0x87, 0xC9, 0x03, 0x78,
+ 0xCC, 0x88, 0xC9, 0x03, 0x79, 0xCC, 0x80, 0xC9,
+ 0x03, 0x79, 0xCC, 0x81, 0xC9, 0x03, 0x79, 0xCC,
+ 0x82, 0xC9, 0x03, 0x79, 0xCC, 0x83, 0xC9, 0x03,
+ 0x79, 0xCC, 0x84, 0xC9, 0x03, 0x79, 0xCC, 0x87,
+ 0xC9, 0x03, 0x79, 0xCC, 0x88, 0xC9, 0x03, 0x79,
+ 0xCC, 0x89, 0xC9, 0x03, 0x79, 0xCC, 0x8A, 0xC9,
+ 0x03, 0x79, 0xCC, 0xA3, 0xB5, 0x03, 0x7A, 0xCC,
+ // Bytes 3580 - 35bf
+ 0x81, 0xC9, 0x03, 0x7A, 0xCC, 0x82, 0xC9, 0x03,
+ 0x7A, 0xCC, 0x87, 0xC9, 0x03, 0x7A, 0xCC, 0x8C,
+ 0xC9, 0x03, 0x7A, 0xCC, 0xA3, 0xB5, 0x03, 0x7A,
+ 0xCC, 0xB1, 0xB5, 0x04, 0xC2, 0xA8, 0xCC, 0x80,
+ 0xCA, 0x04, 0xC2, 0xA8, 0xCC, 0x81, 0xCA, 0x04,
+ 0xC2, 0xA8, 0xCD, 0x82, 0xCA, 0x04, 0xC3, 0x86,
+ 0xCC, 0x81, 0xC9, 0x04, 0xC3, 0x86, 0xCC, 0x84,
+ 0xC9, 0x04, 0xC3, 0x98, 0xCC, 0x81, 0xC9, 0x04,
+ // Bytes 35c0 - 35ff
+ 0xC3, 0xA6, 0xCC, 0x81, 0xC9, 0x04, 0xC3, 0xA6,
+ 0xCC, 0x84, 0xC9, 0x04, 0xC3, 0xB8, 0xCC, 0x81,
+ 0xC9, 0x04, 0xC5, 0xBF, 0xCC, 0x87, 0xC9, 0x04,
+ 0xC6, 0xB7, 0xCC, 0x8C, 0xC9, 0x04, 0xCA, 0x92,
+ 0xCC, 0x8C, 0xC9, 0x04, 0xCE, 0x91, 0xCC, 0x80,
+ 0xC9, 0x04, 0xCE, 0x91, 0xCC, 0x81, 0xC9, 0x04,
+ 0xCE, 0x91, 0xCC, 0x84, 0xC9, 0x04, 0xCE, 0x91,
+ 0xCC, 0x86, 0xC9, 0x04, 0xCE, 0x91, 0xCD, 0x85,
+ // Bytes 3600 - 363f
+ 0xD9, 0x04, 0xCE, 0x95, 0xCC, 0x80, 0xC9, 0x04,
+ 0xCE, 0x95, 0xCC, 0x81, 0xC9, 0x04, 0xCE, 0x97,
+ 0xCC, 0x80, 0xC9, 0x04, 0xCE, 0x97, 0xCC, 0x81,
+ 0xC9, 0x04, 0xCE, 0x97, 0xCD, 0x85, 0xD9, 0x04,
+ 0xCE, 0x99, 0xCC, 0x80, 0xC9, 0x04, 0xCE, 0x99,
+ 0xCC, 0x81, 0xC9, 0x04, 0xCE, 0x99, 0xCC, 0x84,
+ 0xC9, 0x04, 0xCE, 0x99, 0xCC, 0x86, 0xC9, 0x04,
+ 0xCE, 0x99, 0xCC, 0x88, 0xC9, 0x04, 0xCE, 0x9F,
+ // Bytes 3640 - 367f
+ 0xCC, 0x80, 0xC9, 0x04, 0xCE, 0x9F, 0xCC, 0x81,
+ 0xC9, 0x04, 0xCE, 0xA1, 0xCC, 0x94, 0xC9, 0x04,
+ 0xCE, 0xA5, 0xCC, 0x80, 0xC9, 0x04, 0xCE, 0xA5,
+ 0xCC, 0x81, 0xC9, 0x04, 0xCE, 0xA5, 0xCC, 0x84,
+ 0xC9, 0x04, 0xCE, 0xA5, 0xCC, 0x86, 0xC9, 0x04,
+ 0xCE, 0xA5, 0xCC, 0x88, 0xC9, 0x04, 0xCE, 0xA9,
+ 0xCC, 0x80, 0xC9, 0x04, 0xCE, 0xA9, 0xCC, 0x81,
+ 0xC9, 0x04, 0xCE, 0xA9, 0xCD, 0x85, 0xD9, 0x04,
+ // Bytes 3680 - 36bf
+ 0xCE, 0xB1, 0xCC, 0x84, 0xC9, 0x04, 0xCE, 0xB1,
+ 0xCC, 0x86, 0xC9, 0x04, 0xCE, 0xB1, 0xCD, 0x85,
+ 0xD9, 0x04, 0xCE, 0xB5, 0xCC, 0x80, 0xC9, 0x04,
+ 0xCE, 0xB5, 0xCC, 0x81, 0xC9, 0x04, 0xCE, 0xB7,
+ 0xCD, 0x85, 0xD9, 0x04, 0xCE, 0xB9, 0xCC, 0x80,
+ 0xC9, 0x04, 0xCE, 0xB9, 0xCC, 0x81, 0xC9, 0x04,
+ 0xCE, 0xB9, 0xCC, 0x84, 0xC9, 0x04, 0xCE, 0xB9,
+ 0xCC, 0x86, 0xC9, 0x04, 0xCE, 0xB9, 0xCD, 0x82,
+ // Bytes 36c0 - 36ff
+ 0xC9, 0x04, 0xCE, 0xBF, 0xCC, 0x80, 0xC9, 0x04,
+ 0xCE, 0xBF, 0xCC, 0x81, 0xC9, 0x04, 0xCF, 0x81,
+ 0xCC, 0x93, 0xC9, 0x04, 0xCF, 0x81, 0xCC, 0x94,
+ 0xC9, 0x04, 0xCF, 0x85, 0xCC, 0x80, 0xC9, 0x04,
+ 0xCF, 0x85, 0xCC, 0x81, 0xC9, 0x04, 0xCF, 0x85,
+ 0xCC, 0x84, 0xC9, 0x04, 0xCF, 0x85, 0xCC, 0x86,
+ 0xC9, 0x04, 0xCF, 0x85, 0xCD, 0x82, 0xC9, 0x04,
+ 0xCF, 0x89, 0xCD, 0x85, 0xD9, 0x04, 0xCF, 0x92,
+ // Bytes 3700 - 373f
+ 0xCC, 0x81, 0xC9, 0x04, 0xCF, 0x92, 0xCC, 0x88,
+ 0xC9, 0x04, 0xD0, 0x86, 0xCC, 0x88, 0xC9, 0x04,
+ 0xD0, 0x90, 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0x90,
+ 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0x93, 0xCC, 0x81,
+ 0xC9, 0x04, 0xD0, 0x95, 0xCC, 0x80, 0xC9, 0x04,
+ 0xD0, 0x95, 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0x95,
+ 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0x96, 0xCC, 0x86,
+ 0xC9, 0x04, 0xD0, 0x96, 0xCC, 0x88, 0xC9, 0x04,
+ // Bytes 3740 - 377f
+ 0xD0, 0x97, 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0x98,
+ 0xCC, 0x80, 0xC9, 0x04, 0xD0, 0x98, 0xCC, 0x84,
+ 0xC9, 0x04, 0xD0, 0x98, 0xCC, 0x86, 0xC9, 0x04,
+ 0xD0, 0x98, 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0x9A,
+ 0xCC, 0x81, 0xC9, 0x04, 0xD0, 0x9E, 0xCC, 0x88,
+ 0xC9, 0x04, 0xD0, 0xA3, 0xCC, 0x84, 0xC9, 0x04,
+ 0xD0, 0xA3, 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0xA3,
+ 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0xA3, 0xCC, 0x8B,
+ // Bytes 3780 - 37bf
+ 0xC9, 0x04, 0xD0, 0xA7, 0xCC, 0x88, 0xC9, 0x04,
+ 0xD0, 0xAB, 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0xAD,
+ 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0xB0, 0xCC, 0x86,
+ 0xC9, 0x04, 0xD0, 0xB0, 0xCC, 0x88, 0xC9, 0x04,
+ 0xD0, 0xB3, 0xCC, 0x81, 0xC9, 0x04, 0xD0, 0xB5,
+ 0xCC, 0x80, 0xC9, 0x04, 0xD0, 0xB5, 0xCC, 0x86,
+ 0xC9, 0x04, 0xD0, 0xB5, 0xCC, 0x88, 0xC9, 0x04,
+ 0xD0, 0xB6, 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0xB6,
+ // Bytes 37c0 - 37ff
+ 0xCC, 0x88, 0xC9, 0x04, 0xD0, 0xB7, 0xCC, 0x88,
+ 0xC9, 0x04, 0xD0, 0xB8, 0xCC, 0x80, 0xC9, 0x04,
+ 0xD0, 0xB8, 0xCC, 0x84, 0xC9, 0x04, 0xD0, 0xB8,
+ 0xCC, 0x86, 0xC9, 0x04, 0xD0, 0xB8, 0xCC, 0x88,
+ 0xC9, 0x04, 0xD0, 0xBA, 0xCC, 0x81, 0xC9, 0x04,
+ 0xD0, 0xBE, 0xCC, 0x88, 0xC9, 0x04, 0xD1, 0x83,
+ 0xCC, 0x84, 0xC9, 0x04, 0xD1, 0x83, 0xCC, 0x86,
+ 0xC9, 0x04, 0xD1, 0x83, 0xCC, 0x88, 0xC9, 0x04,
+ // Bytes 3800 - 383f
+ 0xD1, 0x83, 0xCC, 0x8B, 0xC9, 0x04, 0xD1, 0x87,
+ 0xCC, 0x88, 0xC9, 0x04, 0xD1, 0x8B, 0xCC, 0x88,
+ 0xC9, 0x04, 0xD1, 0x8D, 0xCC, 0x88, 0xC9, 0x04,
+ 0xD1, 0x96, 0xCC, 0x88, 0xC9, 0x04, 0xD1, 0xB4,
+ 0xCC, 0x8F, 0xC9, 0x04, 0xD1, 0xB5, 0xCC, 0x8F,
+ 0xC9, 0x04, 0xD3, 0x98, 0xCC, 0x88, 0xC9, 0x04,
+ 0xD3, 0x99, 0xCC, 0x88, 0xC9, 0x04, 0xD3, 0xA8,
+ 0xCC, 0x88, 0xC9, 0x04, 0xD3, 0xA9, 0xCC, 0x88,
+ // Bytes 3840 - 387f
+ 0xC9, 0x04, 0xD8, 0xA7, 0xD9, 0x93, 0xC9, 0x04,
+ 0xD8, 0xA7, 0xD9, 0x94, 0xC9, 0x04, 0xD8, 0xA7,
+ 0xD9, 0x95, 0xB5, 0x04, 0xD9, 0x88, 0xD9, 0x94,
+ 0xC9, 0x04, 0xD9, 0x8A, 0xD9, 0x94, 0xC9, 0x04,
+ 0xDB, 0x81, 0xD9, 0x94, 0xC9, 0x04, 0xDB, 0x92,
+ 0xD9, 0x94, 0xC9, 0x04, 0xDB, 0x95, 0xD9, 0x94,
+ 0xC9, 0x05, 0x41, 0xCC, 0x82, 0xCC, 0x80, 0xCA,
+ 0x05, 0x41, 0xCC, 0x82, 0xCC, 0x81, 0xCA, 0x05,
+ // Bytes 3880 - 38bf
+ 0x41, 0xCC, 0x82, 0xCC, 0x83, 0xCA, 0x05, 0x41,
+ 0xCC, 0x82, 0xCC, 0x89, 0xCA, 0x05, 0x41, 0xCC,
+ 0x86, 0xCC, 0x80, 0xCA, 0x05, 0x41, 0xCC, 0x86,
+ 0xCC, 0x81, 0xCA, 0x05, 0x41, 0xCC, 0x86, 0xCC,
+ 0x83, 0xCA, 0x05, 0x41, 0xCC, 0x86, 0xCC, 0x89,
+ 0xCA, 0x05, 0x41, 0xCC, 0x87, 0xCC, 0x84, 0xCA,
+ 0x05, 0x41, 0xCC, 0x88, 0xCC, 0x84, 0xCA, 0x05,
+ 0x41, 0xCC, 0x8A, 0xCC, 0x81, 0xCA, 0x05, 0x41,
+ // Bytes 38c0 - 38ff
+ 0xCC, 0xA3, 0xCC, 0x82, 0xCA, 0x05, 0x41, 0xCC,
+ 0xA3, 0xCC, 0x86, 0xCA, 0x05, 0x43, 0xCC, 0xA7,
+ 0xCC, 0x81, 0xCA, 0x05, 0x45, 0xCC, 0x82, 0xCC,
+ 0x80, 0xCA, 0x05, 0x45, 0xCC, 0x82, 0xCC, 0x81,
+ 0xCA, 0x05, 0x45, 0xCC, 0x82, 0xCC, 0x83, 0xCA,
+ 0x05, 0x45, 0xCC, 0x82, 0xCC, 0x89, 0xCA, 0x05,
+ 0x45, 0xCC, 0x84, 0xCC, 0x80, 0xCA, 0x05, 0x45,
+ 0xCC, 0x84, 0xCC, 0x81, 0xCA, 0x05, 0x45, 0xCC,
+ // Bytes 3900 - 393f
+ 0xA3, 0xCC, 0x82, 0xCA, 0x05, 0x45, 0xCC, 0xA7,
+ 0xCC, 0x86, 0xCA, 0x05, 0x49, 0xCC, 0x88, 0xCC,
+ 0x81, 0xCA, 0x05, 0x4C, 0xCC, 0xA3, 0xCC, 0x84,
+ 0xCA, 0x05, 0x4F, 0xCC, 0x82, 0xCC, 0x80, 0xCA,
+ 0x05, 0x4F, 0xCC, 0x82, 0xCC, 0x81, 0xCA, 0x05,
+ 0x4F, 0xCC, 0x82, 0xCC, 0x83, 0xCA, 0x05, 0x4F,
+ 0xCC, 0x82, 0xCC, 0x89, 0xCA, 0x05, 0x4F, 0xCC,
+ 0x83, 0xCC, 0x81, 0xCA, 0x05, 0x4F, 0xCC, 0x83,
+ // Bytes 3940 - 397f
+ 0xCC, 0x84, 0xCA, 0x05, 0x4F, 0xCC, 0x83, 0xCC,
+ 0x88, 0xCA, 0x05, 0x4F, 0xCC, 0x84, 0xCC, 0x80,
+ 0xCA, 0x05, 0x4F, 0xCC, 0x84, 0xCC, 0x81, 0xCA,
+ 0x05, 0x4F, 0xCC, 0x87, 0xCC, 0x84, 0xCA, 0x05,
+ 0x4F, 0xCC, 0x88, 0xCC, 0x84, 0xCA, 0x05, 0x4F,
+ 0xCC, 0x9B, 0xCC, 0x80, 0xCA, 0x05, 0x4F, 0xCC,
+ 0x9B, 0xCC, 0x81, 0xCA, 0x05, 0x4F, 0xCC, 0x9B,
+ 0xCC, 0x83, 0xCA, 0x05, 0x4F, 0xCC, 0x9B, 0xCC,
+ // Bytes 3980 - 39bf
+ 0x89, 0xCA, 0x05, 0x4F, 0xCC, 0x9B, 0xCC, 0xA3,
+ 0xB6, 0x05, 0x4F, 0xCC, 0xA3, 0xCC, 0x82, 0xCA,
+ 0x05, 0x4F, 0xCC, 0xA8, 0xCC, 0x84, 0xCA, 0x05,
+ 0x52, 0xCC, 0xA3, 0xCC, 0x84, 0xCA, 0x05, 0x53,
+ 0xCC, 0x81, 0xCC, 0x87, 0xCA, 0x05, 0x53, 0xCC,
+ 0x8C, 0xCC, 0x87, 0xCA, 0x05, 0x53, 0xCC, 0xA3,
+ 0xCC, 0x87, 0xCA, 0x05, 0x55, 0xCC, 0x83, 0xCC,
+ 0x81, 0xCA, 0x05, 0x55, 0xCC, 0x84, 0xCC, 0x88,
+ // Bytes 39c0 - 39ff
+ 0xCA, 0x05, 0x55, 0xCC, 0x88, 0xCC, 0x80, 0xCA,
+ 0x05, 0x55, 0xCC, 0x88, 0xCC, 0x81, 0xCA, 0x05,
+ 0x55, 0xCC, 0x88, 0xCC, 0x84, 0xCA, 0x05, 0x55,
+ 0xCC, 0x88, 0xCC, 0x8C, 0xCA, 0x05, 0x55, 0xCC,
+ 0x9B, 0xCC, 0x80, 0xCA, 0x05, 0x55, 0xCC, 0x9B,
+ 0xCC, 0x81, 0xCA, 0x05, 0x55, 0xCC, 0x9B, 0xCC,
+ 0x83, 0xCA, 0x05, 0x55, 0xCC, 0x9B, 0xCC, 0x89,
+ 0xCA, 0x05, 0x55, 0xCC, 0x9B, 0xCC, 0xA3, 0xB6,
+ // Bytes 3a00 - 3a3f
+ 0x05, 0x61, 0xCC, 0x82, 0xCC, 0x80, 0xCA, 0x05,
+ 0x61, 0xCC, 0x82, 0xCC, 0x81, 0xCA, 0x05, 0x61,
+ 0xCC, 0x82, 0xCC, 0x83, 0xCA, 0x05, 0x61, 0xCC,
+ 0x82, 0xCC, 0x89, 0xCA, 0x05, 0x61, 0xCC, 0x86,
+ 0xCC, 0x80, 0xCA, 0x05, 0x61, 0xCC, 0x86, 0xCC,
+ 0x81, 0xCA, 0x05, 0x61, 0xCC, 0x86, 0xCC, 0x83,
+ 0xCA, 0x05, 0x61, 0xCC, 0x86, 0xCC, 0x89, 0xCA,
+ 0x05, 0x61, 0xCC, 0x87, 0xCC, 0x84, 0xCA, 0x05,
+ // Bytes 3a40 - 3a7f
+ 0x61, 0xCC, 0x88, 0xCC, 0x84, 0xCA, 0x05, 0x61,
+ 0xCC, 0x8A, 0xCC, 0x81, 0xCA, 0x05, 0x61, 0xCC,
+ 0xA3, 0xCC, 0x82, 0xCA, 0x05, 0x61, 0xCC, 0xA3,
+ 0xCC, 0x86, 0xCA, 0x05, 0x63, 0xCC, 0xA7, 0xCC,
+ 0x81, 0xCA, 0x05, 0x65, 0xCC, 0x82, 0xCC, 0x80,
+ 0xCA, 0x05, 0x65, 0xCC, 0x82, 0xCC, 0x81, 0xCA,
+ 0x05, 0x65, 0xCC, 0x82, 0xCC, 0x83, 0xCA, 0x05,
+ 0x65, 0xCC, 0x82, 0xCC, 0x89, 0xCA, 0x05, 0x65,
+ // Bytes 3a80 - 3abf
+ 0xCC, 0x84, 0xCC, 0x80, 0xCA, 0x05, 0x65, 0xCC,
+ 0x84, 0xCC, 0x81, 0xCA, 0x05, 0x65, 0xCC, 0xA3,
+ 0xCC, 0x82, 0xCA, 0x05, 0x65, 0xCC, 0xA7, 0xCC,
+ 0x86, 0xCA, 0x05, 0x69, 0xCC, 0x88, 0xCC, 0x81,
+ 0xCA, 0x05, 0x6C, 0xCC, 0xA3, 0xCC, 0x84, 0xCA,
+ 0x05, 0x6F, 0xCC, 0x82, 0xCC, 0x80, 0xCA, 0x05,
+ 0x6F, 0xCC, 0x82, 0xCC, 0x81, 0xCA, 0x05, 0x6F,
+ 0xCC, 0x82, 0xCC, 0x83, 0xCA, 0x05, 0x6F, 0xCC,
+ // Bytes 3ac0 - 3aff
+ 0x82, 0xCC, 0x89, 0xCA, 0x05, 0x6F, 0xCC, 0x83,
+ 0xCC, 0x81, 0xCA, 0x05, 0x6F, 0xCC, 0x83, 0xCC,
+ 0x84, 0xCA, 0x05, 0x6F, 0xCC, 0x83, 0xCC, 0x88,
+ 0xCA, 0x05, 0x6F, 0xCC, 0x84, 0xCC, 0x80, 0xCA,
+ 0x05, 0x6F, 0xCC, 0x84, 0xCC, 0x81, 0xCA, 0x05,
+ 0x6F, 0xCC, 0x87, 0xCC, 0x84, 0xCA, 0x05, 0x6F,
+ 0xCC, 0x88, 0xCC, 0x84, 0xCA, 0x05, 0x6F, 0xCC,
+ 0x9B, 0xCC, 0x80, 0xCA, 0x05, 0x6F, 0xCC, 0x9B,
+ // Bytes 3b00 - 3b3f
+ 0xCC, 0x81, 0xCA, 0x05, 0x6F, 0xCC, 0x9B, 0xCC,
+ 0x83, 0xCA, 0x05, 0x6F, 0xCC, 0x9B, 0xCC, 0x89,
+ 0xCA, 0x05, 0x6F, 0xCC, 0x9B, 0xCC, 0xA3, 0xB6,
+ 0x05, 0x6F, 0xCC, 0xA3, 0xCC, 0x82, 0xCA, 0x05,
+ 0x6F, 0xCC, 0xA8, 0xCC, 0x84, 0xCA, 0x05, 0x72,
+ 0xCC, 0xA3, 0xCC, 0x84, 0xCA, 0x05, 0x73, 0xCC,
+ 0x81, 0xCC, 0x87, 0xCA, 0x05, 0x73, 0xCC, 0x8C,
+ 0xCC, 0x87, 0xCA, 0x05, 0x73, 0xCC, 0xA3, 0xCC,
+ // Bytes 3b40 - 3b7f
+ 0x87, 0xCA, 0x05, 0x75, 0xCC, 0x83, 0xCC, 0x81,
+ 0xCA, 0x05, 0x75, 0xCC, 0x84, 0xCC, 0x88, 0xCA,
+ 0x05, 0x75, 0xCC, 0x88, 0xCC, 0x80, 0xCA, 0x05,
+ 0x75, 0xCC, 0x88, 0xCC, 0x81, 0xCA, 0x05, 0x75,
+ 0xCC, 0x88, 0xCC, 0x84, 0xCA, 0x05, 0x75, 0xCC,
+ 0x88, 0xCC, 0x8C, 0xCA, 0x05, 0x75, 0xCC, 0x9B,
+ 0xCC, 0x80, 0xCA, 0x05, 0x75, 0xCC, 0x9B, 0xCC,
+ 0x81, 0xCA, 0x05, 0x75, 0xCC, 0x9B, 0xCC, 0x83,
+ // Bytes 3b80 - 3bbf
+ 0xCA, 0x05, 0x75, 0xCC, 0x9B, 0xCC, 0x89, 0xCA,
+ 0x05, 0x75, 0xCC, 0x9B, 0xCC, 0xA3, 0xB6, 0x05,
+ 0xE1, 0xBE, 0xBF, 0xCC, 0x80, 0xCA, 0x05, 0xE1,
+ 0xBE, 0xBF, 0xCC, 0x81, 0xCA, 0x05, 0xE1, 0xBE,
+ 0xBF, 0xCD, 0x82, 0xCA, 0x05, 0xE1, 0xBF, 0xBE,
+ 0xCC, 0x80, 0xCA, 0x05, 0xE1, 0xBF, 0xBE, 0xCC,
+ 0x81, 0xCA, 0x05, 0xE1, 0xBF, 0xBE, 0xCD, 0x82,
+ 0xCA, 0x05, 0xE2, 0x86, 0x90, 0xCC, 0xB8, 0x05,
+ // Bytes 3bc0 - 3bff
+ 0x05, 0xE2, 0x86, 0x92, 0xCC, 0xB8, 0x05, 0x05,
+ 0xE2, 0x86, 0x94, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+ 0x87, 0x90, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x87,
+ 0x92, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x87, 0x94,
+ 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x88, 0x83, 0xCC,
+ 0xB8, 0x05, 0x05, 0xE2, 0x88, 0x88, 0xCC, 0xB8,
+ 0x05, 0x05, 0xE2, 0x88, 0x8B, 0xCC, 0xB8, 0x05,
+ 0x05, 0xE2, 0x88, 0xA3, 0xCC, 0xB8, 0x05, 0x05,
+ // Bytes 3c00 - 3c3f
+ 0xE2, 0x88, 0xA5, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+ 0x88, 0xBC, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89,
+ 0x83, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89, 0x85,
+ 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89, 0x88, 0xCC,
+ 0xB8, 0x05, 0x05, 0xE2, 0x89, 0x8D, 0xCC, 0xB8,
+ 0x05, 0x05, 0xE2, 0x89, 0xA1, 0xCC, 0xB8, 0x05,
+ 0x05, 0xE2, 0x89, 0xA4, 0xCC, 0xB8, 0x05, 0x05,
+ 0xE2, 0x89, 0xA5, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+ // Bytes 3c40 - 3c7f
+ 0x89, 0xB2, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89,
+ 0xB3, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89, 0xB6,
+ 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x89, 0xB7, 0xCC,
+ 0xB8, 0x05, 0x05, 0xE2, 0x89, 0xBA, 0xCC, 0xB8,
+ 0x05, 0x05, 0xE2, 0x89, 0xBB, 0xCC, 0xB8, 0x05,
+ 0x05, 0xE2, 0x89, 0xBC, 0xCC, 0xB8, 0x05, 0x05,
+ 0xE2, 0x89, 0xBD, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+ 0x8A, 0x82, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A,
+ // Bytes 3c80 - 3cbf
+ 0x83, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0x86,
+ 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0x87, 0xCC,
+ 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0x91, 0xCC, 0xB8,
+ 0x05, 0x05, 0xE2, 0x8A, 0x92, 0xCC, 0xB8, 0x05,
+ 0x05, 0xE2, 0x8A, 0xA2, 0xCC, 0xB8, 0x05, 0x05,
+ 0xE2, 0x8A, 0xA8, 0xCC, 0xB8, 0x05, 0x05, 0xE2,
+ 0x8A, 0xA9, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A,
+ 0xAB, 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0xB2,
+ // Bytes 3cc0 - 3cff
+ 0xCC, 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0xB3, 0xCC,
+ 0xB8, 0x05, 0x05, 0xE2, 0x8A, 0xB4, 0xCC, 0xB8,
+ 0x05, 0x05, 0xE2, 0x8A, 0xB5, 0xCC, 0xB8, 0x05,
+ 0x06, 0xCE, 0x91, 0xCC, 0x93, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0x91, 0xCC, 0x94, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0x95, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0x95, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0x95, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ // Bytes 3d00 - 3d3f
+ 0x06, 0xCE, 0x95, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0x97, 0xCC, 0x93, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0x97, 0xCC, 0x94, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0x99, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0x99, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0x99, 0xCC, 0x93, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCE, 0x99, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0x99, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ // Bytes 3d40 - 3d7f
+ 0x06, 0xCE, 0x99, 0xCC, 0x94, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCE, 0x9F, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0x9F, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0x9F, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0x9F, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xA5, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xA5, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xA5, 0xCC, 0x94, 0xCD, 0x82, 0xCA,
+ // Bytes 3d80 - 3dbf
+ 0x06, 0xCE, 0xA9, 0xCC, 0x93, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xA9, 0xCC, 0x94, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB1, 0xCC, 0x80, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB1, 0xCC, 0x81, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB1, 0xCC, 0x93, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB1, 0xCC, 0x94, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB1, 0xCD, 0x82, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB5, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ // Bytes 3dc0 - 3dff
+ 0x06, 0xCE, 0xB5, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xB5, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xB5, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xB7, 0xCC, 0x80, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB7, 0xCC, 0x81, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB7, 0xCC, 0x93, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB7, 0xCC, 0x94, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCE, 0xB7, 0xCD, 0x82, 0xCD, 0x85, 0xDA,
+ // Bytes 3e00 - 3e3f
+ 0x06, 0xCE, 0xB9, 0xCC, 0x88, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x88, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x88, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x93, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xB9, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ // Bytes 3e40 - 3e7f
+ 0x06, 0xCE, 0xB9, 0xCC, 0x94, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCE, 0xBF, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xBF, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCE, 0xBF, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCE, 0xBF, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x88, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x88, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x88, 0xCD, 0x82, 0xCA,
+ // Bytes 3e80 - 3ebf
+ 0x06, 0xCF, 0x85, 0xCC, 0x93, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x93, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x93, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x94, 0xCC, 0x80, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x94, 0xCC, 0x81, 0xCA,
+ 0x06, 0xCF, 0x85, 0xCC, 0x94, 0xCD, 0x82, 0xCA,
+ 0x06, 0xCF, 0x89, 0xCC, 0x80, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCF, 0x89, 0xCC, 0x81, 0xCD, 0x85, 0xDA,
+ // Bytes 3ec0 - 3eff
+ 0x06, 0xCF, 0x89, 0xCC, 0x93, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCF, 0x89, 0xCC, 0x94, 0xCD, 0x85, 0xDA,
+ 0x06, 0xCF, 0x89, 0xCD, 0x82, 0xCD, 0x85, 0xDA,
+ 0x06, 0xE0, 0xA4, 0xA8, 0xE0, 0xA4, 0xBC, 0x09,
+ 0x06, 0xE0, 0xA4, 0xB0, 0xE0, 0xA4, 0xBC, 0x09,
+ 0x06, 0xE0, 0xA4, 0xB3, 0xE0, 0xA4, 0xBC, 0x09,
+ 0x06, 0xE0, 0xB1, 0x86, 0xE0, 0xB1, 0x96, 0x85,
+ 0x06, 0xE0, 0xB7, 0x99, 0xE0, 0xB7, 0x8A, 0x11,
+ // Bytes 3f00 - 3f3f
+ 0x06, 0xE3, 0x81, 0x86, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x8B, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x8D, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x8F, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x91, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x93, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x95, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x97, 0xE3, 0x82, 0x99, 0x0D,
+ // Bytes 3f40 - 3f7f
+ 0x06, 0xE3, 0x81, 0x99, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x9B, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x9D, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0x9F, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xA1, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xA4, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xA6, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xA8, 0xE3, 0x82, 0x99, 0x0D,
+ // Bytes 3f80 - 3fbf
+ 0x06, 0xE3, 0x81, 0xAF, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xAF, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x81, 0xB2, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xB2, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x81, 0xB5, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xB5, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x81, 0xB8, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xB8, 0xE3, 0x82, 0x9A, 0x0D,
+ // Bytes 3fc0 - 3fff
+ 0x06, 0xE3, 0x81, 0xBB, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x81, 0xBB, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x82, 0x9D, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xA6, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xAB, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xAD, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xAF, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xB1, 0xE3, 0x82, 0x99, 0x0D,
+ // Bytes 4000 - 403f
+ 0x06, 0xE3, 0x82, 0xB3, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xB5, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xB7, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xB9, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xBB, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xBD, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x82, 0xBF, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x81, 0xE3, 0x82, 0x99, 0x0D,
+ // Bytes 4040 - 407f
+ 0x06, 0xE3, 0x83, 0x84, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x86, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x88, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x8F, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x8F, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x92, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x83, 0x95, 0xE3, 0x82, 0x99, 0x0D,
+ // Bytes 4080 - 40bf
+ 0x06, 0xE3, 0x83, 0x95, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x98, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x83, 0x9B, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0x9B, 0xE3, 0x82, 0x9A, 0x0D,
+ 0x06, 0xE3, 0x83, 0xAF, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0xB0, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0xB1, 0xE3, 0x82, 0x99, 0x0D,
+ // Bytes 40c0 - 40ff
+ 0x06, 0xE3, 0x83, 0xB2, 0xE3, 0x82, 0x99, 0x0D,
+ 0x06, 0xE3, 0x83, 0xBD, 0xE3, 0x82, 0x99, 0x0D,
+ 0x08, 0xCE, 0x91, 0xCC, 0x93, 0xCC, 0x80, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0x91, 0xCC, 0x93, 0xCC,
+ 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0x91, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ 0x91, 0xCC, 0x94, 0xCC, 0x80, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCE, 0x91, 0xCC, 0x94, 0xCC, 0x81, 0xCD,
+ // Bytes 4100 - 413f
+ 0x85, 0xDB, 0x08, 0xCE, 0x91, 0xCC, 0x94, 0xCD,
+ 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0x97, 0xCC,
+ 0x93, 0xCC, 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ 0x97, 0xCC, 0x93, 0xCC, 0x81, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCE, 0x97, 0xCC, 0x93, 0xCD, 0x82, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0x97, 0xCC, 0x94, 0xCC,
+ 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0x97, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ // Bytes 4140 - 417f
+ 0x97, 0xCC, 0x94, 0xCD, 0x82, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCE, 0xA9, 0xCC, 0x93, 0xCC, 0x80, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0xA9, 0xCC, 0x93, 0xCC,
+ 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xA9, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ 0xA9, 0xCC, 0x94, 0xCC, 0x80, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCE, 0xA9, 0xCC, 0x94, 0xCC, 0x81, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0xA9, 0xCC, 0x94, 0xCD,
+ // Bytes 4180 - 41bf
+ 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xB1, 0xCC,
+ 0x93, 0xCC, 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ 0xB1, 0xCC, 0x93, 0xCC, 0x81, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCE, 0xB1, 0xCC, 0x93, 0xCD, 0x82, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0xB1, 0xCC, 0x94, 0xCC,
+ 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xB1, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ 0xB1, 0xCC, 0x94, 0xCD, 0x82, 0xCD, 0x85, 0xDB,
+ // Bytes 41c0 - 41ff
+ 0x08, 0xCE, 0xB7, 0xCC, 0x93, 0xCC, 0x80, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0xB7, 0xCC, 0x93, 0xCC,
+ 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCE, 0xB7, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCE,
+ 0xB7, 0xCC, 0x94, 0xCC, 0x80, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCE, 0xB7, 0xCC, 0x94, 0xCC, 0x81, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCE, 0xB7, 0xCC, 0x94, 0xCD,
+ 0x82, 0xCD, 0x85, 0xDB, 0x08, 0xCF, 0x89, 0xCC,
+ // Bytes 4200 - 423f
+ 0x93, 0xCC, 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCF,
+ 0x89, 0xCC, 0x93, 0xCC, 0x81, 0xCD, 0x85, 0xDB,
+ 0x08, 0xCF, 0x89, 0xCC, 0x93, 0xCD, 0x82, 0xCD,
+ 0x85, 0xDB, 0x08, 0xCF, 0x89, 0xCC, 0x94, 0xCC,
+ 0x80, 0xCD, 0x85, 0xDB, 0x08, 0xCF, 0x89, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCD, 0x85, 0xDB, 0x08, 0xCF,
+ 0x89, 0xCC, 0x94, 0xCD, 0x82, 0xCD, 0x85, 0xDB,
+ 0x08, 0xF0, 0x91, 0x82, 0x99, 0xF0, 0x91, 0x82,
+ // Bytes 4240 - 427f
+ 0xBA, 0x09, 0x08, 0xF0, 0x91, 0x82, 0x9B, 0xF0,
+ 0x91, 0x82, 0xBA, 0x09, 0x08, 0xF0, 0x91, 0x82,
+ 0xA5, 0xF0, 0x91, 0x82, 0xBA, 0x09, 0x42, 0xC2,
+ 0xB4, 0x01, 0x43, 0x20, 0xCC, 0x81, 0xC9, 0x43,
+ 0x20, 0xCC, 0x83, 0xC9, 0x43, 0x20, 0xCC, 0x84,
+ 0xC9, 0x43, 0x20, 0xCC, 0x85, 0xC9, 0x43, 0x20,
+ 0xCC, 0x86, 0xC9, 0x43, 0x20, 0xCC, 0x87, 0xC9,
+ 0x43, 0x20, 0xCC, 0x88, 0xC9, 0x43, 0x20, 0xCC,
+ // Bytes 4280 - 42bf
+ 0x8A, 0xC9, 0x43, 0x20, 0xCC, 0x8B, 0xC9, 0x43,
+ 0x20, 0xCC, 0x93, 0xC9, 0x43, 0x20, 0xCC, 0x94,
+ 0xC9, 0x43, 0x20, 0xCC, 0xA7, 0xA5, 0x43, 0x20,
+ 0xCC, 0xA8, 0xA5, 0x43, 0x20, 0xCC, 0xB3, 0xB5,
+ 0x43, 0x20, 0xCD, 0x82, 0xC9, 0x43, 0x20, 0xCD,
+ 0x85, 0xD9, 0x43, 0x20, 0xD9, 0x8B, 0x59, 0x43,
+ 0x20, 0xD9, 0x8C, 0x5D, 0x43, 0x20, 0xD9, 0x8D,
+ 0x61, 0x43, 0x20, 0xD9, 0x8E, 0x65, 0x43, 0x20,
+ // Bytes 42c0 - 42ff
+ 0xD9, 0x8F, 0x69, 0x43, 0x20, 0xD9, 0x90, 0x6D,
+ 0x43, 0x20, 0xD9, 0x91, 0x71, 0x43, 0x20, 0xD9,
+ 0x92, 0x75, 0x43, 0x41, 0xCC, 0x8A, 0xC9, 0x43,
+ 0x73, 0xCC, 0x87, 0xC9, 0x43, 0xE1, 0x85, 0xA1,
+ 0x01, 0x43, 0xE1, 0x85, 0xA2, 0x01, 0x43, 0xE1,
+ 0x85, 0xA3, 0x01, 0x43, 0xE1, 0x85, 0xA4, 0x01,
+ 0x43, 0xE1, 0x85, 0xA5, 0x01, 0x43, 0xE1, 0x85,
+ 0xA6, 0x01, 0x43, 0xE1, 0x85, 0xA7, 0x01, 0x43,
+ // Bytes 4300 - 433f
+ 0xE1, 0x85, 0xA8, 0x01, 0x43, 0xE1, 0x85, 0xA9,
+ 0x01, 0x43, 0xE1, 0x85, 0xAA, 0x01, 0x43, 0xE1,
+ 0x85, 0xAB, 0x01, 0x43, 0xE1, 0x85, 0xAC, 0x01,
+ 0x43, 0xE1, 0x85, 0xAD, 0x01, 0x43, 0xE1, 0x85,
+ 0xAE, 0x01, 0x43, 0xE1, 0x85, 0xAF, 0x01, 0x43,
+ 0xE1, 0x85, 0xB0, 0x01, 0x43, 0xE1, 0x85, 0xB1,
+ 0x01, 0x43, 0xE1, 0x85, 0xB2, 0x01, 0x43, 0xE1,
+ 0x85, 0xB3, 0x01, 0x43, 0xE1, 0x85, 0xB4, 0x01,
+ // Bytes 4340 - 437f
+ 0x43, 0xE1, 0x85, 0xB5, 0x01, 0x43, 0xE1, 0x86,
+ 0xAA, 0x01, 0x43, 0xE1, 0x86, 0xAC, 0x01, 0x43,
+ 0xE1, 0x86, 0xAD, 0x01, 0x43, 0xE1, 0x86, 0xB0,
+ 0x01, 0x43, 0xE1, 0x86, 0xB1, 0x01, 0x43, 0xE1,
+ 0x86, 0xB2, 0x01, 0x43, 0xE1, 0x86, 0xB3, 0x01,
+ 0x43, 0xE1, 0x86, 0xB4, 0x01, 0x43, 0xE1, 0x86,
+ 0xB5, 0x01, 0x44, 0x20, 0xE3, 0x82, 0x99, 0x0D,
+ 0x44, 0x20, 0xE3, 0x82, 0x9A, 0x0D, 0x44, 0xC2,
+ // Bytes 4380 - 43bf
+ 0xA8, 0xCC, 0x81, 0xCA, 0x44, 0xCE, 0x91, 0xCC,
+ 0x81, 0xC9, 0x44, 0xCE, 0x95, 0xCC, 0x81, 0xC9,
+ 0x44, 0xCE, 0x97, 0xCC, 0x81, 0xC9, 0x44, 0xCE,
+ 0x99, 0xCC, 0x81, 0xC9, 0x44, 0xCE, 0x9F, 0xCC,
+ 0x81, 0xC9, 0x44, 0xCE, 0xA5, 0xCC, 0x81, 0xC9,
+ 0x44, 0xCE, 0xA5, 0xCC, 0x88, 0xC9, 0x44, 0xCE,
+ 0xA9, 0xCC, 0x81, 0xC9, 0x44, 0xCE, 0xB1, 0xCC,
+ 0x81, 0xC9, 0x44, 0xCE, 0xB5, 0xCC, 0x81, 0xC9,
+ // Bytes 43c0 - 43ff
+ 0x44, 0xCE, 0xB7, 0xCC, 0x81, 0xC9, 0x44, 0xCE,
+ 0xB9, 0xCC, 0x81, 0xC9, 0x44, 0xCE, 0xBF, 0xCC,
+ 0x81, 0xC9, 0x44, 0xCF, 0x85, 0xCC, 0x81, 0xC9,
+ 0x44, 0xCF, 0x89, 0xCC, 0x81, 0xC9, 0x44, 0xD7,
+ 0x90, 0xD6, 0xB7, 0x31, 0x44, 0xD7, 0x90, 0xD6,
+ 0xB8, 0x35, 0x44, 0xD7, 0x90, 0xD6, 0xBC, 0x41,
+ 0x44, 0xD7, 0x91, 0xD6, 0xBC, 0x41, 0x44, 0xD7,
+ 0x91, 0xD6, 0xBF, 0x49, 0x44, 0xD7, 0x92, 0xD6,
+ // Bytes 4400 - 443f
+ 0xBC, 0x41, 0x44, 0xD7, 0x93, 0xD6, 0xBC, 0x41,
+ 0x44, 0xD7, 0x94, 0xD6, 0xBC, 0x41, 0x44, 0xD7,
+ 0x95, 0xD6, 0xB9, 0x39, 0x44, 0xD7, 0x95, 0xD6,
+ 0xBC, 0x41, 0x44, 0xD7, 0x96, 0xD6, 0xBC, 0x41,
+ 0x44, 0xD7, 0x98, 0xD6, 0xBC, 0x41, 0x44, 0xD7,
+ 0x99, 0xD6, 0xB4, 0x25, 0x44, 0xD7, 0x99, 0xD6,
+ 0xBC, 0x41, 0x44, 0xD7, 0x9A, 0xD6, 0xBC, 0x41,
+ 0x44, 0xD7, 0x9B, 0xD6, 0xBC, 0x41, 0x44, 0xD7,
+ // Bytes 4440 - 447f
+ 0x9B, 0xD6, 0xBF, 0x49, 0x44, 0xD7, 0x9C, 0xD6,
+ 0xBC, 0x41, 0x44, 0xD7, 0x9E, 0xD6, 0xBC, 0x41,
+ 0x44, 0xD7, 0xA0, 0xD6, 0xBC, 0x41, 0x44, 0xD7,
+ 0xA1, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0xA3, 0xD6,
+ 0xBC, 0x41, 0x44, 0xD7, 0xA4, 0xD6, 0xBC, 0x41,
+ 0x44, 0xD7, 0xA4, 0xD6, 0xBF, 0x49, 0x44, 0xD7,
+ 0xA6, 0xD6, 0xBC, 0x41, 0x44, 0xD7, 0xA7, 0xD6,
+ 0xBC, 0x41, 0x44, 0xD7, 0xA8, 0xD6, 0xBC, 0x41,
+ // Bytes 4480 - 44bf
+ 0x44, 0xD7, 0xA9, 0xD6, 0xBC, 0x41, 0x44, 0xD7,
+ 0xA9, 0xD7, 0x81, 0x4D, 0x44, 0xD7, 0xA9, 0xD7,
+ 0x82, 0x51, 0x44, 0xD7, 0xAA, 0xD6, 0xBC, 0x41,
+ 0x44, 0xD7, 0xB2, 0xD6, 0xB7, 0x31, 0x44, 0xD8,
+ 0xA7, 0xD9, 0x8B, 0x59, 0x44, 0xD8, 0xA7, 0xD9,
+ 0x93, 0xC9, 0x44, 0xD8, 0xA7, 0xD9, 0x94, 0xC9,
+ 0x44, 0xD8, 0xA7, 0xD9, 0x95, 0xB5, 0x44, 0xD8,
+ 0xB0, 0xD9, 0xB0, 0x79, 0x44, 0xD8, 0xB1, 0xD9,
+ // Bytes 44c0 - 44ff
+ 0xB0, 0x79, 0x44, 0xD9, 0x80, 0xD9, 0x8B, 0x59,
+ 0x44, 0xD9, 0x80, 0xD9, 0x8E, 0x65, 0x44, 0xD9,
+ 0x80, 0xD9, 0x8F, 0x69, 0x44, 0xD9, 0x80, 0xD9,
+ 0x90, 0x6D, 0x44, 0xD9, 0x80, 0xD9, 0x91, 0x71,
+ 0x44, 0xD9, 0x80, 0xD9, 0x92, 0x75, 0x44, 0xD9,
+ 0x87, 0xD9, 0xB0, 0x79, 0x44, 0xD9, 0x88, 0xD9,
+ 0x94, 0xC9, 0x44, 0xD9, 0x89, 0xD9, 0xB0, 0x79,
+ 0x44, 0xD9, 0x8A, 0xD9, 0x94, 0xC9, 0x44, 0xDB,
+ // Bytes 4500 - 453f
+ 0x92, 0xD9, 0x94, 0xC9, 0x44, 0xDB, 0x95, 0xD9,
+ 0x94, 0xC9, 0x45, 0x20, 0xCC, 0x88, 0xCC, 0x80,
+ 0xCA, 0x45, 0x20, 0xCC, 0x88, 0xCC, 0x81, 0xCA,
+ 0x45, 0x20, 0xCC, 0x88, 0xCD, 0x82, 0xCA, 0x45,
+ 0x20, 0xCC, 0x93, 0xCC, 0x80, 0xCA, 0x45, 0x20,
+ 0xCC, 0x93, 0xCC, 0x81, 0xCA, 0x45, 0x20, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCA, 0x45, 0x20, 0xCC, 0x94,
+ 0xCC, 0x80, 0xCA, 0x45, 0x20, 0xCC, 0x94, 0xCC,
+ // Bytes 4540 - 457f
+ 0x81, 0xCA, 0x45, 0x20, 0xCC, 0x94, 0xCD, 0x82,
+ 0xCA, 0x45, 0x20, 0xD9, 0x8C, 0xD9, 0x91, 0x72,
+ 0x45, 0x20, 0xD9, 0x8D, 0xD9, 0x91, 0x72, 0x45,
+ 0x20, 0xD9, 0x8E, 0xD9, 0x91, 0x72, 0x45, 0x20,
+ 0xD9, 0x8F, 0xD9, 0x91, 0x72, 0x45, 0x20, 0xD9,
+ 0x90, 0xD9, 0x91, 0x72, 0x45, 0x20, 0xD9, 0x91,
+ 0xD9, 0xB0, 0x7A, 0x45, 0xE2, 0xAB, 0x9D, 0xCC,
+ 0xB8, 0x05, 0x46, 0xCE, 0xB9, 0xCC, 0x88, 0xCC,
+ // Bytes 4580 - 45bf
+ 0x81, 0xCA, 0x46, 0xCF, 0x85, 0xCC, 0x88, 0xCC,
+ 0x81, 0xCA, 0x46, 0xD7, 0xA9, 0xD6, 0xBC, 0xD7,
+ 0x81, 0x4E, 0x46, 0xD7, 0xA9, 0xD6, 0xBC, 0xD7,
+ 0x82, 0x52, 0x46, 0xD9, 0x80, 0xD9, 0x8E, 0xD9,
+ 0x91, 0x72, 0x46, 0xD9, 0x80, 0xD9, 0x8F, 0xD9,
+ 0x91, 0x72, 0x46, 0xD9, 0x80, 0xD9, 0x90, 0xD9,
+ 0x91, 0x72, 0x46, 0xE0, 0xA4, 0x95, 0xE0, 0xA4,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0x96, 0xE0, 0xA4,
+ // Bytes 45c0 - 45ff
+ 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0x97, 0xE0, 0xA4,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0x9C, 0xE0, 0xA4,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0xA1, 0xE0, 0xA4,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0xA2, 0xE0, 0xA4,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0xAB, 0xE0, 0xA4,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA4, 0xAF, 0xE0, 0xA4,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA6, 0xA1, 0xE0, 0xA6,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA6, 0xA2, 0xE0, 0xA6,
+ // Bytes 4600 - 463f
+ 0xBC, 0x09, 0x46, 0xE0, 0xA6, 0xAF, 0xE0, 0xA6,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA8, 0x96, 0xE0, 0xA8,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA8, 0x97, 0xE0, 0xA8,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA8, 0x9C, 0xE0, 0xA8,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA8, 0xAB, 0xE0, 0xA8,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA8, 0xB2, 0xE0, 0xA8,
+ 0xBC, 0x09, 0x46, 0xE0, 0xA8, 0xB8, 0xE0, 0xA8,
+ 0xBC, 0x09, 0x46, 0xE0, 0xAC, 0xA1, 0xE0, 0xAC,
+ // Bytes 4640 - 467f
+ 0xBC, 0x09, 0x46, 0xE0, 0xAC, 0xA2, 0xE0, 0xAC,
+ 0xBC, 0x09, 0x46, 0xE0, 0xBE, 0xB2, 0xE0, 0xBE,
+ 0x80, 0x9D, 0x46, 0xE0, 0xBE, 0xB3, 0xE0, 0xBE,
+ 0x80, 0x9D, 0x46, 0xE3, 0x83, 0x86, 0xE3, 0x82,
+ 0x99, 0x0D, 0x48, 0xF0, 0x9D, 0x85, 0x97, 0xF0,
+ 0x9D, 0x85, 0xA5, 0xAD, 0x48, 0xF0, 0x9D, 0x85,
+ 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xAD, 0x48, 0xF0,
+ 0x9D, 0x86, 0xB9, 0xF0, 0x9D, 0x85, 0xA5, 0xAD,
+ // Bytes 4680 - 46bf
+ 0x48, 0xF0, 0x9D, 0x86, 0xBA, 0xF0, 0x9D, 0x85,
+ 0xA5, 0xAD, 0x49, 0xE0, 0xBE, 0xB2, 0xE0, 0xBD,
+ 0xB1, 0xE0, 0xBE, 0x80, 0x9E, 0x49, 0xE0, 0xBE,
+ 0xB3, 0xE0, 0xBD, 0xB1, 0xE0, 0xBE, 0x80, 0x9E,
+ 0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85,
+ 0xA5, 0xF0, 0x9D, 0x85, 0xAE, 0xAE, 0x4C, 0xF0,
+ 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0,
+ 0x9D, 0x85, 0xAF, 0xAE, 0x4C, 0xF0, 0x9D, 0x85,
+ // Bytes 46c0 - 46ff
+ 0x98, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85,
+ 0xB0, 0xAE, 0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0,
+ 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xB1, 0xAE,
+ 0x4C, 0xF0, 0x9D, 0x85, 0x98, 0xF0, 0x9D, 0x85,
+ 0xA5, 0xF0, 0x9D, 0x85, 0xB2, 0xAE, 0x4C, 0xF0,
+ 0x9D, 0x86, 0xB9, 0xF0, 0x9D, 0x85, 0xA5, 0xF0,
+ 0x9D, 0x85, 0xAE, 0xAE, 0x4C, 0xF0, 0x9D, 0x86,
+ 0xB9, 0xF0, 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85,
+ // Bytes 4700 - 473f
+ 0xAF, 0xAE, 0x4C, 0xF0, 0x9D, 0x86, 0xBA, 0xF0,
+ 0x9D, 0x85, 0xA5, 0xF0, 0x9D, 0x85, 0xAE, 0xAE,
+ 0x4C, 0xF0, 0x9D, 0x86, 0xBA, 0xF0, 0x9D, 0x85,
+ 0xA5, 0xF0, 0x9D, 0x85, 0xAF, 0xAE, 0x83, 0x41,
+ 0xCC, 0x82, 0xC9, 0x83, 0x41, 0xCC, 0x86, 0xC9,
+ 0x83, 0x41, 0xCC, 0x87, 0xC9, 0x83, 0x41, 0xCC,
+ 0x88, 0xC9, 0x83, 0x41, 0xCC, 0x8A, 0xC9, 0x83,
+ 0x41, 0xCC, 0xA3, 0xB5, 0x83, 0x43, 0xCC, 0xA7,
+ // Bytes 4740 - 477f
+ 0xA5, 0x83, 0x45, 0xCC, 0x82, 0xC9, 0x83, 0x45,
+ 0xCC, 0x84, 0xC9, 0x83, 0x45, 0xCC, 0xA3, 0xB5,
+ 0x83, 0x45, 0xCC, 0xA7, 0xA5, 0x83, 0x49, 0xCC,
+ 0x88, 0xC9, 0x83, 0x4C, 0xCC, 0xA3, 0xB5, 0x83,
+ 0x4F, 0xCC, 0x82, 0xC9, 0x83, 0x4F, 0xCC, 0x83,
+ 0xC9, 0x83, 0x4F, 0xCC, 0x84, 0xC9, 0x83, 0x4F,
+ 0xCC, 0x87, 0xC9, 0x83, 0x4F, 0xCC, 0x88, 0xC9,
+ 0x83, 0x4F, 0xCC, 0x9B, 0xAD, 0x83, 0x4F, 0xCC,
+ // Bytes 4780 - 47bf
+ 0xA3, 0xB5, 0x83, 0x4F, 0xCC, 0xA8, 0xA5, 0x83,
+ 0x52, 0xCC, 0xA3, 0xB5, 0x83, 0x53, 0xCC, 0x81,
+ 0xC9, 0x83, 0x53, 0xCC, 0x8C, 0xC9, 0x83, 0x53,
+ 0xCC, 0xA3, 0xB5, 0x83, 0x55, 0xCC, 0x83, 0xC9,
+ 0x83, 0x55, 0xCC, 0x84, 0xC9, 0x83, 0x55, 0xCC,
+ 0x88, 0xC9, 0x83, 0x55, 0xCC, 0x9B, 0xAD, 0x83,
+ 0x61, 0xCC, 0x82, 0xC9, 0x83, 0x61, 0xCC, 0x86,
+ 0xC9, 0x83, 0x61, 0xCC, 0x87, 0xC9, 0x83, 0x61,
+ // Bytes 47c0 - 47ff
+ 0xCC, 0x88, 0xC9, 0x83, 0x61, 0xCC, 0x8A, 0xC9,
+ 0x83, 0x61, 0xCC, 0xA3, 0xB5, 0x83, 0x63, 0xCC,
+ 0xA7, 0xA5, 0x83, 0x65, 0xCC, 0x82, 0xC9, 0x83,
+ 0x65, 0xCC, 0x84, 0xC9, 0x83, 0x65, 0xCC, 0xA3,
+ 0xB5, 0x83, 0x65, 0xCC, 0xA7, 0xA5, 0x83, 0x69,
+ 0xCC, 0x88, 0xC9, 0x83, 0x6C, 0xCC, 0xA3, 0xB5,
+ 0x83, 0x6F, 0xCC, 0x82, 0xC9, 0x83, 0x6F, 0xCC,
+ 0x83, 0xC9, 0x83, 0x6F, 0xCC, 0x84, 0xC9, 0x83,
+ // Bytes 4800 - 483f
+ 0x6F, 0xCC, 0x87, 0xC9, 0x83, 0x6F, 0xCC, 0x88,
+ 0xC9, 0x83, 0x6F, 0xCC, 0x9B, 0xAD, 0x83, 0x6F,
+ 0xCC, 0xA3, 0xB5, 0x83, 0x6F, 0xCC, 0xA8, 0xA5,
+ 0x83, 0x72, 0xCC, 0xA3, 0xB5, 0x83, 0x73, 0xCC,
+ 0x81, 0xC9, 0x83, 0x73, 0xCC, 0x8C, 0xC9, 0x83,
+ 0x73, 0xCC, 0xA3, 0xB5, 0x83, 0x75, 0xCC, 0x83,
+ 0xC9, 0x83, 0x75, 0xCC, 0x84, 0xC9, 0x83, 0x75,
+ 0xCC, 0x88, 0xC9, 0x83, 0x75, 0xCC, 0x9B, 0xAD,
+ // Bytes 4840 - 487f
+ 0x84, 0xCE, 0x91, 0xCC, 0x93, 0xC9, 0x84, 0xCE,
+ 0x91, 0xCC, 0x94, 0xC9, 0x84, 0xCE, 0x95, 0xCC,
+ 0x93, 0xC9, 0x84, 0xCE, 0x95, 0xCC, 0x94, 0xC9,
+ 0x84, 0xCE, 0x97, 0xCC, 0x93, 0xC9, 0x84, 0xCE,
+ 0x97, 0xCC, 0x94, 0xC9, 0x84, 0xCE, 0x99, 0xCC,
+ 0x93, 0xC9, 0x84, 0xCE, 0x99, 0xCC, 0x94, 0xC9,
+ 0x84, 0xCE, 0x9F, 0xCC, 0x93, 0xC9, 0x84, 0xCE,
+ 0x9F, 0xCC, 0x94, 0xC9, 0x84, 0xCE, 0xA5, 0xCC,
+ // Bytes 4880 - 48bf
+ 0x94, 0xC9, 0x84, 0xCE, 0xA9, 0xCC, 0x93, 0xC9,
+ 0x84, 0xCE, 0xA9, 0xCC, 0x94, 0xC9, 0x84, 0xCE,
+ 0xB1, 0xCC, 0x80, 0xC9, 0x84, 0xCE, 0xB1, 0xCC,
+ 0x81, 0xC9, 0x84, 0xCE, 0xB1, 0xCC, 0x93, 0xC9,
+ 0x84, 0xCE, 0xB1, 0xCC, 0x94, 0xC9, 0x84, 0xCE,
+ 0xB1, 0xCD, 0x82, 0xC9, 0x84, 0xCE, 0xB5, 0xCC,
+ 0x93, 0xC9, 0x84, 0xCE, 0xB5, 0xCC, 0x94, 0xC9,
+ 0x84, 0xCE, 0xB7, 0xCC, 0x80, 0xC9, 0x84, 0xCE,
+ // Bytes 48c0 - 48ff
+ 0xB7, 0xCC, 0x81, 0xC9, 0x84, 0xCE, 0xB7, 0xCC,
+ 0x93, 0xC9, 0x84, 0xCE, 0xB7, 0xCC, 0x94, 0xC9,
+ 0x84, 0xCE, 0xB7, 0xCD, 0x82, 0xC9, 0x84, 0xCE,
+ 0xB9, 0xCC, 0x88, 0xC9, 0x84, 0xCE, 0xB9, 0xCC,
+ 0x93, 0xC9, 0x84, 0xCE, 0xB9, 0xCC, 0x94, 0xC9,
+ 0x84, 0xCE, 0xBF, 0xCC, 0x93, 0xC9, 0x84, 0xCE,
+ 0xBF, 0xCC, 0x94, 0xC9, 0x84, 0xCF, 0x85, 0xCC,
+ 0x88, 0xC9, 0x84, 0xCF, 0x85, 0xCC, 0x93, 0xC9,
+ // Bytes 4900 - 493f
+ 0x84, 0xCF, 0x85, 0xCC, 0x94, 0xC9, 0x84, 0xCF,
+ 0x89, 0xCC, 0x80, 0xC9, 0x84, 0xCF, 0x89, 0xCC,
+ 0x81, 0xC9, 0x84, 0xCF, 0x89, 0xCC, 0x93, 0xC9,
+ 0x84, 0xCF, 0x89, 0xCC, 0x94, 0xC9, 0x84, 0xCF,
+ 0x89, 0xCD, 0x82, 0xC9, 0x86, 0xCE, 0x91, 0xCC,
+ 0x93, 0xCC, 0x80, 0xCA, 0x86, 0xCE, 0x91, 0xCC,
+ 0x93, 0xCC, 0x81, 0xCA, 0x86, 0xCE, 0x91, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCA, 0x86, 0xCE, 0x91, 0xCC,
+ // Bytes 4940 - 497f
+ 0x94, 0xCC, 0x80, 0xCA, 0x86, 0xCE, 0x91, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCA, 0x86, 0xCE, 0x91, 0xCC,
+ 0x94, 0xCD, 0x82, 0xCA, 0x86, 0xCE, 0x97, 0xCC,
+ 0x93, 0xCC, 0x80, 0xCA, 0x86, 0xCE, 0x97, 0xCC,
+ 0x93, 0xCC, 0x81, 0xCA, 0x86, 0xCE, 0x97, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCA, 0x86, 0xCE, 0x97, 0xCC,
+ 0x94, 0xCC, 0x80, 0xCA, 0x86, 0xCE, 0x97, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCA, 0x86, 0xCE, 0x97, 0xCC,
+ // Bytes 4980 - 49bf
+ 0x94, 0xCD, 0x82, 0xCA, 0x86, 0xCE, 0xA9, 0xCC,
+ 0x93, 0xCC, 0x80, 0xCA, 0x86, 0xCE, 0xA9, 0xCC,
+ 0x93, 0xCC, 0x81, 0xCA, 0x86, 0xCE, 0xA9, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCA, 0x86, 0xCE, 0xA9, 0xCC,
+ 0x94, 0xCC, 0x80, 0xCA, 0x86, 0xCE, 0xA9, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCA, 0x86, 0xCE, 0xA9, 0xCC,
+ 0x94, 0xCD, 0x82, 0xCA, 0x86, 0xCE, 0xB1, 0xCC,
+ 0x93, 0xCC, 0x80, 0xCA, 0x86, 0xCE, 0xB1, 0xCC,
+ // Bytes 49c0 - 49ff
+ 0x93, 0xCC, 0x81, 0xCA, 0x86, 0xCE, 0xB1, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCA, 0x86, 0xCE, 0xB1, 0xCC,
+ 0x94, 0xCC, 0x80, 0xCA, 0x86, 0xCE, 0xB1, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCA, 0x86, 0xCE, 0xB1, 0xCC,
+ 0x94, 0xCD, 0x82, 0xCA, 0x86, 0xCE, 0xB7, 0xCC,
+ 0x93, 0xCC, 0x80, 0xCA, 0x86, 0xCE, 0xB7, 0xCC,
+ 0x93, 0xCC, 0x81, 0xCA, 0x86, 0xCE, 0xB7, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCA, 0x86, 0xCE, 0xB7, 0xCC,
+ // Bytes 4a00 - 4a3f
+ 0x94, 0xCC, 0x80, 0xCA, 0x86, 0xCE, 0xB7, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCA, 0x86, 0xCE, 0xB7, 0xCC,
+ 0x94, 0xCD, 0x82, 0xCA, 0x86, 0xCF, 0x89, 0xCC,
+ 0x93, 0xCC, 0x80, 0xCA, 0x86, 0xCF, 0x89, 0xCC,
+ 0x93, 0xCC, 0x81, 0xCA, 0x86, 0xCF, 0x89, 0xCC,
+ 0x93, 0xCD, 0x82, 0xCA, 0x86, 0xCF, 0x89, 0xCC,
+ 0x94, 0xCC, 0x80, 0xCA, 0x86, 0xCF, 0x89, 0xCC,
+ 0x94, 0xCC, 0x81, 0xCA, 0x86, 0xCF, 0x89, 0xCC,
+ // Bytes 4a40 - 4a7f
+ 0x94, 0xCD, 0x82, 0xCA, 0x42, 0xCC, 0x80, 0xC9,
+ 0x32, 0x42, 0xCC, 0x81, 0xC9, 0x32, 0x42, 0xCC,
+ 0x93, 0xC9, 0x32, 0x44, 0xCC, 0x88, 0xCC, 0x81,
+ 0xCA, 0x32, 0x43, 0xE3, 0x82, 0x99, 0x0D, 0x03,
+ 0x43, 0xE3, 0x82, 0x9A, 0x0D, 0x03, 0x46, 0xE0,
+ 0xBD, 0xB1, 0xE0, 0xBD, 0xB2, 0x9E, 0x26, 0x46,
+ 0xE0, 0xBD, 0xB1, 0xE0, 0xBD, 0xB4, 0xA2, 0x26,
+ 0x46, 0xE0, 0xBD, 0xB1, 0xE0, 0xBE, 0x80, 0x9E,
+ // Bytes 4a80 - 4abf
+ 0x26, 0x00, 0x01,
+}
+
+// lookup returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *nfcTrie) lookup(s []byte) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return nfcValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := nfcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := nfcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := nfcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = nfcIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *nfcTrie) lookupUnsafe(s []byte) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return nfcValues[c0]
+ }
+ i := nfcIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = nfcIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = nfcIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// lookupString returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *nfcTrie) lookupString(s string) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return nfcValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := nfcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := nfcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := nfcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = nfcIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *nfcTrie) lookupStringUnsafe(s string) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return nfcValues[c0]
+ }
+ i := nfcIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = nfcIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = nfcIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// nfcTrie. Total size: 10332 bytes (10.09 KiB). Checksum: ad355b768fddb1b6.
+type nfcTrie struct{}
+
+func newNfcTrie(i int) *nfcTrie {
+ return &nfcTrie{}
+}
+
+// lookupValue determines the type of block n and looks up the value for b.
+func (t *nfcTrie) lookupValue(n uint32, b byte) uint16 {
+ switch {
+ case n < 44:
+ return uint16(nfcValues[n<<6+uint32(b)])
+ default:
+ n -= 44
+ return uint16(nfcSparse.lookup(n, b))
+ }
+}
+
+// nfcValues: 46 blocks, 2944 entries, 5888 bytes
+// The third block is the zero block.
+var nfcValues = [2944]uint16{
+ // Block 0x0, offset 0x0
+ 0x3c: 0xa000, 0x3d: 0xa000, 0x3e: 0xa000,
+ // Block 0x1, offset 0x40
+ 0x41: 0xa000, 0x42: 0xa000, 0x43: 0xa000, 0x44: 0xa000, 0x45: 0xa000,
+ 0x46: 0xa000, 0x47: 0xa000, 0x48: 0xa000, 0x49: 0xa000, 0x4a: 0xa000, 0x4b: 0xa000,
+ 0x4c: 0xa000, 0x4d: 0xa000, 0x4e: 0xa000, 0x4f: 0xa000, 0x50: 0xa000,
+ 0x52: 0xa000, 0x53: 0xa000, 0x54: 0xa000, 0x55: 0xa000, 0x56: 0xa000, 0x57: 0xa000,
+ 0x58: 0xa000, 0x59: 0xa000, 0x5a: 0xa000,
+ 0x61: 0xa000, 0x62: 0xa000, 0x63: 0xa000,
+ 0x64: 0xa000, 0x65: 0xa000, 0x66: 0xa000, 0x67: 0xa000, 0x68: 0xa000, 0x69: 0xa000,
+ 0x6a: 0xa000, 0x6b: 0xa000, 0x6c: 0xa000, 0x6d: 0xa000, 0x6e: 0xa000, 0x6f: 0xa000,
+ 0x70: 0xa000, 0x72: 0xa000, 0x73: 0xa000, 0x74: 0xa000, 0x75: 0xa000,
+ 0x76: 0xa000, 0x77: 0xa000, 0x78: 0xa000, 0x79: 0xa000, 0x7a: 0xa000,
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc0: 0x2f6f, 0xc1: 0x2f74, 0xc2: 0x471e, 0xc3: 0x2f79, 0xc4: 0x472d, 0xc5: 0x4732,
+ 0xc6: 0xa000, 0xc7: 0x473c, 0xc8: 0x2fe2, 0xc9: 0x2fe7, 0xca: 0x4741, 0xcb: 0x2ffb,
+ 0xcc: 0x306e, 0xcd: 0x3073, 0xce: 0x3078, 0xcf: 0x4755, 0xd1: 0x3104,
+ 0xd2: 0x3127, 0xd3: 0x312c, 0xd4: 0x475f, 0xd5: 0x4764, 0xd6: 0x4773,
+ 0xd8: 0xa000, 0xd9: 0x31b3, 0xda: 0x31b8, 0xdb: 0x31bd, 0xdc: 0x47a5, 0xdd: 0x3235,
+ 0xe0: 0x327b, 0xe1: 0x3280, 0xe2: 0x47af, 0xe3: 0x3285,
+ 0xe4: 0x47be, 0xe5: 0x47c3, 0xe6: 0xa000, 0xe7: 0x47cd, 0xe8: 0x32ee, 0xe9: 0x32f3,
+ 0xea: 0x47d2, 0xeb: 0x3307, 0xec: 0x337f, 0xed: 0x3384, 0xee: 0x3389, 0xef: 0x47e6,
+ 0xf1: 0x3415, 0xf2: 0x3438, 0xf3: 0x343d, 0xf4: 0x47f0, 0xf5: 0x47f5,
+ 0xf6: 0x4804, 0xf8: 0xa000, 0xf9: 0x34c9, 0xfa: 0x34ce, 0xfb: 0x34d3,
+ 0xfc: 0x4836, 0xfd: 0x3550, 0xff: 0x3569,
+ // Block 0x4, offset 0x100
+ 0x100: 0x2f7e, 0x101: 0x328a, 0x102: 0x4723, 0x103: 0x47b4, 0x104: 0x2f9c, 0x105: 0x32a8,
+ 0x106: 0x2fb0, 0x107: 0x32bc, 0x108: 0x2fb5, 0x109: 0x32c1, 0x10a: 0x2fba, 0x10b: 0x32c6,
+ 0x10c: 0x2fbf, 0x10d: 0x32cb, 0x10e: 0x2fc9, 0x10f: 0x32d5,
+ 0x112: 0x4746, 0x113: 0x47d7, 0x114: 0x2ff1, 0x115: 0x32fd, 0x116: 0x2ff6, 0x117: 0x3302,
+ 0x118: 0x3014, 0x119: 0x3320, 0x11a: 0x3005, 0x11b: 0x3311, 0x11c: 0x302d, 0x11d: 0x3339,
+ 0x11e: 0x3037, 0x11f: 0x3343, 0x120: 0x303c, 0x121: 0x3348, 0x122: 0x3046, 0x123: 0x3352,
+ 0x124: 0x304b, 0x125: 0x3357, 0x128: 0x307d, 0x129: 0x338e,
+ 0x12a: 0x3082, 0x12b: 0x3393, 0x12c: 0x3087, 0x12d: 0x3398, 0x12e: 0x30aa, 0x12f: 0x33b6,
+ 0x130: 0x308c, 0x134: 0x30b4, 0x135: 0x33c0,
+ 0x136: 0x30c8, 0x137: 0x33d9, 0x139: 0x30d2, 0x13a: 0x33e3, 0x13b: 0x30dc,
+ 0x13c: 0x33ed, 0x13d: 0x30d7, 0x13e: 0x33e8,
+ // Block 0x5, offset 0x140
+ 0x143: 0x30ff, 0x144: 0x3410, 0x145: 0x3118,
+ 0x146: 0x3429, 0x147: 0x310e, 0x148: 0x341f,
+ 0x14c: 0x4769, 0x14d: 0x47fa, 0x14e: 0x3131, 0x14f: 0x3442, 0x150: 0x313b, 0x151: 0x344c,
+ 0x154: 0x3159, 0x155: 0x346a, 0x156: 0x3172, 0x157: 0x3483,
+ 0x158: 0x3163, 0x159: 0x3474, 0x15a: 0x478c, 0x15b: 0x481d, 0x15c: 0x317c, 0x15d: 0x348d,
+ 0x15e: 0x318b, 0x15f: 0x349c, 0x160: 0x4791, 0x161: 0x4822, 0x162: 0x31a4, 0x163: 0x34ba,
+ 0x164: 0x3195, 0x165: 0x34ab, 0x168: 0x479b, 0x169: 0x482c,
+ 0x16a: 0x47a0, 0x16b: 0x4831, 0x16c: 0x31c2, 0x16d: 0x34d8, 0x16e: 0x31cc, 0x16f: 0x34e2,
+ 0x170: 0x31d1, 0x171: 0x34e7, 0x172: 0x31ef, 0x173: 0x3505, 0x174: 0x3212, 0x175: 0x3528,
+ 0x176: 0x323a, 0x177: 0x3555, 0x178: 0x324e, 0x179: 0x325d, 0x17a: 0x357d, 0x17b: 0x3267,
+ 0x17c: 0x3587, 0x17d: 0x326c, 0x17e: 0x358c, 0x17f: 0xa000,
+ // Block 0x6, offset 0x180
+ 0x184: 0x8100, 0x185: 0x8100,
+ 0x186: 0x8100,
+ 0x18d: 0x2f88, 0x18e: 0x3294, 0x18f: 0x3096, 0x190: 0x33a2, 0x191: 0x3140,
+ 0x192: 0x3451, 0x193: 0x31d6, 0x194: 0x34ec, 0x195: 0x39cf, 0x196: 0x3b5e, 0x197: 0x39c8,
+ 0x198: 0x3b57, 0x199: 0x39d6, 0x19a: 0x3b65, 0x19b: 0x39c1, 0x19c: 0x3b50,
+ 0x19e: 0x38b0, 0x19f: 0x3a3f, 0x1a0: 0x38a9, 0x1a1: 0x3a38, 0x1a2: 0x35b3, 0x1a3: 0x35c5,
+ 0x1a6: 0x3041, 0x1a7: 0x334d, 0x1a8: 0x30be, 0x1a9: 0x33cf,
+ 0x1aa: 0x4782, 0x1ab: 0x4813, 0x1ac: 0x3990, 0x1ad: 0x3b1f, 0x1ae: 0x35d7, 0x1af: 0x35dd,
+ 0x1b0: 0x33c5, 0x1b4: 0x3028, 0x1b5: 0x3334,
+ 0x1b8: 0x30fa, 0x1b9: 0x340b, 0x1ba: 0x38b7, 0x1bb: 0x3a46,
+ 0x1bc: 0x35ad, 0x1bd: 0x35bf, 0x1be: 0x35b9, 0x1bf: 0x35cb,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x2f8d, 0x1c1: 0x3299, 0x1c2: 0x2f92, 0x1c3: 0x329e, 0x1c4: 0x300a, 0x1c5: 0x3316,
+ 0x1c6: 0x300f, 0x1c7: 0x331b, 0x1c8: 0x309b, 0x1c9: 0x33a7, 0x1ca: 0x30a0, 0x1cb: 0x33ac,
+ 0x1cc: 0x3145, 0x1cd: 0x3456, 0x1ce: 0x314a, 0x1cf: 0x345b, 0x1d0: 0x3168, 0x1d1: 0x3479,
+ 0x1d2: 0x316d, 0x1d3: 0x347e, 0x1d4: 0x31db, 0x1d5: 0x34f1, 0x1d6: 0x31e0, 0x1d7: 0x34f6,
+ 0x1d8: 0x3186, 0x1d9: 0x3497, 0x1da: 0x319f, 0x1db: 0x34b5,
+ 0x1de: 0x305a, 0x1df: 0x3366,
+ 0x1e6: 0x4728, 0x1e7: 0x47b9, 0x1e8: 0x4750, 0x1e9: 0x47e1,
+ 0x1ea: 0x395f, 0x1eb: 0x3aee, 0x1ec: 0x393c, 0x1ed: 0x3acb, 0x1ee: 0x476e, 0x1ef: 0x47ff,
+ 0x1f0: 0x3958, 0x1f1: 0x3ae7, 0x1f2: 0x3244, 0x1f3: 0x355f,
+ // Block 0x8, offset 0x200
+ 0x200: 0x9932, 0x201: 0x9932, 0x202: 0x9932, 0x203: 0x9932, 0x204: 0x9932, 0x205: 0x8132,
+ 0x206: 0x9932, 0x207: 0x9932, 0x208: 0x9932, 0x209: 0x9932, 0x20a: 0x9932, 0x20b: 0x9932,
+ 0x20c: 0x9932, 0x20d: 0x8132, 0x20e: 0x8132, 0x20f: 0x9932, 0x210: 0x8132, 0x211: 0x9932,
+ 0x212: 0x8132, 0x213: 0x9932, 0x214: 0x9932, 0x215: 0x8133, 0x216: 0x812d, 0x217: 0x812d,
+ 0x218: 0x812d, 0x219: 0x812d, 0x21a: 0x8133, 0x21b: 0x992b, 0x21c: 0x812d, 0x21d: 0x812d,
+ 0x21e: 0x812d, 0x21f: 0x812d, 0x220: 0x812d, 0x221: 0x8129, 0x222: 0x8129, 0x223: 0x992d,
+ 0x224: 0x992d, 0x225: 0x992d, 0x226: 0x992d, 0x227: 0x9929, 0x228: 0x9929, 0x229: 0x812d,
+ 0x22a: 0x812d, 0x22b: 0x812d, 0x22c: 0x812d, 0x22d: 0x992d, 0x22e: 0x992d, 0x22f: 0x812d,
+ 0x230: 0x992d, 0x231: 0x992d, 0x232: 0x812d, 0x233: 0x812d, 0x234: 0x8101, 0x235: 0x8101,
+ 0x236: 0x8101, 0x237: 0x8101, 0x238: 0x9901, 0x239: 0x812d, 0x23a: 0x812d, 0x23b: 0x812d,
+ 0x23c: 0x812d, 0x23d: 0x8132, 0x23e: 0x8132, 0x23f: 0x8132,
+ // Block 0x9, offset 0x240
+ 0x240: 0x4a44, 0x241: 0x4a49, 0x242: 0x9932, 0x243: 0x4a4e, 0x244: 0x4a53, 0x245: 0x9936,
+ 0x246: 0x8132, 0x247: 0x812d, 0x248: 0x812d, 0x249: 0x812d, 0x24a: 0x8132, 0x24b: 0x8132,
+ 0x24c: 0x8132, 0x24d: 0x812d, 0x24e: 0x812d, 0x250: 0x8132, 0x251: 0x8132,
+ 0x252: 0x8132, 0x253: 0x812d, 0x254: 0x812d, 0x255: 0x812d, 0x256: 0x812d, 0x257: 0x8132,
+ 0x258: 0x8133, 0x259: 0x812d, 0x25a: 0x812d, 0x25b: 0x8132, 0x25c: 0x8134, 0x25d: 0x8135,
+ 0x25e: 0x8135, 0x25f: 0x8134, 0x260: 0x8135, 0x261: 0x8135, 0x262: 0x8134, 0x263: 0x8132,
+ 0x264: 0x8132, 0x265: 0x8132, 0x266: 0x8132, 0x267: 0x8132, 0x268: 0x8132, 0x269: 0x8132,
+ 0x26a: 0x8132, 0x26b: 0x8132, 0x26c: 0x8132, 0x26d: 0x8132, 0x26e: 0x8132, 0x26f: 0x8132,
+ 0x274: 0x0170,
+ 0x27a: 0x8100,
+ 0x27e: 0x0037,
+ // Block 0xa, offset 0x280
+ 0x284: 0x8100, 0x285: 0x35a1,
+ 0x286: 0x35e9, 0x287: 0x00ce, 0x288: 0x3607, 0x289: 0x3613, 0x28a: 0x3625,
+ 0x28c: 0x3643, 0x28e: 0x3655, 0x28f: 0x3673, 0x290: 0x3e08, 0x291: 0xa000,
+ 0x295: 0xa000, 0x297: 0xa000,
+ 0x299: 0xa000,
+ 0x29f: 0xa000, 0x2a1: 0xa000,
+ 0x2a5: 0xa000, 0x2a9: 0xa000,
+ 0x2aa: 0x3637, 0x2ab: 0x3667, 0x2ac: 0x4894, 0x2ad: 0x3697, 0x2ae: 0x48be, 0x2af: 0x36a9,
+ 0x2b0: 0x3e70, 0x2b1: 0xa000, 0x2b5: 0xa000,
+ 0x2b7: 0xa000, 0x2b9: 0xa000,
+ 0x2bf: 0xa000,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x3721, 0x2c1: 0x372d, 0x2c3: 0x371b,
+ 0x2c6: 0xa000, 0x2c7: 0x3709,
+ 0x2cc: 0x375d, 0x2cd: 0x3745, 0x2ce: 0x376f, 0x2d0: 0xa000,
+ 0x2d3: 0xa000, 0x2d5: 0xa000, 0x2d6: 0xa000, 0x2d7: 0xa000,
+ 0x2d8: 0xa000, 0x2d9: 0x3751, 0x2da: 0xa000,
+ 0x2de: 0xa000, 0x2e3: 0xa000,
+ 0x2e7: 0xa000,
+ 0x2eb: 0xa000, 0x2ed: 0xa000,
+ 0x2f0: 0xa000, 0x2f3: 0xa000, 0x2f5: 0xa000,
+ 0x2f6: 0xa000, 0x2f7: 0xa000, 0x2f8: 0xa000, 0x2f9: 0x37d5, 0x2fa: 0xa000,
+ 0x2fe: 0xa000,
+ // Block 0xc, offset 0x300
+ 0x301: 0x3733, 0x302: 0x37b7,
+ 0x310: 0x370f, 0x311: 0x3793,
+ 0x312: 0x3715, 0x313: 0x3799, 0x316: 0x3727, 0x317: 0x37ab,
+ 0x318: 0xa000, 0x319: 0xa000, 0x31a: 0x3829, 0x31b: 0x382f, 0x31c: 0x3739, 0x31d: 0x37bd,
+ 0x31e: 0x373f, 0x31f: 0x37c3, 0x322: 0x374b, 0x323: 0x37cf,
+ 0x324: 0x3757, 0x325: 0x37db, 0x326: 0x3763, 0x327: 0x37e7, 0x328: 0xa000, 0x329: 0xa000,
+ 0x32a: 0x3835, 0x32b: 0x383b, 0x32c: 0x378d, 0x32d: 0x3811, 0x32e: 0x3769, 0x32f: 0x37ed,
+ 0x330: 0x3775, 0x331: 0x37f9, 0x332: 0x377b, 0x333: 0x37ff, 0x334: 0x3781, 0x335: 0x3805,
+ 0x338: 0x3787, 0x339: 0x380b,
+ // Block 0xd, offset 0x340
+ 0x351: 0x812d,
+ 0x352: 0x8132, 0x353: 0x8132, 0x354: 0x8132, 0x355: 0x8132, 0x356: 0x812d, 0x357: 0x8132,
+ 0x358: 0x8132, 0x359: 0x8132, 0x35a: 0x812e, 0x35b: 0x812d, 0x35c: 0x8132, 0x35d: 0x8132,
+ 0x35e: 0x8132, 0x35f: 0x8132, 0x360: 0x8132, 0x361: 0x8132, 0x362: 0x812d, 0x363: 0x812d,
+ 0x364: 0x812d, 0x365: 0x812d, 0x366: 0x812d, 0x367: 0x812d, 0x368: 0x8132, 0x369: 0x8132,
+ 0x36a: 0x812d, 0x36b: 0x8132, 0x36c: 0x8132, 0x36d: 0x812e, 0x36e: 0x8131, 0x36f: 0x8132,
+ 0x370: 0x8105, 0x371: 0x8106, 0x372: 0x8107, 0x373: 0x8108, 0x374: 0x8109, 0x375: 0x810a,
+ 0x376: 0x810b, 0x377: 0x810c, 0x378: 0x810d, 0x379: 0x810e, 0x37a: 0x810e, 0x37b: 0x810f,
+ 0x37c: 0x8110, 0x37d: 0x8111, 0x37f: 0x8112,
+ // Block 0xe, offset 0x380
+ 0x388: 0xa000, 0x38a: 0xa000, 0x38b: 0x8116,
+ 0x38c: 0x8117, 0x38d: 0x8118, 0x38e: 0x8119, 0x38f: 0x811a, 0x390: 0x811b, 0x391: 0x811c,
+ 0x392: 0x811d, 0x393: 0x9932, 0x394: 0x9932, 0x395: 0x992d, 0x396: 0x812d, 0x397: 0x8132,
+ 0x398: 0x8132, 0x399: 0x8132, 0x39a: 0x8132, 0x39b: 0x8132, 0x39c: 0x812d, 0x39d: 0x8132,
+ 0x39e: 0x8132, 0x39f: 0x812d,
+ 0x3b0: 0x811e,
+ // Block 0xf, offset 0x3c0
+ 0x3c5: 0xa000,
+ 0x3c6: 0x2d26, 0x3c7: 0xa000, 0x3c8: 0x2d2e, 0x3c9: 0xa000, 0x3ca: 0x2d36, 0x3cb: 0xa000,
+ 0x3cc: 0x2d3e, 0x3cd: 0xa000, 0x3ce: 0x2d46, 0x3d1: 0xa000,
+ 0x3d2: 0x2d4e,
+ 0x3f4: 0x8102, 0x3f5: 0x9900,
+ 0x3fa: 0xa000, 0x3fb: 0x2d56,
+ 0x3fc: 0xa000, 0x3fd: 0x2d5e, 0x3fe: 0xa000, 0x3ff: 0xa000,
+ // Block 0x10, offset 0x400
+ 0x400: 0x2f97, 0x401: 0x32a3, 0x402: 0x2fa1, 0x403: 0x32ad, 0x404: 0x2fa6, 0x405: 0x32b2,
+ 0x406: 0x2fab, 0x407: 0x32b7, 0x408: 0x38cc, 0x409: 0x3a5b, 0x40a: 0x2fc4, 0x40b: 0x32d0,
+ 0x40c: 0x2fce, 0x40d: 0x32da, 0x40e: 0x2fdd, 0x40f: 0x32e9, 0x410: 0x2fd3, 0x411: 0x32df,
+ 0x412: 0x2fd8, 0x413: 0x32e4, 0x414: 0x38ef, 0x415: 0x3a7e, 0x416: 0x38f6, 0x417: 0x3a85,
+ 0x418: 0x3019, 0x419: 0x3325, 0x41a: 0x301e, 0x41b: 0x332a, 0x41c: 0x3904, 0x41d: 0x3a93,
+ 0x41e: 0x3023, 0x41f: 0x332f, 0x420: 0x3032, 0x421: 0x333e, 0x422: 0x3050, 0x423: 0x335c,
+ 0x424: 0x305f, 0x425: 0x336b, 0x426: 0x3055, 0x427: 0x3361, 0x428: 0x3064, 0x429: 0x3370,
+ 0x42a: 0x3069, 0x42b: 0x3375, 0x42c: 0x30af, 0x42d: 0x33bb, 0x42e: 0x390b, 0x42f: 0x3a9a,
+ 0x430: 0x30b9, 0x431: 0x33ca, 0x432: 0x30c3, 0x433: 0x33d4, 0x434: 0x30cd, 0x435: 0x33de,
+ 0x436: 0x475a, 0x437: 0x47eb, 0x438: 0x3912, 0x439: 0x3aa1, 0x43a: 0x30e6, 0x43b: 0x33f7,
+ 0x43c: 0x30e1, 0x43d: 0x33f2, 0x43e: 0x30eb, 0x43f: 0x33fc,
+ // Block 0x11, offset 0x440
+ 0x440: 0x30f0, 0x441: 0x3401, 0x442: 0x30f5, 0x443: 0x3406, 0x444: 0x3109, 0x445: 0x341a,
+ 0x446: 0x3113, 0x447: 0x3424, 0x448: 0x3122, 0x449: 0x3433, 0x44a: 0x311d, 0x44b: 0x342e,
+ 0x44c: 0x3935, 0x44d: 0x3ac4, 0x44e: 0x3943, 0x44f: 0x3ad2, 0x450: 0x394a, 0x451: 0x3ad9,
+ 0x452: 0x3951, 0x453: 0x3ae0, 0x454: 0x314f, 0x455: 0x3460, 0x456: 0x3154, 0x457: 0x3465,
+ 0x458: 0x315e, 0x459: 0x346f, 0x45a: 0x4787, 0x45b: 0x4818, 0x45c: 0x3997, 0x45d: 0x3b26,
+ 0x45e: 0x3177, 0x45f: 0x3488, 0x460: 0x3181, 0x461: 0x3492, 0x462: 0x4796, 0x463: 0x4827,
+ 0x464: 0x399e, 0x465: 0x3b2d, 0x466: 0x39a5, 0x467: 0x3b34, 0x468: 0x39ac, 0x469: 0x3b3b,
+ 0x46a: 0x3190, 0x46b: 0x34a1, 0x46c: 0x319a, 0x46d: 0x34b0, 0x46e: 0x31ae, 0x46f: 0x34c4,
+ 0x470: 0x31a9, 0x471: 0x34bf, 0x472: 0x31ea, 0x473: 0x3500, 0x474: 0x31f9, 0x475: 0x350f,
+ 0x476: 0x31f4, 0x477: 0x350a, 0x478: 0x39b3, 0x479: 0x3b42, 0x47a: 0x39ba, 0x47b: 0x3b49,
+ 0x47c: 0x31fe, 0x47d: 0x3514, 0x47e: 0x3203, 0x47f: 0x3519,
+ // Block 0x12, offset 0x480
+ 0x480: 0x3208, 0x481: 0x351e, 0x482: 0x320d, 0x483: 0x3523, 0x484: 0x321c, 0x485: 0x3532,
+ 0x486: 0x3217, 0x487: 0x352d, 0x488: 0x3221, 0x489: 0x353c, 0x48a: 0x3226, 0x48b: 0x3541,
+ 0x48c: 0x322b, 0x48d: 0x3546, 0x48e: 0x3249, 0x48f: 0x3564, 0x490: 0x3262, 0x491: 0x3582,
+ 0x492: 0x3271, 0x493: 0x3591, 0x494: 0x3276, 0x495: 0x3596, 0x496: 0x337a, 0x497: 0x34a6,
+ 0x498: 0x3537, 0x499: 0x3573, 0x49b: 0x35d1,
+ 0x4a0: 0x4737, 0x4a1: 0x47c8, 0x4a2: 0x2f83, 0x4a3: 0x328f,
+ 0x4a4: 0x3878, 0x4a5: 0x3a07, 0x4a6: 0x3871, 0x4a7: 0x3a00, 0x4a8: 0x3886, 0x4a9: 0x3a15,
+ 0x4aa: 0x387f, 0x4ab: 0x3a0e, 0x4ac: 0x38be, 0x4ad: 0x3a4d, 0x4ae: 0x3894, 0x4af: 0x3a23,
+ 0x4b0: 0x388d, 0x4b1: 0x3a1c, 0x4b2: 0x38a2, 0x4b3: 0x3a31, 0x4b4: 0x389b, 0x4b5: 0x3a2a,
+ 0x4b6: 0x38c5, 0x4b7: 0x3a54, 0x4b8: 0x474b, 0x4b9: 0x47dc, 0x4ba: 0x3000, 0x4bb: 0x330c,
+ 0x4bc: 0x2fec, 0x4bd: 0x32f8, 0x4be: 0x38da, 0x4bf: 0x3a69,
+ // Block 0x13, offset 0x4c0
+ 0x4c0: 0x38d3, 0x4c1: 0x3a62, 0x4c2: 0x38e8, 0x4c3: 0x3a77, 0x4c4: 0x38e1, 0x4c5: 0x3a70,
+ 0x4c6: 0x38fd, 0x4c7: 0x3a8c, 0x4c8: 0x3091, 0x4c9: 0x339d, 0x4ca: 0x30a5, 0x4cb: 0x33b1,
+ 0x4cc: 0x477d, 0x4cd: 0x480e, 0x4ce: 0x3136, 0x4cf: 0x3447, 0x4d0: 0x3920, 0x4d1: 0x3aaf,
+ 0x4d2: 0x3919, 0x4d3: 0x3aa8, 0x4d4: 0x392e, 0x4d5: 0x3abd, 0x4d6: 0x3927, 0x4d7: 0x3ab6,
+ 0x4d8: 0x3989, 0x4d9: 0x3b18, 0x4da: 0x396d, 0x4db: 0x3afc, 0x4dc: 0x3966, 0x4dd: 0x3af5,
+ 0x4de: 0x397b, 0x4df: 0x3b0a, 0x4e0: 0x3974, 0x4e1: 0x3b03, 0x4e2: 0x3982, 0x4e3: 0x3b11,
+ 0x4e4: 0x31e5, 0x4e5: 0x34fb, 0x4e6: 0x31c7, 0x4e7: 0x34dd, 0x4e8: 0x39e4, 0x4e9: 0x3b73,
+ 0x4ea: 0x39dd, 0x4eb: 0x3b6c, 0x4ec: 0x39f2, 0x4ed: 0x3b81, 0x4ee: 0x39eb, 0x4ef: 0x3b7a,
+ 0x4f0: 0x39f9, 0x4f1: 0x3b88, 0x4f2: 0x3230, 0x4f3: 0x354b, 0x4f4: 0x3258, 0x4f5: 0x3578,
+ 0x4f6: 0x3253, 0x4f7: 0x356e, 0x4f8: 0x323f, 0x4f9: 0x355a,
+ // Block 0x14, offset 0x500
+ 0x500: 0x489a, 0x501: 0x48a0, 0x502: 0x49b4, 0x503: 0x49cc, 0x504: 0x49bc, 0x505: 0x49d4,
+ 0x506: 0x49c4, 0x507: 0x49dc, 0x508: 0x4840, 0x509: 0x4846, 0x50a: 0x4924, 0x50b: 0x493c,
+ 0x50c: 0x492c, 0x50d: 0x4944, 0x50e: 0x4934, 0x50f: 0x494c, 0x510: 0x48ac, 0x511: 0x48b2,
+ 0x512: 0x3db8, 0x513: 0x3dc8, 0x514: 0x3dc0, 0x515: 0x3dd0,
+ 0x518: 0x484c, 0x519: 0x4852, 0x51a: 0x3ce8, 0x51b: 0x3cf8, 0x51c: 0x3cf0, 0x51d: 0x3d00,
+ 0x520: 0x48c4, 0x521: 0x48ca, 0x522: 0x49e4, 0x523: 0x49fc,
+ 0x524: 0x49ec, 0x525: 0x4a04, 0x526: 0x49f4, 0x527: 0x4a0c, 0x528: 0x4858, 0x529: 0x485e,
+ 0x52a: 0x4954, 0x52b: 0x496c, 0x52c: 0x495c, 0x52d: 0x4974, 0x52e: 0x4964, 0x52f: 0x497c,
+ 0x530: 0x48dc, 0x531: 0x48e2, 0x532: 0x3e18, 0x533: 0x3e30, 0x534: 0x3e20, 0x535: 0x3e38,
+ 0x536: 0x3e28, 0x537: 0x3e40, 0x538: 0x4864, 0x539: 0x486a, 0x53a: 0x3d18, 0x53b: 0x3d30,
+ 0x53c: 0x3d20, 0x53d: 0x3d38, 0x53e: 0x3d28, 0x53f: 0x3d40,
+ // Block 0x15, offset 0x540
+ 0x540: 0x48e8, 0x541: 0x48ee, 0x542: 0x3e48, 0x543: 0x3e58, 0x544: 0x3e50, 0x545: 0x3e60,
+ 0x548: 0x4870, 0x549: 0x4876, 0x54a: 0x3d48, 0x54b: 0x3d58,
+ 0x54c: 0x3d50, 0x54d: 0x3d60, 0x550: 0x48fa, 0x551: 0x4900,
+ 0x552: 0x3e80, 0x553: 0x3e98, 0x554: 0x3e88, 0x555: 0x3ea0, 0x556: 0x3e90, 0x557: 0x3ea8,
+ 0x559: 0x487c, 0x55b: 0x3d68, 0x55d: 0x3d70,
+ 0x55f: 0x3d78, 0x560: 0x4912, 0x561: 0x4918, 0x562: 0x4a14, 0x563: 0x4a2c,
+ 0x564: 0x4a1c, 0x565: 0x4a34, 0x566: 0x4a24, 0x567: 0x4a3c, 0x568: 0x4882, 0x569: 0x4888,
+ 0x56a: 0x4984, 0x56b: 0x499c, 0x56c: 0x498c, 0x56d: 0x49a4, 0x56e: 0x4994, 0x56f: 0x49ac,
+ 0x570: 0x488e, 0x571: 0x43b4, 0x572: 0x3691, 0x573: 0x43ba, 0x574: 0x48b8, 0x575: 0x43c0,
+ 0x576: 0x36a3, 0x577: 0x43c6, 0x578: 0x36c1, 0x579: 0x43cc, 0x57a: 0x36d9, 0x57b: 0x43d2,
+ 0x57c: 0x4906, 0x57d: 0x43d8,
+ // Block 0x16, offset 0x580
+ 0x580: 0x3da0, 0x581: 0x3da8, 0x582: 0x4184, 0x583: 0x41a2, 0x584: 0x418e, 0x585: 0x41ac,
+ 0x586: 0x4198, 0x587: 0x41b6, 0x588: 0x3cd8, 0x589: 0x3ce0, 0x58a: 0x40d0, 0x58b: 0x40ee,
+ 0x58c: 0x40da, 0x58d: 0x40f8, 0x58e: 0x40e4, 0x58f: 0x4102, 0x590: 0x3de8, 0x591: 0x3df0,
+ 0x592: 0x41c0, 0x593: 0x41de, 0x594: 0x41ca, 0x595: 0x41e8, 0x596: 0x41d4, 0x597: 0x41f2,
+ 0x598: 0x3d08, 0x599: 0x3d10, 0x59a: 0x410c, 0x59b: 0x412a, 0x59c: 0x4116, 0x59d: 0x4134,
+ 0x59e: 0x4120, 0x59f: 0x413e, 0x5a0: 0x3ec0, 0x5a1: 0x3ec8, 0x5a2: 0x41fc, 0x5a3: 0x421a,
+ 0x5a4: 0x4206, 0x5a5: 0x4224, 0x5a6: 0x4210, 0x5a7: 0x422e, 0x5a8: 0x3d80, 0x5a9: 0x3d88,
+ 0x5aa: 0x4148, 0x5ab: 0x4166, 0x5ac: 0x4152, 0x5ad: 0x4170, 0x5ae: 0x415c, 0x5af: 0x417a,
+ 0x5b0: 0x3685, 0x5b1: 0x367f, 0x5b2: 0x3d90, 0x5b3: 0x368b, 0x5b4: 0x3d98,
+ 0x5b6: 0x48a6, 0x5b7: 0x3db0, 0x5b8: 0x35f5, 0x5b9: 0x35ef, 0x5ba: 0x35e3, 0x5bb: 0x4384,
+ 0x5bc: 0x35fb, 0x5bd: 0x8100, 0x5be: 0x01d3, 0x5bf: 0xa100,
+ // Block 0x17, offset 0x5c0
+ 0x5c0: 0x8100, 0x5c1: 0x35a7, 0x5c2: 0x3dd8, 0x5c3: 0x369d, 0x5c4: 0x3de0,
+ 0x5c6: 0x48d0, 0x5c7: 0x3df8, 0x5c8: 0x3601, 0x5c9: 0x438a, 0x5ca: 0x360d, 0x5cb: 0x4390,
+ 0x5cc: 0x3619, 0x5cd: 0x3b8f, 0x5ce: 0x3b96, 0x5cf: 0x3b9d, 0x5d0: 0x36b5, 0x5d1: 0x36af,
+ 0x5d2: 0x3e00, 0x5d3: 0x457a, 0x5d6: 0x36bb, 0x5d7: 0x3e10,
+ 0x5d8: 0x3631, 0x5d9: 0x362b, 0x5da: 0x361f, 0x5db: 0x4396, 0x5dd: 0x3ba4,
+ 0x5de: 0x3bab, 0x5df: 0x3bb2, 0x5e0: 0x36eb, 0x5e1: 0x36e5, 0x5e2: 0x3e68, 0x5e3: 0x4582,
+ 0x5e4: 0x36cd, 0x5e5: 0x36d3, 0x5e6: 0x36f1, 0x5e7: 0x3e78, 0x5e8: 0x3661, 0x5e9: 0x365b,
+ 0x5ea: 0x364f, 0x5eb: 0x43a2, 0x5ec: 0x3649, 0x5ed: 0x359b, 0x5ee: 0x437e, 0x5ef: 0x0081,
+ 0x5f2: 0x3eb0, 0x5f3: 0x36f7, 0x5f4: 0x3eb8,
+ 0x5f6: 0x491e, 0x5f7: 0x3ed0, 0x5f8: 0x363d, 0x5f9: 0x439c, 0x5fa: 0x366d, 0x5fb: 0x43ae,
+ 0x5fc: 0x3679, 0x5fd: 0x4256, 0x5fe: 0xa100,
+ // Block 0x18, offset 0x600
+ 0x601: 0x3c06, 0x603: 0xa000, 0x604: 0x3c0d, 0x605: 0xa000,
+ 0x607: 0x3c14, 0x608: 0xa000, 0x609: 0x3c1b,
+ 0x60d: 0xa000,
+ 0x620: 0x2f65, 0x621: 0xa000, 0x622: 0x3c29,
+ 0x624: 0xa000, 0x625: 0xa000,
+ 0x62d: 0x3c22, 0x62e: 0x2f60, 0x62f: 0x2f6a,
+ 0x630: 0x3c30, 0x631: 0x3c37, 0x632: 0xa000, 0x633: 0xa000, 0x634: 0x3c3e, 0x635: 0x3c45,
+ 0x636: 0xa000, 0x637: 0xa000, 0x638: 0x3c4c, 0x639: 0x3c53, 0x63a: 0xa000, 0x63b: 0xa000,
+ 0x63c: 0xa000, 0x63d: 0xa000,
+ // Block 0x19, offset 0x640
+ 0x640: 0x3c5a, 0x641: 0x3c61, 0x642: 0xa000, 0x643: 0xa000, 0x644: 0x3c76, 0x645: 0x3c7d,
+ 0x646: 0xa000, 0x647: 0xa000, 0x648: 0x3c84, 0x649: 0x3c8b,
+ 0x651: 0xa000,
+ 0x652: 0xa000,
+ 0x662: 0xa000,
+ 0x668: 0xa000, 0x669: 0xa000,
+ 0x66b: 0xa000, 0x66c: 0x3ca0, 0x66d: 0x3ca7, 0x66e: 0x3cae, 0x66f: 0x3cb5,
+ 0x672: 0xa000, 0x673: 0xa000, 0x674: 0xa000, 0x675: 0xa000,
+ // Block 0x1a, offset 0x680
+ 0x686: 0xa000, 0x68b: 0xa000,
+ 0x68c: 0x3f08, 0x68d: 0xa000, 0x68e: 0x3f10, 0x68f: 0xa000, 0x690: 0x3f18, 0x691: 0xa000,
+ 0x692: 0x3f20, 0x693: 0xa000, 0x694: 0x3f28, 0x695: 0xa000, 0x696: 0x3f30, 0x697: 0xa000,
+ 0x698: 0x3f38, 0x699: 0xa000, 0x69a: 0x3f40, 0x69b: 0xa000, 0x69c: 0x3f48, 0x69d: 0xa000,
+ 0x69e: 0x3f50, 0x69f: 0xa000, 0x6a0: 0x3f58, 0x6a1: 0xa000, 0x6a2: 0x3f60,
+ 0x6a4: 0xa000, 0x6a5: 0x3f68, 0x6a6: 0xa000, 0x6a7: 0x3f70, 0x6a8: 0xa000, 0x6a9: 0x3f78,
+ 0x6af: 0xa000,
+ 0x6b0: 0x3f80, 0x6b1: 0x3f88, 0x6b2: 0xa000, 0x6b3: 0x3f90, 0x6b4: 0x3f98, 0x6b5: 0xa000,
+ 0x6b6: 0x3fa0, 0x6b7: 0x3fa8, 0x6b8: 0xa000, 0x6b9: 0x3fb0, 0x6ba: 0x3fb8, 0x6bb: 0xa000,
+ 0x6bc: 0x3fc0, 0x6bd: 0x3fc8,
+ // Block 0x1b, offset 0x6c0
+ 0x6d4: 0x3f00,
+ 0x6d9: 0x9903, 0x6da: 0x9903, 0x6db: 0x8100, 0x6dc: 0x8100, 0x6dd: 0xa000,
+ 0x6de: 0x3fd0,
+ 0x6e6: 0xa000,
+ 0x6eb: 0xa000, 0x6ec: 0x3fe0, 0x6ed: 0xa000, 0x6ee: 0x3fe8, 0x6ef: 0xa000,
+ 0x6f0: 0x3ff0, 0x6f1: 0xa000, 0x6f2: 0x3ff8, 0x6f3: 0xa000, 0x6f4: 0x4000, 0x6f5: 0xa000,
+ 0x6f6: 0x4008, 0x6f7: 0xa000, 0x6f8: 0x4010, 0x6f9: 0xa000, 0x6fa: 0x4018, 0x6fb: 0xa000,
+ 0x6fc: 0x4020, 0x6fd: 0xa000, 0x6fe: 0x4028, 0x6ff: 0xa000,
+ // Block 0x1c, offset 0x700
+ 0x700: 0x4030, 0x701: 0xa000, 0x702: 0x4038, 0x704: 0xa000, 0x705: 0x4040,
+ 0x706: 0xa000, 0x707: 0x4048, 0x708: 0xa000, 0x709: 0x4050,
+ 0x70f: 0xa000, 0x710: 0x4058, 0x711: 0x4060,
+ 0x712: 0xa000, 0x713: 0x4068, 0x714: 0x4070, 0x715: 0xa000, 0x716: 0x4078, 0x717: 0x4080,
+ 0x718: 0xa000, 0x719: 0x4088, 0x71a: 0x4090, 0x71b: 0xa000, 0x71c: 0x4098, 0x71d: 0x40a0,
+ 0x72f: 0xa000,
+ 0x730: 0xa000, 0x731: 0xa000, 0x732: 0xa000, 0x734: 0x3fd8,
+ 0x737: 0x40a8, 0x738: 0x40b0, 0x739: 0x40b8, 0x73a: 0x40c0,
+ 0x73d: 0xa000, 0x73e: 0x40c8,
+ // Block 0x1d, offset 0x740
+ 0x740: 0x1377, 0x741: 0x0cfb, 0x742: 0x13d3, 0x743: 0x139f, 0x744: 0x0e57, 0x745: 0x06eb,
+ 0x746: 0x08df, 0x747: 0x162b, 0x748: 0x162b, 0x749: 0x0a0b, 0x74a: 0x145f, 0x74b: 0x0943,
+ 0x74c: 0x0a07, 0x74d: 0x0bef, 0x74e: 0x0fcf, 0x74f: 0x115f, 0x750: 0x1297, 0x751: 0x12d3,
+ 0x752: 0x1307, 0x753: 0x141b, 0x754: 0x0d73, 0x755: 0x0dff, 0x756: 0x0eab, 0x757: 0x0f43,
+ 0x758: 0x125f, 0x759: 0x1447, 0x75a: 0x1573, 0x75b: 0x070f, 0x75c: 0x08b3, 0x75d: 0x0d87,
+ 0x75e: 0x0ecf, 0x75f: 0x1293, 0x760: 0x15c3, 0x761: 0x0ab3, 0x762: 0x0e77, 0x763: 0x1283,
+ 0x764: 0x1317, 0x765: 0x0c23, 0x766: 0x11bb, 0x767: 0x12df, 0x768: 0x0b1f, 0x769: 0x0d0f,
+ 0x76a: 0x0e17, 0x76b: 0x0f1b, 0x76c: 0x1427, 0x76d: 0x074f, 0x76e: 0x07e7, 0x76f: 0x0853,
+ 0x770: 0x0c8b, 0x771: 0x0d7f, 0x772: 0x0ecb, 0x773: 0x0fef, 0x774: 0x1177, 0x775: 0x128b,
+ 0x776: 0x12a3, 0x777: 0x13c7, 0x778: 0x14ef, 0x779: 0x15a3, 0x77a: 0x15bf, 0x77b: 0x102b,
+ 0x77c: 0x106b, 0x77d: 0x1123, 0x77e: 0x1243, 0x77f: 0x147b,
+ // Block 0x1e, offset 0x780
+ 0x780: 0x15cb, 0x781: 0x134b, 0x782: 0x09c7, 0x783: 0x0b3b, 0x784: 0x10db, 0x785: 0x119b,
+ 0x786: 0x0eff, 0x787: 0x1033, 0x788: 0x1397, 0x789: 0x14e7, 0x78a: 0x09c3, 0x78b: 0x0a8f,
+ 0x78c: 0x0d77, 0x78d: 0x0e2b, 0x78e: 0x0e5f, 0x78f: 0x1113, 0x790: 0x113b, 0x791: 0x14a7,
+ 0x792: 0x084f, 0x793: 0x11a7, 0x794: 0x07f3, 0x795: 0x07ef, 0x796: 0x1097, 0x797: 0x1127,
+ 0x798: 0x125b, 0x799: 0x14af, 0x79a: 0x1367, 0x79b: 0x0c27, 0x79c: 0x0d73, 0x79d: 0x1357,
+ 0x79e: 0x06f7, 0x79f: 0x0a63, 0x7a0: 0x0b93, 0x7a1: 0x0f2f, 0x7a2: 0x0faf, 0x7a3: 0x0873,
+ 0x7a4: 0x103b, 0x7a5: 0x075f, 0x7a6: 0x0b77, 0x7a7: 0x06d7, 0x7a8: 0x0deb, 0x7a9: 0x0ca3,
+ 0x7aa: 0x110f, 0x7ab: 0x08c7, 0x7ac: 0x09b3, 0x7ad: 0x0ffb, 0x7ae: 0x1263, 0x7af: 0x133b,
+ 0x7b0: 0x0db7, 0x7b1: 0x13f7, 0x7b2: 0x0de3, 0x7b3: 0x0c37, 0x7b4: 0x121b, 0x7b5: 0x0c57,
+ 0x7b6: 0x0fab, 0x7b7: 0x072b, 0x7b8: 0x07a7, 0x7b9: 0x07eb, 0x7ba: 0x0d53, 0x7bb: 0x10fb,
+ 0x7bc: 0x11f3, 0x7bd: 0x1347, 0x7be: 0x145b, 0x7bf: 0x085b,
+ // Block 0x1f, offset 0x7c0
+ 0x7c0: 0x090f, 0x7c1: 0x0a17, 0x7c2: 0x0b2f, 0x7c3: 0x0cbf, 0x7c4: 0x0e7b, 0x7c5: 0x103f,
+ 0x7c6: 0x1497, 0x7c7: 0x157b, 0x7c8: 0x15cf, 0x7c9: 0x15e7, 0x7ca: 0x0837, 0x7cb: 0x0cf3,
+ 0x7cc: 0x0da3, 0x7cd: 0x13eb, 0x7ce: 0x0afb, 0x7cf: 0x0bd7, 0x7d0: 0x0bf3, 0x7d1: 0x0c83,
+ 0x7d2: 0x0e6b, 0x7d3: 0x0eb7, 0x7d4: 0x0f67, 0x7d5: 0x108b, 0x7d6: 0x112f, 0x7d7: 0x1193,
+ 0x7d8: 0x13db, 0x7d9: 0x126b, 0x7da: 0x1403, 0x7db: 0x147f, 0x7dc: 0x080f, 0x7dd: 0x083b,
+ 0x7de: 0x0923, 0x7df: 0x0ea7, 0x7e0: 0x12f3, 0x7e1: 0x133b, 0x7e2: 0x0b1b, 0x7e3: 0x0b8b,
+ 0x7e4: 0x0c4f, 0x7e5: 0x0daf, 0x7e6: 0x10d7, 0x7e7: 0x0f23, 0x7e8: 0x073b, 0x7e9: 0x097f,
+ 0x7ea: 0x0a63, 0x7eb: 0x0ac7, 0x7ec: 0x0b97, 0x7ed: 0x0f3f, 0x7ee: 0x0f5b, 0x7ef: 0x116b,
+ 0x7f0: 0x118b, 0x7f1: 0x1463, 0x7f2: 0x14e3, 0x7f3: 0x14f3, 0x7f4: 0x152f, 0x7f5: 0x0753,
+ 0x7f6: 0x107f, 0x7f7: 0x144f, 0x7f8: 0x14cb, 0x7f9: 0x0baf, 0x7fa: 0x0717, 0x7fb: 0x0777,
+ 0x7fc: 0x0a67, 0x7fd: 0x0a87, 0x7fe: 0x0caf, 0x7ff: 0x0d73,
+ // Block 0x20, offset 0x800
+ 0x800: 0x0ec3, 0x801: 0x0fcb, 0x802: 0x1277, 0x803: 0x1417, 0x804: 0x1623, 0x805: 0x0ce3,
+ 0x806: 0x14a3, 0x807: 0x0833, 0x808: 0x0d2f, 0x809: 0x0d3b, 0x80a: 0x0e0f, 0x80b: 0x0e47,
+ 0x80c: 0x0f4b, 0x80d: 0x0fa7, 0x80e: 0x1027, 0x80f: 0x110b, 0x810: 0x153b, 0x811: 0x07af,
+ 0x812: 0x0c03, 0x813: 0x14b3, 0x814: 0x0767, 0x815: 0x0aab, 0x816: 0x0e2f, 0x817: 0x13df,
+ 0x818: 0x0b67, 0x819: 0x0bb7, 0x81a: 0x0d43, 0x81b: 0x0f2f, 0x81c: 0x14bb, 0x81d: 0x0817,
+ 0x81e: 0x08ff, 0x81f: 0x0a97, 0x820: 0x0cd3, 0x821: 0x0d1f, 0x822: 0x0d5f, 0x823: 0x0df3,
+ 0x824: 0x0f47, 0x825: 0x0fbb, 0x826: 0x1157, 0x827: 0x12f7, 0x828: 0x1303, 0x829: 0x1457,
+ 0x82a: 0x14d7, 0x82b: 0x0883, 0x82c: 0x0e4b, 0x82d: 0x0903, 0x82e: 0x0ec7, 0x82f: 0x0f6b,
+ 0x830: 0x1287, 0x831: 0x14bf, 0x832: 0x15ab, 0x833: 0x15d3, 0x834: 0x0d37, 0x835: 0x0e27,
+ 0x836: 0x11c3, 0x837: 0x10b7, 0x838: 0x10c3, 0x839: 0x10e7, 0x83a: 0x0f17, 0x83b: 0x0e9f,
+ 0x83c: 0x1363, 0x83d: 0x0733, 0x83e: 0x122b, 0x83f: 0x081b,
+ // Block 0x21, offset 0x840
+ 0x840: 0x080b, 0x841: 0x0b0b, 0x842: 0x0c2b, 0x843: 0x10f3, 0x844: 0x0a53, 0x845: 0x0e03,
+ 0x846: 0x0cef, 0x847: 0x13e7, 0x848: 0x12e7, 0x849: 0x14ab, 0x84a: 0x1323, 0x84b: 0x0b27,
+ 0x84c: 0x0787, 0x84d: 0x095b, 0x850: 0x09af,
+ 0x852: 0x0cdf, 0x855: 0x07f7, 0x856: 0x0f1f, 0x857: 0x0fe3,
+ 0x858: 0x1047, 0x859: 0x1063, 0x85a: 0x1067, 0x85b: 0x107b, 0x85c: 0x14fb, 0x85d: 0x10eb,
+ 0x85e: 0x116f, 0x860: 0x128f, 0x862: 0x1353,
+ 0x865: 0x1407, 0x866: 0x1433,
+ 0x86a: 0x154f, 0x86b: 0x1553, 0x86c: 0x1557, 0x86d: 0x15bb, 0x86e: 0x142b, 0x86f: 0x14c7,
+ 0x870: 0x0757, 0x871: 0x077b, 0x872: 0x078f, 0x873: 0x084b, 0x874: 0x0857, 0x875: 0x0897,
+ 0x876: 0x094b, 0x877: 0x0967, 0x878: 0x096f, 0x879: 0x09ab, 0x87a: 0x09b7, 0x87b: 0x0a93,
+ 0x87c: 0x0a9b, 0x87d: 0x0ba3, 0x87e: 0x0bcb, 0x87f: 0x0bd3,
+ // Block 0x22, offset 0x880
+ 0x880: 0x0beb, 0x881: 0x0c97, 0x882: 0x0cc7, 0x883: 0x0ce7, 0x884: 0x0d57, 0x885: 0x0e1b,
+ 0x886: 0x0e37, 0x887: 0x0e67, 0x888: 0x0ebb, 0x889: 0x0edb, 0x88a: 0x0f4f, 0x88b: 0x102f,
+ 0x88c: 0x104b, 0x88d: 0x1053, 0x88e: 0x104f, 0x88f: 0x1057, 0x890: 0x105b, 0x891: 0x105f,
+ 0x892: 0x1073, 0x893: 0x1077, 0x894: 0x109b, 0x895: 0x10af, 0x896: 0x10cb, 0x897: 0x112f,
+ 0x898: 0x1137, 0x899: 0x113f, 0x89a: 0x1153, 0x89b: 0x117b, 0x89c: 0x11cb, 0x89d: 0x11ff,
+ 0x89e: 0x11ff, 0x89f: 0x1267, 0x8a0: 0x130f, 0x8a1: 0x1327, 0x8a2: 0x135b, 0x8a3: 0x135f,
+ 0x8a4: 0x13a3, 0x8a5: 0x13a7, 0x8a6: 0x13ff, 0x8a7: 0x1407, 0x8a8: 0x14db, 0x8a9: 0x151f,
+ 0x8aa: 0x1537, 0x8ab: 0x0b9b, 0x8ac: 0x171e, 0x8ad: 0x11e3,
+ 0x8b0: 0x06df, 0x8b1: 0x07e3, 0x8b2: 0x07a3, 0x8b3: 0x074b, 0x8b4: 0x078b, 0x8b5: 0x07b7,
+ 0x8b6: 0x0847, 0x8b7: 0x0863, 0x8b8: 0x094b, 0x8b9: 0x0937, 0x8ba: 0x0947, 0x8bb: 0x0963,
+ 0x8bc: 0x09af, 0x8bd: 0x09bf, 0x8be: 0x0a03, 0x8bf: 0x0a0f,
+ // Block 0x23, offset 0x8c0
+ 0x8c0: 0x0a2b, 0x8c1: 0x0a3b, 0x8c2: 0x0b23, 0x8c3: 0x0b2b, 0x8c4: 0x0b5b, 0x8c5: 0x0b7b,
+ 0x8c6: 0x0bab, 0x8c7: 0x0bc3, 0x8c8: 0x0bb3, 0x8c9: 0x0bd3, 0x8ca: 0x0bc7, 0x8cb: 0x0beb,
+ 0x8cc: 0x0c07, 0x8cd: 0x0c5f, 0x8ce: 0x0c6b, 0x8cf: 0x0c73, 0x8d0: 0x0c9b, 0x8d1: 0x0cdf,
+ 0x8d2: 0x0d0f, 0x8d3: 0x0d13, 0x8d4: 0x0d27, 0x8d5: 0x0da7, 0x8d6: 0x0db7, 0x8d7: 0x0e0f,
+ 0x8d8: 0x0e5b, 0x8d9: 0x0e53, 0x8da: 0x0e67, 0x8db: 0x0e83, 0x8dc: 0x0ebb, 0x8dd: 0x1013,
+ 0x8de: 0x0edf, 0x8df: 0x0f13, 0x8e0: 0x0f1f, 0x8e1: 0x0f5f, 0x8e2: 0x0f7b, 0x8e3: 0x0f9f,
+ 0x8e4: 0x0fc3, 0x8e5: 0x0fc7, 0x8e6: 0x0fe3, 0x8e7: 0x0fe7, 0x8e8: 0x0ff7, 0x8e9: 0x100b,
+ 0x8ea: 0x1007, 0x8eb: 0x1037, 0x8ec: 0x10b3, 0x8ed: 0x10cb, 0x8ee: 0x10e3, 0x8ef: 0x111b,
+ 0x8f0: 0x112f, 0x8f1: 0x114b, 0x8f2: 0x117b, 0x8f3: 0x122f, 0x8f4: 0x1257, 0x8f5: 0x12cb,
+ 0x8f6: 0x1313, 0x8f7: 0x131f, 0x8f8: 0x1327, 0x8f9: 0x133f, 0x8fa: 0x1353, 0x8fb: 0x1343,
+ 0x8fc: 0x135b, 0x8fd: 0x1357, 0x8fe: 0x134f, 0x8ff: 0x135f,
+ // Block 0x24, offset 0x900
+ 0x900: 0x136b, 0x901: 0x13a7, 0x902: 0x13e3, 0x903: 0x1413, 0x904: 0x144b, 0x905: 0x146b,
+ 0x906: 0x14b7, 0x907: 0x14db, 0x908: 0x14fb, 0x909: 0x150f, 0x90a: 0x151f, 0x90b: 0x152b,
+ 0x90c: 0x1537, 0x90d: 0x158b, 0x90e: 0x162b, 0x90f: 0x16b5, 0x910: 0x16b0, 0x911: 0x16e2,
+ 0x912: 0x0607, 0x913: 0x062f, 0x914: 0x0633, 0x915: 0x1764, 0x916: 0x1791, 0x917: 0x1809,
+ 0x918: 0x1617, 0x919: 0x1627,
+ // Block 0x25, offset 0x940
+ 0x940: 0x06fb, 0x941: 0x06f3, 0x942: 0x0703, 0x943: 0x1647, 0x944: 0x0747, 0x945: 0x0757,
+ 0x946: 0x075b, 0x947: 0x0763, 0x948: 0x076b, 0x949: 0x076f, 0x94a: 0x077b, 0x94b: 0x0773,
+ 0x94c: 0x05b3, 0x94d: 0x165b, 0x94e: 0x078f, 0x94f: 0x0793, 0x950: 0x0797, 0x951: 0x07b3,
+ 0x952: 0x164c, 0x953: 0x05b7, 0x954: 0x079f, 0x955: 0x07bf, 0x956: 0x1656, 0x957: 0x07cf,
+ 0x958: 0x07d7, 0x959: 0x0737, 0x95a: 0x07df, 0x95b: 0x07e3, 0x95c: 0x1831, 0x95d: 0x07ff,
+ 0x95e: 0x0807, 0x95f: 0x05bf, 0x960: 0x081f, 0x961: 0x0823, 0x962: 0x082b, 0x963: 0x082f,
+ 0x964: 0x05c3, 0x965: 0x0847, 0x966: 0x084b, 0x967: 0x0857, 0x968: 0x0863, 0x969: 0x0867,
+ 0x96a: 0x086b, 0x96b: 0x0873, 0x96c: 0x0893, 0x96d: 0x0897, 0x96e: 0x089f, 0x96f: 0x08af,
+ 0x970: 0x08b7, 0x971: 0x08bb, 0x972: 0x08bb, 0x973: 0x08bb, 0x974: 0x166a, 0x975: 0x0e93,
+ 0x976: 0x08cf, 0x977: 0x08d7, 0x978: 0x166f, 0x979: 0x08e3, 0x97a: 0x08eb, 0x97b: 0x08f3,
+ 0x97c: 0x091b, 0x97d: 0x0907, 0x97e: 0x0913, 0x97f: 0x0917,
+ // Block 0x26, offset 0x980
+ 0x980: 0x091f, 0x981: 0x0927, 0x982: 0x092b, 0x983: 0x0933, 0x984: 0x093b, 0x985: 0x093f,
+ 0x986: 0x093f, 0x987: 0x0947, 0x988: 0x094f, 0x989: 0x0953, 0x98a: 0x095f, 0x98b: 0x0983,
+ 0x98c: 0x0967, 0x98d: 0x0987, 0x98e: 0x096b, 0x98f: 0x0973, 0x990: 0x080b, 0x991: 0x09cf,
+ 0x992: 0x0997, 0x993: 0x099b, 0x994: 0x099f, 0x995: 0x0993, 0x996: 0x09a7, 0x997: 0x09a3,
+ 0x998: 0x09bb, 0x999: 0x1674, 0x99a: 0x09d7, 0x99b: 0x09db, 0x99c: 0x09e3, 0x99d: 0x09ef,
+ 0x99e: 0x09f7, 0x99f: 0x0a13, 0x9a0: 0x1679, 0x9a1: 0x167e, 0x9a2: 0x0a1f, 0x9a3: 0x0a23,
+ 0x9a4: 0x0a27, 0x9a5: 0x0a1b, 0x9a6: 0x0a2f, 0x9a7: 0x05c7, 0x9a8: 0x05cb, 0x9a9: 0x0a37,
+ 0x9aa: 0x0a3f, 0x9ab: 0x0a3f, 0x9ac: 0x1683, 0x9ad: 0x0a5b, 0x9ae: 0x0a5f, 0x9af: 0x0a63,
+ 0x9b0: 0x0a6b, 0x9b1: 0x1688, 0x9b2: 0x0a73, 0x9b3: 0x0a77, 0x9b4: 0x0b4f, 0x9b5: 0x0a7f,
+ 0x9b6: 0x05cf, 0x9b7: 0x0a8b, 0x9b8: 0x0a9b, 0x9b9: 0x0aa7, 0x9ba: 0x0aa3, 0x9bb: 0x1692,
+ 0x9bc: 0x0aaf, 0x9bd: 0x1697, 0x9be: 0x0abb, 0x9bf: 0x0ab7,
+ // Block 0x27, offset 0x9c0
+ 0x9c0: 0x0abf, 0x9c1: 0x0acf, 0x9c2: 0x0ad3, 0x9c3: 0x05d3, 0x9c4: 0x0ae3, 0x9c5: 0x0aeb,
+ 0x9c6: 0x0aef, 0x9c7: 0x0af3, 0x9c8: 0x05d7, 0x9c9: 0x169c, 0x9ca: 0x05db, 0x9cb: 0x0b0f,
+ 0x9cc: 0x0b13, 0x9cd: 0x0b17, 0x9ce: 0x0b1f, 0x9cf: 0x1863, 0x9d0: 0x0b37, 0x9d1: 0x16a6,
+ 0x9d2: 0x16a6, 0x9d3: 0x11d7, 0x9d4: 0x0b47, 0x9d5: 0x0b47, 0x9d6: 0x05df, 0x9d7: 0x16c9,
+ 0x9d8: 0x179b, 0x9d9: 0x0b57, 0x9da: 0x0b5f, 0x9db: 0x05e3, 0x9dc: 0x0b73, 0x9dd: 0x0b83,
+ 0x9de: 0x0b87, 0x9df: 0x0b8f, 0x9e0: 0x0b9f, 0x9e1: 0x05eb, 0x9e2: 0x05e7, 0x9e3: 0x0ba3,
+ 0x9e4: 0x16ab, 0x9e5: 0x0ba7, 0x9e6: 0x0bbb, 0x9e7: 0x0bbf, 0x9e8: 0x0bc3, 0x9e9: 0x0bbf,
+ 0x9ea: 0x0bcf, 0x9eb: 0x0bd3, 0x9ec: 0x0be3, 0x9ed: 0x0bdb, 0x9ee: 0x0bdf, 0x9ef: 0x0be7,
+ 0x9f0: 0x0beb, 0x9f1: 0x0bef, 0x9f2: 0x0bfb, 0x9f3: 0x0bff, 0x9f4: 0x0c17, 0x9f5: 0x0c1f,
+ 0x9f6: 0x0c2f, 0x9f7: 0x0c43, 0x9f8: 0x16ba, 0x9f9: 0x0c3f, 0x9fa: 0x0c33, 0x9fb: 0x0c4b,
+ 0x9fc: 0x0c53, 0x9fd: 0x0c67, 0x9fe: 0x16bf, 0x9ff: 0x0c6f,
+ // Block 0x28, offset 0xa00
+ 0xa00: 0x0c63, 0xa01: 0x0c5b, 0xa02: 0x05ef, 0xa03: 0x0c77, 0xa04: 0x0c7f, 0xa05: 0x0c87,
+ 0xa06: 0x0c7b, 0xa07: 0x05f3, 0xa08: 0x0c97, 0xa09: 0x0c9f, 0xa0a: 0x16c4, 0xa0b: 0x0ccb,
+ 0xa0c: 0x0cff, 0xa0d: 0x0cdb, 0xa0e: 0x05ff, 0xa0f: 0x0ce7, 0xa10: 0x05fb, 0xa11: 0x05f7,
+ 0xa12: 0x07c3, 0xa13: 0x07c7, 0xa14: 0x0d03, 0xa15: 0x0ceb, 0xa16: 0x11ab, 0xa17: 0x0663,
+ 0xa18: 0x0d0f, 0xa19: 0x0d13, 0xa1a: 0x0d17, 0xa1b: 0x0d2b, 0xa1c: 0x0d23, 0xa1d: 0x16dd,
+ 0xa1e: 0x0603, 0xa1f: 0x0d3f, 0xa20: 0x0d33, 0xa21: 0x0d4f, 0xa22: 0x0d57, 0xa23: 0x16e7,
+ 0xa24: 0x0d5b, 0xa25: 0x0d47, 0xa26: 0x0d63, 0xa27: 0x0607, 0xa28: 0x0d67, 0xa29: 0x0d6b,
+ 0xa2a: 0x0d6f, 0xa2b: 0x0d7b, 0xa2c: 0x16ec, 0xa2d: 0x0d83, 0xa2e: 0x060b, 0xa2f: 0x0d8f,
+ 0xa30: 0x16f1, 0xa31: 0x0d93, 0xa32: 0x060f, 0xa33: 0x0d9f, 0xa34: 0x0dab, 0xa35: 0x0db7,
+ 0xa36: 0x0dbb, 0xa37: 0x16f6, 0xa38: 0x168d, 0xa39: 0x16fb, 0xa3a: 0x0ddb, 0xa3b: 0x1700,
+ 0xa3c: 0x0de7, 0xa3d: 0x0def, 0xa3e: 0x0ddf, 0xa3f: 0x0dfb,
+ // Block 0x29, offset 0xa40
+ 0xa40: 0x0e0b, 0xa41: 0x0e1b, 0xa42: 0x0e0f, 0xa43: 0x0e13, 0xa44: 0x0e1f, 0xa45: 0x0e23,
+ 0xa46: 0x1705, 0xa47: 0x0e07, 0xa48: 0x0e3b, 0xa49: 0x0e3f, 0xa4a: 0x0613, 0xa4b: 0x0e53,
+ 0xa4c: 0x0e4f, 0xa4d: 0x170a, 0xa4e: 0x0e33, 0xa4f: 0x0e6f, 0xa50: 0x170f, 0xa51: 0x1714,
+ 0xa52: 0x0e73, 0xa53: 0x0e87, 0xa54: 0x0e83, 0xa55: 0x0e7f, 0xa56: 0x0617, 0xa57: 0x0e8b,
+ 0xa58: 0x0e9b, 0xa59: 0x0e97, 0xa5a: 0x0ea3, 0xa5b: 0x1651, 0xa5c: 0x0eb3, 0xa5d: 0x1719,
+ 0xa5e: 0x0ebf, 0xa5f: 0x1723, 0xa60: 0x0ed3, 0xa61: 0x0edf, 0xa62: 0x0ef3, 0xa63: 0x1728,
+ 0xa64: 0x0f07, 0xa65: 0x0f0b, 0xa66: 0x172d, 0xa67: 0x1732, 0xa68: 0x0f27, 0xa69: 0x0f37,
+ 0xa6a: 0x061b, 0xa6b: 0x0f3b, 0xa6c: 0x061f, 0xa6d: 0x061f, 0xa6e: 0x0f53, 0xa6f: 0x0f57,
+ 0xa70: 0x0f5f, 0xa71: 0x0f63, 0xa72: 0x0f6f, 0xa73: 0x0623, 0xa74: 0x0f87, 0xa75: 0x1737,
+ 0xa76: 0x0fa3, 0xa77: 0x173c, 0xa78: 0x0faf, 0xa79: 0x16a1, 0xa7a: 0x0fbf, 0xa7b: 0x1741,
+ 0xa7c: 0x1746, 0xa7d: 0x174b, 0xa7e: 0x0627, 0xa7f: 0x062b,
+ // Block 0x2a, offset 0xa80
+ 0xa80: 0x0ff7, 0xa81: 0x1755, 0xa82: 0x1750, 0xa83: 0x175a, 0xa84: 0x175f, 0xa85: 0x0fff,
+ 0xa86: 0x1003, 0xa87: 0x1003, 0xa88: 0x100b, 0xa89: 0x0633, 0xa8a: 0x100f, 0xa8b: 0x0637,
+ 0xa8c: 0x063b, 0xa8d: 0x1769, 0xa8e: 0x1023, 0xa8f: 0x102b, 0xa90: 0x1037, 0xa91: 0x063f,
+ 0xa92: 0x176e, 0xa93: 0x105b, 0xa94: 0x1773, 0xa95: 0x1778, 0xa96: 0x107b, 0xa97: 0x1093,
+ 0xa98: 0x0643, 0xa99: 0x109b, 0xa9a: 0x109f, 0xa9b: 0x10a3, 0xa9c: 0x177d, 0xa9d: 0x1782,
+ 0xa9e: 0x1782, 0xa9f: 0x10bb, 0xaa0: 0x0647, 0xaa1: 0x1787, 0xaa2: 0x10cf, 0xaa3: 0x10d3,
+ 0xaa4: 0x064b, 0xaa5: 0x178c, 0xaa6: 0x10ef, 0xaa7: 0x064f, 0xaa8: 0x10ff, 0xaa9: 0x10f7,
+ 0xaaa: 0x1107, 0xaab: 0x1796, 0xaac: 0x111f, 0xaad: 0x0653, 0xaae: 0x112b, 0xaaf: 0x1133,
+ 0xab0: 0x1143, 0xab1: 0x0657, 0xab2: 0x17a0, 0xab3: 0x17a5, 0xab4: 0x065b, 0xab5: 0x17aa,
+ 0xab6: 0x115b, 0xab7: 0x17af, 0xab8: 0x1167, 0xab9: 0x1173, 0xaba: 0x117b, 0xabb: 0x17b4,
+ 0xabc: 0x17b9, 0xabd: 0x118f, 0xabe: 0x17be, 0xabf: 0x1197,
+ // Block 0x2b, offset 0xac0
+ 0xac0: 0x16ce, 0xac1: 0x065f, 0xac2: 0x11af, 0xac3: 0x11b3, 0xac4: 0x0667, 0xac5: 0x11b7,
+ 0xac6: 0x0a33, 0xac7: 0x17c3, 0xac8: 0x17c8, 0xac9: 0x16d3, 0xaca: 0x16d8, 0xacb: 0x11d7,
+ 0xacc: 0x11db, 0xacd: 0x13f3, 0xace: 0x066b, 0xacf: 0x1207, 0xad0: 0x1203, 0xad1: 0x120b,
+ 0xad2: 0x083f, 0xad3: 0x120f, 0xad4: 0x1213, 0xad5: 0x1217, 0xad6: 0x121f, 0xad7: 0x17cd,
+ 0xad8: 0x121b, 0xad9: 0x1223, 0xada: 0x1237, 0xadb: 0x123b, 0xadc: 0x1227, 0xadd: 0x123f,
+ 0xade: 0x1253, 0xadf: 0x1267, 0xae0: 0x1233, 0xae1: 0x1247, 0xae2: 0x124b, 0xae3: 0x124f,
+ 0xae4: 0x17d2, 0xae5: 0x17dc, 0xae6: 0x17d7, 0xae7: 0x066f, 0xae8: 0x126f, 0xae9: 0x1273,
+ 0xaea: 0x127b, 0xaeb: 0x17f0, 0xaec: 0x127f, 0xaed: 0x17e1, 0xaee: 0x0673, 0xaef: 0x0677,
+ 0xaf0: 0x17e6, 0xaf1: 0x17eb, 0xaf2: 0x067b, 0xaf3: 0x129f, 0xaf4: 0x12a3, 0xaf5: 0x12a7,
+ 0xaf6: 0x12ab, 0xaf7: 0x12b7, 0xaf8: 0x12b3, 0xaf9: 0x12bf, 0xafa: 0x12bb, 0xafb: 0x12cb,
+ 0xafc: 0x12c3, 0xafd: 0x12c7, 0xafe: 0x12cf, 0xaff: 0x067f,
+ // Block 0x2c, offset 0xb00
+ 0xb00: 0x12d7, 0xb01: 0x12db, 0xb02: 0x0683, 0xb03: 0x12eb, 0xb04: 0x12ef, 0xb05: 0x17f5,
+ 0xb06: 0x12fb, 0xb07: 0x12ff, 0xb08: 0x0687, 0xb09: 0x130b, 0xb0a: 0x05bb, 0xb0b: 0x17fa,
+ 0xb0c: 0x17ff, 0xb0d: 0x068b, 0xb0e: 0x068f, 0xb0f: 0x1337, 0xb10: 0x134f, 0xb11: 0x136b,
+ 0xb12: 0x137b, 0xb13: 0x1804, 0xb14: 0x138f, 0xb15: 0x1393, 0xb16: 0x13ab, 0xb17: 0x13b7,
+ 0xb18: 0x180e, 0xb19: 0x1660, 0xb1a: 0x13c3, 0xb1b: 0x13bf, 0xb1c: 0x13cb, 0xb1d: 0x1665,
+ 0xb1e: 0x13d7, 0xb1f: 0x13e3, 0xb20: 0x1813, 0xb21: 0x1818, 0xb22: 0x1423, 0xb23: 0x142f,
+ 0xb24: 0x1437, 0xb25: 0x181d, 0xb26: 0x143b, 0xb27: 0x1467, 0xb28: 0x1473, 0xb29: 0x1477,
+ 0xb2a: 0x146f, 0xb2b: 0x1483, 0xb2c: 0x1487, 0xb2d: 0x1822, 0xb2e: 0x1493, 0xb2f: 0x0693,
+ 0xb30: 0x149b, 0xb31: 0x1827, 0xb32: 0x0697, 0xb33: 0x14d3, 0xb34: 0x0ac3, 0xb35: 0x14eb,
+ 0xb36: 0x182c, 0xb37: 0x1836, 0xb38: 0x069b, 0xb39: 0x069f, 0xb3a: 0x1513, 0xb3b: 0x183b,
+ 0xb3c: 0x06a3, 0xb3d: 0x1840, 0xb3e: 0x152b, 0xb3f: 0x152b,
+ // Block 0x2d, offset 0xb40
+ 0xb40: 0x1533, 0xb41: 0x1845, 0xb42: 0x154b, 0xb43: 0x06a7, 0xb44: 0x155b, 0xb45: 0x1567,
+ 0xb46: 0x156f, 0xb47: 0x1577, 0xb48: 0x06ab, 0xb49: 0x184a, 0xb4a: 0x158b, 0xb4b: 0x15a7,
+ 0xb4c: 0x15b3, 0xb4d: 0x06af, 0xb4e: 0x06b3, 0xb4f: 0x15b7, 0xb50: 0x184f, 0xb51: 0x06b7,
+ 0xb52: 0x1854, 0xb53: 0x1859, 0xb54: 0x185e, 0xb55: 0x15db, 0xb56: 0x06bb, 0xb57: 0x15ef,
+ 0xb58: 0x15f7, 0xb59: 0x15fb, 0xb5a: 0x1603, 0xb5b: 0x160b, 0xb5c: 0x1613, 0xb5d: 0x1868,
+}
+
+// nfcIndex: 22 blocks, 1408 entries, 1408 bytes
+// Block 0 is the zero block.
+var nfcIndex = [1408]uint8{
+ // Block 0x0, offset 0x0
+ // Block 0x1, offset 0x40
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc2: 0x2c, 0xc3: 0x01, 0xc4: 0x02, 0xc5: 0x03, 0xc6: 0x2d, 0xc7: 0x04,
+ 0xc8: 0x05, 0xca: 0x2e, 0xcb: 0x2f, 0xcc: 0x06, 0xcd: 0x07, 0xce: 0x08, 0xcf: 0x30,
+ 0xd0: 0x09, 0xd1: 0x31, 0xd2: 0x32, 0xd3: 0x0a, 0xd6: 0x0b, 0xd7: 0x33,
+ 0xd8: 0x34, 0xd9: 0x0c, 0xdb: 0x35, 0xdc: 0x36, 0xdd: 0x37, 0xdf: 0x38,
+ 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05,
+ 0xea: 0x06, 0xeb: 0x07, 0xec: 0x08, 0xed: 0x09, 0xef: 0x0a,
+ 0xf0: 0x13,
+ // Block 0x4, offset 0x100
+ 0x120: 0x39, 0x121: 0x3a, 0x123: 0x3b, 0x124: 0x3c, 0x125: 0x3d, 0x126: 0x3e, 0x127: 0x3f,
+ 0x128: 0x40, 0x129: 0x41, 0x12a: 0x42, 0x12b: 0x43, 0x12c: 0x3e, 0x12d: 0x44, 0x12e: 0x45, 0x12f: 0x46,
+ 0x131: 0x47, 0x132: 0x48, 0x133: 0x49, 0x134: 0x4a, 0x135: 0x4b, 0x137: 0x4c,
+ 0x138: 0x4d, 0x139: 0x4e, 0x13a: 0x4f, 0x13b: 0x50, 0x13c: 0x51, 0x13d: 0x52, 0x13e: 0x53, 0x13f: 0x54,
+ // Block 0x5, offset 0x140
+ 0x140: 0x55, 0x142: 0x56, 0x144: 0x57, 0x145: 0x58, 0x146: 0x59, 0x147: 0x5a,
+ 0x14d: 0x5b,
+ 0x15c: 0x5c, 0x15f: 0x5d,
+ 0x162: 0x5e, 0x164: 0x5f,
+ 0x168: 0x60, 0x169: 0x61, 0x16a: 0x62, 0x16c: 0x0d, 0x16d: 0x63, 0x16e: 0x64, 0x16f: 0x65,
+ 0x170: 0x66, 0x173: 0x67, 0x177: 0x68,
+ 0x178: 0x0e, 0x179: 0x0f, 0x17a: 0x10, 0x17b: 0x11, 0x17c: 0x12, 0x17d: 0x13, 0x17e: 0x14, 0x17f: 0x15,
+ // Block 0x6, offset 0x180
+ 0x180: 0x69, 0x183: 0x6a, 0x184: 0x6b, 0x186: 0x6c, 0x187: 0x6d,
+ 0x188: 0x6e, 0x189: 0x16, 0x18a: 0x17, 0x18b: 0x6f, 0x18c: 0x70,
+ 0x1ab: 0x71,
+ 0x1b3: 0x72, 0x1b5: 0x73, 0x1b7: 0x74,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x75, 0x1c1: 0x18, 0x1c2: 0x19, 0x1c3: 0x1a, 0x1c4: 0x76, 0x1c5: 0x77,
+ 0x1c9: 0x78, 0x1cc: 0x79, 0x1cd: 0x7a,
+ // Block 0x8, offset 0x200
+ 0x219: 0x7b, 0x21a: 0x7c, 0x21b: 0x7d,
+ 0x220: 0x7e, 0x223: 0x7f, 0x224: 0x80, 0x225: 0x81, 0x226: 0x82, 0x227: 0x83,
+ 0x22a: 0x84, 0x22b: 0x85, 0x22f: 0x86,
+ 0x230: 0x87, 0x231: 0x88, 0x232: 0x89, 0x233: 0x8a, 0x234: 0x8b, 0x235: 0x8c, 0x236: 0x8d, 0x237: 0x87,
+ 0x238: 0x88, 0x239: 0x89, 0x23a: 0x8a, 0x23b: 0x8b, 0x23c: 0x8c, 0x23d: 0x8d, 0x23e: 0x87, 0x23f: 0x88,
+ // Block 0x9, offset 0x240
+ 0x240: 0x89, 0x241: 0x8a, 0x242: 0x8b, 0x243: 0x8c, 0x244: 0x8d, 0x245: 0x87, 0x246: 0x88, 0x247: 0x89,
+ 0x248: 0x8a, 0x249: 0x8b, 0x24a: 0x8c, 0x24b: 0x8d, 0x24c: 0x87, 0x24d: 0x88, 0x24e: 0x89, 0x24f: 0x8a,
+ 0x250: 0x8b, 0x251: 0x8c, 0x252: 0x8d, 0x253: 0x87, 0x254: 0x88, 0x255: 0x89, 0x256: 0x8a, 0x257: 0x8b,
+ 0x258: 0x8c, 0x259: 0x8d, 0x25a: 0x87, 0x25b: 0x88, 0x25c: 0x89, 0x25d: 0x8a, 0x25e: 0x8b, 0x25f: 0x8c,
+ 0x260: 0x8d, 0x261: 0x87, 0x262: 0x88, 0x263: 0x89, 0x264: 0x8a, 0x265: 0x8b, 0x266: 0x8c, 0x267: 0x8d,
+ 0x268: 0x87, 0x269: 0x88, 0x26a: 0x89, 0x26b: 0x8a, 0x26c: 0x8b, 0x26d: 0x8c, 0x26e: 0x8d, 0x26f: 0x87,
+ 0x270: 0x88, 0x271: 0x89, 0x272: 0x8a, 0x273: 0x8b, 0x274: 0x8c, 0x275: 0x8d, 0x276: 0x87, 0x277: 0x88,
+ 0x278: 0x89, 0x279: 0x8a, 0x27a: 0x8b, 0x27b: 0x8c, 0x27c: 0x8d, 0x27d: 0x87, 0x27e: 0x88, 0x27f: 0x89,
+ // Block 0xa, offset 0x280
+ 0x280: 0x8a, 0x281: 0x8b, 0x282: 0x8c, 0x283: 0x8d, 0x284: 0x87, 0x285: 0x88, 0x286: 0x89, 0x287: 0x8a,
+ 0x288: 0x8b, 0x289: 0x8c, 0x28a: 0x8d, 0x28b: 0x87, 0x28c: 0x88, 0x28d: 0x89, 0x28e: 0x8a, 0x28f: 0x8b,
+ 0x290: 0x8c, 0x291: 0x8d, 0x292: 0x87, 0x293: 0x88, 0x294: 0x89, 0x295: 0x8a, 0x296: 0x8b, 0x297: 0x8c,
+ 0x298: 0x8d, 0x299: 0x87, 0x29a: 0x88, 0x29b: 0x89, 0x29c: 0x8a, 0x29d: 0x8b, 0x29e: 0x8c, 0x29f: 0x8d,
+ 0x2a0: 0x87, 0x2a1: 0x88, 0x2a2: 0x89, 0x2a3: 0x8a, 0x2a4: 0x8b, 0x2a5: 0x8c, 0x2a6: 0x8d, 0x2a7: 0x87,
+ 0x2a8: 0x88, 0x2a9: 0x89, 0x2aa: 0x8a, 0x2ab: 0x8b, 0x2ac: 0x8c, 0x2ad: 0x8d, 0x2ae: 0x87, 0x2af: 0x88,
+ 0x2b0: 0x89, 0x2b1: 0x8a, 0x2b2: 0x8b, 0x2b3: 0x8c, 0x2b4: 0x8d, 0x2b5: 0x87, 0x2b6: 0x88, 0x2b7: 0x89,
+ 0x2b8: 0x8a, 0x2b9: 0x8b, 0x2ba: 0x8c, 0x2bb: 0x8d, 0x2bc: 0x87, 0x2bd: 0x88, 0x2be: 0x89, 0x2bf: 0x8a,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x8b, 0x2c1: 0x8c, 0x2c2: 0x8d, 0x2c3: 0x87, 0x2c4: 0x88, 0x2c5: 0x89, 0x2c6: 0x8a, 0x2c7: 0x8b,
+ 0x2c8: 0x8c, 0x2c9: 0x8d, 0x2ca: 0x87, 0x2cb: 0x88, 0x2cc: 0x89, 0x2cd: 0x8a, 0x2ce: 0x8b, 0x2cf: 0x8c,
+ 0x2d0: 0x8d, 0x2d1: 0x87, 0x2d2: 0x88, 0x2d3: 0x89, 0x2d4: 0x8a, 0x2d5: 0x8b, 0x2d6: 0x8c, 0x2d7: 0x8d,
+ 0x2d8: 0x87, 0x2d9: 0x88, 0x2da: 0x89, 0x2db: 0x8a, 0x2dc: 0x8b, 0x2dd: 0x8c, 0x2de: 0x8e,
+ // Block 0xc, offset 0x300
+ 0x324: 0x1b, 0x325: 0x1c, 0x326: 0x1d, 0x327: 0x1e,
+ 0x328: 0x1f, 0x329: 0x20, 0x32a: 0x21, 0x32b: 0x22, 0x32c: 0x8f, 0x32d: 0x90, 0x32e: 0x91,
+ 0x331: 0x92, 0x332: 0x93, 0x333: 0x94, 0x334: 0x95,
+ 0x338: 0x96, 0x339: 0x97, 0x33a: 0x98, 0x33b: 0x99, 0x33e: 0x9a, 0x33f: 0x9b,
+ // Block 0xd, offset 0x340
+ 0x347: 0x9c,
+ 0x34b: 0x9d, 0x34d: 0x9e,
+ 0x368: 0x9f, 0x36b: 0xa0,
+ // Block 0xe, offset 0x380
+ 0x381: 0xa1, 0x382: 0xa2, 0x384: 0xa3, 0x385: 0x82, 0x387: 0xa4,
+ 0x388: 0xa5, 0x38b: 0xa6, 0x38c: 0x3e, 0x38d: 0xa7,
+ 0x391: 0xa8, 0x392: 0xa9, 0x393: 0xaa, 0x396: 0xab, 0x397: 0xac,
+ 0x398: 0x73, 0x39a: 0xad, 0x39c: 0xae,
+ 0x3b0: 0x73,
+ // Block 0xf, offset 0x3c0
+ 0x3eb: 0xaf, 0x3ec: 0xb0,
+ // Block 0x10, offset 0x400
+ 0x432: 0xb1,
+ // Block 0x11, offset 0x440
+ 0x445: 0xb2, 0x446: 0xb3, 0x447: 0xb4,
+ 0x449: 0xb5,
+ // Block 0x12, offset 0x480
+ 0x480: 0xb6,
+ 0x4a3: 0xb7, 0x4a5: 0xb8,
+ // Block 0x13, offset 0x4c0
+ 0x4c8: 0xb9,
+ // Block 0x14, offset 0x500
+ 0x520: 0x23, 0x521: 0x24, 0x522: 0x25, 0x523: 0x26, 0x524: 0x27, 0x525: 0x28, 0x526: 0x29, 0x527: 0x2a,
+ 0x528: 0x2b,
+ // Block 0x15, offset 0x540
+ 0x550: 0x0b, 0x551: 0x0c, 0x556: 0x0d,
+ 0x55b: 0x0e, 0x55d: 0x0f, 0x55e: 0x10, 0x55f: 0x11,
+ 0x56f: 0x12,
+}
+
+// nfcSparseOffset: 142 entries, 284 bytes
+var nfcSparseOffset = []uint16{0x0, 0x5, 0x9, 0xb, 0xd, 0x18, 0x28, 0x2a, 0x2f, 0x3a, 0x49, 0x56, 0x5e, 0x62, 0x67, 0x69, 0x7a, 0x82, 0x89, 0x8c, 0x93, 0x97, 0x9b, 0x9d, 0x9f, 0xa8, 0xac, 0xb3, 0xb8, 0xbb, 0xc5, 0xc7, 0xce, 0xd6, 0xd9, 0xdb, 0xdd, 0xdf, 0xe4, 0xf5, 0x101, 0x103, 0x109, 0x10b, 0x10d, 0x10f, 0x111, 0x113, 0x115, 0x118, 0x11b, 0x11d, 0x120, 0x123, 0x127, 0x12c, 0x135, 0x137, 0x13a, 0x13c, 0x147, 0x157, 0x15b, 0x169, 0x16c, 0x172, 0x178, 0x183, 0x187, 0x189, 0x18b, 0x18d, 0x18f, 0x191, 0x197, 0x19b, 0x19d, 0x19f, 0x1a7, 0x1ab, 0x1ae, 0x1b0, 0x1b2, 0x1b4, 0x1b7, 0x1b9, 0x1bb, 0x1bd, 0x1bf, 0x1c5, 0x1c8, 0x1ca, 0x1d1, 0x1d7, 0x1dd, 0x1e5, 0x1eb, 0x1f1, 0x1f7, 0x1fb, 0x209, 0x212, 0x215, 0x218, 0x21a, 0x21d, 0x21f, 0x223, 0x228, 0x22a, 0x22c, 0x231, 0x237, 0x239, 0x23b, 0x23d, 0x243, 0x246, 0x249, 0x251, 0x258, 0x25b, 0x25e, 0x260, 0x268, 0x26b, 0x272, 0x275, 0x27b, 0x27d, 0x280, 0x282, 0x284, 0x286, 0x288, 0x295, 0x29f, 0x2a1, 0x2a3, 0x2a9, 0x2ab, 0x2ae}
+
+// nfcSparseValues: 688 entries, 2752 bytes
+var nfcSparseValues = [688]valueRange{
+ // Block 0x0, offset 0x0
+ {value: 0x0000, lo: 0x04},
+ {value: 0xa100, lo: 0xa8, hi: 0xa8},
+ {value: 0x8100, lo: 0xaf, hi: 0xaf},
+ {value: 0x8100, lo: 0xb4, hi: 0xb4},
+ {value: 0x8100, lo: 0xb8, hi: 0xb8},
+ // Block 0x1, offset 0x5
+ {value: 0x0091, lo: 0x03},
+ {value: 0x4778, lo: 0xa0, hi: 0xa1},
+ {value: 0x47aa, lo: 0xaf, hi: 0xb0},
+ {value: 0xa000, lo: 0xb7, hi: 0xb7},
+ // Block 0x2, offset 0x9
+ {value: 0x0000, lo: 0x01},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ // Block 0x3, offset 0xb
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0x98, hi: 0x9d},
+ // Block 0x4, offset 0xd
+ {value: 0x0006, lo: 0x0a},
+ {value: 0xa000, lo: 0x81, hi: 0x81},
+ {value: 0xa000, lo: 0x85, hi: 0x85},
+ {value: 0xa000, lo: 0x89, hi: 0x89},
+ {value: 0x48d6, lo: 0x8a, hi: 0x8a},
+ {value: 0x48f4, lo: 0x8b, hi: 0x8b},
+ {value: 0x36c7, lo: 0x8c, hi: 0x8c},
+ {value: 0x36df, lo: 0x8d, hi: 0x8d},
+ {value: 0x490c, lo: 0x8e, hi: 0x8e},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x36fd, lo: 0x93, hi: 0x94},
+ // Block 0x5, offset 0x18
+ {value: 0x0000, lo: 0x0f},
+ {value: 0xa000, lo: 0x83, hi: 0x83},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0xa000, lo: 0x8b, hi: 0x8b},
+ {value: 0xa000, lo: 0x8d, hi: 0x8d},
+ {value: 0x37a5, lo: 0x90, hi: 0x90},
+ {value: 0x37b1, lo: 0x91, hi: 0x91},
+ {value: 0x379f, lo: 0x93, hi: 0x93},
+ {value: 0xa000, lo: 0x96, hi: 0x96},
+ {value: 0x3817, lo: 0x97, hi: 0x97},
+ {value: 0x37e1, lo: 0x9c, hi: 0x9c},
+ {value: 0x37c9, lo: 0x9d, hi: 0x9d},
+ {value: 0x37f3, lo: 0x9e, hi: 0x9e},
+ {value: 0xa000, lo: 0xb4, hi: 0xb5},
+ {value: 0x381d, lo: 0xb6, hi: 0xb6},
+ {value: 0x3823, lo: 0xb7, hi: 0xb7},
+ // Block 0x6, offset 0x28
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x83, hi: 0x87},
+ // Block 0x7, offset 0x2a
+ {value: 0x0001, lo: 0x04},
+ {value: 0x8113, lo: 0x81, hi: 0x82},
+ {value: 0x8132, lo: 0x84, hi: 0x84},
+ {value: 0x812d, lo: 0x85, hi: 0x85},
+ {value: 0x810d, lo: 0x87, hi: 0x87},
+ // Block 0x8, offset 0x2f
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x8132, lo: 0x90, hi: 0x97},
+ {value: 0x8119, lo: 0x98, hi: 0x98},
+ {value: 0x811a, lo: 0x99, hi: 0x99},
+ {value: 0x811b, lo: 0x9a, hi: 0x9a},
+ {value: 0x3841, lo: 0xa2, hi: 0xa2},
+ {value: 0x3847, lo: 0xa3, hi: 0xa3},
+ {value: 0x3853, lo: 0xa4, hi: 0xa4},
+ {value: 0x384d, lo: 0xa5, hi: 0xa5},
+ {value: 0x3859, lo: 0xa6, hi: 0xa6},
+ {value: 0xa000, lo: 0xa7, hi: 0xa7},
+ // Block 0x9, offset 0x3a
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x386b, lo: 0x80, hi: 0x80},
+ {value: 0xa000, lo: 0x81, hi: 0x81},
+ {value: 0x385f, lo: 0x82, hi: 0x82},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x3865, lo: 0x93, hi: 0x93},
+ {value: 0xa000, lo: 0x95, hi: 0x95},
+ {value: 0x8132, lo: 0x96, hi: 0x9c},
+ {value: 0x8132, lo: 0x9f, hi: 0xa2},
+ {value: 0x812d, lo: 0xa3, hi: 0xa3},
+ {value: 0x8132, lo: 0xa4, hi: 0xa4},
+ {value: 0x8132, lo: 0xa7, hi: 0xa8},
+ {value: 0x812d, lo: 0xaa, hi: 0xaa},
+ {value: 0x8132, lo: 0xab, hi: 0xac},
+ {value: 0x812d, lo: 0xad, hi: 0xad},
+ // Block 0xa, offset 0x49
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x811f, lo: 0x91, hi: 0x91},
+ {value: 0x8132, lo: 0xb0, hi: 0xb0},
+ {value: 0x812d, lo: 0xb1, hi: 0xb1},
+ {value: 0x8132, lo: 0xb2, hi: 0xb3},
+ {value: 0x812d, lo: 0xb4, hi: 0xb4},
+ {value: 0x8132, lo: 0xb5, hi: 0xb6},
+ {value: 0x812d, lo: 0xb7, hi: 0xb9},
+ {value: 0x8132, lo: 0xba, hi: 0xba},
+ {value: 0x812d, lo: 0xbb, hi: 0xbc},
+ {value: 0x8132, lo: 0xbd, hi: 0xbd},
+ {value: 0x812d, lo: 0xbe, hi: 0xbe},
+ {value: 0x8132, lo: 0xbf, hi: 0xbf},
+ // Block 0xb, offset 0x56
+ {value: 0x0005, lo: 0x07},
+ {value: 0x8132, lo: 0x80, hi: 0x80},
+ {value: 0x8132, lo: 0x81, hi: 0x81},
+ {value: 0x812d, lo: 0x82, hi: 0x83},
+ {value: 0x812d, lo: 0x84, hi: 0x85},
+ {value: 0x812d, lo: 0x86, hi: 0x87},
+ {value: 0x812d, lo: 0x88, hi: 0x89},
+ {value: 0x8132, lo: 0x8a, hi: 0x8a},
+ // Block 0xc, offset 0x5e
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8132, lo: 0xab, hi: 0xb1},
+ {value: 0x812d, lo: 0xb2, hi: 0xb2},
+ {value: 0x8132, lo: 0xb3, hi: 0xb3},
+ // Block 0xd, offset 0x62
+ {value: 0x0000, lo: 0x04},
+ {value: 0x8132, lo: 0x96, hi: 0x99},
+ {value: 0x8132, lo: 0x9b, hi: 0xa3},
+ {value: 0x8132, lo: 0xa5, hi: 0xa7},
+ {value: 0x8132, lo: 0xa9, hi: 0xad},
+ // Block 0xe, offset 0x67
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x99, hi: 0x9b},
+ // Block 0xf, offset 0x69
+ {value: 0x0000, lo: 0x10},
+ {value: 0x8132, lo: 0x94, hi: 0xa1},
+ {value: 0x812d, lo: 0xa3, hi: 0xa3},
+ {value: 0x8132, lo: 0xa4, hi: 0xa5},
+ {value: 0x812d, lo: 0xa6, hi: 0xa6},
+ {value: 0x8132, lo: 0xa7, hi: 0xa8},
+ {value: 0x812d, lo: 0xa9, hi: 0xa9},
+ {value: 0x8132, lo: 0xaa, hi: 0xac},
+ {value: 0x812d, lo: 0xad, hi: 0xaf},
+ {value: 0x8116, lo: 0xb0, hi: 0xb0},
+ {value: 0x8117, lo: 0xb1, hi: 0xb1},
+ {value: 0x8118, lo: 0xb2, hi: 0xb2},
+ {value: 0x8132, lo: 0xb3, hi: 0xb5},
+ {value: 0x812d, lo: 0xb6, hi: 0xb6},
+ {value: 0x8132, lo: 0xb7, hi: 0xb8},
+ {value: 0x812d, lo: 0xb9, hi: 0xba},
+ {value: 0x8132, lo: 0xbb, hi: 0xbf},
+ // Block 0x10, offset 0x7a
+ {value: 0x0000, lo: 0x07},
+ {value: 0xa000, lo: 0xa8, hi: 0xa8},
+ {value: 0x3ed8, lo: 0xa9, hi: 0xa9},
+ {value: 0xa000, lo: 0xb0, hi: 0xb0},
+ {value: 0x3ee0, lo: 0xb1, hi: 0xb1},
+ {value: 0xa000, lo: 0xb3, hi: 0xb3},
+ {value: 0x3ee8, lo: 0xb4, hi: 0xb4},
+ {value: 0x9902, lo: 0xbc, hi: 0xbc},
+ // Block 0x11, offset 0x82
+ {value: 0x0008, lo: 0x06},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x8132, lo: 0x91, hi: 0x91},
+ {value: 0x812d, lo: 0x92, hi: 0x92},
+ {value: 0x8132, lo: 0x93, hi: 0x93},
+ {value: 0x8132, lo: 0x94, hi: 0x94},
+ {value: 0x45b2, lo: 0x98, hi: 0x9f},
+ // Block 0x12, offset 0x89
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x13, offset 0x8c
+ {value: 0x0008, lo: 0x06},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2c9e, lo: 0x8b, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ {value: 0x45f2, lo: 0x9c, hi: 0x9d},
+ {value: 0x4602, lo: 0x9f, hi: 0x9f},
+ // Block 0x14, offset 0x93
+ {value: 0x0000, lo: 0x03},
+ {value: 0x462a, lo: 0xb3, hi: 0xb3},
+ {value: 0x4632, lo: 0xb6, hi: 0xb6},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ // Block 0x15, offset 0x97
+ {value: 0x0008, lo: 0x03},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x460a, lo: 0x99, hi: 0x9b},
+ {value: 0x4622, lo: 0x9e, hi: 0x9e},
+ // Block 0x16, offset 0x9b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ // Block 0x17, offset 0x9d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ // Block 0x18, offset 0x9f
+ {value: 0x0000, lo: 0x08},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2cb6, lo: 0x88, hi: 0x88},
+ {value: 0x2cae, lo: 0x8b, hi: 0x8b},
+ {value: 0x2cbe, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x96, hi: 0x97},
+ {value: 0x463a, lo: 0x9c, hi: 0x9c},
+ {value: 0x4642, lo: 0x9d, hi: 0x9d},
+ // Block 0x19, offset 0xa8
+ {value: 0x0000, lo: 0x03},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x2cc6, lo: 0x94, hi: 0x94},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x1a, offset 0xac
+ {value: 0x0000, lo: 0x06},
+ {value: 0xa000, lo: 0x86, hi: 0x87},
+ {value: 0x2cce, lo: 0x8a, hi: 0x8a},
+ {value: 0x2cde, lo: 0x8b, hi: 0x8b},
+ {value: 0x2cd6, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ // Block 0x1b, offset 0xb3
+ {value: 0x1801, lo: 0x04},
+ {value: 0xa000, lo: 0x86, hi: 0x86},
+ {value: 0x3ef0, lo: 0x88, hi: 0x88},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x8120, lo: 0x95, hi: 0x96},
+ // Block 0x1c, offset 0xb8
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ {value: 0xa000, lo: 0xbf, hi: 0xbf},
+ // Block 0x1d, offset 0xbb
+ {value: 0x0000, lo: 0x09},
+ {value: 0x2ce6, lo: 0x80, hi: 0x80},
+ {value: 0x9900, lo: 0x82, hi: 0x82},
+ {value: 0xa000, lo: 0x86, hi: 0x86},
+ {value: 0x2cee, lo: 0x87, hi: 0x87},
+ {value: 0x2cf6, lo: 0x88, hi: 0x88},
+ {value: 0x2f50, lo: 0x8a, hi: 0x8a},
+ {value: 0x2dd8, lo: 0x8b, hi: 0x8b},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x95, hi: 0x96},
+ // Block 0x1e, offset 0xc5
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x1f, offset 0xc7
+ {value: 0x0000, lo: 0x06},
+ {value: 0xa000, lo: 0x86, hi: 0x87},
+ {value: 0x2cfe, lo: 0x8a, hi: 0x8a},
+ {value: 0x2d0e, lo: 0x8b, hi: 0x8b},
+ {value: 0x2d06, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ // Block 0x20, offset 0xce
+ {value: 0x6bea, lo: 0x07},
+ {value: 0x9904, lo: 0x8a, hi: 0x8a},
+ {value: 0x9900, lo: 0x8f, hi: 0x8f},
+ {value: 0xa000, lo: 0x99, hi: 0x99},
+ {value: 0x3ef8, lo: 0x9a, hi: 0x9a},
+ {value: 0x2f58, lo: 0x9c, hi: 0x9c},
+ {value: 0x2de3, lo: 0x9d, hi: 0x9d},
+ {value: 0x2d16, lo: 0x9e, hi: 0x9f},
+ // Block 0x21, offset 0xd6
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8122, lo: 0xb8, hi: 0xb9},
+ {value: 0x8104, lo: 0xba, hi: 0xba},
+ // Block 0x22, offset 0xd9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8123, lo: 0x88, hi: 0x8b},
+ // Block 0x23, offset 0xdb
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8124, lo: 0xb8, hi: 0xb9},
+ // Block 0x24, offset 0xdd
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8125, lo: 0x88, hi: 0x8b},
+ // Block 0x25, offset 0xdf
+ {value: 0x0000, lo: 0x04},
+ {value: 0x812d, lo: 0x98, hi: 0x99},
+ {value: 0x812d, lo: 0xb5, hi: 0xb5},
+ {value: 0x812d, lo: 0xb7, hi: 0xb7},
+ {value: 0x812b, lo: 0xb9, hi: 0xb9},
+ // Block 0x26, offset 0xe4
+ {value: 0x0000, lo: 0x10},
+ {value: 0x2644, lo: 0x83, hi: 0x83},
+ {value: 0x264b, lo: 0x8d, hi: 0x8d},
+ {value: 0x2652, lo: 0x92, hi: 0x92},
+ {value: 0x2659, lo: 0x97, hi: 0x97},
+ {value: 0x2660, lo: 0x9c, hi: 0x9c},
+ {value: 0x263d, lo: 0xa9, hi: 0xa9},
+ {value: 0x8126, lo: 0xb1, hi: 0xb1},
+ {value: 0x8127, lo: 0xb2, hi: 0xb2},
+ {value: 0x4a66, lo: 0xb3, hi: 0xb3},
+ {value: 0x8128, lo: 0xb4, hi: 0xb4},
+ {value: 0x4a6f, lo: 0xb5, hi: 0xb5},
+ {value: 0x464a, lo: 0xb6, hi: 0xb6},
+ {value: 0x8200, lo: 0xb7, hi: 0xb7},
+ {value: 0x4652, lo: 0xb8, hi: 0xb8},
+ {value: 0x8200, lo: 0xb9, hi: 0xb9},
+ {value: 0x8127, lo: 0xba, hi: 0xbd},
+ // Block 0x27, offset 0xf5
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x8127, lo: 0x80, hi: 0x80},
+ {value: 0x4a78, lo: 0x81, hi: 0x81},
+ {value: 0x8132, lo: 0x82, hi: 0x83},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0x86, hi: 0x87},
+ {value: 0x266e, lo: 0x93, hi: 0x93},
+ {value: 0x2675, lo: 0x9d, hi: 0x9d},
+ {value: 0x267c, lo: 0xa2, hi: 0xa2},
+ {value: 0x2683, lo: 0xa7, hi: 0xa7},
+ {value: 0x268a, lo: 0xac, hi: 0xac},
+ {value: 0x2667, lo: 0xb9, hi: 0xb9},
+ // Block 0x28, offset 0x101
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x86, hi: 0x86},
+ // Block 0x29, offset 0x103
+ {value: 0x0000, lo: 0x05},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x2d1e, lo: 0xa6, hi: 0xa6},
+ {value: 0x9900, lo: 0xae, hi: 0xae},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ {value: 0x8104, lo: 0xb9, hi: 0xba},
+ // Block 0x2a, offset 0x109
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x8d, hi: 0x8d},
+ // Block 0x2b, offset 0x10b
+ {value: 0x0000, lo: 0x01},
+ {value: 0xa000, lo: 0x80, hi: 0x92},
+ // Block 0x2c, offset 0x10d
+ {value: 0x0000, lo: 0x01},
+ {value: 0xb900, lo: 0xa1, hi: 0xb5},
+ // Block 0x2d, offset 0x10f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0xa8, hi: 0xbf},
+ // Block 0x2e, offset 0x111
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0x80, hi: 0x82},
+ // Block 0x2f, offset 0x113
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x9d, hi: 0x9f},
+ // Block 0x30, offset 0x115
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x94, hi: 0x94},
+ {value: 0x8104, lo: 0xb4, hi: 0xb4},
+ // Block 0x31, offset 0x118
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x92, hi: 0x92},
+ {value: 0x8132, lo: 0x9d, hi: 0x9d},
+ // Block 0x32, offset 0x11b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8131, lo: 0xa9, hi: 0xa9},
+ // Block 0x33, offset 0x11d
+ {value: 0x0004, lo: 0x02},
+ {value: 0x812e, lo: 0xb9, hi: 0xba},
+ {value: 0x812d, lo: 0xbb, hi: 0xbb},
+ // Block 0x34, offset 0x120
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x97, hi: 0x97},
+ {value: 0x812d, lo: 0x98, hi: 0x98},
+ // Block 0x35, offset 0x123
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8104, lo: 0xa0, hi: 0xa0},
+ {value: 0x8132, lo: 0xb5, hi: 0xbc},
+ {value: 0x812d, lo: 0xbf, hi: 0xbf},
+ // Block 0x36, offset 0x127
+ {value: 0x0000, lo: 0x04},
+ {value: 0x8132, lo: 0xb0, hi: 0xb4},
+ {value: 0x812d, lo: 0xb5, hi: 0xba},
+ {value: 0x8132, lo: 0xbb, hi: 0xbc},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ // Block 0x37, offset 0x12c
+ {value: 0x0000, lo: 0x08},
+ {value: 0x2d66, lo: 0x80, hi: 0x80},
+ {value: 0x2d6e, lo: 0x81, hi: 0x81},
+ {value: 0xa000, lo: 0x82, hi: 0x82},
+ {value: 0x2d76, lo: 0x83, hi: 0x83},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0xab, hi: 0xab},
+ {value: 0x812d, lo: 0xac, hi: 0xac},
+ {value: 0x8132, lo: 0xad, hi: 0xb3},
+ // Block 0x38, offset 0x135
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xaa, hi: 0xab},
+ // Block 0x39, offset 0x137
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xa6, hi: 0xa6},
+ {value: 0x8104, lo: 0xb2, hi: 0xb3},
+ // Block 0x3a, offset 0x13a
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ // Block 0x3b, offset 0x13c
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x8132, lo: 0x90, hi: 0x92},
+ {value: 0x8101, lo: 0x94, hi: 0x94},
+ {value: 0x812d, lo: 0x95, hi: 0x99},
+ {value: 0x8132, lo: 0x9a, hi: 0x9b},
+ {value: 0x812d, lo: 0x9c, hi: 0x9f},
+ {value: 0x8132, lo: 0xa0, hi: 0xa0},
+ {value: 0x8101, lo: 0xa2, hi: 0xa8},
+ {value: 0x812d, lo: 0xad, hi: 0xad},
+ {value: 0x8132, lo: 0xb4, hi: 0xb4},
+ {value: 0x8132, lo: 0xb8, hi: 0xb9},
+ // Block 0x3c, offset 0x147
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x8132, lo: 0x80, hi: 0x81},
+ {value: 0x812d, lo: 0x82, hi: 0x82},
+ {value: 0x8132, lo: 0x83, hi: 0x89},
+ {value: 0x812d, lo: 0x8a, hi: 0x8a},
+ {value: 0x8132, lo: 0x8b, hi: 0x8c},
+ {value: 0x8135, lo: 0x8d, hi: 0x8d},
+ {value: 0x812a, lo: 0x8e, hi: 0x8e},
+ {value: 0x812d, lo: 0x8f, hi: 0x8f},
+ {value: 0x8129, lo: 0x90, hi: 0x90},
+ {value: 0x8132, lo: 0x91, hi: 0xb5},
+ {value: 0x8132, lo: 0xbb, hi: 0xbb},
+ {value: 0x8134, lo: 0xbc, hi: 0xbc},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ {value: 0x8132, lo: 0xbe, hi: 0xbe},
+ {value: 0x812d, lo: 0xbf, hi: 0xbf},
+ // Block 0x3d, offset 0x157
+ {value: 0x0004, lo: 0x03},
+ {value: 0x0433, lo: 0x80, hi: 0x81},
+ {value: 0x8100, lo: 0x97, hi: 0x97},
+ {value: 0x8100, lo: 0xbe, hi: 0xbe},
+ // Block 0x3e, offset 0x15b
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x8132, lo: 0x90, hi: 0x91},
+ {value: 0x8101, lo: 0x92, hi: 0x93},
+ {value: 0x8132, lo: 0x94, hi: 0x97},
+ {value: 0x8101, lo: 0x98, hi: 0x9a},
+ {value: 0x8132, lo: 0x9b, hi: 0x9c},
+ {value: 0x8132, lo: 0xa1, hi: 0xa1},
+ {value: 0x8101, lo: 0xa5, hi: 0xa6},
+ {value: 0x8132, lo: 0xa7, hi: 0xa7},
+ {value: 0x812d, lo: 0xa8, hi: 0xa8},
+ {value: 0x8132, lo: 0xa9, hi: 0xa9},
+ {value: 0x8101, lo: 0xaa, hi: 0xab},
+ {value: 0x812d, lo: 0xac, hi: 0xaf},
+ {value: 0x8132, lo: 0xb0, hi: 0xb0},
+ // Block 0x3f, offset 0x169
+ {value: 0x427b, lo: 0x02},
+ {value: 0x01b8, lo: 0xa6, hi: 0xa6},
+ {value: 0x0057, lo: 0xaa, hi: 0xab},
+ // Block 0x40, offset 0x16c
+ {value: 0x0007, lo: 0x05},
+ {value: 0xa000, lo: 0x90, hi: 0x90},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0xa000, lo: 0x94, hi: 0x94},
+ {value: 0x3bb9, lo: 0x9a, hi: 0x9b},
+ {value: 0x3bc7, lo: 0xae, hi: 0xae},
+ // Block 0x41, offset 0x172
+ {value: 0x000e, lo: 0x05},
+ {value: 0x3bce, lo: 0x8d, hi: 0x8e},
+ {value: 0x3bd5, lo: 0x8f, hi: 0x8f},
+ {value: 0xa000, lo: 0x90, hi: 0x90},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0xa000, lo: 0x94, hi: 0x94},
+ // Block 0x42, offset 0x178
+ {value: 0x6408, lo: 0x0a},
+ {value: 0xa000, lo: 0x83, hi: 0x83},
+ {value: 0x3be3, lo: 0x84, hi: 0x84},
+ {value: 0xa000, lo: 0x88, hi: 0x88},
+ {value: 0x3bea, lo: 0x89, hi: 0x89},
+ {value: 0xa000, lo: 0x8b, hi: 0x8b},
+ {value: 0x3bf1, lo: 0x8c, hi: 0x8c},
+ {value: 0xa000, lo: 0xa3, hi: 0xa3},
+ {value: 0x3bf8, lo: 0xa4, hi: 0xa5},
+ {value: 0x3bff, lo: 0xa6, hi: 0xa6},
+ {value: 0xa000, lo: 0xbc, hi: 0xbc},
+ // Block 0x43, offset 0x183
+ {value: 0x0007, lo: 0x03},
+ {value: 0x3c68, lo: 0xa0, hi: 0xa1},
+ {value: 0x3c92, lo: 0xa2, hi: 0xa3},
+ {value: 0x3cbc, lo: 0xaa, hi: 0xad},
+ // Block 0x44, offset 0x187
+ {value: 0x0004, lo: 0x01},
+ {value: 0x048b, lo: 0xa9, hi: 0xaa},
+ // Block 0x45, offset 0x189
+ {value: 0x0000, lo: 0x01},
+ {value: 0x4573, lo: 0x9c, hi: 0x9c},
+ // Block 0x46, offset 0x18b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xaf, hi: 0xb1},
+ // Block 0x47, offset 0x18d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x48, offset 0x18f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xa0, hi: 0xbf},
+ // Block 0x49, offset 0x191
+ {value: 0x0000, lo: 0x05},
+ {value: 0x812c, lo: 0xaa, hi: 0xaa},
+ {value: 0x8131, lo: 0xab, hi: 0xab},
+ {value: 0x8133, lo: 0xac, hi: 0xac},
+ {value: 0x812e, lo: 0xad, hi: 0xad},
+ {value: 0x812f, lo: 0xae, hi: 0xaf},
+ // Block 0x4a, offset 0x197
+ {value: 0x0000, lo: 0x03},
+ {value: 0x4a81, lo: 0xb3, hi: 0xb3},
+ {value: 0x4a81, lo: 0xb5, hi: 0xb6},
+ {value: 0x4a81, lo: 0xba, hi: 0xbf},
+ // Block 0x4b, offset 0x19b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x4a81, lo: 0x8f, hi: 0xa3},
+ // Block 0x4c, offset 0x19d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0xae, hi: 0xbe},
+ // Block 0x4d, offset 0x19f
+ {value: 0x0000, lo: 0x07},
+ {value: 0x8100, lo: 0x84, hi: 0x84},
+ {value: 0x8100, lo: 0x87, hi: 0x87},
+ {value: 0x8100, lo: 0x90, hi: 0x90},
+ {value: 0x8100, lo: 0x9e, hi: 0x9e},
+ {value: 0x8100, lo: 0xa1, hi: 0xa1},
+ {value: 0x8100, lo: 0xb2, hi: 0xb2},
+ {value: 0x8100, lo: 0xbb, hi: 0xbb},
+ // Block 0x4e, offset 0x1a7
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8100, lo: 0x80, hi: 0x80},
+ {value: 0x8100, lo: 0x8b, hi: 0x8b},
+ {value: 0x8100, lo: 0x8e, hi: 0x8e},
+ // Block 0x4f, offset 0x1ab
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0xaf, hi: 0xaf},
+ {value: 0x8132, lo: 0xb4, hi: 0xbd},
+ // Block 0x50, offset 0x1ae
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x9e, hi: 0x9f},
+ // Block 0x51, offset 0x1b0
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb0, hi: 0xb1},
+ // Block 0x52, offset 0x1b2
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x86, hi: 0x86},
+ // Block 0x53, offset 0x1b4
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0xa0, hi: 0xb1},
+ // Block 0x54, offset 0x1b7
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xab, hi: 0xad},
+ // Block 0x55, offset 0x1b9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x93, hi: 0x93},
+ // Block 0x56, offset 0x1bb
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xb3, hi: 0xb3},
+ // Block 0x57, offset 0x1bd
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x80, hi: 0x80},
+ // Block 0x58, offset 0x1bf
+ {value: 0x0000, lo: 0x05},
+ {value: 0x8132, lo: 0xb0, hi: 0xb0},
+ {value: 0x8132, lo: 0xb2, hi: 0xb3},
+ {value: 0x812d, lo: 0xb4, hi: 0xb4},
+ {value: 0x8132, lo: 0xb7, hi: 0xb8},
+ {value: 0x8132, lo: 0xbe, hi: 0xbf},
+ // Block 0x59, offset 0x1c5
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x81, hi: 0x81},
+ {value: 0x8104, lo: 0xb6, hi: 0xb6},
+ // Block 0x5a, offset 0x1c8
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xad, hi: 0xad},
+ // Block 0x5b, offset 0x1ca
+ {value: 0x0000, lo: 0x06},
+ {value: 0xe500, lo: 0x80, hi: 0x80},
+ {value: 0xc600, lo: 0x81, hi: 0x9b},
+ {value: 0xe500, lo: 0x9c, hi: 0x9c},
+ {value: 0xc600, lo: 0x9d, hi: 0xb7},
+ {value: 0xe500, lo: 0xb8, hi: 0xb8},
+ {value: 0xc600, lo: 0xb9, hi: 0xbf},
+ // Block 0x5c, offset 0x1d1
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x93},
+ {value: 0xe500, lo: 0x94, hi: 0x94},
+ {value: 0xc600, lo: 0x95, hi: 0xaf},
+ {value: 0xe500, lo: 0xb0, hi: 0xb0},
+ {value: 0xc600, lo: 0xb1, hi: 0xbf},
+ // Block 0x5d, offset 0x1d7
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x8b},
+ {value: 0xe500, lo: 0x8c, hi: 0x8c},
+ {value: 0xc600, lo: 0x8d, hi: 0xa7},
+ {value: 0xe500, lo: 0xa8, hi: 0xa8},
+ {value: 0xc600, lo: 0xa9, hi: 0xbf},
+ // Block 0x5e, offset 0x1dd
+ {value: 0x0000, lo: 0x07},
+ {value: 0xc600, lo: 0x80, hi: 0x83},
+ {value: 0xe500, lo: 0x84, hi: 0x84},
+ {value: 0xc600, lo: 0x85, hi: 0x9f},
+ {value: 0xe500, lo: 0xa0, hi: 0xa0},
+ {value: 0xc600, lo: 0xa1, hi: 0xbb},
+ {value: 0xe500, lo: 0xbc, hi: 0xbc},
+ {value: 0xc600, lo: 0xbd, hi: 0xbf},
+ // Block 0x5f, offset 0x1e5
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x97},
+ {value: 0xe500, lo: 0x98, hi: 0x98},
+ {value: 0xc600, lo: 0x99, hi: 0xb3},
+ {value: 0xe500, lo: 0xb4, hi: 0xb4},
+ {value: 0xc600, lo: 0xb5, hi: 0xbf},
+ // Block 0x60, offset 0x1eb
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x8f},
+ {value: 0xe500, lo: 0x90, hi: 0x90},
+ {value: 0xc600, lo: 0x91, hi: 0xab},
+ {value: 0xe500, lo: 0xac, hi: 0xac},
+ {value: 0xc600, lo: 0xad, hi: 0xbf},
+ // Block 0x61, offset 0x1f1
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x87},
+ {value: 0xe500, lo: 0x88, hi: 0x88},
+ {value: 0xc600, lo: 0x89, hi: 0xa3},
+ {value: 0xe500, lo: 0xa4, hi: 0xa4},
+ {value: 0xc600, lo: 0xa5, hi: 0xbf},
+ // Block 0x62, offset 0x1f7
+ {value: 0x0000, lo: 0x03},
+ {value: 0xc600, lo: 0x80, hi: 0x87},
+ {value: 0xe500, lo: 0x88, hi: 0x88},
+ {value: 0xc600, lo: 0x89, hi: 0xa3},
+ // Block 0x63, offset 0x1fb
+ {value: 0x0006, lo: 0x0d},
+ {value: 0x4426, lo: 0x9d, hi: 0x9d},
+ {value: 0x8115, lo: 0x9e, hi: 0x9e},
+ {value: 0x4498, lo: 0x9f, hi: 0x9f},
+ {value: 0x4486, lo: 0xaa, hi: 0xab},
+ {value: 0x458a, lo: 0xac, hi: 0xac},
+ {value: 0x4592, lo: 0xad, hi: 0xad},
+ {value: 0x43de, lo: 0xae, hi: 0xb1},
+ {value: 0x43fc, lo: 0xb2, hi: 0xb4},
+ {value: 0x4414, lo: 0xb5, hi: 0xb6},
+ {value: 0x4420, lo: 0xb8, hi: 0xb8},
+ {value: 0x442c, lo: 0xb9, hi: 0xbb},
+ {value: 0x4444, lo: 0xbc, hi: 0xbc},
+ {value: 0x444a, lo: 0xbe, hi: 0xbe},
+ // Block 0x64, offset 0x209
+ {value: 0x0006, lo: 0x08},
+ {value: 0x4450, lo: 0x80, hi: 0x81},
+ {value: 0x445c, lo: 0x83, hi: 0x84},
+ {value: 0x446e, lo: 0x86, hi: 0x89},
+ {value: 0x4492, lo: 0x8a, hi: 0x8a},
+ {value: 0x440e, lo: 0x8b, hi: 0x8b},
+ {value: 0x43f6, lo: 0x8c, hi: 0x8c},
+ {value: 0x443e, lo: 0x8d, hi: 0x8d},
+ {value: 0x4468, lo: 0x8e, hi: 0x8e},
+ // Block 0x65, offset 0x212
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8100, lo: 0xa4, hi: 0xa5},
+ {value: 0x8100, lo: 0xb0, hi: 0xb1},
+ // Block 0x66, offset 0x215
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8100, lo: 0x9b, hi: 0x9d},
+ {value: 0x8200, lo: 0x9e, hi: 0xa3},
+ // Block 0x67, offset 0x218
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0x90, hi: 0x90},
+ // Block 0x68, offset 0x21a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8100, lo: 0x99, hi: 0x99},
+ {value: 0x8200, lo: 0xb2, hi: 0xb4},
+ // Block 0x69, offset 0x21d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0xbc, hi: 0xbd},
+ // Block 0x6a, offset 0x21f
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8132, lo: 0xa0, hi: 0xa6},
+ {value: 0x812d, lo: 0xa7, hi: 0xad},
+ {value: 0x8132, lo: 0xae, hi: 0xaf},
+ // Block 0x6b, offset 0x223
+ {value: 0x0000, lo: 0x04},
+ {value: 0x8100, lo: 0x89, hi: 0x8c},
+ {value: 0x8100, lo: 0xb0, hi: 0xb2},
+ {value: 0x8100, lo: 0xb4, hi: 0xb4},
+ {value: 0x8100, lo: 0xb6, hi: 0xbf},
+ // Block 0x6c, offset 0x228
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0x81, hi: 0x8c},
+ // Block 0x6d, offset 0x22a
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0xb5, hi: 0xba},
+ // Block 0x6e, offset 0x22c
+ {value: 0x0000, lo: 0x04},
+ {value: 0x4a81, lo: 0x9e, hi: 0x9f},
+ {value: 0x4a81, lo: 0xa3, hi: 0xa3},
+ {value: 0x4a81, lo: 0xa5, hi: 0xa6},
+ {value: 0x4a81, lo: 0xaa, hi: 0xaf},
+ // Block 0x6f, offset 0x231
+ {value: 0x0000, lo: 0x05},
+ {value: 0x4a81, lo: 0x82, hi: 0x87},
+ {value: 0x4a81, lo: 0x8a, hi: 0x8f},
+ {value: 0x4a81, lo: 0x92, hi: 0x97},
+ {value: 0x4a81, lo: 0x9a, hi: 0x9c},
+ {value: 0x8100, lo: 0xa3, hi: 0xa3},
+ // Block 0x70, offset 0x237
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ // Block 0x71, offset 0x239
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xa0, hi: 0xa0},
+ // Block 0x72, offset 0x23b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb6, hi: 0xba},
+ // Block 0x73, offset 0x23d
+ {value: 0x002c, lo: 0x05},
+ {value: 0x812d, lo: 0x8d, hi: 0x8d},
+ {value: 0x8132, lo: 0x8f, hi: 0x8f},
+ {value: 0x8132, lo: 0xb8, hi: 0xb8},
+ {value: 0x8101, lo: 0xb9, hi: 0xba},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x74, offset 0x243
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0xa5, hi: 0xa5},
+ {value: 0x812d, lo: 0xa6, hi: 0xa6},
+ // Block 0x75, offset 0x246
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x86, hi: 0x86},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x76, offset 0x249
+ {value: 0x17fe, lo: 0x07},
+ {value: 0xa000, lo: 0x99, hi: 0x99},
+ {value: 0x4238, lo: 0x9a, hi: 0x9a},
+ {value: 0xa000, lo: 0x9b, hi: 0x9b},
+ {value: 0x4242, lo: 0x9c, hi: 0x9c},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x424c, lo: 0xab, hi: 0xab},
+ {value: 0x8104, lo: 0xb9, hi: 0xba},
+ // Block 0x77, offset 0x251
+ {value: 0x0000, lo: 0x06},
+ {value: 0x8132, lo: 0x80, hi: 0x82},
+ {value: 0x9900, lo: 0xa7, hi: 0xa7},
+ {value: 0x2d7e, lo: 0xae, hi: 0xae},
+ {value: 0x2d88, lo: 0xaf, hi: 0xaf},
+ {value: 0xa000, lo: 0xb1, hi: 0xb2},
+ {value: 0x8104, lo: 0xb3, hi: 0xb4},
+ // Block 0x78, offset 0x258
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x80, hi: 0x80},
+ {value: 0x8102, lo: 0x8a, hi: 0x8a},
+ // Block 0x79, offset 0x25b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0xb5, hi: 0xb5},
+ {value: 0x8102, lo: 0xb6, hi: 0xb6},
+ // Block 0x7a, offset 0x25e
+ {value: 0x0002, lo: 0x01},
+ {value: 0x8102, lo: 0xa9, hi: 0xaa},
+ // Block 0x7b, offset 0x260
+ {value: 0x0000, lo: 0x07},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2d92, lo: 0x8b, hi: 0x8b},
+ {value: 0x2d9c, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ {value: 0x8132, lo: 0xa6, hi: 0xac},
+ {value: 0x8132, lo: 0xb0, hi: 0xb4},
+ // Block 0x7c, offset 0x268
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x82, hi: 0x82},
+ {value: 0x8102, lo: 0x86, hi: 0x86},
+ // Block 0x7d, offset 0x26b
+ {value: 0x6b5a, lo: 0x06},
+ {value: 0x9900, lo: 0xb0, hi: 0xb0},
+ {value: 0xa000, lo: 0xb9, hi: 0xb9},
+ {value: 0x9900, lo: 0xba, hi: 0xba},
+ {value: 0x2db0, lo: 0xbb, hi: 0xbb},
+ {value: 0x2da6, lo: 0xbc, hi: 0xbd},
+ {value: 0x2dba, lo: 0xbe, hi: 0xbe},
+ // Block 0x7e, offset 0x272
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x82, hi: 0x82},
+ {value: 0x8102, lo: 0x83, hi: 0x83},
+ // Block 0x7f, offset 0x275
+ {value: 0x0000, lo: 0x05},
+ {value: 0x9900, lo: 0xaf, hi: 0xaf},
+ {value: 0xa000, lo: 0xb8, hi: 0xb9},
+ {value: 0x2dc4, lo: 0xba, hi: 0xba},
+ {value: 0x2dce, lo: 0xbb, hi: 0xbb},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x80, offset 0x27b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0x80, hi: 0x80},
+ // Block 0x81, offset 0x27d
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0xb6, hi: 0xb6},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ // Block 0x82, offset 0x280
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xab, hi: 0xab},
+ // Block 0x83, offset 0x282
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8101, lo: 0xb0, hi: 0xb4},
+ // Block 0x84, offset 0x284
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb0, hi: 0xb6},
+ // Block 0x85, offset 0x286
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8101, lo: 0x9e, hi: 0x9e},
+ // Block 0x86, offset 0x288
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x4662, lo: 0x9e, hi: 0x9e},
+ {value: 0x466c, lo: 0x9f, hi: 0x9f},
+ {value: 0x46a0, lo: 0xa0, hi: 0xa0},
+ {value: 0x46ae, lo: 0xa1, hi: 0xa1},
+ {value: 0x46bc, lo: 0xa2, hi: 0xa2},
+ {value: 0x46ca, lo: 0xa3, hi: 0xa3},
+ {value: 0x46d8, lo: 0xa4, hi: 0xa4},
+ {value: 0x812b, lo: 0xa5, hi: 0xa6},
+ {value: 0x8101, lo: 0xa7, hi: 0xa9},
+ {value: 0x8130, lo: 0xad, hi: 0xad},
+ {value: 0x812b, lo: 0xae, hi: 0xb2},
+ {value: 0x812d, lo: 0xbb, hi: 0xbf},
+ // Block 0x87, offset 0x295
+ {value: 0x0000, lo: 0x09},
+ {value: 0x812d, lo: 0x80, hi: 0x82},
+ {value: 0x8132, lo: 0x85, hi: 0x89},
+ {value: 0x812d, lo: 0x8a, hi: 0x8b},
+ {value: 0x8132, lo: 0xaa, hi: 0xad},
+ {value: 0x4676, lo: 0xbb, hi: 0xbb},
+ {value: 0x4680, lo: 0xbc, hi: 0xbc},
+ {value: 0x46e6, lo: 0xbd, hi: 0xbd},
+ {value: 0x4702, lo: 0xbe, hi: 0xbe},
+ {value: 0x46f4, lo: 0xbf, hi: 0xbf},
+ // Block 0x88, offset 0x29f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x4710, lo: 0x80, hi: 0x80},
+ // Block 0x89, offset 0x2a1
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x82, hi: 0x84},
+ // Block 0x8a, offset 0x2a3
+ {value: 0x0000, lo: 0x05},
+ {value: 0x8132, lo: 0x80, hi: 0x86},
+ {value: 0x8132, lo: 0x88, hi: 0x98},
+ {value: 0x8132, lo: 0x9b, hi: 0xa1},
+ {value: 0x8132, lo: 0xa3, hi: 0xa4},
+ {value: 0x8132, lo: 0xa6, hi: 0xaa},
+ // Block 0x8b, offset 0x2a9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x90, hi: 0x96},
+ // Block 0x8c, offset 0x2ab
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x84, hi: 0x89},
+ {value: 0x8102, lo: 0x8a, hi: 0x8a},
+ // Block 0x8d, offset 0x2ae
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8100, lo: 0x93, hi: 0x93},
+}
+
+// lookup returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *nfkcTrie) lookup(s []byte) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return nfkcValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := nfkcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := nfkcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfkcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := nfkcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfkcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = nfkcIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *nfkcTrie) lookupUnsafe(s []byte) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return nfkcValues[c0]
+ }
+ i := nfkcIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = nfkcIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = nfkcIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// lookupString returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *nfkcTrie) lookupString(s string) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return nfkcValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := nfkcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := nfkcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfkcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := nfkcIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = nfkcIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = nfkcIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *nfkcTrie) lookupStringUnsafe(s string) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return nfkcValues[c0]
+ }
+ i := nfkcIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = nfkcIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = nfkcIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// nfkcTrie. Total size: 16994 bytes (16.60 KiB). Checksum: 146925fc21092b17.
+type nfkcTrie struct{}
+
+func newNfkcTrie(i int) *nfkcTrie {
+ return &nfkcTrie{}
+}
+
+// lookupValue determines the type of block n and looks up the value for b.
+func (t *nfkcTrie) lookupValue(n uint32, b byte) uint16 {
+ switch {
+ case n < 90:
+ return uint16(nfkcValues[n<<6+uint32(b)])
+ default:
+ n -= 90
+ return uint16(nfkcSparse.lookup(n, b))
+ }
+}
+
+// nfkcValues: 92 blocks, 5888 entries, 11776 bytes
+// The third block is the zero block.
+var nfkcValues = [5888]uint16{
+ // Block 0x0, offset 0x0
+ 0x3c: 0xa000, 0x3d: 0xa000, 0x3e: 0xa000,
+ // Block 0x1, offset 0x40
+ 0x41: 0xa000, 0x42: 0xa000, 0x43: 0xa000, 0x44: 0xa000, 0x45: 0xa000,
+ 0x46: 0xa000, 0x47: 0xa000, 0x48: 0xa000, 0x49: 0xa000, 0x4a: 0xa000, 0x4b: 0xa000,
+ 0x4c: 0xa000, 0x4d: 0xa000, 0x4e: 0xa000, 0x4f: 0xa000, 0x50: 0xa000,
+ 0x52: 0xa000, 0x53: 0xa000, 0x54: 0xa000, 0x55: 0xa000, 0x56: 0xa000, 0x57: 0xa000,
+ 0x58: 0xa000, 0x59: 0xa000, 0x5a: 0xa000,
+ 0x61: 0xa000, 0x62: 0xa000, 0x63: 0xa000,
+ 0x64: 0xa000, 0x65: 0xa000, 0x66: 0xa000, 0x67: 0xa000, 0x68: 0xa000, 0x69: 0xa000,
+ 0x6a: 0xa000, 0x6b: 0xa000, 0x6c: 0xa000, 0x6d: 0xa000, 0x6e: 0xa000, 0x6f: 0xa000,
+ 0x70: 0xa000, 0x72: 0xa000, 0x73: 0xa000, 0x74: 0xa000, 0x75: 0xa000,
+ 0x76: 0xa000, 0x77: 0xa000, 0x78: 0xa000, 0x79: 0xa000, 0x7a: 0xa000,
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc0: 0x2f6f, 0xc1: 0x2f74, 0xc2: 0x471e, 0xc3: 0x2f79, 0xc4: 0x472d, 0xc5: 0x4732,
+ 0xc6: 0xa000, 0xc7: 0x473c, 0xc8: 0x2fe2, 0xc9: 0x2fe7, 0xca: 0x4741, 0xcb: 0x2ffb,
+ 0xcc: 0x306e, 0xcd: 0x3073, 0xce: 0x3078, 0xcf: 0x4755, 0xd1: 0x3104,
+ 0xd2: 0x3127, 0xd3: 0x312c, 0xd4: 0x475f, 0xd5: 0x4764, 0xd6: 0x4773,
+ 0xd8: 0xa000, 0xd9: 0x31b3, 0xda: 0x31b8, 0xdb: 0x31bd, 0xdc: 0x47a5, 0xdd: 0x3235,
+ 0xe0: 0x327b, 0xe1: 0x3280, 0xe2: 0x47af, 0xe3: 0x3285,
+ 0xe4: 0x47be, 0xe5: 0x47c3, 0xe6: 0xa000, 0xe7: 0x47cd, 0xe8: 0x32ee, 0xe9: 0x32f3,
+ 0xea: 0x47d2, 0xeb: 0x3307, 0xec: 0x337f, 0xed: 0x3384, 0xee: 0x3389, 0xef: 0x47e6,
+ 0xf1: 0x3415, 0xf2: 0x3438, 0xf3: 0x343d, 0xf4: 0x47f0, 0xf5: 0x47f5,
+ 0xf6: 0x4804, 0xf8: 0xa000, 0xf9: 0x34c9, 0xfa: 0x34ce, 0xfb: 0x34d3,
+ 0xfc: 0x4836, 0xfd: 0x3550, 0xff: 0x3569,
+ // Block 0x4, offset 0x100
+ 0x100: 0x2f7e, 0x101: 0x328a, 0x102: 0x4723, 0x103: 0x47b4, 0x104: 0x2f9c, 0x105: 0x32a8,
+ 0x106: 0x2fb0, 0x107: 0x32bc, 0x108: 0x2fb5, 0x109: 0x32c1, 0x10a: 0x2fba, 0x10b: 0x32c6,
+ 0x10c: 0x2fbf, 0x10d: 0x32cb, 0x10e: 0x2fc9, 0x10f: 0x32d5,
+ 0x112: 0x4746, 0x113: 0x47d7, 0x114: 0x2ff1, 0x115: 0x32fd, 0x116: 0x2ff6, 0x117: 0x3302,
+ 0x118: 0x3014, 0x119: 0x3320, 0x11a: 0x3005, 0x11b: 0x3311, 0x11c: 0x302d, 0x11d: 0x3339,
+ 0x11e: 0x3037, 0x11f: 0x3343, 0x120: 0x303c, 0x121: 0x3348, 0x122: 0x3046, 0x123: 0x3352,
+ 0x124: 0x304b, 0x125: 0x3357, 0x128: 0x307d, 0x129: 0x338e,
+ 0x12a: 0x3082, 0x12b: 0x3393, 0x12c: 0x3087, 0x12d: 0x3398, 0x12e: 0x30aa, 0x12f: 0x33b6,
+ 0x130: 0x308c, 0x132: 0x195d, 0x133: 0x19e7, 0x134: 0x30b4, 0x135: 0x33c0,
+ 0x136: 0x30c8, 0x137: 0x33d9, 0x139: 0x30d2, 0x13a: 0x33e3, 0x13b: 0x30dc,
+ 0x13c: 0x33ed, 0x13d: 0x30d7, 0x13e: 0x33e8, 0x13f: 0x1bac,
+ // Block 0x5, offset 0x140
+ 0x140: 0x1c34, 0x143: 0x30ff, 0x144: 0x3410, 0x145: 0x3118,
+ 0x146: 0x3429, 0x147: 0x310e, 0x148: 0x341f, 0x149: 0x1c5c,
+ 0x14c: 0x4769, 0x14d: 0x47fa, 0x14e: 0x3131, 0x14f: 0x3442, 0x150: 0x313b, 0x151: 0x344c,
+ 0x154: 0x3159, 0x155: 0x346a, 0x156: 0x3172, 0x157: 0x3483,
+ 0x158: 0x3163, 0x159: 0x3474, 0x15a: 0x478c, 0x15b: 0x481d, 0x15c: 0x317c, 0x15d: 0x348d,
+ 0x15e: 0x318b, 0x15f: 0x349c, 0x160: 0x4791, 0x161: 0x4822, 0x162: 0x31a4, 0x163: 0x34ba,
+ 0x164: 0x3195, 0x165: 0x34ab, 0x168: 0x479b, 0x169: 0x482c,
+ 0x16a: 0x47a0, 0x16b: 0x4831, 0x16c: 0x31c2, 0x16d: 0x34d8, 0x16e: 0x31cc, 0x16f: 0x34e2,
+ 0x170: 0x31d1, 0x171: 0x34e7, 0x172: 0x31ef, 0x173: 0x3505, 0x174: 0x3212, 0x175: 0x3528,
+ 0x176: 0x323a, 0x177: 0x3555, 0x178: 0x324e, 0x179: 0x325d, 0x17a: 0x357d, 0x17b: 0x3267,
+ 0x17c: 0x3587, 0x17d: 0x326c, 0x17e: 0x358c, 0x17f: 0x00a7,
+ // Block 0x6, offset 0x180
+ 0x184: 0x2dee, 0x185: 0x2df4,
+ 0x186: 0x2dfa, 0x187: 0x1972, 0x188: 0x1975, 0x189: 0x1a08, 0x18a: 0x1987, 0x18b: 0x198a,
+ 0x18c: 0x1a3e, 0x18d: 0x2f88, 0x18e: 0x3294, 0x18f: 0x3096, 0x190: 0x33a2, 0x191: 0x3140,
+ 0x192: 0x3451, 0x193: 0x31d6, 0x194: 0x34ec, 0x195: 0x39cf, 0x196: 0x3b5e, 0x197: 0x39c8,
+ 0x198: 0x3b57, 0x199: 0x39d6, 0x19a: 0x3b65, 0x19b: 0x39c1, 0x19c: 0x3b50,
+ 0x19e: 0x38b0, 0x19f: 0x3a3f, 0x1a0: 0x38a9, 0x1a1: 0x3a38, 0x1a2: 0x35b3, 0x1a3: 0x35c5,
+ 0x1a6: 0x3041, 0x1a7: 0x334d, 0x1a8: 0x30be, 0x1a9: 0x33cf,
+ 0x1aa: 0x4782, 0x1ab: 0x4813, 0x1ac: 0x3990, 0x1ad: 0x3b1f, 0x1ae: 0x35d7, 0x1af: 0x35dd,
+ 0x1b0: 0x33c5, 0x1b1: 0x1942, 0x1b2: 0x1945, 0x1b3: 0x19cf, 0x1b4: 0x3028, 0x1b5: 0x3334,
+ 0x1b8: 0x30fa, 0x1b9: 0x340b, 0x1ba: 0x38b7, 0x1bb: 0x3a46,
+ 0x1bc: 0x35ad, 0x1bd: 0x35bf, 0x1be: 0x35b9, 0x1bf: 0x35cb,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x2f8d, 0x1c1: 0x3299, 0x1c2: 0x2f92, 0x1c3: 0x329e, 0x1c4: 0x300a, 0x1c5: 0x3316,
+ 0x1c6: 0x300f, 0x1c7: 0x331b, 0x1c8: 0x309b, 0x1c9: 0x33a7, 0x1ca: 0x30a0, 0x1cb: 0x33ac,
+ 0x1cc: 0x3145, 0x1cd: 0x3456, 0x1ce: 0x314a, 0x1cf: 0x345b, 0x1d0: 0x3168, 0x1d1: 0x3479,
+ 0x1d2: 0x316d, 0x1d3: 0x347e, 0x1d4: 0x31db, 0x1d5: 0x34f1, 0x1d6: 0x31e0, 0x1d7: 0x34f6,
+ 0x1d8: 0x3186, 0x1d9: 0x3497, 0x1da: 0x319f, 0x1db: 0x34b5,
+ 0x1de: 0x305a, 0x1df: 0x3366,
+ 0x1e6: 0x4728, 0x1e7: 0x47b9, 0x1e8: 0x4750, 0x1e9: 0x47e1,
+ 0x1ea: 0x395f, 0x1eb: 0x3aee, 0x1ec: 0x393c, 0x1ed: 0x3acb, 0x1ee: 0x476e, 0x1ef: 0x47ff,
+ 0x1f0: 0x3958, 0x1f1: 0x3ae7, 0x1f2: 0x3244, 0x1f3: 0x355f,
+ // Block 0x8, offset 0x200
+ 0x200: 0x9932, 0x201: 0x9932, 0x202: 0x9932, 0x203: 0x9932, 0x204: 0x9932, 0x205: 0x8132,
+ 0x206: 0x9932, 0x207: 0x9932, 0x208: 0x9932, 0x209: 0x9932, 0x20a: 0x9932, 0x20b: 0x9932,
+ 0x20c: 0x9932, 0x20d: 0x8132, 0x20e: 0x8132, 0x20f: 0x9932, 0x210: 0x8132, 0x211: 0x9932,
+ 0x212: 0x8132, 0x213: 0x9932, 0x214: 0x9932, 0x215: 0x8133, 0x216: 0x812d, 0x217: 0x812d,
+ 0x218: 0x812d, 0x219: 0x812d, 0x21a: 0x8133, 0x21b: 0x992b, 0x21c: 0x812d, 0x21d: 0x812d,
+ 0x21e: 0x812d, 0x21f: 0x812d, 0x220: 0x812d, 0x221: 0x8129, 0x222: 0x8129, 0x223: 0x992d,
+ 0x224: 0x992d, 0x225: 0x992d, 0x226: 0x992d, 0x227: 0x9929, 0x228: 0x9929, 0x229: 0x812d,
+ 0x22a: 0x812d, 0x22b: 0x812d, 0x22c: 0x812d, 0x22d: 0x992d, 0x22e: 0x992d, 0x22f: 0x812d,
+ 0x230: 0x992d, 0x231: 0x992d, 0x232: 0x812d, 0x233: 0x812d, 0x234: 0x8101, 0x235: 0x8101,
+ 0x236: 0x8101, 0x237: 0x8101, 0x238: 0x9901, 0x239: 0x812d, 0x23a: 0x812d, 0x23b: 0x812d,
+ 0x23c: 0x812d, 0x23d: 0x8132, 0x23e: 0x8132, 0x23f: 0x8132,
+ // Block 0x9, offset 0x240
+ 0x240: 0x4a44, 0x241: 0x4a49, 0x242: 0x9932, 0x243: 0x4a4e, 0x244: 0x4a53, 0x245: 0x9936,
+ 0x246: 0x8132, 0x247: 0x812d, 0x248: 0x812d, 0x249: 0x812d, 0x24a: 0x8132, 0x24b: 0x8132,
+ 0x24c: 0x8132, 0x24d: 0x812d, 0x24e: 0x812d, 0x250: 0x8132, 0x251: 0x8132,
+ 0x252: 0x8132, 0x253: 0x812d, 0x254: 0x812d, 0x255: 0x812d, 0x256: 0x812d, 0x257: 0x8132,
+ 0x258: 0x8133, 0x259: 0x812d, 0x25a: 0x812d, 0x25b: 0x8132, 0x25c: 0x8134, 0x25d: 0x8135,
+ 0x25e: 0x8135, 0x25f: 0x8134, 0x260: 0x8135, 0x261: 0x8135, 0x262: 0x8134, 0x263: 0x8132,
+ 0x264: 0x8132, 0x265: 0x8132, 0x266: 0x8132, 0x267: 0x8132, 0x268: 0x8132, 0x269: 0x8132,
+ 0x26a: 0x8132, 0x26b: 0x8132, 0x26c: 0x8132, 0x26d: 0x8132, 0x26e: 0x8132, 0x26f: 0x8132,
+ 0x274: 0x0170,
+ 0x27a: 0x42a5,
+ 0x27e: 0x0037,
+ // Block 0xa, offset 0x280
+ 0x284: 0x425a, 0x285: 0x4511,
+ 0x286: 0x35e9, 0x287: 0x00ce, 0x288: 0x3607, 0x289: 0x3613, 0x28a: 0x3625,
+ 0x28c: 0x3643, 0x28e: 0x3655, 0x28f: 0x3673, 0x290: 0x3e08, 0x291: 0xa000,
+ 0x295: 0xa000, 0x297: 0xa000,
+ 0x299: 0xa000,
+ 0x29f: 0xa000, 0x2a1: 0xa000,
+ 0x2a5: 0xa000, 0x2a9: 0xa000,
+ 0x2aa: 0x3637, 0x2ab: 0x3667, 0x2ac: 0x4894, 0x2ad: 0x3697, 0x2ae: 0x48be, 0x2af: 0x36a9,
+ 0x2b0: 0x3e70, 0x2b1: 0xa000, 0x2b5: 0xa000,
+ 0x2b7: 0xa000, 0x2b9: 0xa000,
+ 0x2bf: 0xa000,
+ // Block 0xb, offset 0x2c0
+ 0x2c1: 0xa000, 0x2c5: 0xa000,
+ 0x2c9: 0xa000, 0x2ca: 0x48d6, 0x2cb: 0x48f4,
+ 0x2cc: 0x36c7, 0x2cd: 0x36df, 0x2ce: 0x490c, 0x2d0: 0x01be, 0x2d1: 0x01d0,
+ 0x2d2: 0x01ac, 0x2d3: 0x43a2, 0x2d4: 0x43a8, 0x2d5: 0x01fa, 0x2d6: 0x01e8,
+ 0x2f0: 0x01d6, 0x2f1: 0x01eb, 0x2f2: 0x01ee, 0x2f4: 0x0188, 0x2f5: 0x01c7,
+ 0x2f9: 0x01a6,
+ // Block 0xc, offset 0x300
+ 0x300: 0x3721, 0x301: 0x372d, 0x303: 0x371b,
+ 0x306: 0xa000, 0x307: 0x3709,
+ 0x30c: 0x375d, 0x30d: 0x3745, 0x30e: 0x376f, 0x310: 0xa000,
+ 0x313: 0xa000, 0x315: 0xa000, 0x316: 0xa000, 0x317: 0xa000,
+ 0x318: 0xa000, 0x319: 0x3751, 0x31a: 0xa000,
+ 0x31e: 0xa000, 0x323: 0xa000,
+ 0x327: 0xa000,
+ 0x32b: 0xa000, 0x32d: 0xa000,
+ 0x330: 0xa000, 0x333: 0xa000, 0x335: 0xa000,
+ 0x336: 0xa000, 0x337: 0xa000, 0x338: 0xa000, 0x339: 0x37d5, 0x33a: 0xa000,
+ 0x33e: 0xa000,
+ // Block 0xd, offset 0x340
+ 0x341: 0x3733, 0x342: 0x37b7,
+ 0x350: 0x370f, 0x351: 0x3793,
+ 0x352: 0x3715, 0x353: 0x3799, 0x356: 0x3727, 0x357: 0x37ab,
+ 0x358: 0xa000, 0x359: 0xa000, 0x35a: 0x3829, 0x35b: 0x382f, 0x35c: 0x3739, 0x35d: 0x37bd,
+ 0x35e: 0x373f, 0x35f: 0x37c3, 0x362: 0x374b, 0x363: 0x37cf,
+ 0x364: 0x3757, 0x365: 0x37db, 0x366: 0x3763, 0x367: 0x37e7, 0x368: 0xa000, 0x369: 0xa000,
+ 0x36a: 0x3835, 0x36b: 0x383b, 0x36c: 0x378d, 0x36d: 0x3811, 0x36e: 0x3769, 0x36f: 0x37ed,
+ 0x370: 0x3775, 0x371: 0x37f9, 0x372: 0x377b, 0x373: 0x37ff, 0x374: 0x3781, 0x375: 0x3805,
+ 0x378: 0x3787, 0x379: 0x380b,
+ // Block 0xe, offset 0x380
+ 0x387: 0x1d61,
+ 0x391: 0x812d,
+ 0x392: 0x8132, 0x393: 0x8132, 0x394: 0x8132, 0x395: 0x8132, 0x396: 0x812d, 0x397: 0x8132,
+ 0x398: 0x8132, 0x399: 0x8132, 0x39a: 0x812e, 0x39b: 0x812d, 0x39c: 0x8132, 0x39d: 0x8132,
+ 0x39e: 0x8132, 0x39f: 0x8132, 0x3a0: 0x8132, 0x3a1: 0x8132, 0x3a2: 0x812d, 0x3a3: 0x812d,
+ 0x3a4: 0x812d, 0x3a5: 0x812d, 0x3a6: 0x812d, 0x3a7: 0x812d, 0x3a8: 0x8132, 0x3a9: 0x8132,
+ 0x3aa: 0x812d, 0x3ab: 0x8132, 0x3ac: 0x8132, 0x3ad: 0x812e, 0x3ae: 0x8131, 0x3af: 0x8132,
+ 0x3b0: 0x8105, 0x3b1: 0x8106, 0x3b2: 0x8107, 0x3b3: 0x8108, 0x3b4: 0x8109, 0x3b5: 0x810a,
+ 0x3b6: 0x810b, 0x3b7: 0x810c, 0x3b8: 0x810d, 0x3b9: 0x810e, 0x3ba: 0x810e, 0x3bb: 0x810f,
+ 0x3bc: 0x8110, 0x3bd: 0x8111, 0x3bf: 0x8112,
+ // Block 0xf, offset 0x3c0
+ 0x3c8: 0xa000, 0x3ca: 0xa000, 0x3cb: 0x8116,
+ 0x3cc: 0x8117, 0x3cd: 0x8118, 0x3ce: 0x8119, 0x3cf: 0x811a, 0x3d0: 0x811b, 0x3d1: 0x811c,
+ 0x3d2: 0x811d, 0x3d3: 0x9932, 0x3d4: 0x9932, 0x3d5: 0x992d, 0x3d6: 0x812d, 0x3d7: 0x8132,
+ 0x3d8: 0x8132, 0x3d9: 0x8132, 0x3da: 0x8132, 0x3db: 0x8132, 0x3dc: 0x812d, 0x3dd: 0x8132,
+ 0x3de: 0x8132, 0x3df: 0x812d,
+ 0x3f0: 0x811e, 0x3f5: 0x1d84,
+ 0x3f6: 0x2013, 0x3f7: 0x204f, 0x3f8: 0x204a,
+ // Block 0x10, offset 0x400
+ 0x405: 0xa000,
+ 0x406: 0x2d26, 0x407: 0xa000, 0x408: 0x2d2e, 0x409: 0xa000, 0x40a: 0x2d36, 0x40b: 0xa000,
+ 0x40c: 0x2d3e, 0x40d: 0xa000, 0x40e: 0x2d46, 0x411: 0xa000,
+ 0x412: 0x2d4e,
+ 0x434: 0x8102, 0x435: 0x9900,
+ 0x43a: 0xa000, 0x43b: 0x2d56,
+ 0x43c: 0xa000, 0x43d: 0x2d5e, 0x43e: 0xa000, 0x43f: 0xa000,
+ // Block 0x11, offset 0x440
+ 0x440: 0x0069, 0x441: 0x006b, 0x442: 0x006f, 0x443: 0x0083, 0x444: 0x00f5, 0x445: 0x00f8,
+ 0x446: 0x0413, 0x447: 0x0085, 0x448: 0x0089, 0x449: 0x008b, 0x44a: 0x0104, 0x44b: 0x0107,
+ 0x44c: 0x010a, 0x44d: 0x008f, 0x44f: 0x0097, 0x450: 0x009b, 0x451: 0x00e0,
+ 0x452: 0x009f, 0x453: 0x00fe, 0x454: 0x0417, 0x455: 0x041b, 0x456: 0x00a1, 0x457: 0x00a9,
+ 0x458: 0x00ab, 0x459: 0x0423, 0x45a: 0x012b, 0x45b: 0x00ad, 0x45c: 0x0427, 0x45d: 0x01be,
+ 0x45e: 0x01c1, 0x45f: 0x01c4, 0x460: 0x01fa, 0x461: 0x01fd, 0x462: 0x0093, 0x463: 0x00a5,
+ 0x464: 0x00ab, 0x465: 0x00ad, 0x466: 0x01be, 0x467: 0x01c1, 0x468: 0x01eb, 0x469: 0x01fa,
+ 0x46a: 0x01fd,
+ 0x478: 0x020c,
+ // Block 0x12, offset 0x480
+ 0x49b: 0x00fb, 0x49c: 0x0087, 0x49d: 0x0101,
+ 0x49e: 0x00d4, 0x49f: 0x010a, 0x4a0: 0x008d, 0x4a1: 0x010d, 0x4a2: 0x0110, 0x4a3: 0x0116,
+ 0x4a4: 0x011c, 0x4a5: 0x011f, 0x4a6: 0x0122, 0x4a7: 0x042b, 0x4a8: 0x016a, 0x4a9: 0x0128,
+ 0x4aa: 0x042f, 0x4ab: 0x016d, 0x4ac: 0x0131, 0x4ad: 0x012e, 0x4ae: 0x0134, 0x4af: 0x0137,
+ 0x4b0: 0x013a, 0x4b1: 0x013d, 0x4b2: 0x0140, 0x4b3: 0x014c, 0x4b4: 0x014f, 0x4b5: 0x00ec,
+ 0x4b6: 0x0152, 0x4b7: 0x0155, 0x4b8: 0x041f, 0x4b9: 0x0158, 0x4ba: 0x015b, 0x4bb: 0x00b5,
+ 0x4bc: 0x015e, 0x4bd: 0x0161, 0x4be: 0x0164, 0x4bf: 0x01d0,
+ // Block 0x13, offset 0x4c0
+ 0x4c0: 0x2f97, 0x4c1: 0x32a3, 0x4c2: 0x2fa1, 0x4c3: 0x32ad, 0x4c4: 0x2fa6, 0x4c5: 0x32b2,
+ 0x4c6: 0x2fab, 0x4c7: 0x32b7, 0x4c8: 0x38cc, 0x4c9: 0x3a5b, 0x4ca: 0x2fc4, 0x4cb: 0x32d0,
+ 0x4cc: 0x2fce, 0x4cd: 0x32da, 0x4ce: 0x2fdd, 0x4cf: 0x32e9, 0x4d0: 0x2fd3, 0x4d1: 0x32df,
+ 0x4d2: 0x2fd8, 0x4d3: 0x32e4, 0x4d4: 0x38ef, 0x4d5: 0x3a7e, 0x4d6: 0x38f6, 0x4d7: 0x3a85,
+ 0x4d8: 0x3019, 0x4d9: 0x3325, 0x4da: 0x301e, 0x4db: 0x332a, 0x4dc: 0x3904, 0x4dd: 0x3a93,
+ 0x4de: 0x3023, 0x4df: 0x332f, 0x4e0: 0x3032, 0x4e1: 0x333e, 0x4e2: 0x3050, 0x4e3: 0x335c,
+ 0x4e4: 0x305f, 0x4e5: 0x336b, 0x4e6: 0x3055, 0x4e7: 0x3361, 0x4e8: 0x3064, 0x4e9: 0x3370,
+ 0x4ea: 0x3069, 0x4eb: 0x3375, 0x4ec: 0x30af, 0x4ed: 0x33bb, 0x4ee: 0x390b, 0x4ef: 0x3a9a,
+ 0x4f0: 0x30b9, 0x4f1: 0x33ca, 0x4f2: 0x30c3, 0x4f3: 0x33d4, 0x4f4: 0x30cd, 0x4f5: 0x33de,
+ 0x4f6: 0x475a, 0x4f7: 0x47eb, 0x4f8: 0x3912, 0x4f9: 0x3aa1, 0x4fa: 0x30e6, 0x4fb: 0x33f7,
+ 0x4fc: 0x30e1, 0x4fd: 0x33f2, 0x4fe: 0x30eb, 0x4ff: 0x33fc,
+ // Block 0x14, offset 0x500
+ 0x500: 0x30f0, 0x501: 0x3401, 0x502: 0x30f5, 0x503: 0x3406, 0x504: 0x3109, 0x505: 0x341a,
+ 0x506: 0x3113, 0x507: 0x3424, 0x508: 0x3122, 0x509: 0x3433, 0x50a: 0x311d, 0x50b: 0x342e,
+ 0x50c: 0x3935, 0x50d: 0x3ac4, 0x50e: 0x3943, 0x50f: 0x3ad2, 0x510: 0x394a, 0x511: 0x3ad9,
+ 0x512: 0x3951, 0x513: 0x3ae0, 0x514: 0x314f, 0x515: 0x3460, 0x516: 0x3154, 0x517: 0x3465,
+ 0x518: 0x315e, 0x519: 0x346f, 0x51a: 0x4787, 0x51b: 0x4818, 0x51c: 0x3997, 0x51d: 0x3b26,
+ 0x51e: 0x3177, 0x51f: 0x3488, 0x520: 0x3181, 0x521: 0x3492, 0x522: 0x4796, 0x523: 0x4827,
+ 0x524: 0x399e, 0x525: 0x3b2d, 0x526: 0x39a5, 0x527: 0x3b34, 0x528: 0x39ac, 0x529: 0x3b3b,
+ 0x52a: 0x3190, 0x52b: 0x34a1, 0x52c: 0x319a, 0x52d: 0x34b0, 0x52e: 0x31ae, 0x52f: 0x34c4,
+ 0x530: 0x31a9, 0x531: 0x34bf, 0x532: 0x31ea, 0x533: 0x3500, 0x534: 0x31f9, 0x535: 0x350f,
+ 0x536: 0x31f4, 0x537: 0x350a, 0x538: 0x39b3, 0x539: 0x3b42, 0x53a: 0x39ba, 0x53b: 0x3b49,
+ 0x53c: 0x31fe, 0x53d: 0x3514, 0x53e: 0x3203, 0x53f: 0x3519,
+ // Block 0x15, offset 0x540
+ 0x540: 0x3208, 0x541: 0x351e, 0x542: 0x320d, 0x543: 0x3523, 0x544: 0x321c, 0x545: 0x3532,
+ 0x546: 0x3217, 0x547: 0x352d, 0x548: 0x3221, 0x549: 0x353c, 0x54a: 0x3226, 0x54b: 0x3541,
+ 0x54c: 0x322b, 0x54d: 0x3546, 0x54e: 0x3249, 0x54f: 0x3564, 0x550: 0x3262, 0x551: 0x3582,
+ 0x552: 0x3271, 0x553: 0x3591, 0x554: 0x3276, 0x555: 0x3596, 0x556: 0x337a, 0x557: 0x34a6,
+ 0x558: 0x3537, 0x559: 0x3573, 0x55a: 0x1be0, 0x55b: 0x42d7,
+ 0x560: 0x4737, 0x561: 0x47c8, 0x562: 0x2f83, 0x563: 0x328f,
+ 0x564: 0x3878, 0x565: 0x3a07, 0x566: 0x3871, 0x567: 0x3a00, 0x568: 0x3886, 0x569: 0x3a15,
+ 0x56a: 0x387f, 0x56b: 0x3a0e, 0x56c: 0x38be, 0x56d: 0x3a4d, 0x56e: 0x3894, 0x56f: 0x3a23,
+ 0x570: 0x388d, 0x571: 0x3a1c, 0x572: 0x38a2, 0x573: 0x3a31, 0x574: 0x389b, 0x575: 0x3a2a,
+ 0x576: 0x38c5, 0x577: 0x3a54, 0x578: 0x474b, 0x579: 0x47dc, 0x57a: 0x3000, 0x57b: 0x330c,
+ 0x57c: 0x2fec, 0x57d: 0x32f8, 0x57e: 0x38da, 0x57f: 0x3a69,
+ // Block 0x16, offset 0x580
+ 0x580: 0x38d3, 0x581: 0x3a62, 0x582: 0x38e8, 0x583: 0x3a77, 0x584: 0x38e1, 0x585: 0x3a70,
+ 0x586: 0x38fd, 0x587: 0x3a8c, 0x588: 0x3091, 0x589: 0x339d, 0x58a: 0x30a5, 0x58b: 0x33b1,
+ 0x58c: 0x477d, 0x58d: 0x480e, 0x58e: 0x3136, 0x58f: 0x3447, 0x590: 0x3920, 0x591: 0x3aaf,
+ 0x592: 0x3919, 0x593: 0x3aa8, 0x594: 0x392e, 0x595: 0x3abd, 0x596: 0x3927, 0x597: 0x3ab6,
+ 0x598: 0x3989, 0x599: 0x3b18, 0x59a: 0x396d, 0x59b: 0x3afc, 0x59c: 0x3966, 0x59d: 0x3af5,
+ 0x59e: 0x397b, 0x59f: 0x3b0a, 0x5a0: 0x3974, 0x5a1: 0x3b03, 0x5a2: 0x3982, 0x5a3: 0x3b11,
+ 0x5a4: 0x31e5, 0x5a5: 0x34fb, 0x5a6: 0x31c7, 0x5a7: 0x34dd, 0x5a8: 0x39e4, 0x5a9: 0x3b73,
+ 0x5aa: 0x39dd, 0x5ab: 0x3b6c, 0x5ac: 0x39f2, 0x5ad: 0x3b81, 0x5ae: 0x39eb, 0x5af: 0x3b7a,
+ 0x5b0: 0x39f9, 0x5b1: 0x3b88, 0x5b2: 0x3230, 0x5b3: 0x354b, 0x5b4: 0x3258, 0x5b5: 0x3578,
+ 0x5b6: 0x3253, 0x5b7: 0x356e, 0x5b8: 0x323f, 0x5b9: 0x355a,
+ // Block 0x17, offset 0x5c0
+ 0x5c0: 0x489a, 0x5c1: 0x48a0, 0x5c2: 0x49b4, 0x5c3: 0x49cc, 0x5c4: 0x49bc, 0x5c5: 0x49d4,
+ 0x5c6: 0x49c4, 0x5c7: 0x49dc, 0x5c8: 0x4840, 0x5c9: 0x4846, 0x5ca: 0x4924, 0x5cb: 0x493c,
+ 0x5cc: 0x492c, 0x5cd: 0x4944, 0x5ce: 0x4934, 0x5cf: 0x494c, 0x5d0: 0x48ac, 0x5d1: 0x48b2,
+ 0x5d2: 0x3db8, 0x5d3: 0x3dc8, 0x5d4: 0x3dc0, 0x5d5: 0x3dd0,
+ 0x5d8: 0x484c, 0x5d9: 0x4852, 0x5da: 0x3ce8, 0x5db: 0x3cf8, 0x5dc: 0x3cf0, 0x5dd: 0x3d00,
+ 0x5e0: 0x48c4, 0x5e1: 0x48ca, 0x5e2: 0x49e4, 0x5e3: 0x49fc,
+ 0x5e4: 0x49ec, 0x5e5: 0x4a04, 0x5e6: 0x49f4, 0x5e7: 0x4a0c, 0x5e8: 0x4858, 0x5e9: 0x485e,
+ 0x5ea: 0x4954, 0x5eb: 0x496c, 0x5ec: 0x495c, 0x5ed: 0x4974, 0x5ee: 0x4964, 0x5ef: 0x497c,
+ 0x5f0: 0x48dc, 0x5f1: 0x48e2, 0x5f2: 0x3e18, 0x5f3: 0x3e30, 0x5f4: 0x3e20, 0x5f5: 0x3e38,
+ 0x5f6: 0x3e28, 0x5f7: 0x3e40, 0x5f8: 0x4864, 0x5f9: 0x486a, 0x5fa: 0x3d18, 0x5fb: 0x3d30,
+ 0x5fc: 0x3d20, 0x5fd: 0x3d38, 0x5fe: 0x3d28, 0x5ff: 0x3d40,
+ // Block 0x18, offset 0x600
+ 0x600: 0x48e8, 0x601: 0x48ee, 0x602: 0x3e48, 0x603: 0x3e58, 0x604: 0x3e50, 0x605: 0x3e60,
+ 0x608: 0x4870, 0x609: 0x4876, 0x60a: 0x3d48, 0x60b: 0x3d58,
+ 0x60c: 0x3d50, 0x60d: 0x3d60, 0x610: 0x48fa, 0x611: 0x4900,
+ 0x612: 0x3e80, 0x613: 0x3e98, 0x614: 0x3e88, 0x615: 0x3ea0, 0x616: 0x3e90, 0x617: 0x3ea8,
+ 0x619: 0x487c, 0x61b: 0x3d68, 0x61d: 0x3d70,
+ 0x61f: 0x3d78, 0x620: 0x4912, 0x621: 0x4918, 0x622: 0x4a14, 0x623: 0x4a2c,
+ 0x624: 0x4a1c, 0x625: 0x4a34, 0x626: 0x4a24, 0x627: 0x4a3c, 0x628: 0x4882, 0x629: 0x4888,
+ 0x62a: 0x4984, 0x62b: 0x499c, 0x62c: 0x498c, 0x62d: 0x49a4, 0x62e: 0x4994, 0x62f: 0x49ac,
+ 0x630: 0x488e, 0x631: 0x43b4, 0x632: 0x3691, 0x633: 0x43ba, 0x634: 0x48b8, 0x635: 0x43c0,
+ 0x636: 0x36a3, 0x637: 0x43c6, 0x638: 0x36c1, 0x639: 0x43cc, 0x63a: 0x36d9, 0x63b: 0x43d2,
+ 0x63c: 0x4906, 0x63d: 0x43d8,
+ // Block 0x19, offset 0x640
+ 0x640: 0x3da0, 0x641: 0x3da8, 0x642: 0x4184, 0x643: 0x41a2, 0x644: 0x418e, 0x645: 0x41ac,
+ 0x646: 0x4198, 0x647: 0x41b6, 0x648: 0x3cd8, 0x649: 0x3ce0, 0x64a: 0x40d0, 0x64b: 0x40ee,
+ 0x64c: 0x40da, 0x64d: 0x40f8, 0x64e: 0x40e4, 0x64f: 0x4102, 0x650: 0x3de8, 0x651: 0x3df0,
+ 0x652: 0x41c0, 0x653: 0x41de, 0x654: 0x41ca, 0x655: 0x41e8, 0x656: 0x41d4, 0x657: 0x41f2,
+ 0x658: 0x3d08, 0x659: 0x3d10, 0x65a: 0x410c, 0x65b: 0x412a, 0x65c: 0x4116, 0x65d: 0x4134,
+ 0x65e: 0x4120, 0x65f: 0x413e, 0x660: 0x3ec0, 0x661: 0x3ec8, 0x662: 0x41fc, 0x663: 0x421a,
+ 0x664: 0x4206, 0x665: 0x4224, 0x666: 0x4210, 0x667: 0x422e, 0x668: 0x3d80, 0x669: 0x3d88,
+ 0x66a: 0x4148, 0x66b: 0x4166, 0x66c: 0x4152, 0x66d: 0x4170, 0x66e: 0x415c, 0x66f: 0x417a,
+ 0x670: 0x3685, 0x671: 0x367f, 0x672: 0x3d90, 0x673: 0x368b, 0x674: 0x3d98,
+ 0x676: 0x48a6, 0x677: 0x3db0, 0x678: 0x35f5, 0x679: 0x35ef, 0x67a: 0x35e3, 0x67b: 0x4384,
+ 0x67c: 0x35fb, 0x67d: 0x4287, 0x67e: 0x01d3, 0x67f: 0x4287,
+ // Block 0x1a, offset 0x680
+ 0x680: 0x42a0, 0x681: 0x4518, 0x682: 0x3dd8, 0x683: 0x369d, 0x684: 0x3de0,
+ 0x686: 0x48d0, 0x687: 0x3df8, 0x688: 0x3601, 0x689: 0x438a, 0x68a: 0x360d, 0x68b: 0x4390,
+ 0x68c: 0x3619, 0x68d: 0x451f, 0x68e: 0x4526, 0x68f: 0x452d, 0x690: 0x36b5, 0x691: 0x36af,
+ 0x692: 0x3e00, 0x693: 0x457a, 0x696: 0x36bb, 0x697: 0x3e10,
+ 0x698: 0x3631, 0x699: 0x362b, 0x69a: 0x361f, 0x69b: 0x4396, 0x69d: 0x4534,
+ 0x69e: 0x453b, 0x69f: 0x4542, 0x6a0: 0x36eb, 0x6a1: 0x36e5, 0x6a2: 0x3e68, 0x6a3: 0x4582,
+ 0x6a4: 0x36cd, 0x6a5: 0x36d3, 0x6a6: 0x36f1, 0x6a7: 0x3e78, 0x6a8: 0x3661, 0x6a9: 0x365b,
+ 0x6aa: 0x364f, 0x6ab: 0x43a2, 0x6ac: 0x3649, 0x6ad: 0x450a, 0x6ae: 0x4511, 0x6af: 0x0081,
+ 0x6b2: 0x3eb0, 0x6b3: 0x36f7, 0x6b4: 0x3eb8,
+ 0x6b6: 0x491e, 0x6b7: 0x3ed0, 0x6b8: 0x363d, 0x6b9: 0x439c, 0x6ba: 0x366d, 0x6bb: 0x43ae,
+ 0x6bc: 0x3679, 0x6bd: 0x425a, 0x6be: 0x428c,
+ // Block 0x1b, offset 0x6c0
+ 0x6c0: 0x1bd8, 0x6c1: 0x1bdc, 0x6c2: 0x0047, 0x6c3: 0x1c54, 0x6c5: 0x1be8,
+ 0x6c6: 0x1bec, 0x6c7: 0x00e9, 0x6c9: 0x1c58, 0x6ca: 0x008f, 0x6cb: 0x0051,
+ 0x6cc: 0x0051, 0x6cd: 0x0051, 0x6ce: 0x0091, 0x6cf: 0x00da, 0x6d0: 0x0053, 0x6d1: 0x0053,
+ 0x6d2: 0x0059, 0x6d3: 0x0099, 0x6d5: 0x005d, 0x6d6: 0x198d,
+ 0x6d9: 0x0061, 0x6da: 0x0063, 0x6db: 0x0065, 0x6dc: 0x0065, 0x6dd: 0x0065,
+ 0x6e0: 0x199f, 0x6e1: 0x1bc8, 0x6e2: 0x19a8,
+ 0x6e4: 0x0075, 0x6e6: 0x01b8, 0x6e8: 0x0075,
+ 0x6ea: 0x0057, 0x6eb: 0x42d2, 0x6ec: 0x0045, 0x6ed: 0x0047, 0x6ef: 0x008b,
+ 0x6f0: 0x004b, 0x6f1: 0x004d, 0x6f3: 0x005b, 0x6f4: 0x009f, 0x6f5: 0x0215,
+ 0x6f6: 0x0218, 0x6f7: 0x021b, 0x6f8: 0x021e, 0x6f9: 0x0093, 0x6fb: 0x1b98,
+ 0x6fc: 0x01e8, 0x6fd: 0x01c1, 0x6fe: 0x0179, 0x6ff: 0x01a0,
+ // Block 0x1c, offset 0x700
+ 0x700: 0x0463, 0x705: 0x0049,
+ 0x706: 0x0089, 0x707: 0x008b, 0x708: 0x0093, 0x709: 0x0095,
+ 0x710: 0x222e, 0x711: 0x223a,
+ 0x712: 0x22ee, 0x713: 0x2216, 0x714: 0x229a, 0x715: 0x2222, 0x716: 0x22a0, 0x717: 0x22b8,
+ 0x718: 0x22c4, 0x719: 0x2228, 0x71a: 0x22ca, 0x71b: 0x2234, 0x71c: 0x22be, 0x71d: 0x22d0,
+ 0x71e: 0x22d6, 0x71f: 0x1cbc, 0x720: 0x0053, 0x721: 0x195a, 0x722: 0x1ba4, 0x723: 0x1963,
+ 0x724: 0x006d, 0x725: 0x19ab, 0x726: 0x1bd0, 0x727: 0x1d48, 0x728: 0x1966, 0x729: 0x0071,
+ 0x72a: 0x19b7, 0x72b: 0x1bd4, 0x72c: 0x0059, 0x72d: 0x0047, 0x72e: 0x0049, 0x72f: 0x005b,
+ 0x730: 0x0093, 0x731: 0x19e4, 0x732: 0x1c18, 0x733: 0x19ed, 0x734: 0x00ad, 0x735: 0x1a62,
+ 0x736: 0x1c4c, 0x737: 0x1d5c, 0x738: 0x19f0, 0x739: 0x00b1, 0x73a: 0x1a65, 0x73b: 0x1c50,
+ 0x73c: 0x0099, 0x73d: 0x0087, 0x73e: 0x0089, 0x73f: 0x009b,
+ // Block 0x1d, offset 0x740
+ 0x741: 0x3c06, 0x743: 0xa000, 0x744: 0x3c0d, 0x745: 0xa000,
+ 0x747: 0x3c14, 0x748: 0xa000, 0x749: 0x3c1b,
+ 0x74d: 0xa000,
+ 0x760: 0x2f65, 0x761: 0xa000, 0x762: 0x3c29,
+ 0x764: 0xa000, 0x765: 0xa000,
+ 0x76d: 0x3c22, 0x76e: 0x2f60, 0x76f: 0x2f6a,
+ 0x770: 0x3c30, 0x771: 0x3c37, 0x772: 0xa000, 0x773: 0xa000, 0x774: 0x3c3e, 0x775: 0x3c45,
+ 0x776: 0xa000, 0x777: 0xa000, 0x778: 0x3c4c, 0x779: 0x3c53, 0x77a: 0xa000, 0x77b: 0xa000,
+ 0x77c: 0xa000, 0x77d: 0xa000,
+ // Block 0x1e, offset 0x780
+ 0x780: 0x3c5a, 0x781: 0x3c61, 0x782: 0xa000, 0x783: 0xa000, 0x784: 0x3c76, 0x785: 0x3c7d,
+ 0x786: 0xa000, 0x787: 0xa000, 0x788: 0x3c84, 0x789: 0x3c8b,
+ 0x791: 0xa000,
+ 0x792: 0xa000,
+ 0x7a2: 0xa000,
+ 0x7a8: 0xa000, 0x7a9: 0xa000,
+ 0x7ab: 0xa000, 0x7ac: 0x3ca0, 0x7ad: 0x3ca7, 0x7ae: 0x3cae, 0x7af: 0x3cb5,
+ 0x7b2: 0xa000, 0x7b3: 0xa000, 0x7b4: 0xa000, 0x7b5: 0xa000,
+ // Block 0x1f, offset 0x7c0
+ 0x7e0: 0x0023, 0x7e1: 0x0025, 0x7e2: 0x0027, 0x7e3: 0x0029,
+ 0x7e4: 0x002b, 0x7e5: 0x002d, 0x7e6: 0x002f, 0x7e7: 0x0031, 0x7e8: 0x0033, 0x7e9: 0x1882,
+ 0x7ea: 0x1885, 0x7eb: 0x1888, 0x7ec: 0x188b, 0x7ed: 0x188e, 0x7ee: 0x1891, 0x7ef: 0x1894,
+ 0x7f0: 0x1897, 0x7f1: 0x189a, 0x7f2: 0x189d, 0x7f3: 0x18a6, 0x7f4: 0x1a68, 0x7f5: 0x1a6c,
+ 0x7f6: 0x1a70, 0x7f7: 0x1a74, 0x7f8: 0x1a78, 0x7f9: 0x1a7c, 0x7fa: 0x1a80, 0x7fb: 0x1a84,
+ 0x7fc: 0x1a88, 0x7fd: 0x1c80, 0x7fe: 0x1c85, 0x7ff: 0x1c8a,
+ // Block 0x20, offset 0x800
+ 0x800: 0x1c8f, 0x801: 0x1c94, 0x802: 0x1c99, 0x803: 0x1c9e, 0x804: 0x1ca3, 0x805: 0x1ca8,
+ 0x806: 0x1cad, 0x807: 0x1cb2, 0x808: 0x187f, 0x809: 0x18a3, 0x80a: 0x18c7, 0x80b: 0x18eb,
+ 0x80c: 0x190f, 0x80d: 0x1918, 0x80e: 0x191e, 0x80f: 0x1924, 0x810: 0x192a, 0x811: 0x1b60,
+ 0x812: 0x1b64, 0x813: 0x1b68, 0x814: 0x1b6c, 0x815: 0x1b70, 0x816: 0x1b74, 0x817: 0x1b78,
+ 0x818: 0x1b7c, 0x819: 0x1b80, 0x81a: 0x1b84, 0x81b: 0x1b88, 0x81c: 0x1af4, 0x81d: 0x1af8,
+ 0x81e: 0x1afc, 0x81f: 0x1b00, 0x820: 0x1b04, 0x821: 0x1b08, 0x822: 0x1b0c, 0x823: 0x1b10,
+ 0x824: 0x1b14, 0x825: 0x1b18, 0x826: 0x1b1c, 0x827: 0x1b20, 0x828: 0x1b24, 0x829: 0x1b28,
+ 0x82a: 0x1b2c, 0x82b: 0x1b30, 0x82c: 0x1b34, 0x82d: 0x1b38, 0x82e: 0x1b3c, 0x82f: 0x1b40,
+ 0x830: 0x1b44, 0x831: 0x1b48, 0x832: 0x1b4c, 0x833: 0x1b50, 0x834: 0x1b54, 0x835: 0x1b58,
+ 0x836: 0x0043, 0x837: 0x0045, 0x838: 0x0047, 0x839: 0x0049, 0x83a: 0x004b, 0x83b: 0x004d,
+ 0x83c: 0x004f, 0x83d: 0x0051, 0x83e: 0x0053, 0x83f: 0x0055,
+ // Block 0x21, offset 0x840
+ 0x840: 0x06bf, 0x841: 0x06e3, 0x842: 0x06ef, 0x843: 0x06ff, 0x844: 0x0707, 0x845: 0x0713,
+ 0x846: 0x071b, 0x847: 0x0723, 0x848: 0x072f, 0x849: 0x0783, 0x84a: 0x079b, 0x84b: 0x07ab,
+ 0x84c: 0x07bb, 0x84d: 0x07cb, 0x84e: 0x07db, 0x84f: 0x07fb, 0x850: 0x07ff, 0x851: 0x0803,
+ 0x852: 0x0837, 0x853: 0x085f, 0x854: 0x086f, 0x855: 0x0877, 0x856: 0x087b, 0x857: 0x0887,
+ 0x858: 0x08a3, 0x859: 0x08a7, 0x85a: 0x08bf, 0x85b: 0x08c3, 0x85c: 0x08cb, 0x85d: 0x08db,
+ 0x85e: 0x0977, 0x85f: 0x098b, 0x860: 0x09cb, 0x861: 0x09df, 0x862: 0x09e7, 0x863: 0x09eb,
+ 0x864: 0x09fb, 0x865: 0x0a17, 0x866: 0x0a43, 0x867: 0x0a4f, 0x868: 0x0a6f, 0x869: 0x0a7b,
+ 0x86a: 0x0a7f, 0x86b: 0x0a83, 0x86c: 0x0a9b, 0x86d: 0x0a9f, 0x86e: 0x0acb, 0x86f: 0x0ad7,
+ 0x870: 0x0adf, 0x871: 0x0ae7, 0x872: 0x0af7, 0x873: 0x0aff, 0x874: 0x0b07, 0x875: 0x0b33,
+ 0x876: 0x0b37, 0x877: 0x0b3f, 0x878: 0x0b43, 0x879: 0x0b4b, 0x87a: 0x0b53, 0x87b: 0x0b63,
+ 0x87c: 0x0b7f, 0x87d: 0x0bf7, 0x87e: 0x0c0b, 0x87f: 0x0c0f,
+ // Block 0x22, offset 0x880
+ 0x880: 0x0c8f, 0x881: 0x0c93, 0x882: 0x0ca7, 0x883: 0x0cab, 0x884: 0x0cb3, 0x885: 0x0cbb,
+ 0x886: 0x0cc3, 0x887: 0x0ccf, 0x888: 0x0cf7, 0x889: 0x0d07, 0x88a: 0x0d1b, 0x88b: 0x0d8b,
+ 0x88c: 0x0d97, 0x88d: 0x0da7, 0x88e: 0x0db3, 0x88f: 0x0dbf, 0x890: 0x0dc7, 0x891: 0x0dcb,
+ 0x892: 0x0dcf, 0x893: 0x0dd3, 0x894: 0x0dd7, 0x895: 0x0e8f, 0x896: 0x0ed7, 0x897: 0x0ee3,
+ 0x898: 0x0ee7, 0x899: 0x0eeb, 0x89a: 0x0eef, 0x89b: 0x0ef7, 0x89c: 0x0efb, 0x89d: 0x0f0f,
+ 0x89e: 0x0f2b, 0x89f: 0x0f33, 0x8a0: 0x0f73, 0x8a1: 0x0f77, 0x8a2: 0x0f7f, 0x8a3: 0x0f83,
+ 0x8a4: 0x0f8b, 0x8a5: 0x0f8f, 0x8a6: 0x0fb3, 0x8a7: 0x0fb7, 0x8a8: 0x0fd3, 0x8a9: 0x0fd7,
+ 0x8aa: 0x0fdb, 0x8ab: 0x0fdf, 0x8ac: 0x0ff3, 0x8ad: 0x1017, 0x8ae: 0x101b, 0x8af: 0x101f,
+ 0x8b0: 0x1043, 0x8b1: 0x1083, 0x8b2: 0x1087, 0x8b3: 0x10a7, 0x8b4: 0x10b7, 0x8b5: 0x10bf,
+ 0x8b6: 0x10df, 0x8b7: 0x1103, 0x8b8: 0x1147, 0x8b9: 0x114f, 0x8ba: 0x1163, 0x8bb: 0x116f,
+ 0x8bc: 0x1177, 0x8bd: 0x117f, 0x8be: 0x1183, 0x8bf: 0x1187,
+ // Block 0x23, offset 0x8c0
+ 0x8c0: 0x119f, 0x8c1: 0x11a3, 0x8c2: 0x11bf, 0x8c3: 0x11c7, 0x8c4: 0x11cf, 0x8c5: 0x11d3,
+ 0x8c6: 0x11df, 0x8c7: 0x11e7, 0x8c8: 0x11eb, 0x8c9: 0x11ef, 0x8ca: 0x11f7, 0x8cb: 0x11fb,
+ 0x8cc: 0x129b, 0x8cd: 0x12af, 0x8ce: 0x12e3, 0x8cf: 0x12e7, 0x8d0: 0x12ef, 0x8d1: 0x131b,
+ 0x8d2: 0x1323, 0x8d3: 0x132b, 0x8d4: 0x1333, 0x8d5: 0x136f, 0x8d6: 0x1373, 0x8d7: 0x137b,
+ 0x8d8: 0x137f, 0x8d9: 0x1383, 0x8da: 0x13af, 0x8db: 0x13b3, 0x8dc: 0x13bb, 0x8dd: 0x13cf,
+ 0x8de: 0x13d3, 0x8df: 0x13ef, 0x8e0: 0x13f7, 0x8e1: 0x13fb, 0x8e2: 0x141f, 0x8e3: 0x143f,
+ 0x8e4: 0x1453, 0x8e5: 0x1457, 0x8e6: 0x145f, 0x8e7: 0x148b, 0x8e8: 0x148f, 0x8e9: 0x149f,
+ 0x8ea: 0x14c3, 0x8eb: 0x14cf, 0x8ec: 0x14df, 0x8ed: 0x14f7, 0x8ee: 0x14ff, 0x8ef: 0x1503,
+ 0x8f0: 0x1507, 0x8f1: 0x150b, 0x8f2: 0x1517, 0x8f3: 0x151b, 0x8f4: 0x1523, 0x8f5: 0x153f,
+ 0x8f6: 0x1543, 0x8f7: 0x1547, 0x8f8: 0x155f, 0x8f9: 0x1563, 0x8fa: 0x156b, 0x8fb: 0x157f,
+ 0x8fc: 0x1583, 0x8fd: 0x1587, 0x8fe: 0x158f, 0x8ff: 0x1593,
+ // Block 0x24, offset 0x900
+ 0x906: 0xa000, 0x90b: 0xa000,
+ 0x90c: 0x3f08, 0x90d: 0xa000, 0x90e: 0x3f10, 0x90f: 0xa000, 0x910: 0x3f18, 0x911: 0xa000,
+ 0x912: 0x3f20, 0x913: 0xa000, 0x914: 0x3f28, 0x915: 0xa000, 0x916: 0x3f30, 0x917: 0xa000,
+ 0x918: 0x3f38, 0x919: 0xa000, 0x91a: 0x3f40, 0x91b: 0xa000, 0x91c: 0x3f48, 0x91d: 0xa000,
+ 0x91e: 0x3f50, 0x91f: 0xa000, 0x920: 0x3f58, 0x921: 0xa000, 0x922: 0x3f60,
+ 0x924: 0xa000, 0x925: 0x3f68, 0x926: 0xa000, 0x927: 0x3f70, 0x928: 0xa000, 0x929: 0x3f78,
+ 0x92f: 0xa000,
+ 0x930: 0x3f80, 0x931: 0x3f88, 0x932: 0xa000, 0x933: 0x3f90, 0x934: 0x3f98, 0x935: 0xa000,
+ 0x936: 0x3fa0, 0x937: 0x3fa8, 0x938: 0xa000, 0x939: 0x3fb0, 0x93a: 0x3fb8, 0x93b: 0xa000,
+ 0x93c: 0x3fc0, 0x93d: 0x3fc8,
+ // Block 0x25, offset 0x940
+ 0x954: 0x3f00,
+ 0x959: 0x9903, 0x95a: 0x9903, 0x95b: 0x4372, 0x95c: 0x4378, 0x95d: 0xa000,
+ 0x95e: 0x3fd0, 0x95f: 0x26b4,
+ 0x966: 0xa000,
+ 0x96b: 0xa000, 0x96c: 0x3fe0, 0x96d: 0xa000, 0x96e: 0x3fe8, 0x96f: 0xa000,
+ 0x970: 0x3ff0, 0x971: 0xa000, 0x972: 0x3ff8, 0x973: 0xa000, 0x974: 0x4000, 0x975: 0xa000,
+ 0x976: 0x4008, 0x977: 0xa000, 0x978: 0x4010, 0x979: 0xa000, 0x97a: 0x4018, 0x97b: 0xa000,
+ 0x97c: 0x4020, 0x97d: 0xa000, 0x97e: 0x4028, 0x97f: 0xa000,
+ // Block 0x26, offset 0x980
+ 0x980: 0x4030, 0x981: 0xa000, 0x982: 0x4038, 0x984: 0xa000, 0x985: 0x4040,
+ 0x986: 0xa000, 0x987: 0x4048, 0x988: 0xa000, 0x989: 0x4050,
+ 0x98f: 0xa000, 0x990: 0x4058, 0x991: 0x4060,
+ 0x992: 0xa000, 0x993: 0x4068, 0x994: 0x4070, 0x995: 0xa000, 0x996: 0x4078, 0x997: 0x4080,
+ 0x998: 0xa000, 0x999: 0x4088, 0x99a: 0x4090, 0x99b: 0xa000, 0x99c: 0x4098, 0x99d: 0x40a0,
+ 0x9af: 0xa000,
+ 0x9b0: 0xa000, 0x9b1: 0xa000, 0x9b2: 0xa000, 0x9b4: 0x3fd8,
+ 0x9b7: 0x40a8, 0x9b8: 0x40b0, 0x9b9: 0x40b8, 0x9ba: 0x40c0,
+ 0x9bd: 0xa000, 0x9be: 0x40c8, 0x9bf: 0x26c9,
+ // Block 0x27, offset 0x9c0
+ 0x9c0: 0x0367, 0x9c1: 0x032b, 0x9c2: 0x032f, 0x9c3: 0x0333, 0x9c4: 0x037b, 0x9c5: 0x0337,
+ 0x9c6: 0x033b, 0x9c7: 0x033f, 0x9c8: 0x0343, 0x9c9: 0x0347, 0x9ca: 0x034b, 0x9cb: 0x034f,
+ 0x9cc: 0x0353, 0x9cd: 0x0357, 0x9ce: 0x035b, 0x9cf: 0x42dc, 0x9d0: 0x42e1, 0x9d1: 0x42e6,
+ 0x9d2: 0x42eb, 0x9d3: 0x42f0, 0x9d4: 0x42f5, 0x9d5: 0x42fa, 0x9d6: 0x42ff, 0x9d7: 0x4304,
+ 0x9d8: 0x4309, 0x9d9: 0x430e, 0x9da: 0x4313, 0x9db: 0x4318, 0x9dc: 0x431d, 0x9dd: 0x4322,
+ 0x9de: 0x4327, 0x9df: 0x432c, 0x9e0: 0x4331, 0x9e1: 0x4336, 0x9e2: 0x433b, 0x9e3: 0x4340,
+ 0x9e4: 0x03c3, 0x9e5: 0x035f, 0x9e6: 0x0363, 0x9e7: 0x03e7, 0x9e8: 0x03eb, 0x9e9: 0x03ef,
+ 0x9ea: 0x03f3, 0x9eb: 0x03f7, 0x9ec: 0x03fb, 0x9ed: 0x03ff, 0x9ee: 0x036b, 0x9ef: 0x0403,
+ 0x9f0: 0x0407, 0x9f1: 0x036f, 0x9f2: 0x0373, 0x9f3: 0x0377, 0x9f4: 0x037f, 0x9f5: 0x0383,
+ 0x9f6: 0x0387, 0x9f7: 0x038b, 0x9f8: 0x038f, 0x9f9: 0x0393, 0x9fa: 0x0397, 0x9fb: 0x039b,
+ 0x9fc: 0x039f, 0x9fd: 0x03a3, 0x9fe: 0x03a7, 0x9ff: 0x03ab,
+ // Block 0x28, offset 0xa00
+ 0xa00: 0x03af, 0xa01: 0x03b3, 0xa02: 0x040b, 0xa03: 0x040f, 0xa04: 0x03b7, 0xa05: 0x03bb,
+ 0xa06: 0x03bf, 0xa07: 0x03c7, 0xa08: 0x03cb, 0xa09: 0x03cf, 0xa0a: 0x03d3, 0xa0b: 0x03d7,
+ 0xa0c: 0x03db, 0xa0d: 0x03df, 0xa0e: 0x03e3,
+ 0xa12: 0x06bf, 0xa13: 0x071b, 0xa14: 0x06cb, 0xa15: 0x097b, 0xa16: 0x06cf, 0xa17: 0x06e7,
+ 0xa18: 0x06d3, 0xa19: 0x0f93, 0xa1a: 0x0707, 0xa1b: 0x06db, 0xa1c: 0x06c3, 0xa1d: 0x09ff,
+ 0xa1e: 0x098f, 0xa1f: 0x072f,
+ // Block 0x29, offset 0xa40
+ 0xa40: 0x2054, 0xa41: 0x205a, 0xa42: 0x2060, 0xa43: 0x2066, 0xa44: 0x206c, 0xa45: 0x2072,
+ 0xa46: 0x2078, 0xa47: 0x207e, 0xa48: 0x2084, 0xa49: 0x208a, 0xa4a: 0x2090, 0xa4b: 0x2096,
+ 0xa4c: 0x209c, 0xa4d: 0x20a2, 0xa4e: 0x2726, 0xa4f: 0x272f, 0xa50: 0x2738, 0xa51: 0x2741,
+ 0xa52: 0x274a, 0xa53: 0x2753, 0xa54: 0x275c, 0xa55: 0x2765, 0xa56: 0x276e, 0xa57: 0x2780,
+ 0xa58: 0x2789, 0xa59: 0x2792, 0xa5a: 0x279b, 0xa5b: 0x27a4, 0xa5c: 0x2777, 0xa5d: 0x2bac,
+ 0xa5e: 0x2aed, 0xa60: 0x20a8, 0xa61: 0x20c0, 0xa62: 0x20b4, 0xa63: 0x2108,
+ 0xa64: 0x20c6, 0xa65: 0x20e4, 0xa66: 0x20ae, 0xa67: 0x20de, 0xa68: 0x20ba, 0xa69: 0x20f0,
+ 0xa6a: 0x2120, 0xa6b: 0x213e, 0xa6c: 0x2138, 0xa6d: 0x212c, 0xa6e: 0x217a, 0xa6f: 0x210e,
+ 0xa70: 0x211a, 0xa71: 0x2132, 0xa72: 0x2126, 0xa73: 0x2150, 0xa74: 0x20fc, 0xa75: 0x2144,
+ 0xa76: 0x216e, 0xa77: 0x2156, 0xa78: 0x20ea, 0xa79: 0x20cc, 0xa7a: 0x2102, 0xa7b: 0x2114,
+ 0xa7c: 0x214a, 0xa7d: 0x20d2, 0xa7e: 0x2174, 0xa7f: 0x20f6,
+ // Block 0x2a, offset 0xa80
+ 0xa80: 0x215c, 0xa81: 0x20d8, 0xa82: 0x2162, 0xa83: 0x2168, 0xa84: 0x092f, 0xa85: 0x0b03,
+ 0xa86: 0x0ca7, 0xa87: 0x10c7,
+ 0xa90: 0x1bc4, 0xa91: 0x18a9,
+ 0xa92: 0x18ac, 0xa93: 0x18af, 0xa94: 0x18b2, 0xa95: 0x18b5, 0xa96: 0x18b8, 0xa97: 0x18bb,
+ 0xa98: 0x18be, 0xa99: 0x18c1, 0xa9a: 0x18ca, 0xa9b: 0x18cd, 0xa9c: 0x18d0, 0xa9d: 0x18d3,
+ 0xa9e: 0x18d6, 0xa9f: 0x18d9, 0xaa0: 0x0313, 0xaa1: 0x031b, 0xaa2: 0x031f, 0xaa3: 0x0327,
+ 0xaa4: 0x032b, 0xaa5: 0x032f, 0xaa6: 0x0337, 0xaa7: 0x033f, 0xaa8: 0x0343, 0xaa9: 0x034b,
+ 0xaaa: 0x034f, 0xaab: 0x0353, 0xaac: 0x0357, 0xaad: 0x035b, 0xaae: 0x2e18, 0xaaf: 0x2e20,
+ 0xab0: 0x2e28, 0xab1: 0x2e30, 0xab2: 0x2e38, 0xab3: 0x2e40, 0xab4: 0x2e48, 0xab5: 0x2e50,
+ 0xab6: 0x2e60, 0xab7: 0x2e68, 0xab8: 0x2e70, 0xab9: 0x2e78, 0xaba: 0x2e80, 0xabb: 0x2e88,
+ 0xabc: 0x2ed3, 0xabd: 0x2e9b, 0xabe: 0x2e58,
+ // Block 0x2b, offset 0xac0
+ 0xac0: 0x06bf, 0xac1: 0x071b, 0xac2: 0x06cb, 0xac3: 0x097b, 0xac4: 0x071f, 0xac5: 0x07af,
+ 0xac6: 0x06c7, 0xac7: 0x07ab, 0xac8: 0x070b, 0xac9: 0x0887, 0xaca: 0x0d07, 0xacb: 0x0e8f,
+ 0xacc: 0x0dd7, 0xacd: 0x0d1b, 0xace: 0x145f, 0xacf: 0x098b, 0xad0: 0x0ccf, 0xad1: 0x0d4b,
+ 0xad2: 0x0d0b, 0xad3: 0x104b, 0xad4: 0x08fb, 0xad5: 0x0f03, 0xad6: 0x1387, 0xad7: 0x105f,
+ 0xad8: 0x0843, 0xad9: 0x108f, 0xada: 0x0f9b, 0xadb: 0x0a17, 0xadc: 0x140f, 0xadd: 0x077f,
+ 0xade: 0x08ab, 0xadf: 0x0df7, 0xae0: 0x1527, 0xae1: 0x0743, 0xae2: 0x07d3, 0xae3: 0x0d9b,
+ 0xae4: 0x06cf, 0xae5: 0x06e7, 0xae6: 0x06d3, 0xae7: 0x0adb, 0xae8: 0x08ef, 0xae9: 0x087f,
+ 0xaea: 0x0a57, 0xaeb: 0x0a4b, 0xaec: 0x0feb, 0xaed: 0x073f, 0xaee: 0x139b, 0xaef: 0x089b,
+ 0xaf0: 0x09f3, 0xaf1: 0x18dc, 0xaf2: 0x18df, 0xaf3: 0x18e2, 0xaf4: 0x18e5, 0xaf5: 0x18ee,
+ 0xaf6: 0x18f1, 0xaf7: 0x18f4, 0xaf8: 0x18f7, 0xaf9: 0x18fa, 0xafa: 0x18fd, 0xafb: 0x1900,
+ 0xafc: 0x1903, 0xafd: 0x1906, 0xafe: 0x1909, 0xaff: 0x1912,
+ // Block 0x2c, offset 0xb00
+ 0xb00: 0x1cc6, 0xb01: 0x1cd5, 0xb02: 0x1ce4, 0xb03: 0x1cf3, 0xb04: 0x1d02, 0xb05: 0x1d11,
+ 0xb06: 0x1d20, 0xb07: 0x1d2f, 0xb08: 0x1d3e, 0xb09: 0x218c, 0xb0a: 0x219e, 0xb0b: 0x21b0,
+ 0xb0c: 0x1954, 0xb0d: 0x1c04, 0xb0e: 0x19d2, 0xb0f: 0x1ba8, 0xb10: 0x04cb, 0xb11: 0x04d3,
+ 0xb12: 0x04db, 0xb13: 0x04e3, 0xb14: 0x04eb, 0xb15: 0x04ef, 0xb16: 0x04f3, 0xb17: 0x04f7,
+ 0xb18: 0x04fb, 0xb19: 0x04ff, 0xb1a: 0x0503, 0xb1b: 0x0507, 0xb1c: 0x050b, 0xb1d: 0x050f,
+ 0xb1e: 0x0513, 0xb1f: 0x0517, 0xb20: 0x051b, 0xb21: 0x0523, 0xb22: 0x0527, 0xb23: 0x052b,
+ 0xb24: 0x052f, 0xb25: 0x0533, 0xb26: 0x0537, 0xb27: 0x053b, 0xb28: 0x053f, 0xb29: 0x0543,
+ 0xb2a: 0x0547, 0xb2b: 0x054b, 0xb2c: 0x054f, 0xb2d: 0x0553, 0xb2e: 0x0557, 0xb2f: 0x055b,
+ 0xb30: 0x055f, 0xb31: 0x0563, 0xb32: 0x0567, 0xb33: 0x056f, 0xb34: 0x0577, 0xb35: 0x057f,
+ 0xb36: 0x0583, 0xb37: 0x0587, 0xb38: 0x058b, 0xb39: 0x058f, 0xb3a: 0x0593, 0xb3b: 0x0597,
+ 0xb3c: 0x059b, 0xb3d: 0x059f, 0xb3e: 0x05a3,
+ // Block 0x2d, offset 0xb40
+ 0xb40: 0x2b0c, 0xb41: 0x29a8, 0xb42: 0x2b1c, 0xb43: 0x2880, 0xb44: 0x2ee4, 0xb45: 0x288a,
+ 0xb46: 0x2894, 0xb47: 0x2f28, 0xb48: 0x29b5, 0xb49: 0x289e, 0xb4a: 0x28a8, 0xb4b: 0x28b2,
+ 0xb4c: 0x29dc, 0xb4d: 0x29e9, 0xb4e: 0x29c2, 0xb4f: 0x29cf, 0xb50: 0x2ea9, 0xb51: 0x29f6,
+ 0xb52: 0x2a03, 0xb53: 0x2bbe, 0xb54: 0x26bb, 0xb55: 0x2bd1, 0xb56: 0x2be4, 0xb57: 0x2b2c,
+ 0xb58: 0x2a10, 0xb59: 0x2bf7, 0xb5a: 0x2c0a, 0xb5b: 0x2a1d, 0xb5c: 0x28bc, 0xb5d: 0x28c6,
+ 0xb5e: 0x2eb7, 0xb5f: 0x2a2a, 0xb60: 0x2b3c, 0xb61: 0x2ef5, 0xb62: 0x28d0, 0xb63: 0x28da,
+ 0xb64: 0x2a37, 0xb65: 0x28e4, 0xb66: 0x28ee, 0xb67: 0x26d0, 0xb68: 0x26d7, 0xb69: 0x28f8,
+ 0xb6a: 0x2902, 0xb6b: 0x2c1d, 0xb6c: 0x2a44, 0xb6d: 0x2b4c, 0xb6e: 0x2c30, 0xb6f: 0x2a51,
+ 0xb70: 0x2916, 0xb71: 0x290c, 0xb72: 0x2f3c, 0xb73: 0x2a5e, 0xb74: 0x2c43, 0xb75: 0x2920,
+ 0xb76: 0x2b5c, 0xb77: 0x292a, 0xb78: 0x2a78, 0xb79: 0x2934, 0xb7a: 0x2a85, 0xb7b: 0x2f06,
+ 0xb7c: 0x2a6b, 0xb7d: 0x2b6c, 0xb7e: 0x2a92, 0xb7f: 0x26de,
+ // Block 0x2e, offset 0xb80
+ 0xb80: 0x2f17, 0xb81: 0x293e, 0xb82: 0x2948, 0xb83: 0x2a9f, 0xb84: 0x2952, 0xb85: 0x295c,
+ 0xb86: 0x2966, 0xb87: 0x2b7c, 0xb88: 0x2aac, 0xb89: 0x26e5, 0xb8a: 0x2c56, 0xb8b: 0x2e90,
+ 0xb8c: 0x2b8c, 0xb8d: 0x2ab9, 0xb8e: 0x2ec5, 0xb8f: 0x2970, 0xb90: 0x297a, 0xb91: 0x2ac6,
+ 0xb92: 0x26ec, 0xb93: 0x2ad3, 0xb94: 0x2b9c, 0xb95: 0x26f3, 0xb96: 0x2c69, 0xb97: 0x2984,
+ 0xb98: 0x1cb7, 0xb99: 0x1ccb, 0xb9a: 0x1cda, 0xb9b: 0x1ce9, 0xb9c: 0x1cf8, 0xb9d: 0x1d07,
+ 0xb9e: 0x1d16, 0xb9f: 0x1d25, 0xba0: 0x1d34, 0xba1: 0x1d43, 0xba2: 0x2192, 0xba3: 0x21a4,
+ 0xba4: 0x21b6, 0xba5: 0x21c2, 0xba6: 0x21ce, 0xba7: 0x21da, 0xba8: 0x21e6, 0xba9: 0x21f2,
+ 0xbaa: 0x21fe, 0xbab: 0x220a, 0xbac: 0x2246, 0xbad: 0x2252, 0xbae: 0x225e, 0xbaf: 0x226a,
+ 0xbb0: 0x2276, 0xbb1: 0x1c14, 0xbb2: 0x19c6, 0xbb3: 0x1936, 0xbb4: 0x1be4, 0xbb5: 0x1a47,
+ 0xbb6: 0x1a56, 0xbb7: 0x19cc, 0xbb8: 0x1bfc, 0xbb9: 0x1c00, 0xbba: 0x1960, 0xbbb: 0x2701,
+ 0xbbc: 0x270f, 0xbbd: 0x26fa, 0xbbe: 0x2708, 0xbbf: 0x2ae0,
+ // Block 0x2f, offset 0xbc0
+ 0xbc0: 0x1a4a, 0xbc1: 0x1a32, 0xbc2: 0x1c60, 0xbc3: 0x1a1a, 0xbc4: 0x19f3, 0xbc5: 0x1969,
+ 0xbc6: 0x1978, 0xbc7: 0x1948, 0xbc8: 0x1bf0, 0xbc9: 0x1d52, 0xbca: 0x1a4d, 0xbcb: 0x1a35,
+ 0xbcc: 0x1c64, 0xbcd: 0x1c70, 0xbce: 0x1a26, 0xbcf: 0x19fc, 0xbd0: 0x1957, 0xbd1: 0x1c1c,
+ 0xbd2: 0x1bb0, 0xbd3: 0x1b9c, 0xbd4: 0x1bcc, 0xbd5: 0x1c74, 0xbd6: 0x1a29, 0xbd7: 0x19c9,
+ 0xbd8: 0x19ff, 0xbd9: 0x19de, 0xbda: 0x1a41, 0xbdb: 0x1c78, 0xbdc: 0x1a2c, 0xbdd: 0x19c0,
+ 0xbde: 0x1a02, 0xbdf: 0x1c3c, 0xbe0: 0x1bf4, 0xbe1: 0x1a14, 0xbe2: 0x1c24, 0xbe3: 0x1c40,
+ 0xbe4: 0x1bf8, 0xbe5: 0x1a17, 0xbe6: 0x1c28, 0xbe7: 0x22e8, 0xbe8: 0x22fc, 0xbe9: 0x1996,
+ 0xbea: 0x1c20, 0xbeb: 0x1bb4, 0xbec: 0x1ba0, 0xbed: 0x1c48, 0xbee: 0x2716, 0xbef: 0x27ad,
+ 0xbf0: 0x1a59, 0xbf1: 0x1a44, 0xbf2: 0x1c7c, 0xbf3: 0x1a2f, 0xbf4: 0x1a50, 0xbf5: 0x1a38,
+ 0xbf6: 0x1c68, 0xbf7: 0x1a1d, 0xbf8: 0x19f6, 0xbf9: 0x1981, 0xbfa: 0x1a53, 0xbfb: 0x1a3b,
+ 0xbfc: 0x1c6c, 0xbfd: 0x1a20, 0xbfe: 0x19f9, 0xbff: 0x1984,
+ // Block 0x30, offset 0xc00
+ 0xc00: 0x1c2c, 0xc01: 0x1bb8, 0xc02: 0x1d4d, 0xc03: 0x1939, 0xc04: 0x19ba, 0xc05: 0x19bd,
+ 0xc06: 0x22f5, 0xc07: 0x1b94, 0xc08: 0x19c3, 0xc09: 0x194b, 0xc0a: 0x19e1, 0xc0b: 0x194e,
+ 0xc0c: 0x19ea, 0xc0d: 0x196c, 0xc0e: 0x196f, 0xc0f: 0x1a05, 0xc10: 0x1a0b, 0xc11: 0x1a0e,
+ 0xc12: 0x1c30, 0xc13: 0x1a11, 0xc14: 0x1a23, 0xc15: 0x1c38, 0xc16: 0x1c44, 0xc17: 0x1990,
+ 0xc18: 0x1d57, 0xc19: 0x1bbc, 0xc1a: 0x1993, 0xc1b: 0x1a5c, 0xc1c: 0x19a5, 0xc1d: 0x19b4,
+ 0xc1e: 0x22e2, 0xc1f: 0x22dc, 0xc20: 0x1cc1, 0xc21: 0x1cd0, 0xc22: 0x1cdf, 0xc23: 0x1cee,
+ 0xc24: 0x1cfd, 0xc25: 0x1d0c, 0xc26: 0x1d1b, 0xc27: 0x1d2a, 0xc28: 0x1d39, 0xc29: 0x2186,
+ 0xc2a: 0x2198, 0xc2b: 0x21aa, 0xc2c: 0x21bc, 0xc2d: 0x21c8, 0xc2e: 0x21d4, 0xc2f: 0x21e0,
+ 0xc30: 0x21ec, 0xc31: 0x21f8, 0xc32: 0x2204, 0xc33: 0x2240, 0xc34: 0x224c, 0xc35: 0x2258,
+ 0xc36: 0x2264, 0xc37: 0x2270, 0xc38: 0x227c, 0xc39: 0x2282, 0xc3a: 0x2288, 0xc3b: 0x228e,
+ 0xc3c: 0x2294, 0xc3d: 0x22a6, 0xc3e: 0x22ac, 0xc3f: 0x1c10,
+ // Block 0x31, offset 0xc40
+ 0xc40: 0x1377, 0xc41: 0x0cfb, 0xc42: 0x13d3, 0xc43: 0x139f, 0xc44: 0x0e57, 0xc45: 0x06eb,
+ 0xc46: 0x08df, 0xc47: 0x162b, 0xc48: 0x162b, 0xc49: 0x0a0b, 0xc4a: 0x145f, 0xc4b: 0x0943,
+ 0xc4c: 0x0a07, 0xc4d: 0x0bef, 0xc4e: 0x0fcf, 0xc4f: 0x115f, 0xc50: 0x1297, 0xc51: 0x12d3,
+ 0xc52: 0x1307, 0xc53: 0x141b, 0xc54: 0x0d73, 0xc55: 0x0dff, 0xc56: 0x0eab, 0xc57: 0x0f43,
+ 0xc58: 0x125f, 0xc59: 0x1447, 0xc5a: 0x1573, 0xc5b: 0x070f, 0xc5c: 0x08b3, 0xc5d: 0x0d87,
+ 0xc5e: 0x0ecf, 0xc5f: 0x1293, 0xc60: 0x15c3, 0xc61: 0x0ab3, 0xc62: 0x0e77, 0xc63: 0x1283,
+ 0xc64: 0x1317, 0xc65: 0x0c23, 0xc66: 0x11bb, 0xc67: 0x12df, 0xc68: 0x0b1f, 0xc69: 0x0d0f,
+ 0xc6a: 0x0e17, 0xc6b: 0x0f1b, 0xc6c: 0x1427, 0xc6d: 0x074f, 0xc6e: 0x07e7, 0xc6f: 0x0853,
+ 0xc70: 0x0c8b, 0xc71: 0x0d7f, 0xc72: 0x0ecb, 0xc73: 0x0fef, 0xc74: 0x1177, 0xc75: 0x128b,
+ 0xc76: 0x12a3, 0xc77: 0x13c7, 0xc78: 0x14ef, 0xc79: 0x15a3, 0xc7a: 0x15bf, 0xc7b: 0x102b,
+ 0xc7c: 0x106b, 0xc7d: 0x1123, 0xc7e: 0x1243, 0xc7f: 0x147b,
+ // Block 0x32, offset 0xc80
+ 0xc80: 0x15cb, 0xc81: 0x134b, 0xc82: 0x09c7, 0xc83: 0x0b3b, 0xc84: 0x10db, 0xc85: 0x119b,
+ 0xc86: 0x0eff, 0xc87: 0x1033, 0xc88: 0x1397, 0xc89: 0x14e7, 0xc8a: 0x09c3, 0xc8b: 0x0a8f,
+ 0xc8c: 0x0d77, 0xc8d: 0x0e2b, 0xc8e: 0x0e5f, 0xc8f: 0x1113, 0xc90: 0x113b, 0xc91: 0x14a7,
+ 0xc92: 0x084f, 0xc93: 0x11a7, 0xc94: 0x07f3, 0xc95: 0x07ef, 0xc96: 0x1097, 0xc97: 0x1127,
+ 0xc98: 0x125b, 0xc99: 0x14af, 0xc9a: 0x1367, 0xc9b: 0x0c27, 0xc9c: 0x0d73, 0xc9d: 0x1357,
+ 0xc9e: 0x06f7, 0xc9f: 0x0a63, 0xca0: 0x0b93, 0xca1: 0x0f2f, 0xca2: 0x0faf, 0xca3: 0x0873,
+ 0xca4: 0x103b, 0xca5: 0x075f, 0xca6: 0x0b77, 0xca7: 0x06d7, 0xca8: 0x0deb, 0xca9: 0x0ca3,
+ 0xcaa: 0x110f, 0xcab: 0x08c7, 0xcac: 0x09b3, 0xcad: 0x0ffb, 0xcae: 0x1263, 0xcaf: 0x133b,
+ 0xcb0: 0x0db7, 0xcb1: 0x13f7, 0xcb2: 0x0de3, 0xcb3: 0x0c37, 0xcb4: 0x121b, 0xcb5: 0x0c57,
+ 0xcb6: 0x0fab, 0xcb7: 0x072b, 0xcb8: 0x07a7, 0xcb9: 0x07eb, 0xcba: 0x0d53, 0xcbb: 0x10fb,
+ 0xcbc: 0x11f3, 0xcbd: 0x1347, 0xcbe: 0x145b, 0xcbf: 0x085b,
+ // Block 0x33, offset 0xcc0
+ 0xcc0: 0x090f, 0xcc1: 0x0a17, 0xcc2: 0x0b2f, 0xcc3: 0x0cbf, 0xcc4: 0x0e7b, 0xcc5: 0x103f,
+ 0xcc6: 0x1497, 0xcc7: 0x157b, 0xcc8: 0x15cf, 0xcc9: 0x15e7, 0xcca: 0x0837, 0xccb: 0x0cf3,
+ 0xccc: 0x0da3, 0xccd: 0x13eb, 0xcce: 0x0afb, 0xccf: 0x0bd7, 0xcd0: 0x0bf3, 0xcd1: 0x0c83,
+ 0xcd2: 0x0e6b, 0xcd3: 0x0eb7, 0xcd4: 0x0f67, 0xcd5: 0x108b, 0xcd6: 0x112f, 0xcd7: 0x1193,
+ 0xcd8: 0x13db, 0xcd9: 0x126b, 0xcda: 0x1403, 0xcdb: 0x147f, 0xcdc: 0x080f, 0xcdd: 0x083b,
+ 0xcde: 0x0923, 0xcdf: 0x0ea7, 0xce0: 0x12f3, 0xce1: 0x133b, 0xce2: 0x0b1b, 0xce3: 0x0b8b,
+ 0xce4: 0x0c4f, 0xce5: 0x0daf, 0xce6: 0x10d7, 0xce7: 0x0f23, 0xce8: 0x073b, 0xce9: 0x097f,
+ 0xcea: 0x0a63, 0xceb: 0x0ac7, 0xcec: 0x0b97, 0xced: 0x0f3f, 0xcee: 0x0f5b, 0xcef: 0x116b,
+ 0xcf0: 0x118b, 0xcf1: 0x1463, 0xcf2: 0x14e3, 0xcf3: 0x14f3, 0xcf4: 0x152f, 0xcf5: 0x0753,
+ 0xcf6: 0x107f, 0xcf7: 0x144f, 0xcf8: 0x14cb, 0xcf9: 0x0baf, 0xcfa: 0x0717, 0xcfb: 0x0777,
+ 0xcfc: 0x0a67, 0xcfd: 0x0a87, 0xcfe: 0x0caf, 0xcff: 0x0d73,
+ // Block 0x34, offset 0xd00
+ 0xd00: 0x0ec3, 0xd01: 0x0fcb, 0xd02: 0x1277, 0xd03: 0x1417, 0xd04: 0x1623, 0xd05: 0x0ce3,
+ 0xd06: 0x14a3, 0xd07: 0x0833, 0xd08: 0x0d2f, 0xd09: 0x0d3b, 0xd0a: 0x0e0f, 0xd0b: 0x0e47,
+ 0xd0c: 0x0f4b, 0xd0d: 0x0fa7, 0xd0e: 0x1027, 0xd0f: 0x110b, 0xd10: 0x153b, 0xd11: 0x07af,
+ 0xd12: 0x0c03, 0xd13: 0x14b3, 0xd14: 0x0767, 0xd15: 0x0aab, 0xd16: 0x0e2f, 0xd17: 0x13df,
+ 0xd18: 0x0b67, 0xd19: 0x0bb7, 0xd1a: 0x0d43, 0xd1b: 0x0f2f, 0xd1c: 0x14bb, 0xd1d: 0x0817,
+ 0xd1e: 0x08ff, 0xd1f: 0x0a97, 0xd20: 0x0cd3, 0xd21: 0x0d1f, 0xd22: 0x0d5f, 0xd23: 0x0df3,
+ 0xd24: 0x0f47, 0xd25: 0x0fbb, 0xd26: 0x1157, 0xd27: 0x12f7, 0xd28: 0x1303, 0xd29: 0x1457,
+ 0xd2a: 0x14d7, 0xd2b: 0x0883, 0xd2c: 0x0e4b, 0xd2d: 0x0903, 0xd2e: 0x0ec7, 0xd2f: 0x0f6b,
+ 0xd30: 0x1287, 0xd31: 0x14bf, 0xd32: 0x15ab, 0xd33: 0x15d3, 0xd34: 0x0d37, 0xd35: 0x0e27,
+ 0xd36: 0x11c3, 0xd37: 0x10b7, 0xd38: 0x10c3, 0xd39: 0x10e7, 0xd3a: 0x0f17, 0xd3b: 0x0e9f,
+ 0xd3c: 0x1363, 0xd3d: 0x0733, 0xd3e: 0x122b, 0xd3f: 0x081b,
+ // Block 0x35, offset 0xd40
+ 0xd40: 0x080b, 0xd41: 0x0b0b, 0xd42: 0x0c2b, 0xd43: 0x10f3, 0xd44: 0x0a53, 0xd45: 0x0e03,
+ 0xd46: 0x0cef, 0xd47: 0x13e7, 0xd48: 0x12e7, 0xd49: 0x14ab, 0xd4a: 0x1323, 0xd4b: 0x0b27,
+ 0xd4c: 0x0787, 0xd4d: 0x095b, 0xd50: 0x09af,
+ 0xd52: 0x0cdf, 0xd55: 0x07f7, 0xd56: 0x0f1f, 0xd57: 0x0fe3,
+ 0xd58: 0x1047, 0xd59: 0x1063, 0xd5a: 0x1067, 0xd5b: 0x107b, 0xd5c: 0x14fb, 0xd5d: 0x10eb,
+ 0xd5e: 0x116f, 0xd60: 0x128f, 0xd62: 0x1353,
+ 0xd65: 0x1407, 0xd66: 0x1433,
+ 0xd6a: 0x154f, 0xd6b: 0x1553, 0xd6c: 0x1557, 0xd6d: 0x15bb, 0xd6e: 0x142b, 0xd6f: 0x14c7,
+ 0xd70: 0x0757, 0xd71: 0x077b, 0xd72: 0x078f, 0xd73: 0x084b, 0xd74: 0x0857, 0xd75: 0x0897,
+ 0xd76: 0x094b, 0xd77: 0x0967, 0xd78: 0x096f, 0xd79: 0x09ab, 0xd7a: 0x09b7, 0xd7b: 0x0a93,
+ 0xd7c: 0x0a9b, 0xd7d: 0x0ba3, 0xd7e: 0x0bcb, 0xd7f: 0x0bd3,
+ // Block 0x36, offset 0xd80
+ 0xd80: 0x0beb, 0xd81: 0x0c97, 0xd82: 0x0cc7, 0xd83: 0x0ce7, 0xd84: 0x0d57, 0xd85: 0x0e1b,
+ 0xd86: 0x0e37, 0xd87: 0x0e67, 0xd88: 0x0ebb, 0xd89: 0x0edb, 0xd8a: 0x0f4f, 0xd8b: 0x102f,
+ 0xd8c: 0x104b, 0xd8d: 0x1053, 0xd8e: 0x104f, 0xd8f: 0x1057, 0xd90: 0x105b, 0xd91: 0x105f,
+ 0xd92: 0x1073, 0xd93: 0x1077, 0xd94: 0x109b, 0xd95: 0x10af, 0xd96: 0x10cb, 0xd97: 0x112f,
+ 0xd98: 0x1137, 0xd99: 0x113f, 0xd9a: 0x1153, 0xd9b: 0x117b, 0xd9c: 0x11cb, 0xd9d: 0x11ff,
+ 0xd9e: 0x11ff, 0xd9f: 0x1267, 0xda0: 0x130f, 0xda1: 0x1327, 0xda2: 0x135b, 0xda3: 0x135f,
+ 0xda4: 0x13a3, 0xda5: 0x13a7, 0xda6: 0x13ff, 0xda7: 0x1407, 0xda8: 0x14db, 0xda9: 0x151f,
+ 0xdaa: 0x1537, 0xdab: 0x0b9b, 0xdac: 0x171e, 0xdad: 0x11e3,
+ 0xdb0: 0x06df, 0xdb1: 0x07e3, 0xdb2: 0x07a3, 0xdb3: 0x074b, 0xdb4: 0x078b, 0xdb5: 0x07b7,
+ 0xdb6: 0x0847, 0xdb7: 0x0863, 0xdb8: 0x094b, 0xdb9: 0x0937, 0xdba: 0x0947, 0xdbb: 0x0963,
+ 0xdbc: 0x09af, 0xdbd: 0x09bf, 0xdbe: 0x0a03, 0xdbf: 0x0a0f,
+ // Block 0x37, offset 0xdc0
+ 0xdc0: 0x0a2b, 0xdc1: 0x0a3b, 0xdc2: 0x0b23, 0xdc3: 0x0b2b, 0xdc4: 0x0b5b, 0xdc5: 0x0b7b,
+ 0xdc6: 0x0bab, 0xdc7: 0x0bc3, 0xdc8: 0x0bb3, 0xdc9: 0x0bd3, 0xdca: 0x0bc7, 0xdcb: 0x0beb,
+ 0xdcc: 0x0c07, 0xdcd: 0x0c5f, 0xdce: 0x0c6b, 0xdcf: 0x0c73, 0xdd0: 0x0c9b, 0xdd1: 0x0cdf,
+ 0xdd2: 0x0d0f, 0xdd3: 0x0d13, 0xdd4: 0x0d27, 0xdd5: 0x0da7, 0xdd6: 0x0db7, 0xdd7: 0x0e0f,
+ 0xdd8: 0x0e5b, 0xdd9: 0x0e53, 0xdda: 0x0e67, 0xddb: 0x0e83, 0xddc: 0x0ebb, 0xddd: 0x1013,
+ 0xdde: 0x0edf, 0xddf: 0x0f13, 0xde0: 0x0f1f, 0xde1: 0x0f5f, 0xde2: 0x0f7b, 0xde3: 0x0f9f,
+ 0xde4: 0x0fc3, 0xde5: 0x0fc7, 0xde6: 0x0fe3, 0xde7: 0x0fe7, 0xde8: 0x0ff7, 0xde9: 0x100b,
+ 0xdea: 0x1007, 0xdeb: 0x1037, 0xdec: 0x10b3, 0xded: 0x10cb, 0xdee: 0x10e3, 0xdef: 0x111b,
+ 0xdf0: 0x112f, 0xdf1: 0x114b, 0xdf2: 0x117b, 0xdf3: 0x122f, 0xdf4: 0x1257, 0xdf5: 0x12cb,
+ 0xdf6: 0x1313, 0xdf7: 0x131f, 0xdf8: 0x1327, 0xdf9: 0x133f, 0xdfa: 0x1353, 0xdfb: 0x1343,
+ 0xdfc: 0x135b, 0xdfd: 0x1357, 0xdfe: 0x134f, 0xdff: 0x135f,
+ // Block 0x38, offset 0xe00
+ 0xe00: 0x136b, 0xe01: 0x13a7, 0xe02: 0x13e3, 0xe03: 0x1413, 0xe04: 0x144b, 0xe05: 0x146b,
+ 0xe06: 0x14b7, 0xe07: 0x14db, 0xe08: 0x14fb, 0xe09: 0x150f, 0xe0a: 0x151f, 0xe0b: 0x152b,
+ 0xe0c: 0x1537, 0xe0d: 0x158b, 0xe0e: 0x162b, 0xe0f: 0x16b5, 0xe10: 0x16b0, 0xe11: 0x16e2,
+ 0xe12: 0x0607, 0xe13: 0x062f, 0xe14: 0x0633, 0xe15: 0x1764, 0xe16: 0x1791, 0xe17: 0x1809,
+ 0xe18: 0x1617, 0xe19: 0x1627,
+ // Block 0x39, offset 0xe40
+ 0xe40: 0x19d5, 0xe41: 0x19d8, 0xe42: 0x19db, 0xe43: 0x1c08, 0xe44: 0x1c0c, 0xe45: 0x1a5f,
+ 0xe46: 0x1a5f,
+ 0xe53: 0x1d75, 0xe54: 0x1d66, 0xe55: 0x1d6b, 0xe56: 0x1d7a, 0xe57: 0x1d70,
+ 0xe5d: 0x4426,
+ 0xe5e: 0x8115, 0xe5f: 0x4498, 0xe60: 0x022d, 0xe61: 0x0215, 0xe62: 0x021e, 0xe63: 0x0221,
+ 0xe64: 0x0224, 0xe65: 0x0227, 0xe66: 0x022a, 0xe67: 0x0230, 0xe68: 0x0233, 0xe69: 0x0017,
+ 0xe6a: 0x4486, 0xe6b: 0x448c, 0xe6c: 0x458a, 0xe6d: 0x4592, 0xe6e: 0x43de, 0xe6f: 0x43e4,
+ 0xe70: 0x43ea, 0xe71: 0x43f0, 0xe72: 0x43fc, 0xe73: 0x4402, 0xe74: 0x4408, 0xe75: 0x4414,
+ 0xe76: 0x441a, 0xe78: 0x4420, 0xe79: 0x442c, 0xe7a: 0x4432, 0xe7b: 0x4438,
+ 0xe7c: 0x4444, 0xe7e: 0x444a,
+ // Block 0x3a, offset 0xe80
+ 0xe80: 0x4450, 0xe81: 0x4456, 0xe83: 0x445c, 0xe84: 0x4462,
+ 0xe86: 0x446e, 0xe87: 0x4474, 0xe88: 0x447a, 0xe89: 0x4480, 0xe8a: 0x4492, 0xe8b: 0x440e,
+ 0xe8c: 0x43f6, 0xe8d: 0x443e, 0xe8e: 0x4468, 0xe8f: 0x1d7f, 0xe90: 0x0299, 0xe91: 0x0299,
+ 0xe92: 0x02a2, 0xe93: 0x02a2, 0xe94: 0x02a2, 0xe95: 0x02a2, 0xe96: 0x02a5, 0xe97: 0x02a5,
+ 0xe98: 0x02a5, 0xe99: 0x02a5, 0xe9a: 0x02ab, 0xe9b: 0x02ab, 0xe9c: 0x02ab, 0xe9d: 0x02ab,
+ 0xe9e: 0x029f, 0xe9f: 0x029f, 0xea0: 0x029f, 0xea1: 0x029f, 0xea2: 0x02a8, 0xea3: 0x02a8,
+ 0xea4: 0x02a8, 0xea5: 0x02a8, 0xea6: 0x029c, 0xea7: 0x029c, 0xea8: 0x029c, 0xea9: 0x029c,
+ 0xeaa: 0x02cf, 0xeab: 0x02cf, 0xeac: 0x02cf, 0xead: 0x02cf, 0xeae: 0x02d2, 0xeaf: 0x02d2,
+ 0xeb0: 0x02d2, 0xeb1: 0x02d2, 0xeb2: 0x02b1, 0xeb3: 0x02b1, 0xeb4: 0x02b1, 0xeb5: 0x02b1,
+ 0xeb6: 0x02ae, 0xeb7: 0x02ae, 0xeb8: 0x02ae, 0xeb9: 0x02ae, 0xeba: 0x02b4, 0xebb: 0x02b4,
+ 0xebc: 0x02b4, 0xebd: 0x02b4, 0xebe: 0x02b7, 0xebf: 0x02b7,
+ // Block 0x3b, offset 0xec0
+ 0xec0: 0x02b7, 0xec1: 0x02b7, 0xec2: 0x02c0, 0xec3: 0x02c0, 0xec4: 0x02bd, 0xec5: 0x02bd,
+ 0xec6: 0x02c3, 0xec7: 0x02c3, 0xec8: 0x02ba, 0xec9: 0x02ba, 0xeca: 0x02c9, 0xecb: 0x02c9,
+ 0xecc: 0x02c6, 0xecd: 0x02c6, 0xece: 0x02d5, 0xecf: 0x02d5, 0xed0: 0x02d5, 0xed1: 0x02d5,
+ 0xed2: 0x02db, 0xed3: 0x02db, 0xed4: 0x02db, 0xed5: 0x02db, 0xed6: 0x02e1, 0xed7: 0x02e1,
+ 0xed8: 0x02e1, 0xed9: 0x02e1, 0xeda: 0x02de, 0xedb: 0x02de, 0xedc: 0x02de, 0xedd: 0x02de,
+ 0xede: 0x02e4, 0xedf: 0x02e4, 0xee0: 0x02e7, 0xee1: 0x02e7, 0xee2: 0x02e7, 0xee3: 0x02e7,
+ 0xee4: 0x4504, 0xee5: 0x4504, 0xee6: 0x02ed, 0xee7: 0x02ed, 0xee8: 0x02ed, 0xee9: 0x02ed,
+ 0xeea: 0x02ea, 0xeeb: 0x02ea, 0xeec: 0x02ea, 0xeed: 0x02ea, 0xeee: 0x0308, 0xeef: 0x0308,
+ 0xef0: 0x44fe, 0xef1: 0x44fe,
+ // Block 0x3c, offset 0xf00
+ 0xf13: 0x02d8, 0xf14: 0x02d8, 0xf15: 0x02d8, 0xf16: 0x02d8, 0xf17: 0x02f6,
+ 0xf18: 0x02f6, 0xf19: 0x02f3, 0xf1a: 0x02f3, 0xf1b: 0x02f9, 0xf1c: 0x02f9, 0xf1d: 0x204f,
+ 0xf1e: 0x02ff, 0xf1f: 0x02ff, 0xf20: 0x02f0, 0xf21: 0x02f0, 0xf22: 0x02fc, 0xf23: 0x02fc,
+ 0xf24: 0x0305, 0xf25: 0x0305, 0xf26: 0x0305, 0xf27: 0x0305, 0xf28: 0x028d, 0xf29: 0x028d,
+ 0xf2a: 0x25aa, 0xf2b: 0x25aa, 0xf2c: 0x261a, 0xf2d: 0x261a, 0xf2e: 0x25e9, 0xf2f: 0x25e9,
+ 0xf30: 0x2605, 0xf31: 0x2605, 0xf32: 0x25fe, 0xf33: 0x25fe, 0xf34: 0x260c, 0xf35: 0x260c,
+ 0xf36: 0x2613, 0xf37: 0x2613, 0xf38: 0x2613, 0xf39: 0x25f0, 0xf3a: 0x25f0, 0xf3b: 0x25f0,
+ 0xf3c: 0x0302, 0xf3d: 0x0302, 0xf3e: 0x0302, 0xf3f: 0x0302,
+ // Block 0x3d, offset 0xf40
+ 0xf40: 0x25b1, 0xf41: 0x25b8, 0xf42: 0x25d4, 0xf43: 0x25f0, 0xf44: 0x25f7, 0xf45: 0x1d89,
+ 0xf46: 0x1d8e, 0xf47: 0x1d93, 0xf48: 0x1da2, 0xf49: 0x1db1, 0xf4a: 0x1db6, 0xf4b: 0x1dbb,
+ 0xf4c: 0x1dc0, 0xf4d: 0x1dc5, 0xf4e: 0x1dd4, 0xf4f: 0x1de3, 0xf50: 0x1de8, 0xf51: 0x1ded,
+ 0xf52: 0x1dfc, 0xf53: 0x1e0b, 0xf54: 0x1e10, 0xf55: 0x1e15, 0xf56: 0x1e1a, 0xf57: 0x1e29,
+ 0xf58: 0x1e2e, 0xf59: 0x1e3d, 0xf5a: 0x1e42, 0xf5b: 0x1e47, 0xf5c: 0x1e56, 0xf5d: 0x1e5b,
+ 0xf5e: 0x1e60, 0xf5f: 0x1e6a, 0xf60: 0x1ea6, 0xf61: 0x1eb5, 0xf62: 0x1ec4, 0xf63: 0x1ec9,
+ 0xf64: 0x1ece, 0xf65: 0x1ed8, 0xf66: 0x1ee7, 0xf67: 0x1eec, 0xf68: 0x1efb, 0xf69: 0x1f00,
+ 0xf6a: 0x1f05, 0xf6b: 0x1f14, 0xf6c: 0x1f19, 0xf6d: 0x1f28, 0xf6e: 0x1f2d, 0xf6f: 0x1f32,
+ 0xf70: 0x1f37, 0xf71: 0x1f3c, 0xf72: 0x1f41, 0xf73: 0x1f46, 0xf74: 0x1f4b, 0xf75: 0x1f50,
+ 0xf76: 0x1f55, 0xf77: 0x1f5a, 0xf78: 0x1f5f, 0xf79: 0x1f64, 0xf7a: 0x1f69, 0xf7b: 0x1f6e,
+ 0xf7c: 0x1f73, 0xf7d: 0x1f78, 0xf7e: 0x1f7d, 0xf7f: 0x1f87,
+ // Block 0x3e, offset 0xf80
+ 0xf80: 0x1f8c, 0xf81: 0x1f91, 0xf82: 0x1f96, 0xf83: 0x1fa0, 0xf84: 0x1fa5, 0xf85: 0x1faf,
+ 0xf86: 0x1fb4, 0xf87: 0x1fb9, 0xf88: 0x1fbe, 0xf89: 0x1fc3, 0xf8a: 0x1fc8, 0xf8b: 0x1fcd,
+ 0xf8c: 0x1fd2, 0xf8d: 0x1fd7, 0xf8e: 0x1fe6, 0xf8f: 0x1ff5, 0xf90: 0x1ffa, 0xf91: 0x1fff,
+ 0xf92: 0x2004, 0xf93: 0x2009, 0xf94: 0x200e, 0xf95: 0x2018, 0xf96: 0x201d, 0xf97: 0x2022,
+ 0xf98: 0x2031, 0xf99: 0x2040, 0xf9a: 0x2045, 0xf9b: 0x44b6, 0xf9c: 0x44bc, 0xf9d: 0x44f2,
+ 0xf9e: 0x4549, 0xf9f: 0x4550, 0xfa0: 0x4557, 0xfa1: 0x455e, 0xfa2: 0x4565, 0xfa3: 0x456c,
+ 0xfa4: 0x25c6, 0xfa5: 0x25cd, 0xfa6: 0x25d4, 0xfa7: 0x25db, 0xfa8: 0x25f0, 0xfa9: 0x25f7,
+ 0xfaa: 0x1d98, 0xfab: 0x1d9d, 0xfac: 0x1da2, 0xfad: 0x1da7, 0xfae: 0x1db1, 0xfaf: 0x1db6,
+ 0xfb0: 0x1dca, 0xfb1: 0x1dcf, 0xfb2: 0x1dd4, 0xfb3: 0x1dd9, 0xfb4: 0x1de3, 0xfb5: 0x1de8,
+ 0xfb6: 0x1df2, 0xfb7: 0x1df7, 0xfb8: 0x1dfc, 0xfb9: 0x1e01, 0xfba: 0x1e0b, 0xfbb: 0x1e10,
+ 0xfbc: 0x1f3c, 0xfbd: 0x1f41, 0xfbe: 0x1f50, 0xfbf: 0x1f55,
+ // Block 0x3f, offset 0xfc0
+ 0xfc0: 0x1f5a, 0xfc1: 0x1f6e, 0xfc2: 0x1f73, 0xfc3: 0x1f78, 0xfc4: 0x1f7d, 0xfc5: 0x1f96,
+ 0xfc6: 0x1fa0, 0xfc7: 0x1fa5, 0xfc8: 0x1faa, 0xfc9: 0x1fbe, 0xfca: 0x1fdc, 0xfcb: 0x1fe1,
+ 0xfcc: 0x1fe6, 0xfcd: 0x1feb, 0xfce: 0x1ff5, 0xfcf: 0x1ffa, 0xfd0: 0x44f2, 0xfd1: 0x2027,
+ 0xfd2: 0x202c, 0xfd3: 0x2031, 0xfd4: 0x2036, 0xfd5: 0x2040, 0xfd6: 0x2045, 0xfd7: 0x25b1,
+ 0xfd8: 0x25b8, 0xfd9: 0x25bf, 0xfda: 0x25d4, 0xfdb: 0x25e2, 0xfdc: 0x1d89, 0xfdd: 0x1d8e,
+ 0xfde: 0x1d93, 0xfdf: 0x1da2, 0xfe0: 0x1dac, 0xfe1: 0x1dbb, 0xfe2: 0x1dc0, 0xfe3: 0x1dc5,
+ 0xfe4: 0x1dd4, 0xfe5: 0x1dde, 0xfe6: 0x1dfc, 0xfe7: 0x1e15, 0xfe8: 0x1e1a, 0xfe9: 0x1e29,
+ 0xfea: 0x1e2e, 0xfeb: 0x1e3d, 0xfec: 0x1e47, 0xfed: 0x1e56, 0xfee: 0x1e5b, 0xfef: 0x1e60,
+ 0xff0: 0x1e6a, 0xff1: 0x1ea6, 0xff2: 0x1eab, 0xff3: 0x1eb5, 0xff4: 0x1ec4, 0xff5: 0x1ec9,
+ 0xff6: 0x1ece, 0xff7: 0x1ed8, 0xff8: 0x1ee7, 0xff9: 0x1efb, 0xffa: 0x1f00, 0xffb: 0x1f05,
+ 0xffc: 0x1f14, 0xffd: 0x1f19, 0xffe: 0x1f28, 0xfff: 0x1f2d,
+ // Block 0x40, offset 0x1000
+ 0x1000: 0x1f32, 0x1001: 0x1f37, 0x1002: 0x1f46, 0x1003: 0x1f4b, 0x1004: 0x1f5f, 0x1005: 0x1f64,
+ 0x1006: 0x1f69, 0x1007: 0x1f6e, 0x1008: 0x1f73, 0x1009: 0x1f87, 0x100a: 0x1f8c, 0x100b: 0x1f91,
+ 0x100c: 0x1f96, 0x100d: 0x1f9b, 0x100e: 0x1faf, 0x100f: 0x1fb4, 0x1010: 0x1fb9, 0x1011: 0x1fbe,
+ 0x1012: 0x1fcd, 0x1013: 0x1fd2, 0x1014: 0x1fd7, 0x1015: 0x1fe6, 0x1016: 0x1ff0, 0x1017: 0x1fff,
+ 0x1018: 0x2004, 0x1019: 0x44e6, 0x101a: 0x2018, 0x101b: 0x201d, 0x101c: 0x2022, 0x101d: 0x2031,
+ 0x101e: 0x203b, 0x101f: 0x25d4, 0x1020: 0x25e2, 0x1021: 0x1da2, 0x1022: 0x1dac, 0x1023: 0x1dd4,
+ 0x1024: 0x1dde, 0x1025: 0x1dfc, 0x1026: 0x1e06, 0x1027: 0x1e6a, 0x1028: 0x1e6f, 0x1029: 0x1e92,
+ 0x102a: 0x1e97, 0x102b: 0x1f6e, 0x102c: 0x1f73, 0x102d: 0x1f96, 0x102e: 0x1fe6, 0x102f: 0x1ff0,
+ 0x1030: 0x2031, 0x1031: 0x203b, 0x1032: 0x459a, 0x1033: 0x45a2, 0x1034: 0x45aa, 0x1035: 0x1ef1,
+ 0x1036: 0x1ef6, 0x1037: 0x1f0a, 0x1038: 0x1f0f, 0x1039: 0x1f1e, 0x103a: 0x1f23, 0x103b: 0x1e74,
+ 0x103c: 0x1e79, 0x103d: 0x1e9c, 0x103e: 0x1ea1, 0x103f: 0x1e33,
+ // Block 0x41, offset 0x1040
+ 0x1040: 0x1e38, 0x1041: 0x1e1f, 0x1042: 0x1e24, 0x1043: 0x1e4c, 0x1044: 0x1e51, 0x1045: 0x1eba,
+ 0x1046: 0x1ebf, 0x1047: 0x1edd, 0x1048: 0x1ee2, 0x1049: 0x1e7e, 0x104a: 0x1e83, 0x104b: 0x1e88,
+ 0x104c: 0x1e92, 0x104d: 0x1e8d, 0x104e: 0x1e65, 0x104f: 0x1eb0, 0x1050: 0x1ed3, 0x1051: 0x1ef1,
+ 0x1052: 0x1ef6, 0x1053: 0x1f0a, 0x1054: 0x1f0f, 0x1055: 0x1f1e, 0x1056: 0x1f23, 0x1057: 0x1e74,
+ 0x1058: 0x1e79, 0x1059: 0x1e9c, 0x105a: 0x1ea1, 0x105b: 0x1e33, 0x105c: 0x1e38, 0x105d: 0x1e1f,
+ 0x105e: 0x1e24, 0x105f: 0x1e4c, 0x1060: 0x1e51, 0x1061: 0x1eba, 0x1062: 0x1ebf, 0x1063: 0x1edd,
+ 0x1064: 0x1ee2, 0x1065: 0x1e7e, 0x1066: 0x1e83, 0x1067: 0x1e88, 0x1068: 0x1e92, 0x1069: 0x1e8d,
+ 0x106a: 0x1e65, 0x106b: 0x1eb0, 0x106c: 0x1ed3, 0x106d: 0x1e7e, 0x106e: 0x1e83, 0x106f: 0x1e88,
+ 0x1070: 0x1e92, 0x1071: 0x1e6f, 0x1072: 0x1e97, 0x1073: 0x1eec, 0x1074: 0x1e56, 0x1075: 0x1e5b,
+ 0x1076: 0x1e60, 0x1077: 0x1e7e, 0x1078: 0x1e83, 0x1079: 0x1e88, 0x107a: 0x1eec, 0x107b: 0x1efb,
+ 0x107c: 0x449e, 0x107d: 0x449e,
+ // Block 0x42, offset 0x1080
+ 0x1090: 0x2311, 0x1091: 0x2326,
+ 0x1092: 0x2326, 0x1093: 0x232d, 0x1094: 0x2334, 0x1095: 0x2349, 0x1096: 0x2350, 0x1097: 0x2357,
+ 0x1098: 0x237a, 0x1099: 0x237a, 0x109a: 0x239d, 0x109b: 0x2396, 0x109c: 0x23b2, 0x109d: 0x23a4,
+ 0x109e: 0x23ab, 0x109f: 0x23ce, 0x10a0: 0x23ce, 0x10a1: 0x23c7, 0x10a2: 0x23d5, 0x10a3: 0x23d5,
+ 0x10a4: 0x23ff, 0x10a5: 0x23ff, 0x10a6: 0x241b, 0x10a7: 0x23e3, 0x10a8: 0x23e3, 0x10a9: 0x23dc,
+ 0x10aa: 0x23f1, 0x10ab: 0x23f1, 0x10ac: 0x23f8, 0x10ad: 0x23f8, 0x10ae: 0x2422, 0x10af: 0x2430,
+ 0x10b0: 0x2430, 0x10b1: 0x2437, 0x10b2: 0x2437, 0x10b3: 0x243e, 0x10b4: 0x2445, 0x10b5: 0x244c,
+ 0x10b6: 0x2453, 0x10b7: 0x2453, 0x10b8: 0x245a, 0x10b9: 0x2468, 0x10ba: 0x2476, 0x10bb: 0x246f,
+ 0x10bc: 0x247d, 0x10bd: 0x247d, 0x10be: 0x2492, 0x10bf: 0x2499,
+ // Block 0x43, offset 0x10c0
+ 0x10c0: 0x24ca, 0x10c1: 0x24d8, 0x10c2: 0x24d1, 0x10c3: 0x24b5, 0x10c4: 0x24b5, 0x10c5: 0x24df,
+ 0x10c6: 0x24df, 0x10c7: 0x24e6, 0x10c8: 0x24e6, 0x10c9: 0x2510, 0x10ca: 0x2517, 0x10cb: 0x251e,
+ 0x10cc: 0x24f4, 0x10cd: 0x2502, 0x10ce: 0x2525, 0x10cf: 0x252c,
+ 0x10d2: 0x24fb, 0x10d3: 0x2580, 0x10d4: 0x2587, 0x10d5: 0x255d, 0x10d6: 0x2564, 0x10d7: 0x2548,
+ 0x10d8: 0x2548, 0x10d9: 0x254f, 0x10da: 0x2579, 0x10db: 0x2572, 0x10dc: 0x259c, 0x10dd: 0x259c,
+ 0x10de: 0x230a, 0x10df: 0x231f, 0x10e0: 0x2318, 0x10e1: 0x2342, 0x10e2: 0x233b, 0x10e3: 0x2365,
+ 0x10e4: 0x235e, 0x10e5: 0x2388, 0x10e6: 0x236c, 0x10e7: 0x2381, 0x10e8: 0x23b9, 0x10e9: 0x2406,
+ 0x10ea: 0x23ea, 0x10eb: 0x2429, 0x10ec: 0x24c3, 0x10ed: 0x24ed, 0x10ee: 0x2595, 0x10ef: 0x258e,
+ 0x10f0: 0x25a3, 0x10f1: 0x253a, 0x10f2: 0x24a0, 0x10f3: 0x256b, 0x10f4: 0x2492, 0x10f5: 0x24ca,
+ 0x10f6: 0x2461, 0x10f7: 0x24ae, 0x10f8: 0x2541, 0x10f9: 0x2533, 0x10fa: 0x24bc, 0x10fb: 0x24a7,
+ 0x10fc: 0x24bc, 0x10fd: 0x2541, 0x10fe: 0x2373, 0x10ff: 0x238f,
+ // Block 0x44, offset 0x1100
+ 0x1100: 0x2509, 0x1101: 0x2484, 0x1102: 0x2303, 0x1103: 0x24a7, 0x1104: 0x244c, 0x1105: 0x241b,
+ 0x1106: 0x23c0, 0x1107: 0x2556,
+ 0x1130: 0x2414, 0x1131: 0x248b, 0x1132: 0x27bf, 0x1133: 0x27b6, 0x1134: 0x27ec, 0x1135: 0x27da,
+ 0x1136: 0x27c8, 0x1137: 0x27e3, 0x1138: 0x27f5, 0x1139: 0x240d, 0x113a: 0x2c7c, 0x113b: 0x2afc,
+ 0x113c: 0x27d1,
+ // Block 0x45, offset 0x1140
+ 0x1150: 0x0019, 0x1151: 0x0483,
+ 0x1152: 0x0487, 0x1153: 0x0035, 0x1154: 0x0037, 0x1155: 0x0003, 0x1156: 0x003f, 0x1157: 0x04bf,
+ 0x1158: 0x04c3, 0x1159: 0x1b5c,
+ 0x1160: 0x8132, 0x1161: 0x8132, 0x1162: 0x8132, 0x1163: 0x8132,
+ 0x1164: 0x8132, 0x1165: 0x8132, 0x1166: 0x8132, 0x1167: 0x812d, 0x1168: 0x812d, 0x1169: 0x812d,
+ 0x116a: 0x812d, 0x116b: 0x812d, 0x116c: 0x812d, 0x116d: 0x812d, 0x116e: 0x8132, 0x116f: 0x8132,
+ 0x1170: 0x1873, 0x1171: 0x0443, 0x1172: 0x043f, 0x1173: 0x007f, 0x1174: 0x007f, 0x1175: 0x0011,
+ 0x1176: 0x0013, 0x1177: 0x00b7, 0x1178: 0x00bb, 0x1179: 0x04b7, 0x117a: 0x04bb, 0x117b: 0x04ab,
+ 0x117c: 0x04af, 0x117d: 0x0493, 0x117e: 0x0497, 0x117f: 0x048b,
+ // Block 0x46, offset 0x1180
+ 0x1180: 0x048f, 0x1181: 0x049b, 0x1182: 0x049f, 0x1183: 0x04a3, 0x1184: 0x04a7,
+ 0x1187: 0x0077, 0x1188: 0x007b, 0x1189: 0x4269, 0x118a: 0x4269, 0x118b: 0x4269,
+ 0x118c: 0x4269, 0x118d: 0x007f, 0x118e: 0x007f, 0x118f: 0x007f, 0x1190: 0x0019, 0x1191: 0x0483,
+ 0x1192: 0x001d, 0x1194: 0x0037, 0x1195: 0x0035, 0x1196: 0x003f, 0x1197: 0x0003,
+ 0x1198: 0x0443, 0x1199: 0x0011, 0x119a: 0x0013, 0x119b: 0x00b7, 0x119c: 0x00bb, 0x119d: 0x04b7,
+ 0x119e: 0x04bb, 0x119f: 0x0007, 0x11a0: 0x000d, 0x11a1: 0x0015, 0x11a2: 0x0017, 0x11a3: 0x001b,
+ 0x11a4: 0x0039, 0x11a5: 0x003d, 0x11a6: 0x003b, 0x11a8: 0x0079, 0x11a9: 0x0009,
+ 0x11aa: 0x000b, 0x11ab: 0x0041,
+ 0x11b0: 0x42aa, 0x11b1: 0x44c2, 0x11b2: 0x42af, 0x11b4: 0x42b4,
+ 0x11b6: 0x42b9, 0x11b7: 0x44c8, 0x11b8: 0x42be, 0x11b9: 0x44ce, 0x11ba: 0x42c3, 0x11bb: 0x44d4,
+ 0x11bc: 0x42c8, 0x11bd: 0x44da, 0x11be: 0x42cd, 0x11bf: 0x44e0,
+ // Block 0x47, offset 0x11c0
+ 0x11c0: 0x0236, 0x11c1: 0x44a4, 0x11c2: 0x44a4, 0x11c3: 0x44aa, 0x11c4: 0x44aa, 0x11c5: 0x44ec,
+ 0x11c6: 0x44ec, 0x11c7: 0x44b0, 0x11c8: 0x44b0, 0x11c9: 0x44f8, 0x11ca: 0x44f8, 0x11cb: 0x44f8,
+ 0x11cc: 0x44f8, 0x11cd: 0x0239, 0x11ce: 0x0239, 0x11cf: 0x023c, 0x11d0: 0x023c, 0x11d1: 0x023c,
+ 0x11d2: 0x023c, 0x11d3: 0x023f, 0x11d4: 0x023f, 0x11d5: 0x0242, 0x11d6: 0x0242, 0x11d7: 0x0242,
+ 0x11d8: 0x0242, 0x11d9: 0x0245, 0x11da: 0x0245, 0x11db: 0x0245, 0x11dc: 0x0245, 0x11dd: 0x0248,
+ 0x11de: 0x0248, 0x11df: 0x0248, 0x11e0: 0x0248, 0x11e1: 0x024b, 0x11e2: 0x024b, 0x11e3: 0x024b,
+ 0x11e4: 0x024b, 0x11e5: 0x024e, 0x11e6: 0x024e, 0x11e7: 0x024e, 0x11e8: 0x024e, 0x11e9: 0x0251,
+ 0x11ea: 0x0251, 0x11eb: 0x0254, 0x11ec: 0x0254, 0x11ed: 0x0257, 0x11ee: 0x0257, 0x11ef: 0x025a,
+ 0x11f0: 0x025a, 0x11f1: 0x025d, 0x11f2: 0x025d, 0x11f3: 0x025d, 0x11f4: 0x025d, 0x11f5: 0x0260,
+ 0x11f6: 0x0260, 0x11f7: 0x0260, 0x11f8: 0x0260, 0x11f9: 0x0263, 0x11fa: 0x0263, 0x11fb: 0x0263,
+ 0x11fc: 0x0263, 0x11fd: 0x0266, 0x11fe: 0x0266, 0x11ff: 0x0266,
+ // Block 0x48, offset 0x1200
+ 0x1200: 0x0266, 0x1201: 0x0269, 0x1202: 0x0269, 0x1203: 0x0269, 0x1204: 0x0269, 0x1205: 0x026c,
+ 0x1206: 0x026c, 0x1207: 0x026c, 0x1208: 0x026c, 0x1209: 0x026f, 0x120a: 0x026f, 0x120b: 0x026f,
+ 0x120c: 0x026f, 0x120d: 0x0272, 0x120e: 0x0272, 0x120f: 0x0272, 0x1210: 0x0272, 0x1211: 0x0275,
+ 0x1212: 0x0275, 0x1213: 0x0275, 0x1214: 0x0275, 0x1215: 0x0278, 0x1216: 0x0278, 0x1217: 0x0278,
+ 0x1218: 0x0278, 0x1219: 0x027b, 0x121a: 0x027b, 0x121b: 0x027b, 0x121c: 0x027b, 0x121d: 0x027e,
+ 0x121e: 0x027e, 0x121f: 0x027e, 0x1220: 0x027e, 0x1221: 0x0281, 0x1222: 0x0281, 0x1223: 0x0281,
+ 0x1224: 0x0281, 0x1225: 0x0284, 0x1226: 0x0284, 0x1227: 0x0284, 0x1228: 0x0284, 0x1229: 0x0287,
+ 0x122a: 0x0287, 0x122b: 0x0287, 0x122c: 0x0287, 0x122d: 0x028a, 0x122e: 0x028a, 0x122f: 0x028d,
+ 0x1230: 0x028d, 0x1231: 0x0290, 0x1232: 0x0290, 0x1233: 0x0290, 0x1234: 0x0290, 0x1235: 0x2e00,
+ 0x1236: 0x2e00, 0x1237: 0x2e08, 0x1238: 0x2e08, 0x1239: 0x2e10, 0x123a: 0x2e10, 0x123b: 0x1f82,
+ 0x123c: 0x1f82,
+ // Block 0x49, offset 0x1240
+ 0x1240: 0x0081, 0x1241: 0x0083, 0x1242: 0x0085, 0x1243: 0x0087, 0x1244: 0x0089, 0x1245: 0x008b,
+ 0x1246: 0x008d, 0x1247: 0x008f, 0x1248: 0x0091, 0x1249: 0x0093, 0x124a: 0x0095, 0x124b: 0x0097,
+ 0x124c: 0x0099, 0x124d: 0x009b, 0x124e: 0x009d, 0x124f: 0x009f, 0x1250: 0x00a1, 0x1251: 0x00a3,
+ 0x1252: 0x00a5, 0x1253: 0x00a7, 0x1254: 0x00a9, 0x1255: 0x00ab, 0x1256: 0x00ad, 0x1257: 0x00af,
+ 0x1258: 0x00b1, 0x1259: 0x00b3, 0x125a: 0x00b5, 0x125b: 0x00b7, 0x125c: 0x00b9, 0x125d: 0x00bb,
+ 0x125e: 0x00bd, 0x125f: 0x0477, 0x1260: 0x047b, 0x1261: 0x0487, 0x1262: 0x049b, 0x1263: 0x049f,
+ 0x1264: 0x0483, 0x1265: 0x05ab, 0x1266: 0x05a3, 0x1267: 0x04c7, 0x1268: 0x04cf, 0x1269: 0x04d7,
+ 0x126a: 0x04df, 0x126b: 0x04e7, 0x126c: 0x056b, 0x126d: 0x0573, 0x126e: 0x057b, 0x126f: 0x051f,
+ 0x1270: 0x05af, 0x1271: 0x04cb, 0x1272: 0x04d3, 0x1273: 0x04db, 0x1274: 0x04e3, 0x1275: 0x04eb,
+ 0x1276: 0x04ef, 0x1277: 0x04f3, 0x1278: 0x04f7, 0x1279: 0x04fb, 0x127a: 0x04ff, 0x127b: 0x0503,
+ 0x127c: 0x0507, 0x127d: 0x050b, 0x127e: 0x050f, 0x127f: 0x0513,
+ // Block 0x4a, offset 0x1280
+ 0x1280: 0x0517, 0x1281: 0x051b, 0x1282: 0x0523, 0x1283: 0x0527, 0x1284: 0x052b, 0x1285: 0x052f,
+ 0x1286: 0x0533, 0x1287: 0x0537, 0x1288: 0x053b, 0x1289: 0x053f, 0x128a: 0x0543, 0x128b: 0x0547,
+ 0x128c: 0x054b, 0x128d: 0x054f, 0x128e: 0x0553, 0x128f: 0x0557, 0x1290: 0x055b, 0x1291: 0x055f,
+ 0x1292: 0x0563, 0x1293: 0x0567, 0x1294: 0x056f, 0x1295: 0x0577, 0x1296: 0x057f, 0x1297: 0x0583,
+ 0x1298: 0x0587, 0x1299: 0x058b, 0x129a: 0x058f, 0x129b: 0x0593, 0x129c: 0x0597, 0x129d: 0x05a7,
+ 0x129e: 0x4a5a, 0x129f: 0x4a60, 0x12a0: 0x03c3, 0x12a1: 0x0313, 0x12a2: 0x0317, 0x12a3: 0x4345,
+ 0x12a4: 0x031b, 0x12a5: 0x434a, 0x12a6: 0x434f, 0x12a7: 0x031f, 0x12a8: 0x0323, 0x12a9: 0x0327,
+ 0x12aa: 0x4354, 0x12ab: 0x4359, 0x12ac: 0x435e, 0x12ad: 0x4363, 0x12ae: 0x4368, 0x12af: 0x436d,
+ 0x12b0: 0x0367, 0x12b1: 0x032b, 0x12b2: 0x032f, 0x12b3: 0x0333, 0x12b4: 0x037b, 0x12b5: 0x0337,
+ 0x12b6: 0x033b, 0x12b7: 0x033f, 0x12b8: 0x0343, 0x12b9: 0x0347, 0x12ba: 0x034b, 0x12bb: 0x034f,
+ 0x12bc: 0x0353, 0x12bd: 0x0357, 0x12be: 0x035b,
+ // Block 0x4b, offset 0x12c0
+ 0x12c2: 0x42dc, 0x12c3: 0x42e1, 0x12c4: 0x42e6, 0x12c5: 0x42eb,
+ 0x12c6: 0x42f0, 0x12c7: 0x42f5, 0x12ca: 0x42fa, 0x12cb: 0x42ff,
+ 0x12cc: 0x4304, 0x12cd: 0x4309, 0x12ce: 0x430e, 0x12cf: 0x4313,
+ 0x12d2: 0x4318, 0x12d3: 0x431d, 0x12d4: 0x4322, 0x12d5: 0x4327, 0x12d6: 0x432c, 0x12d7: 0x4331,
+ 0x12da: 0x4336, 0x12db: 0x433b, 0x12dc: 0x4340,
+ 0x12e0: 0x00bf, 0x12e1: 0x00c2, 0x12e2: 0x00cb, 0x12e3: 0x4264,
+ 0x12e4: 0x00c8, 0x12e5: 0x00c5, 0x12e6: 0x0447, 0x12e8: 0x046b, 0x12e9: 0x044b,
+ 0x12ea: 0x044f, 0x12eb: 0x0453, 0x12ec: 0x0457, 0x12ed: 0x046f, 0x12ee: 0x0473,
+ // Block 0x4c, offset 0x1300
+ 0x1300: 0x0063, 0x1301: 0x0065, 0x1302: 0x0067, 0x1303: 0x0069, 0x1304: 0x006b, 0x1305: 0x006d,
+ 0x1306: 0x006f, 0x1307: 0x0071, 0x1308: 0x0073, 0x1309: 0x0075, 0x130a: 0x0083, 0x130b: 0x0085,
+ 0x130c: 0x0087, 0x130d: 0x0089, 0x130e: 0x008b, 0x130f: 0x008d, 0x1310: 0x008f, 0x1311: 0x0091,
+ 0x1312: 0x0093, 0x1313: 0x0095, 0x1314: 0x0097, 0x1315: 0x0099, 0x1316: 0x009b, 0x1317: 0x009d,
+ 0x1318: 0x009f, 0x1319: 0x00a1, 0x131a: 0x00a3, 0x131b: 0x00a5, 0x131c: 0x00a7, 0x131d: 0x00a9,
+ 0x131e: 0x00ab, 0x131f: 0x00ad, 0x1320: 0x00af, 0x1321: 0x00b1, 0x1322: 0x00b3, 0x1323: 0x00b5,
+ 0x1324: 0x00dd, 0x1325: 0x00f2, 0x1328: 0x0173, 0x1329: 0x0176,
+ 0x132a: 0x0179, 0x132b: 0x017c, 0x132c: 0x017f, 0x132d: 0x0182, 0x132e: 0x0185, 0x132f: 0x0188,
+ 0x1330: 0x018b, 0x1331: 0x018e, 0x1332: 0x0191, 0x1333: 0x0194, 0x1334: 0x0197, 0x1335: 0x019a,
+ 0x1336: 0x019d, 0x1337: 0x01a0, 0x1338: 0x01a3, 0x1339: 0x0188, 0x133a: 0x01a6, 0x133b: 0x01a9,
+ 0x133c: 0x01ac, 0x133d: 0x01af, 0x133e: 0x01b2, 0x133f: 0x01b5,
+ // Block 0x4d, offset 0x1340
+ 0x1340: 0x01fd, 0x1341: 0x0200, 0x1342: 0x0203, 0x1343: 0x045b, 0x1344: 0x01c7, 0x1345: 0x01d0,
+ 0x1346: 0x01d6, 0x1347: 0x01fa, 0x1348: 0x01eb, 0x1349: 0x01e8, 0x134a: 0x0206, 0x134b: 0x0209,
+ 0x134e: 0x0021, 0x134f: 0x0023, 0x1350: 0x0025, 0x1351: 0x0027,
+ 0x1352: 0x0029, 0x1353: 0x002b, 0x1354: 0x002d, 0x1355: 0x002f, 0x1356: 0x0031, 0x1357: 0x0033,
+ 0x1358: 0x0021, 0x1359: 0x0023, 0x135a: 0x0025, 0x135b: 0x0027, 0x135c: 0x0029, 0x135d: 0x002b,
+ 0x135e: 0x002d, 0x135f: 0x002f, 0x1360: 0x0031, 0x1361: 0x0033, 0x1362: 0x0021, 0x1363: 0x0023,
+ 0x1364: 0x0025, 0x1365: 0x0027, 0x1366: 0x0029, 0x1367: 0x002b, 0x1368: 0x002d, 0x1369: 0x002f,
+ 0x136a: 0x0031, 0x136b: 0x0033, 0x136c: 0x0021, 0x136d: 0x0023, 0x136e: 0x0025, 0x136f: 0x0027,
+ 0x1370: 0x0029, 0x1371: 0x002b, 0x1372: 0x002d, 0x1373: 0x002f, 0x1374: 0x0031, 0x1375: 0x0033,
+ 0x1376: 0x0021, 0x1377: 0x0023, 0x1378: 0x0025, 0x1379: 0x0027, 0x137a: 0x0029, 0x137b: 0x002b,
+ 0x137c: 0x002d, 0x137d: 0x002f, 0x137e: 0x0031, 0x137f: 0x0033,
+ // Block 0x4e, offset 0x1380
+ 0x1380: 0x0239, 0x1381: 0x023c, 0x1382: 0x0248, 0x1383: 0x0251, 0x1385: 0x028a,
+ 0x1386: 0x025a, 0x1387: 0x024b, 0x1388: 0x0269, 0x1389: 0x0290, 0x138a: 0x027b, 0x138b: 0x027e,
+ 0x138c: 0x0281, 0x138d: 0x0284, 0x138e: 0x025d, 0x138f: 0x026f, 0x1390: 0x0275, 0x1391: 0x0263,
+ 0x1392: 0x0278, 0x1393: 0x0257, 0x1394: 0x0260, 0x1395: 0x0242, 0x1396: 0x0245, 0x1397: 0x024e,
+ 0x1398: 0x0254, 0x1399: 0x0266, 0x139a: 0x026c, 0x139b: 0x0272, 0x139c: 0x0293, 0x139d: 0x02e4,
+ 0x139e: 0x02cc, 0x139f: 0x0296, 0x13a1: 0x023c, 0x13a2: 0x0248,
+ 0x13a4: 0x0287, 0x13a7: 0x024b, 0x13a9: 0x0290,
+ 0x13aa: 0x027b, 0x13ab: 0x027e, 0x13ac: 0x0281, 0x13ad: 0x0284, 0x13ae: 0x025d, 0x13af: 0x026f,
+ 0x13b0: 0x0275, 0x13b1: 0x0263, 0x13b2: 0x0278, 0x13b4: 0x0260, 0x13b5: 0x0242,
+ 0x13b6: 0x0245, 0x13b7: 0x024e, 0x13b9: 0x0266, 0x13bb: 0x0272,
+ // Block 0x4f, offset 0x13c0
+ 0x13c2: 0x0248,
+ 0x13c7: 0x024b, 0x13c9: 0x0290, 0x13cb: 0x027e,
+ 0x13cd: 0x0284, 0x13ce: 0x025d, 0x13cf: 0x026f, 0x13d1: 0x0263,
+ 0x13d2: 0x0278, 0x13d4: 0x0260, 0x13d7: 0x024e,
+ 0x13d9: 0x0266, 0x13db: 0x0272, 0x13dd: 0x02e4,
+ 0x13df: 0x0296, 0x13e1: 0x023c, 0x13e2: 0x0248,
+ 0x13e4: 0x0287, 0x13e7: 0x024b, 0x13e8: 0x0269, 0x13e9: 0x0290,
+ 0x13ea: 0x027b, 0x13ec: 0x0281, 0x13ed: 0x0284, 0x13ee: 0x025d, 0x13ef: 0x026f,
+ 0x13f0: 0x0275, 0x13f1: 0x0263, 0x13f2: 0x0278, 0x13f4: 0x0260, 0x13f5: 0x0242,
+ 0x13f6: 0x0245, 0x13f7: 0x024e, 0x13f9: 0x0266, 0x13fa: 0x026c, 0x13fb: 0x0272,
+ 0x13fc: 0x0293, 0x13fe: 0x02cc,
+ // Block 0x50, offset 0x1400
+ 0x1400: 0x0239, 0x1401: 0x023c, 0x1402: 0x0248, 0x1403: 0x0251, 0x1404: 0x0287, 0x1405: 0x028a,
+ 0x1406: 0x025a, 0x1407: 0x024b, 0x1408: 0x0269, 0x1409: 0x0290, 0x140b: 0x027e,
+ 0x140c: 0x0281, 0x140d: 0x0284, 0x140e: 0x025d, 0x140f: 0x026f, 0x1410: 0x0275, 0x1411: 0x0263,
+ 0x1412: 0x0278, 0x1413: 0x0257, 0x1414: 0x0260, 0x1415: 0x0242, 0x1416: 0x0245, 0x1417: 0x024e,
+ 0x1418: 0x0254, 0x1419: 0x0266, 0x141a: 0x026c, 0x141b: 0x0272,
+ 0x1421: 0x023c, 0x1422: 0x0248, 0x1423: 0x0251,
+ 0x1425: 0x028a, 0x1426: 0x025a, 0x1427: 0x024b, 0x1428: 0x0269, 0x1429: 0x0290,
+ 0x142b: 0x027e, 0x142c: 0x0281, 0x142d: 0x0284, 0x142e: 0x025d, 0x142f: 0x026f,
+ 0x1430: 0x0275, 0x1431: 0x0263, 0x1432: 0x0278, 0x1433: 0x0257, 0x1434: 0x0260, 0x1435: 0x0242,
+ 0x1436: 0x0245, 0x1437: 0x024e, 0x1438: 0x0254, 0x1439: 0x0266, 0x143a: 0x026c, 0x143b: 0x0272,
+ // Block 0x51, offset 0x1440
+ 0x1440: 0x1879, 0x1441: 0x1876, 0x1442: 0x187c, 0x1443: 0x18a0, 0x1444: 0x18c4, 0x1445: 0x18e8,
+ 0x1446: 0x190c, 0x1447: 0x1915, 0x1448: 0x191b, 0x1449: 0x1921, 0x144a: 0x1927,
+ 0x1450: 0x1a8c, 0x1451: 0x1a90,
+ 0x1452: 0x1a94, 0x1453: 0x1a98, 0x1454: 0x1a9c, 0x1455: 0x1aa0, 0x1456: 0x1aa4, 0x1457: 0x1aa8,
+ 0x1458: 0x1aac, 0x1459: 0x1ab0, 0x145a: 0x1ab4, 0x145b: 0x1ab8, 0x145c: 0x1abc, 0x145d: 0x1ac0,
+ 0x145e: 0x1ac4, 0x145f: 0x1ac8, 0x1460: 0x1acc, 0x1461: 0x1ad0, 0x1462: 0x1ad4, 0x1463: 0x1ad8,
+ 0x1464: 0x1adc, 0x1465: 0x1ae0, 0x1466: 0x1ae4, 0x1467: 0x1ae8, 0x1468: 0x1aec, 0x1469: 0x1af0,
+ 0x146a: 0x271e, 0x146b: 0x0047, 0x146c: 0x0065, 0x146d: 0x193c, 0x146e: 0x19b1,
+ 0x1470: 0x0043, 0x1471: 0x0045, 0x1472: 0x0047, 0x1473: 0x0049, 0x1474: 0x004b, 0x1475: 0x004d,
+ 0x1476: 0x004f, 0x1477: 0x0051, 0x1478: 0x0053, 0x1479: 0x0055, 0x147a: 0x0057, 0x147b: 0x0059,
+ 0x147c: 0x005b, 0x147d: 0x005d, 0x147e: 0x005f, 0x147f: 0x0061,
+ // Block 0x52, offset 0x1480
+ 0x1480: 0x26ad, 0x1481: 0x26c2, 0x1482: 0x0503,
+ 0x1490: 0x0c0f, 0x1491: 0x0a47,
+ 0x1492: 0x08d3, 0x1493: 0x465a, 0x1494: 0x071b, 0x1495: 0x09ef, 0x1496: 0x132f, 0x1497: 0x09ff,
+ 0x1498: 0x0727, 0x1499: 0x0cd7, 0x149a: 0x0eaf, 0x149b: 0x0caf, 0x149c: 0x0827, 0x149d: 0x0b6b,
+ 0x149e: 0x07bf, 0x149f: 0x0cb7, 0x14a0: 0x0813, 0x14a1: 0x1117, 0x14a2: 0x0f83, 0x14a3: 0x138b,
+ 0x14a4: 0x09d3, 0x14a5: 0x090b, 0x14a6: 0x0e63, 0x14a7: 0x0c1b, 0x14a8: 0x0c47, 0x14a9: 0x06bf,
+ 0x14aa: 0x06cb, 0x14ab: 0x140b, 0x14ac: 0x0adb, 0x14ad: 0x06e7, 0x14ae: 0x08ef, 0x14af: 0x0c3b,
+ 0x14b0: 0x13b3, 0x14b1: 0x0c13, 0x14b2: 0x106f, 0x14b3: 0x10ab, 0x14b4: 0x08f7, 0x14b5: 0x0e43,
+ 0x14b6: 0x0d0b, 0x14b7: 0x0d07, 0x14b8: 0x0f97, 0x14b9: 0x082b, 0x14ba: 0x0957, 0x14bb: 0x1443,
+ // Block 0x53, offset 0x14c0
+ 0x14c0: 0x06fb, 0x14c1: 0x06f3, 0x14c2: 0x0703, 0x14c3: 0x1647, 0x14c4: 0x0747, 0x14c5: 0x0757,
+ 0x14c6: 0x075b, 0x14c7: 0x0763, 0x14c8: 0x076b, 0x14c9: 0x076f, 0x14ca: 0x077b, 0x14cb: 0x0773,
+ 0x14cc: 0x05b3, 0x14cd: 0x165b, 0x14ce: 0x078f, 0x14cf: 0x0793, 0x14d0: 0x0797, 0x14d1: 0x07b3,
+ 0x14d2: 0x164c, 0x14d3: 0x05b7, 0x14d4: 0x079f, 0x14d5: 0x07bf, 0x14d6: 0x1656, 0x14d7: 0x07cf,
+ 0x14d8: 0x07d7, 0x14d9: 0x0737, 0x14da: 0x07df, 0x14db: 0x07e3, 0x14dc: 0x1831, 0x14dd: 0x07ff,
+ 0x14de: 0x0807, 0x14df: 0x05bf, 0x14e0: 0x081f, 0x14e1: 0x0823, 0x14e2: 0x082b, 0x14e3: 0x082f,
+ 0x14e4: 0x05c3, 0x14e5: 0x0847, 0x14e6: 0x084b, 0x14e7: 0x0857, 0x14e8: 0x0863, 0x14e9: 0x0867,
+ 0x14ea: 0x086b, 0x14eb: 0x0873, 0x14ec: 0x0893, 0x14ed: 0x0897, 0x14ee: 0x089f, 0x14ef: 0x08af,
+ 0x14f0: 0x08b7, 0x14f1: 0x08bb, 0x14f2: 0x08bb, 0x14f3: 0x08bb, 0x14f4: 0x166a, 0x14f5: 0x0e93,
+ 0x14f6: 0x08cf, 0x14f7: 0x08d7, 0x14f8: 0x166f, 0x14f9: 0x08e3, 0x14fa: 0x08eb, 0x14fb: 0x08f3,
+ 0x14fc: 0x091b, 0x14fd: 0x0907, 0x14fe: 0x0913, 0x14ff: 0x0917,
+ // Block 0x54, offset 0x1500
+ 0x1500: 0x091f, 0x1501: 0x0927, 0x1502: 0x092b, 0x1503: 0x0933, 0x1504: 0x093b, 0x1505: 0x093f,
+ 0x1506: 0x093f, 0x1507: 0x0947, 0x1508: 0x094f, 0x1509: 0x0953, 0x150a: 0x095f, 0x150b: 0x0983,
+ 0x150c: 0x0967, 0x150d: 0x0987, 0x150e: 0x096b, 0x150f: 0x0973, 0x1510: 0x080b, 0x1511: 0x09cf,
+ 0x1512: 0x0997, 0x1513: 0x099b, 0x1514: 0x099f, 0x1515: 0x0993, 0x1516: 0x09a7, 0x1517: 0x09a3,
+ 0x1518: 0x09bb, 0x1519: 0x1674, 0x151a: 0x09d7, 0x151b: 0x09db, 0x151c: 0x09e3, 0x151d: 0x09ef,
+ 0x151e: 0x09f7, 0x151f: 0x0a13, 0x1520: 0x1679, 0x1521: 0x167e, 0x1522: 0x0a1f, 0x1523: 0x0a23,
+ 0x1524: 0x0a27, 0x1525: 0x0a1b, 0x1526: 0x0a2f, 0x1527: 0x05c7, 0x1528: 0x05cb, 0x1529: 0x0a37,
+ 0x152a: 0x0a3f, 0x152b: 0x0a3f, 0x152c: 0x1683, 0x152d: 0x0a5b, 0x152e: 0x0a5f, 0x152f: 0x0a63,
+ 0x1530: 0x0a6b, 0x1531: 0x1688, 0x1532: 0x0a73, 0x1533: 0x0a77, 0x1534: 0x0b4f, 0x1535: 0x0a7f,
+ 0x1536: 0x05cf, 0x1537: 0x0a8b, 0x1538: 0x0a9b, 0x1539: 0x0aa7, 0x153a: 0x0aa3, 0x153b: 0x1692,
+ 0x153c: 0x0aaf, 0x153d: 0x1697, 0x153e: 0x0abb, 0x153f: 0x0ab7,
+ // Block 0x55, offset 0x1540
+ 0x1540: 0x0abf, 0x1541: 0x0acf, 0x1542: 0x0ad3, 0x1543: 0x05d3, 0x1544: 0x0ae3, 0x1545: 0x0aeb,
+ 0x1546: 0x0aef, 0x1547: 0x0af3, 0x1548: 0x05d7, 0x1549: 0x169c, 0x154a: 0x05db, 0x154b: 0x0b0f,
+ 0x154c: 0x0b13, 0x154d: 0x0b17, 0x154e: 0x0b1f, 0x154f: 0x1863, 0x1550: 0x0b37, 0x1551: 0x16a6,
+ 0x1552: 0x16a6, 0x1553: 0x11d7, 0x1554: 0x0b47, 0x1555: 0x0b47, 0x1556: 0x05df, 0x1557: 0x16c9,
+ 0x1558: 0x179b, 0x1559: 0x0b57, 0x155a: 0x0b5f, 0x155b: 0x05e3, 0x155c: 0x0b73, 0x155d: 0x0b83,
+ 0x155e: 0x0b87, 0x155f: 0x0b8f, 0x1560: 0x0b9f, 0x1561: 0x05eb, 0x1562: 0x05e7, 0x1563: 0x0ba3,
+ 0x1564: 0x16ab, 0x1565: 0x0ba7, 0x1566: 0x0bbb, 0x1567: 0x0bbf, 0x1568: 0x0bc3, 0x1569: 0x0bbf,
+ 0x156a: 0x0bcf, 0x156b: 0x0bd3, 0x156c: 0x0be3, 0x156d: 0x0bdb, 0x156e: 0x0bdf, 0x156f: 0x0be7,
+ 0x1570: 0x0beb, 0x1571: 0x0bef, 0x1572: 0x0bfb, 0x1573: 0x0bff, 0x1574: 0x0c17, 0x1575: 0x0c1f,
+ 0x1576: 0x0c2f, 0x1577: 0x0c43, 0x1578: 0x16ba, 0x1579: 0x0c3f, 0x157a: 0x0c33, 0x157b: 0x0c4b,
+ 0x157c: 0x0c53, 0x157d: 0x0c67, 0x157e: 0x16bf, 0x157f: 0x0c6f,
+ // Block 0x56, offset 0x1580
+ 0x1580: 0x0c63, 0x1581: 0x0c5b, 0x1582: 0x05ef, 0x1583: 0x0c77, 0x1584: 0x0c7f, 0x1585: 0x0c87,
+ 0x1586: 0x0c7b, 0x1587: 0x05f3, 0x1588: 0x0c97, 0x1589: 0x0c9f, 0x158a: 0x16c4, 0x158b: 0x0ccb,
+ 0x158c: 0x0cff, 0x158d: 0x0cdb, 0x158e: 0x05ff, 0x158f: 0x0ce7, 0x1590: 0x05fb, 0x1591: 0x05f7,
+ 0x1592: 0x07c3, 0x1593: 0x07c7, 0x1594: 0x0d03, 0x1595: 0x0ceb, 0x1596: 0x11ab, 0x1597: 0x0663,
+ 0x1598: 0x0d0f, 0x1599: 0x0d13, 0x159a: 0x0d17, 0x159b: 0x0d2b, 0x159c: 0x0d23, 0x159d: 0x16dd,
+ 0x159e: 0x0603, 0x159f: 0x0d3f, 0x15a0: 0x0d33, 0x15a1: 0x0d4f, 0x15a2: 0x0d57, 0x15a3: 0x16e7,
+ 0x15a4: 0x0d5b, 0x15a5: 0x0d47, 0x15a6: 0x0d63, 0x15a7: 0x0607, 0x15a8: 0x0d67, 0x15a9: 0x0d6b,
+ 0x15aa: 0x0d6f, 0x15ab: 0x0d7b, 0x15ac: 0x16ec, 0x15ad: 0x0d83, 0x15ae: 0x060b, 0x15af: 0x0d8f,
+ 0x15b0: 0x16f1, 0x15b1: 0x0d93, 0x15b2: 0x060f, 0x15b3: 0x0d9f, 0x15b4: 0x0dab, 0x15b5: 0x0db7,
+ 0x15b6: 0x0dbb, 0x15b7: 0x16f6, 0x15b8: 0x168d, 0x15b9: 0x16fb, 0x15ba: 0x0ddb, 0x15bb: 0x1700,
+ 0x15bc: 0x0de7, 0x15bd: 0x0def, 0x15be: 0x0ddf, 0x15bf: 0x0dfb,
+ // Block 0x57, offset 0x15c0
+ 0x15c0: 0x0e0b, 0x15c1: 0x0e1b, 0x15c2: 0x0e0f, 0x15c3: 0x0e13, 0x15c4: 0x0e1f, 0x15c5: 0x0e23,
+ 0x15c6: 0x1705, 0x15c7: 0x0e07, 0x15c8: 0x0e3b, 0x15c9: 0x0e3f, 0x15ca: 0x0613, 0x15cb: 0x0e53,
+ 0x15cc: 0x0e4f, 0x15cd: 0x170a, 0x15ce: 0x0e33, 0x15cf: 0x0e6f, 0x15d0: 0x170f, 0x15d1: 0x1714,
+ 0x15d2: 0x0e73, 0x15d3: 0x0e87, 0x15d4: 0x0e83, 0x15d5: 0x0e7f, 0x15d6: 0x0617, 0x15d7: 0x0e8b,
+ 0x15d8: 0x0e9b, 0x15d9: 0x0e97, 0x15da: 0x0ea3, 0x15db: 0x1651, 0x15dc: 0x0eb3, 0x15dd: 0x1719,
+ 0x15de: 0x0ebf, 0x15df: 0x1723, 0x15e0: 0x0ed3, 0x15e1: 0x0edf, 0x15e2: 0x0ef3, 0x15e3: 0x1728,
+ 0x15e4: 0x0f07, 0x15e5: 0x0f0b, 0x15e6: 0x172d, 0x15e7: 0x1732, 0x15e8: 0x0f27, 0x15e9: 0x0f37,
+ 0x15ea: 0x061b, 0x15eb: 0x0f3b, 0x15ec: 0x061f, 0x15ed: 0x061f, 0x15ee: 0x0f53, 0x15ef: 0x0f57,
+ 0x15f0: 0x0f5f, 0x15f1: 0x0f63, 0x15f2: 0x0f6f, 0x15f3: 0x0623, 0x15f4: 0x0f87, 0x15f5: 0x1737,
+ 0x15f6: 0x0fa3, 0x15f7: 0x173c, 0x15f8: 0x0faf, 0x15f9: 0x16a1, 0x15fa: 0x0fbf, 0x15fb: 0x1741,
+ 0x15fc: 0x1746, 0x15fd: 0x174b, 0x15fe: 0x0627, 0x15ff: 0x062b,
+ // Block 0x58, offset 0x1600
+ 0x1600: 0x0ff7, 0x1601: 0x1755, 0x1602: 0x1750, 0x1603: 0x175a, 0x1604: 0x175f, 0x1605: 0x0fff,
+ 0x1606: 0x1003, 0x1607: 0x1003, 0x1608: 0x100b, 0x1609: 0x0633, 0x160a: 0x100f, 0x160b: 0x0637,
+ 0x160c: 0x063b, 0x160d: 0x1769, 0x160e: 0x1023, 0x160f: 0x102b, 0x1610: 0x1037, 0x1611: 0x063f,
+ 0x1612: 0x176e, 0x1613: 0x105b, 0x1614: 0x1773, 0x1615: 0x1778, 0x1616: 0x107b, 0x1617: 0x1093,
+ 0x1618: 0x0643, 0x1619: 0x109b, 0x161a: 0x109f, 0x161b: 0x10a3, 0x161c: 0x177d, 0x161d: 0x1782,
+ 0x161e: 0x1782, 0x161f: 0x10bb, 0x1620: 0x0647, 0x1621: 0x1787, 0x1622: 0x10cf, 0x1623: 0x10d3,
+ 0x1624: 0x064b, 0x1625: 0x178c, 0x1626: 0x10ef, 0x1627: 0x064f, 0x1628: 0x10ff, 0x1629: 0x10f7,
+ 0x162a: 0x1107, 0x162b: 0x1796, 0x162c: 0x111f, 0x162d: 0x0653, 0x162e: 0x112b, 0x162f: 0x1133,
+ 0x1630: 0x1143, 0x1631: 0x0657, 0x1632: 0x17a0, 0x1633: 0x17a5, 0x1634: 0x065b, 0x1635: 0x17aa,
+ 0x1636: 0x115b, 0x1637: 0x17af, 0x1638: 0x1167, 0x1639: 0x1173, 0x163a: 0x117b, 0x163b: 0x17b4,
+ 0x163c: 0x17b9, 0x163d: 0x118f, 0x163e: 0x17be, 0x163f: 0x1197,
+ // Block 0x59, offset 0x1640
+ 0x1640: 0x16ce, 0x1641: 0x065f, 0x1642: 0x11af, 0x1643: 0x11b3, 0x1644: 0x0667, 0x1645: 0x11b7,
+ 0x1646: 0x0a33, 0x1647: 0x17c3, 0x1648: 0x17c8, 0x1649: 0x16d3, 0x164a: 0x16d8, 0x164b: 0x11d7,
+ 0x164c: 0x11db, 0x164d: 0x13f3, 0x164e: 0x066b, 0x164f: 0x1207, 0x1650: 0x1203, 0x1651: 0x120b,
+ 0x1652: 0x083f, 0x1653: 0x120f, 0x1654: 0x1213, 0x1655: 0x1217, 0x1656: 0x121f, 0x1657: 0x17cd,
+ 0x1658: 0x121b, 0x1659: 0x1223, 0x165a: 0x1237, 0x165b: 0x123b, 0x165c: 0x1227, 0x165d: 0x123f,
+ 0x165e: 0x1253, 0x165f: 0x1267, 0x1660: 0x1233, 0x1661: 0x1247, 0x1662: 0x124b, 0x1663: 0x124f,
+ 0x1664: 0x17d2, 0x1665: 0x17dc, 0x1666: 0x17d7, 0x1667: 0x066f, 0x1668: 0x126f, 0x1669: 0x1273,
+ 0x166a: 0x127b, 0x166b: 0x17f0, 0x166c: 0x127f, 0x166d: 0x17e1, 0x166e: 0x0673, 0x166f: 0x0677,
+ 0x1670: 0x17e6, 0x1671: 0x17eb, 0x1672: 0x067b, 0x1673: 0x129f, 0x1674: 0x12a3, 0x1675: 0x12a7,
+ 0x1676: 0x12ab, 0x1677: 0x12b7, 0x1678: 0x12b3, 0x1679: 0x12bf, 0x167a: 0x12bb, 0x167b: 0x12cb,
+ 0x167c: 0x12c3, 0x167d: 0x12c7, 0x167e: 0x12cf, 0x167f: 0x067f,
+ // Block 0x5a, offset 0x1680
+ 0x1680: 0x12d7, 0x1681: 0x12db, 0x1682: 0x0683, 0x1683: 0x12eb, 0x1684: 0x12ef, 0x1685: 0x17f5,
+ 0x1686: 0x12fb, 0x1687: 0x12ff, 0x1688: 0x0687, 0x1689: 0x130b, 0x168a: 0x05bb, 0x168b: 0x17fa,
+ 0x168c: 0x17ff, 0x168d: 0x068b, 0x168e: 0x068f, 0x168f: 0x1337, 0x1690: 0x134f, 0x1691: 0x136b,
+ 0x1692: 0x137b, 0x1693: 0x1804, 0x1694: 0x138f, 0x1695: 0x1393, 0x1696: 0x13ab, 0x1697: 0x13b7,
+ 0x1698: 0x180e, 0x1699: 0x1660, 0x169a: 0x13c3, 0x169b: 0x13bf, 0x169c: 0x13cb, 0x169d: 0x1665,
+ 0x169e: 0x13d7, 0x169f: 0x13e3, 0x16a0: 0x1813, 0x16a1: 0x1818, 0x16a2: 0x1423, 0x16a3: 0x142f,
+ 0x16a4: 0x1437, 0x16a5: 0x181d, 0x16a6: 0x143b, 0x16a7: 0x1467, 0x16a8: 0x1473, 0x16a9: 0x1477,
+ 0x16aa: 0x146f, 0x16ab: 0x1483, 0x16ac: 0x1487, 0x16ad: 0x1822, 0x16ae: 0x1493, 0x16af: 0x0693,
+ 0x16b0: 0x149b, 0x16b1: 0x1827, 0x16b2: 0x0697, 0x16b3: 0x14d3, 0x16b4: 0x0ac3, 0x16b5: 0x14eb,
+ 0x16b6: 0x182c, 0x16b7: 0x1836, 0x16b8: 0x069b, 0x16b9: 0x069f, 0x16ba: 0x1513, 0x16bb: 0x183b,
+ 0x16bc: 0x06a3, 0x16bd: 0x1840, 0x16be: 0x152b, 0x16bf: 0x152b,
+ // Block 0x5b, offset 0x16c0
+ 0x16c0: 0x1533, 0x16c1: 0x1845, 0x16c2: 0x154b, 0x16c3: 0x06a7, 0x16c4: 0x155b, 0x16c5: 0x1567,
+ 0x16c6: 0x156f, 0x16c7: 0x1577, 0x16c8: 0x06ab, 0x16c9: 0x184a, 0x16ca: 0x158b, 0x16cb: 0x15a7,
+ 0x16cc: 0x15b3, 0x16cd: 0x06af, 0x16ce: 0x06b3, 0x16cf: 0x15b7, 0x16d0: 0x184f, 0x16d1: 0x06b7,
+ 0x16d2: 0x1854, 0x16d3: 0x1859, 0x16d4: 0x185e, 0x16d5: 0x15db, 0x16d6: 0x06bb, 0x16d7: 0x15ef,
+ 0x16d8: 0x15f7, 0x16d9: 0x15fb, 0x16da: 0x1603, 0x16db: 0x160b, 0x16dc: 0x1613, 0x16dd: 0x1868,
+}
+
+// nfkcIndex: 22 blocks, 1408 entries, 1408 bytes
+// Block 0 is the zero block.
+var nfkcIndex = [1408]uint8{
+ // Block 0x0, offset 0x0
+ // Block 0x1, offset 0x40
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc2: 0x5a, 0xc3: 0x01, 0xc4: 0x02, 0xc5: 0x03, 0xc6: 0x5b, 0xc7: 0x04,
+ 0xc8: 0x05, 0xca: 0x5c, 0xcb: 0x5d, 0xcc: 0x06, 0xcd: 0x07, 0xce: 0x08, 0xcf: 0x09,
+ 0xd0: 0x0a, 0xd1: 0x5e, 0xd2: 0x5f, 0xd3: 0x0b, 0xd6: 0x0c, 0xd7: 0x60,
+ 0xd8: 0x61, 0xd9: 0x0d, 0xdb: 0x62, 0xdc: 0x63, 0xdd: 0x64, 0xdf: 0x65,
+ 0xe0: 0x02, 0xe1: 0x03, 0xe2: 0x04, 0xe3: 0x05,
+ 0xea: 0x06, 0xeb: 0x07, 0xec: 0x08, 0xed: 0x09, 0xef: 0x0a,
+ 0xf0: 0x13,
+ // Block 0x4, offset 0x100
+ 0x120: 0x66, 0x121: 0x67, 0x123: 0x68, 0x124: 0x69, 0x125: 0x6a, 0x126: 0x6b, 0x127: 0x6c,
+ 0x128: 0x6d, 0x129: 0x6e, 0x12a: 0x6f, 0x12b: 0x70, 0x12c: 0x6b, 0x12d: 0x71, 0x12e: 0x72, 0x12f: 0x73,
+ 0x131: 0x74, 0x132: 0x75, 0x133: 0x76, 0x134: 0x77, 0x135: 0x78, 0x137: 0x79,
+ 0x138: 0x7a, 0x139: 0x7b, 0x13a: 0x7c, 0x13b: 0x7d, 0x13c: 0x7e, 0x13d: 0x7f, 0x13e: 0x80, 0x13f: 0x81,
+ // Block 0x5, offset 0x140
+ 0x140: 0x82, 0x142: 0x83, 0x143: 0x84, 0x144: 0x85, 0x145: 0x86, 0x146: 0x87, 0x147: 0x88,
+ 0x14d: 0x89,
+ 0x15c: 0x8a, 0x15f: 0x8b,
+ 0x162: 0x8c, 0x164: 0x8d,
+ 0x168: 0x8e, 0x169: 0x8f, 0x16a: 0x90, 0x16c: 0x0e, 0x16d: 0x91, 0x16e: 0x92, 0x16f: 0x93,
+ 0x170: 0x94, 0x173: 0x95, 0x174: 0x96, 0x175: 0x0f, 0x176: 0x10, 0x177: 0x97,
+ 0x178: 0x11, 0x179: 0x12, 0x17a: 0x13, 0x17b: 0x14, 0x17c: 0x15, 0x17d: 0x16, 0x17e: 0x17, 0x17f: 0x18,
+ // Block 0x6, offset 0x180
+ 0x180: 0x98, 0x181: 0x99, 0x182: 0x9a, 0x183: 0x9b, 0x184: 0x19, 0x185: 0x1a, 0x186: 0x9c, 0x187: 0x9d,
+ 0x188: 0x9e, 0x189: 0x1b, 0x18a: 0x1c, 0x18b: 0x9f, 0x18c: 0xa0,
+ 0x191: 0x1d, 0x192: 0x1e, 0x193: 0xa1,
+ 0x1a8: 0xa2, 0x1a9: 0xa3, 0x1ab: 0xa4,
+ 0x1b1: 0xa5, 0x1b3: 0xa6, 0x1b5: 0xa7, 0x1b7: 0xa8,
+ 0x1ba: 0xa9, 0x1bb: 0xaa, 0x1bc: 0x1f, 0x1bd: 0x20, 0x1be: 0x21, 0x1bf: 0xab,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0xac, 0x1c1: 0x22, 0x1c2: 0x23, 0x1c3: 0x24, 0x1c4: 0xad, 0x1c5: 0x25, 0x1c6: 0x26,
+ 0x1c8: 0x27, 0x1c9: 0x28, 0x1ca: 0x29, 0x1cb: 0x2a, 0x1cc: 0x2b, 0x1cd: 0x2c, 0x1ce: 0x2d, 0x1cf: 0x2e,
+ // Block 0x8, offset 0x200
+ 0x219: 0xae, 0x21a: 0xaf, 0x21b: 0xb0, 0x21d: 0xb1, 0x21f: 0xb2,
+ 0x220: 0xb3, 0x223: 0xb4, 0x224: 0xb5, 0x225: 0xb6, 0x226: 0xb7, 0x227: 0xb8,
+ 0x22a: 0xb9, 0x22b: 0xba, 0x22d: 0xbb, 0x22f: 0xbc,
+ 0x230: 0xbd, 0x231: 0xbe, 0x232: 0xbf, 0x233: 0xc0, 0x234: 0xc1, 0x235: 0xc2, 0x236: 0xc3, 0x237: 0xbd,
+ 0x238: 0xbe, 0x239: 0xbf, 0x23a: 0xc0, 0x23b: 0xc1, 0x23c: 0xc2, 0x23d: 0xc3, 0x23e: 0xbd, 0x23f: 0xbe,
+ // Block 0x9, offset 0x240
+ 0x240: 0xbf, 0x241: 0xc0, 0x242: 0xc1, 0x243: 0xc2, 0x244: 0xc3, 0x245: 0xbd, 0x246: 0xbe, 0x247: 0xbf,
+ 0x248: 0xc0, 0x249: 0xc1, 0x24a: 0xc2, 0x24b: 0xc3, 0x24c: 0xbd, 0x24d: 0xbe, 0x24e: 0xbf, 0x24f: 0xc0,
+ 0x250: 0xc1, 0x251: 0xc2, 0x252: 0xc3, 0x253: 0xbd, 0x254: 0xbe, 0x255: 0xbf, 0x256: 0xc0, 0x257: 0xc1,
+ 0x258: 0xc2, 0x259: 0xc3, 0x25a: 0xbd, 0x25b: 0xbe, 0x25c: 0xbf, 0x25d: 0xc0, 0x25e: 0xc1, 0x25f: 0xc2,
+ 0x260: 0xc3, 0x261: 0xbd, 0x262: 0xbe, 0x263: 0xbf, 0x264: 0xc0, 0x265: 0xc1, 0x266: 0xc2, 0x267: 0xc3,
+ 0x268: 0xbd, 0x269: 0xbe, 0x26a: 0xbf, 0x26b: 0xc0, 0x26c: 0xc1, 0x26d: 0xc2, 0x26e: 0xc3, 0x26f: 0xbd,
+ 0x270: 0xbe, 0x271: 0xbf, 0x272: 0xc0, 0x273: 0xc1, 0x274: 0xc2, 0x275: 0xc3, 0x276: 0xbd, 0x277: 0xbe,
+ 0x278: 0xbf, 0x279: 0xc0, 0x27a: 0xc1, 0x27b: 0xc2, 0x27c: 0xc3, 0x27d: 0xbd, 0x27e: 0xbe, 0x27f: 0xbf,
+ // Block 0xa, offset 0x280
+ 0x280: 0xc0, 0x281: 0xc1, 0x282: 0xc2, 0x283: 0xc3, 0x284: 0xbd, 0x285: 0xbe, 0x286: 0xbf, 0x287: 0xc0,
+ 0x288: 0xc1, 0x289: 0xc2, 0x28a: 0xc3, 0x28b: 0xbd, 0x28c: 0xbe, 0x28d: 0xbf, 0x28e: 0xc0, 0x28f: 0xc1,
+ 0x290: 0xc2, 0x291: 0xc3, 0x292: 0xbd, 0x293: 0xbe, 0x294: 0xbf, 0x295: 0xc0, 0x296: 0xc1, 0x297: 0xc2,
+ 0x298: 0xc3, 0x299: 0xbd, 0x29a: 0xbe, 0x29b: 0xbf, 0x29c: 0xc0, 0x29d: 0xc1, 0x29e: 0xc2, 0x29f: 0xc3,
+ 0x2a0: 0xbd, 0x2a1: 0xbe, 0x2a2: 0xbf, 0x2a3: 0xc0, 0x2a4: 0xc1, 0x2a5: 0xc2, 0x2a6: 0xc3, 0x2a7: 0xbd,
+ 0x2a8: 0xbe, 0x2a9: 0xbf, 0x2aa: 0xc0, 0x2ab: 0xc1, 0x2ac: 0xc2, 0x2ad: 0xc3, 0x2ae: 0xbd, 0x2af: 0xbe,
+ 0x2b0: 0xbf, 0x2b1: 0xc0, 0x2b2: 0xc1, 0x2b3: 0xc2, 0x2b4: 0xc3, 0x2b5: 0xbd, 0x2b6: 0xbe, 0x2b7: 0xbf,
+ 0x2b8: 0xc0, 0x2b9: 0xc1, 0x2ba: 0xc2, 0x2bb: 0xc3, 0x2bc: 0xbd, 0x2bd: 0xbe, 0x2be: 0xbf, 0x2bf: 0xc0,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0xc1, 0x2c1: 0xc2, 0x2c2: 0xc3, 0x2c3: 0xbd, 0x2c4: 0xbe, 0x2c5: 0xbf, 0x2c6: 0xc0, 0x2c7: 0xc1,
+ 0x2c8: 0xc2, 0x2c9: 0xc3, 0x2ca: 0xbd, 0x2cb: 0xbe, 0x2cc: 0xbf, 0x2cd: 0xc0, 0x2ce: 0xc1, 0x2cf: 0xc2,
+ 0x2d0: 0xc3, 0x2d1: 0xbd, 0x2d2: 0xbe, 0x2d3: 0xbf, 0x2d4: 0xc0, 0x2d5: 0xc1, 0x2d6: 0xc2, 0x2d7: 0xc3,
+ 0x2d8: 0xbd, 0x2d9: 0xbe, 0x2da: 0xbf, 0x2db: 0xc0, 0x2dc: 0xc1, 0x2dd: 0xc2, 0x2de: 0xc4,
+ // Block 0xc, offset 0x300
+ 0x324: 0x2f, 0x325: 0x30, 0x326: 0x31, 0x327: 0x32,
+ 0x328: 0x33, 0x329: 0x34, 0x32a: 0x35, 0x32b: 0x36, 0x32c: 0x37, 0x32d: 0x38, 0x32e: 0x39, 0x32f: 0x3a,
+ 0x330: 0x3b, 0x331: 0x3c, 0x332: 0x3d, 0x333: 0x3e, 0x334: 0x3f, 0x335: 0x40, 0x336: 0x41, 0x337: 0x42,
+ 0x338: 0x43, 0x339: 0x44, 0x33a: 0x45, 0x33b: 0x46, 0x33c: 0xc5, 0x33d: 0x47, 0x33e: 0x48, 0x33f: 0x49,
+ // Block 0xd, offset 0x340
+ 0x347: 0xc6,
+ 0x34b: 0xc7, 0x34d: 0xc8,
+ 0x368: 0xc9, 0x36b: 0xca,
+ // Block 0xe, offset 0x380
+ 0x381: 0xcb, 0x382: 0xcc, 0x384: 0xcd, 0x385: 0xb7, 0x387: 0xce,
+ 0x388: 0xcf, 0x38b: 0xd0, 0x38c: 0x6b, 0x38d: 0xd1,
+ 0x391: 0xd2, 0x392: 0xd3, 0x393: 0xd4, 0x396: 0xd5, 0x397: 0xd6,
+ 0x398: 0xd7, 0x39a: 0xd8, 0x39c: 0xd9,
+ 0x3b0: 0xd7,
+ // Block 0xf, offset 0x3c0
+ 0x3eb: 0xda, 0x3ec: 0xdb,
+ // Block 0x10, offset 0x400
+ 0x432: 0xdc,
+ // Block 0x11, offset 0x440
+ 0x445: 0xdd, 0x446: 0xde, 0x447: 0xdf,
+ 0x449: 0xe0,
+ 0x450: 0xe1, 0x451: 0xe2, 0x452: 0xe3, 0x453: 0xe4, 0x454: 0xe5, 0x455: 0xe6, 0x456: 0xe7, 0x457: 0xe8,
+ 0x458: 0xe9, 0x459: 0xea, 0x45a: 0x4a, 0x45b: 0xeb, 0x45c: 0xec, 0x45d: 0xed, 0x45e: 0xee, 0x45f: 0x4b,
+ // Block 0x12, offset 0x480
+ 0x480: 0xef,
+ 0x4a3: 0xf0, 0x4a5: 0xf1,
+ 0x4b8: 0x4c, 0x4b9: 0x4d, 0x4ba: 0x4e,
+ // Block 0x13, offset 0x4c0
+ 0x4c4: 0x4f, 0x4c5: 0xf2, 0x4c6: 0xf3,
+ 0x4c8: 0x50, 0x4c9: 0xf4,
+ // Block 0x14, offset 0x500
+ 0x520: 0x51, 0x521: 0x52, 0x522: 0x53, 0x523: 0x54, 0x524: 0x55, 0x525: 0x56, 0x526: 0x57, 0x527: 0x58,
+ 0x528: 0x59,
+ // Block 0x15, offset 0x540
+ 0x550: 0x0b, 0x551: 0x0c, 0x556: 0x0d,
+ 0x55b: 0x0e, 0x55d: 0x0f, 0x55e: 0x10, 0x55f: 0x11,
+ 0x56f: 0x12,
+}
+
+// nfkcSparseOffset: 155 entries, 310 bytes
+var nfkcSparseOffset = []uint16{0x0, 0xe, 0x12, 0x1b, 0x25, 0x35, 0x37, 0x3c, 0x47, 0x56, 0x63, 0x6b, 0x6f, 0x74, 0x76, 0x87, 0x8f, 0x96, 0x99, 0xa0, 0xa4, 0xa8, 0xaa, 0xac, 0xb5, 0xb9, 0xc0, 0xc5, 0xc8, 0xd2, 0xd4, 0xdb, 0xe3, 0xe7, 0xe9, 0xec, 0xf0, 0xf6, 0x107, 0x113, 0x115, 0x11b, 0x11d, 0x11f, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12c, 0x12f, 0x131, 0x134, 0x137, 0x13b, 0x140, 0x149, 0x14b, 0x14e, 0x150, 0x15b, 0x166, 0x176, 0x184, 0x192, 0x1a2, 0x1b0, 0x1b7, 0x1bd, 0x1cc, 0x1d0, 0x1d2, 0x1d6, 0x1d8, 0x1db, 0x1dd, 0x1e0, 0x1e2, 0x1e5, 0x1e7, 0x1e9, 0x1eb, 0x1f7, 0x201, 0x20b, 0x20e, 0x212, 0x214, 0x216, 0x218, 0x21a, 0x21d, 0x21f, 0x221, 0x223, 0x225, 0x22b, 0x22e, 0x232, 0x234, 0x23b, 0x241, 0x247, 0x24f, 0x255, 0x25b, 0x261, 0x265, 0x267, 0x269, 0x26b, 0x26d, 0x273, 0x276, 0x279, 0x281, 0x288, 0x28b, 0x28e, 0x290, 0x298, 0x29b, 0x2a2, 0x2a5, 0x2ab, 0x2ad, 0x2af, 0x2b2, 0x2b4, 0x2b6, 0x2b8, 0x2ba, 0x2c7, 0x2d1, 0x2d3, 0x2d5, 0x2d9, 0x2de, 0x2ea, 0x2ef, 0x2f8, 0x2fe, 0x303, 0x307, 0x30c, 0x310, 0x320, 0x32e, 0x33c, 0x34a, 0x350, 0x352, 0x355, 0x35f, 0x361}
+
+// nfkcSparseValues: 875 entries, 3500 bytes
+var nfkcSparseValues = [875]valueRange{
+ // Block 0x0, offset 0x0
+ {value: 0x0002, lo: 0x0d},
+ {value: 0x0001, lo: 0xa0, hi: 0xa0},
+ {value: 0x4278, lo: 0xa8, hi: 0xa8},
+ {value: 0x0083, lo: 0xaa, hi: 0xaa},
+ {value: 0x4264, lo: 0xaf, hi: 0xaf},
+ {value: 0x0025, lo: 0xb2, hi: 0xb3},
+ {value: 0x425a, lo: 0xb4, hi: 0xb4},
+ {value: 0x01dc, lo: 0xb5, hi: 0xb5},
+ {value: 0x4291, lo: 0xb8, hi: 0xb8},
+ {value: 0x0023, lo: 0xb9, hi: 0xb9},
+ {value: 0x009f, lo: 0xba, hi: 0xba},
+ {value: 0x221c, lo: 0xbc, hi: 0xbc},
+ {value: 0x2210, lo: 0xbd, hi: 0xbd},
+ {value: 0x22b2, lo: 0xbe, hi: 0xbe},
+ // Block 0x1, offset 0xe
+ {value: 0x0091, lo: 0x03},
+ {value: 0x4778, lo: 0xa0, hi: 0xa1},
+ {value: 0x47aa, lo: 0xaf, hi: 0xb0},
+ {value: 0xa000, lo: 0xb7, hi: 0xb7},
+ // Block 0x2, offset 0x12
+ {value: 0x0003, lo: 0x08},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x0091, lo: 0xb0, hi: 0xb0},
+ {value: 0x0119, lo: 0xb1, hi: 0xb1},
+ {value: 0x0095, lo: 0xb2, hi: 0xb2},
+ {value: 0x00a5, lo: 0xb3, hi: 0xb3},
+ {value: 0x0143, lo: 0xb4, hi: 0xb6},
+ {value: 0x00af, lo: 0xb7, hi: 0xb7},
+ {value: 0x00b3, lo: 0xb8, hi: 0xb8},
+ // Block 0x3, offset 0x1b
+ {value: 0x000a, lo: 0x09},
+ {value: 0x426e, lo: 0x98, hi: 0x98},
+ {value: 0x4273, lo: 0x99, hi: 0x9a},
+ {value: 0x4296, lo: 0x9b, hi: 0x9b},
+ {value: 0x425f, lo: 0x9c, hi: 0x9c},
+ {value: 0x4282, lo: 0x9d, hi: 0x9d},
+ {value: 0x0113, lo: 0xa0, hi: 0xa0},
+ {value: 0x0099, lo: 0xa1, hi: 0xa1},
+ {value: 0x00a7, lo: 0xa2, hi: 0xa3},
+ {value: 0x0167, lo: 0xa4, hi: 0xa4},
+ // Block 0x4, offset 0x25
+ {value: 0x0000, lo: 0x0f},
+ {value: 0xa000, lo: 0x83, hi: 0x83},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0xa000, lo: 0x8b, hi: 0x8b},
+ {value: 0xa000, lo: 0x8d, hi: 0x8d},
+ {value: 0x37a5, lo: 0x90, hi: 0x90},
+ {value: 0x37b1, lo: 0x91, hi: 0x91},
+ {value: 0x379f, lo: 0x93, hi: 0x93},
+ {value: 0xa000, lo: 0x96, hi: 0x96},
+ {value: 0x3817, lo: 0x97, hi: 0x97},
+ {value: 0x37e1, lo: 0x9c, hi: 0x9c},
+ {value: 0x37c9, lo: 0x9d, hi: 0x9d},
+ {value: 0x37f3, lo: 0x9e, hi: 0x9e},
+ {value: 0xa000, lo: 0xb4, hi: 0xb5},
+ {value: 0x381d, lo: 0xb6, hi: 0xb6},
+ {value: 0x3823, lo: 0xb7, hi: 0xb7},
+ // Block 0x5, offset 0x35
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x83, hi: 0x87},
+ // Block 0x6, offset 0x37
+ {value: 0x0001, lo: 0x04},
+ {value: 0x8113, lo: 0x81, hi: 0x82},
+ {value: 0x8132, lo: 0x84, hi: 0x84},
+ {value: 0x812d, lo: 0x85, hi: 0x85},
+ {value: 0x810d, lo: 0x87, hi: 0x87},
+ // Block 0x7, offset 0x3c
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x8132, lo: 0x90, hi: 0x97},
+ {value: 0x8119, lo: 0x98, hi: 0x98},
+ {value: 0x811a, lo: 0x99, hi: 0x99},
+ {value: 0x811b, lo: 0x9a, hi: 0x9a},
+ {value: 0x3841, lo: 0xa2, hi: 0xa2},
+ {value: 0x3847, lo: 0xa3, hi: 0xa3},
+ {value: 0x3853, lo: 0xa4, hi: 0xa4},
+ {value: 0x384d, lo: 0xa5, hi: 0xa5},
+ {value: 0x3859, lo: 0xa6, hi: 0xa6},
+ {value: 0xa000, lo: 0xa7, hi: 0xa7},
+ // Block 0x8, offset 0x47
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x386b, lo: 0x80, hi: 0x80},
+ {value: 0xa000, lo: 0x81, hi: 0x81},
+ {value: 0x385f, lo: 0x82, hi: 0x82},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x3865, lo: 0x93, hi: 0x93},
+ {value: 0xa000, lo: 0x95, hi: 0x95},
+ {value: 0x8132, lo: 0x96, hi: 0x9c},
+ {value: 0x8132, lo: 0x9f, hi: 0xa2},
+ {value: 0x812d, lo: 0xa3, hi: 0xa3},
+ {value: 0x8132, lo: 0xa4, hi: 0xa4},
+ {value: 0x8132, lo: 0xa7, hi: 0xa8},
+ {value: 0x812d, lo: 0xaa, hi: 0xaa},
+ {value: 0x8132, lo: 0xab, hi: 0xac},
+ {value: 0x812d, lo: 0xad, hi: 0xad},
+ // Block 0x9, offset 0x56
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x811f, lo: 0x91, hi: 0x91},
+ {value: 0x8132, lo: 0xb0, hi: 0xb0},
+ {value: 0x812d, lo: 0xb1, hi: 0xb1},
+ {value: 0x8132, lo: 0xb2, hi: 0xb3},
+ {value: 0x812d, lo: 0xb4, hi: 0xb4},
+ {value: 0x8132, lo: 0xb5, hi: 0xb6},
+ {value: 0x812d, lo: 0xb7, hi: 0xb9},
+ {value: 0x8132, lo: 0xba, hi: 0xba},
+ {value: 0x812d, lo: 0xbb, hi: 0xbc},
+ {value: 0x8132, lo: 0xbd, hi: 0xbd},
+ {value: 0x812d, lo: 0xbe, hi: 0xbe},
+ {value: 0x8132, lo: 0xbf, hi: 0xbf},
+ // Block 0xa, offset 0x63
+ {value: 0x0005, lo: 0x07},
+ {value: 0x8132, lo: 0x80, hi: 0x80},
+ {value: 0x8132, lo: 0x81, hi: 0x81},
+ {value: 0x812d, lo: 0x82, hi: 0x83},
+ {value: 0x812d, lo: 0x84, hi: 0x85},
+ {value: 0x812d, lo: 0x86, hi: 0x87},
+ {value: 0x812d, lo: 0x88, hi: 0x89},
+ {value: 0x8132, lo: 0x8a, hi: 0x8a},
+ // Block 0xb, offset 0x6b
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8132, lo: 0xab, hi: 0xb1},
+ {value: 0x812d, lo: 0xb2, hi: 0xb2},
+ {value: 0x8132, lo: 0xb3, hi: 0xb3},
+ // Block 0xc, offset 0x6f
+ {value: 0x0000, lo: 0x04},
+ {value: 0x8132, lo: 0x96, hi: 0x99},
+ {value: 0x8132, lo: 0x9b, hi: 0xa3},
+ {value: 0x8132, lo: 0xa5, hi: 0xa7},
+ {value: 0x8132, lo: 0xa9, hi: 0xad},
+ // Block 0xd, offset 0x74
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x99, hi: 0x9b},
+ // Block 0xe, offset 0x76
+ {value: 0x0000, lo: 0x10},
+ {value: 0x8132, lo: 0x94, hi: 0xa1},
+ {value: 0x812d, lo: 0xa3, hi: 0xa3},
+ {value: 0x8132, lo: 0xa4, hi: 0xa5},
+ {value: 0x812d, lo: 0xa6, hi: 0xa6},
+ {value: 0x8132, lo: 0xa7, hi: 0xa8},
+ {value: 0x812d, lo: 0xa9, hi: 0xa9},
+ {value: 0x8132, lo: 0xaa, hi: 0xac},
+ {value: 0x812d, lo: 0xad, hi: 0xaf},
+ {value: 0x8116, lo: 0xb0, hi: 0xb0},
+ {value: 0x8117, lo: 0xb1, hi: 0xb1},
+ {value: 0x8118, lo: 0xb2, hi: 0xb2},
+ {value: 0x8132, lo: 0xb3, hi: 0xb5},
+ {value: 0x812d, lo: 0xb6, hi: 0xb6},
+ {value: 0x8132, lo: 0xb7, hi: 0xb8},
+ {value: 0x812d, lo: 0xb9, hi: 0xba},
+ {value: 0x8132, lo: 0xbb, hi: 0xbf},
+ // Block 0xf, offset 0x87
+ {value: 0x0000, lo: 0x07},
+ {value: 0xa000, lo: 0xa8, hi: 0xa8},
+ {value: 0x3ed8, lo: 0xa9, hi: 0xa9},
+ {value: 0xa000, lo: 0xb0, hi: 0xb0},
+ {value: 0x3ee0, lo: 0xb1, hi: 0xb1},
+ {value: 0xa000, lo: 0xb3, hi: 0xb3},
+ {value: 0x3ee8, lo: 0xb4, hi: 0xb4},
+ {value: 0x9902, lo: 0xbc, hi: 0xbc},
+ // Block 0x10, offset 0x8f
+ {value: 0x0008, lo: 0x06},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x8132, lo: 0x91, hi: 0x91},
+ {value: 0x812d, lo: 0x92, hi: 0x92},
+ {value: 0x8132, lo: 0x93, hi: 0x93},
+ {value: 0x8132, lo: 0x94, hi: 0x94},
+ {value: 0x45b2, lo: 0x98, hi: 0x9f},
+ // Block 0x11, offset 0x96
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x12, offset 0x99
+ {value: 0x0008, lo: 0x06},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2c9e, lo: 0x8b, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ {value: 0x45f2, lo: 0x9c, hi: 0x9d},
+ {value: 0x4602, lo: 0x9f, hi: 0x9f},
+ // Block 0x13, offset 0xa0
+ {value: 0x0000, lo: 0x03},
+ {value: 0x462a, lo: 0xb3, hi: 0xb3},
+ {value: 0x4632, lo: 0xb6, hi: 0xb6},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ // Block 0x14, offset 0xa4
+ {value: 0x0008, lo: 0x03},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x460a, lo: 0x99, hi: 0x9b},
+ {value: 0x4622, lo: 0x9e, hi: 0x9e},
+ // Block 0x15, offset 0xa8
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ // Block 0x16, offset 0xaa
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ // Block 0x17, offset 0xac
+ {value: 0x0000, lo: 0x08},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2cb6, lo: 0x88, hi: 0x88},
+ {value: 0x2cae, lo: 0x8b, hi: 0x8b},
+ {value: 0x2cbe, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x96, hi: 0x97},
+ {value: 0x463a, lo: 0x9c, hi: 0x9c},
+ {value: 0x4642, lo: 0x9d, hi: 0x9d},
+ // Block 0x18, offset 0xb5
+ {value: 0x0000, lo: 0x03},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0x2cc6, lo: 0x94, hi: 0x94},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x19, offset 0xb9
+ {value: 0x0000, lo: 0x06},
+ {value: 0xa000, lo: 0x86, hi: 0x87},
+ {value: 0x2cce, lo: 0x8a, hi: 0x8a},
+ {value: 0x2cde, lo: 0x8b, hi: 0x8b},
+ {value: 0x2cd6, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ // Block 0x1a, offset 0xc0
+ {value: 0x1801, lo: 0x04},
+ {value: 0xa000, lo: 0x86, hi: 0x86},
+ {value: 0x3ef0, lo: 0x88, hi: 0x88},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x8120, lo: 0x95, hi: 0x96},
+ // Block 0x1b, offset 0xc5
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xbc, hi: 0xbc},
+ {value: 0xa000, lo: 0xbf, hi: 0xbf},
+ // Block 0x1c, offset 0xc8
+ {value: 0x0000, lo: 0x09},
+ {value: 0x2ce6, lo: 0x80, hi: 0x80},
+ {value: 0x9900, lo: 0x82, hi: 0x82},
+ {value: 0xa000, lo: 0x86, hi: 0x86},
+ {value: 0x2cee, lo: 0x87, hi: 0x87},
+ {value: 0x2cf6, lo: 0x88, hi: 0x88},
+ {value: 0x2f50, lo: 0x8a, hi: 0x8a},
+ {value: 0x2dd8, lo: 0x8b, hi: 0x8b},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x95, hi: 0x96},
+ // Block 0x1d, offset 0xd2
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0xbe, hi: 0xbe},
+ // Block 0x1e, offset 0xd4
+ {value: 0x0000, lo: 0x06},
+ {value: 0xa000, lo: 0x86, hi: 0x87},
+ {value: 0x2cfe, lo: 0x8a, hi: 0x8a},
+ {value: 0x2d0e, lo: 0x8b, hi: 0x8b},
+ {value: 0x2d06, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ // Block 0x1f, offset 0xdb
+ {value: 0x6bea, lo: 0x07},
+ {value: 0x9904, lo: 0x8a, hi: 0x8a},
+ {value: 0x9900, lo: 0x8f, hi: 0x8f},
+ {value: 0xa000, lo: 0x99, hi: 0x99},
+ {value: 0x3ef8, lo: 0x9a, hi: 0x9a},
+ {value: 0x2f58, lo: 0x9c, hi: 0x9c},
+ {value: 0x2de3, lo: 0x9d, hi: 0x9d},
+ {value: 0x2d16, lo: 0x9e, hi: 0x9f},
+ // Block 0x20, offset 0xe3
+ {value: 0x0000, lo: 0x03},
+ {value: 0x2621, lo: 0xb3, hi: 0xb3},
+ {value: 0x8122, lo: 0xb8, hi: 0xb9},
+ {value: 0x8104, lo: 0xba, hi: 0xba},
+ // Block 0x21, offset 0xe7
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8123, lo: 0x88, hi: 0x8b},
+ // Block 0x22, offset 0xe9
+ {value: 0x0000, lo: 0x02},
+ {value: 0x2636, lo: 0xb3, hi: 0xb3},
+ {value: 0x8124, lo: 0xb8, hi: 0xb9},
+ // Block 0x23, offset 0xec
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8125, lo: 0x88, hi: 0x8b},
+ {value: 0x2628, lo: 0x9c, hi: 0x9c},
+ {value: 0x262f, lo: 0x9d, hi: 0x9d},
+ // Block 0x24, offset 0xf0
+ {value: 0x0000, lo: 0x05},
+ {value: 0x030b, lo: 0x8c, hi: 0x8c},
+ {value: 0x812d, lo: 0x98, hi: 0x99},
+ {value: 0x812d, lo: 0xb5, hi: 0xb5},
+ {value: 0x812d, lo: 0xb7, hi: 0xb7},
+ {value: 0x812b, lo: 0xb9, hi: 0xb9},
+ // Block 0x25, offset 0xf6
+ {value: 0x0000, lo: 0x10},
+ {value: 0x2644, lo: 0x83, hi: 0x83},
+ {value: 0x264b, lo: 0x8d, hi: 0x8d},
+ {value: 0x2652, lo: 0x92, hi: 0x92},
+ {value: 0x2659, lo: 0x97, hi: 0x97},
+ {value: 0x2660, lo: 0x9c, hi: 0x9c},
+ {value: 0x263d, lo: 0xa9, hi: 0xa9},
+ {value: 0x8126, lo: 0xb1, hi: 0xb1},
+ {value: 0x8127, lo: 0xb2, hi: 0xb2},
+ {value: 0x4a66, lo: 0xb3, hi: 0xb3},
+ {value: 0x8128, lo: 0xb4, hi: 0xb4},
+ {value: 0x4a6f, lo: 0xb5, hi: 0xb5},
+ {value: 0x464a, lo: 0xb6, hi: 0xb6},
+ {value: 0x468a, lo: 0xb7, hi: 0xb7},
+ {value: 0x4652, lo: 0xb8, hi: 0xb8},
+ {value: 0x4695, lo: 0xb9, hi: 0xb9},
+ {value: 0x8127, lo: 0xba, hi: 0xbd},
+ // Block 0x26, offset 0x107
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x8127, lo: 0x80, hi: 0x80},
+ {value: 0x4a78, lo: 0x81, hi: 0x81},
+ {value: 0x8132, lo: 0x82, hi: 0x83},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0x86, hi: 0x87},
+ {value: 0x266e, lo: 0x93, hi: 0x93},
+ {value: 0x2675, lo: 0x9d, hi: 0x9d},
+ {value: 0x267c, lo: 0xa2, hi: 0xa2},
+ {value: 0x2683, lo: 0xa7, hi: 0xa7},
+ {value: 0x268a, lo: 0xac, hi: 0xac},
+ {value: 0x2667, lo: 0xb9, hi: 0xb9},
+ // Block 0x27, offset 0x113
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x86, hi: 0x86},
+ // Block 0x28, offset 0x115
+ {value: 0x0000, lo: 0x05},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x2d1e, lo: 0xa6, hi: 0xa6},
+ {value: 0x9900, lo: 0xae, hi: 0xae},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ {value: 0x8104, lo: 0xb9, hi: 0xba},
+ // Block 0x29, offset 0x11b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x8d, hi: 0x8d},
+ // Block 0x2a, offset 0x11d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x030f, lo: 0xbc, hi: 0xbc},
+ // Block 0x2b, offset 0x11f
+ {value: 0x0000, lo: 0x01},
+ {value: 0xa000, lo: 0x80, hi: 0x92},
+ // Block 0x2c, offset 0x121
+ {value: 0x0000, lo: 0x01},
+ {value: 0xb900, lo: 0xa1, hi: 0xb5},
+ // Block 0x2d, offset 0x123
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0xa8, hi: 0xbf},
+ // Block 0x2e, offset 0x125
+ {value: 0x0000, lo: 0x01},
+ {value: 0x9900, lo: 0x80, hi: 0x82},
+ // Block 0x2f, offset 0x127
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x9d, hi: 0x9f},
+ // Block 0x30, offset 0x129
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x94, hi: 0x94},
+ {value: 0x8104, lo: 0xb4, hi: 0xb4},
+ // Block 0x31, offset 0x12c
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x92, hi: 0x92},
+ {value: 0x8132, lo: 0x9d, hi: 0x9d},
+ // Block 0x32, offset 0x12f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8131, lo: 0xa9, hi: 0xa9},
+ // Block 0x33, offset 0x131
+ {value: 0x0004, lo: 0x02},
+ {value: 0x812e, lo: 0xb9, hi: 0xba},
+ {value: 0x812d, lo: 0xbb, hi: 0xbb},
+ // Block 0x34, offset 0x134
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x97, hi: 0x97},
+ {value: 0x812d, lo: 0x98, hi: 0x98},
+ // Block 0x35, offset 0x137
+ {value: 0x0000, lo: 0x03},
+ {value: 0x8104, lo: 0xa0, hi: 0xa0},
+ {value: 0x8132, lo: 0xb5, hi: 0xbc},
+ {value: 0x812d, lo: 0xbf, hi: 0xbf},
+ // Block 0x36, offset 0x13b
+ {value: 0x0000, lo: 0x04},
+ {value: 0x8132, lo: 0xb0, hi: 0xb4},
+ {value: 0x812d, lo: 0xb5, hi: 0xba},
+ {value: 0x8132, lo: 0xbb, hi: 0xbc},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ // Block 0x37, offset 0x140
+ {value: 0x0000, lo: 0x08},
+ {value: 0x2d66, lo: 0x80, hi: 0x80},
+ {value: 0x2d6e, lo: 0x81, hi: 0x81},
+ {value: 0xa000, lo: 0x82, hi: 0x82},
+ {value: 0x2d76, lo: 0x83, hi: 0x83},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0xab, hi: 0xab},
+ {value: 0x812d, lo: 0xac, hi: 0xac},
+ {value: 0x8132, lo: 0xad, hi: 0xb3},
+ // Block 0x38, offset 0x149
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xaa, hi: 0xab},
+ // Block 0x39, offset 0x14b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8102, lo: 0xa6, hi: 0xa6},
+ {value: 0x8104, lo: 0xb2, hi: 0xb3},
+ // Block 0x3a, offset 0x14e
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ // Block 0x3b, offset 0x150
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x8132, lo: 0x90, hi: 0x92},
+ {value: 0x8101, lo: 0x94, hi: 0x94},
+ {value: 0x812d, lo: 0x95, hi: 0x99},
+ {value: 0x8132, lo: 0x9a, hi: 0x9b},
+ {value: 0x812d, lo: 0x9c, hi: 0x9f},
+ {value: 0x8132, lo: 0xa0, hi: 0xa0},
+ {value: 0x8101, lo: 0xa2, hi: 0xa8},
+ {value: 0x812d, lo: 0xad, hi: 0xad},
+ {value: 0x8132, lo: 0xb4, hi: 0xb4},
+ {value: 0x8132, lo: 0xb8, hi: 0xb9},
+ // Block 0x3c, offset 0x15b
+ {value: 0x0002, lo: 0x0a},
+ {value: 0x0043, lo: 0xac, hi: 0xac},
+ {value: 0x00d1, lo: 0xad, hi: 0xad},
+ {value: 0x0045, lo: 0xae, hi: 0xae},
+ {value: 0x0049, lo: 0xb0, hi: 0xb1},
+ {value: 0x00e6, lo: 0xb2, hi: 0xb2},
+ {value: 0x004f, lo: 0xb3, hi: 0xba},
+ {value: 0x005f, lo: 0xbc, hi: 0xbc},
+ {value: 0x00ef, lo: 0xbd, hi: 0xbd},
+ {value: 0x0061, lo: 0xbe, hi: 0xbe},
+ {value: 0x0065, lo: 0xbf, hi: 0xbf},
+ // Block 0x3d, offset 0x166
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x8132, lo: 0x80, hi: 0x81},
+ {value: 0x812d, lo: 0x82, hi: 0x82},
+ {value: 0x8132, lo: 0x83, hi: 0x89},
+ {value: 0x812d, lo: 0x8a, hi: 0x8a},
+ {value: 0x8132, lo: 0x8b, hi: 0x8c},
+ {value: 0x8135, lo: 0x8d, hi: 0x8d},
+ {value: 0x812a, lo: 0x8e, hi: 0x8e},
+ {value: 0x812d, lo: 0x8f, hi: 0x8f},
+ {value: 0x8129, lo: 0x90, hi: 0x90},
+ {value: 0x8132, lo: 0x91, hi: 0xb5},
+ {value: 0x8132, lo: 0xbb, hi: 0xbb},
+ {value: 0x8134, lo: 0xbc, hi: 0xbc},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ {value: 0x8132, lo: 0xbe, hi: 0xbe},
+ {value: 0x812d, lo: 0xbf, hi: 0xbf},
+ // Block 0x3e, offset 0x176
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x0001, lo: 0x80, hi: 0x8a},
+ {value: 0x043b, lo: 0x91, hi: 0x91},
+ {value: 0x429b, lo: 0x97, hi: 0x97},
+ {value: 0x001d, lo: 0xa4, hi: 0xa4},
+ {value: 0x1873, lo: 0xa5, hi: 0xa5},
+ {value: 0x1b5c, lo: 0xa6, hi: 0xa6},
+ {value: 0x0001, lo: 0xaf, hi: 0xaf},
+ {value: 0x2691, lo: 0xb3, hi: 0xb3},
+ {value: 0x27fe, lo: 0xb4, hi: 0xb4},
+ {value: 0x2698, lo: 0xb6, hi: 0xb6},
+ {value: 0x2808, lo: 0xb7, hi: 0xb7},
+ {value: 0x186d, lo: 0xbc, hi: 0xbc},
+ {value: 0x4269, lo: 0xbe, hi: 0xbe},
+ // Block 0x3f, offset 0x184
+ {value: 0x0002, lo: 0x0d},
+ {value: 0x1933, lo: 0x87, hi: 0x87},
+ {value: 0x1930, lo: 0x88, hi: 0x88},
+ {value: 0x1870, lo: 0x89, hi: 0x89},
+ {value: 0x298e, lo: 0x97, hi: 0x97},
+ {value: 0x0001, lo: 0x9f, hi: 0x9f},
+ {value: 0x0021, lo: 0xb0, hi: 0xb0},
+ {value: 0x0093, lo: 0xb1, hi: 0xb1},
+ {value: 0x0029, lo: 0xb4, hi: 0xb9},
+ {value: 0x0017, lo: 0xba, hi: 0xba},
+ {value: 0x0467, lo: 0xbb, hi: 0xbb},
+ {value: 0x003b, lo: 0xbc, hi: 0xbc},
+ {value: 0x0011, lo: 0xbd, hi: 0xbe},
+ {value: 0x009d, lo: 0xbf, hi: 0xbf},
+ // Block 0x40, offset 0x192
+ {value: 0x0002, lo: 0x0f},
+ {value: 0x0021, lo: 0x80, hi: 0x89},
+ {value: 0x0017, lo: 0x8a, hi: 0x8a},
+ {value: 0x0467, lo: 0x8b, hi: 0x8b},
+ {value: 0x003b, lo: 0x8c, hi: 0x8c},
+ {value: 0x0011, lo: 0x8d, hi: 0x8e},
+ {value: 0x0083, lo: 0x90, hi: 0x90},
+ {value: 0x008b, lo: 0x91, hi: 0x91},
+ {value: 0x009f, lo: 0x92, hi: 0x92},
+ {value: 0x00b1, lo: 0x93, hi: 0x93},
+ {value: 0x0104, lo: 0x94, hi: 0x94},
+ {value: 0x0091, lo: 0x95, hi: 0x95},
+ {value: 0x0097, lo: 0x96, hi: 0x99},
+ {value: 0x00a1, lo: 0x9a, hi: 0x9a},
+ {value: 0x00a7, lo: 0x9b, hi: 0x9c},
+ {value: 0x1999, lo: 0xa8, hi: 0xa8},
+ // Block 0x41, offset 0x1a2
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x8132, lo: 0x90, hi: 0x91},
+ {value: 0x8101, lo: 0x92, hi: 0x93},
+ {value: 0x8132, lo: 0x94, hi: 0x97},
+ {value: 0x8101, lo: 0x98, hi: 0x9a},
+ {value: 0x8132, lo: 0x9b, hi: 0x9c},
+ {value: 0x8132, lo: 0xa1, hi: 0xa1},
+ {value: 0x8101, lo: 0xa5, hi: 0xa6},
+ {value: 0x8132, lo: 0xa7, hi: 0xa7},
+ {value: 0x812d, lo: 0xa8, hi: 0xa8},
+ {value: 0x8132, lo: 0xa9, hi: 0xa9},
+ {value: 0x8101, lo: 0xaa, hi: 0xab},
+ {value: 0x812d, lo: 0xac, hi: 0xaf},
+ {value: 0x8132, lo: 0xb0, hi: 0xb0},
+ // Block 0x42, offset 0x1b0
+ {value: 0x0007, lo: 0x06},
+ {value: 0x2180, lo: 0x89, hi: 0x89},
+ {value: 0xa000, lo: 0x90, hi: 0x90},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0xa000, lo: 0x94, hi: 0x94},
+ {value: 0x3bb9, lo: 0x9a, hi: 0x9b},
+ {value: 0x3bc7, lo: 0xae, hi: 0xae},
+ // Block 0x43, offset 0x1b7
+ {value: 0x000e, lo: 0x05},
+ {value: 0x3bce, lo: 0x8d, hi: 0x8e},
+ {value: 0x3bd5, lo: 0x8f, hi: 0x8f},
+ {value: 0xa000, lo: 0x90, hi: 0x90},
+ {value: 0xa000, lo: 0x92, hi: 0x92},
+ {value: 0xa000, lo: 0x94, hi: 0x94},
+ // Block 0x44, offset 0x1bd
+ {value: 0x0173, lo: 0x0e},
+ {value: 0xa000, lo: 0x83, hi: 0x83},
+ {value: 0x3be3, lo: 0x84, hi: 0x84},
+ {value: 0xa000, lo: 0x88, hi: 0x88},
+ {value: 0x3bea, lo: 0x89, hi: 0x89},
+ {value: 0xa000, lo: 0x8b, hi: 0x8b},
+ {value: 0x3bf1, lo: 0x8c, hi: 0x8c},
+ {value: 0xa000, lo: 0xa3, hi: 0xa3},
+ {value: 0x3bf8, lo: 0xa4, hi: 0xa4},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x3bff, lo: 0xa6, hi: 0xa6},
+ {value: 0x269f, lo: 0xac, hi: 0xad},
+ {value: 0x26a6, lo: 0xaf, hi: 0xaf},
+ {value: 0x281c, lo: 0xb0, hi: 0xb0},
+ {value: 0xa000, lo: 0xbc, hi: 0xbc},
+ // Block 0x45, offset 0x1cc
+ {value: 0x0007, lo: 0x03},
+ {value: 0x3c68, lo: 0xa0, hi: 0xa1},
+ {value: 0x3c92, lo: 0xa2, hi: 0xa3},
+ {value: 0x3cbc, lo: 0xaa, hi: 0xad},
+ // Block 0x46, offset 0x1d0
+ {value: 0x0004, lo: 0x01},
+ {value: 0x048b, lo: 0xa9, hi: 0xaa},
+ // Block 0x47, offset 0x1d2
+ {value: 0x0002, lo: 0x03},
+ {value: 0x0057, lo: 0x80, hi: 0x8f},
+ {value: 0x0083, lo: 0x90, hi: 0xa9},
+ {value: 0x0021, lo: 0xaa, hi: 0xaa},
+ // Block 0x48, offset 0x1d6
+ {value: 0x0000, lo: 0x01},
+ {value: 0x299b, lo: 0x8c, hi: 0x8c},
+ // Block 0x49, offset 0x1d8
+ {value: 0x0263, lo: 0x02},
+ {value: 0x1b8c, lo: 0xb4, hi: 0xb4},
+ {value: 0x192d, lo: 0xb5, hi: 0xb6},
+ // Block 0x4a, offset 0x1db
+ {value: 0x0000, lo: 0x01},
+ {value: 0x4573, lo: 0x9c, hi: 0x9c},
+ // Block 0x4b, offset 0x1dd
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0095, lo: 0xbc, hi: 0xbc},
+ {value: 0x006d, lo: 0xbd, hi: 0xbd},
+ // Block 0x4c, offset 0x1e0
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xaf, hi: 0xb1},
+ // Block 0x4d, offset 0x1e2
+ {value: 0x0000, lo: 0x02},
+ {value: 0x047f, lo: 0xaf, hi: 0xaf},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x4e, offset 0x1e5
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xa0, hi: 0xbf},
+ // Block 0x4f, offset 0x1e7
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0dc3, lo: 0x9f, hi: 0x9f},
+ // Block 0x50, offset 0x1e9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x162f, lo: 0xb3, hi: 0xb3},
+ // Block 0x51, offset 0x1eb
+ {value: 0x0004, lo: 0x0b},
+ {value: 0x1597, lo: 0x80, hi: 0x82},
+ {value: 0x15af, lo: 0x83, hi: 0x83},
+ {value: 0x15c7, lo: 0x84, hi: 0x85},
+ {value: 0x15d7, lo: 0x86, hi: 0x89},
+ {value: 0x15eb, lo: 0x8a, hi: 0x8c},
+ {value: 0x15ff, lo: 0x8d, hi: 0x8d},
+ {value: 0x1607, lo: 0x8e, hi: 0x8e},
+ {value: 0x160f, lo: 0x8f, hi: 0x90},
+ {value: 0x161b, lo: 0x91, hi: 0x93},
+ {value: 0x162b, lo: 0x94, hi: 0x94},
+ {value: 0x1633, lo: 0x95, hi: 0x95},
+ // Block 0x52, offset 0x1f7
+ {value: 0x0004, lo: 0x09},
+ {value: 0x0001, lo: 0x80, hi: 0x80},
+ {value: 0x812c, lo: 0xaa, hi: 0xaa},
+ {value: 0x8131, lo: 0xab, hi: 0xab},
+ {value: 0x8133, lo: 0xac, hi: 0xac},
+ {value: 0x812e, lo: 0xad, hi: 0xad},
+ {value: 0x812f, lo: 0xae, hi: 0xae},
+ {value: 0x812f, lo: 0xaf, hi: 0xaf},
+ {value: 0x04b3, lo: 0xb6, hi: 0xb6},
+ {value: 0x0887, lo: 0xb8, hi: 0xba},
+ // Block 0x53, offset 0x201
+ {value: 0x0005, lo: 0x09},
+ {value: 0x0313, lo: 0xb1, hi: 0xb1},
+ {value: 0x0317, lo: 0xb2, hi: 0xb2},
+ {value: 0x4345, lo: 0xb3, hi: 0xb3},
+ {value: 0x031b, lo: 0xb4, hi: 0xb4},
+ {value: 0x434a, lo: 0xb5, hi: 0xb6},
+ {value: 0x031f, lo: 0xb7, hi: 0xb7},
+ {value: 0x0323, lo: 0xb8, hi: 0xb8},
+ {value: 0x0327, lo: 0xb9, hi: 0xb9},
+ {value: 0x4354, lo: 0xba, hi: 0xbf},
+ // Block 0x54, offset 0x20b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0xaf, hi: 0xaf},
+ {value: 0x8132, lo: 0xb4, hi: 0xbd},
+ // Block 0x55, offset 0x20e
+ {value: 0x0000, lo: 0x03},
+ {value: 0x020f, lo: 0x9c, hi: 0x9c},
+ {value: 0x0212, lo: 0x9d, hi: 0x9d},
+ {value: 0x8132, lo: 0x9e, hi: 0x9f},
+ // Block 0x56, offset 0x212
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb0, hi: 0xb1},
+ // Block 0x57, offset 0x214
+ {value: 0x0000, lo: 0x01},
+ {value: 0x163b, lo: 0xb0, hi: 0xb0},
+ // Block 0x58, offset 0x216
+ {value: 0x000c, lo: 0x01},
+ {value: 0x00d7, lo: 0xb8, hi: 0xb9},
+ // Block 0x59, offset 0x218
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x86, hi: 0x86},
+ // Block 0x5a, offset 0x21a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x84, hi: 0x84},
+ {value: 0x8132, lo: 0xa0, hi: 0xb1},
+ // Block 0x5b, offset 0x21d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xab, hi: 0xad},
+ // Block 0x5c, offset 0x21f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x93, hi: 0x93},
+ // Block 0x5d, offset 0x221
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0xb3, hi: 0xb3},
+ // Block 0x5e, offset 0x223
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0x80, hi: 0x80},
+ // Block 0x5f, offset 0x225
+ {value: 0x0000, lo: 0x05},
+ {value: 0x8132, lo: 0xb0, hi: 0xb0},
+ {value: 0x8132, lo: 0xb2, hi: 0xb3},
+ {value: 0x812d, lo: 0xb4, hi: 0xb4},
+ {value: 0x8132, lo: 0xb7, hi: 0xb8},
+ {value: 0x8132, lo: 0xbe, hi: 0xbf},
+ // Block 0x60, offset 0x22b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x81, hi: 0x81},
+ {value: 0x8104, lo: 0xb6, hi: 0xb6},
+ // Block 0x61, offset 0x22e
+ {value: 0x0008, lo: 0x03},
+ {value: 0x1637, lo: 0x9c, hi: 0x9d},
+ {value: 0x0125, lo: 0x9e, hi: 0x9e},
+ {value: 0x1643, lo: 0x9f, hi: 0x9f},
+ // Block 0x62, offset 0x232
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xad, hi: 0xad},
+ // Block 0x63, offset 0x234
+ {value: 0x0000, lo: 0x06},
+ {value: 0xe500, lo: 0x80, hi: 0x80},
+ {value: 0xc600, lo: 0x81, hi: 0x9b},
+ {value: 0xe500, lo: 0x9c, hi: 0x9c},
+ {value: 0xc600, lo: 0x9d, hi: 0xb7},
+ {value: 0xe500, lo: 0xb8, hi: 0xb8},
+ {value: 0xc600, lo: 0xb9, hi: 0xbf},
+ // Block 0x64, offset 0x23b
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x93},
+ {value: 0xe500, lo: 0x94, hi: 0x94},
+ {value: 0xc600, lo: 0x95, hi: 0xaf},
+ {value: 0xe500, lo: 0xb0, hi: 0xb0},
+ {value: 0xc600, lo: 0xb1, hi: 0xbf},
+ // Block 0x65, offset 0x241
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x8b},
+ {value: 0xe500, lo: 0x8c, hi: 0x8c},
+ {value: 0xc600, lo: 0x8d, hi: 0xa7},
+ {value: 0xe500, lo: 0xa8, hi: 0xa8},
+ {value: 0xc600, lo: 0xa9, hi: 0xbf},
+ // Block 0x66, offset 0x247
+ {value: 0x0000, lo: 0x07},
+ {value: 0xc600, lo: 0x80, hi: 0x83},
+ {value: 0xe500, lo: 0x84, hi: 0x84},
+ {value: 0xc600, lo: 0x85, hi: 0x9f},
+ {value: 0xe500, lo: 0xa0, hi: 0xa0},
+ {value: 0xc600, lo: 0xa1, hi: 0xbb},
+ {value: 0xe500, lo: 0xbc, hi: 0xbc},
+ {value: 0xc600, lo: 0xbd, hi: 0xbf},
+ // Block 0x67, offset 0x24f
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x97},
+ {value: 0xe500, lo: 0x98, hi: 0x98},
+ {value: 0xc600, lo: 0x99, hi: 0xb3},
+ {value: 0xe500, lo: 0xb4, hi: 0xb4},
+ {value: 0xc600, lo: 0xb5, hi: 0xbf},
+ // Block 0x68, offset 0x255
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x8f},
+ {value: 0xe500, lo: 0x90, hi: 0x90},
+ {value: 0xc600, lo: 0x91, hi: 0xab},
+ {value: 0xe500, lo: 0xac, hi: 0xac},
+ {value: 0xc600, lo: 0xad, hi: 0xbf},
+ // Block 0x69, offset 0x25b
+ {value: 0x0000, lo: 0x05},
+ {value: 0xc600, lo: 0x80, hi: 0x87},
+ {value: 0xe500, lo: 0x88, hi: 0x88},
+ {value: 0xc600, lo: 0x89, hi: 0xa3},
+ {value: 0xe500, lo: 0xa4, hi: 0xa4},
+ {value: 0xc600, lo: 0xa5, hi: 0xbf},
+ // Block 0x6a, offset 0x261
+ {value: 0x0000, lo: 0x03},
+ {value: 0xc600, lo: 0x80, hi: 0x87},
+ {value: 0xe500, lo: 0x88, hi: 0x88},
+ {value: 0xc600, lo: 0x89, hi: 0xa3},
+ // Block 0x6b, offset 0x265
+ {value: 0x0002, lo: 0x01},
+ {value: 0x0003, lo: 0x81, hi: 0xbf},
+ // Block 0x6c, offset 0x267
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xbd, hi: 0xbd},
+ // Block 0x6d, offset 0x269
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0xa0, hi: 0xa0},
+ // Block 0x6e, offset 0x26b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb6, hi: 0xba},
+ // Block 0x6f, offset 0x26d
+ {value: 0x002c, lo: 0x05},
+ {value: 0x812d, lo: 0x8d, hi: 0x8d},
+ {value: 0x8132, lo: 0x8f, hi: 0x8f},
+ {value: 0x8132, lo: 0xb8, hi: 0xb8},
+ {value: 0x8101, lo: 0xb9, hi: 0xba},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x70, offset 0x273
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0xa5, hi: 0xa5},
+ {value: 0x812d, lo: 0xa6, hi: 0xa6},
+ // Block 0x71, offset 0x276
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x86, hi: 0x86},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x72, offset 0x279
+ {value: 0x17fe, lo: 0x07},
+ {value: 0xa000, lo: 0x99, hi: 0x99},
+ {value: 0x4238, lo: 0x9a, hi: 0x9a},
+ {value: 0xa000, lo: 0x9b, hi: 0x9b},
+ {value: 0x4242, lo: 0x9c, hi: 0x9c},
+ {value: 0xa000, lo: 0xa5, hi: 0xa5},
+ {value: 0x424c, lo: 0xab, hi: 0xab},
+ {value: 0x8104, lo: 0xb9, hi: 0xba},
+ // Block 0x73, offset 0x281
+ {value: 0x0000, lo: 0x06},
+ {value: 0x8132, lo: 0x80, hi: 0x82},
+ {value: 0x9900, lo: 0xa7, hi: 0xa7},
+ {value: 0x2d7e, lo: 0xae, hi: 0xae},
+ {value: 0x2d88, lo: 0xaf, hi: 0xaf},
+ {value: 0xa000, lo: 0xb1, hi: 0xb2},
+ {value: 0x8104, lo: 0xb3, hi: 0xb4},
+ // Block 0x74, offset 0x288
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x80, hi: 0x80},
+ {value: 0x8102, lo: 0x8a, hi: 0x8a},
+ // Block 0x75, offset 0x28b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0xb5, hi: 0xb5},
+ {value: 0x8102, lo: 0xb6, hi: 0xb6},
+ // Block 0x76, offset 0x28e
+ {value: 0x0002, lo: 0x01},
+ {value: 0x8102, lo: 0xa9, hi: 0xaa},
+ // Block 0x77, offset 0x290
+ {value: 0x0000, lo: 0x07},
+ {value: 0xa000, lo: 0x87, hi: 0x87},
+ {value: 0x2d92, lo: 0x8b, hi: 0x8b},
+ {value: 0x2d9c, lo: 0x8c, hi: 0x8c},
+ {value: 0x8104, lo: 0x8d, hi: 0x8d},
+ {value: 0x9900, lo: 0x97, hi: 0x97},
+ {value: 0x8132, lo: 0xa6, hi: 0xac},
+ {value: 0x8132, lo: 0xb0, hi: 0xb4},
+ // Block 0x78, offset 0x298
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x82, hi: 0x82},
+ {value: 0x8102, lo: 0x86, hi: 0x86},
+ // Block 0x79, offset 0x29b
+ {value: 0x6b5a, lo: 0x06},
+ {value: 0x9900, lo: 0xb0, hi: 0xb0},
+ {value: 0xa000, lo: 0xb9, hi: 0xb9},
+ {value: 0x9900, lo: 0xba, hi: 0xba},
+ {value: 0x2db0, lo: 0xbb, hi: 0xbb},
+ {value: 0x2da6, lo: 0xbc, hi: 0xbd},
+ {value: 0x2dba, lo: 0xbe, hi: 0xbe},
+ // Block 0x7a, offset 0x2a2
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0x82, hi: 0x82},
+ {value: 0x8102, lo: 0x83, hi: 0x83},
+ // Block 0x7b, offset 0x2a5
+ {value: 0x0000, lo: 0x05},
+ {value: 0x9900, lo: 0xaf, hi: 0xaf},
+ {value: 0xa000, lo: 0xb8, hi: 0xb9},
+ {value: 0x2dc4, lo: 0xba, hi: 0xba},
+ {value: 0x2dce, lo: 0xbb, hi: 0xbb},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x7c, offset 0x2ab
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8102, lo: 0x80, hi: 0x80},
+ // Block 0x7d, offset 0x2ad
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xbf, hi: 0xbf},
+ // Block 0x7e, offset 0x2af
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8104, lo: 0xb6, hi: 0xb6},
+ {value: 0x8102, lo: 0xb7, hi: 0xb7},
+ // Block 0x7f, offset 0x2b2
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8104, lo: 0xab, hi: 0xab},
+ // Block 0x80, offset 0x2b4
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8101, lo: 0xb0, hi: 0xb4},
+ // Block 0x81, offset 0x2b6
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0xb0, hi: 0xb6},
+ // Block 0x82, offset 0x2b8
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8101, lo: 0x9e, hi: 0x9e},
+ // Block 0x83, offset 0x2ba
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x4662, lo: 0x9e, hi: 0x9e},
+ {value: 0x466c, lo: 0x9f, hi: 0x9f},
+ {value: 0x46a0, lo: 0xa0, hi: 0xa0},
+ {value: 0x46ae, lo: 0xa1, hi: 0xa1},
+ {value: 0x46bc, lo: 0xa2, hi: 0xa2},
+ {value: 0x46ca, lo: 0xa3, hi: 0xa3},
+ {value: 0x46d8, lo: 0xa4, hi: 0xa4},
+ {value: 0x812b, lo: 0xa5, hi: 0xa6},
+ {value: 0x8101, lo: 0xa7, hi: 0xa9},
+ {value: 0x8130, lo: 0xad, hi: 0xad},
+ {value: 0x812b, lo: 0xae, hi: 0xb2},
+ {value: 0x812d, lo: 0xbb, hi: 0xbf},
+ // Block 0x84, offset 0x2c7
+ {value: 0x0000, lo: 0x09},
+ {value: 0x812d, lo: 0x80, hi: 0x82},
+ {value: 0x8132, lo: 0x85, hi: 0x89},
+ {value: 0x812d, lo: 0x8a, hi: 0x8b},
+ {value: 0x8132, lo: 0xaa, hi: 0xad},
+ {value: 0x4676, lo: 0xbb, hi: 0xbb},
+ {value: 0x4680, lo: 0xbc, hi: 0xbc},
+ {value: 0x46e6, lo: 0xbd, hi: 0xbd},
+ {value: 0x4702, lo: 0xbe, hi: 0xbe},
+ {value: 0x46f4, lo: 0xbf, hi: 0xbf},
+ // Block 0x85, offset 0x2d1
+ {value: 0x0000, lo: 0x01},
+ {value: 0x4710, lo: 0x80, hi: 0x80},
+ // Block 0x86, offset 0x2d3
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8132, lo: 0x82, hi: 0x84},
+ // Block 0x87, offset 0x2d5
+ {value: 0x0002, lo: 0x03},
+ {value: 0x0043, lo: 0x80, hi: 0x99},
+ {value: 0x0083, lo: 0x9a, hi: 0xb3},
+ {value: 0x0043, lo: 0xb4, hi: 0xbf},
+ // Block 0x88, offset 0x2d9
+ {value: 0x0002, lo: 0x04},
+ {value: 0x005b, lo: 0x80, hi: 0x8d},
+ {value: 0x0083, lo: 0x8e, hi: 0x94},
+ {value: 0x0093, lo: 0x96, hi: 0xa7},
+ {value: 0x0043, lo: 0xa8, hi: 0xbf},
+ // Block 0x89, offset 0x2de
+ {value: 0x0002, lo: 0x0b},
+ {value: 0x0073, lo: 0x80, hi: 0x81},
+ {value: 0x0083, lo: 0x82, hi: 0x9b},
+ {value: 0x0043, lo: 0x9c, hi: 0x9c},
+ {value: 0x0047, lo: 0x9e, hi: 0x9f},
+ {value: 0x004f, lo: 0xa2, hi: 0xa2},
+ {value: 0x0055, lo: 0xa5, hi: 0xa6},
+ {value: 0x005d, lo: 0xa9, hi: 0xac},
+ {value: 0x0067, lo: 0xae, hi: 0xb5},
+ {value: 0x0083, lo: 0xb6, hi: 0xb9},
+ {value: 0x008d, lo: 0xbb, hi: 0xbb},
+ {value: 0x0091, lo: 0xbd, hi: 0xbf},
+ // Block 0x8a, offset 0x2ea
+ {value: 0x0002, lo: 0x04},
+ {value: 0x0097, lo: 0x80, hi: 0x83},
+ {value: 0x00a1, lo: 0x85, hi: 0x8f},
+ {value: 0x0043, lo: 0x90, hi: 0xa9},
+ {value: 0x0083, lo: 0xaa, hi: 0xbf},
+ // Block 0x8b, offset 0x2ef
+ {value: 0x0002, lo: 0x08},
+ {value: 0x00af, lo: 0x80, hi: 0x83},
+ {value: 0x0043, lo: 0x84, hi: 0x85},
+ {value: 0x0049, lo: 0x87, hi: 0x8a},
+ {value: 0x0055, lo: 0x8d, hi: 0x94},
+ {value: 0x0067, lo: 0x96, hi: 0x9c},
+ {value: 0x0083, lo: 0x9e, hi: 0xb7},
+ {value: 0x0043, lo: 0xb8, hi: 0xb9},
+ {value: 0x0049, lo: 0xbb, hi: 0xbe},
+ // Block 0x8c, offset 0x2f8
+ {value: 0x0002, lo: 0x05},
+ {value: 0x0053, lo: 0x80, hi: 0x84},
+ {value: 0x005f, lo: 0x86, hi: 0x86},
+ {value: 0x0067, lo: 0x8a, hi: 0x90},
+ {value: 0x0083, lo: 0x92, hi: 0xab},
+ {value: 0x0043, lo: 0xac, hi: 0xbf},
+ // Block 0x8d, offset 0x2fe
+ {value: 0x0002, lo: 0x04},
+ {value: 0x006b, lo: 0x80, hi: 0x85},
+ {value: 0x0083, lo: 0x86, hi: 0x9f},
+ {value: 0x0043, lo: 0xa0, hi: 0xb9},
+ {value: 0x0083, lo: 0xba, hi: 0xbf},
+ // Block 0x8e, offset 0x303
+ {value: 0x0002, lo: 0x03},
+ {value: 0x008f, lo: 0x80, hi: 0x93},
+ {value: 0x0043, lo: 0x94, hi: 0xad},
+ {value: 0x0083, lo: 0xae, hi: 0xbf},
+ // Block 0x8f, offset 0x307
+ {value: 0x0002, lo: 0x04},
+ {value: 0x00a7, lo: 0x80, hi: 0x87},
+ {value: 0x0043, lo: 0x88, hi: 0xa1},
+ {value: 0x0083, lo: 0xa2, hi: 0xbb},
+ {value: 0x0043, lo: 0xbc, hi: 0xbf},
+ // Block 0x90, offset 0x30c
+ {value: 0x0002, lo: 0x03},
+ {value: 0x004b, lo: 0x80, hi: 0x95},
+ {value: 0x0083, lo: 0x96, hi: 0xaf},
+ {value: 0x0043, lo: 0xb0, hi: 0xbf},
+ // Block 0x91, offset 0x310
+ {value: 0x0003, lo: 0x0f},
+ {value: 0x01b8, lo: 0x80, hi: 0x80},
+ {value: 0x045f, lo: 0x81, hi: 0x81},
+ {value: 0x01bb, lo: 0x82, hi: 0x9a},
+ {value: 0x045b, lo: 0x9b, hi: 0x9b},
+ {value: 0x01c7, lo: 0x9c, hi: 0x9c},
+ {value: 0x01d0, lo: 0x9d, hi: 0x9d},
+ {value: 0x01d6, lo: 0x9e, hi: 0x9e},
+ {value: 0x01fa, lo: 0x9f, hi: 0x9f},
+ {value: 0x01eb, lo: 0xa0, hi: 0xa0},
+ {value: 0x01e8, lo: 0xa1, hi: 0xa1},
+ {value: 0x0173, lo: 0xa2, hi: 0xb2},
+ {value: 0x0188, lo: 0xb3, hi: 0xb3},
+ {value: 0x01a6, lo: 0xb4, hi: 0xba},
+ {value: 0x045f, lo: 0xbb, hi: 0xbb},
+ {value: 0x01bb, lo: 0xbc, hi: 0xbf},
+ // Block 0x92, offset 0x320
+ {value: 0x0003, lo: 0x0d},
+ {value: 0x01c7, lo: 0x80, hi: 0x94},
+ {value: 0x045b, lo: 0x95, hi: 0x95},
+ {value: 0x01c7, lo: 0x96, hi: 0x96},
+ {value: 0x01d0, lo: 0x97, hi: 0x97},
+ {value: 0x01d6, lo: 0x98, hi: 0x98},
+ {value: 0x01fa, lo: 0x99, hi: 0x99},
+ {value: 0x01eb, lo: 0x9a, hi: 0x9a},
+ {value: 0x01e8, lo: 0x9b, hi: 0x9b},
+ {value: 0x0173, lo: 0x9c, hi: 0xac},
+ {value: 0x0188, lo: 0xad, hi: 0xad},
+ {value: 0x01a6, lo: 0xae, hi: 0xb4},
+ {value: 0x045f, lo: 0xb5, hi: 0xb5},
+ {value: 0x01bb, lo: 0xb6, hi: 0xbf},
+ // Block 0x93, offset 0x32e
+ {value: 0x0003, lo: 0x0d},
+ {value: 0x01d9, lo: 0x80, hi: 0x8e},
+ {value: 0x045b, lo: 0x8f, hi: 0x8f},
+ {value: 0x01c7, lo: 0x90, hi: 0x90},
+ {value: 0x01d0, lo: 0x91, hi: 0x91},
+ {value: 0x01d6, lo: 0x92, hi: 0x92},
+ {value: 0x01fa, lo: 0x93, hi: 0x93},
+ {value: 0x01eb, lo: 0x94, hi: 0x94},
+ {value: 0x01e8, lo: 0x95, hi: 0x95},
+ {value: 0x0173, lo: 0x96, hi: 0xa6},
+ {value: 0x0188, lo: 0xa7, hi: 0xa7},
+ {value: 0x01a6, lo: 0xa8, hi: 0xae},
+ {value: 0x045f, lo: 0xaf, hi: 0xaf},
+ {value: 0x01bb, lo: 0xb0, hi: 0xbf},
+ // Block 0x94, offset 0x33c
+ {value: 0x0003, lo: 0x0d},
+ {value: 0x01eb, lo: 0x80, hi: 0x88},
+ {value: 0x045b, lo: 0x89, hi: 0x89},
+ {value: 0x01c7, lo: 0x8a, hi: 0x8a},
+ {value: 0x01d0, lo: 0x8b, hi: 0x8b},
+ {value: 0x01d6, lo: 0x8c, hi: 0x8c},
+ {value: 0x01fa, lo: 0x8d, hi: 0x8d},
+ {value: 0x01eb, lo: 0x8e, hi: 0x8e},
+ {value: 0x01e8, lo: 0x8f, hi: 0x8f},
+ {value: 0x0173, lo: 0x90, hi: 0xa0},
+ {value: 0x0188, lo: 0xa1, hi: 0xa1},
+ {value: 0x01a6, lo: 0xa2, hi: 0xa8},
+ {value: 0x045f, lo: 0xa9, hi: 0xa9},
+ {value: 0x01bb, lo: 0xaa, hi: 0xbf},
+ // Block 0x95, offset 0x34a
+ {value: 0x0000, lo: 0x05},
+ {value: 0x8132, lo: 0x80, hi: 0x86},
+ {value: 0x8132, lo: 0x88, hi: 0x98},
+ {value: 0x8132, lo: 0x9b, hi: 0xa1},
+ {value: 0x8132, lo: 0xa3, hi: 0xa4},
+ {value: 0x8132, lo: 0xa6, hi: 0xaa},
+ // Block 0x96, offset 0x350
+ {value: 0x0000, lo: 0x01},
+ {value: 0x812d, lo: 0x90, hi: 0x96},
+ // Block 0x97, offset 0x352
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8132, lo: 0x84, hi: 0x89},
+ {value: 0x8102, lo: 0x8a, hi: 0x8a},
+ // Block 0x98, offset 0x355
+ {value: 0x0002, lo: 0x09},
+ {value: 0x0063, lo: 0x80, hi: 0x89},
+ {value: 0x1951, lo: 0x8a, hi: 0x8a},
+ {value: 0x1981, lo: 0x8b, hi: 0x8b},
+ {value: 0x199c, lo: 0x8c, hi: 0x8c},
+ {value: 0x19a2, lo: 0x8d, hi: 0x8d},
+ {value: 0x1bc0, lo: 0x8e, hi: 0x8e},
+ {value: 0x19ae, lo: 0x8f, hi: 0x8f},
+ {value: 0x197b, lo: 0xaa, hi: 0xaa},
+ {value: 0x197e, lo: 0xab, hi: 0xab},
+ // Block 0x99, offset 0x35f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x193f, lo: 0x90, hi: 0x90},
+ // Block 0x9a, offset 0x361
+ {value: 0x0028, lo: 0x09},
+ {value: 0x2862, lo: 0x80, hi: 0x80},
+ {value: 0x2826, lo: 0x81, hi: 0x81},
+ {value: 0x2830, lo: 0x82, hi: 0x82},
+ {value: 0x2844, lo: 0x83, hi: 0x84},
+ {value: 0x284e, lo: 0x85, hi: 0x86},
+ {value: 0x283a, lo: 0x87, hi: 0x87},
+ {value: 0x2858, lo: 0x88, hi: 0x88},
+ {value: 0x0b6f, lo: 0x90, hi: 0x90},
+ {value: 0x08e7, lo: 0x91, hi: 0x91},
+}
+
+// recompMap: 7520 bytes (entries only)
+var recompMap = map[uint32]rune{
+ 0x00410300: 0x00C0,
+ 0x00410301: 0x00C1,
+ 0x00410302: 0x00C2,
+ 0x00410303: 0x00C3,
+ 0x00410308: 0x00C4,
+ 0x0041030A: 0x00C5,
+ 0x00430327: 0x00C7,
+ 0x00450300: 0x00C8,
+ 0x00450301: 0x00C9,
+ 0x00450302: 0x00CA,
+ 0x00450308: 0x00CB,
+ 0x00490300: 0x00CC,
+ 0x00490301: 0x00CD,
+ 0x00490302: 0x00CE,
+ 0x00490308: 0x00CF,
+ 0x004E0303: 0x00D1,
+ 0x004F0300: 0x00D2,
+ 0x004F0301: 0x00D3,
+ 0x004F0302: 0x00D4,
+ 0x004F0303: 0x00D5,
+ 0x004F0308: 0x00D6,
+ 0x00550300: 0x00D9,
+ 0x00550301: 0x00DA,
+ 0x00550302: 0x00DB,
+ 0x00550308: 0x00DC,
+ 0x00590301: 0x00DD,
+ 0x00610300: 0x00E0,
+ 0x00610301: 0x00E1,
+ 0x00610302: 0x00E2,
+ 0x00610303: 0x00E3,
+ 0x00610308: 0x00E4,
+ 0x0061030A: 0x00E5,
+ 0x00630327: 0x00E7,
+ 0x00650300: 0x00E8,
+ 0x00650301: 0x00E9,
+ 0x00650302: 0x00EA,
+ 0x00650308: 0x00EB,
+ 0x00690300: 0x00EC,
+ 0x00690301: 0x00ED,
+ 0x00690302: 0x00EE,
+ 0x00690308: 0x00EF,
+ 0x006E0303: 0x00F1,
+ 0x006F0300: 0x00F2,
+ 0x006F0301: 0x00F3,
+ 0x006F0302: 0x00F4,
+ 0x006F0303: 0x00F5,
+ 0x006F0308: 0x00F6,
+ 0x00750300: 0x00F9,
+ 0x00750301: 0x00FA,
+ 0x00750302: 0x00FB,
+ 0x00750308: 0x00FC,
+ 0x00790301: 0x00FD,
+ 0x00790308: 0x00FF,
+ 0x00410304: 0x0100,
+ 0x00610304: 0x0101,
+ 0x00410306: 0x0102,
+ 0x00610306: 0x0103,
+ 0x00410328: 0x0104,
+ 0x00610328: 0x0105,
+ 0x00430301: 0x0106,
+ 0x00630301: 0x0107,
+ 0x00430302: 0x0108,
+ 0x00630302: 0x0109,
+ 0x00430307: 0x010A,
+ 0x00630307: 0x010B,
+ 0x0043030C: 0x010C,
+ 0x0063030C: 0x010D,
+ 0x0044030C: 0x010E,
+ 0x0064030C: 0x010F,
+ 0x00450304: 0x0112,
+ 0x00650304: 0x0113,
+ 0x00450306: 0x0114,
+ 0x00650306: 0x0115,
+ 0x00450307: 0x0116,
+ 0x00650307: 0x0117,
+ 0x00450328: 0x0118,
+ 0x00650328: 0x0119,
+ 0x0045030C: 0x011A,
+ 0x0065030C: 0x011B,
+ 0x00470302: 0x011C,
+ 0x00670302: 0x011D,
+ 0x00470306: 0x011E,
+ 0x00670306: 0x011F,
+ 0x00470307: 0x0120,
+ 0x00670307: 0x0121,
+ 0x00470327: 0x0122,
+ 0x00670327: 0x0123,
+ 0x00480302: 0x0124,
+ 0x00680302: 0x0125,
+ 0x00490303: 0x0128,
+ 0x00690303: 0x0129,
+ 0x00490304: 0x012A,
+ 0x00690304: 0x012B,
+ 0x00490306: 0x012C,
+ 0x00690306: 0x012D,
+ 0x00490328: 0x012E,
+ 0x00690328: 0x012F,
+ 0x00490307: 0x0130,
+ 0x004A0302: 0x0134,
+ 0x006A0302: 0x0135,
+ 0x004B0327: 0x0136,
+ 0x006B0327: 0x0137,
+ 0x004C0301: 0x0139,
+ 0x006C0301: 0x013A,
+ 0x004C0327: 0x013B,
+ 0x006C0327: 0x013C,
+ 0x004C030C: 0x013D,
+ 0x006C030C: 0x013E,
+ 0x004E0301: 0x0143,
+ 0x006E0301: 0x0144,
+ 0x004E0327: 0x0145,
+ 0x006E0327: 0x0146,
+ 0x004E030C: 0x0147,
+ 0x006E030C: 0x0148,
+ 0x004F0304: 0x014C,
+ 0x006F0304: 0x014D,
+ 0x004F0306: 0x014E,
+ 0x006F0306: 0x014F,
+ 0x004F030B: 0x0150,
+ 0x006F030B: 0x0151,
+ 0x00520301: 0x0154,
+ 0x00720301: 0x0155,
+ 0x00520327: 0x0156,
+ 0x00720327: 0x0157,
+ 0x0052030C: 0x0158,
+ 0x0072030C: 0x0159,
+ 0x00530301: 0x015A,
+ 0x00730301: 0x015B,
+ 0x00530302: 0x015C,
+ 0x00730302: 0x015D,
+ 0x00530327: 0x015E,
+ 0x00730327: 0x015F,
+ 0x0053030C: 0x0160,
+ 0x0073030C: 0x0161,
+ 0x00540327: 0x0162,
+ 0x00740327: 0x0163,
+ 0x0054030C: 0x0164,
+ 0x0074030C: 0x0165,
+ 0x00550303: 0x0168,
+ 0x00750303: 0x0169,
+ 0x00550304: 0x016A,
+ 0x00750304: 0x016B,
+ 0x00550306: 0x016C,
+ 0x00750306: 0x016D,
+ 0x0055030A: 0x016E,
+ 0x0075030A: 0x016F,
+ 0x0055030B: 0x0170,
+ 0x0075030B: 0x0171,
+ 0x00550328: 0x0172,
+ 0x00750328: 0x0173,
+ 0x00570302: 0x0174,
+ 0x00770302: 0x0175,
+ 0x00590302: 0x0176,
+ 0x00790302: 0x0177,
+ 0x00590308: 0x0178,
+ 0x005A0301: 0x0179,
+ 0x007A0301: 0x017A,
+ 0x005A0307: 0x017B,
+ 0x007A0307: 0x017C,
+ 0x005A030C: 0x017D,
+ 0x007A030C: 0x017E,
+ 0x004F031B: 0x01A0,
+ 0x006F031B: 0x01A1,
+ 0x0055031B: 0x01AF,
+ 0x0075031B: 0x01B0,
+ 0x0041030C: 0x01CD,
+ 0x0061030C: 0x01CE,
+ 0x0049030C: 0x01CF,
+ 0x0069030C: 0x01D0,
+ 0x004F030C: 0x01D1,
+ 0x006F030C: 0x01D2,
+ 0x0055030C: 0x01D3,
+ 0x0075030C: 0x01D4,
+ 0x00DC0304: 0x01D5,
+ 0x00FC0304: 0x01D6,
+ 0x00DC0301: 0x01D7,
+ 0x00FC0301: 0x01D8,
+ 0x00DC030C: 0x01D9,
+ 0x00FC030C: 0x01DA,
+ 0x00DC0300: 0x01DB,
+ 0x00FC0300: 0x01DC,
+ 0x00C40304: 0x01DE,
+ 0x00E40304: 0x01DF,
+ 0x02260304: 0x01E0,
+ 0x02270304: 0x01E1,
+ 0x00C60304: 0x01E2,
+ 0x00E60304: 0x01E3,
+ 0x0047030C: 0x01E6,
+ 0x0067030C: 0x01E7,
+ 0x004B030C: 0x01E8,
+ 0x006B030C: 0x01E9,
+ 0x004F0328: 0x01EA,
+ 0x006F0328: 0x01EB,
+ 0x01EA0304: 0x01EC,
+ 0x01EB0304: 0x01ED,
+ 0x01B7030C: 0x01EE,
+ 0x0292030C: 0x01EF,
+ 0x006A030C: 0x01F0,
+ 0x00470301: 0x01F4,
+ 0x00670301: 0x01F5,
+ 0x004E0300: 0x01F8,
+ 0x006E0300: 0x01F9,
+ 0x00C50301: 0x01FA,
+ 0x00E50301: 0x01FB,
+ 0x00C60301: 0x01FC,
+ 0x00E60301: 0x01FD,
+ 0x00D80301: 0x01FE,
+ 0x00F80301: 0x01FF,
+ 0x0041030F: 0x0200,
+ 0x0061030F: 0x0201,
+ 0x00410311: 0x0202,
+ 0x00610311: 0x0203,
+ 0x0045030F: 0x0204,
+ 0x0065030F: 0x0205,
+ 0x00450311: 0x0206,
+ 0x00650311: 0x0207,
+ 0x0049030F: 0x0208,
+ 0x0069030F: 0x0209,
+ 0x00490311: 0x020A,
+ 0x00690311: 0x020B,
+ 0x004F030F: 0x020C,
+ 0x006F030F: 0x020D,
+ 0x004F0311: 0x020E,
+ 0x006F0311: 0x020F,
+ 0x0052030F: 0x0210,
+ 0x0072030F: 0x0211,
+ 0x00520311: 0x0212,
+ 0x00720311: 0x0213,
+ 0x0055030F: 0x0214,
+ 0x0075030F: 0x0215,
+ 0x00550311: 0x0216,
+ 0x00750311: 0x0217,
+ 0x00530326: 0x0218,
+ 0x00730326: 0x0219,
+ 0x00540326: 0x021A,
+ 0x00740326: 0x021B,
+ 0x0048030C: 0x021E,
+ 0x0068030C: 0x021F,
+ 0x00410307: 0x0226,
+ 0x00610307: 0x0227,
+ 0x00450327: 0x0228,
+ 0x00650327: 0x0229,
+ 0x00D60304: 0x022A,
+ 0x00F60304: 0x022B,
+ 0x00D50304: 0x022C,
+ 0x00F50304: 0x022D,
+ 0x004F0307: 0x022E,
+ 0x006F0307: 0x022F,
+ 0x022E0304: 0x0230,
+ 0x022F0304: 0x0231,
+ 0x00590304: 0x0232,
+ 0x00790304: 0x0233,
+ 0x00A80301: 0x0385,
+ 0x03910301: 0x0386,
+ 0x03950301: 0x0388,
+ 0x03970301: 0x0389,
+ 0x03990301: 0x038A,
+ 0x039F0301: 0x038C,
+ 0x03A50301: 0x038E,
+ 0x03A90301: 0x038F,
+ 0x03CA0301: 0x0390,
+ 0x03990308: 0x03AA,
+ 0x03A50308: 0x03AB,
+ 0x03B10301: 0x03AC,
+ 0x03B50301: 0x03AD,
+ 0x03B70301: 0x03AE,
+ 0x03B90301: 0x03AF,
+ 0x03CB0301: 0x03B0,
+ 0x03B90308: 0x03CA,
+ 0x03C50308: 0x03CB,
+ 0x03BF0301: 0x03CC,
+ 0x03C50301: 0x03CD,
+ 0x03C90301: 0x03CE,
+ 0x03D20301: 0x03D3,
+ 0x03D20308: 0x03D4,
+ 0x04150300: 0x0400,
+ 0x04150308: 0x0401,
+ 0x04130301: 0x0403,
+ 0x04060308: 0x0407,
+ 0x041A0301: 0x040C,
+ 0x04180300: 0x040D,
+ 0x04230306: 0x040E,
+ 0x04180306: 0x0419,
+ 0x04380306: 0x0439,
+ 0x04350300: 0x0450,
+ 0x04350308: 0x0451,
+ 0x04330301: 0x0453,
+ 0x04560308: 0x0457,
+ 0x043A0301: 0x045C,
+ 0x04380300: 0x045D,
+ 0x04430306: 0x045E,
+ 0x0474030F: 0x0476,
+ 0x0475030F: 0x0477,
+ 0x04160306: 0x04C1,
+ 0x04360306: 0x04C2,
+ 0x04100306: 0x04D0,
+ 0x04300306: 0x04D1,
+ 0x04100308: 0x04D2,
+ 0x04300308: 0x04D3,
+ 0x04150306: 0x04D6,
+ 0x04350306: 0x04D7,
+ 0x04D80308: 0x04DA,
+ 0x04D90308: 0x04DB,
+ 0x04160308: 0x04DC,
+ 0x04360308: 0x04DD,
+ 0x04170308: 0x04DE,
+ 0x04370308: 0x04DF,
+ 0x04180304: 0x04E2,
+ 0x04380304: 0x04E3,
+ 0x04180308: 0x04E4,
+ 0x04380308: 0x04E5,
+ 0x041E0308: 0x04E6,
+ 0x043E0308: 0x04E7,
+ 0x04E80308: 0x04EA,
+ 0x04E90308: 0x04EB,
+ 0x042D0308: 0x04EC,
+ 0x044D0308: 0x04ED,
+ 0x04230304: 0x04EE,
+ 0x04430304: 0x04EF,
+ 0x04230308: 0x04F0,
+ 0x04430308: 0x04F1,
+ 0x0423030B: 0x04F2,
+ 0x0443030B: 0x04F3,
+ 0x04270308: 0x04F4,
+ 0x04470308: 0x04F5,
+ 0x042B0308: 0x04F8,
+ 0x044B0308: 0x04F9,
+ 0x06270653: 0x0622,
+ 0x06270654: 0x0623,
+ 0x06480654: 0x0624,
+ 0x06270655: 0x0625,
+ 0x064A0654: 0x0626,
+ 0x06D50654: 0x06C0,
+ 0x06C10654: 0x06C2,
+ 0x06D20654: 0x06D3,
+ 0x0928093C: 0x0929,
+ 0x0930093C: 0x0931,
+ 0x0933093C: 0x0934,
+ 0x09C709BE: 0x09CB,
+ 0x09C709D7: 0x09CC,
+ 0x0B470B56: 0x0B48,
+ 0x0B470B3E: 0x0B4B,
+ 0x0B470B57: 0x0B4C,
+ 0x0B920BD7: 0x0B94,
+ 0x0BC60BBE: 0x0BCA,
+ 0x0BC70BBE: 0x0BCB,
+ 0x0BC60BD7: 0x0BCC,
+ 0x0C460C56: 0x0C48,
+ 0x0CBF0CD5: 0x0CC0,
+ 0x0CC60CD5: 0x0CC7,
+ 0x0CC60CD6: 0x0CC8,
+ 0x0CC60CC2: 0x0CCA,
+ 0x0CCA0CD5: 0x0CCB,
+ 0x0D460D3E: 0x0D4A,
+ 0x0D470D3E: 0x0D4B,
+ 0x0D460D57: 0x0D4C,
+ 0x0DD90DCA: 0x0DDA,
+ 0x0DD90DCF: 0x0DDC,
+ 0x0DDC0DCA: 0x0DDD,
+ 0x0DD90DDF: 0x0DDE,
+ 0x1025102E: 0x1026,
+ 0x1B051B35: 0x1B06,
+ 0x1B071B35: 0x1B08,
+ 0x1B091B35: 0x1B0A,
+ 0x1B0B1B35: 0x1B0C,
+ 0x1B0D1B35: 0x1B0E,
+ 0x1B111B35: 0x1B12,
+ 0x1B3A1B35: 0x1B3B,
+ 0x1B3C1B35: 0x1B3D,
+ 0x1B3E1B35: 0x1B40,
+ 0x1B3F1B35: 0x1B41,
+ 0x1B421B35: 0x1B43,
+ 0x00410325: 0x1E00,
+ 0x00610325: 0x1E01,
+ 0x00420307: 0x1E02,
+ 0x00620307: 0x1E03,
+ 0x00420323: 0x1E04,
+ 0x00620323: 0x1E05,
+ 0x00420331: 0x1E06,
+ 0x00620331: 0x1E07,
+ 0x00C70301: 0x1E08,
+ 0x00E70301: 0x1E09,
+ 0x00440307: 0x1E0A,
+ 0x00640307: 0x1E0B,
+ 0x00440323: 0x1E0C,
+ 0x00640323: 0x1E0D,
+ 0x00440331: 0x1E0E,
+ 0x00640331: 0x1E0F,
+ 0x00440327: 0x1E10,
+ 0x00640327: 0x1E11,
+ 0x0044032D: 0x1E12,
+ 0x0064032D: 0x1E13,
+ 0x01120300: 0x1E14,
+ 0x01130300: 0x1E15,
+ 0x01120301: 0x1E16,
+ 0x01130301: 0x1E17,
+ 0x0045032D: 0x1E18,
+ 0x0065032D: 0x1E19,
+ 0x00450330: 0x1E1A,
+ 0x00650330: 0x1E1B,
+ 0x02280306: 0x1E1C,
+ 0x02290306: 0x1E1D,
+ 0x00460307: 0x1E1E,
+ 0x00660307: 0x1E1F,
+ 0x00470304: 0x1E20,
+ 0x00670304: 0x1E21,
+ 0x00480307: 0x1E22,
+ 0x00680307: 0x1E23,
+ 0x00480323: 0x1E24,
+ 0x00680323: 0x1E25,
+ 0x00480308: 0x1E26,
+ 0x00680308: 0x1E27,
+ 0x00480327: 0x1E28,
+ 0x00680327: 0x1E29,
+ 0x0048032E: 0x1E2A,
+ 0x0068032E: 0x1E2B,
+ 0x00490330: 0x1E2C,
+ 0x00690330: 0x1E2D,
+ 0x00CF0301: 0x1E2E,
+ 0x00EF0301: 0x1E2F,
+ 0x004B0301: 0x1E30,
+ 0x006B0301: 0x1E31,
+ 0x004B0323: 0x1E32,
+ 0x006B0323: 0x1E33,
+ 0x004B0331: 0x1E34,
+ 0x006B0331: 0x1E35,
+ 0x004C0323: 0x1E36,
+ 0x006C0323: 0x1E37,
+ 0x1E360304: 0x1E38,
+ 0x1E370304: 0x1E39,
+ 0x004C0331: 0x1E3A,
+ 0x006C0331: 0x1E3B,
+ 0x004C032D: 0x1E3C,
+ 0x006C032D: 0x1E3D,
+ 0x004D0301: 0x1E3E,
+ 0x006D0301: 0x1E3F,
+ 0x004D0307: 0x1E40,
+ 0x006D0307: 0x1E41,
+ 0x004D0323: 0x1E42,
+ 0x006D0323: 0x1E43,
+ 0x004E0307: 0x1E44,
+ 0x006E0307: 0x1E45,
+ 0x004E0323: 0x1E46,
+ 0x006E0323: 0x1E47,
+ 0x004E0331: 0x1E48,
+ 0x006E0331: 0x1E49,
+ 0x004E032D: 0x1E4A,
+ 0x006E032D: 0x1E4B,
+ 0x00D50301: 0x1E4C,
+ 0x00F50301: 0x1E4D,
+ 0x00D50308: 0x1E4E,
+ 0x00F50308: 0x1E4F,
+ 0x014C0300: 0x1E50,
+ 0x014D0300: 0x1E51,
+ 0x014C0301: 0x1E52,
+ 0x014D0301: 0x1E53,
+ 0x00500301: 0x1E54,
+ 0x00700301: 0x1E55,
+ 0x00500307: 0x1E56,
+ 0x00700307: 0x1E57,
+ 0x00520307: 0x1E58,
+ 0x00720307: 0x1E59,
+ 0x00520323: 0x1E5A,
+ 0x00720323: 0x1E5B,
+ 0x1E5A0304: 0x1E5C,
+ 0x1E5B0304: 0x1E5D,
+ 0x00520331: 0x1E5E,
+ 0x00720331: 0x1E5F,
+ 0x00530307: 0x1E60,
+ 0x00730307: 0x1E61,
+ 0x00530323: 0x1E62,
+ 0x00730323: 0x1E63,
+ 0x015A0307: 0x1E64,
+ 0x015B0307: 0x1E65,
+ 0x01600307: 0x1E66,
+ 0x01610307: 0x1E67,
+ 0x1E620307: 0x1E68,
+ 0x1E630307: 0x1E69,
+ 0x00540307: 0x1E6A,
+ 0x00740307: 0x1E6B,
+ 0x00540323: 0x1E6C,
+ 0x00740323: 0x1E6D,
+ 0x00540331: 0x1E6E,
+ 0x00740331: 0x1E6F,
+ 0x0054032D: 0x1E70,
+ 0x0074032D: 0x1E71,
+ 0x00550324: 0x1E72,
+ 0x00750324: 0x1E73,
+ 0x00550330: 0x1E74,
+ 0x00750330: 0x1E75,
+ 0x0055032D: 0x1E76,
+ 0x0075032D: 0x1E77,
+ 0x01680301: 0x1E78,
+ 0x01690301: 0x1E79,
+ 0x016A0308: 0x1E7A,
+ 0x016B0308: 0x1E7B,
+ 0x00560303: 0x1E7C,
+ 0x00760303: 0x1E7D,
+ 0x00560323: 0x1E7E,
+ 0x00760323: 0x1E7F,
+ 0x00570300: 0x1E80,
+ 0x00770300: 0x1E81,
+ 0x00570301: 0x1E82,
+ 0x00770301: 0x1E83,
+ 0x00570308: 0x1E84,
+ 0x00770308: 0x1E85,
+ 0x00570307: 0x1E86,
+ 0x00770307: 0x1E87,
+ 0x00570323: 0x1E88,
+ 0x00770323: 0x1E89,
+ 0x00580307: 0x1E8A,
+ 0x00780307: 0x1E8B,
+ 0x00580308: 0x1E8C,
+ 0x00780308: 0x1E8D,
+ 0x00590307: 0x1E8E,
+ 0x00790307: 0x1E8F,
+ 0x005A0302: 0x1E90,
+ 0x007A0302: 0x1E91,
+ 0x005A0323: 0x1E92,
+ 0x007A0323: 0x1E93,
+ 0x005A0331: 0x1E94,
+ 0x007A0331: 0x1E95,
+ 0x00680331: 0x1E96,
+ 0x00740308: 0x1E97,
+ 0x0077030A: 0x1E98,
+ 0x0079030A: 0x1E99,
+ 0x017F0307: 0x1E9B,
+ 0x00410323: 0x1EA0,
+ 0x00610323: 0x1EA1,
+ 0x00410309: 0x1EA2,
+ 0x00610309: 0x1EA3,
+ 0x00C20301: 0x1EA4,
+ 0x00E20301: 0x1EA5,
+ 0x00C20300: 0x1EA6,
+ 0x00E20300: 0x1EA7,
+ 0x00C20309: 0x1EA8,
+ 0x00E20309: 0x1EA9,
+ 0x00C20303: 0x1EAA,
+ 0x00E20303: 0x1EAB,
+ 0x1EA00302: 0x1EAC,
+ 0x1EA10302: 0x1EAD,
+ 0x01020301: 0x1EAE,
+ 0x01030301: 0x1EAF,
+ 0x01020300: 0x1EB0,
+ 0x01030300: 0x1EB1,
+ 0x01020309: 0x1EB2,
+ 0x01030309: 0x1EB3,
+ 0x01020303: 0x1EB4,
+ 0x01030303: 0x1EB5,
+ 0x1EA00306: 0x1EB6,
+ 0x1EA10306: 0x1EB7,
+ 0x00450323: 0x1EB8,
+ 0x00650323: 0x1EB9,
+ 0x00450309: 0x1EBA,
+ 0x00650309: 0x1EBB,
+ 0x00450303: 0x1EBC,
+ 0x00650303: 0x1EBD,
+ 0x00CA0301: 0x1EBE,
+ 0x00EA0301: 0x1EBF,
+ 0x00CA0300: 0x1EC0,
+ 0x00EA0300: 0x1EC1,
+ 0x00CA0309: 0x1EC2,
+ 0x00EA0309: 0x1EC3,
+ 0x00CA0303: 0x1EC4,
+ 0x00EA0303: 0x1EC5,
+ 0x1EB80302: 0x1EC6,
+ 0x1EB90302: 0x1EC7,
+ 0x00490309: 0x1EC8,
+ 0x00690309: 0x1EC9,
+ 0x00490323: 0x1ECA,
+ 0x00690323: 0x1ECB,
+ 0x004F0323: 0x1ECC,
+ 0x006F0323: 0x1ECD,
+ 0x004F0309: 0x1ECE,
+ 0x006F0309: 0x1ECF,
+ 0x00D40301: 0x1ED0,
+ 0x00F40301: 0x1ED1,
+ 0x00D40300: 0x1ED2,
+ 0x00F40300: 0x1ED3,
+ 0x00D40309: 0x1ED4,
+ 0x00F40309: 0x1ED5,
+ 0x00D40303: 0x1ED6,
+ 0x00F40303: 0x1ED7,
+ 0x1ECC0302: 0x1ED8,
+ 0x1ECD0302: 0x1ED9,
+ 0x01A00301: 0x1EDA,
+ 0x01A10301: 0x1EDB,
+ 0x01A00300: 0x1EDC,
+ 0x01A10300: 0x1EDD,
+ 0x01A00309: 0x1EDE,
+ 0x01A10309: 0x1EDF,
+ 0x01A00303: 0x1EE0,
+ 0x01A10303: 0x1EE1,
+ 0x01A00323: 0x1EE2,
+ 0x01A10323: 0x1EE3,
+ 0x00550323: 0x1EE4,
+ 0x00750323: 0x1EE5,
+ 0x00550309: 0x1EE6,
+ 0x00750309: 0x1EE7,
+ 0x01AF0301: 0x1EE8,
+ 0x01B00301: 0x1EE9,
+ 0x01AF0300: 0x1EEA,
+ 0x01B00300: 0x1EEB,
+ 0x01AF0309: 0x1EEC,
+ 0x01B00309: 0x1EED,
+ 0x01AF0303: 0x1EEE,
+ 0x01B00303: 0x1EEF,
+ 0x01AF0323: 0x1EF0,
+ 0x01B00323: 0x1EF1,
+ 0x00590300: 0x1EF2,
+ 0x00790300: 0x1EF3,
+ 0x00590323: 0x1EF4,
+ 0x00790323: 0x1EF5,
+ 0x00590309: 0x1EF6,
+ 0x00790309: 0x1EF7,
+ 0x00590303: 0x1EF8,
+ 0x00790303: 0x1EF9,
+ 0x03B10313: 0x1F00,
+ 0x03B10314: 0x1F01,
+ 0x1F000300: 0x1F02,
+ 0x1F010300: 0x1F03,
+ 0x1F000301: 0x1F04,
+ 0x1F010301: 0x1F05,
+ 0x1F000342: 0x1F06,
+ 0x1F010342: 0x1F07,
+ 0x03910313: 0x1F08,
+ 0x03910314: 0x1F09,
+ 0x1F080300: 0x1F0A,
+ 0x1F090300: 0x1F0B,
+ 0x1F080301: 0x1F0C,
+ 0x1F090301: 0x1F0D,
+ 0x1F080342: 0x1F0E,
+ 0x1F090342: 0x1F0F,
+ 0x03B50313: 0x1F10,
+ 0x03B50314: 0x1F11,
+ 0x1F100300: 0x1F12,
+ 0x1F110300: 0x1F13,
+ 0x1F100301: 0x1F14,
+ 0x1F110301: 0x1F15,
+ 0x03950313: 0x1F18,
+ 0x03950314: 0x1F19,
+ 0x1F180300: 0x1F1A,
+ 0x1F190300: 0x1F1B,
+ 0x1F180301: 0x1F1C,
+ 0x1F190301: 0x1F1D,
+ 0x03B70313: 0x1F20,
+ 0x03B70314: 0x1F21,
+ 0x1F200300: 0x1F22,
+ 0x1F210300: 0x1F23,
+ 0x1F200301: 0x1F24,
+ 0x1F210301: 0x1F25,
+ 0x1F200342: 0x1F26,
+ 0x1F210342: 0x1F27,
+ 0x03970313: 0x1F28,
+ 0x03970314: 0x1F29,
+ 0x1F280300: 0x1F2A,
+ 0x1F290300: 0x1F2B,
+ 0x1F280301: 0x1F2C,
+ 0x1F290301: 0x1F2D,
+ 0x1F280342: 0x1F2E,
+ 0x1F290342: 0x1F2F,
+ 0x03B90313: 0x1F30,
+ 0x03B90314: 0x1F31,
+ 0x1F300300: 0x1F32,
+ 0x1F310300: 0x1F33,
+ 0x1F300301: 0x1F34,
+ 0x1F310301: 0x1F35,
+ 0x1F300342: 0x1F36,
+ 0x1F310342: 0x1F37,
+ 0x03990313: 0x1F38,
+ 0x03990314: 0x1F39,
+ 0x1F380300: 0x1F3A,
+ 0x1F390300: 0x1F3B,
+ 0x1F380301: 0x1F3C,
+ 0x1F390301: 0x1F3D,
+ 0x1F380342: 0x1F3E,
+ 0x1F390342: 0x1F3F,
+ 0x03BF0313: 0x1F40,
+ 0x03BF0314: 0x1F41,
+ 0x1F400300: 0x1F42,
+ 0x1F410300: 0x1F43,
+ 0x1F400301: 0x1F44,
+ 0x1F410301: 0x1F45,
+ 0x039F0313: 0x1F48,
+ 0x039F0314: 0x1F49,
+ 0x1F480300: 0x1F4A,
+ 0x1F490300: 0x1F4B,
+ 0x1F480301: 0x1F4C,
+ 0x1F490301: 0x1F4D,
+ 0x03C50313: 0x1F50,
+ 0x03C50314: 0x1F51,
+ 0x1F500300: 0x1F52,
+ 0x1F510300: 0x1F53,
+ 0x1F500301: 0x1F54,
+ 0x1F510301: 0x1F55,
+ 0x1F500342: 0x1F56,
+ 0x1F510342: 0x1F57,
+ 0x03A50314: 0x1F59,
+ 0x1F590300: 0x1F5B,
+ 0x1F590301: 0x1F5D,
+ 0x1F590342: 0x1F5F,
+ 0x03C90313: 0x1F60,
+ 0x03C90314: 0x1F61,
+ 0x1F600300: 0x1F62,
+ 0x1F610300: 0x1F63,
+ 0x1F600301: 0x1F64,
+ 0x1F610301: 0x1F65,
+ 0x1F600342: 0x1F66,
+ 0x1F610342: 0x1F67,
+ 0x03A90313: 0x1F68,
+ 0x03A90314: 0x1F69,
+ 0x1F680300: 0x1F6A,
+ 0x1F690300: 0x1F6B,
+ 0x1F680301: 0x1F6C,
+ 0x1F690301: 0x1F6D,
+ 0x1F680342: 0x1F6E,
+ 0x1F690342: 0x1F6F,
+ 0x03B10300: 0x1F70,
+ 0x03B50300: 0x1F72,
+ 0x03B70300: 0x1F74,
+ 0x03B90300: 0x1F76,
+ 0x03BF0300: 0x1F78,
+ 0x03C50300: 0x1F7A,
+ 0x03C90300: 0x1F7C,
+ 0x1F000345: 0x1F80,
+ 0x1F010345: 0x1F81,
+ 0x1F020345: 0x1F82,
+ 0x1F030345: 0x1F83,
+ 0x1F040345: 0x1F84,
+ 0x1F050345: 0x1F85,
+ 0x1F060345: 0x1F86,
+ 0x1F070345: 0x1F87,
+ 0x1F080345: 0x1F88,
+ 0x1F090345: 0x1F89,
+ 0x1F0A0345: 0x1F8A,
+ 0x1F0B0345: 0x1F8B,
+ 0x1F0C0345: 0x1F8C,
+ 0x1F0D0345: 0x1F8D,
+ 0x1F0E0345: 0x1F8E,
+ 0x1F0F0345: 0x1F8F,
+ 0x1F200345: 0x1F90,
+ 0x1F210345: 0x1F91,
+ 0x1F220345: 0x1F92,
+ 0x1F230345: 0x1F93,
+ 0x1F240345: 0x1F94,
+ 0x1F250345: 0x1F95,
+ 0x1F260345: 0x1F96,
+ 0x1F270345: 0x1F97,
+ 0x1F280345: 0x1F98,
+ 0x1F290345: 0x1F99,
+ 0x1F2A0345: 0x1F9A,
+ 0x1F2B0345: 0x1F9B,
+ 0x1F2C0345: 0x1F9C,
+ 0x1F2D0345: 0x1F9D,
+ 0x1F2E0345: 0x1F9E,
+ 0x1F2F0345: 0x1F9F,
+ 0x1F600345: 0x1FA0,
+ 0x1F610345: 0x1FA1,
+ 0x1F620345: 0x1FA2,
+ 0x1F630345: 0x1FA3,
+ 0x1F640345: 0x1FA4,
+ 0x1F650345: 0x1FA5,
+ 0x1F660345: 0x1FA6,
+ 0x1F670345: 0x1FA7,
+ 0x1F680345: 0x1FA8,
+ 0x1F690345: 0x1FA9,
+ 0x1F6A0345: 0x1FAA,
+ 0x1F6B0345: 0x1FAB,
+ 0x1F6C0345: 0x1FAC,
+ 0x1F6D0345: 0x1FAD,
+ 0x1F6E0345: 0x1FAE,
+ 0x1F6F0345: 0x1FAF,
+ 0x03B10306: 0x1FB0,
+ 0x03B10304: 0x1FB1,
+ 0x1F700345: 0x1FB2,
+ 0x03B10345: 0x1FB3,
+ 0x03AC0345: 0x1FB4,
+ 0x03B10342: 0x1FB6,
+ 0x1FB60345: 0x1FB7,
+ 0x03910306: 0x1FB8,
+ 0x03910304: 0x1FB9,
+ 0x03910300: 0x1FBA,
+ 0x03910345: 0x1FBC,
+ 0x00A80342: 0x1FC1,
+ 0x1F740345: 0x1FC2,
+ 0x03B70345: 0x1FC3,
+ 0x03AE0345: 0x1FC4,
+ 0x03B70342: 0x1FC6,
+ 0x1FC60345: 0x1FC7,
+ 0x03950300: 0x1FC8,
+ 0x03970300: 0x1FCA,
+ 0x03970345: 0x1FCC,
+ 0x1FBF0300: 0x1FCD,
+ 0x1FBF0301: 0x1FCE,
+ 0x1FBF0342: 0x1FCF,
+ 0x03B90306: 0x1FD0,
+ 0x03B90304: 0x1FD1,
+ 0x03CA0300: 0x1FD2,
+ 0x03B90342: 0x1FD6,
+ 0x03CA0342: 0x1FD7,
+ 0x03990306: 0x1FD8,
+ 0x03990304: 0x1FD9,
+ 0x03990300: 0x1FDA,
+ 0x1FFE0300: 0x1FDD,
+ 0x1FFE0301: 0x1FDE,
+ 0x1FFE0342: 0x1FDF,
+ 0x03C50306: 0x1FE0,
+ 0x03C50304: 0x1FE1,
+ 0x03CB0300: 0x1FE2,
+ 0x03C10313: 0x1FE4,
+ 0x03C10314: 0x1FE5,
+ 0x03C50342: 0x1FE6,
+ 0x03CB0342: 0x1FE7,
+ 0x03A50306: 0x1FE8,
+ 0x03A50304: 0x1FE9,
+ 0x03A50300: 0x1FEA,
+ 0x03A10314: 0x1FEC,
+ 0x00A80300: 0x1FED,
+ 0x1F7C0345: 0x1FF2,
+ 0x03C90345: 0x1FF3,
+ 0x03CE0345: 0x1FF4,
+ 0x03C90342: 0x1FF6,
+ 0x1FF60345: 0x1FF7,
+ 0x039F0300: 0x1FF8,
+ 0x03A90300: 0x1FFA,
+ 0x03A90345: 0x1FFC,
+ 0x21900338: 0x219A,
+ 0x21920338: 0x219B,
+ 0x21940338: 0x21AE,
+ 0x21D00338: 0x21CD,
+ 0x21D40338: 0x21CE,
+ 0x21D20338: 0x21CF,
+ 0x22030338: 0x2204,
+ 0x22080338: 0x2209,
+ 0x220B0338: 0x220C,
+ 0x22230338: 0x2224,
+ 0x22250338: 0x2226,
+ 0x223C0338: 0x2241,
+ 0x22430338: 0x2244,
+ 0x22450338: 0x2247,
+ 0x22480338: 0x2249,
+ 0x003D0338: 0x2260,
+ 0x22610338: 0x2262,
+ 0x224D0338: 0x226D,
+ 0x003C0338: 0x226E,
+ 0x003E0338: 0x226F,
+ 0x22640338: 0x2270,
+ 0x22650338: 0x2271,
+ 0x22720338: 0x2274,
+ 0x22730338: 0x2275,
+ 0x22760338: 0x2278,
+ 0x22770338: 0x2279,
+ 0x227A0338: 0x2280,
+ 0x227B0338: 0x2281,
+ 0x22820338: 0x2284,
+ 0x22830338: 0x2285,
+ 0x22860338: 0x2288,
+ 0x22870338: 0x2289,
+ 0x22A20338: 0x22AC,
+ 0x22A80338: 0x22AD,
+ 0x22A90338: 0x22AE,
+ 0x22AB0338: 0x22AF,
+ 0x227C0338: 0x22E0,
+ 0x227D0338: 0x22E1,
+ 0x22910338: 0x22E2,
+ 0x22920338: 0x22E3,
+ 0x22B20338: 0x22EA,
+ 0x22B30338: 0x22EB,
+ 0x22B40338: 0x22EC,
+ 0x22B50338: 0x22ED,
+ 0x304B3099: 0x304C,
+ 0x304D3099: 0x304E,
+ 0x304F3099: 0x3050,
+ 0x30513099: 0x3052,
+ 0x30533099: 0x3054,
+ 0x30553099: 0x3056,
+ 0x30573099: 0x3058,
+ 0x30593099: 0x305A,
+ 0x305B3099: 0x305C,
+ 0x305D3099: 0x305E,
+ 0x305F3099: 0x3060,
+ 0x30613099: 0x3062,
+ 0x30643099: 0x3065,
+ 0x30663099: 0x3067,
+ 0x30683099: 0x3069,
+ 0x306F3099: 0x3070,
+ 0x306F309A: 0x3071,
+ 0x30723099: 0x3073,
+ 0x3072309A: 0x3074,
+ 0x30753099: 0x3076,
+ 0x3075309A: 0x3077,
+ 0x30783099: 0x3079,
+ 0x3078309A: 0x307A,
+ 0x307B3099: 0x307C,
+ 0x307B309A: 0x307D,
+ 0x30463099: 0x3094,
+ 0x309D3099: 0x309E,
+ 0x30AB3099: 0x30AC,
+ 0x30AD3099: 0x30AE,
+ 0x30AF3099: 0x30B0,
+ 0x30B13099: 0x30B2,
+ 0x30B33099: 0x30B4,
+ 0x30B53099: 0x30B6,
+ 0x30B73099: 0x30B8,
+ 0x30B93099: 0x30BA,
+ 0x30BB3099: 0x30BC,
+ 0x30BD3099: 0x30BE,
+ 0x30BF3099: 0x30C0,
+ 0x30C13099: 0x30C2,
+ 0x30C43099: 0x30C5,
+ 0x30C63099: 0x30C7,
+ 0x30C83099: 0x30C9,
+ 0x30CF3099: 0x30D0,
+ 0x30CF309A: 0x30D1,
+ 0x30D23099: 0x30D3,
+ 0x30D2309A: 0x30D4,
+ 0x30D53099: 0x30D6,
+ 0x30D5309A: 0x30D7,
+ 0x30D83099: 0x30D9,
+ 0x30D8309A: 0x30DA,
+ 0x30DB3099: 0x30DC,
+ 0x30DB309A: 0x30DD,
+ 0x30A63099: 0x30F4,
+ 0x30EF3099: 0x30F7,
+ 0x30F03099: 0x30F8,
+ 0x30F13099: 0x30F9,
+ 0x30F23099: 0x30FA,
+ 0x30FD3099: 0x30FE,
+ 0x109910BA: 0x1109A,
+ 0x109B10BA: 0x1109C,
+ 0x10A510BA: 0x110AB,
+ 0x11311127: 0x1112E,
+ 0x11321127: 0x1112F,
+ 0x1347133E: 0x1134B,
+ 0x13471357: 0x1134C,
+ 0x14B914BA: 0x114BB,
+ 0x14B914B0: 0x114BC,
+ 0x14B914BD: 0x114BE,
+ 0x15B815AF: 0x115BA,
+ 0x15B915AF: 0x115BB,
+}
+
+// Total size of tables: 53KB (53976 bytes)
diff --git a/libgo/go/golang_org/x/text/unicode/norm/transform.go b/libgo/go/golang_org/x/text/unicode/norm/transform.go
new file mode 100644
index 00000000000..b341789b4c6
--- /dev/null
+++ b/libgo/go/golang_org/x/text/unicode/norm/transform.go
@@ -0,0 +1,88 @@
+// 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 norm
+
+import (
+ "unicode/utf8"
+
+ "golang_org/x/text/transform"
+)
+
+// Reset implements the Reset method of the transform.Transformer interface.
+func (Form) Reset() {}
+
+// Transform implements the Transform method of the transform.Transformer
+// interface. It may need to write segments of up to MaxSegmentSize at once.
+// Users should either catch ErrShortDst and allow dst to grow or have dst be at
+// least of size MaxTransformChunkSize to be guaranteed of progress.
+func (f Form) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ n := 0
+ // Cap the maximum number of src bytes to check.
+ b := src
+ eof := atEOF
+ if ns := len(dst); ns < len(b) {
+ err = transform.ErrShortDst
+ eof = false
+ b = b[:ns]
+ }
+ i, ok := formTable[f].quickSpan(inputBytes(b), n, len(b), eof)
+ n += copy(dst[n:], b[n:i])
+ if !ok {
+ nDst, nSrc, err = f.transform(dst[n:], src[n:], atEOF)
+ return nDst + n, nSrc + n, err
+ }
+ if n < len(src) && !atEOF {
+ err = transform.ErrShortSrc
+ }
+ return n, n, err
+}
+
+func flushTransform(rb *reorderBuffer) bool {
+ // Write out (must fully fit in dst, or else it is a ErrShortDst).
+ if len(rb.out) < rb.nrune*utf8.UTFMax {
+ return false
+ }
+ rb.out = rb.out[rb.flushCopy(rb.out):]
+ return true
+}
+
+var errs = []error{nil, transform.ErrShortDst, transform.ErrShortSrc}
+
+// transform implements the transform.Transformer interface. It is only called
+// when quickSpan does not pass for a given string.
+func (f Form) transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ // TODO: get rid of reorderBuffer. See CL 23460044.
+ rb := reorderBuffer{}
+ rb.init(f, src)
+ for {
+ // Load segment into reorder buffer.
+ rb.setFlusher(dst[nDst:], flushTransform)
+ end := decomposeSegment(&rb, nSrc, atEOF)
+ if end < 0 {
+ return nDst, nSrc, errs[-end]
+ }
+ nDst = len(dst) - len(rb.out)
+ nSrc = end
+
+ // Next quickSpan.
+ end = rb.nsrc
+ eof := atEOF
+ if n := nSrc + len(dst) - nDst; n < end {
+ err = transform.ErrShortDst
+ end = n
+ eof = false
+ }
+ end, ok := rb.f.quickSpan(rb.src, nSrc, end, eof)
+ n := copy(dst[nDst:], rb.src.bytes[nSrc:end])
+ nSrc += n
+ nDst += n
+ if ok {
+ if n < rb.nsrc && !atEOF {
+ err = transform.ErrShortSrc
+ }
+ return nDst, nSrc, err
+ }
+ }
+}
diff --git a/libgo/go/golang_org/x/text/unicode/norm/trie.go b/libgo/go/golang_org/x/text/unicode/norm/trie.go
new file mode 100644
index 00000000000..423386bf436
--- /dev/null
+++ b/libgo/go/golang_org/x/text/unicode/norm/trie.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 norm
+
+type valueRange struct {
+ value uint16 // header: value:stride
+ lo, hi byte // header: lo:n
+}
+
+type sparseBlocks struct {
+ values []valueRange
+ offset []uint16
+}
+
+var nfcSparse = sparseBlocks{
+ values: nfcSparseValues[:],
+ offset: nfcSparseOffset[:],
+}
+
+var nfkcSparse = sparseBlocks{
+ values: nfkcSparseValues[:],
+ offset: nfkcSparseOffset[:],
+}
+
+var (
+ nfcData = newNfcTrie(0)
+ nfkcData = newNfkcTrie(0)
+)
+
+// lookupValue determines the type of block n and looks up the value for b.
+// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
+// is a list of ranges with an accompanying value. Given a matching range r,
+// the value for b is by r.value + (b - r.lo) * stride.
+func (t *sparseBlocks) lookup(n uint32, b byte) uint16 {
+ offset := t.offset[n]
+ header := t.values[offset]
+ lo := offset + 1
+ hi := lo + uint16(header.lo)
+ for lo < hi {
+ m := lo + (hi-lo)/2
+ r := t.values[m]
+ if r.lo <= b && b <= r.hi {
+ return r.value + uint16(b-r.lo)*header.value
+ }
+ if b < r.lo {
+ hi = m
+ } else {
+ lo = m + 1
+ }
+ }
+ return 0
+}
diff --git a/libgo/go/golang_org/x/text/unicode/norm/triegen.go b/libgo/go/golang_org/x/text/unicode/norm/triegen.go
new file mode 100644
index 00000000000..45d711900d1
--- /dev/null
+++ b/libgo/go/golang_org/x/text/unicode/norm/triegen.go
@@ -0,0 +1,117 @@
+// 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 ignore
+
+// Trie table generator.
+// Used by make*tables tools to generate a go file with trie data structures
+// for mapping UTF-8 to a 16-bit value. All but the last byte in a UTF-8 byte
+// sequence are used to lookup offsets in the index table to be used for the
+// next byte. The last byte is used to index into a table with 16-bit values.
+
+package main
+
+import (
+ "fmt"
+ "io"
+)
+
+const maxSparseEntries = 16
+
+type normCompacter struct {
+ sparseBlocks [][]uint64
+ sparseOffset []uint16
+ sparseCount int
+ name string
+}
+
+func mostFrequentStride(a []uint64) int {
+ counts := make(map[int]int)
+ var v int
+ for _, x := range a {
+ if stride := int(x) - v; v != 0 && stride >= 0 {
+ counts[stride]++
+ }
+ v = int(x)
+ }
+ var maxs, maxc int
+ for stride, cnt := range counts {
+ if cnt > maxc || (cnt == maxc && stride < maxs) {
+ maxs, maxc = stride, cnt
+ }
+ }
+ return maxs
+}
+
+func countSparseEntries(a []uint64) int {
+ stride := mostFrequentStride(a)
+ var v, count int
+ for _, tv := range a {
+ if int(tv)-v != stride {
+ if tv != 0 {
+ count++
+ }
+ }
+ v = int(tv)
+ }
+ return count
+}
+
+func (c *normCompacter) Size(v []uint64) (sz int, ok bool) {
+ if n := countSparseEntries(v); n <= maxSparseEntries {
+ return (n+1)*4 + 2, true
+ }
+ return 0, false
+}
+
+func (c *normCompacter) Store(v []uint64) uint32 {
+ h := uint32(len(c.sparseOffset))
+ c.sparseBlocks = append(c.sparseBlocks, v)
+ c.sparseOffset = append(c.sparseOffset, uint16(c.sparseCount))
+ c.sparseCount += countSparseEntries(v) + 1
+ return h
+}
+
+func (c *normCompacter) Handler() string {
+ return c.name + "Sparse.lookup"
+}
+
+func (c *normCompacter) Print(w io.Writer) (retErr error) {
+ p := func(f string, x ...interface{}) {
+ if _, err := fmt.Fprintf(w, f, x...); retErr == nil && err != nil {
+ retErr = err
+ }
+ }
+
+ ls := len(c.sparseBlocks)
+ p("// %sSparseOffset: %d entries, %d bytes\n", c.name, ls, ls*2)
+ p("var %sSparseOffset = %#v\n\n", c.name, c.sparseOffset)
+
+ ns := c.sparseCount
+ p("// %sSparseValues: %d entries, %d bytes\n", c.name, ns, ns*4)
+ p("var %sSparseValues = [%d]valueRange {", c.name, ns)
+ for i, b := range c.sparseBlocks {
+ p("\n// Block %#x, offset %#x", i, c.sparseOffset[i])
+ var v int
+ stride := mostFrequentStride(b)
+ n := countSparseEntries(b)
+ p("\n{value:%#04x,lo:%#02x},", stride, uint8(n))
+ for i, nv := range b {
+ if int(nv)-v != stride {
+ if v != 0 {
+ p(",hi:%#02x},", 0x80+i-1)
+ }
+ if nv != 0 {
+ p("\n{value:%#04x,lo:%#02x", nv, 0x80+i)
+ }
+ }
+ v = int(nv)
+ }
+ if v != 0 {
+ p(",hi:%#02x},", 0x80+len(b)-1)
+ }
+ }
+ p("\n}\n\n")
+ return
+}
diff --git a/libgo/go/golang_org/x/text/width/kind_string.go b/libgo/go/golang_org/x/text/width/kind_string.go
new file mode 100644
index 00000000000..ab4fee542f3
--- /dev/null
+++ b/libgo/go/golang_org/x/text/width/kind_string.go
@@ -0,0 +1,16 @@
+// Code generated by "stringer -type=Kind"; DO NOT EDIT
+
+package width
+
+import "fmt"
+
+const _Kind_name = "NeutralEastAsianAmbiguousEastAsianWideEastAsianNarrowEastAsianFullwidthEastAsianHalfwidth"
+
+var _Kind_index = [...]uint8{0, 7, 25, 38, 53, 71, 89}
+
+func (i Kind) String() string {
+ if i < 0 || i >= Kind(len(_Kind_index)-1) {
+ return fmt.Sprintf("Kind(%d)", i)
+ }
+ return _Kind_name[_Kind_index[i]:_Kind_index[i+1]]
+}
diff --git a/libgo/go/golang_org/x/text/width/tables.go b/libgo/go/golang_org/x/text/width/tables.go
new file mode 100644
index 00000000000..242da0fdb9c
--- /dev/null
+++ b/libgo/go/golang_org/x/text/width/tables.go
@@ -0,0 +1,1284 @@
+// This file was generated by go generate; DO NOT EDIT
+
+package width
+
+// UnicodeVersion is the Unicode version from which the tables in this package are derived.
+const UnicodeVersion = "9.0.0"
+
+// lookup returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *widthTrie) lookup(s []byte) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return widthValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := widthIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := widthIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = widthIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := widthIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = widthIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = widthIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *widthTrie) lookupUnsafe(s []byte) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return widthValues[c0]
+ }
+ i := widthIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = widthIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = widthIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// lookupString returns the trie value for the first UTF-8 encoding in s and
+// the width in bytes of this encoding. The size will be 0 if s does not
+// hold enough bytes to complete the encoding. len(s) must be greater than 0.
+func (t *widthTrie) lookupString(s string) (v uint16, sz int) {
+ c0 := s[0]
+ switch {
+ case c0 < 0x80: // is ASCII
+ return widthValues[c0], 1
+ case c0 < 0xC2:
+ return 0, 1 // Illegal UTF-8: not a starter, not ASCII.
+ case c0 < 0xE0: // 2-byte UTF-8
+ if len(s) < 2 {
+ return 0, 0
+ }
+ i := widthIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c1), 2
+ case c0 < 0xF0: // 3-byte UTF-8
+ if len(s) < 3 {
+ return 0, 0
+ }
+ i := widthIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = widthIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c2), 3
+ case c0 < 0xF8: // 4-byte UTF-8
+ if len(s) < 4 {
+ return 0, 0
+ }
+ i := widthIndex[c0]
+ c1 := s[1]
+ if c1 < 0x80 || 0xC0 <= c1 {
+ return 0, 1 // Illegal UTF-8: not a continuation byte.
+ }
+ o := uint32(i)<<6 + uint32(c1)
+ i = widthIndex[o]
+ c2 := s[2]
+ if c2 < 0x80 || 0xC0 <= c2 {
+ return 0, 2 // Illegal UTF-8: not a continuation byte.
+ }
+ o = uint32(i)<<6 + uint32(c2)
+ i = widthIndex[o]
+ c3 := s[3]
+ if c3 < 0x80 || 0xC0 <= c3 {
+ return 0, 3 // Illegal UTF-8: not a continuation byte.
+ }
+ return t.lookupValue(uint32(i), c3), 4
+ }
+ // Illegal rune
+ return 0, 1
+}
+
+// lookupStringUnsafe returns the trie value for the first UTF-8 encoding in s.
+// s must start with a full and valid UTF-8 encoded rune.
+func (t *widthTrie) lookupStringUnsafe(s string) uint16 {
+ c0 := s[0]
+ if c0 < 0x80 { // is ASCII
+ return widthValues[c0]
+ }
+ i := widthIndex[c0]
+ if c0 < 0xE0 { // 2-byte UTF-8
+ return t.lookupValue(uint32(i), s[1])
+ }
+ i = widthIndex[uint32(i)<<6+uint32(s[1])]
+ if c0 < 0xF0 { // 3-byte UTF-8
+ return t.lookupValue(uint32(i), s[2])
+ }
+ i = widthIndex[uint32(i)<<6+uint32(s[2])]
+ if c0 < 0xF8 { // 4-byte UTF-8
+ return t.lookupValue(uint32(i), s[3])
+ }
+ return 0
+}
+
+// widthTrie. Total size: 14080 bytes (13.75 KiB). Checksum: 3b8aeb3dc03667a3.
+type widthTrie struct{}
+
+func newWidthTrie(i int) *widthTrie {
+ return &widthTrie{}
+}
+
+// lookupValue determines the type of block n and looks up the value for b.
+func (t *widthTrie) lookupValue(n uint32, b byte) uint16 {
+ switch {
+ default:
+ return uint16(widthValues[n<<6+uint32(b)])
+ }
+}
+
+// widthValues: 99 blocks, 6336 entries, 12672 bytes
+// The third block is the zero block.
+var widthValues = [6336]uint16{
+ // Block 0x0, offset 0x0
+ 0x20: 0x6001, 0x21: 0x6002, 0x22: 0x6002, 0x23: 0x6002,
+ 0x24: 0x6002, 0x25: 0x6002, 0x26: 0x6002, 0x27: 0x6002, 0x28: 0x6002, 0x29: 0x6002,
+ 0x2a: 0x6002, 0x2b: 0x6002, 0x2c: 0x6002, 0x2d: 0x6002, 0x2e: 0x6002, 0x2f: 0x6002,
+ 0x30: 0x6002, 0x31: 0x6002, 0x32: 0x6002, 0x33: 0x6002, 0x34: 0x6002, 0x35: 0x6002,
+ 0x36: 0x6002, 0x37: 0x6002, 0x38: 0x6002, 0x39: 0x6002, 0x3a: 0x6002, 0x3b: 0x6002,
+ 0x3c: 0x6002, 0x3d: 0x6002, 0x3e: 0x6002, 0x3f: 0x6002,
+ // Block 0x1, offset 0x40
+ 0x40: 0x6003, 0x41: 0x6003, 0x42: 0x6003, 0x43: 0x6003, 0x44: 0x6003, 0x45: 0x6003,
+ 0x46: 0x6003, 0x47: 0x6003, 0x48: 0x6003, 0x49: 0x6003, 0x4a: 0x6003, 0x4b: 0x6003,
+ 0x4c: 0x6003, 0x4d: 0x6003, 0x4e: 0x6003, 0x4f: 0x6003, 0x50: 0x6003, 0x51: 0x6003,
+ 0x52: 0x6003, 0x53: 0x6003, 0x54: 0x6003, 0x55: 0x6003, 0x56: 0x6003, 0x57: 0x6003,
+ 0x58: 0x6003, 0x59: 0x6003, 0x5a: 0x6003, 0x5b: 0x6003, 0x5c: 0x6003, 0x5d: 0x6003,
+ 0x5e: 0x6003, 0x5f: 0x6003, 0x60: 0x6004, 0x61: 0x6004, 0x62: 0x6004, 0x63: 0x6004,
+ 0x64: 0x6004, 0x65: 0x6004, 0x66: 0x6004, 0x67: 0x6004, 0x68: 0x6004, 0x69: 0x6004,
+ 0x6a: 0x6004, 0x6b: 0x6004, 0x6c: 0x6004, 0x6d: 0x6004, 0x6e: 0x6004, 0x6f: 0x6004,
+ 0x70: 0x6004, 0x71: 0x6004, 0x72: 0x6004, 0x73: 0x6004, 0x74: 0x6004, 0x75: 0x6004,
+ 0x76: 0x6004, 0x77: 0x6004, 0x78: 0x6004, 0x79: 0x6004, 0x7a: 0x6004, 0x7b: 0x6004,
+ 0x7c: 0x6004, 0x7d: 0x6004, 0x7e: 0x6004,
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xe1: 0x2000, 0xe2: 0x6005, 0xe3: 0x6005,
+ 0xe4: 0x2000, 0xe5: 0x6006, 0xe6: 0x6005, 0xe7: 0x2000, 0xe8: 0x2000,
+ 0xea: 0x2000, 0xec: 0x6007, 0xed: 0x2000, 0xee: 0x2000, 0xef: 0x6008,
+ 0xf0: 0x2000, 0xf1: 0x2000, 0xf2: 0x2000, 0xf3: 0x2000, 0xf4: 0x2000,
+ 0xf6: 0x2000, 0xf7: 0x2000, 0xf8: 0x2000, 0xf9: 0x2000, 0xfa: 0x2000,
+ 0xfc: 0x2000, 0xfd: 0x2000, 0xfe: 0x2000, 0xff: 0x2000,
+ // Block 0x4, offset 0x100
+ 0x106: 0x2000,
+ 0x110: 0x2000,
+ 0x117: 0x2000,
+ 0x118: 0x2000,
+ 0x11e: 0x2000, 0x11f: 0x2000, 0x120: 0x2000, 0x121: 0x2000,
+ 0x126: 0x2000, 0x128: 0x2000, 0x129: 0x2000,
+ 0x12a: 0x2000, 0x12c: 0x2000, 0x12d: 0x2000,
+ 0x130: 0x2000, 0x132: 0x2000, 0x133: 0x2000,
+ 0x137: 0x2000, 0x138: 0x2000, 0x139: 0x2000, 0x13a: 0x2000,
+ 0x13c: 0x2000, 0x13e: 0x2000,
+ // Block 0x5, offset 0x140
+ 0x141: 0x2000,
+ 0x151: 0x2000,
+ 0x153: 0x2000,
+ 0x15b: 0x2000,
+ 0x166: 0x2000, 0x167: 0x2000,
+ 0x16b: 0x2000,
+ 0x171: 0x2000, 0x172: 0x2000, 0x173: 0x2000,
+ 0x178: 0x2000,
+ 0x17f: 0x2000,
+ // Block 0x6, offset 0x180
+ 0x180: 0x2000, 0x181: 0x2000, 0x182: 0x2000, 0x184: 0x2000,
+ 0x188: 0x2000, 0x189: 0x2000, 0x18a: 0x2000, 0x18b: 0x2000,
+ 0x18d: 0x2000,
+ 0x192: 0x2000, 0x193: 0x2000,
+ 0x1a6: 0x2000, 0x1a7: 0x2000,
+ 0x1ab: 0x2000,
+ // Block 0x7, offset 0x1c0
+ 0x1ce: 0x2000, 0x1d0: 0x2000,
+ 0x1d2: 0x2000, 0x1d4: 0x2000, 0x1d6: 0x2000,
+ 0x1d8: 0x2000, 0x1da: 0x2000, 0x1dc: 0x2000,
+ // Block 0x8, offset 0x200
+ 0x211: 0x2000,
+ 0x221: 0x2000,
+ // Block 0x9, offset 0x240
+ 0x244: 0x2000,
+ 0x247: 0x2000, 0x249: 0x2000, 0x24a: 0x2000, 0x24b: 0x2000,
+ 0x24d: 0x2000, 0x250: 0x2000,
+ 0x258: 0x2000, 0x259: 0x2000, 0x25a: 0x2000, 0x25b: 0x2000, 0x25d: 0x2000,
+ 0x25f: 0x2000,
+ // Block 0xa, offset 0x280
+ 0x280: 0x2000, 0x281: 0x2000, 0x282: 0x2000, 0x283: 0x2000, 0x284: 0x2000, 0x285: 0x2000,
+ 0x286: 0x2000, 0x287: 0x2000, 0x288: 0x2000, 0x289: 0x2000, 0x28a: 0x2000, 0x28b: 0x2000,
+ 0x28c: 0x2000, 0x28d: 0x2000, 0x28e: 0x2000, 0x28f: 0x2000, 0x290: 0x2000, 0x291: 0x2000,
+ 0x292: 0x2000, 0x293: 0x2000, 0x294: 0x2000, 0x295: 0x2000, 0x296: 0x2000, 0x297: 0x2000,
+ 0x298: 0x2000, 0x299: 0x2000, 0x29a: 0x2000, 0x29b: 0x2000, 0x29c: 0x2000, 0x29d: 0x2000,
+ 0x29e: 0x2000, 0x29f: 0x2000, 0x2a0: 0x2000, 0x2a1: 0x2000, 0x2a2: 0x2000, 0x2a3: 0x2000,
+ 0x2a4: 0x2000, 0x2a5: 0x2000, 0x2a6: 0x2000, 0x2a7: 0x2000, 0x2a8: 0x2000, 0x2a9: 0x2000,
+ 0x2aa: 0x2000, 0x2ab: 0x2000, 0x2ac: 0x2000, 0x2ad: 0x2000, 0x2ae: 0x2000, 0x2af: 0x2000,
+ 0x2b0: 0x2000, 0x2b1: 0x2000, 0x2b2: 0x2000, 0x2b3: 0x2000, 0x2b4: 0x2000, 0x2b5: 0x2000,
+ 0x2b6: 0x2000, 0x2b7: 0x2000, 0x2b8: 0x2000, 0x2b9: 0x2000, 0x2ba: 0x2000, 0x2bb: 0x2000,
+ 0x2bc: 0x2000, 0x2bd: 0x2000, 0x2be: 0x2000, 0x2bf: 0x2000,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x2000, 0x2c1: 0x2000, 0x2c2: 0x2000, 0x2c3: 0x2000, 0x2c4: 0x2000, 0x2c5: 0x2000,
+ 0x2c6: 0x2000, 0x2c7: 0x2000, 0x2c8: 0x2000, 0x2c9: 0x2000, 0x2ca: 0x2000, 0x2cb: 0x2000,
+ 0x2cc: 0x2000, 0x2cd: 0x2000, 0x2ce: 0x2000, 0x2cf: 0x2000, 0x2d0: 0x2000, 0x2d1: 0x2000,
+ 0x2d2: 0x2000, 0x2d3: 0x2000, 0x2d4: 0x2000, 0x2d5: 0x2000, 0x2d6: 0x2000, 0x2d7: 0x2000,
+ 0x2d8: 0x2000, 0x2d9: 0x2000, 0x2da: 0x2000, 0x2db: 0x2000, 0x2dc: 0x2000, 0x2dd: 0x2000,
+ 0x2de: 0x2000, 0x2df: 0x2000, 0x2e0: 0x2000, 0x2e1: 0x2000, 0x2e2: 0x2000, 0x2e3: 0x2000,
+ 0x2e4: 0x2000, 0x2e5: 0x2000, 0x2e6: 0x2000, 0x2e7: 0x2000, 0x2e8: 0x2000, 0x2e9: 0x2000,
+ 0x2ea: 0x2000, 0x2eb: 0x2000, 0x2ec: 0x2000, 0x2ed: 0x2000, 0x2ee: 0x2000, 0x2ef: 0x2000,
+ // Block 0xc, offset 0x300
+ 0x311: 0x2000,
+ 0x312: 0x2000, 0x313: 0x2000, 0x314: 0x2000, 0x315: 0x2000, 0x316: 0x2000, 0x317: 0x2000,
+ 0x318: 0x2000, 0x319: 0x2000, 0x31a: 0x2000, 0x31b: 0x2000, 0x31c: 0x2000, 0x31d: 0x2000,
+ 0x31e: 0x2000, 0x31f: 0x2000, 0x320: 0x2000, 0x321: 0x2000, 0x323: 0x2000,
+ 0x324: 0x2000, 0x325: 0x2000, 0x326: 0x2000, 0x327: 0x2000, 0x328: 0x2000, 0x329: 0x2000,
+ 0x331: 0x2000, 0x332: 0x2000, 0x333: 0x2000, 0x334: 0x2000, 0x335: 0x2000,
+ 0x336: 0x2000, 0x337: 0x2000, 0x338: 0x2000, 0x339: 0x2000, 0x33a: 0x2000, 0x33b: 0x2000,
+ 0x33c: 0x2000, 0x33d: 0x2000, 0x33e: 0x2000, 0x33f: 0x2000,
+ // Block 0xd, offset 0x340
+ 0x340: 0x2000, 0x341: 0x2000, 0x343: 0x2000, 0x344: 0x2000, 0x345: 0x2000,
+ 0x346: 0x2000, 0x347: 0x2000, 0x348: 0x2000, 0x349: 0x2000,
+ // Block 0xe, offset 0x380
+ 0x381: 0x2000,
+ 0x390: 0x2000, 0x391: 0x2000,
+ 0x392: 0x2000, 0x393: 0x2000, 0x394: 0x2000, 0x395: 0x2000, 0x396: 0x2000, 0x397: 0x2000,
+ 0x398: 0x2000, 0x399: 0x2000, 0x39a: 0x2000, 0x39b: 0x2000, 0x39c: 0x2000, 0x39d: 0x2000,
+ 0x39e: 0x2000, 0x39f: 0x2000, 0x3a0: 0x2000, 0x3a1: 0x2000, 0x3a2: 0x2000, 0x3a3: 0x2000,
+ 0x3a4: 0x2000, 0x3a5: 0x2000, 0x3a6: 0x2000, 0x3a7: 0x2000, 0x3a8: 0x2000, 0x3a9: 0x2000,
+ 0x3aa: 0x2000, 0x3ab: 0x2000, 0x3ac: 0x2000, 0x3ad: 0x2000, 0x3ae: 0x2000, 0x3af: 0x2000,
+ 0x3b0: 0x2000, 0x3b1: 0x2000, 0x3b2: 0x2000, 0x3b3: 0x2000, 0x3b4: 0x2000, 0x3b5: 0x2000,
+ 0x3b6: 0x2000, 0x3b7: 0x2000, 0x3b8: 0x2000, 0x3b9: 0x2000, 0x3ba: 0x2000, 0x3bb: 0x2000,
+ 0x3bc: 0x2000, 0x3bd: 0x2000, 0x3be: 0x2000, 0x3bf: 0x2000,
+ // Block 0xf, offset 0x3c0
+ 0x3c0: 0x2000, 0x3c1: 0x2000, 0x3c2: 0x2000, 0x3c3: 0x2000, 0x3c4: 0x2000, 0x3c5: 0x2000,
+ 0x3c6: 0x2000, 0x3c7: 0x2000, 0x3c8: 0x2000, 0x3c9: 0x2000, 0x3ca: 0x2000, 0x3cb: 0x2000,
+ 0x3cc: 0x2000, 0x3cd: 0x2000, 0x3ce: 0x2000, 0x3cf: 0x2000, 0x3d1: 0x2000,
+ // Block 0x10, offset 0x400
+ 0x400: 0x4000, 0x401: 0x4000, 0x402: 0x4000, 0x403: 0x4000, 0x404: 0x4000, 0x405: 0x4000,
+ 0x406: 0x4000, 0x407: 0x4000, 0x408: 0x4000, 0x409: 0x4000, 0x40a: 0x4000, 0x40b: 0x4000,
+ 0x40c: 0x4000, 0x40d: 0x4000, 0x40e: 0x4000, 0x40f: 0x4000, 0x410: 0x4000, 0x411: 0x4000,
+ 0x412: 0x4000, 0x413: 0x4000, 0x414: 0x4000, 0x415: 0x4000, 0x416: 0x4000, 0x417: 0x4000,
+ 0x418: 0x4000, 0x419: 0x4000, 0x41a: 0x4000, 0x41b: 0x4000, 0x41c: 0x4000, 0x41d: 0x4000,
+ 0x41e: 0x4000, 0x41f: 0x4000, 0x420: 0x4000, 0x421: 0x4000, 0x422: 0x4000, 0x423: 0x4000,
+ 0x424: 0x4000, 0x425: 0x4000, 0x426: 0x4000, 0x427: 0x4000, 0x428: 0x4000, 0x429: 0x4000,
+ 0x42a: 0x4000, 0x42b: 0x4000, 0x42c: 0x4000, 0x42d: 0x4000, 0x42e: 0x4000, 0x42f: 0x4000,
+ 0x430: 0x4000, 0x431: 0x4000, 0x432: 0x4000, 0x433: 0x4000, 0x434: 0x4000, 0x435: 0x4000,
+ 0x436: 0x4000, 0x437: 0x4000, 0x438: 0x4000, 0x439: 0x4000, 0x43a: 0x4000, 0x43b: 0x4000,
+ 0x43c: 0x4000, 0x43d: 0x4000, 0x43e: 0x4000, 0x43f: 0x4000,
+ // Block 0x11, offset 0x440
+ 0x440: 0x4000, 0x441: 0x4000, 0x442: 0x4000, 0x443: 0x4000, 0x444: 0x4000, 0x445: 0x4000,
+ 0x446: 0x4000, 0x447: 0x4000, 0x448: 0x4000, 0x449: 0x4000, 0x44a: 0x4000, 0x44b: 0x4000,
+ 0x44c: 0x4000, 0x44d: 0x4000, 0x44e: 0x4000, 0x44f: 0x4000, 0x450: 0x4000, 0x451: 0x4000,
+ 0x452: 0x4000, 0x453: 0x4000, 0x454: 0x4000, 0x455: 0x4000, 0x456: 0x4000, 0x457: 0x4000,
+ 0x458: 0x4000, 0x459: 0x4000, 0x45a: 0x4000, 0x45b: 0x4000, 0x45c: 0x4000, 0x45d: 0x4000,
+ 0x45e: 0x4000, 0x45f: 0x4000,
+ // Block 0x12, offset 0x480
+ 0x490: 0x2000,
+ 0x493: 0x2000, 0x494: 0x2000, 0x495: 0x2000, 0x496: 0x2000,
+ 0x498: 0x2000, 0x499: 0x2000, 0x49c: 0x2000, 0x49d: 0x2000,
+ 0x4a0: 0x2000, 0x4a1: 0x2000, 0x4a2: 0x2000,
+ 0x4a4: 0x2000, 0x4a5: 0x2000, 0x4a6: 0x2000, 0x4a7: 0x2000,
+ 0x4b0: 0x2000, 0x4b2: 0x2000, 0x4b3: 0x2000, 0x4b5: 0x2000,
+ 0x4bb: 0x2000,
+ 0x4be: 0x2000,
+ // Block 0x13, offset 0x4c0
+ 0x4f4: 0x2000,
+ 0x4ff: 0x2000,
+ // Block 0x14, offset 0x500
+ 0x501: 0x2000, 0x502: 0x2000, 0x503: 0x2000, 0x504: 0x2000,
+ 0x529: 0xa009,
+ 0x52c: 0x2000,
+ // Block 0x15, offset 0x540
+ 0x543: 0x2000, 0x545: 0x2000,
+ 0x549: 0x2000,
+ 0x553: 0x2000, 0x556: 0x2000,
+ 0x561: 0x2000, 0x562: 0x2000,
+ 0x566: 0x2000,
+ 0x56b: 0x2000,
+ // Block 0x16, offset 0x580
+ 0x593: 0x2000, 0x594: 0x2000,
+ 0x59b: 0x2000, 0x59c: 0x2000, 0x59d: 0x2000,
+ 0x59e: 0x2000, 0x5a0: 0x2000, 0x5a1: 0x2000, 0x5a2: 0x2000, 0x5a3: 0x2000,
+ 0x5a4: 0x2000, 0x5a5: 0x2000, 0x5a6: 0x2000, 0x5a7: 0x2000, 0x5a8: 0x2000, 0x5a9: 0x2000,
+ 0x5aa: 0x2000, 0x5ab: 0x2000,
+ 0x5b0: 0x2000, 0x5b1: 0x2000, 0x5b2: 0x2000, 0x5b3: 0x2000, 0x5b4: 0x2000, 0x5b5: 0x2000,
+ 0x5b6: 0x2000, 0x5b7: 0x2000, 0x5b8: 0x2000, 0x5b9: 0x2000,
+ // Block 0x17, offset 0x5c0
+ 0x5c9: 0x2000,
+ 0x5d0: 0x200a, 0x5d1: 0x200b,
+ 0x5d2: 0x200a, 0x5d3: 0x200c, 0x5d4: 0x2000, 0x5d5: 0x2000, 0x5d6: 0x2000, 0x5d7: 0x2000,
+ 0x5d8: 0x2000, 0x5d9: 0x2000,
+ 0x5f8: 0x2000, 0x5f9: 0x2000,
+ // Block 0x18, offset 0x600
+ 0x612: 0x2000, 0x614: 0x2000,
+ 0x627: 0x2000,
+ // Block 0x19, offset 0x640
+ 0x640: 0x2000, 0x642: 0x2000, 0x643: 0x2000,
+ 0x647: 0x2000, 0x648: 0x2000, 0x64b: 0x2000,
+ 0x64f: 0x2000, 0x651: 0x2000,
+ 0x655: 0x2000,
+ 0x65a: 0x2000, 0x65d: 0x2000,
+ 0x65e: 0x2000, 0x65f: 0x2000, 0x660: 0x2000, 0x663: 0x2000,
+ 0x665: 0x2000, 0x667: 0x2000, 0x668: 0x2000, 0x669: 0x2000,
+ 0x66a: 0x2000, 0x66b: 0x2000, 0x66c: 0x2000, 0x66e: 0x2000,
+ 0x674: 0x2000, 0x675: 0x2000,
+ 0x676: 0x2000, 0x677: 0x2000,
+ 0x67c: 0x2000, 0x67d: 0x2000,
+ // Block 0x1a, offset 0x680
+ 0x688: 0x2000,
+ 0x68c: 0x2000,
+ 0x692: 0x2000,
+ 0x6a0: 0x2000, 0x6a1: 0x2000,
+ 0x6a4: 0x2000, 0x6a5: 0x2000, 0x6a6: 0x2000, 0x6a7: 0x2000,
+ 0x6aa: 0x2000, 0x6ab: 0x2000, 0x6ae: 0x2000, 0x6af: 0x2000,
+ // Block 0x1b, offset 0x6c0
+ 0x6c2: 0x2000, 0x6c3: 0x2000,
+ 0x6c6: 0x2000, 0x6c7: 0x2000,
+ 0x6d5: 0x2000,
+ 0x6d9: 0x2000,
+ 0x6e5: 0x2000,
+ 0x6ff: 0x2000,
+ // Block 0x1c, offset 0x700
+ 0x712: 0x2000,
+ 0x71a: 0x4000, 0x71b: 0x4000,
+ 0x729: 0x4000,
+ 0x72a: 0x4000,
+ // Block 0x1d, offset 0x740
+ 0x769: 0x4000,
+ 0x76a: 0x4000, 0x76b: 0x4000, 0x76c: 0x4000,
+ 0x770: 0x4000, 0x773: 0x4000,
+ // Block 0x1e, offset 0x780
+ 0x7a0: 0x2000, 0x7a1: 0x2000, 0x7a2: 0x2000, 0x7a3: 0x2000,
+ 0x7a4: 0x2000, 0x7a5: 0x2000, 0x7a6: 0x2000, 0x7a7: 0x2000, 0x7a8: 0x2000, 0x7a9: 0x2000,
+ 0x7aa: 0x2000, 0x7ab: 0x2000, 0x7ac: 0x2000, 0x7ad: 0x2000, 0x7ae: 0x2000, 0x7af: 0x2000,
+ 0x7b0: 0x2000, 0x7b1: 0x2000, 0x7b2: 0x2000, 0x7b3: 0x2000, 0x7b4: 0x2000, 0x7b5: 0x2000,
+ 0x7b6: 0x2000, 0x7b7: 0x2000, 0x7b8: 0x2000, 0x7b9: 0x2000, 0x7ba: 0x2000, 0x7bb: 0x2000,
+ 0x7bc: 0x2000, 0x7bd: 0x2000, 0x7be: 0x2000, 0x7bf: 0x2000,
+ // Block 0x1f, offset 0x7c0
+ 0x7c0: 0x2000, 0x7c1: 0x2000, 0x7c2: 0x2000, 0x7c3: 0x2000, 0x7c4: 0x2000, 0x7c5: 0x2000,
+ 0x7c6: 0x2000, 0x7c7: 0x2000, 0x7c8: 0x2000, 0x7c9: 0x2000, 0x7ca: 0x2000, 0x7cb: 0x2000,
+ 0x7cc: 0x2000, 0x7cd: 0x2000, 0x7ce: 0x2000, 0x7cf: 0x2000, 0x7d0: 0x2000, 0x7d1: 0x2000,
+ 0x7d2: 0x2000, 0x7d3: 0x2000, 0x7d4: 0x2000, 0x7d5: 0x2000, 0x7d6: 0x2000, 0x7d7: 0x2000,
+ 0x7d8: 0x2000, 0x7d9: 0x2000, 0x7da: 0x2000, 0x7db: 0x2000, 0x7dc: 0x2000, 0x7dd: 0x2000,
+ 0x7de: 0x2000, 0x7df: 0x2000, 0x7e0: 0x2000, 0x7e1: 0x2000, 0x7e2: 0x2000, 0x7e3: 0x2000,
+ 0x7e4: 0x2000, 0x7e5: 0x2000, 0x7e6: 0x2000, 0x7e7: 0x2000, 0x7e8: 0x2000, 0x7e9: 0x2000,
+ 0x7eb: 0x2000, 0x7ec: 0x2000, 0x7ed: 0x2000, 0x7ee: 0x2000, 0x7ef: 0x2000,
+ 0x7f0: 0x2000, 0x7f1: 0x2000, 0x7f2: 0x2000, 0x7f3: 0x2000, 0x7f4: 0x2000, 0x7f5: 0x2000,
+ 0x7f6: 0x2000, 0x7f7: 0x2000, 0x7f8: 0x2000, 0x7f9: 0x2000, 0x7fa: 0x2000, 0x7fb: 0x2000,
+ 0x7fc: 0x2000, 0x7fd: 0x2000, 0x7fe: 0x2000, 0x7ff: 0x2000,
+ // Block 0x20, offset 0x800
+ 0x800: 0x2000, 0x801: 0x2000, 0x802: 0x200d, 0x803: 0x2000, 0x804: 0x2000, 0x805: 0x2000,
+ 0x806: 0x2000, 0x807: 0x2000, 0x808: 0x2000, 0x809: 0x2000, 0x80a: 0x2000, 0x80b: 0x2000,
+ 0x80c: 0x2000, 0x80d: 0x2000, 0x80e: 0x2000, 0x80f: 0x2000, 0x810: 0x2000, 0x811: 0x2000,
+ 0x812: 0x2000, 0x813: 0x2000, 0x814: 0x2000, 0x815: 0x2000, 0x816: 0x2000, 0x817: 0x2000,
+ 0x818: 0x2000, 0x819: 0x2000, 0x81a: 0x2000, 0x81b: 0x2000, 0x81c: 0x2000, 0x81d: 0x2000,
+ 0x81e: 0x2000, 0x81f: 0x2000, 0x820: 0x2000, 0x821: 0x2000, 0x822: 0x2000, 0x823: 0x2000,
+ 0x824: 0x2000, 0x825: 0x2000, 0x826: 0x2000, 0x827: 0x2000, 0x828: 0x2000, 0x829: 0x2000,
+ 0x82a: 0x2000, 0x82b: 0x2000, 0x82c: 0x2000, 0x82d: 0x2000, 0x82e: 0x2000, 0x82f: 0x2000,
+ 0x830: 0x2000, 0x831: 0x2000, 0x832: 0x2000, 0x833: 0x2000, 0x834: 0x2000, 0x835: 0x2000,
+ 0x836: 0x2000, 0x837: 0x2000, 0x838: 0x2000, 0x839: 0x2000, 0x83a: 0x2000, 0x83b: 0x2000,
+ 0x83c: 0x2000, 0x83d: 0x2000, 0x83e: 0x2000, 0x83f: 0x2000,
+ // Block 0x21, offset 0x840
+ 0x840: 0x2000, 0x841: 0x2000, 0x842: 0x2000, 0x843: 0x2000, 0x844: 0x2000, 0x845: 0x2000,
+ 0x846: 0x2000, 0x847: 0x2000, 0x848: 0x2000, 0x849: 0x2000, 0x84a: 0x2000, 0x84b: 0x2000,
+ 0x850: 0x2000, 0x851: 0x2000,
+ 0x852: 0x2000, 0x853: 0x2000, 0x854: 0x2000, 0x855: 0x2000, 0x856: 0x2000, 0x857: 0x2000,
+ 0x858: 0x2000, 0x859: 0x2000, 0x85a: 0x2000, 0x85b: 0x2000, 0x85c: 0x2000, 0x85d: 0x2000,
+ 0x85e: 0x2000, 0x85f: 0x2000, 0x860: 0x2000, 0x861: 0x2000, 0x862: 0x2000, 0x863: 0x2000,
+ 0x864: 0x2000, 0x865: 0x2000, 0x866: 0x2000, 0x867: 0x2000, 0x868: 0x2000, 0x869: 0x2000,
+ 0x86a: 0x2000, 0x86b: 0x2000, 0x86c: 0x2000, 0x86d: 0x2000, 0x86e: 0x2000, 0x86f: 0x2000,
+ 0x870: 0x2000, 0x871: 0x2000, 0x872: 0x2000, 0x873: 0x2000,
+ // Block 0x22, offset 0x880
+ 0x880: 0x2000, 0x881: 0x2000, 0x882: 0x2000, 0x883: 0x2000, 0x884: 0x2000, 0x885: 0x2000,
+ 0x886: 0x2000, 0x887: 0x2000, 0x888: 0x2000, 0x889: 0x2000, 0x88a: 0x2000, 0x88b: 0x2000,
+ 0x88c: 0x2000, 0x88d: 0x2000, 0x88e: 0x2000, 0x88f: 0x2000,
+ 0x892: 0x2000, 0x893: 0x2000, 0x894: 0x2000, 0x895: 0x2000,
+ 0x8a0: 0x200e, 0x8a1: 0x2000, 0x8a3: 0x2000,
+ 0x8a4: 0x2000, 0x8a5: 0x2000, 0x8a6: 0x2000, 0x8a7: 0x2000, 0x8a8: 0x2000, 0x8a9: 0x2000,
+ 0x8b2: 0x2000, 0x8b3: 0x2000,
+ 0x8b6: 0x2000, 0x8b7: 0x2000,
+ 0x8bc: 0x2000, 0x8bd: 0x2000,
+ // Block 0x23, offset 0x8c0
+ 0x8c0: 0x2000, 0x8c1: 0x2000,
+ 0x8c6: 0x2000, 0x8c7: 0x2000, 0x8c8: 0x2000, 0x8cb: 0x200f,
+ 0x8ce: 0x2000, 0x8cf: 0x2000, 0x8d0: 0x2000, 0x8d1: 0x2000,
+ 0x8e2: 0x2000, 0x8e3: 0x2000,
+ 0x8e4: 0x2000, 0x8e5: 0x2000,
+ 0x8ef: 0x2000,
+ 0x8fd: 0x4000, 0x8fe: 0x4000,
+ // Block 0x24, offset 0x900
+ 0x905: 0x2000,
+ 0x906: 0x2000, 0x909: 0x2000,
+ 0x90e: 0x2000, 0x90f: 0x2000,
+ 0x914: 0x4000, 0x915: 0x4000,
+ 0x91c: 0x2000,
+ 0x91e: 0x2000,
+ // Block 0x25, offset 0x940
+ 0x940: 0x2000, 0x942: 0x2000,
+ 0x948: 0x4000, 0x949: 0x4000, 0x94a: 0x4000, 0x94b: 0x4000,
+ 0x94c: 0x4000, 0x94d: 0x4000, 0x94e: 0x4000, 0x94f: 0x4000, 0x950: 0x4000, 0x951: 0x4000,
+ 0x952: 0x4000, 0x953: 0x4000,
+ 0x960: 0x2000, 0x961: 0x2000, 0x963: 0x2000,
+ 0x964: 0x2000, 0x965: 0x2000, 0x967: 0x2000, 0x968: 0x2000, 0x969: 0x2000,
+ 0x96a: 0x2000, 0x96c: 0x2000, 0x96d: 0x2000, 0x96f: 0x2000,
+ 0x97f: 0x4000,
+ // Block 0x26, offset 0x980
+ 0x993: 0x4000,
+ 0x99e: 0x2000, 0x99f: 0x2000, 0x9a1: 0x4000,
+ 0x9aa: 0x4000, 0x9ab: 0x4000,
+ 0x9bd: 0x4000, 0x9be: 0x4000, 0x9bf: 0x2000,
+ // Block 0x27, offset 0x9c0
+ 0x9c4: 0x4000, 0x9c5: 0x4000,
+ 0x9c6: 0x2000, 0x9c7: 0x2000, 0x9c8: 0x2000, 0x9c9: 0x2000, 0x9ca: 0x2000, 0x9cb: 0x2000,
+ 0x9cc: 0x2000, 0x9cd: 0x2000, 0x9ce: 0x4000, 0x9cf: 0x2000, 0x9d0: 0x2000, 0x9d1: 0x2000,
+ 0x9d2: 0x2000, 0x9d3: 0x2000, 0x9d4: 0x4000, 0x9d5: 0x2000, 0x9d6: 0x2000, 0x9d7: 0x2000,
+ 0x9d8: 0x2000, 0x9d9: 0x2000, 0x9da: 0x2000, 0x9db: 0x2000, 0x9dc: 0x2000, 0x9dd: 0x2000,
+ 0x9de: 0x2000, 0x9df: 0x2000, 0x9e0: 0x2000, 0x9e1: 0x2000, 0x9e3: 0x2000,
+ 0x9e8: 0x2000, 0x9e9: 0x2000,
+ 0x9ea: 0x4000, 0x9eb: 0x2000, 0x9ec: 0x2000, 0x9ed: 0x2000, 0x9ee: 0x2000, 0x9ef: 0x2000,
+ 0x9f0: 0x2000, 0x9f1: 0x2000, 0x9f2: 0x4000, 0x9f3: 0x4000, 0x9f4: 0x2000, 0x9f5: 0x4000,
+ 0x9f6: 0x2000, 0x9f7: 0x2000, 0x9f8: 0x2000, 0x9f9: 0x2000, 0x9fa: 0x4000, 0x9fb: 0x2000,
+ 0x9fc: 0x2000, 0x9fd: 0x4000, 0x9fe: 0x2000, 0x9ff: 0x2000,
+ // Block 0x28, offset 0xa00
+ 0xa05: 0x4000,
+ 0xa0a: 0x4000, 0xa0b: 0x4000,
+ 0xa28: 0x4000,
+ 0xa3d: 0x2000,
+ // Block 0x29, offset 0xa40
+ 0xa4c: 0x4000, 0xa4e: 0x4000,
+ 0xa53: 0x4000, 0xa54: 0x4000, 0xa55: 0x4000, 0xa57: 0x4000,
+ 0xa76: 0x2000, 0xa77: 0x2000, 0xa78: 0x2000, 0xa79: 0x2000, 0xa7a: 0x2000, 0xa7b: 0x2000,
+ 0xa7c: 0x2000, 0xa7d: 0x2000, 0xa7e: 0x2000, 0xa7f: 0x2000,
+ // Block 0x2a, offset 0xa80
+ 0xa95: 0x4000, 0xa96: 0x4000, 0xa97: 0x4000,
+ 0xab0: 0x4000,
+ 0xabf: 0x4000,
+ // Block 0x2b, offset 0xac0
+ 0xae6: 0x6000, 0xae7: 0x6000, 0xae8: 0x6000, 0xae9: 0x6000,
+ 0xaea: 0x6000, 0xaeb: 0x6000, 0xaec: 0x6000, 0xaed: 0x6000,
+ // Block 0x2c, offset 0xb00
+ 0xb05: 0x6010,
+ 0xb06: 0x6011,
+ // Block 0x2d, offset 0xb40
+ 0xb5b: 0x4000, 0xb5c: 0x4000,
+ // Block 0x2e, offset 0xb80
+ 0xb90: 0x4000,
+ 0xb95: 0x4000, 0xb96: 0x2000, 0xb97: 0x2000,
+ 0xb98: 0x2000, 0xb99: 0x2000,
+ // Block 0x2f, offset 0xbc0
+ 0xbc0: 0x4000, 0xbc1: 0x4000, 0xbc2: 0x4000, 0xbc3: 0x4000, 0xbc4: 0x4000, 0xbc5: 0x4000,
+ 0xbc6: 0x4000, 0xbc7: 0x4000, 0xbc8: 0x4000, 0xbc9: 0x4000, 0xbca: 0x4000, 0xbcb: 0x4000,
+ 0xbcc: 0x4000, 0xbcd: 0x4000, 0xbce: 0x4000, 0xbcf: 0x4000, 0xbd0: 0x4000, 0xbd1: 0x4000,
+ 0xbd2: 0x4000, 0xbd3: 0x4000, 0xbd4: 0x4000, 0xbd5: 0x4000, 0xbd6: 0x4000, 0xbd7: 0x4000,
+ 0xbd8: 0x4000, 0xbd9: 0x4000, 0xbdb: 0x4000, 0xbdc: 0x4000, 0xbdd: 0x4000,
+ 0xbde: 0x4000, 0xbdf: 0x4000, 0xbe0: 0x4000, 0xbe1: 0x4000, 0xbe2: 0x4000, 0xbe3: 0x4000,
+ 0xbe4: 0x4000, 0xbe5: 0x4000, 0xbe6: 0x4000, 0xbe7: 0x4000, 0xbe8: 0x4000, 0xbe9: 0x4000,
+ 0xbea: 0x4000, 0xbeb: 0x4000, 0xbec: 0x4000, 0xbed: 0x4000, 0xbee: 0x4000, 0xbef: 0x4000,
+ 0xbf0: 0x4000, 0xbf1: 0x4000, 0xbf2: 0x4000, 0xbf3: 0x4000, 0xbf4: 0x4000, 0xbf5: 0x4000,
+ 0xbf6: 0x4000, 0xbf7: 0x4000, 0xbf8: 0x4000, 0xbf9: 0x4000, 0xbfa: 0x4000, 0xbfb: 0x4000,
+ 0xbfc: 0x4000, 0xbfd: 0x4000, 0xbfe: 0x4000, 0xbff: 0x4000,
+ // Block 0x30, offset 0xc00
+ 0xc00: 0x4000, 0xc01: 0x4000, 0xc02: 0x4000, 0xc03: 0x4000, 0xc04: 0x4000, 0xc05: 0x4000,
+ 0xc06: 0x4000, 0xc07: 0x4000, 0xc08: 0x4000, 0xc09: 0x4000, 0xc0a: 0x4000, 0xc0b: 0x4000,
+ 0xc0c: 0x4000, 0xc0d: 0x4000, 0xc0e: 0x4000, 0xc0f: 0x4000, 0xc10: 0x4000, 0xc11: 0x4000,
+ 0xc12: 0x4000, 0xc13: 0x4000, 0xc14: 0x4000, 0xc15: 0x4000, 0xc16: 0x4000, 0xc17: 0x4000,
+ 0xc18: 0x4000, 0xc19: 0x4000, 0xc1a: 0x4000, 0xc1b: 0x4000, 0xc1c: 0x4000, 0xc1d: 0x4000,
+ 0xc1e: 0x4000, 0xc1f: 0x4000, 0xc20: 0x4000, 0xc21: 0x4000, 0xc22: 0x4000, 0xc23: 0x4000,
+ 0xc24: 0x4000, 0xc25: 0x4000, 0xc26: 0x4000, 0xc27: 0x4000, 0xc28: 0x4000, 0xc29: 0x4000,
+ 0xc2a: 0x4000, 0xc2b: 0x4000, 0xc2c: 0x4000, 0xc2d: 0x4000, 0xc2e: 0x4000, 0xc2f: 0x4000,
+ 0xc30: 0x4000, 0xc31: 0x4000, 0xc32: 0x4000, 0xc33: 0x4000,
+ // Block 0x31, offset 0xc40
+ 0xc40: 0x4000, 0xc41: 0x4000, 0xc42: 0x4000, 0xc43: 0x4000, 0xc44: 0x4000, 0xc45: 0x4000,
+ 0xc46: 0x4000, 0xc47: 0x4000, 0xc48: 0x4000, 0xc49: 0x4000, 0xc4a: 0x4000, 0xc4b: 0x4000,
+ 0xc4c: 0x4000, 0xc4d: 0x4000, 0xc4e: 0x4000, 0xc4f: 0x4000, 0xc50: 0x4000, 0xc51: 0x4000,
+ 0xc52: 0x4000, 0xc53: 0x4000, 0xc54: 0x4000, 0xc55: 0x4000,
+ 0xc70: 0x4000, 0xc71: 0x4000, 0xc72: 0x4000, 0xc73: 0x4000, 0xc74: 0x4000, 0xc75: 0x4000,
+ 0xc76: 0x4000, 0xc77: 0x4000, 0xc78: 0x4000, 0xc79: 0x4000, 0xc7a: 0x4000, 0xc7b: 0x4000,
+ // Block 0x32, offset 0xc80
+ 0xc80: 0x9012, 0xc81: 0x4013, 0xc82: 0x4014, 0xc83: 0x4000, 0xc84: 0x4000, 0xc85: 0x4000,
+ 0xc86: 0x4000, 0xc87: 0x4000, 0xc88: 0x4000, 0xc89: 0x4000, 0xc8a: 0x4000, 0xc8b: 0x4000,
+ 0xc8c: 0x4015, 0xc8d: 0x4015, 0xc8e: 0x4000, 0xc8f: 0x4000, 0xc90: 0x4000, 0xc91: 0x4000,
+ 0xc92: 0x4000, 0xc93: 0x4000, 0xc94: 0x4000, 0xc95: 0x4000, 0xc96: 0x4000, 0xc97: 0x4000,
+ 0xc98: 0x4000, 0xc99: 0x4000, 0xc9a: 0x4000, 0xc9b: 0x4000, 0xc9c: 0x4000, 0xc9d: 0x4000,
+ 0xc9e: 0x4000, 0xc9f: 0x4000, 0xca0: 0x4000, 0xca1: 0x4000, 0xca2: 0x4000, 0xca3: 0x4000,
+ 0xca4: 0x4000, 0xca5: 0x4000, 0xca6: 0x4000, 0xca7: 0x4000, 0xca8: 0x4000, 0xca9: 0x4000,
+ 0xcaa: 0x4000, 0xcab: 0x4000, 0xcac: 0x4000, 0xcad: 0x4000, 0xcae: 0x4000, 0xcaf: 0x4000,
+ 0xcb0: 0x4000, 0xcb1: 0x4000, 0xcb2: 0x4000, 0xcb3: 0x4000, 0xcb4: 0x4000, 0xcb5: 0x4000,
+ 0xcb6: 0x4000, 0xcb7: 0x4000, 0xcb8: 0x4000, 0xcb9: 0x4000, 0xcba: 0x4000, 0xcbb: 0x4000,
+ 0xcbc: 0x4000, 0xcbd: 0x4000, 0xcbe: 0x4000,
+ // Block 0x33, offset 0xcc0
+ 0xcc1: 0x4000, 0xcc2: 0x4000, 0xcc3: 0x4000, 0xcc4: 0x4000, 0xcc5: 0x4000,
+ 0xcc6: 0x4000, 0xcc7: 0x4000, 0xcc8: 0x4000, 0xcc9: 0x4000, 0xcca: 0x4000, 0xccb: 0x4000,
+ 0xccc: 0x4000, 0xccd: 0x4000, 0xcce: 0x4000, 0xccf: 0x4000, 0xcd0: 0x4000, 0xcd1: 0x4000,
+ 0xcd2: 0x4000, 0xcd3: 0x4000, 0xcd4: 0x4000, 0xcd5: 0x4000, 0xcd6: 0x4000, 0xcd7: 0x4000,
+ 0xcd8: 0x4000, 0xcd9: 0x4000, 0xcda: 0x4000, 0xcdb: 0x4000, 0xcdc: 0x4000, 0xcdd: 0x4000,
+ 0xcde: 0x4000, 0xcdf: 0x4000, 0xce0: 0x4000, 0xce1: 0x4000, 0xce2: 0x4000, 0xce3: 0x4000,
+ 0xce4: 0x4000, 0xce5: 0x4000, 0xce6: 0x4000, 0xce7: 0x4000, 0xce8: 0x4000, 0xce9: 0x4000,
+ 0xcea: 0x4000, 0xceb: 0x4000, 0xcec: 0x4000, 0xced: 0x4000, 0xcee: 0x4000, 0xcef: 0x4000,
+ 0xcf0: 0x4000, 0xcf1: 0x4000, 0xcf2: 0x4000, 0xcf3: 0x4000, 0xcf4: 0x4000, 0xcf5: 0x4000,
+ 0xcf6: 0x4000, 0xcf7: 0x4000, 0xcf8: 0x4000, 0xcf9: 0x4000, 0xcfa: 0x4000, 0xcfb: 0x4000,
+ 0xcfc: 0x4000, 0xcfd: 0x4000, 0xcfe: 0x4000, 0xcff: 0x4000,
+ // Block 0x34, offset 0xd00
+ 0xd00: 0x4000, 0xd01: 0x4000, 0xd02: 0x4000, 0xd03: 0x4000, 0xd04: 0x4000, 0xd05: 0x4000,
+ 0xd06: 0x4000, 0xd07: 0x4000, 0xd08: 0x4000, 0xd09: 0x4000, 0xd0a: 0x4000, 0xd0b: 0x4000,
+ 0xd0c: 0x4000, 0xd0d: 0x4000, 0xd0e: 0x4000, 0xd0f: 0x4000, 0xd10: 0x4000, 0xd11: 0x4000,
+ 0xd12: 0x4000, 0xd13: 0x4000, 0xd14: 0x4000, 0xd15: 0x4000, 0xd16: 0x4000,
+ 0xd19: 0x4016, 0xd1a: 0x4017, 0xd1b: 0x4000, 0xd1c: 0x4000, 0xd1d: 0x4000,
+ 0xd1e: 0x4000, 0xd1f: 0x4000, 0xd20: 0x4000, 0xd21: 0x4018, 0xd22: 0x4019, 0xd23: 0x401a,
+ 0xd24: 0x401b, 0xd25: 0x401c, 0xd26: 0x401d, 0xd27: 0x401e, 0xd28: 0x401f, 0xd29: 0x4020,
+ 0xd2a: 0x4021, 0xd2b: 0x4022, 0xd2c: 0x4000, 0xd2d: 0x4010, 0xd2e: 0x4000, 0xd2f: 0x4023,
+ 0xd30: 0x4000, 0xd31: 0x4024, 0xd32: 0x4000, 0xd33: 0x4025, 0xd34: 0x4000, 0xd35: 0x4026,
+ 0xd36: 0x4000, 0xd37: 0x401a, 0xd38: 0x4000, 0xd39: 0x4027, 0xd3a: 0x4000, 0xd3b: 0x4028,
+ 0xd3c: 0x4000, 0xd3d: 0x4020, 0xd3e: 0x4000, 0xd3f: 0x4029,
+ // Block 0x35, offset 0xd40
+ 0xd40: 0x4000, 0xd41: 0x402a, 0xd42: 0x4000, 0xd43: 0x402b, 0xd44: 0x402c, 0xd45: 0x4000,
+ 0xd46: 0x4017, 0xd47: 0x4000, 0xd48: 0x402d, 0xd49: 0x4000, 0xd4a: 0x402e, 0xd4b: 0x402f,
+ 0xd4c: 0x4030, 0xd4d: 0x4017, 0xd4e: 0x4016, 0xd4f: 0x4017, 0xd50: 0x4000, 0xd51: 0x4000,
+ 0xd52: 0x4031, 0xd53: 0x4000, 0xd54: 0x4000, 0xd55: 0x4031, 0xd56: 0x4000, 0xd57: 0x4000,
+ 0xd58: 0x4032, 0xd59: 0x4000, 0xd5a: 0x4000, 0xd5b: 0x4032, 0xd5c: 0x4000, 0xd5d: 0x4000,
+ 0xd5e: 0x4033, 0xd5f: 0x402e, 0xd60: 0x4034, 0xd61: 0x4035, 0xd62: 0x4034, 0xd63: 0x4036,
+ 0xd64: 0x4037, 0xd65: 0x4024, 0xd66: 0x4035, 0xd67: 0x4025, 0xd68: 0x4038, 0xd69: 0x4038,
+ 0xd6a: 0x4039, 0xd6b: 0x4039, 0xd6c: 0x403a, 0xd6d: 0x403a, 0xd6e: 0x4000, 0xd6f: 0x4035,
+ 0xd70: 0x4000, 0xd71: 0x4000, 0xd72: 0x403b, 0xd73: 0x403c, 0xd74: 0x4000, 0xd75: 0x4000,
+ 0xd76: 0x4000, 0xd77: 0x4000, 0xd78: 0x4000, 0xd79: 0x4000, 0xd7a: 0x4000, 0xd7b: 0x403d,
+ 0xd7c: 0x401c, 0xd7d: 0x4000, 0xd7e: 0x4000, 0xd7f: 0x4000,
+ // Block 0x36, offset 0xd80
+ 0xd85: 0x4000,
+ 0xd86: 0x4000, 0xd87: 0x4000, 0xd88: 0x4000, 0xd89: 0x4000, 0xd8a: 0x4000, 0xd8b: 0x4000,
+ 0xd8c: 0x4000, 0xd8d: 0x4000, 0xd8e: 0x4000, 0xd8f: 0x4000, 0xd90: 0x4000, 0xd91: 0x4000,
+ 0xd92: 0x4000, 0xd93: 0x4000, 0xd94: 0x4000, 0xd95: 0x4000, 0xd96: 0x4000, 0xd97: 0x4000,
+ 0xd98: 0x4000, 0xd99: 0x4000, 0xd9a: 0x4000, 0xd9b: 0x4000, 0xd9c: 0x4000, 0xd9d: 0x4000,
+ 0xd9e: 0x4000, 0xd9f: 0x4000, 0xda0: 0x4000, 0xda1: 0x4000, 0xda2: 0x4000, 0xda3: 0x4000,
+ 0xda4: 0x4000, 0xda5: 0x4000, 0xda6: 0x4000, 0xda7: 0x4000, 0xda8: 0x4000, 0xda9: 0x4000,
+ 0xdaa: 0x4000, 0xdab: 0x4000, 0xdac: 0x4000, 0xdad: 0x4000,
+ 0xdb1: 0x403e, 0xdb2: 0x403e, 0xdb3: 0x403e, 0xdb4: 0x403e, 0xdb5: 0x403e,
+ 0xdb6: 0x403e, 0xdb7: 0x403e, 0xdb8: 0x403e, 0xdb9: 0x403e, 0xdba: 0x403e, 0xdbb: 0x403e,
+ 0xdbc: 0x403e, 0xdbd: 0x403e, 0xdbe: 0x403e, 0xdbf: 0x403e,
+ // Block 0x37, offset 0xdc0
+ 0xdc0: 0x4037, 0xdc1: 0x4037, 0xdc2: 0x4037, 0xdc3: 0x4037, 0xdc4: 0x4037, 0xdc5: 0x4037,
+ 0xdc6: 0x4037, 0xdc7: 0x4037, 0xdc8: 0x4037, 0xdc9: 0x4037, 0xdca: 0x4037, 0xdcb: 0x4037,
+ 0xdcc: 0x4037, 0xdcd: 0x4037, 0xdce: 0x4037, 0xdcf: 0x400e, 0xdd0: 0x403f, 0xdd1: 0x4040,
+ 0xdd2: 0x4041, 0xdd3: 0x4040, 0xdd4: 0x403f, 0xdd5: 0x4042, 0xdd6: 0x4043, 0xdd7: 0x4044,
+ 0xdd8: 0x4040, 0xdd9: 0x4041, 0xdda: 0x4040, 0xddb: 0x4045, 0xddc: 0x4009, 0xddd: 0x4045,
+ 0xdde: 0x4046, 0xddf: 0x4045, 0xde0: 0x4047, 0xde1: 0x400b, 0xde2: 0x400a, 0xde3: 0x400c,
+ 0xde4: 0x4048, 0xde5: 0x4000, 0xde6: 0x4000, 0xde7: 0x4000, 0xde8: 0x4000, 0xde9: 0x4000,
+ 0xdea: 0x4000, 0xdeb: 0x4000, 0xdec: 0x4000, 0xded: 0x4000, 0xdee: 0x4000, 0xdef: 0x4000,
+ 0xdf0: 0x4000, 0xdf1: 0x4000, 0xdf2: 0x4000, 0xdf3: 0x4000, 0xdf4: 0x4000, 0xdf5: 0x4000,
+ 0xdf6: 0x4000, 0xdf7: 0x4000, 0xdf8: 0x4000, 0xdf9: 0x4000, 0xdfa: 0x4000, 0xdfb: 0x4000,
+ 0xdfc: 0x4000, 0xdfd: 0x4000, 0xdfe: 0x4000, 0xdff: 0x4000,
+ // Block 0x38, offset 0xe00
+ 0xe00: 0x4000, 0xe01: 0x4000, 0xe02: 0x4000, 0xe03: 0x4000, 0xe04: 0x4000, 0xe05: 0x4000,
+ 0xe06: 0x4000, 0xe07: 0x4000, 0xe08: 0x4000, 0xe09: 0x4000, 0xe0a: 0x4000, 0xe0b: 0x4000,
+ 0xe0c: 0x4000, 0xe0d: 0x4000, 0xe0e: 0x4000, 0xe10: 0x4000, 0xe11: 0x4000,
+ 0xe12: 0x4000, 0xe13: 0x4000, 0xe14: 0x4000, 0xe15: 0x4000, 0xe16: 0x4000, 0xe17: 0x4000,
+ 0xe18: 0x4000, 0xe19: 0x4000, 0xe1a: 0x4000, 0xe1b: 0x4000, 0xe1c: 0x4000, 0xe1d: 0x4000,
+ 0xe1e: 0x4000, 0xe1f: 0x4000, 0xe20: 0x4000, 0xe21: 0x4000, 0xe22: 0x4000, 0xe23: 0x4000,
+ 0xe24: 0x4000, 0xe25: 0x4000, 0xe26: 0x4000, 0xe27: 0x4000, 0xe28: 0x4000, 0xe29: 0x4000,
+ 0xe2a: 0x4000, 0xe2b: 0x4000, 0xe2c: 0x4000, 0xe2d: 0x4000, 0xe2e: 0x4000, 0xe2f: 0x4000,
+ 0xe30: 0x4000, 0xe31: 0x4000, 0xe32: 0x4000, 0xe33: 0x4000, 0xe34: 0x4000, 0xe35: 0x4000,
+ 0xe36: 0x4000, 0xe37: 0x4000, 0xe38: 0x4000, 0xe39: 0x4000, 0xe3a: 0x4000,
+ // Block 0x39, offset 0xe40
+ 0xe40: 0x4000, 0xe41: 0x4000, 0xe42: 0x4000, 0xe43: 0x4000, 0xe44: 0x4000, 0xe45: 0x4000,
+ 0xe46: 0x4000, 0xe47: 0x4000, 0xe48: 0x4000, 0xe49: 0x4000, 0xe4a: 0x4000, 0xe4b: 0x4000,
+ 0xe4c: 0x4000, 0xe4d: 0x4000, 0xe4e: 0x4000, 0xe4f: 0x4000, 0xe50: 0x4000, 0xe51: 0x4000,
+ 0xe52: 0x4000, 0xe53: 0x4000, 0xe54: 0x4000, 0xe55: 0x4000, 0xe56: 0x4000, 0xe57: 0x4000,
+ 0xe58: 0x4000, 0xe59: 0x4000, 0xe5a: 0x4000, 0xe5b: 0x4000, 0xe5c: 0x4000, 0xe5d: 0x4000,
+ 0xe5e: 0x4000, 0xe5f: 0x4000, 0xe60: 0x4000, 0xe61: 0x4000, 0xe62: 0x4000, 0xe63: 0x4000,
+ 0xe70: 0x4000, 0xe71: 0x4000, 0xe72: 0x4000, 0xe73: 0x4000, 0xe74: 0x4000, 0xe75: 0x4000,
+ 0xe76: 0x4000, 0xe77: 0x4000, 0xe78: 0x4000, 0xe79: 0x4000, 0xe7a: 0x4000, 0xe7b: 0x4000,
+ 0xe7c: 0x4000, 0xe7d: 0x4000, 0xe7e: 0x4000, 0xe7f: 0x4000,
+ // Block 0x3a, offset 0xe80
+ 0xe80: 0x4000, 0xe81: 0x4000, 0xe82: 0x4000, 0xe83: 0x4000, 0xe84: 0x4000, 0xe85: 0x4000,
+ 0xe86: 0x4000, 0xe87: 0x4000, 0xe88: 0x4000, 0xe89: 0x4000, 0xe8a: 0x4000, 0xe8b: 0x4000,
+ 0xe8c: 0x4000, 0xe8d: 0x4000, 0xe8e: 0x4000, 0xe8f: 0x4000, 0xe90: 0x4000, 0xe91: 0x4000,
+ 0xe92: 0x4000, 0xe93: 0x4000, 0xe94: 0x4000, 0xe95: 0x4000, 0xe96: 0x4000, 0xe97: 0x4000,
+ 0xe98: 0x4000, 0xe99: 0x4000, 0xe9a: 0x4000, 0xe9b: 0x4000, 0xe9c: 0x4000, 0xe9d: 0x4000,
+ 0xe9e: 0x4000, 0xea0: 0x4000, 0xea1: 0x4000, 0xea2: 0x4000, 0xea3: 0x4000,
+ 0xea4: 0x4000, 0xea5: 0x4000, 0xea6: 0x4000, 0xea7: 0x4000, 0xea8: 0x4000, 0xea9: 0x4000,
+ 0xeaa: 0x4000, 0xeab: 0x4000, 0xeac: 0x4000, 0xead: 0x4000, 0xeae: 0x4000, 0xeaf: 0x4000,
+ 0xeb0: 0x4000, 0xeb1: 0x4000, 0xeb2: 0x4000, 0xeb3: 0x4000, 0xeb4: 0x4000, 0xeb5: 0x4000,
+ 0xeb6: 0x4000, 0xeb7: 0x4000, 0xeb8: 0x4000, 0xeb9: 0x4000, 0xeba: 0x4000, 0xebb: 0x4000,
+ 0xebc: 0x4000, 0xebd: 0x4000, 0xebe: 0x4000, 0xebf: 0x4000,
+ // Block 0x3b, offset 0xec0
+ 0xec0: 0x4000, 0xec1: 0x4000, 0xec2: 0x4000, 0xec3: 0x4000, 0xec4: 0x4000, 0xec5: 0x4000,
+ 0xec6: 0x4000, 0xec7: 0x4000, 0xec8: 0x2000, 0xec9: 0x2000, 0xeca: 0x2000, 0xecb: 0x2000,
+ 0xecc: 0x2000, 0xecd: 0x2000, 0xece: 0x2000, 0xecf: 0x2000, 0xed0: 0x4000, 0xed1: 0x4000,
+ 0xed2: 0x4000, 0xed3: 0x4000, 0xed4: 0x4000, 0xed5: 0x4000, 0xed6: 0x4000, 0xed7: 0x4000,
+ 0xed8: 0x4000, 0xed9: 0x4000, 0xeda: 0x4000, 0xedb: 0x4000, 0xedc: 0x4000, 0xedd: 0x4000,
+ 0xede: 0x4000, 0xedf: 0x4000, 0xee0: 0x4000, 0xee1: 0x4000, 0xee2: 0x4000, 0xee3: 0x4000,
+ 0xee4: 0x4000, 0xee5: 0x4000, 0xee6: 0x4000, 0xee7: 0x4000, 0xee8: 0x4000, 0xee9: 0x4000,
+ 0xeea: 0x4000, 0xeeb: 0x4000, 0xeec: 0x4000, 0xeed: 0x4000, 0xeee: 0x4000, 0xeef: 0x4000,
+ 0xef0: 0x4000, 0xef1: 0x4000, 0xef2: 0x4000, 0xef3: 0x4000, 0xef4: 0x4000, 0xef5: 0x4000,
+ 0xef6: 0x4000, 0xef7: 0x4000, 0xef8: 0x4000, 0xef9: 0x4000, 0xefa: 0x4000, 0xefb: 0x4000,
+ 0xefc: 0x4000, 0xefd: 0x4000, 0xefe: 0x4000, 0xeff: 0x4000,
+ // Block 0x3c, offset 0xf00
+ 0xf00: 0x4000, 0xf01: 0x4000, 0xf02: 0x4000, 0xf03: 0x4000, 0xf04: 0x4000, 0xf05: 0x4000,
+ 0xf06: 0x4000, 0xf07: 0x4000, 0xf08: 0x4000, 0xf09: 0x4000, 0xf0a: 0x4000, 0xf0b: 0x4000,
+ 0xf0c: 0x4000, 0xf0d: 0x4000, 0xf0e: 0x4000, 0xf0f: 0x4000, 0xf10: 0x4000, 0xf11: 0x4000,
+ 0xf12: 0x4000, 0xf13: 0x4000, 0xf14: 0x4000, 0xf15: 0x4000, 0xf16: 0x4000, 0xf17: 0x4000,
+ 0xf18: 0x4000, 0xf19: 0x4000, 0xf1a: 0x4000, 0xf1b: 0x4000, 0xf1c: 0x4000, 0xf1d: 0x4000,
+ 0xf1e: 0x4000, 0xf1f: 0x4000, 0xf20: 0x4000, 0xf21: 0x4000, 0xf22: 0x4000, 0xf23: 0x4000,
+ 0xf24: 0x4000, 0xf25: 0x4000, 0xf26: 0x4000, 0xf27: 0x4000, 0xf28: 0x4000, 0xf29: 0x4000,
+ 0xf2a: 0x4000, 0xf2b: 0x4000, 0xf2c: 0x4000, 0xf2d: 0x4000, 0xf2e: 0x4000, 0xf2f: 0x4000,
+ 0xf30: 0x4000, 0xf31: 0x4000, 0xf32: 0x4000, 0xf33: 0x4000, 0xf34: 0x4000, 0xf35: 0x4000,
+ 0xf36: 0x4000, 0xf37: 0x4000, 0xf38: 0x4000, 0xf39: 0x4000, 0xf3a: 0x4000, 0xf3b: 0x4000,
+ 0xf3c: 0x4000, 0xf3d: 0x4000, 0xf3e: 0x4000,
+ // Block 0x3d, offset 0xf40
+ 0xf40: 0x4000, 0xf41: 0x4000, 0xf42: 0x4000, 0xf43: 0x4000, 0xf44: 0x4000, 0xf45: 0x4000,
+ 0xf46: 0x4000, 0xf47: 0x4000, 0xf48: 0x4000, 0xf49: 0x4000, 0xf4a: 0x4000, 0xf4b: 0x4000,
+ 0xf4c: 0x4000, 0xf50: 0x4000, 0xf51: 0x4000,
+ 0xf52: 0x4000, 0xf53: 0x4000, 0xf54: 0x4000, 0xf55: 0x4000, 0xf56: 0x4000, 0xf57: 0x4000,
+ 0xf58: 0x4000, 0xf59: 0x4000, 0xf5a: 0x4000, 0xf5b: 0x4000, 0xf5c: 0x4000, 0xf5d: 0x4000,
+ 0xf5e: 0x4000, 0xf5f: 0x4000, 0xf60: 0x4000, 0xf61: 0x4000, 0xf62: 0x4000, 0xf63: 0x4000,
+ 0xf64: 0x4000, 0xf65: 0x4000, 0xf66: 0x4000, 0xf67: 0x4000, 0xf68: 0x4000, 0xf69: 0x4000,
+ 0xf6a: 0x4000, 0xf6b: 0x4000, 0xf6c: 0x4000, 0xf6d: 0x4000, 0xf6e: 0x4000, 0xf6f: 0x4000,
+ 0xf70: 0x4000, 0xf71: 0x4000, 0xf72: 0x4000, 0xf73: 0x4000, 0xf74: 0x4000, 0xf75: 0x4000,
+ 0xf76: 0x4000, 0xf77: 0x4000, 0xf78: 0x4000, 0xf79: 0x4000, 0xf7a: 0x4000, 0xf7b: 0x4000,
+ 0xf7c: 0x4000, 0xf7d: 0x4000, 0xf7e: 0x4000, 0xf7f: 0x4000,
+ // Block 0x3e, offset 0xf80
+ 0xf80: 0x4000, 0xf81: 0x4000, 0xf82: 0x4000, 0xf83: 0x4000, 0xf84: 0x4000, 0xf85: 0x4000,
+ 0xf86: 0x4000,
+ // Block 0x3f, offset 0xfc0
+ 0xfe0: 0x4000, 0xfe1: 0x4000, 0xfe2: 0x4000, 0xfe3: 0x4000,
+ 0xfe4: 0x4000, 0xfe5: 0x4000, 0xfe6: 0x4000, 0xfe7: 0x4000, 0xfe8: 0x4000, 0xfe9: 0x4000,
+ 0xfea: 0x4000, 0xfeb: 0x4000, 0xfec: 0x4000, 0xfed: 0x4000, 0xfee: 0x4000, 0xfef: 0x4000,
+ 0xff0: 0x4000, 0xff1: 0x4000, 0xff2: 0x4000, 0xff3: 0x4000, 0xff4: 0x4000, 0xff5: 0x4000,
+ 0xff6: 0x4000, 0xff7: 0x4000, 0xff8: 0x4000, 0xff9: 0x4000, 0xffa: 0x4000, 0xffb: 0x4000,
+ 0xffc: 0x4000,
+ // Block 0x40, offset 0x1000
+ 0x1000: 0x4000, 0x1001: 0x4000, 0x1002: 0x4000, 0x1003: 0x4000, 0x1004: 0x4000, 0x1005: 0x4000,
+ 0x1006: 0x4000, 0x1007: 0x4000, 0x1008: 0x4000, 0x1009: 0x4000, 0x100a: 0x4000, 0x100b: 0x4000,
+ 0x100c: 0x4000, 0x100d: 0x4000, 0x100e: 0x4000, 0x100f: 0x4000, 0x1010: 0x4000, 0x1011: 0x4000,
+ 0x1012: 0x4000, 0x1013: 0x4000, 0x1014: 0x4000, 0x1015: 0x4000, 0x1016: 0x4000, 0x1017: 0x4000,
+ 0x1018: 0x4000, 0x1019: 0x4000, 0x101a: 0x4000, 0x101b: 0x4000, 0x101c: 0x4000, 0x101d: 0x4000,
+ 0x101e: 0x4000, 0x101f: 0x4000, 0x1020: 0x4000, 0x1021: 0x4000, 0x1022: 0x4000, 0x1023: 0x4000,
+ // Block 0x41, offset 0x1040
+ 0x1040: 0x2000, 0x1041: 0x2000, 0x1042: 0x2000, 0x1043: 0x2000, 0x1044: 0x2000, 0x1045: 0x2000,
+ 0x1046: 0x2000, 0x1047: 0x2000, 0x1048: 0x2000, 0x1049: 0x2000, 0x104a: 0x2000, 0x104b: 0x2000,
+ 0x104c: 0x2000, 0x104d: 0x2000, 0x104e: 0x2000, 0x104f: 0x2000, 0x1050: 0x4000, 0x1051: 0x4000,
+ 0x1052: 0x4000, 0x1053: 0x4000, 0x1054: 0x4000, 0x1055: 0x4000, 0x1056: 0x4000, 0x1057: 0x4000,
+ 0x1058: 0x4000, 0x1059: 0x4000,
+ 0x1070: 0x4000, 0x1071: 0x4000, 0x1072: 0x4000, 0x1073: 0x4000, 0x1074: 0x4000, 0x1075: 0x4000,
+ 0x1076: 0x4000, 0x1077: 0x4000, 0x1078: 0x4000, 0x1079: 0x4000, 0x107a: 0x4000, 0x107b: 0x4000,
+ 0x107c: 0x4000, 0x107d: 0x4000, 0x107e: 0x4000, 0x107f: 0x4000,
+ // Block 0x42, offset 0x1080
+ 0x1080: 0x4000, 0x1081: 0x4000, 0x1082: 0x4000, 0x1083: 0x4000, 0x1084: 0x4000, 0x1085: 0x4000,
+ 0x1086: 0x4000, 0x1087: 0x4000, 0x1088: 0x4000, 0x1089: 0x4000, 0x108a: 0x4000, 0x108b: 0x4000,
+ 0x108c: 0x4000, 0x108d: 0x4000, 0x108e: 0x4000, 0x108f: 0x4000, 0x1090: 0x4000, 0x1091: 0x4000,
+ 0x1092: 0x4000, 0x1094: 0x4000, 0x1095: 0x4000, 0x1096: 0x4000, 0x1097: 0x4000,
+ 0x1098: 0x4000, 0x1099: 0x4000, 0x109a: 0x4000, 0x109b: 0x4000, 0x109c: 0x4000, 0x109d: 0x4000,
+ 0x109e: 0x4000, 0x109f: 0x4000, 0x10a0: 0x4000, 0x10a1: 0x4000, 0x10a2: 0x4000, 0x10a3: 0x4000,
+ 0x10a4: 0x4000, 0x10a5: 0x4000, 0x10a6: 0x4000, 0x10a8: 0x4000, 0x10a9: 0x4000,
+ 0x10aa: 0x4000, 0x10ab: 0x4000,
+ // Block 0x43, offset 0x10c0
+ 0x10c1: 0x9012, 0x10c2: 0x9012, 0x10c3: 0x9012, 0x10c4: 0x9012, 0x10c5: 0x9012,
+ 0x10c6: 0x9012, 0x10c7: 0x9012, 0x10c8: 0x9012, 0x10c9: 0x9012, 0x10ca: 0x9012, 0x10cb: 0x9012,
+ 0x10cc: 0x9012, 0x10cd: 0x9012, 0x10ce: 0x9012, 0x10cf: 0x9012, 0x10d0: 0x9012, 0x10d1: 0x9012,
+ 0x10d2: 0x9012, 0x10d3: 0x9012, 0x10d4: 0x9012, 0x10d5: 0x9012, 0x10d6: 0x9012, 0x10d7: 0x9012,
+ 0x10d8: 0x9012, 0x10d9: 0x9012, 0x10da: 0x9012, 0x10db: 0x9012, 0x10dc: 0x9012, 0x10dd: 0x9012,
+ 0x10de: 0x9012, 0x10df: 0x9012, 0x10e0: 0x9049, 0x10e1: 0x9049, 0x10e2: 0x9049, 0x10e3: 0x9049,
+ 0x10e4: 0x9049, 0x10e5: 0x9049, 0x10e6: 0x9049, 0x10e7: 0x9049, 0x10e8: 0x9049, 0x10e9: 0x9049,
+ 0x10ea: 0x9049, 0x10eb: 0x9049, 0x10ec: 0x9049, 0x10ed: 0x9049, 0x10ee: 0x9049, 0x10ef: 0x9049,
+ 0x10f0: 0x9049, 0x10f1: 0x9049, 0x10f2: 0x9049, 0x10f3: 0x9049, 0x10f4: 0x9049, 0x10f5: 0x9049,
+ 0x10f6: 0x9049, 0x10f7: 0x9049, 0x10f8: 0x9049, 0x10f9: 0x9049, 0x10fa: 0x9049, 0x10fb: 0x9049,
+ 0x10fc: 0x9049, 0x10fd: 0x9049, 0x10fe: 0x9049, 0x10ff: 0x9049,
+ // Block 0x44, offset 0x1100
+ 0x1100: 0x9049, 0x1101: 0x9049, 0x1102: 0x9049, 0x1103: 0x9049, 0x1104: 0x9049, 0x1105: 0x9049,
+ 0x1106: 0x9049, 0x1107: 0x9049, 0x1108: 0x9049, 0x1109: 0x9049, 0x110a: 0x9049, 0x110b: 0x9049,
+ 0x110c: 0x9049, 0x110d: 0x9049, 0x110e: 0x9049, 0x110f: 0x9049, 0x1110: 0x9049, 0x1111: 0x9049,
+ 0x1112: 0x9049, 0x1113: 0x9049, 0x1114: 0x9049, 0x1115: 0x9049, 0x1116: 0x9049, 0x1117: 0x9049,
+ 0x1118: 0x9049, 0x1119: 0x9049, 0x111a: 0x9049, 0x111b: 0x9049, 0x111c: 0x9049, 0x111d: 0x9049,
+ 0x111e: 0x9049, 0x111f: 0x904a, 0x1120: 0x904b, 0x1121: 0xb04c, 0x1122: 0xb04d, 0x1123: 0xb04d,
+ 0x1124: 0xb04e, 0x1125: 0xb04f, 0x1126: 0xb050, 0x1127: 0xb051, 0x1128: 0xb052, 0x1129: 0xb053,
+ 0x112a: 0xb054, 0x112b: 0xb055, 0x112c: 0xb056, 0x112d: 0xb057, 0x112e: 0xb058, 0x112f: 0xb059,
+ 0x1130: 0xb05a, 0x1131: 0xb05b, 0x1132: 0xb05c, 0x1133: 0xb05d, 0x1134: 0xb05e, 0x1135: 0xb05f,
+ 0x1136: 0xb060, 0x1137: 0xb061, 0x1138: 0xb062, 0x1139: 0xb063, 0x113a: 0xb064, 0x113b: 0xb065,
+ 0x113c: 0xb052, 0x113d: 0xb066, 0x113e: 0xb067, 0x113f: 0xb055,
+ // Block 0x45, offset 0x1140
+ 0x1140: 0xb068, 0x1141: 0xb069, 0x1142: 0xb06a, 0x1143: 0xb06b, 0x1144: 0xb05a, 0x1145: 0xb056,
+ 0x1146: 0xb06c, 0x1147: 0xb06d, 0x1148: 0xb06b, 0x1149: 0xb06e, 0x114a: 0xb06b, 0x114b: 0xb06f,
+ 0x114c: 0xb06f, 0x114d: 0xb070, 0x114e: 0xb070, 0x114f: 0xb071, 0x1150: 0xb056, 0x1151: 0xb072,
+ 0x1152: 0xb073, 0x1153: 0xb072, 0x1154: 0xb074, 0x1155: 0xb073, 0x1156: 0xb075, 0x1157: 0xb075,
+ 0x1158: 0xb076, 0x1159: 0xb076, 0x115a: 0xb077, 0x115b: 0xb077, 0x115c: 0xb073, 0x115d: 0xb078,
+ 0x115e: 0xb079, 0x115f: 0xb067, 0x1160: 0xb07a, 0x1161: 0xb07b, 0x1162: 0xb07b, 0x1163: 0xb07b,
+ 0x1164: 0xb07b, 0x1165: 0xb07b, 0x1166: 0xb07b, 0x1167: 0xb07b, 0x1168: 0xb07b, 0x1169: 0xb07b,
+ 0x116a: 0xb07b, 0x116b: 0xb07b, 0x116c: 0xb07b, 0x116d: 0xb07b, 0x116e: 0xb07b, 0x116f: 0xb07b,
+ 0x1170: 0xb07c, 0x1171: 0xb07c, 0x1172: 0xb07c, 0x1173: 0xb07c, 0x1174: 0xb07c, 0x1175: 0xb07c,
+ 0x1176: 0xb07c, 0x1177: 0xb07c, 0x1178: 0xb07c, 0x1179: 0xb07c, 0x117a: 0xb07c, 0x117b: 0xb07c,
+ 0x117c: 0xb07c, 0x117d: 0xb07c, 0x117e: 0xb07c,
+ // Block 0x46, offset 0x1180
+ 0x1182: 0xb07d, 0x1183: 0xb07e, 0x1184: 0xb07f, 0x1185: 0xb080,
+ 0x1186: 0xb07f, 0x1187: 0xb07e, 0x118a: 0xb081, 0x118b: 0xb082,
+ 0x118c: 0xb083, 0x118d: 0xb07f, 0x118e: 0xb080, 0x118f: 0xb07f,
+ 0x1192: 0xb084, 0x1193: 0xb085, 0x1194: 0xb084, 0x1195: 0xb086, 0x1196: 0xb084, 0x1197: 0xb087,
+ 0x119a: 0xb088, 0x119b: 0xb089, 0x119c: 0xb08a,
+ 0x11a0: 0x908b, 0x11a1: 0x908b, 0x11a2: 0x908c, 0x11a3: 0x908d,
+ 0x11a4: 0x908b, 0x11a5: 0x908e, 0x11a6: 0x908f, 0x11a8: 0xb090, 0x11a9: 0xb091,
+ 0x11aa: 0xb092, 0x11ab: 0xb091, 0x11ac: 0xb093, 0x11ad: 0xb094, 0x11ae: 0xb095,
+ 0x11bd: 0x2000,
+ // Block 0x47, offset 0x11c0
+ 0x11e0: 0x4000,
+ // Block 0x48, offset 0x1200
+ 0x1200: 0x4000, 0x1201: 0x4000, 0x1202: 0x4000, 0x1203: 0x4000, 0x1204: 0x4000, 0x1205: 0x4000,
+ 0x1206: 0x4000, 0x1207: 0x4000, 0x1208: 0x4000, 0x1209: 0x4000, 0x120a: 0x4000, 0x120b: 0x4000,
+ 0x120c: 0x4000, 0x120d: 0x4000, 0x120e: 0x4000, 0x120f: 0x4000, 0x1210: 0x4000, 0x1211: 0x4000,
+ 0x1212: 0x4000, 0x1213: 0x4000, 0x1214: 0x4000, 0x1215: 0x4000, 0x1216: 0x4000, 0x1217: 0x4000,
+ 0x1218: 0x4000, 0x1219: 0x4000, 0x121a: 0x4000, 0x121b: 0x4000, 0x121c: 0x4000, 0x121d: 0x4000,
+ 0x121e: 0x4000, 0x121f: 0x4000, 0x1220: 0x4000, 0x1221: 0x4000, 0x1222: 0x4000, 0x1223: 0x4000,
+ 0x1224: 0x4000, 0x1225: 0x4000, 0x1226: 0x4000, 0x1227: 0x4000, 0x1228: 0x4000, 0x1229: 0x4000,
+ 0x122a: 0x4000, 0x122b: 0x4000, 0x122c: 0x4000,
+ // Block 0x49, offset 0x1240
+ 0x1240: 0x4000, 0x1241: 0x4000, 0x1242: 0x4000, 0x1243: 0x4000, 0x1244: 0x4000, 0x1245: 0x4000,
+ 0x1246: 0x4000, 0x1247: 0x4000, 0x1248: 0x4000, 0x1249: 0x4000, 0x124a: 0x4000, 0x124b: 0x4000,
+ 0x124c: 0x4000, 0x124d: 0x4000, 0x124e: 0x4000, 0x124f: 0x4000, 0x1250: 0x4000, 0x1251: 0x4000,
+ 0x1252: 0x4000, 0x1253: 0x4000, 0x1254: 0x4000, 0x1255: 0x4000, 0x1256: 0x4000, 0x1257: 0x4000,
+ 0x1258: 0x4000, 0x1259: 0x4000, 0x125a: 0x4000, 0x125b: 0x4000, 0x125c: 0x4000, 0x125d: 0x4000,
+ 0x125e: 0x4000, 0x125f: 0x4000, 0x1260: 0x4000, 0x1261: 0x4000, 0x1262: 0x4000, 0x1263: 0x4000,
+ 0x1264: 0x4000, 0x1265: 0x4000, 0x1266: 0x4000, 0x1267: 0x4000, 0x1268: 0x4000, 0x1269: 0x4000,
+ 0x126a: 0x4000, 0x126b: 0x4000, 0x126c: 0x4000, 0x126d: 0x4000, 0x126e: 0x4000, 0x126f: 0x4000,
+ 0x1270: 0x4000, 0x1271: 0x4000, 0x1272: 0x4000,
+ // Block 0x4a, offset 0x1280
+ 0x1280: 0x4000, 0x1281: 0x4000,
+ // Block 0x4b, offset 0x12c0
+ 0x12c4: 0x4000,
+ // Block 0x4c, offset 0x1300
+ 0x130f: 0x4000,
+ // Block 0x4d, offset 0x1340
+ 0x1340: 0x2000, 0x1341: 0x2000, 0x1342: 0x2000, 0x1343: 0x2000, 0x1344: 0x2000, 0x1345: 0x2000,
+ 0x1346: 0x2000, 0x1347: 0x2000, 0x1348: 0x2000, 0x1349: 0x2000, 0x134a: 0x2000,
+ 0x1350: 0x2000, 0x1351: 0x2000,
+ 0x1352: 0x2000, 0x1353: 0x2000, 0x1354: 0x2000, 0x1355: 0x2000, 0x1356: 0x2000, 0x1357: 0x2000,
+ 0x1358: 0x2000, 0x1359: 0x2000, 0x135a: 0x2000, 0x135b: 0x2000, 0x135c: 0x2000, 0x135d: 0x2000,
+ 0x135e: 0x2000, 0x135f: 0x2000, 0x1360: 0x2000, 0x1361: 0x2000, 0x1362: 0x2000, 0x1363: 0x2000,
+ 0x1364: 0x2000, 0x1365: 0x2000, 0x1366: 0x2000, 0x1367: 0x2000, 0x1368: 0x2000, 0x1369: 0x2000,
+ 0x136a: 0x2000, 0x136b: 0x2000, 0x136c: 0x2000, 0x136d: 0x2000,
+ 0x1370: 0x2000, 0x1371: 0x2000, 0x1372: 0x2000, 0x1373: 0x2000, 0x1374: 0x2000, 0x1375: 0x2000,
+ 0x1376: 0x2000, 0x1377: 0x2000, 0x1378: 0x2000, 0x1379: 0x2000, 0x137a: 0x2000, 0x137b: 0x2000,
+ 0x137c: 0x2000, 0x137d: 0x2000, 0x137e: 0x2000, 0x137f: 0x2000,
+ // Block 0x4e, offset 0x1380
+ 0x1380: 0x2000, 0x1381: 0x2000, 0x1382: 0x2000, 0x1383: 0x2000, 0x1384: 0x2000, 0x1385: 0x2000,
+ 0x1386: 0x2000, 0x1387: 0x2000, 0x1388: 0x2000, 0x1389: 0x2000, 0x138a: 0x2000, 0x138b: 0x2000,
+ 0x138c: 0x2000, 0x138d: 0x2000, 0x138e: 0x2000, 0x138f: 0x2000, 0x1390: 0x2000, 0x1391: 0x2000,
+ 0x1392: 0x2000, 0x1393: 0x2000, 0x1394: 0x2000, 0x1395: 0x2000, 0x1396: 0x2000, 0x1397: 0x2000,
+ 0x1398: 0x2000, 0x1399: 0x2000, 0x139a: 0x2000, 0x139b: 0x2000, 0x139c: 0x2000, 0x139d: 0x2000,
+ 0x139e: 0x2000, 0x139f: 0x2000, 0x13a0: 0x2000, 0x13a1: 0x2000, 0x13a2: 0x2000, 0x13a3: 0x2000,
+ 0x13a4: 0x2000, 0x13a5: 0x2000, 0x13a6: 0x2000, 0x13a7: 0x2000, 0x13a8: 0x2000, 0x13a9: 0x2000,
+ 0x13b0: 0x2000, 0x13b1: 0x2000, 0x13b2: 0x2000, 0x13b3: 0x2000, 0x13b4: 0x2000, 0x13b5: 0x2000,
+ 0x13b6: 0x2000, 0x13b7: 0x2000, 0x13b8: 0x2000, 0x13b9: 0x2000, 0x13ba: 0x2000, 0x13bb: 0x2000,
+ 0x13bc: 0x2000, 0x13bd: 0x2000, 0x13be: 0x2000, 0x13bf: 0x2000,
+ // Block 0x4f, offset 0x13c0
+ 0x13c0: 0x2000, 0x13c1: 0x2000, 0x13c2: 0x2000, 0x13c3: 0x2000, 0x13c4: 0x2000, 0x13c5: 0x2000,
+ 0x13c6: 0x2000, 0x13c7: 0x2000, 0x13c8: 0x2000, 0x13c9: 0x2000, 0x13ca: 0x2000, 0x13cb: 0x2000,
+ 0x13cc: 0x2000, 0x13cd: 0x2000, 0x13ce: 0x4000, 0x13cf: 0x2000, 0x13d0: 0x2000, 0x13d1: 0x4000,
+ 0x13d2: 0x4000, 0x13d3: 0x4000, 0x13d4: 0x4000, 0x13d5: 0x4000, 0x13d6: 0x4000, 0x13d7: 0x4000,
+ 0x13d8: 0x4000, 0x13d9: 0x4000, 0x13da: 0x4000, 0x13db: 0x2000, 0x13dc: 0x2000, 0x13dd: 0x2000,
+ 0x13de: 0x2000, 0x13df: 0x2000, 0x13e0: 0x2000, 0x13e1: 0x2000, 0x13e2: 0x2000, 0x13e3: 0x2000,
+ 0x13e4: 0x2000, 0x13e5: 0x2000, 0x13e6: 0x2000, 0x13e7: 0x2000, 0x13e8: 0x2000, 0x13e9: 0x2000,
+ 0x13ea: 0x2000, 0x13eb: 0x2000, 0x13ec: 0x2000,
+ // Block 0x50, offset 0x1400
+ 0x1400: 0x4000, 0x1401: 0x4000, 0x1402: 0x4000,
+ 0x1410: 0x4000, 0x1411: 0x4000,
+ 0x1412: 0x4000, 0x1413: 0x4000, 0x1414: 0x4000, 0x1415: 0x4000, 0x1416: 0x4000, 0x1417: 0x4000,
+ 0x1418: 0x4000, 0x1419: 0x4000, 0x141a: 0x4000, 0x141b: 0x4000, 0x141c: 0x4000, 0x141d: 0x4000,
+ 0x141e: 0x4000, 0x141f: 0x4000, 0x1420: 0x4000, 0x1421: 0x4000, 0x1422: 0x4000, 0x1423: 0x4000,
+ 0x1424: 0x4000, 0x1425: 0x4000, 0x1426: 0x4000, 0x1427: 0x4000, 0x1428: 0x4000, 0x1429: 0x4000,
+ 0x142a: 0x4000, 0x142b: 0x4000, 0x142c: 0x4000, 0x142d: 0x4000, 0x142e: 0x4000, 0x142f: 0x4000,
+ 0x1430: 0x4000, 0x1431: 0x4000, 0x1432: 0x4000, 0x1433: 0x4000, 0x1434: 0x4000, 0x1435: 0x4000,
+ 0x1436: 0x4000, 0x1437: 0x4000, 0x1438: 0x4000, 0x1439: 0x4000, 0x143a: 0x4000, 0x143b: 0x4000,
+ // Block 0x51, offset 0x1440
+ 0x1440: 0x4000, 0x1441: 0x4000, 0x1442: 0x4000, 0x1443: 0x4000, 0x1444: 0x4000, 0x1445: 0x4000,
+ 0x1446: 0x4000, 0x1447: 0x4000, 0x1448: 0x4000,
+ 0x1450: 0x4000, 0x1451: 0x4000,
+ // Block 0x52, offset 0x1480
+ 0x1480: 0x4000, 0x1481: 0x4000, 0x1482: 0x4000, 0x1483: 0x4000, 0x1484: 0x4000, 0x1485: 0x4000,
+ 0x1486: 0x4000, 0x1487: 0x4000, 0x1488: 0x4000, 0x1489: 0x4000, 0x148a: 0x4000, 0x148b: 0x4000,
+ 0x148c: 0x4000, 0x148d: 0x4000, 0x148e: 0x4000, 0x148f: 0x4000, 0x1490: 0x4000, 0x1491: 0x4000,
+ 0x1492: 0x4000, 0x1493: 0x4000, 0x1494: 0x4000, 0x1495: 0x4000, 0x1496: 0x4000, 0x1497: 0x4000,
+ 0x1498: 0x4000, 0x1499: 0x4000, 0x149a: 0x4000, 0x149b: 0x4000, 0x149c: 0x4000, 0x149d: 0x4000,
+ 0x149e: 0x4000, 0x149f: 0x4000, 0x14a0: 0x4000,
+ 0x14ad: 0x4000, 0x14ae: 0x4000, 0x14af: 0x4000,
+ 0x14b0: 0x4000, 0x14b1: 0x4000, 0x14b2: 0x4000, 0x14b3: 0x4000, 0x14b4: 0x4000, 0x14b5: 0x4000,
+ 0x14b7: 0x4000, 0x14b8: 0x4000, 0x14b9: 0x4000, 0x14ba: 0x4000, 0x14bb: 0x4000,
+ 0x14bc: 0x4000, 0x14bd: 0x4000, 0x14be: 0x4000, 0x14bf: 0x4000,
+ // Block 0x53, offset 0x14c0
+ 0x14c0: 0x4000, 0x14c1: 0x4000, 0x14c2: 0x4000, 0x14c3: 0x4000, 0x14c4: 0x4000, 0x14c5: 0x4000,
+ 0x14c6: 0x4000, 0x14c7: 0x4000, 0x14c8: 0x4000, 0x14c9: 0x4000, 0x14ca: 0x4000, 0x14cb: 0x4000,
+ 0x14cc: 0x4000, 0x14cd: 0x4000, 0x14ce: 0x4000, 0x14cf: 0x4000, 0x14d0: 0x4000, 0x14d1: 0x4000,
+ 0x14d2: 0x4000, 0x14d3: 0x4000, 0x14d4: 0x4000, 0x14d5: 0x4000, 0x14d6: 0x4000, 0x14d7: 0x4000,
+ 0x14d8: 0x4000, 0x14d9: 0x4000, 0x14da: 0x4000, 0x14db: 0x4000, 0x14dc: 0x4000, 0x14dd: 0x4000,
+ 0x14de: 0x4000, 0x14df: 0x4000, 0x14e0: 0x4000, 0x14e1: 0x4000, 0x14e2: 0x4000, 0x14e3: 0x4000,
+ 0x14e4: 0x4000, 0x14e5: 0x4000, 0x14e6: 0x4000, 0x14e7: 0x4000, 0x14e8: 0x4000, 0x14e9: 0x4000,
+ 0x14ea: 0x4000, 0x14eb: 0x4000, 0x14ec: 0x4000, 0x14ed: 0x4000, 0x14ee: 0x4000, 0x14ef: 0x4000,
+ 0x14f0: 0x4000, 0x14f1: 0x4000, 0x14f2: 0x4000, 0x14f3: 0x4000, 0x14f4: 0x4000, 0x14f5: 0x4000,
+ 0x14f6: 0x4000, 0x14f7: 0x4000, 0x14f8: 0x4000, 0x14f9: 0x4000, 0x14fa: 0x4000, 0x14fb: 0x4000,
+ 0x14fc: 0x4000, 0x14fe: 0x4000, 0x14ff: 0x4000,
+ // Block 0x54, offset 0x1500
+ 0x1500: 0x4000, 0x1501: 0x4000, 0x1502: 0x4000, 0x1503: 0x4000, 0x1504: 0x4000, 0x1505: 0x4000,
+ 0x1506: 0x4000, 0x1507: 0x4000, 0x1508: 0x4000, 0x1509: 0x4000, 0x150a: 0x4000, 0x150b: 0x4000,
+ 0x150c: 0x4000, 0x150d: 0x4000, 0x150e: 0x4000, 0x150f: 0x4000, 0x1510: 0x4000, 0x1511: 0x4000,
+ 0x1512: 0x4000, 0x1513: 0x4000,
+ 0x1520: 0x4000, 0x1521: 0x4000, 0x1522: 0x4000, 0x1523: 0x4000,
+ 0x1524: 0x4000, 0x1525: 0x4000, 0x1526: 0x4000, 0x1527: 0x4000, 0x1528: 0x4000, 0x1529: 0x4000,
+ 0x152a: 0x4000, 0x152b: 0x4000, 0x152c: 0x4000, 0x152d: 0x4000, 0x152e: 0x4000, 0x152f: 0x4000,
+ 0x1530: 0x4000, 0x1531: 0x4000, 0x1532: 0x4000, 0x1533: 0x4000, 0x1534: 0x4000, 0x1535: 0x4000,
+ 0x1536: 0x4000, 0x1537: 0x4000, 0x1538: 0x4000, 0x1539: 0x4000, 0x153a: 0x4000, 0x153b: 0x4000,
+ 0x153c: 0x4000, 0x153d: 0x4000, 0x153e: 0x4000, 0x153f: 0x4000,
+ // Block 0x55, offset 0x1540
+ 0x1540: 0x4000, 0x1541: 0x4000, 0x1542: 0x4000, 0x1543: 0x4000, 0x1544: 0x4000, 0x1545: 0x4000,
+ 0x1546: 0x4000, 0x1547: 0x4000, 0x1548: 0x4000, 0x1549: 0x4000, 0x154a: 0x4000,
+ 0x154f: 0x4000, 0x1550: 0x4000, 0x1551: 0x4000,
+ 0x1552: 0x4000, 0x1553: 0x4000,
+ 0x1560: 0x4000, 0x1561: 0x4000, 0x1562: 0x4000, 0x1563: 0x4000,
+ 0x1564: 0x4000, 0x1565: 0x4000, 0x1566: 0x4000, 0x1567: 0x4000, 0x1568: 0x4000, 0x1569: 0x4000,
+ 0x156a: 0x4000, 0x156b: 0x4000, 0x156c: 0x4000, 0x156d: 0x4000, 0x156e: 0x4000, 0x156f: 0x4000,
+ 0x1570: 0x4000, 0x1574: 0x4000,
+ 0x1578: 0x4000, 0x1579: 0x4000, 0x157a: 0x4000, 0x157b: 0x4000,
+ 0x157c: 0x4000, 0x157d: 0x4000, 0x157e: 0x4000, 0x157f: 0x4000,
+ // Block 0x56, offset 0x1580
+ 0x1580: 0x4000, 0x1582: 0x4000, 0x1583: 0x4000, 0x1584: 0x4000, 0x1585: 0x4000,
+ 0x1586: 0x4000, 0x1587: 0x4000, 0x1588: 0x4000, 0x1589: 0x4000, 0x158a: 0x4000, 0x158b: 0x4000,
+ 0x158c: 0x4000, 0x158d: 0x4000, 0x158e: 0x4000, 0x158f: 0x4000, 0x1590: 0x4000, 0x1591: 0x4000,
+ 0x1592: 0x4000, 0x1593: 0x4000, 0x1594: 0x4000, 0x1595: 0x4000, 0x1596: 0x4000, 0x1597: 0x4000,
+ 0x1598: 0x4000, 0x1599: 0x4000, 0x159a: 0x4000, 0x159b: 0x4000, 0x159c: 0x4000, 0x159d: 0x4000,
+ 0x159e: 0x4000, 0x159f: 0x4000, 0x15a0: 0x4000, 0x15a1: 0x4000, 0x15a2: 0x4000, 0x15a3: 0x4000,
+ 0x15a4: 0x4000, 0x15a5: 0x4000, 0x15a6: 0x4000, 0x15a7: 0x4000, 0x15a8: 0x4000, 0x15a9: 0x4000,
+ 0x15aa: 0x4000, 0x15ab: 0x4000, 0x15ac: 0x4000, 0x15ad: 0x4000, 0x15ae: 0x4000, 0x15af: 0x4000,
+ 0x15b0: 0x4000, 0x15b1: 0x4000, 0x15b2: 0x4000, 0x15b3: 0x4000, 0x15b4: 0x4000, 0x15b5: 0x4000,
+ 0x15b6: 0x4000, 0x15b7: 0x4000, 0x15b8: 0x4000, 0x15b9: 0x4000, 0x15ba: 0x4000, 0x15bb: 0x4000,
+ 0x15bc: 0x4000, 0x15bd: 0x4000, 0x15be: 0x4000, 0x15bf: 0x4000,
+ // Block 0x57, offset 0x15c0
+ 0x15c0: 0x4000, 0x15c1: 0x4000, 0x15c2: 0x4000, 0x15c3: 0x4000, 0x15c4: 0x4000, 0x15c5: 0x4000,
+ 0x15c6: 0x4000, 0x15c7: 0x4000, 0x15c8: 0x4000, 0x15c9: 0x4000, 0x15ca: 0x4000, 0x15cb: 0x4000,
+ 0x15cc: 0x4000, 0x15cd: 0x4000, 0x15ce: 0x4000, 0x15cf: 0x4000, 0x15d0: 0x4000, 0x15d1: 0x4000,
+ 0x15d2: 0x4000, 0x15d3: 0x4000, 0x15d4: 0x4000, 0x15d5: 0x4000, 0x15d6: 0x4000, 0x15d7: 0x4000,
+ 0x15d8: 0x4000, 0x15d9: 0x4000, 0x15da: 0x4000, 0x15db: 0x4000, 0x15dc: 0x4000, 0x15dd: 0x4000,
+ 0x15de: 0x4000, 0x15df: 0x4000, 0x15e0: 0x4000, 0x15e1: 0x4000, 0x15e2: 0x4000, 0x15e3: 0x4000,
+ 0x15e4: 0x4000, 0x15e5: 0x4000, 0x15e6: 0x4000, 0x15e7: 0x4000, 0x15e8: 0x4000, 0x15e9: 0x4000,
+ 0x15ea: 0x4000, 0x15eb: 0x4000, 0x15ec: 0x4000, 0x15ed: 0x4000, 0x15ee: 0x4000, 0x15ef: 0x4000,
+ 0x15f0: 0x4000, 0x15f1: 0x4000, 0x15f2: 0x4000, 0x15f3: 0x4000, 0x15f4: 0x4000, 0x15f5: 0x4000,
+ 0x15f6: 0x4000, 0x15f7: 0x4000, 0x15f8: 0x4000, 0x15f9: 0x4000, 0x15fa: 0x4000, 0x15fb: 0x4000,
+ 0x15fc: 0x4000, 0x15ff: 0x4000,
+ // Block 0x58, offset 0x1600
+ 0x1600: 0x4000, 0x1601: 0x4000, 0x1602: 0x4000, 0x1603: 0x4000, 0x1604: 0x4000, 0x1605: 0x4000,
+ 0x1606: 0x4000, 0x1607: 0x4000, 0x1608: 0x4000, 0x1609: 0x4000, 0x160a: 0x4000, 0x160b: 0x4000,
+ 0x160c: 0x4000, 0x160d: 0x4000, 0x160e: 0x4000, 0x160f: 0x4000, 0x1610: 0x4000, 0x1611: 0x4000,
+ 0x1612: 0x4000, 0x1613: 0x4000, 0x1614: 0x4000, 0x1615: 0x4000, 0x1616: 0x4000, 0x1617: 0x4000,
+ 0x1618: 0x4000, 0x1619: 0x4000, 0x161a: 0x4000, 0x161b: 0x4000, 0x161c: 0x4000, 0x161d: 0x4000,
+ 0x161e: 0x4000, 0x161f: 0x4000, 0x1620: 0x4000, 0x1621: 0x4000, 0x1622: 0x4000, 0x1623: 0x4000,
+ 0x1624: 0x4000, 0x1625: 0x4000, 0x1626: 0x4000, 0x1627: 0x4000, 0x1628: 0x4000, 0x1629: 0x4000,
+ 0x162a: 0x4000, 0x162b: 0x4000, 0x162c: 0x4000, 0x162d: 0x4000, 0x162e: 0x4000, 0x162f: 0x4000,
+ 0x1630: 0x4000, 0x1631: 0x4000, 0x1632: 0x4000, 0x1633: 0x4000, 0x1634: 0x4000, 0x1635: 0x4000,
+ 0x1636: 0x4000, 0x1637: 0x4000, 0x1638: 0x4000, 0x1639: 0x4000, 0x163a: 0x4000, 0x163b: 0x4000,
+ 0x163c: 0x4000, 0x163d: 0x4000,
+ // Block 0x59, offset 0x1640
+ 0x164b: 0x4000,
+ 0x164c: 0x4000, 0x164d: 0x4000, 0x164e: 0x4000, 0x1650: 0x4000, 0x1651: 0x4000,
+ 0x1652: 0x4000, 0x1653: 0x4000, 0x1654: 0x4000, 0x1655: 0x4000, 0x1656: 0x4000, 0x1657: 0x4000,
+ 0x1658: 0x4000, 0x1659: 0x4000, 0x165a: 0x4000, 0x165b: 0x4000, 0x165c: 0x4000, 0x165d: 0x4000,
+ 0x165e: 0x4000, 0x165f: 0x4000, 0x1660: 0x4000, 0x1661: 0x4000, 0x1662: 0x4000, 0x1663: 0x4000,
+ 0x1664: 0x4000, 0x1665: 0x4000, 0x1666: 0x4000, 0x1667: 0x4000,
+ 0x167a: 0x4000,
+ // Block 0x5a, offset 0x1680
+ 0x1695: 0x4000, 0x1696: 0x4000,
+ 0x16a4: 0x4000,
+ // Block 0x5b, offset 0x16c0
+ 0x16fb: 0x4000,
+ 0x16fc: 0x4000, 0x16fd: 0x4000, 0x16fe: 0x4000, 0x16ff: 0x4000,
+ // Block 0x5c, offset 0x1700
+ 0x1700: 0x4000, 0x1701: 0x4000, 0x1702: 0x4000, 0x1703: 0x4000, 0x1704: 0x4000, 0x1705: 0x4000,
+ 0x1706: 0x4000, 0x1707: 0x4000, 0x1708: 0x4000, 0x1709: 0x4000, 0x170a: 0x4000, 0x170b: 0x4000,
+ 0x170c: 0x4000, 0x170d: 0x4000, 0x170e: 0x4000, 0x170f: 0x4000,
+ // Block 0x5d, offset 0x1740
+ 0x1740: 0x4000, 0x1741: 0x4000, 0x1742: 0x4000, 0x1743: 0x4000, 0x1744: 0x4000, 0x1745: 0x4000,
+ 0x174c: 0x4000, 0x1750: 0x4000, 0x1751: 0x4000,
+ 0x1752: 0x4000,
+ 0x176b: 0x4000, 0x176c: 0x4000,
+ 0x1774: 0x4000, 0x1775: 0x4000,
+ 0x1776: 0x4000,
+ // Block 0x5e, offset 0x1780
+ 0x1790: 0x4000, 0x1791: 0x4000,
+ 0x1792: 0x4000, 0x1793: 0x4000, 0x1794: 0x4000, 0x1795: 0x4000, 0x1796: 0x4000, 0x1797: 0x4000,
+ 0x1798: 0x4000, 0x1799: 0x4000, 0x179a: 0x4000, 0x179b: 0x4000, 0x179c: 0x4000, 0x179d: 0x4000,
+ 0x179e: 0x4000, 0x17a0: 0x4000, 0x17a1: 0x4000, 0x17a2: 0x4000, 0x17a3: 0x4000,
+ 0x17a4: 0x4000, 0x17a5: 0x4000, 0x17a6: 0x4000, 0x17a7: 0x4000,
+ 0x17b0: 0x4000, 0x17b3: 0x4000, 0x17b4: 0x4000, 0x17b5: 0x4000,
+ 0x17b6: 0x4000, 0x17b7: 0x4000, 0x17b8: 0x4000, 0x17b9: 0x4000, 0x17ba: 0x4000, 0x17bb: 0x4000,
+ 0x17bc: 0x4000, 0x17bd: 0x4000, 0x17be: 0x4000,
+ // Block 0x5f, offset 0x17c0
+ 0x17c0: 0x4000, 0x17c1: 0x4000, 0x17c2: 0x4000, 0x17c3: 0x4000, 0x17c4: 0x4000, 0x17c5: 0x4000,
+ 0x17c6: 0x4000, 0x17c7: 0x4000, 0x17c8: 0x4000, 0x17c9: 0x4000, 0x17ca: 0x4000, 0x17cb: 0x4000,
+ 0x17d0: 0x4000, 0x17d1: 0x4000,
+ 0x17d2: 0x4000, 0x17d3: 0x4000, 0x17d4: 0x4000, 0x17d5: 0x4000, 0x17d6: 0x4000, 0x17d7: 0x4000,
+ 0x17d8: 0x4000, 0x17d9: 0x4000, 0x17da: 0x4000, 0x17db: 0x4000, 0x17dc: 0x4000, 0x17dd: 0x4000,
+ 0x17de: 0x4000,
+ // Block 0x60, offset 0x1800
+ 0x1800: 0x4000, 0x1801: 0x4000, 0x1802: 0x4000, 0x1803: 0x4000, 0x1804: 0x4000, 0x1805: 0x4000,
+ 0x1806: 0x4000, 0x1807: 0x4000, 0x1808: 0x4000, 0x1809: 0x4000, 0x180a: 0x4000, 0x180b: 0x4000,
+ 0x180c: 0x4000, 0x180d: 0x4000, 0x180e: 0x4000, 0x180f: 0x4000, 0x1810: 0x4000, 0x1811: 0x4000,
+ // Block 0x61, offset 0x1840
+ 0x1840: 0x4000,
+ // Block 0x62, offset 0x1880
+ 0x1880: 0x2000, 0x1881: 0x2000, 0x1882: 0x2000, 0x1883: 0x2000, 0x1884: 0x2000, 0x1885: 0x2000,
+ 0x1886: 0x2000, 0x1887: 0x2000, 0x1888: 0x2000, 0x1889: 0x2000, 0x188a: 0x2000, 0x188b: 0x2000,
+ 0x188c: 0x2000, 0x188d: 0x2000, 0x188e: 0x2000, 0x188f: 0x2000, 0x1890: 0x2000, 0x1891: 0x2000,
+ 0x1892: 0x2000, 0x1893: 0x2000, 0x1894: 0x2000, 0x1895: 0x2000, 0x1896: 0x2000, 0x1897: 0x2000,
+ 0x1898: 0x2000, 0x1899: 0x2000, 0x189a: 0x2000, 0x189b: 0x2000, 0x189c: 0x2000, 0x189d: 0x2000,
+ 0x189e: 0x2000, 0x189f: 0x2000, 0x18a0: 0x2000, 0x18a1: 0x2000, 0x18a2: 0x2000, 0x18a3: 0x2000,
+ 0x18a4: 0x2000, 0x18a5: 0x2000, 0x18a6: 0x2000, 0x18a7: 0x2000, 0x18a8: 0x2000, 0x18a9: 0x2000,
+ 0x18aa: 0x2000, 0x18ab: 0x2000, 0x18ac: 0x2000, 0x18ad: 0x2000, 0x18ae: 0x2000, 0x18af: 0x2000,
+ 0x18b0: 0x2000, 0x18b1: 0x2000, 0x18b2: 0x2000, 0x18b3: 0x2000, 0x18b4: 0x2000, 0x18b5: 0x2000,
+ 0x18b6: 0x2000, 0x18b7: 0x2000, 0x18b8: 0x2000, 0x18b9: 0x2000, 0x18ba: 0x2000, 0x18bb: 0x2000,
+ 0x18bc: 0x2000, 0x18bd: 0x2000,
+}
+
+// widthIndex: 22 blocks, 1408 entries, 1408 bytes
+// Block 0 is the zero block.
+var widthIndex = [1408]uint8{
+ // Block 0x0, offset 0x0
+ // Block 0x1, offset 0x40
+ // Block 0x2, offset 0x80
+ // Block 0x3, offset 0xc0
+ 0xc2: 0x01, 0xc3: 0x02, 0xc4: 0x03, 0xc5: 0x04, 0xc7: 0x05,
+ 0xc9: 0x06, 0xcb: 0x07, 0xcc: 0x08, 0xcd: 0x09, 0xce: 0x0a, 0xcf: 0x0b,
+ 0xd0: 0x0c, 0xd1: 0x0d,
+ 0xe1: 0x02, 0xe2: 0x03, 0xe3: 0x04, 0xe4: 0x05, 0xe5: 0x06, 0xe6: 0x06, 0xe7: 0x06,
+ 0xe8: 0x06, 0xe9: 0x06, 0xea: 0x07, 0xeb: 0x06, 0xec: 0x06, 0xed: 0x08, 0xee: 0x09, 0xef: 0x0a,
+ 0xf0: 0x0f, 0xf3: 0x12, 0xf4: 0x13,
+ // Block 0x4, offset 0x100
+ 0x104: 0x0e, 0x105: 0x0f,
+ // Block 0x5, offset 0x140
+ 0x140: 0x10, 0x141: 0x11, 0x142: 0x12, 0x144: 0x13, 0x145: 0x14, 0x146: 0x15, 0x147: 0x16,
+ 0x148: 0x17, 0x149: 0x18, 0x14a: 0x19, 0x14c: 0x1a, 0x14f: 0x1b,
+ 0x151: 0x1c, 0x152: 0x08, 0x153: 0x1d, 0x154: 0x1e, 0x155: 0x1f, 0x156: 0x20, 0x157: 0x21,
+ 0x158: 0x22, 0x159: 0x23, 0x15a: 0x24, 0x15b: 0x25, 0x15c: 0x26, 0x15d: 0x27, 0x15e: 0x28, 0x15f: 0x29,
+ 0x166: 0x2a,
+ 0x16c: 0x2b, 0x16d: 0x2c,
+ 0x17a: 0x2d, 0x17b: 0x2e, 0x17c: 0x0e, 0x17d: 0x0e, 0x17e: 0x0e, 0x17f: 0x2f,
+ // Block 0x6, offset 0x180
+ 0x180: 0x30, 0x181: 0x31, 0x182: 0x32, 0x183: 0x33, 0x184: 0x34, 0x185: 0x35, 0x186: 0x36, 0x187: 0x37,
+ 0x188: 0x38, 0x189: 0x39, 0x18a: 0x0e, 0x18b: 0x3a, 0x18c: 0x0e, 0x18d: 0x0e, 0x18e: 0x0e, 0x18f: 0x0e,
+ 0x190: 0x0e, 0x191: 0x0e, 0x192: 0x0e, 0x193: 0x0e, 0x194: 0x0e, 0x195: 0x0e, 0x196: 0x0e, 0x197: 0x0e,
+ 0x198: 0x0e, 0x199: 0x0e, 0x19a: 0x0e, 0x19b: 0x0e, 0x19c: 0x0e, 0x19d: 0x0e, 0x19e: 0x0e, 0x19f: 0x0e,
+ 0x1a0: 0x0e, 0x1a1: 0x0e, 0x1a2: 0x0e, 0x1a3: 0x0e, 0x1a4: 0x0e, 0x1a5: 0x0e, 0x1a6: 0x0e, 0x1a7: 0x0e,
+ 0x1a8: 0x0e, 0x1a9: 0x0e, 0x1aa: 0x0e, 0x1ab: 0x0e, 0x1ac: 0x0e, 0x1ad: 0x0e, 0x1ae: 0x0e, 0x1af: 0x0e,
+ 0x1b0: 0x0e, 0x1b1: 0x0e, 0x1b2: 0x0e, 0x1b3: 0x0e, 0x1b4: 0x0e, 0x1b5: 0x0e, 0x1b6: 0x0e, 0x1b7: 0x0e,
+ 0x1b8: 0x0e, 0x1b9: 0x0e, 0x1ba: 0x0e, 0x1bb: 0x0e, 0x1bc: 0x0e, 0x1bd: 0x0e, 0x1be: 0x0e, 0x1bf: 0x0e,
+ // Block 0x7, offset 0x1c0
+ 0x1c0: 0x0e, 0x1c1: 0x0e, 0x1c2: 0x0e, 0x1c3: 0x0e, 0x1c4: 0x0e, 0x1c5: 0x0e, 0x1c6: 0x0e, 0x1c7: 0x0e,
+ 0x1c8: 0x0e, 0x1c9: 0x0e, 0x1ca: 0x0e, 0x1cb: 0x0e, 0x1cc: 0x0e, 0x1cd: 0x0e, 0x1ce: 0x0e, 0x1cf: 0x0e,
+ 0x1d0: 0x0e, 0x1d1: 0x0e, 0x1d2: 0x0e, 0x1d3: 0x0e, 0x1d4: 0x0e, 0x1d5: 0x0e, 0x1d6: 0x0e, 0x1d7: 0x0e,
+ 0x1d8: 0x0e, 0x1d9: 0x0e, 0x1da: 0x0e, 0x1db: 0x0e, 0x1dc: 0x0e, 0x1dd: 0x0e, 0x1de: 0x0e, 0x1df: 0x0e,
+ 0x1e0: 0x0e, 0x1e1: 0x0e, 0x1e2: 0x0e, 0x1e3: 0x0e, 0x1e4: 0x0e, 0x1e5: 0x0e, 0x1e6: 0x0e, 0x1e7: 0x0e,
+ 0x1e8: 0x0e, 0x1e9: 0x0e, 0x1ea: 0x0e, 0x1eb: 0x0e, 0x1ec: 0x0e, 0x1ed: 0x0e, 0x1ee: 0x0e, 0x1ef: 0x0e,
+ 0x1f0: 0x0e, 0x1f1: 0x0e, 0x1f2: 0x0e, 0x1f3: 0x0e, 0x1f4: 0x0e, 0x1f5: 0x0e, 0x1f6: 0x0e,
+ 0x1f8: 0x0e, 0x1f9: 0x0e, 0x1fa: 0x0e, 0x1fb: 0x0e, 0x1fc: 0x0e, 0x1fd: 0x0e, 0x1fe: 0x0e, 0x1ff: 0x0e,
+ // Block 0x8, offset 0x200
+ 0x200: 0x0e, 0x201: 0x0e, 0x202: 0x0e, 0x203: 0x0e, 0x204: 0x0e, 0x205: 0x0e, 0x206: 0x0e, 0x207: 0x0e,
+ 0x208: 0x0e, 0x209: 0x0e, 0x20a: 0x0e, 0x20b: 0x0e, 0x20c: 0x0e, 0x20d: 0x0e, 0x20e: 0x0e, 0x20f: 0x0e,
+ 0x210: 0x0e, 0x211: 0x0e, 0x212: 0x0e, 0x213: 0x0e, 0x214: 0x0e, 0x215: 0x0e, 0x216: 0x0e, 0x217: 0x0e,
+ 0x218: 0x0e, 0x219: 0x0e, 0x21a: 0x0e, 0x21b: 0x0e, 0x21c: 0x0e, 0x21d: 0x0e, 0x21e: 0x0e, 0x21f: 0x0e,
+ 0x220: 0x0e, 0x221: 0x0e, 0x222: 0x0e, 0x223: 0x0e, 0x224: 0x0e, 0x225: 0x0e, 0x226: 0x0e, 0x227: 0x0e,
+ 0x228: 0x0e, 0x229: 0x0e, 0x22a: 0x0e, 0x22b: 0x0e, 0x22c: 0x0e, 0x22d: 0x0e, 0x22e: 0x0e, 0x22f: 0x0e,
+ 0x230: 0x0e, 0x231: 0x0e, 0x232: 0x0e, 0x233: 0x0e, 0x234: 0x0e, 0x235: 0x0e, 0x236: 0x0e, 0x237: 0x0e,
+ 0x238: 0x0e, 0x239: 0x0e, 0x23a: 0x0e, 0x23b: 0x0e, 0x23c: 0x0e, 0x23d: 0x0e, 0x23e: 0x0e, 0x23f: 0x0e,
+ // Block 0x9, offset 0x240
+ 0x240: 0x0e, 0x241: 0x0e, 0x242: 0x0e, 0x243: 0x0e, 0x244: 0x0e, 0x245: 0x0e, 0x246: 0x0e, 0x247: 0x0e,
+ 0x248: 0x0e, 0x249: 0x0e, 0x24a: 0x0e, 0x24b: 0x0e, 0x24c: 0x0e, 0x24d: 0x0e, 0x24e: 0x0e, 0x24f: 0x0e,
+ 0x250: 0x0e, 0x251: 0x0e, 0x252: 0x3b, 0x253: 0x3c,
+ 0x265: 0x3d,
+ 0x270: 0x0e, 0x271: 0x0e, 0x272: 0x0e, 0x273: 0x0e, 0x274: 0x0e, 0x275: 0x0e, 0x276: 0x0e, 0x277: 0x0e,
+ 0x278: 0x0e, 0x279: 0x0e, 0x27a: 0x0e, 0x27b: 0x0e, 0x27c: 0x0e, 0x27d: 0x0e, 0x27e: 0x0e, 0x27f: 0x0e,
+ // Block 0xa, offset 0x280
+ 0x280: 0x0e, 0x281: 0x0e, 0x282: 0x0e, 0x283: 0x0e, 0x284: 0x0e, 0x285: 0x0e, 0x286: 0x0e, 0x287: 0x0e,
+ 0x288: 0x0e, 0x289: 0x0e, 0x28a: 0x0e, 0x28b: 0x0e, 0x28c: 0x0e, 0x28d: 0x0e, 0x28e: 0x0e, 0x28f: 0x0e,
+ 0x290: 0x0e, 0x291: 0x0e, 0x292: 0x0e, 0x293: 0x0e, 0x294: 0x0e, 0x295: 0x0e, 0x296: 0x0e, 0x297: 0x0e,
+ 0x298: 0x0e, 0x299: 0x0e, 0x29a: 0x0e, 0x29b: 0x0e, 0x29c: 0x0e, 0x29d: 0x0e, 0x29e: 0x3e,
+ // Block 0xb, offset 0x2c0
+ 0x2c0: 0x08, 0x2c1: 0x08, 0x2c2: 0x08, 0x2c3: 0x08, 0x2c4: 0x08, 0x2c5: 0x08, 0x2c6: 0x08, 0x2c7: 0x08,
+ 0x2c8: 0x08, 0x2c9: 0x08, 0x2ca: 0x08, 0x2cb: 0x08, 0x2cc: 0x08, 0x2cd: 0x08, 0x2ce: 0x08, 0x2cf: 0x08,
+ 0x2d0: 0x08, 0x2d1: 0x08, 0x2d2: 0x08, 0x2d3: 0x08, 0x2d4: 0x08, 0x2d5: 0x08, 0x2d6: 0x08, 0x2d7: 0x08,
+ 0x2d8: 0x08, 0x2d9: 0x08, 0x2da: 0x08, 0x2db: 0x08, 0x2dc: 0x08, 0x2dd: 0x08, 0x2de: 0x08, 0x2df: 0x08,
+ 0x2e0: 0x08, 0x2e1: 0x08, 0x2e2: 0x08, 0x2e3: 0x08, 0x2e4: 0x08, 0x2e5: 0x08, 0x2e6: 0x08, 0x2e7: 0x08,
+ 0x2e8: 0x08, 0x2e9: 0x08, 0x2ea: 0x08, 0x2eb: 0x08, 0x2ec: 0x08, 0x2ed: 0x08, 0x2ee: 0x08, 0x2ef: 0x08,
+ 0x2f0: 0x08, 0x2f1: 0x08, 0x2f2: 0x08, 0x2f3: 0x08, 0x2f4: 0x08, 0x2f5: 0x08, 0x2f6: 0x08, 0x2f7: 0x08,
+ 0x2f8: 0x08, 0x2f9: 0x08, 0x2fa: 0x08, 0x2fb: 0x08, 0x2fc: 0x08, 0x2fd: 0x08, 0x2fe: 0x08, 0x2ff: 0x08,
+ // Block 0xc, offset 0x300
+ 0x300: 0x08, 0x301: 0x08, 0x302: 0x08, 0x303: 0x08, 0x304: 0x08, 0x305: 0x08, 0x306: 0x08, 0x307: 0x08,
+ 0x308: 0x08, 0x309: 0x08, 0x30a: 0x08, 0x30b: 0x08, 0x30c: 0x08, 0x30d: 0x08, 0x30e: 0x08, 0x30f: 0x08,
+ 0x310: 0x08, 0x311: 0x08, 0x312: 0x08, 0x313: 0x08, 0x314: 0x08, 0x315: 0x08, 0x316: 0x08, 0x317: 0x08,
+ 0x318: 0x08, 0x319: 0x08, 0x31a: 0x08, 0x31b: 0x08, 0x31c: 0x08, 0x31d: 0x08, 0x31e: 0x08, 0x31f: 0x08,
+ 0x320: 0x08, 0x321: 0x08, 0x322: 0x08, 0x323: 0x08, 0x324: 0x0e, 0x325: 0x0e, 0x326: 0x0e, 0x327: 0x0e,
+ 0x328: 0x0e, 0x329: 0x0e, 0x32a: 0x0e, 0x32b: 0x0e,
+ 0x338: 0x3f, 0x339: 0x40, 0x33c: 0x41, 0x33d: 0x42, 0x33e: 0x43, 0x33f: 0x44,
+ // Block 0xd, offset 0x340
+ 0x37f: 0x45,
+ // Block 0xe, offset 0x380
+ 0x380: 0x0e, 0x381: 0x0e, 0x382: 0x0e, 0x383: 0x0e, 0x384: 0x0e, 0x385: 0x0e, 0x386: 0x0e, 0x387: 0x0e,
+ 0x388: 0x0e, 0x389: 0x0e, 0x38a: 0x0e, 0x38b: 0x0e, 0x38c: 0x0e, 0x38d: 0x0e, 0x38e: 0x0e, 0x38f: 0x0e,
+ 0x390: 0x0e, 0x391: 0x0e, 0x392: 0x0e, 0x393: 0x0e, 0x394: 0x0e, 0x395: 0x0e, 0x396: 0x0e, 0x397: 0x0e,
+ 0x398: 0x0e, 0x399: 0x0e, 0x39a: 0x0e, 0x39b: 0x0e, 0x39c: 0x0e, 0x39d: 0x0e, 0x39e: 0x0e, 0x39f: 0x46,
+ 0x3a0: 0x0e, 0x3a1: 0x0e, 0x3a2: 0x0e, 0x3a3: 0x0e, 0x3a4: 0x0e, 0x3a5: 0x0e, 0x3a6: 0x0e, 0x3a7: 0x0e,
+ 0x3a8: 0x0e, 0x3a9: 0x0e, 0x3aa: 0x0e, 0x3ab: 0x47,
+ // Block 0xf, offset 0x3c0
+ 0x3c0: 0x48,
+ // Block 0x10, offset 0x400
+ 0x400: 0x49, 0x403: 0x4a, 0x404: 0x4b, 0x405: 0x4c, 0x406: 0x4d,
+ 0x408: 0x4e, 0x409: 0x4f, 0x40c: 0x50, 0x40d: 0x51, 0x40e: 0x52, 0x40f: 0x53,
+ 0x410: 0x3a, 0x411: 0x54, 0x412: 0x0e, 0x413: 0x55, 0x414: 0x56, 0x415: 0x57, 0x416: 0x58, 0x417: 0x59,
+ 0x418: 0x0e, 0x419: 0x5a, 0x41a: 0x0e, 0x41b: 0x5b,
+ 0x424: 0x5c, 0x425: 0x5d, 0x426: 0x5e, 0x427: 0x5f,
+ // Block 0x11, offset 0x440
+ 0x456: 0x0b, 0x457: 0x06,
+ 0x458: 0x0c, 0x45b: 0x0d, 0x45f: 0x0e,
+ 0x460: 0x06, 0x461: 0x06, 0x462: 0x06, 0x463: 0x06, 0x464: 0x06, 0x465: 0x06, 0x466: 0x06, 0x467: 0x06,
+ 0x468: 0x06, 0x469: 0x06, 0x46a: 0x06, 0x46b: 0x06, 0x46c: 0x06, 0x46d: 0x06, 0x46e: 0x06, 0x46f: 0x06,
+ 0x470: 0x06, 0x471: 0x06, 0x472: 0x06, 0x473: 0x06, 0x474: 0x06, 0x475: 0x06, 0x476: 0x06, 0x477: 0x06,
+ 0x478: 0x06, 0x479: 0x06, 0x47a: 0x06, 0x47b: 0x06, 0x47c: 0x06, 0x47d: 0x06, 0x47e: 0x06, 0x47f: 0x06,
+ // Block 0x12, offset 0x480
+ 0x484: 0x08, 0x485: 0x08, 0x486: 0x08, 0x487: 0x09,
+ // Block 0x13, offset 0x4c0
+ 0x4c0: 0x08, 0x4c1: 0x08, 0x4c2: 0x08, 0x4c3: 0x08, 0x4c4: 0x08, 0x4c5: 0x08, 0x4c6: 0x08, 0x4c7: 0x08,
+ 0x4c8: 0x08, 0x4c9: 0x08, 0x4ca: 0x08, 0x4cb: 0x08, 0x4cc: 0x08, 0x4cd: 0x08, 0x4ce: 0x08, 0x4cf: 0x08,
+ 0x4d0: 0x08, 0x4d1: 0x08, 0x4d2: 0x08, 0x4d3: 0x08, 0x4d4: 0x08, 0x4d5: 0x08, 0x4d6: 0x08, 0x4d7: 0x08,
+ 0x4d8: 0x08, 0x4d9: 0x08, 0x4da: 0x08, 0x4db: 0x08, 0x4dc: 0x08, 0x4dd: 0x08, 0x4de: 0x08, 0x4df: 0x08,
+ 0x4e0: 0x08, 0x4e1: 0x08, 0x4e2: 0x08, 0x4e3: 0x08, 0x4e4: 0x08, 0x4e5: 0x08, 0x4e6: 0x08, 0x4e7: 0x08,
+ 0x4e8: 0x08, 0x4e9: 0x08, 0x4ea: 0x08, 0x4eb: 0x08, 0x4ec: 0x08, 0x4ed: 0x08, 0x4ee: 0x08, 0x4ef: 0x08,
+ 0x4f0: 0x08, 0x4f1: 0x08, 0x4f2: 0x08, 0x4f3: 0x08, 0x4f4: 0x08, 0x4f5: 0x08, 0x4f6: 0x08, 0x4f7: 0x08,
+ 0x4f8: 0x08, 0x4f9: 0x08, 0x4fa: 0x08, 0x4fb: 0x08, 0x4fc: 0x08, 0x4fd: 0x08, 0x4fe: 0x08, 0x4ff: 0x60,
+ // Block 0x14, offset 0x500
+ 0x520: 0x10,
+ 0x530: 0x09, 0x531: 0x09, 0x532: 0x09, 0x533: 0x09, 0x534: 0x09, 0x535: 0x09, 0x536: 0x09, 0x537: 0x09,
+ 0x538: 0x09, 0x539: 0x09, 0x53a: 0x09, 0x53b: 0x09, 0x53c: 0x09, 0x53d: 0x09, 0x53e: 0x09, 0x53f: 0x11,
+ // Block 0x15, offset 0x540
+ 0x540: 0x09, 0x541: 0x09, 0x542: 0x09, 0x543: 0x09, 0x544: 0x09, 0x545: 0x09, 0x546: 0x09, 0x547: 0x09,
+ 0x548: 0x09, 0x549: 0x09, 0x54a: 0x09, 0x54b: 0x09, 0x54c: 0x09, 0x54d: 0x09, 0x54e: 0x09, 0x54f: 0x11,
+}
+
+// inverseData contains 4-byte entries of the following format:
+// <length> <modified UTF-8-encoded rune> <0 padding>
+// The last byte of the UTF-8-encoded rune is xor-ed with the last byte of the
+// UTF-8 encoding of the original rune. Mappings often have the following
+// pattern:
+// A -> A (U+FF21 -> U+0041)
+// B -> B (U+FF22 -> U+0042)
+// ...
+// By xor-ing the last byte the same entry can be shared by many mappings. This
+// reduces the total number of distinct entries by about two thirds.
+// The resulting entry for the aforementioned mappings is
+// { 0x01, 0xE0, 0x00, 0x00 }
+// Using this entry to map U+FF21 (UTF-8 [EF BC A1]), we get
+// E0 ^ A1 = 41.
+// Similarly, for U+FF22 (UTF-8 [EF BC A2]), we get
+// E0 ^ A2 = 42.
+// Note that because of the xor-ing, the byte sequence stored in the entry is
+// not valid UTF-8.
+var inverseData = [150][4]byte{
+ {0x00, 0x00, 0x00, 0x00},
+ {0x03, 0xe3, 0x80, 0xa0},
+ {0x03, 0xef, 0xbc, 0xa0},
+ {0x03, 0xef, 0xbc, 0xe0},
+ {0x03, 0xef, 0xbd, 0xe0},
+ {0x03, 0xef, 0xbf, 0x02},
+ {0x03, 0xef, 0xbf, 0x00},
+ {0x03, 0xef, 0xbf, 0x0e},
+ {0x03, 0xef, 0xbf, 0x0c},
+ {0x03, 0xef, 0xbf, 0x0f},
+ {0x03, 0xef, 0xbf, 0x39},
+ {0x03, 0xef, 0xbf, 0x3b},
+ {0x03, 0xef, 0xbf, 0x3f},
+ {0x03, 0xef, 0xbf, 0x2a},
+ {0x03, 0xef, 0xbf, 0x0d},
+ {0x03, 0xef, 0xbf, 0x25},
+ {0x03, 0xef, 0xbd, 0x1a},
+ {0x03, 0xef, 0xbd, 0x26},
+ {0x01, 0xa0, 0x00, 0x00},
+ {0x03, 0xef, 0xbd, 0x25},
+ {0x03, 0xef, 0xbd, 0x23},
+ {0x03, 0xef, 0xbd, 0x2e},
+ {0x03, 0xef, 0xbe, 0x07},
+ {0x03, 0xef, 0xbe, 0x05},
+ {0x03, 0xef, 0xbd, 0x06},
+ {0x03, 0xef, 0xbd, 0x13},
+ {0x03, 0xef, 0xbd, 0x0b},
+ {0x03, 0xef, 0xbd, 0x16},
+ {0x03, 0xef, 0xbd, 0x0c},
+ {0x03, 0xef, 0xbd, 0x15},
+ {0x03, 0xef, 0xbd, 0x0d},
+ {0x03, 0xef, 0xbd, 0x1c},
+ {0x03, 0xef, 0xbd, 0x02},
+ {0x03, 0xef, 0xbd, 0x1f},
+ {0x03, 0xef, 0xbd, 0x1d},
+ {0x03, 0xef, 0xbd, 0x17},
+ {0x03, 0xef, 0xbd, 0x08},
+ {0x03, 0xef, 0xbd, 0x09},
+ {0x03, 0xef, 0xbd, 0x0e},
+ {0x03, 0xef, 0xbd, 0x04},
+ {0x03, 0xef, 0xbd, 0x05},
+ {0x03, 0xef, 0xbe, 0x3f},
+ {0x03, 0xef, 0xbe, 0x00},
+ {0x03, 0xef, 0xbd, 0x2c},
+ {0x03, 0xef, 0xbe, 0x06},
+ {0x03, 0xef, 0xbe, 0x0c},
+ {0x03, 0xef, 0xbe, 0x0f},
+ {0x03, 0xef, 0xbe, 0x0d},
+ {0x03, 0xef, 0xbe, 0x0b},
+ {0x03, 0xef, 0xbe, 0x19},
+ {0x03, 0xef, 0xbe, 0x15},
+ {0x03, 0xef, 0xbe, 0x11},
+ {0x03, 0xef, 0xbe, 0x31},
+ {0x03, 0xef, 0xbe, 0x33},
+ {0x03, 0xef, 0xbd, 0x0f},
+ {0x03, 0xef, 0xbe, 0x30},
+ {0x03, 0xef, 0xbe, 0x3e},
+ {0x03, 0xef, 0xbe, 0x32},
+ {0x03, 0xef, 0xbe, 0x36},
+ {0x03, 0xef, 0xbd, 0x14},
+ {0x03, 0xef, 0xbe, 0x2e},
+ {0x03, 0xef, 0xbd, 0x1e},
+ {0x03, 0xef, 0xbe, 0x10},
+ {0x03, 0xef, 0xbf, 0x13},
+ {0x03, 0xef, 0xbf, 0x15},
+ {0x03, 0xef, 0xbf, 0x17},
+ {0x03, 0xef, 0xbf, 0x1f},
+ {0x03, 0xef, 0xbf, 0x1d},
+ {0x03, 0xef, 0xbf, 0x1b},
+ {0x03, 0xef, 0xbf, 0x09},
+ {0x03, 0xef, 0xbf, 0x0b},
+ {0x03, 0xef, 0xbf, 0x37},
+ {0x03, 0xef, 0xbe, 0x04},
+ {0x01, 0xe0, 0x00, 0x00},
+ {0x03, 0xe2, 0xa6, 0x1a},
+ {0x03, 0xe2, 0xa6, 0x26},
+ {0x03, 0xe3, 0x80, 0x23},
+ {0x03, 0xe3, 0x80, 0x2e},
+ {0x03, 0xe3, 0x80, 0x25},
+ {0x03, 0xe3, 0x83, 0x1e},
+ {0x03, 0xe3, 0x83, 0x14},
+ {0x03, 0xe3, 0x82, 0x06},
+ {0x03, 0xe3, 0x82, 0x0b},
+ {0x03, 0xe3, 0x82, 0x0c},
+ {0x03, 0xe3, 0x82, 0x0d},
+ {0x03, 0xe3, 0x82, 0x02},
+ {0x03, 0xe3, 0x83, 0x0f},
+ {0x03, 0xe3, 0x83, 0x08},
+ {0x03, 0xe3, 0x83, 0x09},
+ {0x03, 0xe3, 0x83, 0x2c},
+ {0x03, 0xe3, 0x83, 0x0c},
+ {0x03, 0xe3, 0x82, 0x13},
+ {0x03, 0xe3, 0x82, 0x16},
+ {0x03, 0xe3, 0x82, 0x15},
+ {0x03, 0xe3, 0x82, 0x1c},
+ {0x03, 0xe3, 0x82, 0x1f},
+ {0x03, 0xe3, 0x82, 0x1d},
+ {0x03, 0xe3, 0x82, 0x1a},
+ {0x03, 0xe3, 0x82, 0x17},
+ {0x03, 0xe3, 0x82, 0x08},
+ {0x03, 0xe3, 0x82, 0x09},
+ {0x03, 0xe3, 0x82, 0x0e},
+ {0x03, 0xe3, 0x82, 0x04},
+ {0x03, 0xe3, 0x82, 0x05},
+ {0x03, 0xe3, 0x82, 0x3f},
+ {0x03, 0xe3, 0x83, 0x00},
+ {0x03, 0xe3, 0x83, 0x06},
+ {0x03, 0xe3, 0x83, 0x05},
+ {0x03, 0xe3, 0x83, 0x0d},
+ {0x03, 0xe3, 0x83, 0x0b},
+ {0x03, 0xe3, 0x83, 0x07},
+ {0x03, 0xe3, 0x83, 0x19},
+ {0x03, 0xe3, 0x83, 0x15},
+ {0x03, 0xe3, 0x83, 0x11},
+ {0x03, 0xe3, 0x83, 0x31},
+ {0x03, 0xe3, 0x83, 0x33},
+ {0x03, 0xe3, 0x83, 0x30},
+ {0x03, 0xe3, 0x83, 0x3e},
+ {0x03, 0xe3, 0x83, 0x32},
+ {0x03, 0xe3, 0x83, 0x36},
+ {0x03, 0xe3, 0x83, 0x2e},
+ {0x03, 0xe3, 0x82, 0x07},
+ {0x03, 0xe3, 0x85, 0x04},
+ {0x03, 0xe3, 0x84, 0x10},
+ {0x03, 0xe3, 0x85, 0x30},
+ {0x03, 0xe3, 0x85, 0x0d},
+ {0x03, 0xe3, 0x85, 0x13},
+ {0x03, 0xe3, 0x85, 0x15},
+ {0x03, 0xe3, 0x85, 0x17},
+ {0x03, 0xe3, 0x85, 0x1f},
+ {0x03, 0xe3, 0x85, 0x1d},
+ {0x03, 0xe3, 0x85, 0x1b},
+ {0x03, 0xe3, 0x85, 0x09},
+ {0x03, 0xe3, 0x85, 0x0f},
+ {0x03, 0xe3, 0x85, 0x0b},
+ {0x03, 0xe3, 0x85, 0x37},
+ {0x03, 0xe3, 0x85, 0x3b},
+ {0x03, 0xe3, 0x85, 0x39},
+ {0x03, 0xe3, 0x85, 0x3f},
+ {0x02, 0xc2, 0x02, 0x00},
+ {0x02, 0xc2, 0x0e, 0x00},
+ {0x02, 0xc2, 0x0c, 0x00},
+ {0x02, 0xc2, 0x00, 0x00},
+ {0x03, 0xe2, 0x82, 0x0f},
+ {0x03, 0xe2, 0x94, 0x2a},
+ {0x03, 0xe2, 0x86, 0x39},
+ {0x03, 0xe2, 0x86, 0x3b},
+ {0x03, 0xe2, 0x86, 0x3f},
+ {0x03, 0xe2, 0x96, 0x0d},
+ {0x03, 0xe2, 0x97, 0x25},
+}
+
+// Total table size 14680 bytes (14KiB)
diff --git a/libgo/go/golang_org/x/text/width/transform.go b/libgo/go/golang_org/x/text/width/transform.go
new file mode 100644
index 00000000000..04f1a3fc590
--- /dev/null
+++ b/libgo/go/golang_org/x/text/width/transform.go
@@ -0,0 +1,239 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package width
+
+import (
+ "unicode/utf8"
+
+ "golang_org/x/text/transform"
+)
+
+type foldTransform struct {
+ transform.NopResetter
+}
+
+func (foldTransform) Span(src []byte, atEOF bool) (n int, err error) {
+ for n < len(src) {
+ if src[n] < utf8.RuneSelf {
+ // ASCII fast path.
+ for n++; n < len(src) && src[n] < utf8.RuneSelf; n++ {
+ }
+ continue
+ }
+ v, size := trie.lookup(src[n:])
+ if size == 0 { // incomplete UTF-8 encoding
+ if !atEOF {
+ err = transform.ErrShortSrc
+ } else {
+ n = len(src)
+ }
+ break
+ }
+ if elem(v)&tagNeedsFold != 0 {
+ err = transform.ErrEndOfSpan
+ break
+ }
+ n += size
+ }
+ return n, err
+}
+
+func (foldTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ for nSrc < len(src) {
+ if src[nSrc] < utf8.RuneSelf {
+ // ASCII fast path.
+ start, end := nSrc, len(src)
+ if d := len(dst) - nDst; d < end-start {
+ end = nSrc + d
+ }
+ for nSrc++; nSrc < end && src[nSrc] < utf8.RuneSelf; nSrc++ {
+ }
+ n := copy(dst[nDst:], src[start:nSrc])
+ if nDst += n; nDst == len(dst) {
+ nSrc = start + n
+ if nSrc == len(src) {
+ return nDst, nSrc, nil
+ }
+ if src[nSrc] < utf8.RuneSelf {
+ return nDst, nSrc, transform.ErrShortDst
+ }
+ }
+ continue
+ }
+ v, size := trie.lookup(src[nSrc:])
+ if size == 0 { // incomplete UTF-8 encoding
+ if !atEOF {
+ return nDst, nSrc, transform.ErrShortSrc
+ }
+ size = 1 // gobble 1 byte
+ }
+ if elem(v)&tagNeedsFold == 0 {
+ if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
+ return nDst, nSrc, transform.ErrShortDst
+ }
+ nDst += size
+ } else {
+ data := inverseData[byte(v)]
+ if len(dst)-nDst < int(data[0]) {
+ return nDst, nSrc, transform.ErrShortDst
+ }
+ i := 1
+ for end := int(data[0]); i < end; i++ {
+ dst[nDst] = data[i]
+ nDst++
+ }
+ dst[nDst] = data[i] ^ src[nSrc+size-1]
+ nDst++
+ }
+ nSrc += size
+ }
+ return nDst, nSrc, nil
+}
+
+type narrowTransform struct {
+ transform.NopResetter
+}
+
+func (narrowTransform) Span(src []byte, atEOF bool) (n int, err error) {
+ for n < len(src) {
+ if src[n] < utf8.RuneSelf {
+ // ASCII fast path.
+ for n++; n < len(src) && src[n] < utf8.RuneSelf; n++ {
+ }
+ continue
+ }
+ v, size := trie.lookup(src[n:])
+ if size == 0 { // incomplete UTF-8 encoding
+ if !atEOF {
+ err = transform.ErrShortSrc
+ } else {
+ n = len(src)
+ }
+ break
+ }
+ if k := elem(v).kind(); byte(v) == 0 || k != EastAsianFullwidth && k != EastAsianWide && k != EastAsianAmbiguous {
+ } else {
+ err = transform.ErrEndOfSpan
+ break
+ }
+ n += size
+ }
+ return n, err
+}
+
+func (narrowTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ for nSrc < len(src) {
+ if src[nSrc] < utf8.RuneSelf {
+ // ASCII fast path.
+ start, end := nSrc, len(src)
+ if d := len(dst) - nDst; d < end-start {
+ end = nSrc + d
+ }
+ for nSrc++; nSrc < end && src[nSrc] < utf8.RuneSelf; nSrc++ {
+ }
+ n := copy(dst[nDst:], src[start:nSrc])
+ if nDst += n; nDst == len(dst) {
+ nSrc = start + n
+ if nSrc == len(src) {
+ return nDst, nSrc, nil
+ }
+ if src[nSrc] < utf8.RuneSelf {
+ return nDst, nSrc, transform.ErrShortDst
+ }
+ }
+ continue
+ }
+ v, size := trie.lookup(src[nSrc:])
+ if size == 0 { // incomplete UTF-8 encoding
+ if !atEOF {
+ return nDst, nSrc, transform.ErrShortSrc
+ }
+ size = 1 // gobble 1 byte
+ }
+ if k := elem(v).kind(); byte(v) == 0 || k != EastAsianFullwidth && k != EastAsianWide && k != EastAsianAmbiguous {
+ if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
+ return nDst, nSrc, transform.ErrShortDst
+ }
+ nDst += size
+ } else {
+ data := inverseData[byte(v)]
+ if len(dst)-nDst < int(data[0]) {
+ return nDst, nSrc, transform.ErrShortDst
+ }
+ i := 1
+ for end := int(data[0]); i < end; i++ {
+ dst[nDst] = data[i]
+ nDst++
+ }
+ dst[nDst] = data[i] ^ src[nSrc+size-1]
+ nDst++
+ }
+ nSrc += size
+ }
+ return nDst, nSrc, nil
+}
+
+type wideTransform struct {
+ transform.NopResetter
+}
+
+func (wideTransform) Span(src []byte, atEOF bool) (n int, err error) {
+ for n < len(src) {
+ // TODO: Consider ASCII fast path. Special-casing ASCII handling can
+ // reduce the ns/op of BenchmarkWideASCII by about 30%. This is probably
+ // not enough to warrant the extra code and complexity.
+ v, size := trie.lookup(src[n:])
+ if size == 0 { // incomplete UTF-8 encoding
+ if !atEOF {
+ err = transform.ErrShortSrc
+ } else {
+ n = len(src)
+ }
+ break
+ }
+ if k := elem(v).kind(); byte(v) == 0 || k != EastAsianHalfwidth && k != EastAsianNarrow {
+ } else {
+ err = transform.ErrEndOfSpan
+ break
+ }
+ n += size
+ }
+ return n, err
+}
+
+func (wideTransform) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ for nSrc < len(src) {
+ // TODO: Consider ASCII fast path. Special-casing ASCII handling can
+ // reduce the ns/op of BenchmarkWideASCII by about 30%. This is probably
+ // not enough to warrant the extra code and complexity.
+ v, size := trie.lookup(src[nSrc:])
+ if size == 0 { // incomplete UTF-8 encoding
+ if !atEOF {
+ return nDst, nSrc, transform.ErrShortSrc
+ }
+ size = 1 // gobble 1 byte
+ }
+ if k := elem(v).kind(); byte(v) == 0 || k != EastAsianHalfwidth && k != EastAsianNarrow {
+ if size != copy(dst[nDst:], src[nSrc:nSrc+size]) {
+ return nDst, nSrc, transform.ErrShortDst
+ }
+ nDst += size
+ } else {
+ data := inverseData[byte(v)]
+ if len(dst)-nDst < int(data[0]) {
+ return nDst, nSrc, transform.ErrShortDst
+ }
+ i := 1
+ for end := int(data[0]); i < end; i++ {
+ dst[nDst] = data[i]
+ nDst++
+ }
+ dst[nDst] = data[i] ^ src[nSrc+size-1]
+ nDst++
+ }
+ nSrc += size
+ }
+ return nDst, nSrc, nil
+}
diff --git a/libgo/go/golang_org/x/text/width/trieval.go b/libgo/go/golang_org/x/text/width/trieval.go
new file mode 100644
index 00000000000..0ecffb4c64f
--- /dev/null
+++ b/libgo/go/golang_org/x/text/width/trieval.go
@@ -0,0 +1,30 @@
+// This file was generated by go generate; DO NOT EDIT
+
+package width
+
+// elem is an entry of the width trie. The high byte is used to encode the type
+// of the rune. The low byte is used to store the index to a mapping entry in
+// the inverseData array.
+type elem uint16
+
+const (
+ tagNeutral elem = iota << typeShift
+ tagAmbiguous
+ tagWide
+ tagNarrow
+ tagFullwidth
+ tagHalfwidth
+)
+
+const (
+ numTypeBits = 3
+ typeShift = 16 - numTypeBits
+
+ // tagNeedsFold is true for all fullwidth and halfwidth runes except for
+ // the Won sign U+20A9.
+ tagNeedsFold = 0x1000
+
+ // The Korean Won sign is halfwidth, but SHOULD NOT be mapped to a wide
+ // variant.
+ wonSign rune = 0x20A9
+)
diff --git a/libgo/go/golang_org/x/text/width/width.go b/libgo/go/golang_org/x/text/width/width.go
new file mode 100644
index 00000000000..27f55b8db72
--- /dev/null
+++ b/libgo/go/golang_org/x/text/width/width.go
@@ -0,0 +1,206 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:generate stringer -type=Kind
+//go:generate go run gen.go gen_common.go gen_trieval.go
+
+// Package width provides functionality for handling different widths in text.
+//
+// Wide characters behave like ideographs; they tend to allow line breaks after
+// each character and remain upright in vertical text layout. Narrow characters
+// are kept together in words or runs that are rotated sideways in vertical text
+// layout.
+//
+// For more information, see http://unicode.org/reports/tr11/.
+package width // import "golang_org/x/text/width"
+
+import (
+ "unicode/utf8"
+
+ "golang_org/x/text/transform"
+)
+
+// TODO
+// 1) Reduce table size by compressing blocks.
+// 2) API proposition for computing display length
+// (approximation, fixed pitch only).
+// 3) Implement display length.
+
+// Kind indicates the type of width property as defined in http://unicode.org/reports/tr11/.
+type Kind int
+
+const (
+ // Neutral characters do not occur in legacy East Asian character sets.
+ Neutral Kind = iota
+
+ // EastAsianAmbiguous characters that can be sometimes wide and sometimes
+ // narrow and require additional information not contained in the character
+ // code to further resolve their width.
+ EastAsianAmbiguous
+
+ // EastAsianWide characters are wide in its usual form. They occur only in
+ // the context of East Asian typography. These runes may have explicit
+ // halfwidth counterparts.
+ EastAsianWide
+
+ // EastAsianNarrow characters are narrow in its usual form. They often have
+ // fullwidth counterparts.
+ EastAsianNarrow
+
+ // Note: there exist Narrow runes that do not have fullwidth or wide
+ // counterparts, despite what the definition says (e.g. U+27E6).
+
+ // EastAsianFullwidth characters have a compatibility decompositions of type
+ // wide that map to a narrow counterpart.
+ EastAsianFullwidth
+
+ // EastAsianHalfwidth characters have a compatibility decomposition of type
+ // narrow that map to a wide or ambiguous counterpart, plus U+20A9 ₩ WON
+ // SIGN.
+ EastAsianHalfwidth
+
+ // Note: there exist runes that have a halfwidth counterparts but that are
+ // classified as Ambiguous, rather than wide (e.g. U+2190).
+)
+
+// TODO: the generated tries need to return size 1 for invalid runes for the
+// width to be computed correctly (each byte should render width 1)
+
+var trie = newWidthTrie(0)
+
+// Lookup reports the Properties of the first rune in b and the number of bytes
+// of its UTF-8 encoding.
+func Lookup(b []byte) (p Properties, size int) {
+ v, sz := trie.lookup(b)
+ return Properties{elem(v), b[sz-1]}, sz
+}
+
+// LookupString reports the Properties of the first rune in s and the number of
+// bytes of its UTF-8 encoding.
+func LookupString(s string) (p Properties, size int) {
+ v, sz := trie.lookupString(s)
+ return Properties{elem(v), s[sz-1]}, sz
+}
+
+// LookupRune reports the Properties of rune r.
+func LookupRune(r rune) Properties {
+ var buf [4]byte
+ n := utf8.EncodeRune(buf[:], r)
+ v, _ := trie.lookup(buf[:n])
+ last := byte(r)
+ if r >= utf8.RuneSelf {
+ last = 0x80 + byte(r&0x3f)
+ }
+ return Properties{elem(v), last}
+}
+
+// Properties provides access to width properties of a rune.
+type Properties struct {
+ elem elem
+ last byte
+}
+
+func (e elem) kind() Kind {
+ return Kind(e >> typeShift)
+}
+
+// Kind returns the Kind of a rune as defined in Unicode TR #11.
+// See http://unicode.org/reports/tr11/ for more details.
+func (p Properties) Kind() Kind {
+ return p.elem.kind()
+}
+
+// Folded returns the folded variant of a rune or 0 if the rune is canonical.
+func (p Properties) Folded() rune {
+ if p.elem&tagNeedsFold != 0 {
+ buf := inverseData[byte(p.elem)]
+ buf[buf[0]] ^= p.last
+ r, _ := utf8.DecodeRune(buf[1 : 1+buf[0]])
+ return r
+ }
+ return 0
+}
+
+// Narrow returns the narrow variant of a rune or 0 if the rune is already
+// narrow or doesn't have a narrow variant.
+func (p Properties) Narrow() rune {
+ if k := p.elem.kind(); byte(p.elem) != 0 && (k == EastAsianFullwidth || k == EastAsianWide || k == EastAsianAmbiguous) {
+ buf := inverseData[byte(p.elem)]
+ buf[buf[0]] ^= p.last
+ r, _ := utf8.DecodeRune(buf[1 : 1+buf[0]])
+ return r
+ }
+ return 0
+}
+
+// Wide returns the wide variant of a rune or 0 if the rune is already
+// wide or doesn't have a wide variant.
+func (p Properties) Wide() rune {
+ if k := p.elem.kind(); byte(p.elem) != 0 && (k == EastAsianHalfwidth || k == EastAsianNarrow) {
+ buf := inverseData[byte(p.elem)]
+ buf[buf[0]] ^= p.last
+ r, _ := utf8.DecodeRune(buf[1 : 1+buf[0]])
+ return r
+ }
+ return 0
+}
+
+// TODO for Properties:
+// - Add Fullwidth/Halfwidth or Inverted methods for computing variants
+// mapping.
+// - Add width information (including information on non-spacing runes).
+
+// Transformer implements the transform.Transformer interface.
+type Transformer struct {
+ t transform.SpanningTransformer
+}
+
+// Reset implements the transform.Transformer interface.
+func (t Transformer) Reset() { t.t.Reset() }
+
+// Transform implements the transform.Transformer interface.
+func (t Transformer) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
+ return t.t.Transform(dst, src, atEOF)
+}
+
+// Span implements the transform.SpanningTransformer interface.
+func (t Transformer) Span(src []byte, atEOF bool) (n int, err error) {
+ return t.t.Span(src, atEOF)
+}
+
+// Bytes returns a new byte slice with the result of applying t to b.
+func (t Transformer) Bytes(b []byte) []byte {
+ b, _, _ = transform.Bytes(t, b)
+ return b
+}
+
+// String returns a string with the result of applying t to s.
+func (t Transformer) String(s string) string {
+ s, _, _ = transform.String(t, s)
+ return s
+}
+
+var (
+ // Fold is a transform that maps all runes to their canonical width.
+ //
+ // Note that the NFKC and NFKD transforms in golang.org/x/text/unicode/norm
+ // provide a more generic folding mechanism.
+ Fold Transformer = Transformer{foldTransform{}}
+
+ // Widen is a transform that maps runes to their wide variant, if
+ // available.
+ Widen Transformer = Transformer{wideTransform{}}
+
+ // Narrow is a transform that maps runes to their narrow variant, if
+ // available.
+ Narrow Transformer = Transformer{narrowTransform{}}
+)
+
+// TODO: Consider the following options:
+// - Treat Ambiguous runes that have a halfwidth counterpart as wide, or some
+// generalized variant of this.
+// - Consider a wide Won character to be the default width (or some generalized
+// variant of this).
+// - Filter the set of characters that gets converted (the preferred approach is
+// to allow applying filters to transforms).
diff --git a/libgo/go/hash/crc32/crc32.go b/libgo/go/hash/crc32/crc32.go
index c3ac7b80c3c..8aa91b17e90 100644
--- a/libgo/go/hash/crc32/crc32.go
+++ b/libgo/go/hash/crc32/crc32.go
@@ -20,9 +20,6 @@ import (
// The size of a CRC-32 checksum in bytes.
const Size = 4
-// Use "slice by 8" when payload >= this value.
-const sliceBy8Cutoff = 16
-
// Predefined polynomials.
const (
// IEEE is by far and away the most common CRC-32 polynomial.
@@ -43,71 +40,96 @@ const (
// Table is a 256-word table representing the polynomial for efficient processing.
type Table [256]uint32
+// This file makes use of functions implemented in architecture-specific files.
+// The interface that they implement is as follows:
+//
+// // archAvailableIEEE reports whether an architecture-specific CRC32-IEEE
+// // algorithm is available.
+// archAvailableIEEE() bool
+//
+// // archInitIEEE initializes the architecture-specific CRC3-IEEE algorithm.
+// // It can only be called if archAvailableIEEE() returns true.
+// archInitIEEE()
+//
+// // archUpdateIEEE updates the given CRC32-IEEE. It can only be called if
+// // archInitIEEE() was previously called.
+// archUpdateIEEE(crc uint32, p []byte) uint32
+//
+// // archAvailableCastagnoli reports whether an architecture-specific
+// // CRC32-C algorithm is available.
+// archAvailableCastagnoli() bool
+//
+// // archInitCastagnoli initializes the architecture-specific CRC32-C
+// // algorithm. It can only be called if archAvailableCastagnoli() returns
+// // true.
+// archInitCastagnoli()
+//
+// // archUpdateCastagnoli updates the given CRC32-C. It can only be called
+// // if archInitCastagnoli() was previously called.
+// archUpdateCastagnoli(crc uint32, p []byte) uint32
+
// castagnoliTable points to a lazily initialized Table for the Castagnoli
// polynomial. MakeTable will always return this value when asked to make a
// Castagnoli table so we can compare against it to find when the caller is
// using this polynomial.
var castagnoliTable *Table
var castagnoliTable8 *slicing8Table
+var castagnoliArchImpl bool
+var updateCastagnoli func(crc uint32, p []byte) uint32
var castagnoliOnce sync.Once
func castagnoliInit() {
- castagnoliTable = makeTable(Castagnoli)
- castagnoliTable8 = makeTable8(Castagnoli)
+ castagnoliTable = simpleMakeTable(Castagnoli)
+ castagnoliArchImpl = archAvailableCastagnoli()
+
+ if castagnoliArchImpl {
+ archInitCastagnoli()
+ updateCastagnoli = archUpdateCastagnoli
+ } else {
+ // Initialize the slicing-by-8 table.
+ castagnoliTable8 = slicingMakeTable(Castagnoli)
+ updateCastagnoli = func(crc uint32, p []byte) uint32 {
+ return slicingUpdate(crc, castagnoliTable8, p)
+ }
+ }
}
// IEEETable is the table for the IEEE polynomial.
-var IEEETable = makeTable(IEEE)
-
-// slicing8Table is array of 8 Tables
-type slicing8Table [8]Table
+var IEEETable = simpleMakeTable(IEEE)
// ieeeTable8 is the slicing8Table for IEEE
var ieeeTable8 *slicing8Table
-var ieeeTable8Once sync.Once
+var ieeeArchImpl bool
+var updateIEEE func(crc uint32, p []byte) uint32
+var ieeeOnce sync.Once
+
+func ieeeInit() {
+ ieeeArchImpl = archAvailableIEEE()
+
+ if ieeeArchImpl {
+ archInitIEEE()
+ updateIEEE = archUpdateIEEE
+ } else {
+ // Initialize the slicing-by-8 table.
+ ieeeTable8 = slicingMakeTable(IEEE)
+ updateIEEE = func(crc uint32, p []byte) uint32 {
+ return slicingUpdate(crc, ieeeTable8, p)
+ }
+ }
+}
// MakeTable returns a Table constructed from the specified polynomial.
// The contents of this Table must not be modified.
func MakeTable(poly uint32) *Table {
switch poly {
case IEEE:
+ ieeeOnce.Do(ieeeInit)
return IEEETable
case Castagnoli:
castagnoliOnce.Do(castagnoliInit)
return castagnoliTable
}
- return makeTable(poly)
-}
-
-// makeTable returns the Table constructed from the specified polynomial.
-func makeTable(poly uint32) *Table {
- t := new(Table)
- for i := 0; i < 256; i++ {
- crc := uint32(i)
- for j := 0; j < 8; j++ {
- if crc&1 == 1 {
- crc = (crc >> 1) ^ poly
- } else {
- crc >>= 1
- }
- }
- t[i] = crc
- }
- return t
-}
-
-// makeTable8 returns slicing8Table constructed from the specified polynomial.
-func makeTable8(poly uint32) *slicing8Table {
- t := new(slicing8Table)
- t[0] = *makeTable(poly)
- for i := 0; i < 256; i++ {
- crc := t[0][i]
- for j := 1; j < 8; j++ {
- crc = t[0][crc&0xFF] ^ (crc >> 8)
- t[j][i] = crc
- }
- }
- return t
+ return simpleMakeTable(poly)
}
// digest represents the partial evaluation of a checksum.
@@ -119,7 +141,12 @@ type digest struct {
// New creates a new hash.Hash32 computing the CRC-32 checksum
// using the polynomial represented by the Table.
// Its Sum method will lay the value out in big-endian byte order.
-func New(tab *Table) hash.Hash32 { return &digest{0, tab} }
+func New(tab *Table) hash.Hash32 {
+ if tab == IEEETable {
+ ieeeOnce.Do(ieeeInit)
+ }
+ return &digest{0, tab}
+}
// NewIEEE creates a new hash.Hash32 computing the CRC-32 checksum
// using the IEEE polynomial.
@@ -132,44 +159,32 @@ func (d *digest) BlockSize() int { return 1 }
func (d *digest) Reset() { d.crc = 0 }
-func update(crc uint32, tab *Table, p []byte) uint32 {
- crc = ^crc
- for _, v := range p {
- crc = tab[byte(crc)^v] ^ (crc >> 8)
- }
- return ^crc
-}
-
-// updateSlicingBy8 updates CRC using Slicing-by-8
-func updateSlicingBy8(crc uint32, tab *slicing8Table, p []byte) uint32 {
- crc = ^crc
- for len(p) > 8 {
- crc ^= uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
- crc = tab[0][p[7]] ^ tab[1][p[6]] ^ tab[2][p[5]] ^ tab[3][p[4]] ^
- tab[4][crc>>24] ^ tab[5][(crc>>16)&0xFF] ^
- tab[6][(crc>>8)&0xFF] ^ tab[7][crc&0xFF]
- p = p[8:]
- }
- crc = ^crc
- if len(p) == 0 {
- return crc
- }
- return update(crc, &tab[0], p)
-}
-
// Update returns the result of adding the bytes in p to the crc.
func Update(crc uint32, tab *Table, p []byte) uint32 {
switch tab {
case castagnoliTable:
return updateCastagnoli(crc, p)
case IEEETable:
+ // Unfortunately, because IEEETable is exported, IEEE may be used without a
+ // call to MakeTable. We have to make sure it gets initialized in that case.
+ ieeeOnce.Do(ieeeInit)
return updateIEEE(crc, p)
+ default:
+ return simpleUpdate(crc, tab, p)
}
- return update(crc, tab, p)
}
func (d *digest) Write(p []byte) (n int, err error) {
- d.crc = Update(d.crc, d.tab, p)
+ switch d.tab {
+ case castagnoliTable:
+ d.crc = updateCastagnoli(d.crc, p)
+ case IEEETable:
+ // We only create digest objects through New() which takes care of
+ // initialization in this case.
+ d.crc = updateIEEE(d.crc, p)
+ default:
+ d.crc = simpleUpdate(d.crc, d.tab, p)
+ }
return len(p), nil
}
@@ -186,4 +201,7 @@ func Checksum(data []byte, tab *Table) uint32 { return Update(0, tab, data) }
// ChecksumIEEE returns the CRC-32 checksum of data
// using the IEEE polynomial.
-func ChecksumIEEE(data []byte) uint32 { return updateIEEE(0, data) }
+func ChecksumIEEE(data []byte) uint32 {
+ ieeeOnce.Do(ieeeInit)
+ return updateIEEE(0, data)
+}
diff --git a/libgo/go/hash/crc32/crc32_amd64.go b/libgo/go/hash/crc32/crc32_amd64.go
index 8eae850bbf3..72844f0037c 100644
--- a/libgo/go/hash/crc32/crc32_amd64.go
+++ b/libgo/go/hash/crc32/crc32_amd64.go
@@ -2,10 +2,16 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// AMD64-specific hardware-assisted CRC32 algorithms. See crc32.go for a
+// description of the interface that each architecture-specific file
+// implements.
+
// +build ignore
package crc32
+import "unsafe"
+
// This file contains the code to call the SSE 4.2 version of the Castagnoli
// and IEEE CRC.
@@ -15,11 +21,20 @@ func haveSSE41() bool
func haveSSE42() bool
func haveCLMUL() bool
-// castagnoliSSE42 is defined in crc_amd64.s and uses the SSE4.2 CRC32
+// castagnoliSSE42 is defined in crc32_amd64.s and uses the SSE4.2 CRC32
// instruction.
//go:noescape
func castagnoliSSE42(crc uint32, p []byte) uint32
+// castagnoliSSE42Triple is defined in crc32_amd64.s and uses the SSE4.2 CRC32
+// instruction.
+//go:noescape
+func castagnoliSSE42Triple(
+ crcA, crcB, crcC uint32,
+ a, b, c []byte,
+ rounds uint32,
+) (retA uint32, retB uint32, retC uint32)
+
// ieeeCLMUL is defined in crc_amd64.s and uses the PCLMULQDQ
// instruction as well as SSE 4.1.
//go:noescape
@@ -28,35 +43,188 @@ func ieeeCLMUL(crc uint32, p []byte) uint32
var sse42 = haveSSE42()
var useFastIEEE = haveCLMUL() && haveSSE41()
-func updateCastagnoli(crc uint32, p []byte) uint32 {
- if sse42 {
- return castagnoliSSE42(crc, p)
+const castagnoliK1 = 168
+const castagnoliK2 = 1344
+
+type sse42Table [4]Table
+
+var castagnoliSSE42TableK1 *sse42Table
+var castagnoliSSE42TableK2 *sse42Table
+
+func archAvailableCastagnoli() bool {
+ return sse42
+}
+
+func archInitCastagnoli() {
+ if !sse42 {
+ panic("arch-specific Castagnoli not available")
}
- // Use slicing-by-8 on larger inputs.
- if len(p) >= sliceBy8Cutoff {
- return updateSlicingBy8(crc, castagnoliTable8, p)
+ castagnoliSSE42TableK1 = new(sse42Table)
+ castagnoliSSE42TableK2 = new(sse42Table)
+ // See description in updateCastagnoli.
+ // t[0][i] = CRC(i000, O)
+ // t[1][i] = CRC(0i00, O)
+ // t[2][i] = CRC(00i0, O)
+ // t[3][i] = CRC(000i, O)
+ // where O is a sequence of K zeros.
+ var tmp [castagnoliK2]byte
+ for b := 0; b < 4; b++ {
+ for i := 0; i < 256; i++ {
+ val := uint32(i) << uint32(b*8)
+ castagnoliSSE42TableK1[b][i] = castagnoliSSE42(val, tmp[:castagnoliK1])
+ castagnoliSSE42TableK2[b][i] = castagnoliSSE42(val, tmp[:])
+ }
}
- return update(crc, castagnoliTable, p)
}
-func updateIEEE(crc uint32, p []byte) uint32 {
- if useFastIEEE && len(p) >= 64 {
- left := len(p) & 15
- do := len(p) - left
- crc = ^ieeeCLMUL(^crc, p[:do])
- if left > 0 {
- crc = update(crc, IEEETable, p[do:])
+// castagnoliShift computes the CRC32-C of K1 or K2 zeroes (depending on the
+// table given) with the given initial crc value. This corresponds to
+// CRC(crc, O) in the description in updateCastagnoli.
+func castagnoliShift(table *sse42Table, crc uint32) uint32 {
+ return table[3][crc>>24] ^
+ table[2][(crc>>16)&0xFF] ^
+ table[1][(crc>>8)&0xFF] ^
+ table[0][crc&0xFF]
+}
+
+func archUpdateCastagnoli(crc uint32, p []byte) uint32 {
+ if !sse42 {
+ panic("not available")
+ }
+
+ // This method is inspired from the algorithm in Intel's white paper:
+ // "Fast CRC Computation for iSCSI Polynomial Using CRC32 Instruction"
+ // The same strategy of splitting the buffer in three is used but the
+ // combining calculation is different; the complete derivation is explained
+ // below.
+ //
+ // -- The basic idea --
+ //
+ // The CRC32 instruction (available in SSE4.2) can process 8 bytes at a
+ // time. In recent Intel architectures the instruction takes 3 cycles;
+ // however the processor can pipeline up to three instructions if they
+ // don't depend on each other.
+ //
+ // Roughly this means that we can process three buffers in about the same
+ // time we can process one buffer.
+ //
+ // The idea is then to split the buffer in three, CRC the three pieces
+ // separately and then combine the results.
+ //
+ // Combining the results requires precomputed tables, so we must choose a
+ // fixed buffer length to optimize. The longer the length, the faster; but
+ // only buffers longer than this length will use the optimization. We choose
+ // two cutoffs and compute tables for both:
+ // - one around 512: 168*3=504
+ // - one around 4KB: 1344*3=4032
+ //
+ // -- The nitty gritty --
+ //
+ // Let CRC(I, X) be the non-inverted CRC32-C of the sequence X (with
+ // initial non-inverted CRC I). This function has the following properties:
+ // (a) CRC(I, AB) = CRC(CRC(I, A), B)
+ // (b) CRC(I, A xor B) = CRC(I, A) xor CRC(0, B)
+ //
+ // Say we want to compute CRC(I, ABC) where A, B, C are three sequences of
+ // K bytes each, where K is a fixed constant. Let O be the sequence of K zero
+ // bytes.
+ //
+ // CRC(I, ABC) = CRC(I, ABO xor C)
+ // = CRC(I, ABO) xor CRC(0, C)
+ // = CRC(CRC(I, AB), O) xor CRC(0, C)
+ // = CRC(CRC(I, AO xor B), O) xor CRC(0, C)
+ // = CRC(CRC(I, AO) xor CRC(0, B), O) xor CRC(0, C)
+ // = CRC(CRC(CRC(I, A), O) xor CRC(0, B), O) xor CRC(0, C)
+ //
+ // The castagnoliSSE42Triple function can compute CRC(I, A), CRC(0, B),
+ // and CRC(0, C) efficiently. We just need to find a way to quickly compute
+ // CRC(uvwx, O) given a 4-byte initial value uvwx. We can precompute these
+ // values; since we can't have a 32-bit table, we break it up into four
+ // 8-bit tables:
+ //
+ // CRC(uvwx, O) = CRC(u000, O) xor
+ // CRC(0v00, O) xor
+ // CRC(00w0, O) xor
+ // CRC(000x, O)
+ //
+ // We can compute tables corresponding to the four terms for all 8-bit
+ // values.
+
+ crc = ^crc
+
+ // If a buffer is long enough to use the optimization, process the first few
+ // bytes to align the buffer to an 8 byte boundary (if necessary).
+ if len(p) >= castagnoliK1*3 {
+ delta := int(uintptr(unsafe.Pointer(&p[0])) & 7)
+ if delta != 0 {
+ delta = 8 - delta
+ crc = castagnoliSSE42(crc, p[:delta])
+ p = p[delta:]
}
- return crc
}
- // Use slicing-by-8 on larger inputs.
- if len(p) >= sliceBy8Cutoff {
- ieeeTable8Once.Do(func() {
- ieeeTable8 = makeTable8(IEEE)
- })
- return updateSlicingBy8(crc, ieeeTable8, p)
+ // Process 3*K2 at a time.
+ for len(p) >= castagnoliK2*3 {
+ // Compute CRC(I, A), CRC(0, B), and CRC(0, C).
+ crcA, crcB, crcC := castagnoliSSE42Triple(
+ crc, 0, 0,
+ p, p[castagnoliK2:], p[castagnoliK2*2:],
+ castagnoliK2/24)
+
+ // CRC(I, AB) = CRC(CRC(I, A), O) xor CRC(0, B)
+ crcAB := castagnoliShift(castagnoliSSE42TableK2, crcA) ^ crcB
+ // CRC(I, ABC) = CRC(CRC(I, AB), O) xor CRC(0, C)
+ crc = castagnoliShift(castagnoliSSE42TableK2, crcAB) ^ crcC
+ p = p[castagnoliK2*3:]
+ }
+
+ // Process 3*K1 at a time.
+ for len(p) >= castagnoliK1*3 {
+ // Compute CRC(I, A), CRC(0, B), and CRC(0, C).
+ crcA, crcB, crcC := castagnoliSSE42Triple(
+ crc, 0, 0,
+ p, p[castagnoliK1:], p[castagnoliK1*2:],
+ castagnoliK1/24)
+
+ // CRC(I, AB) = CRC(CRC(I, A), O) xor CRC(0, B)
+ crcAB := castagnoliShift(castagnoliSSE42TableK1, crcA) ^ crcB
+ // CRC(I, ABC) = CRC(CRC(I, AB), O) xor CRC(0, C)
+ crc = castagnoliShift(castagnoliSSE42TableK1, crcAB) ^ crcC
+ p = p[castagnoliK1*3:]
+ }
+
+ // Use the simple implementation for what's left.
+ crc = castagnoliSSE42(crc, p)
+ return ^crc
+}
+
+func archAvailableIEEE() bool {
+ return useFastIEEE
+}
+
+var archIeeeTable8 *slicing8Table
+
+func archInitIEEE() {
+ if !useFastIEEE {
+ panic("not available")
}
+ // We still use slicing-by-8 for small buffers.
+ archIeeeTable8 = slicingMakeTable(IEEE)
+}
- return update(crc, IEEETable, p)
+func archUpdateIEEE(crc uint32, p []byte) uint32 {
+ if !useFastIEEE {
+ panic("not available")
+ }
+
+ if len(p) >= 64 {
+ left := len(p) & 15
+ do := len(p) - left
+ crc = ^ieeeCLMUL(^crc, p[:do])
+ p = p[do:]
+ }
+ if len(p) == 0 {
+ return crc
+ }
+ return slicingUpdate(crc, archIeeeTable8, p)
}
diff --git a/libgo/go/hash/crc32/crc32_amd64p32.go b/libgo/go/hash/crc32/crc32_amd64p32.go
index 1f6cd346431..9d728fc8feb 100644
--- a/libgo/go/hash/crc32/crc32_amd64p32.go
+++ b/libgo/go/hash/crc32/crc32_amd64p32.go
@@ -7,36 +7,35 @@ package crc32
// This file contains the code to call the SSE 4.2 version of the Castagnoli
// CRC.
-// haveSSE42 is defined in crc_amd64p32.s and uses CPUID to test for SSE 4.2
+// haveSSE42 is defined in crc32_amd64p32.s and uses CPUID to test for SSE 4.2
// support.
func haveSSE42() bool
-// castagnoliSSE42 is defined in crc_amd64.s and uses the SSE4.2 CRC32
+// castagnoliSSE42 is defined in crc32_amd64p32.s and uses the SSE4.2 CRC32
// instruction.
//go:noescape
func castagnoliSSE42(crc uint32, p []byte) uint32
var sse42 = haveSSE42()
-func updateCastagnoli(crc uint32, p []byte) uint32 {
- if sse42 {
- return castagnoliSSE42(crc, p)
- }
- // Use slicing-by-8 on larger inputs.
- if len(p) >= sliceBy8Cutoff {
- return updateSlicingBy8(crc, castagnoliTable8, p)
- }
- return update(crc, castagnoliTable, p)
+func archAvailableCastagnoli() bool {
+ return sse42
}
-func updateIEEE(crc uint32, p []byte) uint32 {
- // Use slicing-by-8 on larger inputs.
- if len(p) >= sliceBy8Cutoff {
- ieeeTable8Once.Do(func() {
- ieeeTable8 = makeTable8(IEEE)
- })
- return updateSlicingBy8(crc, ieeeTable8, p)
+func archInitCastagnoli() {
+ if !sse42 {
+ panic("not available")
}
+ // No initialization necessary.
+}
- return update(crc, IEEETable, p)
+func archUpdateCastagnoli(crc uint32, p []byte) uint32 {
+ if !sse42 {
+ panic("not available")
+ }
+ return castagnoliSSE42(crc, p)
}
+
+func archAvailableIEEE() bool { return false }
+func archInitIEEE() { panic("not available") }
+func archUpdateIEEE(crc uint32, p []byte) uint32 { panic("not available") }
diff --git a/libgo/go/hash/crc32/crc32_generic.go b/libgo/go/hash/crc32/crc32_generic.go
index e9096cef786..abacbb663d4 100644
--- a/libgo/go/hash/crc32/crc32_generic.go
+++ b/libgo/go/hash/crc32/crc32_generic.go
@@ -2,28 +2,88 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// -build !amd64,!amd64p32,!s390x
+// This file contains CRC32 algorithms that are not specific to any architecture
+// and don't use hardware acceleration.
+//
+// The simple (and slow) CRC32 implementation only uses a 256*4 bytes table.
+//
+// The slicing-by-8 algorithm is a faster implementation that uses a bigger
+// table (8*256*4 bytes).
package crc32
-// This file contains the generic version of updateCastagnoli which does
-// slicing-by-8, or uses the fallback for very small sizes.
+// simpleMakeTable allocates and constructs a Table for the specified
+// polynomial. The table is suitable for use with the simple algorithm
+// (simpleUpdate).
+func simpleMakeTable(poly uint32) *Table {
+ t := new(Table)
+ simplePopulateTable(poly, t)
+ return t
+}
+
+// simplePopulateTable constructs a Table for the specified polynomial, suitable
+// for use with simpleUpdate.
+func simplePopulateTable(poly uint32, t *Table) {
+ for i := 0; i < 256; i++ {
+ crc := uint32(i)
+ for j := 0; j < 8; j++ {
+ if crc&1 == 1 {
+ crc = (crc >> 1) ^ poly
+ } else {
+ crc >>= 1
+ }
+ }
+ t[i] = crc
+ }
+}
+
+// simpleUpdate uses the simple algorithm to update the CRC, given a table that
+// was previously computed using simpleMakeTable.
+func simpleUpdate(crc uint32, tab *Table, p []byte) uint32 {
+ crc = ^crc
+ for _, v := range p {
+ crc = tab[byte(crc)^v] ^ (crc >> 8)
+ }
+ return ^crc
+}
+
+// Use slicing-by-8 when payload >= this value.
+const slicing8Cutoff = 16
-func updateCastagnoli(crc uint32, p []byte) uint32 {
- // Use slicing-by-8 on larger inputs.
- if len(p) >= sliceBy8Cutoff {
- return updateSlicingBy8(crc, castagnoliTable8, p)
+// slicing8Table is array of 8 Tables, used by the slicing-by-8 algorithm.
+type slicing8Table [8]Table
+
+// slicingMakeTable constructs a slicing8Table for the specified polynomial. The
+// table is suitable for use with the slicing-by-8 algorithm (slicingUpdate).
+func slicingMakeTable(poly uint32) *slicing8Table {
+ t := new(slicing8Table)
+ simplePopulateTable(poly, &t[0])
+ for i := 0; i < 256; i++ {
+ crc := t[0][i]
+ for j := 1; j < 8; j++ {
+ crc = t[0][crc&0xFF] ^ (crc >> 8)
+ t[j][i] = crc
+ }
}
- return update(crc, castagnoliTable, p)
+ return t
}
-func updateIEEE(crc uint32, p []byte) uint32 {
- // Use slicing-by-8 on larger inputs.
- if len(p) >= sliceBy8Cutoff {
- ieeeTable8Once.Do(func() {
- ieeeTable8 = makeTable8(IEEE)
- })
- return updateSlicingBy8(crc, ieeeTable8, p)
+// slicingUpdate uses the slicing-by-8 algorithm to update the CRC, given a
+// table that was previously computed using slicingMakeTable.
+func slicingUpdate(crc uint32, tab *slicing8Table, p []byte) uint32 {
+ if len(p) >= slicing8Cutoff {
+ crc = ^crc
+ for len(p) > 8 {
+ crc ^= uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
+ crc = tab[0][p[7]] ^ tab[1][p[6]] ^ tab[2][p[5]] ^ tab[3][p[4]] ^
+ tab[4][crc>>24] ^ tab[5][(crc>>16)&0xFF] ^
+ tab[6][(crc>>8)&0xFF] ^ tab[7][crc&0xFF]
+ p = p[8:]
+ }
+ crc = ^crc
+ }
+ if len(p) == 0 {
+ return crc
}
- return update(crc, IEEETable, p)
+ return simpleUpdate(crc, &tab[0], p)
}
diff --git a/libgo/go/hash/crc32/crc32_otherarch.go b/libgo/go/hash/crc32/crc32_otherarch.go
new file mode 100644
index 00000000000..09c3389ea7a
--- /dev/null
+++ b/libgo/go/hash/crc32/crc32_otherarch.go
@@ -0,0 +1,15 @@
+// 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 !amd64,!amd64p32,!s390x
+
+package crc32
+
+func archAvailableIEEE() bool { return false }
+func archInitIEEE() { panic("not available") }
+func archUpdateIEEE(crc uint32, p []byte) uint32 { panic("not available") }
+
+func archAvailableCastagnoli() bool { return false }
+func archInitCastagnoli() { panic("not available") }
+func archUpdateCastagnoli(crc uint32, p []byte) uint32 { panic("not available") }
diff --git a/libgo/go/hash/crc32/crc32_s390x.go b/libgo/go/hash/crc32/crc32_s390x.go
index 2a7926b4796..8815c70470b 100644
--- a/libgo/go/hash/crc32/crc32_s390x.go
+++ b/libgo/go/hash/crc32/crc32_s390x.go
@@ -27,58 +27,65 @@ func vectorizedCastagnoli(crc uint32, p []byte) uint32
//go:noescape
func vectorizedIEEE(crc uint32, p []byte) uint32
-func genericCastagnoli(crc uint32, p []byte) uint32 {
- // Use slicing-by-8 on larger inputs.
- if len(p) >= sliceBy8Cutoff {
- return updateSlicingBy8(crc, castagnoliTable8, p)
- }
- return update(crc, castagnoliTable, p)
+func archAvailableCastagnoli() bool {
+ return hasVX
}
-func genericIEEE(crc uint32, p []byte) uint32 {
- // Use slicing-by-8 on larger inputs.
- if len(p) >= sliceBy8Cutoff {
- ieeeTable8Once.Do(func() {
- ieeeTable8 = makeTable8(IEEE)
- })
- return updateSlicingBy8(crc, ieeeTable8, p)
+var archCastagnoliTable8 *slicing8Table
+
+func archInitCastagnoli() {
+ if !hasVX {
+ panic("not available")
}
- return update(crc, IEEETable, p)
+ // We still use slicing-by-8 for small buffers.
+ archCastagnoliTable8 = slicingMakeTable(Castagnoli)
}
-// updateCastagnoli calculates the checksum of p using
-// vectorizedCastagnoli if possible and falling back onto
-// genericCastagnoli as needed.
-func updateCastagnoli(crc uint32, p []byte) uint32 {
- // Use vectorized function if vector facility is available and
- // data length is above threshold.
- if hasVX && len(p) >= vxMinLen {
+// archUpdateCastagnoli calculates the checksum of p using
+// vectorizedCastagnoli.
+func archUpdateCastagnoli(crc uint32, p []byte) uint32 {
+ if !hasVX {
+ panic("not available")
+ }
+ // Use vectorized function if data length is above threshold.
+ if len(p) >= vxMinLen {
aligned := len(p) & ^vxAlignMask
crc = vectorizedCastagnoli(crc, p[:aligned])
p = p[aligned:]
- // process remaining data
- if len(p) > 0 {
- crc = genericCastagnoli(crc, p)
- }
+ }
+ if len(p) == 0 {
return crc
}
- return genericCastagnoli(crc, p)
+ return slicingUpdate(crc, archCastagnoliTable8, p)
+}
+
+func archAvailableIEEE() bool {
+ return hasVX
+}
+
+var archIeeeTable8 *slicing8Table
+
+func archInitIEEE() {
+ if !hasVX {
+ panic("not available")
+ }
+ // We still use slicing-by-8 for small buffers.
+ archIeeeTable8 = slicingMakeTable(IEEE)
}
-// updateIEEE calculates the checksum of p using vectorizedIEEE if
-// possible and falling back onto genericIEEE as needed.
-func updateIEEE(crc uint32, p []byte) uint32 {
- // Use vectorized function if vector facility is available and
- // data length is above threshold.
- if hasVX && len(p) >= vxMinLen {
+// archUpdateIEEE calculates the checksum of p using vectorizedIEEE.
+func archUpdateIEEE(crc uint32, p []byte) uint32 {
+ if !hasVX {
+ panic("not available")
+ }
+ // Use vectorized function if data length is above threshold.
+ if len(p) >= vxMinLen {
aligned := len(p) & ^vxAlignMask
crc = vectorizedIEEE(crc, p[:aligned])
p = p[aligned:]
- // process remaining data
- if len(p) > 0 {
- crc = genericIEEE(crc, p)
- }
+ }
+ if len(p) == 0 {
return crc
}
- return genericIEEE(crc, p)
+ return slicingUpdate(crc, archIeeeTable8, p)
}
diff --git a/libgo/go/hash/crc32/crc32_test.go b/libgo/go/hash/crc32/crc32_test.go
index e2b3557828c..1356734d504 100644
--- a/libgo/go/hash/crc32/crc32_test.go
+++ b/libgo/go/hash/crc32/crc32_test.go
@@ -6,7 +6,7 @@ package crc32
import (
"hash"
- "io"
+ "math/rand"
"testing"
)
@@ -49,74 +49,221 @@ var golden = []test{
{0x8e0bb443, 0xdcded527, "How can you write a big system without C++? -Paul Glick"},
}
-func TestGolden(t *testing.T) {
- castagnoliTab := MakeTable(Castagnoli)
+// testGoldenIEEE verifies that the given function returns
+// correct IEEE checksums.
+func testGoldenIEEE(t *testing.T, crcFunc func(b []byte) uint32) {
+ for _, g := range golden {
+ if crc := crcFunc([]byte(g.in)); crc != g.ieee {
+ t.Errorf("IEEE(%s) = 0x%x want 0x%x", g.in, crc, g.ieee)
+ }
+ }
+}
+// testGoldenCastagnoli verifies that the given function returns
+// correct IEEE checksums.
+func testGoldenCastagnoli(t *testing.T, crcFunc func(b []byte) uint32) {
for _, g := range golden {
- ieee := NewIEEE()
- io.WriteString(ieee, g.in)
- s := ieee.Sum32()
- if s != g.ieee {
- t.Errorf("IEEE(%s) = 0x%x want 0x%x", g.in, s, g.ieee)
+ if crc := crcFunc([]byte(g.in)); crc != g.castagnoli {
+ t.Errorf("Castagnoli(%s) = 0x%x want 0x%x", g.in, crc, g.castagnoli)
}
+ }
+}
- castagnoli := New(castagnoliTab)
- io.WriteString(castagnoli, g.in)
- s = castagnoli.Sum32()
- if s != g.castagnoli {
- t.Errorf("Castagnoli(%s) = 0x%x want 0x%x", g.in, s, g.castagnoli)
+// testCrossCheck generates random buffers of various lengths and verifies that
+// the two "update" functions return the same result.
+func testCrossCheck(t *testing.T, crcFunc1, crcFunc2 func(crc uint32, b []byte) uint32) {
+ // The AMD64 implementation has some cutoffs at lengths 168*3=504 and
+ // 1344*3=4032. We should make sure lengths around these values are in the
+ // list.
+ lengths := []int{0, 1, 2, 3, 4, 5, 10, 16, 50, 100, 128,
+ 500, 501, 502, 503, 504, 505, 512, 1000, 1024, 2000,
+ 4030, 4031, 4032, 4033, 4036, 4040, 4048, 4096, 5000, 10000}
+ for _, length := range lengths {
+ p := make([]byte, length)
+ _, _ = rand.Read(p)
+ crcInit := uint32(rand.Int63())
+ crc1 := crcFunc1(crcInit, p)
+ crc2 := crcFunc2(crcInit, p)
+ if crc1 != crc2 {
+ t.Errorf("mismatch: 0x%x vs 0x%x (buffer length %d)", crc1, crc2, length)
}
+ }
+}
- if len(g.in) > 0 {
- // The SSE4.2 implementation of this has code to deal
- // with misaligned data so we ensure that we test that
- // too.
- castagnoli = New(castagnoliTab)
- io.WriteString(castagnoli, g.in[:1])
- io.WriteString(castagnoli, g.in[1:])
- s = castagnoli.Sum32()
- if s != g.castagnoli {
- t.Errorf("Castagnoli[misaligned](%s) = 0x%x want 0x%x", g.in, s, g.castagnoli)
- }
+// TestSimple tests the simple generic algorithm.
+func TestSimple(t *testing.T) {
+ tab := simpleMakeTable(IEEE)
+ testGoldenIEEE(t, func(b []byte) uint32 {
+ return simpleUpdate(0, tab, b)
+ })
+
+ tab = simpleMakeTable(Castagnoli)
+ testGoldenCastagnoli(t, func(b []byte) uint32 {
+ return simpleUpdate(0, tab, b)
+ })
+}
+
+// TestSimple tests the slicing-by-8 algorithm.
+func TestSlicing(t *testing.T) {
+ tab := slicingMakeTable(IEEE)
+ testGoldenIEEE(t, func(b []byte) uint32 {
+ return slicingUpdate(0, tab, b)
+ })
+
+ tab = slicingMakeTable(Castagnoli)
+ testGoldenCastagnoli(t, func(b []byte) uint32 {
+ return slicingUpdate(0, tab, b)
+ })
+
+ // Cross-check various polys against the simple algorithm.
+ for _, poly := range []uint32{IEEE, Castagnoli, Koopman, 0xD5828281} {
+ t1 := simpleMakeTable(poly)
+ f1 := func(crc uint32, b []byte) uint32 {
+ return simpleUpdate(crc, t1, b)
+ }
+ t2 := slicingMakeTable(poly)
+ f2 := func(crc uint32, b []byte) uint32 {
+ return slicingUpdate(crc, t2, b)
}
+ testCrossCheck(t, f1, f2)
+ }
+}
+
+func TestArchIEEE(t *testing.T) {
+ if !archAvailableIEEE() {
+ t.Skip("Arch-specific IEEE not available.")
+ }
+ archInitIEEE()
+ slicingTable := slicingMakeTable(IEEE)
+ testCrossCheck(t, archUpdateIEEE, func(crc uint32, b []byte) uint32 {
+ return slicingUpdate(crc, slicingTable, b)
+ })
+}
+
+func TestArchCastagnoli(t *testing.T) {
+ if !archAvailableCastagnoli() {
+ t.Skip("Arch-specific Castagnoli not available.")
+ }
+ archInitCastagnoli()
+ slicingTable := slicingMakeTable(Castagnoli)
+ testCrossCheck(t, archUpdateCastagnoli, func(crc uint32, b []byte) uint32 {
+ return slicingUpdate(crc, slicingTable, b)
+ })
+}
+
+func TestGolden(t *testing.T) {
+ testGoldenIEEE(t, ChecksumIEEE)
+
+ // Some implementations have special code to deal with misaligned
+ // data; test that as well.
+ for delta := 1; delta <= 7; delta++ {
+ testGoldenIEEE(t, func(b []byte) uint32 {
+ ieee := NewIEEE()
+ d := delta
+ if d >= len(b) {
+ d = len(b)
+ }
+ ieee.Write(b[:d])
+ ieee.Write(b[d:])
+ return ieee.Sum32()
+ })
+ }
+
+ castagnoliTab := MakeTable(Castagnoli)
+ if castagnoliTab == nil {
+ t.Errorf("nil Castagnoli Table")
+ }
+
+ testGoldenCastagnoli(t, func(b []byte) uint32 {
+ castagnoli := New(castagnoliTab)
+ castagnoli.Write(b)
+ return castagnoli.Sum32()
+ })
+
+ // Some implementations have special code to deal with misaligned
+ // data; test that as well.
+ for delta := 1; delta <= 7; delta++ {
+ testGoldenCastagnoli(t, func(b []byte) uint32 {
+ castagnoli := New(castagnoliTab)
+ d := delta
+ if d >= len(b) {
+ d = len(b)
+ }
+ castagnoli.Write(b[:d])
+ castagnoli.Write(b[d:])
+ return castagnoli.Sum32()
+ })
}
}
func BenchmarkIEEECrc40B(b *testing.B) {
- benchmark(b, NewIEEE(), 40)
+ benchmark(b, NewIEEE(), 40, 0)
}
func BenchmarkIEEECrc1KB(b *testing.B) {
- benchmark(b, NewIEEE(), 1<<10)
+ benchmark(b, NewIEEE(), 1<<10, 0)
}
func BenchmarkIEEECrc4KB(b *testing.B) {
- benchmark(b, NewIEEE(), 4<<10)
+ benchmark(b, NewIEEE(), 4<<10, 0)
}
func BenchmarkIEEECrc32KB(b *testing.B) {
- benchmark(b, NewIEEE(), 32<<10)
+ benchmark(b, NewIEEE(), 32<<10, 0)
+}
+
+func BenchmarkCastagnoliCrc15B(b *testing.B) {
+ benchmark(b, New(MakeTable(Castagnoli)), 15, 0)
+}
+
+func BenchmarkCastagnoliCrc15BMisaligned(b *testing.B) {
+ benchmark(b, New(MakeTable(Castagnoli)), 15, 1)
}
func BenchmarkCastagnoliCrc40B(b *testing.B) {
- benchmark(b, New(MakeTable(Castagnoli)), 40)
+ benchmark(b, New(MakeTable(Castagnoli)), 40, 0)
+}
+
+func BenchmarkCastagnoliCrc40BMisaligned(b *testing.B) {
+ benchmark(b, New(MakeTable(Castagnoli)), 40, 1)
+}
+
+func BenchmarkCastagnoliCrc512(b *testing.B) {
+ benchmark(b, New(MakeTable(Castagnoli)), 512, 0)
+}
+
+func BenchmarkCastagnoliCrc512Misaligned(b *testing.B) {
+ benchmark(b, New(MakeTable(Castagnoli)), 512, 1)
}
func BenchmarkCastagnoliCrc1KB(b *testing.B) {
- benchmark(b, New(MakeTable(Castagnoli)), 1<<10)
+ benchmark(b, New(MakeTable(Castagnoli)), 1<<10, 0)
+}
+
+func BenchmarkCastagnoliCrc1KBMisaligned(b *testing.B) {
+ benchmark(b, New(MakeTable(Castagnoli)), 1<<10, 1)
}
func BenchmarkCastagnoliCrc4KB(b *testing.B) {
- benchmark(b, New(MakeTable(Castagnoli)), 4<<10)
+ benchmark(b, New(MakeTable(Castagnoli)), 4<<10, 0)
+}
+
+func BenchmarkCastagnoliCrc4KBMisaligned(b *testing.B) {
+ benchmark(b, New(MakeTable(Castagnoli)), 4<<10, 1)
}
func BenchmarkCastagnoliCrc32KB(b *testing.B) {
- benchmark(b, New(MakeTable(Castagnoli)), 32<<10)
+ benchmark(b, New(MakeTable(Castagnoli)), 32<<10, 0)
+}
+
+func BenchmarkCastagnoliCrc32KBMisaligned(b *testing.B) {
+ benchmark(b, New(MakeTable(Castagnoli)), 32<<10, 1)
}
-func benchmark(b *testing.B, h hash.Hash32, n int64) {
+func benchmark(b *testing.B, h hash.Hash32, n, alignment int64) {
b.SetBytes(n)
- data := make([]byte, n)
+ data := make([]byte, n+alignment)
+ data = data[alignment:]
for i := range data {
data[i] = byte(i)
}
diff --git a/libgo/go/html/template/clone_test.go b/libgo/go/html/template/clone_test.go
index d7c62fa3993..b500715ac6e 100644
--- a/libgo/go/html/template/clone_test.go
+++ b/libgo/go/html/template/clone_test.go
@@ -7,7 +7,9 @@ package template
import (
"bytes"
"errors"
+ "fmt"
"io/ioutil"
+ "sync"
"testing"
"text/template/parse"
)
@@ -194,3 +196,69 @@ func TestFuncMapWorksAfterClone(t *testing.T) {
t.Errorf("clone error message mismatch want %q got %q", wantErr, gotErr)
}
}
+
+// https://golang.org/issue/16101
+func TestTemplateCloneExecuteRace(t *testing.T) {
+ const (
+ input = `<title>{{block "a" .}}a{{end}}</title><body>{{block "b" .}}b{{end}}<body>`
+ overlay = `{{define "b"}}A{{end}}`
+ )
+ outer := Must(New("outer").Parse(input))
+ tmpl := Must(Must(outer.Clone()).Parse(overlay))
+
+ var wg sync.WaitGroup
+ for i := 0; i < 10; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ for i := 0; i < 100; i++ {
+ if err := tmpl.Execute(ioutil.Discard, "data"); err != nil {
+ panic(err)
+ }
+ }
+ }()
+ }
+ wg.Wait()
+}
+
+func TestTemplateCloneLookup(t *testing.T) {
+ // Template.escape makes an assumption that the template associated
+ // with t.Name() is t. Check that this holds.
+ tmpl := Must(New("x").Parse("a"))
+ tmpl = Must(tmpl.Clone())
+ if tmpl.Lookup(tmpl.Name()) != tmpl {
+ t.Error("after Clone, tmpl.Lookup(tmpl.Name()) != tmpl")
+ }
+}
+
+func TestCloneGrowth(t *testing.T) {
+ tmpl := Must(New("root").Parse(`<title>{{block "B". }}Arg{{end}}</title>`))
+ tmpl = Must(tmpl.Clone())
+ Must(tmpl.Parse(`{{define "B"}}Text{{end}}`))
+ for i := 0; i < 10; i++ {
+ tmpl.Execute(ioutil.Discard, nil)
+ }
+ if len(tmpl.DefinedTemplates()) > 200 {
+ t.Fatalf("too many templates: %v", len(tmpl.DefinedTemplates()))
+ }
+}
+
+// https://golang.org/issue/17735
+func TestCloneRedefinedName(t *testing.T) {
+ const base = `
+{{ define "a" -}}<title>{{ template "b" . -}}</title>{{ end -}}
+{{ define "b" }}{{ end -}}
+`
+ const page = `{{ template "a" . }}`
+
+ t1 := Must(New("a").Parse(base))
+
+ for i := 0; i < 2; i++ {
+ t2 := Must(t1.Clone())
+ t2 = Must(t2.New(fmt.Sprintf("%d", i)).Parse(page))
+ err := t2.Execute(ioutil.Discard, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+}
diff --git a/libgo/go/html/template/content_test.go b/libgo/go/html/template/content_test.go
index e698328693e..0b4365c83ba 100644
--- a/libgo/go/html/template/content_test.go
+++ b/libgo/go/html/template/content_test.go
@@ -162,6 +162,47 @@ func TestTypedContent(t *testing.T) {
},
},
{
+ `<script type="text/javascript">alert("{{.}}")</script>`,
+ []string{
+ `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
+ `a[href =~ \x22\/\/example.com\x22]#foo`,
+ `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
+ ` dir=\x22ltr\x22`,
+ `c \x26\x26 alert(\x22Hello, World!\x22);`,
+ // Escape sequence not over-escaped.
+ `Hello, World \x26 O\x27Reilly\x21`,
+ `greeting=H%69\x26addressee=(World)`,
+ },
+ },
+ {
+ `<script type="text/javascript">alert({{.}})</script>`,
+ []string{
+ `"\u003cb\u003e \"foo%\" O'Reilly \u0026bar;"`,
+ `"a[href =~ \"//example.com\"]#foo"`,
+ `"Hello, \u003cb\u003eWorld\u003c/b\u003e \u0026amp;tc!"`,
+ `" dir=\"ltr\""`,
+ // Not escaped.
+ `c && alert("Hello, World!");`,
+ // Escape sequence not over-escaped.
+ `"Hello, World & O'Reilly\x21"`,
+ `"greeting=H%69\u0026addressee=(World)"`,
+ },
+ },
+ {
+ // Not treated as JS. The output is same as for <div>{{.}}</div>
+ `<script type="text/template">{{.}}</script>`,
+ []string{
+ `&lt;b&gt; &#34;foo%&#34; O&#39;Reilly &amp;bar;`,
+ `a[href =~ &#34;//example.com&#34;]#foo`,
+ // Not escaped.
+ `Hello, <b>World</b> &amp;tc!`,
+ ` dir=&#34;ltr&#34;`,
+ `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
+ `Hello, World &amp; O&#39;Reilly\x21`,
+ `greeting=H%69&amp;addressee=(World)`,
+ },
+ },
+ {
`<button onclick='alert("{{.}}")'>`,
[]string{
`\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
diff --git a/libgo/go/html/template/context.go b/libgo/go/html/template/context.go
index c90fc1fda5d..37a3faf88b9 100644
--- a/libgo/go/html/template/context.go
+++ b/libgo/go/html/template/context.go
@@ -285,7 +285,8 @@ type element uint8
const (
// elementNone occurs outside a special tag or special element body.
elementNone element = iota
- // elementScript corresponds to the raw text <script> element.
+ // elementScript corresponds to the raw text <script> element
+ // with JS MIME type or no type attribute.
elementScript
// elementStyle corresponds to the raw text <style> element.
elementStyle
@@ -319,6 +320,8 @@ const (
attrNone attr = iota
// attrScript corresponds to an event handler attribute.
attrScript
+ // attrScriptType corresponds to the type attribute in script HTML element
+ attrScriptType
// attrStyle corresponds to the style attribute whose value is CSS.
attrStyle
// attrURL corresponds to an attribute whose value is a URL.
@@ -326,10 +329,11 @@ const (
)
var attrNames = [...]string{
- attrNone: "attrNone",
- attrScript: "attrScript",
- attrStyle: "attrStyle",
- attrURL: "attrURL",
+ attrNone: "attrNone",
+ attrScript: "attrScript",
+ attrScriptType: "attrScriptType",
+ attrStyle: "attrStyle",
+ attrURL: "attrURL",
}
func (a attr) String() string {
diff --git a/libgo/go/html/template/doc.go b/libgo/go/html/template/doc.go
index e1e9cad0af7..cb898127432 100644
--- a/libgo/go/html/template/doc.go
+++ b/libgo/go/html/template/doc.go
@@ -129,7 +129,7 @@ then the template output is
<script>var pair = {"A": "foo", "B": "bar"};</script>
-See package json to understand how non-string content is marshalled for
+See package json to understand how non-string content is marshaled for
embedding in JavaScript contexts.
diff --git a/libgo/go/html/template/error.go b/libgo/go/html/template/error.go
index 5637384bd86..cbcaf92e4ab 100644
--- a/libgo/go/html/template/error.go
+++ b/libgo/go/html/template/error.go
@@ -44,7 +44,7 @@ const (
// OK indicates the lack of an error.
OK ErrorCode = iota
- // ErrAmbigContext: "... appears in an ambiguous URL context"
+ // ErrAmbigContext: "... appears in an ambiguous context within a URL"
// Example:
// <a href="
// {{if .C}}
diff --git a/libgo/go/html/template/escape.go b/libgo/go/html/template/escape.go
index 8f2fe460de6..0e7d2be143b 100644
--- a/libgo/go/html/template/escape.go
+++ b/libgo/go/html/template/escape.go
@@ -161,7 +161,7 @@ func (e *escaper) escapeAction(c context, n *parse.ActionNode) context {
case urlPartUnknown:
return context{
state: stateError,
- err: errorf(ErrAmbigContext, n, n.Line, "%s appears in an ambiguous URL context", n),
+ err: errorf(ErrAmbigContext, n, n.Line, "%s appears in an ambiguous context within a URL", n),
}
default:
panic(c.urlPart.String())
@@ -673,6 +673,8 @@ func contextAfterText(c context, s []byte) (context, int) {
return transitionFunc[c.state](c, s[:i])
}
+ // We are at the beginning of an attribute value.
+
i := bytes.IndexAny(s, delimEnds[c.delim])
if i == -1 {
i = len(s)
@@ -703,13 +705,21 @@ func contextAfterText(c context, s []byte) (context, int) {
}
return c, len(s)
}
+
+ element := c.element
+
+ // If this is a non-JS "type" attribute inside "script" tag, do not treat the contents as JS.
+ if c.state == stateAttr && c.element == elementScript && c.attr == attrScriptType && !isJSType(string(s[:i])) {
+ element = elementNone
+ }
+
if c.delim != delimSpaceOrTagEnd {
// Consume any quote.
i++
}
// On exiting an attribute, we discard all state information
// except the state and element.
- return context{state: stateTag, element: c.element}, i
+ return context{state: stateTag, element: element}, i
}
// editActionNode records a change to an action pipeline for later commit.
diff --git a/libgo/go/html/template/escape_test.go b/libgo/go/html/template/escape_test.go
index 023ee57d597..f6ace496e7b 100644
--- a/libgo/go/html/template/escape_test.go
+++ b/libgo/go/html/template/escape_test.go
@@ -903,7 +903,7 @@ func TestErrors(t *testing.T) {
},
{
`<a href="{{if .F}}/foo?a={{else}}/bar/{{end}}{{.H}}">`,
- "z:1:47: {{.H}} appears in an ambiguous URL context",
+ "z:1:47: {{.H}} appears in an ambiguous context within a URL",
},
{
`<a onclick="alert('Hello \`,
@@ -1365,6 +1365,10 @@ func TestEscapeText(t *testing.T) {
context{state: stateTag, element: elementScript},
},
{
+ `<script>`,
+ context{state: stateJS, jsCtx: jsCtxRegexp, element: elementScript},
+ },
+ {
`<script>foo`,
context{state: stateJS, jsCtx: jsCtxDivOp, element: elementScript},
},
@@ -1389,6 +1393,14 @@ func TestEscapeText(t *testing.T) {
context{state: stateText},
},
{
+ `<script type="text/template">`,
+ context{state: stateText},
+ },
+ {
+ `<script type="notjs">`,
+ context{state: stateText},
+ },
+ {
`<Script>`,
context{state: stateJS, element: elementScript},
},
diff --git a/libgo/go/html/template/js.go b/libgo/go/html/template/js.go
index f6d166b3113..6434fa3be63 100644
--- a/libgo/go/html/template/js.go
+++ b/libgo/go/html/template/js.go
@@ -162,14 +162,14 @@ func jsValEscaper(args ...interface{}) string {
// a division operator it is not turned into a line comment:
// x/{{y}}
// turning into
- // x//* error marshalling y:
+ // x//* error marshaling y:
// second line of error message */null
return fmt.Sprintf(" /* %s */null ", strings.Replace(err.Error(), "*/", "* /", -1))
}
// TODO: maybe post-process output to prevent it from containing
// "<!--", "-->", "<![CDATA[", "]]>", or "</script"
- // in case custom marshallers produce output containing those.
+ // in case custom marshalers produce output containing those.
// TODO: Maybe abbreviate \u00ab to \xab to produce more compact output.
if len(b) == 0 {
@@ -362,3 +362,43 @@ func isJSIdentPart(r rune) bool {
}
return false
}
+
+// isJSType returns true if the given MIME type should be considered JavaScript.
+//
+// It is used to determine whether a script tag with a type attribute is a javascript container.
+func isJSType(mimeType string) bool {
+ // per
+ // https://www.w3.org/TR/html5/scripting-1.html#attr-script-type
+ // https://tools.ietf.org/html/rfc7231#section-3.1.1
+ // https://tools.ietf.org/html/rfc4329#section-3
+ // https://www.ietf.org/rfc/rfc4627.txt
+
+ // discard parameters
+ if i := strings.Index(mimeType, ";"); i >= 0 {
+ mimeType = mimeType[:i]
+ }
+ mimeType = strings.TrimSpace(mimeType)
+ switch mimeType {
+ case
+ "application/ecmascript",
+ "application/javascript",
+ "application/json",
+ "application/x-ecmascript",
+ "application/x-javascript",
+ "text/ecmascript",
+ "text/javascript",
+ "text/javascript1.0",
+ "text/javascript1.1",
+ "text/javascript1.2",
+ "text/javascript1.3",
+ "text/javascript1.4",
+ "text/javascript1.5",
+ "text/jscript",
+ "text/livescript",
+ "text/x-ecmascript",
+ "text/x-javascript":
+ return true
+ default:
+ return false
+ }
+}
diff --git a/libgo/go/html/template/js_test.go b/libgo/go/html/template/js_test.go
index 7af7997de9b..7484f60b54d 100644
--- a/libgo/go/html/template/js_test.go
+++ b/libgo/go/html/template/js_test.go
@@ -332,6 +332,25 @@ func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) {
}
}
+func TestIsJsMimeType(t *testing.T) {
+ tests := []struct {
+ in string
+ out bool
+ }{
+ {"application/javascript;version=1.8", true},
+ {"application/javascript;version=1.8;foo=bar", true},
+ {"application/javascript/version=1.8", false},
+ {"text/javascript", true},
+ {"application/json", true},
+ }
+
+ for _, test := range tests {
+ if isJSType(test.in) != test.out {
+ t.Errorf("isJSType(%q) = %v, want %v", test.in, !test.out, test.out)
+ }
+ }
+}
+
func BenchmarkJSValEscaperWithNum(b *testing.B) {
for i := 0; i < b.N; i++ {
jsValEscaper(3.141592654)
diff --git a/libgo/go/html/template/template.go b/libgo/go/html/template/template.go
index 063e46d6bf3..b313a6b104a 100644
--- a/libgo/go/html/template/template.go
+++ b/libgo/go/html/template/template.go
@@ -33,8 +33,9 @@ var escapeOK = fmt.Errorf("template escaped correctly")
// nameSpace is the data structure shared by all templates in an association.
type nameSpace struct {
- mu sync.Mutex
- set map[string]*Template
+ mu sync.Mutex
+ set map[string]*Template
+ escaped bool
}
// Templates returns a slice of the templates associated with t, including t
@@ -74,13 +75,28 @@ func (t *Template) Option(opt ...string) *Template {
return t
}
+// checkCanParse checks whether it is OK to parse templates.
+// If not, it returns an error.
+func (t *Template) checkCanParse() error {
+ if t == nil {
+ return nil
+ }
+ t.nameSpace.mu.Lock()
+ defer t.nameSpace.mu.Unlock()
+ if t.nameSpace.escaped {
+ return fmt.Errorf("html/template: cannot Parse after Execute")
+ }
+ return nil
+}
+
// escape escapes all associated templates.
func (t *Template) escape() error {
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
+ t.nameSpace.escaped = true
if t.escapeErr == nil {
if t.Tree == nil {
- return fmt.Errorf("template: %q is an incomplete or empty template%s", t.Name(), t.DefinedTemplates())
+ return fmt.Errorf("template: %q is an incomplete or empty template", t.Name())
}
if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil {
return err
@@ -124,6 +140,7 @@ func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{})
func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err error) {
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
+ t.nameSpace.escaped = true
tmpl = t.set[name]
if tmpl == nil {
return nil, fmt.Errorf("html/template: %q is undefined", name)
@@ -150,22 +167,27 @@ func (t *Template) DefinedTemplates() string {
return t.text.DefinedTemplates()
}
-// Parse parses a string into a template. Nested template definitions
-// will be associated with the top-level template t. Parse may be
-// called multiple times to parse definitions of templates to associate
-// with t. It is an error if a resulting template is non-empty (contains
-// content other than template definitions) and would replace a
-// non-empty template with the same name. (In multiple calls to Parse
-// with the same receiver template, only one call can contain text
-// other than space, comments, and template definitions.)
-func (t *Template) Parse(src string) (*Template, error) {
- t.nameSpace.mu.Lock()
- t.escapeErr = nil
- t.nameSpace.mu.Unlock()
- ret, err := t.text.Parse(src)
+// Parse parses text as a template body for t.
+// Named template definitions ({{define ...}} or {{block ...}} statements) in text
+// define additional templates associated with t and are removed from the
+// definition of t itself.
+//
+// Templates can be redefined in successive calls to Parse,
+// before the first use of Execute on t or any associated template.
+// A template definition with a body containing only white space and comments
+// is considered empty and will not replace an existing template's body.
+// This allows using Parse to add new named template definitions without
+// overwriting the main template body.
+func (t *Template) Parse(text string) (*Template, error) {
+ if err := t.checkCanParse(); err != nil {
+ return nil, err
+ }
+
+ ret, err := t.text.Parse(text)
if err != nil {
return nil, err
}
+
// In general, all the named templates might have changed underfoot.
// Regardless, some new ones may have been defined.
// The template.Template set has been updated; update ours.
@@ -176,11 +198,7 @@ func (t *Template) Parse(src string) (*Template, error) {
tmpl := t.set[name]
if tmpl == nil {
tmpl = t.new(name)
- } else if tmpl.escapeErr != nil {
- return nil, fmt.Errorf("html/template: cannot redefine %q after it has executed", name)
}
- // Restore our record of this text/template to its unescaped original state.
- tmpl.escapeErr = nil
tmpl.text = v
tmpl.Tree = v.Tree
}
@@ -190,13 +208,14 @@ func (t *Template) Parse(src string) (*Template, error) {
// AddParseTree creates a new template with the name and parse tree
// and associates it with t.
//
-// It returns an error if t has already been executed.
+// It returns an error if t or any associated template has already been executed.
func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
+ if err := t.checkCanParse(); err != nil {
+ return nil, err
+ }
+
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
- if t.escapeErr != nil {
- return nil, fmt.Errorf("html/template: cannot AddParseTree to %q after it has executed", t.Name())
- }
text, err := t.text.AddParseTree(name, tree)
if err != nil {
return nil, err
@@ -252,7 +271,8 @@ func (t *Template) Clone() (*Template, error) {
ret.nameSpace,
}
}
- return ret, nil
+ // Return the template associated with the name of this template.
+ return ret.set[ret.Name()], nil
}
// New allocates a new HTML template with the given name.
@@ -361,6 +381,8 @@ func ParseFiles(filenames ...string) (*Template, error) {
//
// When parsing multiple files with the same name in different directories,
// the last one mentioned will be the one that results.
+//
+// ParseFiles returns an error if t or any associated template has already been executed.
func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
return parseFiles(t, filenames...)
}
@@ -368,6 +390,10 @@ func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
// parseFiles is the helper for the method and function. If the argument
// template is nil, it is created from the first file.
func parseFiles(t *Template, filenames ...string) (*Template, error) {
+ if err := t.checkCanParse(); err != nil {
+ return nil, err
+ }
+
if len(filenames) == 0 {
// Not really a problem, but be consistent.
return nil, fmt.Errorf("html/template: no files named in call to ParseFiles")
@@ -422,12 +448,17 @@ func ParseGlob(pattern string) (*Template, error) {
//
// When parsing multiple files with the same name in different directories,
// the last one mentioned will be the one that results.
+//
+// ParseGlob returns an error if t or any associated template has already been executed.
func (t *Template) ParseGlob(pattern string) (*Template, error) {
return parseGlob(t, pattern)
}
// parseGlob is the implementation of the function and method ParseGlob.
func parseGlob(t *Template, pattern string) (*Template, error) {
+ if err := t.checkCanParse(); err != nil {
+ return nil, err
+ }
filenames, err := filepath.Glob(pattern)
if err != nil {
return nil, err
diff --git a/libgo/go/html/template/template_test.go b/libgo/go/html/template/template_test.go
index 46df1f8d495..90c5a73ba7a 100644
--- a/libgo/go/html/template/template_test.go
+++ b/libgo/go/html/template/template_test.go
@@ -1,7 +1,13 @@
-package template
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package template_test
import (
"bytes"
+ . "html/template"
+ "strings"
"testing"
)
@@ -27,3 +33,125 @@ func TestTemplateClone(t *testing.T) {
t.Fatalf("got %q; want %q", got, want)
}
}
+
+func TestRedefineNonEmptyAfterExecution(t *testing.T) {
+ c := newTestCase(t)
+ c.mustParse(c.root, `foo`)
+ c.mustExecute(c.root, nil, "foo")
+ c.mustNotParse(c.root, `bar`)
+}
+
+func TestRedefineEmptyAfterExecution(t *testing.T) {
+ c := newTestCase(t)
+ c.mustParse(c.root, ``)
+ c.mustExecute(c.root, nil, "")
+ c.mustNotParse(c.root, `foo`)
+ c.mustExecute(c.root, nil, "")
+}
+
+func TestRedefineAfterNonExecution(t *testing.T) {
+ c := newTestCase(t)
+ c.mustParse(c.root, `{{if .}}<{{template "X"}}>{{end}}{{define "X"}}foo{{end}}`)
+ c.mustExecute(c.root, 0, "")
+ c.mustNotParse(c.root, `{{define "X"}}bar{{end}}`)
+ c.mustExecute(c.root, 1, "&lt;foo>")
+}
+
+func TestRedefineAfterNamedExecution(t *testing.T) {
+ c := newTestCase(t)
+ c.mustParse(c.root, `<{{template "X" .}}>{{define "X"}}foo{{end}}`)
+ c.mustExecute(c.root, nil, "&lt;foo>")
+ c.mustNotParse(c.root, `{{define "X"}}bar{{end}}`)
+ c.mustExecute(c.root, nil, "&lt;foo>")
+}
+
+func TestRedefineNestedByNameAfterExecution(t *testing.T) {
+ c := newTestCase(t)
+ c.mustParse(c.root, `{{define "X"}}foo{{end}}`)
+ c.mustExecute(c.lookup("X"), nil, "foo")
+ c.mustNotParse(c.root, `{{define "X"}}bar{{end}}`)
+ c.mustExecute(c.lookup("X"), nil, "foo")
+}
+
+func TestRedefineNestedByTemplateAfterExecution(t *testing.T) {
+ c := newTestCase(t)
+ c.mustParse(c.root, `{{define "X"}}foo{{end}}`)
+ c.mustExecute(c.lookup("X"), nil, "foo")
+ c.mustNotParse(c.lookup("X"), `bar`)
+ c.mustExecute(c.lookup("X"), nil, "foo")
+}
+
+func TestRedefineSafety(t *testing.T) {
+ c := newTestCase(t)
+ c.mustParse(c.root, `<html><a href="{{template "X"}}">{{define "X"}}{{end}}`)
+ c.mustExecute(c.root, nil, `<html><a href="">`)
+ // Note: Every version of Go prior to Go 1.8 accepted the redefinition of "X"
+ // on the next line, but luckily kept it from being used in the outer template.
+ // Now we reject it, which makes clearer that we're not going to use it.
+ c.mustNotParse(c.root, `{{define "X"}}" bar="baz{{end}}`)
+ c.mustExecute(c.root, nil, `<html><a href="">`)
+}
+
+func TestRedefineTopUse(t *testing.T) {
+ c := newTestCase(t)
+ c.mustParse(c.root, `{{template "X"}}{{.}}{{define "X"}}{{end}}`)
+ c.mustExecute(c.root, 42, `42`)
+ c.mustNotParse(c.root, `{{define "X"}}<script>{{end}}`)
+ c.mustExecute(c.root, 42, `42`)
+}
+
+func TestRedefineOtherParsers(t *testing.T) {
+ c := newTestCase(t)
+ c.mustParse(c.root, ``)
+ c.mustExecute(c.root, nil, ``)
+ if _, err := c.root.ParseFiles("no.template"); err == nil || !strings.Contains(err.Error(), "Execute") {
+ t.Errorf("ParseFiles: %v\nwanted error about already having Executed", err)
+ }
+ if _, err := c.root.ParseGlob("*.no.template"); err == nil || !strings.Contains(err.Error(), "Execute") {
+ t.Errorf("ParseGlob: %v\nwanted error about already having Executed", err)
+ }
+ if _, err := c.root.AddParseTree("t1", c.root.Tree); err == nil || !strings.Contains(err.Error(), "Execute") {
+ t.Errorf("AddParseTree: %v\nwanted error about already having Executed", err)
+ }
+}
+
+type testCase struct {
+ t *testing.T
+ root *Template
+}
+
+func newTestCase(t *testing.T) *testCase {
+ return &testCase{
+ t: t,
+ root: New("root"),
+ }
+}
+
+func (c *testCase) lookup(name string) *Template {
+ return c.root.Lookup(name)
+}
+
+func (c *testCase) mustParse(t *Template, text string) {
+ _, err := t.Parse(text)
+ if err != nil {
+ c.t.Fatalf("parse: %v", err)
+ }
+}
+
+func (c *testCase) mustNotParse(t *Template, text string) {
+ _, err := t.Parse(text)
+ if err == nil {
+ c.t.Fatalf("parse: unexpected success")
+ }
+}
+
+func (c *testCase) mustExecute(t *Template, val interface{}, want string) {
+ var buf bytes.Buffer
+ err := t.Execute(&buf, val)
+ if err != nil {
+ c.t.Fatalf("execute: %v", err)
+ }
+ if buf.String() != want {
+ c.t.Fatalf("template output:\n%s\nwant:\n%s", buf.String(), want)
+ }
+}
diff --git a/libgo/go/html/template/transition.go b/libgo/go/html/template/transition.go
index aefe0355af4..4a4716d7820 100644
--- a/libgo/go/html/template/transition.go
+++ b/libgo/go/html/template/transition.go
@@ -105,14 +105,21 @@ func tTag(c context, s []byte) (context, int) {
err: errorf(ErrBadHTML, nil, 0, "expected space, attr name, or end of tag, but got %q", s[i:]),
}, len(s)
}
- switch attrType(string(s[i:j])) {
- case contentTypeURL:
- attr = attrURL
- case contentTypeCSS:
- attr = attrStyle
- case contentTypeJS:
- attr = attrScript
+
+ attrName := string(s[i:j])
+ if c.element == elementScript && attrName == "type" {
+ attr = attrScriptType
+ } else {
+ switch attrType(attrName) {
+ case contentTypeURL:
+ attr = attrURL
+ case contentTypeCSS:
+ attr = attrStyle
+ case contentTypeJS:
+ attr = attrScript
+ }
}
+
if j == len(s) {
state = stateAttrName
} else {
@@ -149,10 +156,11 @@ func tAfterName(c context, s []byte) (context, int) {
}
var attrStartStates = [...]state{
- attrNone: stateAttr,
- attrScript: stateJS,
- attrStyle: stateCSS,
- attrURL: stateURL,
+ attrNone: stateAttr,
+ attrScript: stateJS,
+ attrScriptType: stateAttr,
+ attrStyle: stateCSS,
+ attrURL: stateURL,
}
// tBeforeValue is the context transition function for stateBeforeValue.
diff --git a/libgo/go/html/template/url.go b/libgo/go/html/template/url.go
index 246bfd32cd5..02123b2cccd 100644
--- a/libgo/go/html/template/url.go
+++ b/libgo/go/html/template/url.go
@@ -32,7 +32,7 @@ func urlEscaper(args ...interface{}) string {
return urlProcessor(false, args...)
}
-// urlEscaper normalizes URL content so it can be embedded in a quote-delimited
+// urlNormalizer normalizes URL content so it can be embedded in a quote-delimited
// string or parenthesis delimited url(...).
// The normalizer does not encode all HTML specials. Specifically, it does not
// encode '&' so correct embedding in an HTML attribute requires escaping of
diff --git a/libgo/go/image/color/color.go b/libgo/go/image/color/color.go
index 104433974ea..0832c597293 100644
--- a/libgo/go/image/color/color.go
+++ b/libgo/go/image/color/color.go
@@ -246,8 +246,18 @@ func grayModel(c Color) Color {
return c
}
r, g, b, _ := c.RGBA()
- y := (299*r + 587*g + 114*b + 500) / 1000
- return Gray{uint8(y >> 8)}
+
+ // These coefficients (the fractions 0.299, 0.587 and 0.114) are the same
+ // as those given by the JFIF specification and used by func RGBToYCbCr in
+ // ycbcr.go.
+ //
+ // Note that 19595 + 38470 + 7471 equals 65536.
+ //
+ // The 24 is 16 + 8. The 16 is the same as used in RGBToYCbCr. The 8 is
+ // because the return value is 8 bit color, not 16 bit color.
+ y := (19595*r + 38470*g + 7471*b + 1<<15) >> 24
+
+ return Gray{uint8(y)}
}
func gray16Model(c Color) Color {
@@ -255,7 +265,14 @@ func gray16Model(c Color) Color {
return c
}
r, g, b, _ := c.RGBA()
- y := (299*r + 587*g + 114*b + 500) / 1000
+
+ // These coefficients (the fractions 0.299, 0.587 and 0.114) are the same
+ // as those given by the JFIF specification and used by func RGBToYCbCr in
+ // ycbcr.go.
+ //
+ // Note that 19595 + 38470 + 7471 equals 65536.
+ y := (19595*r + 38470*g + 7471*b + 1<<15) >> 16
+
return Gray16{uint16(y)}
}
diff --git a/libgo/go/image/color/ycbcr.go b/libgo/go/image/color/ycbcr.go
index 3df5d3675d6..18d1a568aac 100644
--- a/libgo/go/image/color/ycbcr.go
+++ b/libgo/go/image/color/ycbcr.go
@@ -17,6 +17,8 @@ func RGBToYCbCr(r, g, b uint8) (uint8, uint8, uint8) {
b1 := int32(b)
// yy is in range [0,0xff].
+ //
+ // Note that 19595 + 38470 + 7471 equals 65536.
yy := (19595*r1 + 38470*g1 + 7471*b1 + 1<<15) >> 16
// The bit twiddling below is equivalent to
@@ -32,6 +34,8 @@ func RGBToYCbCr(r, g, b uint8) (uint8, uint8, uint8) {
// Note that the uint8 type conversion in the return
// statement will convert ^int32(0) to 0xff.
// The code below to compute cr uses a similar pattern.
+ //
+ // Note that -11056 - 21712 + 32768 equals 0.
cb := -11056*r1 - 21712*g1 + 32768*b1 + 257<<15
if uint32(cb)&0xff000000 == 0 {
cb >>= 16
@@ -39,6 +43,7 @@ func RGBToYCbCr(r, g, b uint8) (uint8, uint8, uint8) {
cb = ^(cb >> 31)
}
+ // Note that 32768 - 27440 - 5328 equals 0.
cr := 32768*r1 - 27440*g1 - 5328*b1 + 257<<15
if uint32(cr)&0xff000000 == 0 {
cr >>= 16
@@ -134,24 +139,39 @@ func (c YCbCr) RGBA() (uint32, uint32, uint32, uint32) {
yy1 := int32(c.Y) * 0x10100 // Convert 0x12 to 0x121200.
cb1 := int32(c.Cb) - 128
cr1 := int32(c.Cr) - 128
- r := (yy1 + 91881*cr1) >> 8
- g := (yy1 - 22554*cb1 - 46802*cr1) >> 8
- b := (yy1 + 116130*cb1) >> 8
- if r < 0 {
- r = 0
- } else if r > 0xffff {
- r = 0xffff
+
+ // The bit twiddling below is equivalent to
+ //
+ // r := (yy1 + 91881*cr1) >> 8
+ // if r < 0 {
+ // r = 0
+ // } else if r > 0xff {
+ // r = 0xffff
+ // }
+ //
+ // but uses fewer branches and is faster.
+ // The code below to compute g and b uses a similar pattern.
+ r := yy1 + 91881*cr1
+ if uint32(r)&0xff000000 == 0 {
+ r >>= 8
+ } else {
+ r = ^(r >> 31) & 0xffff
}
- if g < 0 {
- g = 0
- } else if g > 0xffff {
- g = 0xffff
+
+ g := yy1 - 22554*cb1 - 46802*cr1
+ if uint32(g)&0xff000000 == 0 {
+ g >>= 8
+ } else {
+ g = ^(g >> 31) & 0xffff
}
- if b < 0 {
- b = 0
- } else if b > 0xffff {
- b = 0xffff
+
+ b := yy1 + 116130*cb1
+ if uint32(b)&0xff000000 == 0 {
+ b >>= 8
+ } else {
+ b = ^(b >> 31) & 0xffff
}
+
return uint32(r), uint32(g), uint32(b), 0xffff
}
@@ -179,23 +199,37 @@ func (c NYCbCrA) RGBA() (uint32, uint32, uint32, uint32) {
yy1 := int32(c.Y) * 0x10100 // Convert 0x12 to 0x121200.
cb1 := int32(c.Cb) - 128
cr1 := int32(c.Cr) - 128
- r := (yy1 + 91881*cr1) >> 8
- g := (yy1 - 22554*cb1 - 46802*cr1) >> 8
- b := (yy1 + 116130*cb1) >> 8
- if r < 0 {
- r = 0
- } else if r > 0xffff {
- r = 0xffff
+
+ // The bit twiddling below is equivalent to
+ //
+ // r := (yy1 + 91881*cr1) >> 8
+ // if r < 0 {
+ // r = 0
+ // } else if r > 0xff {
+ // r = 0xffff
+ // }
+ //
+ // but uses fewer branches and is faster.
+ // The code below to compute g and b uses a similar pattern.
+ r := yy1 + 91881*cr1
+ if uint32(r)&0xff000000 == 0 {
+ r >>= 8
+ } else {
+ r = ^(r >> 31) & 0xffff
}
- if g < 0 {
- g = 0
- } else if g > 0xffff {
- g = 0xffff
+
+ g := yy1 - 22554*cb1 - 46802*cr1
+ if uint32(g)&0xff000000 == 0 {
+ g >>= 8
+ } else {
+ g = ^(g >> 31) & 0xffff
}
- if b < 0 {
- b = 0
- } else if b > 0xffff {
- b = 0xffff
+
+ b := yy1 + 116130*cb1
+ if uint32(b)&0xff000000 == 0 {
+ b >>= 8
+ } else {
+ b = ^(b >> 31) & 0xffff
}
// The second part of this method applies the alpha.
diff --git a/libgo/go/image/color/ycbcr_test.go b/libgo/go/image/color/ycbcr_test.go
index 561699f4e0e..85c1b984a65 100644
--- a/libgo/go/image/color/ycbcr_test.go
+++ b/libgo/go/image/color/ycbcr_test.go
@@ -172,7 +172,8 @@ func TestPalette(t *testing.T) {
}
}
-var sink uint8
+var sink8 uint8
+var sink32 uint32
func BenchmarkYCbCrToRGB(b *testing.B) {
// YCbCrToRGB does saturating arithmetic.
@@ -180,17 +181,17 @@ func BenchmarkYCbCrToRGB(b *testing.B) {
// different paths through the generated code.
b.Run("0", func(b *testing.B) {
for i := 0; i < b.N; i++ {
- sink, sink, sink = YCbCrToRGB(0, 0, 0)
+ sink8, sink8, sink8 = YCbCrToRGB(0, 0, 0)
}
})
b.Run("128", func(b *testing.B) {
for i := 0; i < b.N; i++ {
- sink, sink, sink = YCbCrToRGB(128, 128, 128)
+ sink8, sink8, sink8 = YCbCrToRGB(128, 128, 128)
}
})
b.Run("255", func(b *testing.B) {
for i := 0; i < b.N; i++ {
- sink, sink, sink = YCbCrToRGB(255, 255, 255)
+ sink8, sink8, sink8 = YCbCrToRGB(255, 255, 255)
}
})
}
@@ -201,17 +202,65 @@ func BenchmarkRGBToYCbCr(b *testing.B) {
// through the generated code.
b.Run("0", func(b *testing.B) {
for i := 0; i < b.N; i++ {
- sink, sink, sink = RGBToYCbCr(0, 0, 0)
+ sink8, sink8, sink8 = RGBToYCbCr(0, 0, 0)
}
})
b.Run("Cb", func(b *testing.B) {
for i := 0; i < b.N; i++ {
- sink, sink, sink = RGBToYCbCr(0, 0, 255)
+ sink8, sink8, sink8 = RGBToYCbCr(0, 0, 255)
}
})
b.Run("Cr", func(b *testing.B) {
for i := 0; i < b.N; i++ {
- sink, sink, sink = RGBToYCbCr(255, 0, 0)
+ sink8, sink8, sink8 = RGBToYCbCr(255, 0, 0)
+ }
+ })
+}
+
+func BenchmarkYCbCrToRGBA(b *testing.B) {
+ // RGB does saturating arithmetic.
+ // Low, middle, and high values can take
+ // different paths through the generated code.
+ b.Run("0", func(b *testing.B) {
+ c := YCbCr{0, 0, 0}
+ for i := 0; i < b.N; i++ {
+ sink32, sink32, sink32, sink32 = c.RGBA()
+ }
+ })
+ b.Run("128", func(b *testing.B) {
+ c := YCbCr{128, 128, 128}
+ for i := 0; i < b.N; i++ {
+ sink32, sink32, sink32, sink32 = c.RGBA()
+ }
+ })
+ b.Run("255", func(b *testing.B) {
+ c := YCbCr{255, 255, 255}
+ for i := 0; i < b.N; i++ {
+ sink32, sink32, sink32, sink32 = c.RGBA()
+ }
+ })
+}
+
+func BenchmarkNYCbCrAToRGBA(b *testing.B) {
+ // RGBA does saturating arithmetic.
+ // Low, middle, and high values can take
+ // different paths through the generated code.
+ b.Run("0", func(b *testing.B) {
+ c := NYCbCrA{YCbCr{0, 0, 0}, 0xff}
+ for i := 0; i < b.N; i++ {
+ sink32, sink32, sink32, sink32 = c.RGBA()
+ }
+ })
+ b.Run("128", func(b *testing.B) {
+ c := NYCbCrA{YCbCr{128, 128, 128}, 0xff}
+ for i := 0; i < b.N; i++ {
+ sink32, sink32, sink32, sink32 = c.RGBA()
+ }
+ })
+ b.Run("255", func(b *testing.B) {
+ c := NYCbCrA{YCbCr{255, 255, 255}, 0xff}
+ for i := 0; i < b.N; i++ {
+ sink32, sink32, sink32, sink32 = c.RGBA()
}
})
}
diff --git a/libgo/go/image/draw/bench_test.go b/libgo/go/image/draw/bench_test.go
index 7b89f95d118..a41d7e7dfb7 100644
--- a/libgo/go/image/draw/bench_test.go
+++ b/libgo/go/image/draw/bench_test.go
@@ -74,7 +74,7 @@ func bench(b *testing.B, dcm, scm, mcm color.Model, op Op) {
var src image.Image
switch scm {
case nil:
- src = &image.Uniform{C: color.RGBA{0x11, 0x22, 0x33, 0xff}}
+ src = &image.Uniform{C: color.RGBA{0x11, 0x22, 0x33, 0x44}}
case color.CMYKModel:
src1 := image.NewCMYK(image.Rect(0, 0, srcw, srch))
for y := 0; y < srch; y++ {
diff --git a/libgo/go/image/draw/draw.go b/libgo/go/image/draw/draw.go
index 6a16cd39cf8..a31dd427ce1 100644
--- a/libgo/go/image/draw/draw.go
+++ b/libgo/go/image/draw/draw.go
@@ -116,7 +116,12 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
if mask == nil {
switch src0 := src.(type) {
case *image.Uniform:
- drawFillOver(dst0, r, src0)
+ sr, sg, sb, sa := src0.RGBA()
+ if sa == 0xffff {
+ drawFillSrc(dst0, r, sr, sg, sb, sa)
+ } else {
+ drawFillOver(dst0, r, sr, sg, sb, sa)
+ }
return
case *image.RGBA:
drawCopyOver(dst0, r, src0, sp)
@@ -150,7 +155,8 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
if mask == nil {
switch src0 := src.(type) {
case *image.Uniform:
- drawFillSrc(dst0, r, src0)
+ sr, sg, sb, sa := src0.RGBA()
+ drawFillSrc(dst0, r, sr, sg, sb, sa)
return
case *image.RGBA:
drawCopySrc(dst0, r, src0, sp)
@@ -232,8 +238,7 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
}
}
-func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
- sr, sg, sb, sa := src.RGBA()
+func drawFillOver(dst *image.RGBA, r image.Rectangle, sr, sg, sb, sa uint32) {
// The 0x101 is here for the same reason as in drawRGBA.
a := (m - sa) * 0x101
i0 := dst.PixOffset(r.Min.X, r.Min.Y)
@@ -255,8 +260,7 @@ func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
}
}
-func drawFillSrc(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
- sr, sg, sb, sa := src.RGBA()
+func drawFillSrc(dst *image.RGBA, r image.Rectangle, sr, sg, sb, sa uint32) {
sr8 := uint8(sr >> 8)
sg8 := uint8(sg >> 8)
sb8 := uint8(sb >> 8)
diff --git a/libgo/go/image/draw/example_test.go b/libgo/go/image/draw/example_test.go
new file mode 100644
index 00000000000..d381c1c67fd
--- /dev/null
+++ b/libgo/go/image/draw/example_test.go
@@ -0,0 +1,50 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package draw_test
+
+import (
+ "fmt"
+ "image"
+ "image/color"
+ "image/draw"
+ "math"
+)
+
+func ExampleDrawer_floydSteinberg() {
+ const width = 130
+ const height = 50
+
+ im := image.NewGray(image.Rectangle{Max: image.Point{X: width, Y: height}})
+ for x := 0; x < width; x++ {
+ for y := 0; y < height; y++ {
+ dist := math.Sqrt(math.Pow(float64(x-width/2), 2)/3+math.Pow(float64(y-height/2), 2)) / (height / 1.5) * 255
+ var gray uint8
+ if dist > 255 {
+ gray = 255
+ } else {
+ gray = uint8(dist)
+ }
+ im.SetGray(x, y, color.Gray{Y: 255 - gray})
+ }
+ }
+ pi := image.NewPaletted(im.Bounds(), []color.Color{
+ color.Gray{Y: 255},
+ color.Gray{Y: 160},
+ color.Gray{Y: 70},
+ color.Gray{Y: 35},
+ color.Gray{Y: 0},
+ })
+
+ draw.FloydSteinberg.Draw(pi, im.Bounds(), im, image.ZP)
+ shade := []string{" ", "░", "▒", "▓", "█"}
+ for i, p := range pi.Pix {
+ fmt.Print(shade[p])
+ if (i+1)%width == 0 {
+ fmt.Print("\n")
+ }
+ }
+}
diff --git a/libgo/go/image/gif/reader.go b/libgo/go/image/gif/reader.go
index 6181a946fad..e61112817b7 100644
--- a/libgo/go/image/gif/reader.go
+++ b/libgo/go/image/gif/reader.go
@@ -63,6 +63,22 @@ const (
eApplication = 0xFF // Application
)
+func readFull(r io.Reader, b []byte) error {
+ _, err := io.ReadFull(r, b)
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return err
+}
+
+func readByte(r io.ByteReader) (byte, error) {
+ b, err := r.ReadByte()
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return b, err
+}
+
// decoder is the type used to decode a GIF file.
type decoder struct {
r reader
@@ -124,7 +140,7 @@ func (b *blockReader) Read(p []byte) (int, error) {
return 0, b.err
}
b.slice = b.tmp[:blockLen]
- if _, b.err = io.ReadFull(b.r, b.slice); b.err != nil {
+ if b.err = readFull(b.r, b.slice); b.err != nil {
return 0, b.err
}
}
@@ -151,9 +167,9 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
}
for {
- c, err := d.r.ReadByte()
+ c, err := readByte(d.r)
if err != nil {
- return err
+ return fmt.Errorf("gif: reading frames: %v", err)
}
switch c {
case sExtension:
@@ -198,9 +214,9 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
m.Palette = p
}
}
- litWidth, err := d.r.ReadByte()
+ litWidth, err := readByte(d.r)
if err != nil {
- return err
+ return fmt.Errorf("gif: reading image data: %v", err)
}
if litWidth < 2 || litWidth > 8 {
return fmt.Errorf("gif: pixel size in decode out of range: %d", litWidth)
@@ -209,9 +225,9 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
br := &blockReader{r: d.r}
lzwr := lzw.NewReader(br, lzw.LSB, int(litWidth))
defer lzwr.Close()
- if _, err = io.ReadFull(lzwr, m.Pix); err != nil {
+ if err = readFull(lzwr, m.Pix); err != nil {
if err != io.ErrUnexpectedEOF {
- return err
+ return fmt.Errorf("gif: reading image data: %v", err)
}
return errNotEnough
}
@@ -228,13 +244,13 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
// See https://golang.org/issue/9856 for an example GIF.
if n, err := lzwr.Read(d.tmp[:1]); n != 0 || (err != io.EOF && err != io.ErrUnexpectedEOF) {
if err != nil {
- return err
+ return fmt.Errorf("gif: reading image data: %v", err)
}
return errTooMuch
}
if n, err := br.Read(d.tmp[:1]); n != 0 || err != io.EOF {
if err != nil {
- return err
+ return fmt.Errorf("gif: reading image data: %v", err)
}
return errTooMuch
}
@@ -264,7 +280,7 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
case sTrailer:
if len(d.image) == 0 {
- return io.ErrUnexpectedEOF
+ return fmt.Errorf("gif: missing image data")
}
return nil
@@ -275,13 +291,13 @@ func (d *decoder) decode(r io.Reader, configOnly bool) error {
}
func (d *decoder) readHeaderAndScreenDescriptor() error {
- _, err := io.ReadFull(d.r, d.tmp[:13])
+ err := readFull(d.r, d.tmp[:13])
if err != nil {
- return err
+ return fmt.Errorf("gif: reading header: %v", err)
}
d.vers = string(d.tmp[:6])
if d.vers != "GIF87a" && d.vers != "GIF89a" {
- return fmt.Errorf("gif: can't recognize format %s", d.vers)
+ return fmt.Errorf("gif: can't recognize format %q", d.vers)
}
d.width = int(d.tmp[6]) + int(d.tmp[7])<<8
d.height = int(d.tmp[8]) + int(d.tmp[9])<<8
@@ -298,9 +314,9 @@ func (d *decoder) readHeaderAndScreenDescriptor() error {
func (d *decoder) readColorTable(fields byte) (color.Palette, error) {
n := 1 << (1 + uint(fields&fColorTableBitsMask))
- _, err := io.ReadFull(d.r, d.tmp[:3*n])
+ err := readFull(d.r, d.tmp[:3*n])
if err != nil {
- return nil, fmt.Errorf("gif: short read on color table: %s", err)
+ return nil, fmt.Errorf("gif: reading color table: %s", err)
}
j, p := 0, make(color.Palette, n)
for i := range p {
@@ -311,9 +327,9 @@ func (d *decoder) readColorTable(fields byte) (color.Palette, error) {
}
func (d *decoder) readExtension() error {
- extension, err := d.r.ReadByte()
+ extension, err := readByte(d.r)
if err != nil {
- return err
+ return fmt.Errorf("gif: reading extension: %v", err)
}
size := 0
switch extension {
@@ -324,9 +340,9 @@ func (d *decoder) readExtension() error {
case eComment:
// nothing to do but read the data.
case eApplication:
- b, err := d.r.ReadByte()
+ b, err := readByte(d.r)
if err != nil {
- return err
+ return fmt.Errorf("gif: reading extension: %v", err)
}
// The spec requires size be 11, but Adobe sometimes uses 10.
size = int(b)
@@ -334,8 +350,8 @@ func (d *decoder) readExtension() error {
return fmt.Errorf("gif: unknown extension 0x%.2x", extension)
}
if size > 0 {
- if _, err := io.ReadFull(d.r, d.tmp[:size]); err != nil {
- return err
+ if err := readFull(d.r, d.tmp[:size]); err != nil {
+ return fmt.Errorf("gif: reading extension: %v", err)
}
}
@@ -343,8 +359,11 @@ func (d *decoder) readExtension() error {
// this extension defines a loop count.
if extension == eApplication && string(d.tmp[:size]) == "NETSCAPE2.0" {
n, err := d.readBlock()
- if n == 0 || err != nil {
- return err
+ if err != nil {
+ return fmt.Errorf("gif: reading extension: %v", err)
+ }
+ if n == 0 {
+ return nil
}
if n == 3 && d.tmp[0] == 1 {
d.loopCount = int(d.tmp[1]) | int(d.tmp[2])<<8
@@ -352,14 +371,17 @@ func (d *decoder) readExtension() error {
}
for {
n, err := d.readBlock()
- if n == 0 || err != nil {
- return err
+ if err != nil {
+ return fmt.Errorf("gif: reading extension: %v", err)
+ }
+ if n == 0 {
+ return nil
}
}
}
func (d *decoder) readGraphicControl() error {
- if _, err := io.ReadFull(d.r, d.tmp[:6]); err != nil {
+ if err := readFull(d.r, d.tmp[:6]); err != nil {
return fmt.Errorf("gif: can't read graphic control: %s", err)
}
if d.tmp[0] != 4 {
@@ -379,7 +401,7 @@ func (d *decoder) readGraphicControl() error {
}
func (d *decoder) newImageFromDescriptor() (*image.Paletted, error) {
- if _, err := io.ReadFull(d.r, d.tmp[:9]); err != nil {
+ if err := readFull(d.r, d.tmp[:9]); err != nil {
return nil, fmt.Errorf("gif: can't read image descriptor: %s", err)
}
left := int(d.tmp[0]) + int(d.tmp[1])<<8
@@ -399,11 +421,14 @@ func (d *decoder) newImageFromDescriptor() (*image.Paletted, error) {
}
func (d *decoder) readBlock() (int, error) {
- n, err := d.r.ReadByte()
+ n, err := readByte(d.r)
if n == 0 || err != nil {
return 0, err
}
- return io.ReadFull(d.r, d.tmp[:n])
+ if err := readFull(d.r, d.tmp[:n]); err != nil {
+ return 0, err
+ }
+ return int(n), nil
}
// interlaceScan defines the ordering for a pass of the interlace algorithm.
diff --git a/libgo/go/image/gif/reader_test.go b/libgo/go/image/gif/reader_test.go
index 90c81493cba..1267ba06a9d 100644
--- a/libgo/go/image/gif/reader_test.go
+++ b/libgo/go/image/gif/reader_test.go
@@ -10,6 +10,7 @@ import (
"image"
"image/color"
"reflect"
+ "strings"
"testing"
)
@@ -292,3 +293,19 @@ func TestLoopCount(t *testing.T) {
t.Errorf("loop count mismatch: %d vs %d", img.LoopCount, img1.LoopCount)
}
}
+
+func TestUnexpectedEOF(t *testing.T) {
+ for i := len(testGIF) - 1; i >= 0; i-- {
+ _, err := Decode(bytes.NewReader(testGIF[:i]))
+ if err == errNotEnough {
+ continue
+ }
+ text := ""
+ if err != nil {
+ text = err.Error()
+ }
+ if !strings.HasPrefix(text, "gif:") || !strings.HasSuffix(text, ": unexpected EOF") {
+ t.Errorf("Decode(testGIF[:%d]) = %v, want gif: ...: unexpected EOF", i, err)
+ }
+ }
+}
diff --git a/libgo/go/image/png/example_test.go b/libgo/go/image/png/example_test.go
new file mode 100644
index 00000000000..2a03be5a1a0
--- /dev/null
+++ b/libgo/go/image/png/example_test.go
@@ -0,0 +1,79 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package png_test
+
+import (
+ "encoding/base64"
+ "fmt"
+ "image"
+ "image/color"
+ "image/png"
+ "io"
+ "log"
+ "os"
+ "strings"
+)
+
+const gopher = `iVBORw0KGgoAAAANSUhEUgAAAEsAAAA8CAAAAAALAhhPAAAFfUlEQVRYw62XeWwUVRzHf2+OPbo9d7tsWyiyaZti6eWGAhISoIGKECEKCAiJJkYTiUgTMYSIosYYBBIUIxoSPIINEBDi2VhwkQrVsj1ESgu9doHWdrul7ba73WNm3vOPtsseM9MdwvvrzTs+8/t95ze/33sI5BqiabU6m9En8oNjduLnAEDLUsQXFF8tQ5oxK3vmnNmDSMtrncks9Hhtt/qeWZapHb1ha3UqYSWVl2ZmpWgaXMXGohQAvmeop3bjTRtv6SgaK/Pb9/bFzUrYslbFAmHPp+3WhAYdr+7GN/YnpN46Opv55VDsJkoEpMrY/vO2BIYQ6LLvm0ThY3MzDzzeSJeeWNyTkgnIE5ePKsvKlcg/0T9QMzXalwXMlj54z4c0rh/mzEfr+FgWEz2w6uk8dkzFAgcARAgNp1ZYef8bH2AgvuStbc2/i6CiWGj98y2tw2l4FAXKkQBIf+exyRnteY83LfEwDQAYCoK+P6bxkZm/0966LxcAAILHB56kgD95PPxltuYcMtFTWw/FKkY/6Opf3GGd9ZF+Qp6mzJxzuRSractOmJrH1u8XTvWFHINNkLQLMR+XHXvfPPHw967raE1xxwtA36IMRfkAAG29/7mLuQcb2WOnsJReZGfpiHsSBX81cvMKywYZHhX5hFPtOqPGWZCXnhWGAu6lX91ElKXSalcLXu3UaOXVay57ZSe5f6Gpx7J2MXAsi7EqSp09b/MirKSyJfnfEEgeDjl8FgDAfvewP03zZ+AJ0m9aFRM8eEHBDRKjfcreDXnZdQuAxXpT2NRJ7xl3UkLBhuVGU16gZiGOgZmrSbRdqkILuL/yYoSXHHkl9KXgqNu3PB8oRg0geC5vFmLjad6mUyTKLmF3OtraWDIfACyXqmephaDABawfpi6tqqBZytfQMqOz6S09iWXhktrRaB8Xz4Yi/8gyABDm5NVe6qq/3VzPrcjELWrebVuyY2T7ar4zQyybUCtsQ5Es1FGaZVrRVQwAgHGW2ZCRZshI5bGQi7HesyE972pOSeMM0dSktlzxRdrlqb3Osa6CCS8IJoQQQgBAbTAa5l5epO34rJszibJI8rxLfGzcp1dRosutGeb2VDNgqYrwTiPNsLxXiPi3dz7LiS1WBRBDBOnqEjyy3aQb+/bLiJzz9dIkscVBBLxMfSEac7kO4Fpkngi0ruNBeSOal+u8jgOuqPz12nryMLCniEjtOOOmpt+KEIqsEdocJjYXwrh9OZqWJQyPCTo67LNS/TdxLAv6R5ZNK9npEjbYdT33gRo4o5oTqR34R+OmaSzDBWsAIPhuRcgyoteNi9gF0KzNYWVItPf2TLoXEg+7isNC7uJkgo1iQWOfRSP9NR11RtbZZ3OMG/VhL6jvx+J1m87+RCfJChAtEBQkSBX2PnSiihc/Twh3j0h7qdYQAoRVsRGmq7HU2QRbaxVGa1D6nIOqaIWRjyRZpHMQKWKpZM5feA+lzC4ZFultV8S6T0mzQGhQohi5I8iw+CsqBSxhFMuwyLgSwbghGb0AiIKkSDmGZVmJSiKihsiyOAUs70UkywooYP0bii9GdH4sfr1UNysd3fUyLLMQN+rsmo3grHl9VNJHbbwxoa47Vw5gupIqrZcjPh9R4Nye3nRDk199V+aetmvVtDRE8/+cbgAAgMIWGb3UA0MGLE9SCbWX670TDy1y98c3D27eppUjsZ6fql3jcd5rUe7+ZIlLNQny3Rd+E5Tct3WVhTM5RBCEdiEK0b6B+/ca2gYU393nFj/n1AygRQxPIUA043M42u85+z2SnssKrPl8Mx76NL3E6eXc3be7OD+H4WHbJkKI8AU8irbITQjZ+0hQcPEgId/Fn/pl9crKH02+5o2b9T/eMx7pKoskYgAAAABJRU5ErkJggg==`
+
+// gopherPNG creates an io.Reader by decoding the base64 encoded image data string in the gopher constant.
+func gopherPNG() io.Reader { return base64.NewDecoder(base64.StdEncoding, strings.NewReader(gopher)) }
+
+func ExampleDecode() {
+ // This example uses png.Decode which can only decode PNG images.
+ // Consider using the general image.Decode as it can sniff and decode any registered image format.
+ img, err := png.Decode(gopherPNG())
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ levels := []string{" ", "░", "▒", "▓", "█"}
+
+ for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
+ for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
+ c := color.GrayModel.Convert(img.At(x, y)).(color.Gray)
+ level := c.Y / 51 // 51 * 5 = 255
+ if level == 5 {
+ level--
+ }
+ fmt.Print(levels[level])
+ }
+ fmt.Print("\n")
+ }
+}
+
+func ExampleEncode() {
+ const width, height = 256, 256
+
+ // Create a colored image of the given width and height.
+ img := image.NewNRGBA(image.Rect(0, 0, width, height))
+
+ for y := 0; y < height; y++ {
+ for x := 0; x < width; x++ {
+ img.Set(x, y, color.NRGBA{
+ R: uint8((x + y) & 255),
+ G: uint8((x + y) << 1 & 255),
+ B: uint8((x + y) << 2 & 255),
+ A: 255,
+ })
+ }
+ }
+
+ f, err := os.Create("image.png")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ if err := png.Encode(f, img); err != nil {
+ f.Close()
+ log.Fatal(err)
+ }
+
+ if err := f.Close(); err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/libgo/go/image/png/reader.go b/libgo/go/image/png/reader.go
index 2dd5ed80736..32f78f0ffe8 100644
--- a/libgo/go/image/png/reader.go
+++ b/libgo/go/image/png/reader.go
@@ -113,6 +113,11 @@ type decoder struct {
idatLength uint32
tmp [3 * 256]byte
interlace int
+
+ // useTransparent and transparent are used for grayscale and truecolor
+ // transparency, as opposed to palette transparency.
+ useTransparent bool
+ transparent [6]byte
}
// A FormatError reports that the input is not a valid PNG.
@@ -252,20 +257,51 @@ func (d *decoder) parsePLTE(length uint32) error {
}
func (d *decoder) parsetRNS(length uint32) error {
- if length > 256 {
- return FormatError("bad tRNS length")
- }
- n, err := io.ReadFull(d.r, d.tmp[:length])
- if err != nil {
- return err
- }
- d.crc.Write(d.tmp[:n])
switch d.cb {
- case cbG8, cbG16:
- return UnsupportedError("grayscale transparency")
+ case cbG1, cbG2, cbG4, cbG8, cbG16:
+ if length != 2 {
+ return FormatError("bad tRNS length")
+ }
+ n, err := io.ReadFull(d.r, d.tmp[:length])
+ if err != nil {
+ return err
+ }
+ d.crc.Write(d.tmp[:n])
+
+ copy(d.transparent[:], d.tmp[:length])
+ switch d.cb {
+ case cbG1:
+ d.transparent[1] *= 0xff
+ case cbG2:
+ d.transparent[1] *= 0x55
+ case cbG4:
+ d.transparent[1] *= 0x11
+ }
+ d.useTransparent = true
+
case cbTC8, cbTC16:
- return UnsupportedError("truecolor transparency")
+ if length != 6 {
+ return FormatError("bad tRNS length")
+ }
+ n, err := io.ReadFull(d.r, d.tmp[:length])
+ if err != nil {
+ return err
+ }
+ d.crc.Write(d.tmp[:n])
+
+ copy(d.transparent[:], d.tmp[:length])
+ d.useTransparent = true
+
case cbP1, cbP2, cbP4, cbP8:
+ if length > 256 {
+ return FormatError("bad tRNS length")
+ }
+ n, err := io.ReadFull(d.r, d.tmp[:length])
+ if err != nil {
+ return err
+ }
+ d.crc.Write(d.tmp[:n])
+
if len(d.palette) < n {
d.palette = d.palette[:n]
}
@@ -273,7 +309,8 @@ func (d *decoder) parsetRNS(length uint32) error {
rgba := d.palette[i].(color.RGBA)
d.palette[i] = color.NRGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]}
}
- case cbGA8, cbGA16, cbTCA8, cbTCA16:
+
+ default:
return FormatError("tRNS, color type mismatch")
}
return d.verifyChecksum()
@@ -366,7 +403,7 @@ func (d *decoder) decode() (image.Image, error) {
// readImagePass reads a single image pass, sized according to the pass number.
func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image.Image, error) {
- var bitsPerPixel int = 0
+ bitsPerPixel := 0
pixOffset := 0
var (
gray *image.Gray
@@ -394,16 +431,26 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
switch d.cb {
case cbG1, cbG2, cbG4, cbG8:
bitsPerPixel = d.depth
- gray = image.NewGray(image.Rect(0, 0, width, height))
- img = gray
+ if d.useTransparent {
+ nrgba = image.NewNRGBA(image.Rect(0, 0, width, height))
+ img = nrgba
+ } else {
+ gray = image.NewGray(image.Rect(0, 0, width, height))
+ img = gray
+ }
case cbGA8:
bitsPerPixel = 16
nrgba = image.NewNRGBA(image.Rect(0, 0, width, height))
img = nrgba
case cbTC8:
bitsPerPixel = 24
- rgba = image.NewRGBA(image.Rect(0, 0, width, height))
- img = rgba
+ if d.useTransparent {
+ nrgba = image.NewNRGBA(image.Rect(0, 0, width, height))
+ img = nrgba
+ } else {
+ rgba = image.NewRGBA(image.Rect(0, 0, width, height))
+ img = rgba
+ }
case cbP1, cbP2, cbP4, cbP8:
bitsPerPixel = d.depth
paletted = image.NewPaletted(image.Rect(0, 0, width, height), d.palette)
@@ -414,16 +461,26 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
img = nrgba
case cbG16:
bitsPerPixel = 16
- gray16 = image.NewGray16(image.Rect(0, 0, width, height))
- img = gray16
+ if d.useTransparent {
+ nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
+ img = nrgba64
+ } else {
+ gray16 = image.NewGray16(image.Rect(0, 0, width, height))
+ img = gray16
+ }
case cbGA16:
bitsPerPixel = 32
nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
img = nrgba64
case cbTC16:
bitsPerPixel = 48
- rgba64 = image.NewRGBA64(image.Rect(0, 0, width, height))
- img = rgba64
+ if d.useTransparent {
+ nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
+ img = nrgba64
+ } else {
+ rgba64 = image.NewRGBA64(image.Rect(0, 0, width, height))
+ img = rgba64
+ }
case cbTCA16:
bitsPerPixel = 64
nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
@@ -483,27 +540,75 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
// Convert from bytes to colors.
switch d.cb {
case cbG1:
- for x := 0; x < width; x += 8 {
- b := cdat[x/8]
- for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
- gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff})
- b <<= 1
+ if d.useTransparent {
+ ty := d.transparent[1]
+ for x := 0; x < width; x += 8 {
+ b := cdat[x/8]
+ for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
+ ycol := (b >> 7) * 0xff
+ acol := uint8(0xff)
+ if ycol == ty {
+ acol = 0x00
+ }
+ nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
+ b <<= 1
+ }
+ }
+ } else {
+ for x := 0; x < width; x += 8 {
+ b := cdat[x/8]
+ for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
+ gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff})
+ b <<= 1
+ }
}
}
case cbG2:
- for x := 0; x < width; x += 4 {
- b := cdat[x/4]
- for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
- gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55})
- b <<= 2
+ if d.useTransparent {
+ ty := d.transparent[1]
+ for x := 0; x < width; x += 4 {
+ b := cdat[x/4]
+ for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
+ ycol := (b >> 6) * 0x55
+ acol := uint8(0xff)
+ if ycol == ty {
+ acol = 0x00
+ }
+ nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
+ b <<= 2
+ }
+ }
+ } else {
+ for x := 0; x < width; x += 4 {
+ b := cdat[x/4]
+ for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
+ gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55})
+ b <<= 2
+ }
}
}
case cbG4:
- for x := 0; x < width; x += 2 {
- b := cdat[x/2]
- for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
- gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11})
- b <<= 4
+ if d.useTransparent {
+ ty := d.transparent[1]
+ for x := 0; x < width; x += 2 {
+ b := cdat[x/2]
+ for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
+ ycol := (b >> 4) * 0x11
+ acol := uint8(0xff)
+ if ycol == ty {
+ acol = 0x00
+ }
+ nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
+ b <<= 4
+ }
+ }
+ } else {
+ for x := 0; x < width; x += 2 {
+ b := cdat[x/2]
+ for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
+ gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11})
+ b <<= 4
+ }
}
}
case cbG8:
@@ -515,16 +620,37 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]})
}
case cbTC8:
- pix, i, j := rgba.Pix, pixOffset, 0
- for x := 0; x < width; x++ {
- pix[i+0] = cdat[j+0]
- pix[i+1] = cdat[j+1]
- pix[i+2] = cdat[j+2]
- pix[i+3] = 0xff
- i += 4
- j += 3
+ if d.useTransparent {
+ pix, i, j := nrgba.Pix, pixOffset, 0
+ tr, tg, tb := d.transparent[1], d.transparent[3], d.transparent[5]
+ for x := 0; x < width; x++ {
+ r := cdat[j+0]
+ g := cdat[j+1]
+ b := cdat[j+2]
+ a := uint8(0xff)
+ if r == tr && g == tg && b == tb {
+ a = 0x00
+ }
+ pix[i+0] = r
+ pix[i+1] = g
+ pix[i+2] = b
+ pix[i+3] = a
+ i += 4
+ j += 3
+ }
+ pixOffset += nrgba.Stride
+ } else {
+ pix, i, j := rgba.Pix, pixOffset, 0
+ for x := 0; x < width; x++ {
+ pix[i+0] = cdat[j+0]
+ pix[i+1] = cdat[j+1]
+ pix[i+2] = cdat[j+2]
+ pix[i+3] = 0xff
+ i += 4
+ j += 3
+ }
+ pixOffset += rgba.Stride
}
- pixOffset += rgba.Stride
case cbP1:
for x := 0; x < width; x += 8 {
b := cdat[x/8]
@@ -575,9 +701,21 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
copy(nrgba.Pix[pixOffset:], cdat)
pixOffset += nrgba.Stride
case cbG16:
- for x := 0; x < width; x++ {
- ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
- gray16.SetGray16(x, y, color.Gray16{ycol})
+ if d.useTransparent {
+ ty := uint16(d.transparent[0])<<8 | uint16(d.transparent[1])
+ for x := 0; x < width; x++ {
+ ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
+ acol := uint16(0xffff)
+ if ycol == ty {
+ acol = 0x0000
+ }
+ nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
+ }
+ } else {
+ for x := 0; x < width; x++ {
+ ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
+ gray16.SetGray16(x, y, color.Gray16{ycol})
+ }
}
case cbGA16:
for x := 0; x < width; x++ {
@@ -586,11 +724,27 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
}
case cbTC16:
- for x := 0; x < width; x++ {
- rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
- gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
- bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
- rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff})
+ if d.useTransparent {
+ tr := uint16(d.transparent[0])<<8 | uint16(d.transparent[1])
+ tg := uint16(d.transparent[2])<<8 | uint16(d.transparent[3])
+ tb := uint16(d.transparent[4])<<8 | uint16(d.transparent[5])
+ for x := 0; x < width; x++ {
+ rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
+ gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
+ bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
+ acol := uint16(0xffff)
+ if rcol == tr && gcol == tg && bcol == tb {
+ acol = 0x0000
+ }
+ nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol})
+ }
+ } else {
+ for x := 0; x < width; x++ {
+ rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
+ gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
+ bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
+ rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff})
+ }
}
case cbTCA16:
for x := 0; x < width; x++ {
@@ -709,7 +863,11 @@ func (d *decoder) parseChunk() error {
d.stage = dsSeenPLTE
return d.parsePLTE(length)
case "tRNS":
- if d.stage != dsSeenPLTE {
+ if cbPaletted(d.cb) {
+ if d.stage != dsSeenPLTE {
+ return chunkOrderError
+ }
+ } else if d.stage != dsSeenIHDR {
return chunkOrderError
}
d.stage = dsSeentRNS
diff --git a/libgo/go/image/png/reader_test.go b/libgo/go/image/png/reader_test.go
index 0bc4203acbe..b9e9f4d02c6 100644
--- a/libgo/go/image/png/reader_test.go
+++ b/libgo/go/image/png/reader_test.go
@@ -39,6 +39,21 @@ var filenames = []string{
"basn4a16",
"basn6a08",
"basn6a16",
+ "ftbbn0g01",
+ "ftbbn0g02",
+ "ftbbn0g04",
+ "ftbbn2c16",
+ "ftbbn3p08",
+ "ftbgn2c16",
+ "ftbgn3p08",
+ "ftbrn2c08",
+ "ftbwn0g16",
+ "ftbwn3p08",
+ "ftbyn3p08",
+ "ftp0n0g08",
+ "ftp0n2c08",
+ "ftp0n3p08",
+ "ftp1n3p08",
}
var filenamesPaletted = []string{
@@ -64,6 +79,50 @@ func readPNG(filename string) (image.Image, error) {
return Decode(f)
}
+// fakebKGDs maps from filenames to fake bKGD chunks for our approximation to
+// the sng command-line tool. Package png doesn't keep that metadata when
+// png.Decode returns an image.Image.
+var fakebKGDs = map[string]string{
+ "ftbbn0g01": "bKGD {gray: 0;}\n",
+ "ftbbn0g02": "bKGD {gray: 0;}\n",
+ "ftbbn0g04": "bKGD {gray: 0;}\n",
+ "ftbbn2c16": "bKGD {red: 0; green: 0; blue: 65535;}\n",
+ "ftbbn3p08": "bKGD {index: 245}\n",
+ "ftbgn2c16": "bKGD {red: 0; green: 65535; blue: 0;}\n",
+ "ftbgn3p08": "bKGD {index: 245}\n",
+ "ftbrn2c08": "bKGD {red: 255; green: 0; blue: 0;}\n",
+ "ftbwn0g16": "bKGD {gray: 65535;}\n",
+ "ftbwn3p08": "bKGD {index: 0}\n",
+ "ftbyn3p08": "bKGD {index: 245}\n",
+}
+
+// fakegAMAs maps from filenames to fake gAMA chunks for our approximation to
+// the sng command-line tool. Package png doesn't keep that metadata when
+// png.Decode returns an image.Image.
+var fakegAMAs = map[string]string{
+ "ftbbn0g01": "",
+ "ftbbn0g02": "gAMA {0.45455}\n",
+}
+
+// fakeIHDRUsings maps from filenames to fake IHDR "using" lines for our
+// approximation to the sng command-line tool. The PNG model is that
+// transparency (in the tRNS chunk) is separate to the color/grayscale/palette
+// color model (in the IHDR chunk). The Go model is that the concrete
+// image.Image type returned by png.Decode, such as image.RGBA (with all pixels
+// having 100% alpha) or image.NRGBA, encapsulates whether or not the image has
+// transparency. This map is a hack to work around the fact that the Go model
+// can't otherwise discriminate PNG's "IHDR says color (with no alpha) but tRNS
+// says alpha" and "IHDR says color with alpha".
+var fakeIHDRUsings = map[string]string{
+ "ftbbn0g01": " using grayscale;\n",
+ "ftbbn0g02": " using grayscale;\n",
+ "ftbbn0g04": " using grayscale;\n",
+ "ftbbn2c16": " using color;\n",
+ "ftbgn2c16": " using color;\n",
+ "ftbrn2c08": " using color;\n",
+ "ftbwn0g16": " using grayscale;\n",
+}
+
// An approximation of the sng command-line tool.
func sng(w io.WriteCloser, filename string, png image.Image) {
defer w.Close()
@@ -95,25 +154,35 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
// Write the filename and IHDR.
io.WriteString(w, "#SNG: from "+filename+".png\nIHDR {\n")
fmt.Fprintf(w, " width: %d; height: %d; bitdepth: %d;\n", bounds.Dx(), bounds.Dy(), bitdepth)
- switch {
- case cm == color.RGBAModel, cm == color.RGBA64Model:
- io.WriteString(w, " using color;\n")
- case cm == color.NRGBAModel, cm == color.NRGBA64Model:
- io.WriteString(w, " using color alpha;\n")
- case cm == color.GrayModel, cm == color.Gray16Model:
- io.WriteString(w, " using grayscale;\n")
- case cpm != nil:
- io.WriteString(w, " using color palette;\n")
- default:
- io.WriteString(w, "unknown PNG decoder color model\n")
+ if s, ok := fakeIHDRUsings[filename]; ok {
+ io.WriteString(w, s)
+ } else {
+ switch {
+ case cm == color.RGBAModel, cm == color.RGBA64Model:
+ io.WriteString(w, " using color;\n")
+ case cm == color.NRGBAModel, cm == color.NRGBA64Model:
+ io.WriteString(w, " using color alpha;\n")
+ case cm == color.GrayModel, cm == color.Gray16Model:
+ io.WriteString(w, " using grayscale;\n")
+ case cpm != nil:
+ io.WriteString(w, " using color palette;\n")
+ default:
+ io.WriteString(w, "unknown PNG decoder color model\n")
+ }
}
io.WriteString(w, "}\n")
- // We fake a gAMA output. The test files have a gAMA chunk but the go PNG parser ignores it
- // (the PNG spec section 11.3 says "Ancillary chunks may be ignored by a decoder").
- io.WriteString(w, "gAMA {1.0000}\n")
+ // We fake a gAMA chunk. The test files have a gAMA chunk but the go PNG
+ // parser ignores it (the PNG spec section 11.3 says "Ancillary chunks may
+ // be ignored by a decoder").
+ if s, ok := fakegAMAs[filename]; ok {
+ io.WriteString(w, s)
+ } else {
+ io.WriteString(w, "gAMA {1.0000}\n")
+ }
// Write the PLTE and tRNS (if applicable).
+ useTransparent := false
if cpm != nil {
lastAlpha := -1
io.WriteString(w, "PLTE {\n")
@@ -133,6 +202,9 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
fmt.Fprintf(w, " (%3d,%3d,%3d) # rgb = (0x%02x,0x%02x,0x%02x)\n", r, g, b, r, g, b)
}
io.WriteString(w, "}\n")
+ if s, ok := fakebKGDs[filename]; ok {
+ io.WriteString(w, s)
+ }
if lastAlpha != -1 {
io.WriteString(w, "tRNS {\n")
for i := 0; i <= lastAlpha; i++ {
@@ -142,6 +214,42 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
}
io.WriteString(w, "}\n")
}
+ } else if strings.HasPrefix(filename, "ft") {
+ if s, ok := fakebKGDs[filename]; ok {
+ io.WriteString(w, s)
+ }
+ // We fake a tRNS chunk. The test files' grayscale and truecolor
+ // transparent images all have their top left corner transparent.
+ switch c := png.At(0, 0).(type) {
+ case color.NRGBA:
+ if c.A == 0 {
+ useTransparent = true
+ io.WriteString(w, "tRNS {\n")
+ switch filename {
+ case "ftbbn0g01", "ftbbn0g02", "ftbbn0g04":
+ // The standard image package doesn't have a "gray with
+ // alpha" type. Instead, we use an image.NRGBA.
+ fmt.Fprintf(w, " gray: %d;\n", c.R)
+ default:
+ fmt.Fprintf(w, " red: %d; green: %d; blue: %d;\n", c.R, c.G, c.B)
+ }
+ io.WriteString(w, "}\n")
+ }
+ case color.NRGBA64:
+ if c.A == 0 {
+ useTransparent = true
+ io.WriteString(w, "tRNS {\n")
+ switch filename {
+ case "ftbwn0g16":
+ // The standard image package doesn't have a "gray16 with
+ // alpha" type. Instead, we use an image.NRGBA64.
+ fmt.Fprintf(w, " gray: %d;\n", c.R)
+ default:
+ fmt.Fprintf(w, " red: %d; green: %d; blue: %d;\n", c.R, c.G, c.B)
+ }
+ io.WriteString(w, "}\n")
+ }
+ }
}
// Write the IMAGE.
@@ -171,12 +279,30 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
case cm == color.NRGBAModel:
for x := bounds.Min.X; x < bounds.Max.X; x++ {
nrgba := png.At(x, y).(color.NRGBA)
- fmt.Fprintf(w, "%02x%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B, nrgba.A)
+ switch filename {
+ case "ftbbn0g01", "ftbbn0g02", "ftbbn0g04":
+ fmt.Fprintf(w, "%02x", nrgba.R)
+ default:
+ if useTransparent {
+ fmt.Fprintf(w, "%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B)
+ } else {
+ fmt.Fprintf(w, "%02x%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B, nrgba.A)
+ }
+ }
}
case cm == color.NRGBA64Model:
for x := bounds.Min.X; x < bounds.Max.X; x++ {
nrgba64 := png.At(x, y).(color.NRGBA64)
- fmt.Fprintf(w, "%04x%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B, nrgba64.A)
+ switch filename {
+ case "ftbwn0g16":
+ fmt.Fprintf(w, "%04x ", nrgba64.R)
+ default:
+ if useTransparent {
+ fmt.Fprintf(w, "%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B)
+ } else {
+ fmt.Fprintf(w, "%04x%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B, nrgba64.A)
+ }
+ }
}
case cpm != nil:
var b, c int
@@ -256,8 +382,23 @@ func TestReader(t *testing.T) {
}
ps := pb.Text()
ss := sb.Text()
+
+ // Newer versions of the sng command line tool append an optional
+ // color name to the RGB tuple. For example:
+ // # rgb = (0xff,0xff,0xff) grey100
+ // # rgb = (0x00,0x00,0xff) blue1
+ // instead of the older version's plainer:
+ // # rgb = (0xff,0xff,0xff)
+ // # rgb = (0x00,0x00,0xff)
+ // We strip any such name.
+ if strings.Contains(ss, "# rgb = (") && !strings.HasSuffix(ss, ")") {
+ if i := strings.LastIndex(ss, ") "); i >= 0 {
+ ss = ss[:i+1]
+ }
+ }
+
if ps != ss {
- t.Errorf("%s: Mismatch\n%sversus\n%s\n", fn, ps, ss)
+ t.Errorf("%s: Mismatch\n%s\nversus\n%s\n", fn, ps, ss)
break
}
}
diff --git a/libgo/go/image/png/testdata/pngsuite/README b/libgo/go/image/png/testdata/pngsuite/README
index c0f78bde87a..01d1d896d6f 100644
--- a/libgo/go/image/png/testdata/pngsuite/README
+++ b/libgo/go/image/png/testdata/pngsuite/README
@@ -1,21 +1,20 @@
The *.png and README.original files in this directory are copied from
-libpng.org, specifically contrib/pngsuite/* in libpng-1.2.40.tar.gz.
+libpng.org, specifically contrib/pngsuite/* in libpng 1.6.26.
+
README.original gives the following license for those files:
Permission to use, copy, and distribute these images for any purpose
and without fee is hereby granted.
-
-The files basn0g01-30.png, basn0g02-29.png and basn0g04-31.png are in fact
-not part of pngsuite but were created from files in pngsuite. Their non-power-
-of-two sizes makes them useful for testing bit-depths smaller than a byte.
+The files basn0g01-30.png, basn0g02-29.png and basn0g04-31.png are in fact not
+part of pngsuite but were created from files in pngsuite. Their non-power-of-2
+sizes makes them useful for testing bit-depths smaller than a byte.
basn3a08.png was generated from basn6a08.png using the pngnq tool, which
converted it to the 8-bit paletted image with alpha values in tRNS chunk.
-The *.sng files in this directory were generated from the *.png files
-by the sng command-line tool and some hand editing. The files
-basn0g0{1,2,4}.sng were actually generated by first converting the PNG
-to a bitdepth of 8 and then running sng on them. basn4a08.sng was generated
-by from a 16-bit rgba version of basn4a08.png rather than the original
-gray + alpha.
+The *.sng files in this directory were generated from the *.png files by the
+sng command-line tool and some hand editing. The files basn0g0{1,2,4}.sng and
+ftbbn0g0{1,2,4}.sng were actually generated by first converting the PNG to a
+bitdepth of 8 and then running sng on them. basn4a08.sng was generated from a
+16-bit rgba version of basn4a08.png rather than the original gray + alpha.
diff --git a/libgo/go/image/png/writer.go b/libgo/go/image/png/writer.go
index df23270ee97..dd87d816291 100644
--- a/libgo/go/image/png/writer.go
+++ b/libgo/go/image/png/writer.go
@@ -420,8 +420,11 @@ func writeImage(w io.Writer, m image.Image, cb int, level int) error {
}
// Apply the filter.
+ // Skip filter for NoCompression and paletted images (cbP8) as
+ // "filters are rarely useful on palette images" and will result
+ // in larger files (see http://www.libpng.org/pub/png/book/chapter09.html).
f := ftNone
- if level != zlib.NoCompression {
+ if level != zlib.NoCompression && cb != cbP8 {
f = filter(&cr, pr, bpp)
}
diff --git a/libgo/go/index/suffixarray/example_test.go b/libgo/go/index/suffixarray/example_test.go
new file mode 100644
index 00000000000..a23a58026be
--- /dev/null
+++ b/libgo/go/index/suffixarray/example_test.go
@@ -0,0 +1,24 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package suffixarray_test
+
+import (
+ "fmt"
+ "index/suffixarray"
+)
+
+func ExampleIndex_Lookup() {
+ index := suffixarray.New([]byte("banana"))
+ offsets := index.Lookup([]byte("ana"), -1)
+ for _, off := range offsets {
+ fmt.Println(off)
+ }
+
+ // Unordered output:
+ // 1
+ // 3
+}
diff --git a/libgo/go/internal/pprof/profile/encode.go b/libgo/go/internal/pprof/profile/encode.go
new file mode 100644
index 00000000000..6b879a84acd
--- /dev/null
+++ b/libgo/go/internal/pprof/profile/encode.go
@@ -0,0 +1,470 @@
+// 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 profile
+
+import (
+ "errors"
+ "fmt"
+ "sort"
+)
+
+func (p *Profile) decoder() []decoder {
+ return profileDecoder
+}
+
+// preEncode populates the unexported fields to be used by encode
+// (with suffix X) from the corresponding exported fields. The
+// exported fields are cleared up to facilitate testing.
+func (p *Profile) preEncode() {
+ strings := make(map[string]int)
+ addString(strings, "")
+
+ for _, st := range p.SampleType {
+ st.typeX = addString(strings, st.Type)
+ st.unitX = addString(strings, st.Unit)
+ }
+
+ for _, s := range p.Sample {
+ s.labelX = nil
+ var keys []string
+ for k := range s.Label {
+ keys = append(keys, k)
+ }
+ sort.Strings(keys)
+ for _, k := range keys {
+ vs := s.Label[k]
+ for _, v := range vs {
+ s.labelX = append(s.labelX,
+ Label{
+ keyX: addString(strings, k),
+ strX: addString(strings, v),
+ },
+ )
+ }
+ }
+ var numKeys []string
+ for k := range s.NumLabel {
+ numKeys = append(numKeys, k)
+ }
+ sort.Strings(numKeys)
+ for _, k := range numKeys {
+ vs := s.NumLabel[k]
+ for _, v := range vs {
+ s.labelX = append(s.labelX,
+ Label{
+ keyX: addString(strings, k),
+ numX: v,
+ },
+ )
+ }
+ }
+ s.locationIDX = nil
+ for _, l := range s.Location {
+ s.locationIDX = append(s.locationIDX, l.ID)
+ }
+ }
+
+ for _, m := range p.Mapping {
+ m.fileX = addString(strings, m.File)
+ m.buildIDX = addString(strings, m.BuildID)
+ }
+
+ for _, l := range p.Location {
+ for i, ln := range l.Line {
+ if ln.Function != nil {
+ l.Line[i].functionIDX = ln.Function.ID
+ } else {
+ l.Line[i].functionIDX = 0
+ }
+ }
+ if l.Mapping != nil {
+ l.mappingIDX = l.Mapping.ID
+ } else {
+ l.mappingIDX = 0
+ }
+ }
+ for _, f := range p.Function {
+ f.nameX = addString(strings, f.Name)
+ f.systemNameX = addString(strings, f.SystemName)
+ f.filenameX = addString(strings, f.Filename)
+ }
+
+ p.dropFramesX = addString(strings, p.DropFrames)
+ p.keepFramesX = addString(strings, p.KeepFrames)
+
+ if pt := p.PeriodType; pt != nil {
+ pt.typeX = addString(strings, pt.Type)
+ pt.unitX = addString(strings, pt.Unit)
+ }
+
+ p.stringTable = make([]string, len(strings))
+ for s, i := range strings {
+ p.stringTable[i] = s
+ }
+}
+
+func (p *Profile) encode(b *buffer) {
+ for _, x := range p.SampleType {
+ encodeMessage(b, 1, x)
+ }
+ for _, x := range p.Sample {
+ encodeMessage(b, 2, x)
+ }
+ for _, x := range p.Mapping {
+ encodeMessage(b, 3, x)
+ }
+ for _, x := range p.Location {
+ encodeMessage(b, 4, x)
+ }
+ for _, x := range p.Function {
+ encodeMessage(b, 5, x)
+ }
+ encodeStrings(b, 6, p.stringTable)
+ encodeInt64Opt(b, 7, p.dropFramesX)
+ encodeInt64Opt(b, 8, p.keepFramesX)
+ encodeInt64Opt(b, 9, p.TimeNanos)
+ encodeInt64Opt(b, 10, p.DurationNanos)
+ if pt := p.PeriodType; pt != nil && (pt.typeX != 0 || pt.unitX != 0) {
+ encodeMessage(b, 11, p.PeriodType)
+ }
+ encodeInt64Opt(b, 12, p.Period)
+}
+
+var profileDecoder = []decoder{
+ nil, // 0
+ // repeated ValueType sample_type = 1
+ func(b *buffer, m message) error {
+ x := new(ValueType)
+ pp := m.(*Profile)
+ pp.SampleType = append(pp.SampleType, x)
+ return decodeMessage(b, x)
+ },
+ // repeated Sample sample = 2
+ func(b *buffer, m message) error {
+ x := new(Sample)
+ pp := m.(*Profile)
+ pp.Sample = append(pp.Sample, x)
+ return decodeMessage(b, x)
+ },
+ // repeated Mapping mapping = 3
+ func(b *buffer, m message) error {
+ x := new(Mapping)
+ pp := m.(*Profile)
+ pp.Mapping = append(pp.Mapping, x)
+ return decodeMessage(b, x)
+ },
+ // repeated Location location = 4
+ func(b *buffer, m message) error {
+ x := new(Location)
+ pp := m.(*Profile)
+ pp.Location = append(pp.Location, x)
+ return decodeMessage(b, x)
+ },
+ // repeated Function function = 5
+ func(b *buffer, m message) error {
+ x := new(Function)
+ pp := m.(*Profile)
+ pp.Function = append(pp.Function, x)
+ return decodeMessage(b, x)
+ },
+ // repeated string string_table = 6
+ func(b *buffer, m message) error {
+ err := decodeStrings(b, &m.(*Profile).stringTable)
+ if err != nil {
+ return err
+ }
+ if *&m.(*Profile).stringTable[0] != "" {
+ return errors.New("string_table[0] must be ''")
+ }
+ return nil
+ },
+ // repeated int64 drop_frames = 7
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).dropFramesX) },
+ // repeated int64 keep_frames = 8
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).keepFramesX) },
+ // repeated int64 time_nanos = 9
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).TimeNanos) },
+ // repeated int64 duration_nanos = 10
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).DurationNanos) },
+ // optional string period_type = 11
+ func(b *buffer, m message) error {
+ x := new(ValueType)
+ pp := m.(*Profile)
+ pp.PeriodType = x
+ return decodeMessage(b, x)
+ },
+ // repeated int64 period = 12
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Profile).Period) },
+}
+
+// postDecode takes the unexported fields populated by decode (with
+// suffix X) and populates the corresponding exported fields.
+// The unexported fields are cleared up to facilitate testing.
+func (p *Profile) postDecode() error {
+ var err error
+
+ mappings := make(map[uint64]*Mapping)
+ for _, m := range p.Mapping {
+ m.File, err = getString(p.stringTable, &m.fileX, err)
+ m.BuildID, err = getString(p.stringTable, &m.buildIDX, err)
+ mappings[m.ID] = m
+ }
+
+ functions := make(map[uint64]*Function)
+ for _, f := range p.Function {
+ f.Name, err = getString(p.stringTable, &f.nameX, err)
+ f.SystemName, err = getString(p.stringTable, &f.systemNameX, err)
+ f.Filename, err = getString(p.stringTable, &f.filenameX, err)
+ functions[f.ID] = f
+ }
+
+ locations := make(map[uint64]*Location)
+ for _, l := range p.Location {
+ l.Mapping = mappings[l.mappingIDX]
+ l.mappingIDX = 0
+ for i, ln := range l.Line {
+ if id := ln.functionIDX; id != 0 {
+ l.Line[i].Function = functions[id]
+ if l.Line[i].Function == nil {
+ return fmt.Errorf("Function ID %d not found", id)
+ }
+ l.Line[i].functionIDX = 0
+ }
+ }
+ locations[l.ID] = l
+ }
+
+ for _, st := range p.SampleType {
+ st.Type, err = getString(p.stringTable, &st.typeX, err)
+ st.Unit, err = getString(p.stringTable, &st.unitX, err)
+ }
+
+ for _, s := range p.Sample {
+ labels := make(map[string][]string)
+ numLabels := make(map[string][]int64)
+ for _, l := range s.labelX {
+ var key, value string
+ key, err = getString(p.stringTable, &l.keyX, err)
+ if l.strX != 0 {
+ value, err = getString(p.stringTable, &l.strX, err)
+ labels[key] = append(labels[key], value)
+ } else {
+ numLabels[key] = append(numLabels[key], l.numX)
+ }
+ }
+ if len(labels) > 0 {
+ s.Label = labels
+ }
+ if len(numLabels) > 0 {
+ s.NumLabel = numLabels
+ }
+ s.Location = nil
+ for _, lid := range s.locationIDX {
+ s.Location = append(s.Location, locations[lid])
+ }
+ s.locationIDX = nil
+ }
+
+ p.DropFrames, err = getString(p.stringTable, &p.dropFramesX, err)
+ p.KeepFrames, err = getString(p.stringTable, &p.keepFramesX, err)
+
+ if pt := p.PeriodType; pt == nil {
+ p.PeriodType = &ValueType{}
+ }
+
+ if pt := p.PeriodType; pt != nil {
+ pt.Type, err = getString(p.stringTable, &pt.typeX, err)
+ pt.Unit, err = getString(p.stringTable, &pt.unitX, err)
+ }
+ p.stringTable = nil
+ return nil
+}
+
+func (p *ValueType) decoder() []decoder {
+ return valueTypeDecoder
+}
+
+func (p *ValueType) encode(b *buffer) {
+ encodeInt64Opt(b, 1, p.typeX)
+ encodeInt64Opt(b, 2, p.unitX)
+}
+
+var valueTypeDecoder = []decoder{
+ nil, // 0
+ // optional int64 type = 1
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).typeX) },
+ // optional int64 unit = 2
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*ValueType).unitX) },
+}
+
+func (p *Sample) decoder() []decoder {
+ return sampleDecoder
+}
+
+func (p *Sample) encode(b *buffer) {
+ encodeUint64s(b, 1, p.locationIDX)
+ for _, x := range p.Value {
+ encodeInt64(b, 2, x)
+ }
+ for _, x := range p.labelX {
+ encodeMessage(b, 3, x)
+ }
+}
+
+var sampleDecoder = []decoder{
+ nil, // 0
+ // repeated uint64 location = 1
+ func(b *buffer, m message) error { return decodeUint64s(b, &m.(*Sample).locationIDX) },
+ // repeated int64 value = 2
+ func(b *buffer, m message) error { return decodeInt64s(b, &m.(*Sample).Value) },
+ // repeated Label label = 3
+ func(b *buffer, m message) error {
+ s := m.(*Sample)
+ n := len(s.labelX)
+ s.labelX = append(s.labelX, Label{})
+ return decodeMessage(b, &s.labelX[n])
+ },
+}
+
+func (p Label) decoder() []decoder {
+ return labelDecoder
+}
+
+func (p Label) encode(b *buffer) {
+ encodeInt64Opt(b, 1, p.keyX)
+ encodeInt64Opt(b, 2, p.strX)
+ encodeInt64Opt(b, 3, p.numX)
+}
+
+var labelDecoder = []decoder{
+ nil, // 0
+ // optional int64 key = 1
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).keyX) },
+ // optional int64 str = 2
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).strX) },
+ // optional int64 num = 3
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Label).numX) },
+}
+
+func (p *Mapping) decoder() []decoder {
+ return mappingDecoder
+}
+
+func (p *Mapping) encode(b *buffer) {
+ encodeUint64Opt(b, 1, p.ID)
+ encodeUint64Opt(b, 2, p.Start)
+ encodeUint64Opt(b, 3, p.Limit)
+ encodeUint64Opt(b, 4, p.Offset)
+ encodeInt64Opt(b, 5, p.fileX)
+ encodeInt64Opt(b, 6, p.buildIDX)
+ encodeBoolOpt(b, 7, p.HasFunctions)
+ encodeBoolOpt(b, 8, p.HasFilenames)
+ encodeBoolOpt(b, 9, p.HasLineNumbers)
+ encodeBoolOpt(b, 10, p.HasInlineFrames)
+}
+
+var mappingDecoder = []decoder{
+ nil, // 0
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).ID) }, // optional uint64 id = 1
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Start) }, // optional uint64 memory_offset = 2
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Limit) }, // optional uint64 memory_limit = 3
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Mapping).Offset) }, // optional uint64 file_offset = 4
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).fileX) }, // optional int64 filename = 5
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Mapping).buildIDX) }, // optional int64 build_id = 6
+ func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFunctions) }, // optional bool has_functions = 7
+ func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasFilenames) }, // optional bool has_filenames = 8
+ func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasLineNumbers) }, // optional bool has_line_numbers = 9
+ func(b *buffer, m message) error { return decodeBool(b, &m.(*Mapping).HasInlineFrames) }, // optional bool has_inline_frames = 10
+}
+
+func (p *Location) decoder() []decoder {
+ return locationDecoder
+}
+
+func (p *Location) encode(b *buffer) {
+ encodeUint64Opt(b, 1, p.ID)
+ encodeUint64Opt(b, 2, p.mappingIDX)
+ encodeUint64Opt(b, 3, p.Address)
+ for i := range p.Line {
+ encodeMessage(b, 4, &p.Line[i])
+ }
+}
+
+var locationDecoder = []decoder{
+ nil, // 0
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).ID) }, // optional uint64 id = 1;
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).mappingIDX) }, // optional uint64 mapping_id = 2;
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Location).Address) }, // optional uint64 address = 3;
+ func(b *buffer, m message) error { // repeated Line line = 4
+ pp := m.(*Location)
+ n := len(pp.Line)
+ pp.Line = append(pp.Line, Line{})
+ return decodeMessage(b, &pp.Line[n])
+ },
+}
+
+func (p *Line) decoder() []decoder {
+ return lineDecoder
+}
+
+func (p *Line) encode(b *buffer) {
+ encodeUint64Opt(b, 1, p.functionIDX)
+ encodeInt64Opt(b, 2, p.Line)
+}
+
+var lineDecoder = []decoder{
+ nil, // 0
+ // optional uint64 function_id = 1
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Line).functionIDX) },
+ // optional int64 line = 2
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Line).Line) },
+}
+
+func (p *Function) decoder() []decoder {
+ return functionDecoder
+}
+
+func (p *Function) encode(b *buffer) {
+ encodeUint64Opt(b, 1, p.ID)
+ encodeInt64Opt(b, 2, p.nameX)
+ encodeInt64Opt(b, 3, p.systemNameX)
+ encodeInt64Opt(b, 4, p.filenameX)
+ encodeInt64Opt(b, 5, p.StartLine)
+}
+
+var functionDecoder = []decoder{
+ nil, // 0
+ // optional uint64 id = 1
+ func(b *buffer, m message) error { return decodeUint64(b, &m.(*Function).ID) },
+ // optional int64 function_name = 2
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).nameX) },
+ // optional int64 function_system_name = 3
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).systemNameX) },
+ // repeated int64 filename = 4
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).filenameX) },
+ // optional int64 start_line = 5
+ func(b *buffer, m message) error { return decodeInt64(b, &m.(*Function).StartLine) },
+}
+
+func addString(strings map[string]int, s string) int64 {
+ i, ok := strings[s]
+ if !ok {
+ i = len(strings)
+ strings[s] = i
+ }
+ return int64(i)
+}
+
+func getString(strings []string, strng *int64, err error) (string, error) {
+ if err != nil {
+ return "", err
+ }
+ s := int(*strng)
+ if s < 0 || s >= len(strings) {
+ return "", errMalformed
+ }
+ *strng = 0
+ return strings[s], nil
+}
diff --git a/libgo/go/internal/pprof/profile/filter.go b/libgo/go/internal/pprof/profile/filter.go
new file mode 100644
index 00000000000..1baa096a49c
--- /dev/null
+++ b/libgo/go/internal/pprof/profile/filter.go
@@ -0,0 +1,158 @@
+// 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.
+
+// Implements methods to filter samples from profiles.
+
+package profile
+
+import "regexp"
+
+// FilterSamplesByName filters the samples in a profile and only keeps
+// samples where at least one frame matches focus but none match ignore.
+// Returns true is the corresponding regexp matched at least one sample.
+func (p *Profile) FilterSamplesByName(focus, ignore, hide *regexp.Regexp) (fm, im, hm bool) {
+ focusOrIgnore := make(map[uint64]bool)
+ hidden := make(map[uint64]bool)
+ for _, l := range p.Location {
+ if ignore != nil && l.matchesName(ignore) {
+ im = true
+ focusOrIgnore[l.ID] = false
+ } else if focus == nil || l.matchesName(focus) {
+ fm = true
+ focusOrIgnore[l.ID] = true
+ }
+ if hide != nil && l.matchesName(hide) {
+ hm = true
+ l.Line = l.unmatchedLines(hide)
+ if len(l.Line) == 0 {
+ hidden[l.ID] = true
+ }
+ }
+ }
+
+ s := make([]*Sample, 0, len(p.Sample))
+ for _, sample := range p.Sample {
+ if focusedAndNotIgnored(sample.Location, focusOrIgnore) {
+ if len(hidden) > 0 {
+ var locs []*Location
+ for _, loc := range sample.Location {
+ if !hidden[loc.ID] {
+ locs = append(locs, loc)
+ }
+ }
+ if len(locs) == 0 {
+ // Remove sample with no locations (by not adding it to s).
+ continue
+ }
+ sample.Location = locs
+ }
+ s = append(s, sample)
+ }
+ }
+ p.Sample = s
+
+ return
+}
+
+// matchesName returns whether the function name or file in the
+// location matches the regular expression.
+func (loc *Location) matchesName(re *regexp.Regexp) bool {
+ for _, ln := range loc.Line {
+ if fn := ln.Function; fn != nil {
+ if re.MatchString(fn.Name) {
+ return true
+ }
+ if re.MatchString(fn.Filename) {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+// unmatchedLines returns the lines in the location that do not match
+// the regular expression.
+func (loc *Location) unmatchedLines(re *regexp.Regexp) []Line {
+ var lines []Line
+ for _, ln := range loc.Line {
+ if fn := ln.Function; fn != nil {
+ if re.MatchString(fn.Name) {
+ continue
+ }
+ if re.MatchString(fn.Filename) {
+ continue
+ }
+ }
+ lines = append(lines, ln)
+ }
+ return lines
+}
+
+// focusedAndNotIgnored looks up a slice of ids against a map of
+// focused/ignored locations. The map only contains locations that are
+// explicitly focused or ignored. Returns whether there is at least
+// one focused location but no ignored locations.
+func focusedAndNotIgnored(locs []*Location, m map[uint64]bool) bool {
+ var f bool
+ for _, loc := range locs {
+ if focus, focusOrIgnore := m[loc.ID]; focusOrIgnore {
+ if focus {
+ // Found focused location. Must keep searching in case there
+ // is an ignored one as well.
+ f = true
+ } else {
+ // Found ignored location. Can return false right away.
+ return false
+ }
+ }
+ }
+ return f
+}
+
+// TagMatch selects tags for filtering
+type TagMatch func(key, val string, nval int64) bool
+
+// FilterSamplesByTag removes all samples from the profile, except
+// those that match focus and do not match the ignore regular
+// expression.
+func (p *Profile) FilterSamplesByTag(focus, ignore TagMatch) (fm, im bool) {
+ samples := make([]*Sample, 0, len(p.Sample))
+ for _, s := range p.Sample {
+ focused, ignored := focusedSample(s, focus, ignore)
+ fm = fm || focused
+ im = im || ignored
+ if focused && !ignored {
+ samples = append(samples, s)
+ }
+ }
+ p.Sample = samples
+ return
+}
+
+// focusedTag checks a sample against focus and ignore regexps.
+// Returns whether the focus/ignore regexps match any tags
+func focusedSample(s *Sample, focus, ignore TagMatch) (fm, im bool) {
+ fm = focus == nil
+ for key, vals := range s.Label {
+ for _, val := range vals {
+ if ignore != nil && ignore(key, val, 0) {
+ im = true
+ }
+ if !fm && focus(key, val, 0) {
+ fm = true
+ }
+ }
+ }
+ for key, vals := range s.NumLabel {
+ for _, val := range vals {
+ if ignore != nil && ignore(key, "", val) {
+ im = true
+ }
+ if !fm && focus(key, "", val) {
+ fm = true
+ }
+ }
+ }
+ return fm, im
+}
diff --git a/libgo/go/internal/pprof/profile/legacy_profile.go b/libgo/go/internal/pprof/profile/legacy_profile.go
new file mode 100644
index 00000000000..d69f8deee7c
--- /dev/null
+++ b/libgo/go/internal/pprof/profile/legacy_profile.go
@@ -0,0 +1,1266 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements parsers to convert legacy profiles into the
+// profile.proto format.
+
+package profile
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "math"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var (
+ countStartRE = regexp.MustCompile(`\A(\w+) profile: total \d+\n\z`)
+ countRE = regexp.MustCompile(`\A(\d+) @(( 0x[0-9a-f]+)+)\n\z`)
+
+ heapHeaderRE = regexp.MustCompile(`heap profile: *(\d+): *(\d+) *\[ *(\d+): *(\d+) *\] *@ *(heap[_a-z0-9]*)/?(\d*)`)
+ heapSampleRE = regexp.MustCompile(`(-?\d+): *(-?\d+) *\[ *(\d+): *(\d+) *] @([ x0-9a-f]*)`)
+
+ contentionSampleRE = regexp.MustCompile(`(\d+) *(\d+) @([ x0-9a-f]*)`)
+
+ hexNumberRE = regexp.MustCompile(`0x[0-9a-f]+`)
+
+ growthHeaderRE = regexp.MustCompile(`heap profile: *(\d+): *(\d+) *\[ *(\d+): *(\d+) *\] @ growthz`)
+
+ fragmentationHeaderRE = regexp.MustCompile(`heap profile: *(\d+): *(\d+) *\[ *(\d+): *(\d+) *\] @ fragmentationz`)
+
+ threadzStartRE = regexp.MustCompile(`--- threadz \d+ ---`)
+ threadStartRE = regexp.MustCompile(`--- Thread ([[:xdigit:]]+) \(name: (.*)/(\d+)\) stack: ---`)
+
+ procMapsRE = regexp.MustCompile(`([[:xdigit:]]+)-([[:xdigit:]]+)\s+([-rwxp]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]+):([[:xdigit:]]+)\s+([[:digit:]]+)\s*(\S+)?`)
+
+ briefMapsRE = regexp.MustCompile(`\s*([[:xdigit:]]+)-([[:xdigit:]]+):\s*(\S+)(\s.*@)?([[:xdigit:]]+)?`)
+
+ // LegacyHeapAllocated instructs the heapz parsers to use the
+ // allocated memory stats instead of the default in-use memory. Note
+ // that tcmalloc doesn't provide all allocated memory, only in-use
+ // stats.
+ LegacyHeapAllocated bool
+)
+
+func isSpaceOrComment(line string) bool {
+ trimmed := strings.TrimSpace(line)
+ return len(trimmed) == 0 || trimmed[0] == '#'
+}
+
+// parseGoCount parses a Go count profile (e.g., threadcreate or
+// goroutine) and returns a new Profile.
+func parseGoCount(b []byte) (*Profile, error) {
+ r := bytes.NewBuffer(b)
+
+ var line string
+ var err error
+ for {
+ // Skip past comments and empty lines seeking a real header.
+ line, err = r.ReadString('\n')
+ if err != nil {
+ return nil, err
+ }
+ if !isSpaceOrComment(line) {
+ break
+ }
+ }
+
+ m := countStartRE.FindStringSubmatch(line)
+ if m == nil {
+ return nil, errUnrecognized
+ }
+ profileType := m[1]
+ p := &Profile{
+ PeriodType: &ValueType{Type: profileType, Unit: "count"},
+ Period: 1,
+ SampleType: []*ValueType{{Type: profileType, Unit: "count"}},
+ }
+ locations := make(map[uint64]*Location)
+ for {
+ line, err = r.ReadString('\n')
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return nil, err
+ }
+ if isSpaceOrComment(line) {
+ continue
+ }
+ if strings.HasPrefix(line, "---") {
+ break
+ }
+ m := countRE.FindStringSubmatch(line)
+ if m == nil {
+ return nil, errMalformed
+ }
+ n, err := strconv.ParseInt(m[1], 0, 64)
+ if err != nil {
+ return nil, errMalformed
+ }
+ fields := strings.Fields(m[2])
+ locs := make([]*Location, 0, len(fields))
+ for _, stk := range fields {
+ addr, err := strconv.ParseUint(stk, 0, 64)
+ if err != nil {
+ return nil, errMalformed
+ }
+ // Adjust all frames by -1 to land on the call instruction.
+ addr--
+ loc := locations[addr]
+ if loc == nil {
+ loc = &Location{
+ Address: addr,
+ }
+ locations[addr] = loc
+ p.Location = append(p.Location, loc)
+ }
+ locs = append(locs, loc)
+ }
+ p.Sample = append(p.Sample, &Sample{
+ Location: locs,
+ Value: []int64{n},
+ })
+ }
+
+ if err = parseAdditionalSections(strings.TrimSpace(line), r, p); err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+// remapLocationIDs ensures there is a location for each address
+// referenced by a sample, and remaps the samples to point to the new
+// location ids.
+func (p *Profile) remapLocationIDs() {
+ seen := make(map[*Location]bool, len(p.Location))
+ var locs []*Location
+
+ for _, s := range p.Sample {
+ for _, l := range s.Location {
+ if seen[l] {
+ continue
+ }
+ l.ID = uint64(len(locs) + 1)
+ locs = append(locs, l)
+ seen[l] = true
+ }
+ }
+ p.Location = locs
+}
+
+func (p *Profile) remapFunctionIDs() {
+ seen := make(map[*Function]bool, len(p.Function))
+ var fns []*Function
+
+ for _, l := range p.Location {
+ for _, ln := range l.Line {
+ fn := ln.Function
+ if fn == nil || seen[fn] {
+ continue
+ }
+ fn.ID = uint64(len(fns) + 1)
+ fns = append(fns, fn)
+ seen[fn] = true
+ }
+ }
+ p.Function = fns
+}
+
+// remapMappingIDs matches location addresses with existing mappings
+// and updates them appropriately. This is O(N*M), if this ever shows
+// up as a bottleneck, evaluate sorting the mappings and doing a
+// binary search, which would make it O(N*log(M)).
+func (p *Profile) remapMappingIDs() {
+ if len(p.Mapping) == 0 {
+ return
+ }
+
+ // Some profile handlers will incorrectly set regions for the main
+ // executable if its section is remapped. Fix them through heuristics.
+
+ // Remove the initial mapping if named '/anon_hugepage' and has a
+ // consecutive adjacent mapping.
+ if m := p.Mapping[0]; strings.HasPrefix(m.File, "/anon_hugepage") {
+ if len(p.Mapping) > 1 && m.Limit == p.Mapping[1].Start {
+ p.Mapping = p.Mapping[1:]
+ }
+ }
+
+ // Subtract the offset from the start of the main mapping if it
+ // ends up at a recognizable start address.
+ const expectedStart = 0x400000
+ if m := p.Mapping[0]; m.Start-m.Offset == expectedStart {
+ m.Start = expectedStart
+ m.Offset = 0
+ }
+
+ for _, l := range p.Location {
+ if a := l.Address; a != 0 {
+ for _, m := range p.Mapping {
+ if m.Start <= a && a < m.Limit {
+ l.Mapping = m
+ break
+ }
+ }
+ }
+ }
+
+ // Reset all mapping IDs.
+ for i, m := range p.Mapping {
+ m.ID = uint64(i + 1)
+ }
+}
+
+var cpuInts = []func([]byte) (uint64, []byte){
+ get32l,
+ get32b,
+ get64l,
+ get64b,
+}
+
+func get32l(b []byte) (uint64, []byte) {
+ if len(b) < 4 {
+ return 0, nil
+ }
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24, b[4:]
+}
+
+func get32b(b []byte) (uint64, []byte) {
+ if len(b) < 4 {
+ return 0, nil
+ }
+ return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24, b[4:]
+}
+
+func get64l(b []byte) (uint64, []byte) {
+ if len(b) < 8 {
+ return 0, nil
+ }
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56, b[8:]
+}
+
+func get64b(b []byte) (uint64, []byte) {
+ if len(b) < 8 {
+ return 0, nil
+ }
+ return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56, b[8:]
+}
+
+// ParseTracebacks parses a set of tracebacks and returns a newly
+// populated profile. It will accept any text file and generate a
+// Profile out of it with any hex addresses it can identify, including
+// a process map if it can recognize one. Each sample will include a
+// tag "source" with the addresses recognized in string format.
+func ParseTracebacks(b []byte) (*Profile, error) {
+ r := bytes.NewBuffer(b)
+
+ p := &Profile{
+ PeriodType: &ValueType{Type: "trace", Unit: "count"},
+ Period: 1,
+ SampleType: []*ValueType{
+ {Type: "trace", Unit: "count"},
+ },
+ }
+
+ var sources []string
+ var sloc []*Location
+
+ locs := make(map[uint64]*Location)
+ for {
+ l, err := r.ReadString('\n')
+ if err != nil {
+ if err != io.EOF {
+ return nil, err
+ }
+ if l == "" {
+ break
+ }
+ }
+ if sectionTrigger(l) == memoryMapSection {
+ break
+ }
+ if s, addrs := extractHexAddresses(l); len(s) > 0 {
+ for _, addr := range addrs {
+ // Addresses from stack traces point to the next instruction after
+ // each call. Adjust by -1 to land somewhere on the actual call.
+ addr--
+ loc := locs[addr]
+ if locs[addr] == nil {
+ loc = &Location{
+ Address: addr,
+ }
+ p.Location = append(p.Location, loc)
+ locs[addr] = loc
+ }
+ sloc = append(sloc, loc)
+ }
+
+ sources = append(sources, s...)
+ } else {
+ if len(sources) > 0 || len(sloc) > 0 {
+ addTracebackSample(sloc, sources, p)
+ sloc, sources = nil, nil
+ }
+ }
+ }
+
+ // Add final sample to save any leftover data.
+ if len(sources) > 0 || len(sloc) > 0 {
+ addTracebackSample(sloc, sources, p)
+ }
+
+ if err := p.ParseMemoryMap(r); err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+func addTracebackSample(l []*Location, s []string, p *Profile) {
+ p.Sample = append(p.Sample,
+ &Sample{
+ Value: []int64{1},
+ Location: l,
+ Label: map[string][]string{"source": s},
+ })
+}
+
+// parseCPU parses a profilez legacy profile and returns a newly
+// populated Profile.
+//
+// The general format for profilez samples is a sequence of words in
+// binary format. The first words are a header with the following data:
+// 1st word -- 0
+// 2nd word -- 3
+// 3rd word -- 0 if a c++ application, 1 if a java application.
+// 4th word -- Sampling period (in microseconds).
+// 5th word -- Padding.
+func parseCPU(b []byte) (*Profile, error) {
+ var parse func([]byte) (uint64, []byte)
+ var n1, n2, n3, n4, n5 uint64
+ for _, parse = range cpuInts {
+ var tmp []byte
+ n1, tmp = parse(b)
+ n2, tmp = parse(tmp)
+ n3, tmp = parse(tmp)
+ n4, tmp = parse(tmp)
+ n5, tmp = parse(tmp)
+
+ if tmp != nil && n1 == 0 && n2 == 3 && n3 == 0 && n4 > 0 && n5 == 0 {
+ b = tmp
+ return cpuProfile(b, int64(n4), parse)
+ }
+ }
+ return nil, errUnrecognized
+}
+
+// cpuProfile returns a new Profile from C++ profilez data.
+// b is the profile bytes after the header, period is the profiling
+// period, and parse is a function to parse 8-byte chunks from the
+// profile in its native endianness.
+func cpuProfile(b []byte, period int64, parse func(b []byte) (uint64, []byte)) (*Profile, error) {
+ p := &Profile{
+ Period: period * 1000,
+ PeriodType: &ValueType{Type: "cpu", Unit: "nanoseconds"},
+ SampleType: []*ValueType{
+ {Type: "samples", Unit: "count"},
+ {Type: "cpu", Unit: "nanoseconds"},
+ },
+ }
+ var err error
+ if b, _, err = parseCPUSamples(b, parse, true, p); err != nil {
+ return nil, err
+ }
+
+ // If all samples have the same second-to-the-bottom frame, it
+ // strongly suggests that it is an uninteresting artifact of
+ // measurement -- a stack frame pushed by the signal handler. The
+ // bottom frame is always correct as it is picked up from the signal
+ // structure, not the stack. Check if this is the case and if so,
+ // remove.
+ if len(p.Sample) > 1 && len(p.Sample[0].Location) > 1 {
+ allSame := true
+ id1 := p.Sample[0].Location[1].Address
+ for _, s := range p.Sample {
+ if len(s.Location) < 2 || id1 != s.Location[1].Address {
+ allSame = false
+ break
+ }
+ }
+ if allSame {
+ for _, s := range p.Sample {
+ s.Location = append(s.Location[:1], s.Location[2:]...)
+ }
+ }
+ }
+
+ if err := p.ParseMemoryMap(bytes.NewBuffer(b)); err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+// parseCPUSamples parses a collection of profilez samples from a
+// profile.
+//
+// profilez samples are a repeated sequence of stack frames of the
+// form:
+// 1st word -- The number of times this stack was encountered.
+// 2nd word -- The size of the stack (StackSize).
+// 3rd word -- The first address on the stack.
+// ...
+// StackSize + 2 -- The last address on the stack
+// The last stack trace is of the form:
+// 1st word -- 0
+// 2nd word -- 1
+// 3rd word -- 0
+//
+// Addresses from stack traces may point to the next instruction after
+// each call. Optionally adjust by -1 to land somewhere on the actual
+// call (except for the leaf, which is not a call).
+func parseCPUSamples(b []byte, parse func(b []byte) (uint64, []byte), adjust bool, p *Profile) ([]byte, map[uint64]*Location, error) {
+ locs := make(map[uint64]*Location)
+ for len(b) > 0 {
+ var count, nstk uint64
+ count, b = parse(b)
+ nstk, b = parse(b)
+ if b == nil || nstk > uint64(len(b)/4) {
+ return nil, nil, errUnrecognized
+ }
+ var sloc []*Location
+ addrs := make([]uint64, nstk)
+ for i := 0; i < int(nstk); i++ {
+ addrs[i], b = parse(b)
+ }
+
+ if count == 0 && nstk == 1 && addrs[0] == 0 {
+ // End of data marker
+ break
+ }
+ for i, addr := range addrs {
+ if adjust && i > 0 {
+ addr--
+ }
+ loc := locs[addr]
+ if loc == nil {
+ loc = &Location{
+ Address: addr,
+ }
+ locs[addr] = loc
+ p.Location = append(p.Location, loc)
+ }
+ sloc = append(sloc, loc)
+ }
+ p.Sample = append(p.Sample,
+ &Sample{
+ Value: []int64{int64(count), int64(count) * p.Period},
+ Location: sloc,
+ })
+ }
+ // Reached the end without finding the EOD marker.
+ return b, locs, nil
+}
+
+// parseHeap parses a heapz legacy or a growthz profile and
+// returns a newly populated Profile.
+func parseHeap(b []byte) (p *Profile, err error) {
+ r := bytes.NewBuffer(b)
+ l, err := r.ReadString('\n')
+ if err != nil {
+ return nil, errUnrecognized
+ }
+
+ sampling := ""
+
+ if header := heapHeaderRE.FindStringSubmatch(l); header != nil {
+ p = &Profile{
+ SampleType: []*ValueType{
+ {Type: "objects", Unit: "count"},
+ {Type: "space", Unit: "bytes"},
+ },
+ PeriodType: &ValueType{Type: "objects", Unit: "bytes"},
+ }
+
+ var period int64
+ if len(header[6]) > 0 {
+ if period, err = strconv.ParseInt(header[6], 10, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ }
+
+ switch header[5] {
+ case "heapz_v2", "heap_v2":
+ sampling, p.Period = "v2", period
+ case "heapprofile":
+ sampling, p.Period = "", 1
+ case "heap":
+ sampling, p.Period = "v2", period/2
+ default:
+ return nil, errUnrecognized
+ }
+ } else if header = growthHeaderRE.FindStringSubmatch(l); header != nil {
+ p = &Profile{
+ SampleType: []*ValueType{
+ {Type: "objects", Unit: "count"},
+ {Type: "space", Unit: "bytes"},
+ },
+ PeriodType: &ValueType{Type: "heapgrowth", Unit: "count"},
+ Period: 1,
+ }
+ } else if header = fragmentationHeaderRE.FindStringSubmatch(l); header != nil {
+ p = &Profile{
+ SampleType: []*ValueType{
+ {Type: "objects", Unit: "count"},
+ {Type: "space", Unit: "bytes"},
+ },
+ PeriodType: &ValueType{Type: "allocations", Unit: "count"},
+ Period: 1,
+ }
+ } else {
+ return nil, errUnrecognized
+ }
+
+ if LegacyHeapAllocated {
+ for _, st := range p.SampleType {
+ st.Type = "alloc_" + st.Type
+ }
+ } else {
+ for _, st := range p.SampleType {
+ st.Type = "inuse_" + st.Type
+ }
+ }
+
+ locs := make(map[uint64]*Location)
+ for {
+ l, err = r.ReadString('\n')
+ if err != nil {
+ if err != io.EOF {
+ return nil, err
+ }
+
+ if l == "" {
+ break
+ }
+ }
+
+ if isSpaceOrComment(l) {
+ continue
+ }
+ l = strings.TrimSpace(l)
+
+ if sectionTrigger(l) != unrecognizedSection {
+ break
+ }
+
+ value, blocksize, addrs, err := parseHeapSample(l, p.Period, sampling)
+ if err != nil {
+ return nil, err
+ }
+ var sloc []*Location
+ for _, addr := range addrs {
+ // Addresses from stack traces point to the next instruction after
+ // each call. Adjust by -1 to land somewhere on the actual call.
+ addr--
+ loc := locs[addr]
+ if locs[addr] == nil {
+ loc = &Location{
+ Address: addr,
+ }
+ p.Location = append(p.Location, loc)
+ locs[addr] = loc
+ }
+ sloc = append(sloc, loc)
+ }
+
+ p.Sample = append(p.Sample, &Sample{
+ Value: value,
+ Location: sloc,
+ NumLabel: map[string][]int64{"bytes": {blocksize}},
+ })
+ }
+
+ if err = parseAdditionalSections(l, r, p); err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+// parseHeapSample parses a single row from a heap profile into a new Sample.
+func parseHeapSample(line string, rate int64, sampling string) (value []int64, blocksize int64, addrs []uint64, err error) {
+ sampleData := heapSampleRE.FindStringSubmatch(line)
+ if len(sampleData) != 6 {
+ return value, blocksize, addrs, fmt.Errorf("unexpected number of sample values: got %d, want 6", len(sampleData))
+ }
+
+ // Use first two values by default; tcmalloc sampling generates the
+ // same value for both, only the older heap-profile collect separate
+ // stats for in-use and allocated objects.
+ valueIndex := 1
+ if LegacyHeapAllocated {
+ valueIndex = 3
+ }
+
+ var v1, v2 int64
+ if v1, err = strconv.ParseInt(sampleData[valueIndex], 10, 64); err != nil {
+ return value, blocksize, addrs, fmt.Errorf("malformed sample: %s: %v", line, err)
+ }
+ if v2, err = strconv.ParseInt(sampleData[valueIndex+1], 10, 64); err != nil {
+ return value, blocksize, addrs, fmt.Errorf("malformed sample: %s: %v", line, err)
+ }
+
+ if v1 == 0 {
+ if v2 != 0 {
+ return value, blocksize, addrs, fmt.Errorf("allocation count was 0 but allocation bytes was %d", v2)
+ }
+ } else {
+ blocksize = v2 / v1
+ if sampling == "v2" {
+ v1, v2 = scaleHeapSample(v1, v2, rate)
+ }
+ }
+
+ value = []int64{v1, v2}
+ addrs = parseHexAddresses(sampleData[5])
+
+ return value, blocksize, addrs, nil
+}
+
+// extractHexAddresses extracts hex numbers from a string and returns
+// them, together with their numeric value, in a slice.
+func extractHexAddresses(s string) ([]string, []uint64) {
+ hexStrings := hexNumberRE.FindAllString(s, -1)
+ var ids []uint64
+ for _, s := range hexStrings {
+ if id, err := strconv.ParseUint(s, 0, 64); err == nil {
+ ids = append(ids, id)
+ } else {
+ // Do not expect any parsing failures due to the regexp matching.
+ panic("failed to parse hex value:" + s)
+ }
+ }
+ return hexStrings, ids
+}
+
+// parseHexAddresses parses hex numbers from a string and returns them
+// in a slice.
+func parseHexAddresses(s string) []uint64 {
+ _, ids := extractHexAddresses(s)
+ return ids
+}
+
+// scaleHeapSample adjusts the data from a heapz Sample to
+// account for its probability of appearing in the collected
+// data. heapz profiles are a sampling of the memory allocations
+// requests in a program. We estimate the unsampled value by dividing
+// each collected sample by its probability of appearing in the
+// profile. heapz v2 profiles rely on a poisson process to determine
+// which samples to collect, based on the desired average collection
+// rate R. The probability of a sample of size S to appear in that
+// profile is 1-exp(-S/R).
+func scaleHeapSample(count, size, rate int64) (int64, int64) {
+ if count == 0 || size == 0 {
+ return 0, 0
+ }
+
+ if rate <= 1 {
+ // if rate==1 all samples were collected so no adjustment is needed.
+ // if rate<1 treat as unknown and skip scaling.
+ return count, size
+ }
+
+ avgSize := float64(size) / float64(count)
+ scale := 1 / (1 - math.Exp(-avgSize/float64(rate)))
+
+ return int64(float64(count) * scale), int64(float64(size) * scale)
+}
+
+// parseContention parses a mutex or contention profile. There are 2 cases:
+// "--- contentionz " for legacy C++ profiles (and backwards compatibility)
+// "--- mutex:" or "--- contention:" for profiles generated by the Go runtime.
+// This code converts the text output from runtime into a *Profile. (In the future
+// the runtime might write a serialized Profile directly making this unnecessary.)
+func parseContention(b []byte) (*Profile, error) {
+ r := bytes.NewBuffer(b)
+ var l string
+ var err error
+ for {
+ // Skip past comments and empty lines seeking a real header.
+ l, err = r.ReadString('\n')
+ if err != nil {
+ return nil, err
+ }
+ if !isSpaceOrComment(l) {
+ break
+ }
+ }
+
+ if strings.HasPrefix(l, "--- contentionz ") {
+ return parseCppContention(r)
+ } else if strings.HasPrefix(l, "--- mutex:") {
+ return parseCppContention(r)
+ } else if strings.HasPrefix(l, "--- contention:") {
+ return parseCppContention(r)
+ }
+ return nil, errUnrecognized
+}
+
+// parseCppContention parses the output from synchronization_profiling.cc
+// for backward compatibility, and the compatible (non-debug) block profile
+// output from the Go runtime.
+func parseCppContention(r *bytes.Buffer) (*Profile, error) {
+ p := &Profile{
+ PeriodType: &ValueType{Type: "contentions", Unit: "count"},
+ Period: 1,
+ SampleType: []*ValueType{
+ {Type: "contentions", Unit: "count"},
+ {Type: "delay", Unit: "nanoseconds"},
+ },
+ }
+
+ var cpuHz int64
+ var l string
+ var err error
+ // Parse text of the form "attribute = value" before the samples.
+ const delimiter = "="
+ for {
+ l, err = r.ReadString('\n')
+ if err != nil {
+ if err != io.EOF {
+ return nil, err
+ }
+
+ if l == "" {
+ break
+ }
+ }
+ if isSpaceOrComment(l) {
+ continue
+ }
+
+ if l = strings.TrimSpace(l); l == "" {
+ continue
+ }
+
+ if strings.HasPrefix(l, "---") {
+ break
+ }
+
+ attr := strings.SplitN(l, delimiter, 2)
+ if len(attr) != 2 {
+ break
+ }
+ key, val := strings.TrimSpace(attr[0]), strings.TrimSpace(attr[1])
+ var err error
+ switch key {
+ case "cycles/second":
+ if cpuHz, err = strconv.ParseInt(val, 0, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ case "sampling period":
+ if p.Period, err = strconv.ParseInt(val, 0, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ case "ms since reset":
+ ms, err := strconv.ParseInt(val, 0, 64)
+ if err != nil {
+ return nil, errUnrecognized
+ }
+ p.DurationNanos = ms * 1000 * 1000
+ case "format":
+ // CPP contentionz profiles don't have format.
+ return nil, errUnrecognized
+ case "resolution":
+ // CPP contentionz profiles don't have resolution.
+ return nil, errUnrecognized
+ case "discarded samples":
+ default:
+ return nil, errUnrecognized
+ }
+ }
+
+ locs := make(map[uint64]*Location)
+ for {
+ if !isSpaceOrComment(l) {
+ if l = strings.TrimSpace(l); strings.HasPrefix(l, "---") {
+ break
+ }
+ value, addrs, err := parseContentionSample(l, p.Period, cpuHz)
+ if err != nil {
+ return nil, err
+ }
+ var sloc []*Location
+ for _, addr := range addrs {
+ // Addresses from stack traces point to the next instruction after
+ // each call. Adjust by -1 to land somewhere on the actual call.
+ addr--
+ loc := locs[addr]
+ if locs[addr] == nil {
+ loc = &Location{
+ Address: addr,
+ }
+ p.Location = append(p.Location, loc)
+ locs[addr] = loc
+ }
+ sloc = append(sloc, loc)
+ }
+ p.Sample = append(p.Sample, &Sample{
+ Value: value,
+ Location: sloc,
+ })
+ }
+
+ if l, err = r.ReadString('\n'); err != nil {
+ if err != io.EOF {
+ return nil, err
+ }
+ if l == "" {
+ break
+ }
+ }
+ }
+
+ if err = parseAdditionalSections(l, r, p); err != nil {
+ return nil, err
+ }
+
+ return p, nil
+}
+
+// parseContentionSample parses a single row from a contention profile
+// into a new Sample.
+func parseContentionSample(line string, period, cpuHz int64) (value []int64, addrs []uint64, err error) {
+ sampleData := contentionSampleRE.FindStringSubmatch(line)
+ if sampleData == nil {
+ return value, addrs, errUnrecognized
+ }
+
+ v1, err := strconv.ParseInt(sampleData[1], 10, 64)
+ if err != nil {
+ return value, addrs, fmt.Errorf("malformed sample: %s: %v", line, err)
+ }
+ v2, err := strconv.ParseInt(sampleData[2], 10, 64)
+ if err != nil {
+ return value, addrs, fmt.Errorf("malformed sample: %s: %v", line, err)
+ }
+
+ // Unsample values if period and cpuHz are available.
+ // - Delays are scaled to cycles and then to nanoseconds.
+ // - Contentions are scaled to cycles.
+ if period > 0 {
+ if cpuHz > 0 {
+ cpuGHz := float64(cpuHz) / 1e9
+ v1 = int64(float64(v1) * float64(period) / cpuGHz)
+ }
+ v2 = v2 * period
+ }
+
+ value = []int64{v2, v1}
+ addrs = parseHexAddresses(sampleData[3])
+
+ return value, addrs, nil
+}
+
+// parseThread parses a Threadz profile and returns a new Profile.
+func parseThread(b []byte) (*Profile, error) {
+ r := bytes.NewBuffer(b)
+
+ var line string
+ var err error
+ for {
+ // Skip past comments and empty lines seeking a real header.
+ line, err = r.ReadString('\n')
+ if err != nil {
+ return nil, err
+ }
+ if !isSpaceOrComment(line) {
+ break
+ }
+ }
+
+ if m := threadzStartRE.FindStringSubmatch(line); m != nil {
+ // Advance over initial comments until first stack trace.
+ for {
+ line, err = r.ReadString('\n')
+ if err != nil {
+ if err != io.EOF {
+ return nil, err
+ }
+
+ if line == "" {
+ break
+ }
+ }
+ if sectionTrigger(line) != unrecognizedSection || line[0] == '-' {
+ break
+ }
+ }
+ } else if t := threadStartRE.FindStringSubmatch(line); len(t) != 4 {
+ return nil, errUnrecognized
+ }
+
+ p := &Profile{
+ SampleType: []*ValueType{{Type: "thread", Unit: "count"}},
+ PeriodType: &ValueType{Type: "thread", Unit: "count"},
+ Period: 1,
+ }
+
+ locs := make(map[uint64]*Location)
+ // Recognize each thread and populate profile samples.
+ for sectionTrigger(line) == unrecognizedSection {
+ if strings.HasPrefix(line, "---- no stack trace for") {
+ line = ""
+ break
+ }
+ if t := threadStartRE.FindStringSubmatch(line); len(t) != 4 {
+ return nil, errUnrecognized
+ }
+
+ var addrs []uint64
+ line, addrs, err = parseThreadSample(r)
+ if err != nil {
+ return nil, errUnrecognized
+ }
+ if len(addrs) == 0 {
+ // We got a --same as previous threads--. Bump counters.
+ if len(p.Sample) > 0 {
+ s := p.Sample[len(p.Sample)-1]
+ s.Value[0]++
+ }
+ continue
+ }
+
+ var sloc []*Location
+ for _, addr := range addrs {
+ // Addresses from stack traces point to the next instruction after
+ // each call. Adjust by -1 to land somewhere on the actual call.
+ addr--
+ loc := locs[addr]
+ if locs[addr] == nil {
+ loc = &Location{
+ Address: addr,
+ }
+ p.Location = append(p.Location, loc)
+ locs[addr] = loc
+ }
+ sloc = append(sloc, loc)
+ }
+
+ p.Sample = append(p.Sample, &Sample{
+ Value: []int64{1},
+ Location: sloc,
+ })
+ }
+
+ if err = parseAdditionalSections(line, r, p); err != nil {
+ return nil, err
+ }
+
+ return p, nil
+}
+
+// parseThreadSample parses a symbolized or unsymbolized stack trace.
+// Returns the first line after the traceback, the sample (or nil if
+// it hits a 'same-as-previous' marker) and an error.
+func parseThreadSample(b *bytes.Buffer) (nextl string, addrs []uint64, err error) {
+ var l string
+ sameAsPrevious := false
+ for {
+ if l, err = b.ReadString('\n'); err != nil {
+ if err != io.EOF {
+ return "", nil, err
+ }
+ if l == "" {
+ break
+ }
+ }
+ if l = strings.TrimSpace(l); l == "" {
+ continue
+ }
+
+ if strings.HasPrefix(l, "---") {
+ break
+ }
+ if strings.Contains(l, "same as previous thread") {
+ sameAsPrevious = true
+ continue
+ }
+
+ addrs = append(addrs, parseHexAddresses(l)...)
+ }
+
+ if sameAsPrevious {
+ return l, nil, nil
+ }
+ return l, addrs, nil
+}
+
+// parseAdditionalSections parses any additional sections in the
+// profile, ignoring any unrecognized sections.
+func parseAdditionalSections(l string, b *bytes.Buffer, p *Profile) (err error) {
+ for {
+ if sectionTrigger(l) == memoryMapSection {
+ break
+ }
+ // Ignore any unrecognized sections.
+ if l, err := b.ReadString('\n'); err != nil {
+ if err != io.EOF {
+ return err
+ }
+ if l == "" {
+ break
+ }
+ }
+ }
+ return p.ParseMemoryMap(b)
+}
+
+// ParseMemoryMap parses a memory map in the format of
+// /proc/self/maps, and overrides the mappings in the current profile.
+// It renumbers the samples and locations in the profile correspondingly.
+func (p *Profile) ParseMemoryMap(rd io.Reader) error {
+ b := bufio.NewReader(rd)
+
+ var attrs []string
+ var r *strings.Replacer
+ const delimiter = "="
+ for {
+ l, err := b.ReadString('\n')
+ if err != nil {
+ if err != io.EOF {
+ return err
+ }
+ if l == "" {
+ break
+ }
+ }
+ if l = strings.TrimSpace(l); l == "" {
+ continue
+ }
+
+ if r != nil {
+ l = r.Replace(l)
+ }
+ m, err := parseMappingEntry(l)
+ if err != nil {
+ if err == errUnrecognized {
+ // Recognize assignments of the form: attr=value, and replace
+ // $attr with value on subsequent mappings.
+ if attr := strings.SplitN(l, delimiter, 2); len(attr) == 2 {
+ attrs = append(attrs, "$"+strings.TrimSpace(attr[0]), strings.TrimSpace(attr[1]))
+ r = strings.NewReplacer(attrs...)
+ }
+ // Ignore any unrecognized entries
+ continue
+ }
+ return err
+ }
+ if m == nil || (m.File == "" && len(p.Mapping) != 0) {
+ // In some cases the first entry may include the address range
+ // but not the name of the file. It should be followed by
+ // another entry with the name.
+ continue
+ }
+ if len(p.Mapping) == 1 && p.Mapping[0].File == "" {
+ // Update the name if this is the entry following that empty one.
+ p.Mapping[0].File = m.File
+ continue
+ }
+ p.Mapping = append(p.Mapping, m)
+ }
+ p.remapLocationIDs()
+ p.remapFunctionIDs()
+ p.remapMappingIDs()
+ return nil
+}
+
+func parseMappingEntry(l string) (*Mapping, error) {
+ mapping := &Mapping{}
+ var err error
+ if me := procMapsRE.FindStringSubmatch(l); len(me) == 9 {
+ if !strings.Contains(me[3], "x") {
+ // Skip non-executable entries.
+ return nil, nil
+ }
+ if mapping.Start, err = strconv.ParseUint(me[1], 16, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ if mapping.Limit, err = strconv.ParseUint(me[2], 16, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ if me[4] != "" {
+ if mapping.Offset, err = strconv.ParseUint(me[4], 16, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ }
+ mapping.File = me[8]
+ return mapping, nil
+ }
+
+ if me := briefMapsRE.FindStringSubmatch(l); len(me) == 6 {
+ if mapping.Start, err = strconv.ParseUint(me[1], 16, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ if mapping.Limit, err = strconv.ParseUint(me[2], 16, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ mapping.File = me[3]
+ if me[5] != "" {
+ if mapping.Offset, err = strconv.ParseUint(me[5], 16, 64); err != nil {
+ return nil, errUnrecognized
+ }
+ }
+ return mapping, nil
+ }
+
+ return nil, errUnrecognized
+}
+
+type sectionType int
+
+const (
+ unrecognizedSection sectionType = iota
+ memoryMapSection
+)
+
+var memoryMapTriggers = []string{
+ "--- Memory map: ---",
+ "MAPPED_LIBRARIES:",
+}
+
+func sectionTrigger(line string) sectionType {
+ for _, trigger := range memoryMapTriggers {
+ if strings.Contains(line, trigger) {
+ return memoryMapSection
+ }
+ }
+ return unrecognizedSection
+}
+
+func (p *Profile) addLegacyFrameInfo() {
+ switch {
+ case isProfileType(p, heapzSampleTypes) ||
+ isProfileType(p, heapzInUseSampleTypes) ||
+ isProfileType(p, heapzAllocSampleTypes):
+ p.DropFrames, p.KeepFrames = allocRxStr, allocSkipRxStr
+ case isProfileType(p, contentionzSampleTypes):
+ p.DropFrames, p.KeepFrames = lockRxStr, ""
+ default:
+ p.DropFrames, p.KeepFrames = cpuProfilerRxStr, ""
+ }
+}
+
+var heapzSampleTypes = []string{"allocations", "size"} // early Go pprof profiles
+var heapzInUseSampleTypes = []string{"inuse_objects", "inuse_space"}
+var heapzAllocSampleTypes = []string{"alloc_objects", "alloc_space"}
+var contentionzSampleTypes = []string{"contentions", "delay"}
+
+func isProfileType(p *Profile, t []string) bool {
+ st := p.SampleType
+ if len(st) != len(t) {
+ return false
+ }
+
+ for i := range st {
+ if st[i].Type != t[i] {
+ return false
+ }
+ }
+ return true
+}
+
+var allocRxStr = strings.Join([]string{
+ // POSIX entry points.
+ `calloc`,
+ `cfree`,
+ `malloc`,
+ `free`,
+ `memalign`,
+ `do_memalign`,
+ `(__)?posix_memalign`,
+ `pvalloc`,
+ `valloc`,
+ `realloc`,
+
+ // TC malloc.
+ `tcmalloc::.*`,
+ `tc_calloc`,
+ `tc_cfree`,
+ `tc_malloc`,
+ `tc_free`,
+ `tc_memalign`,
+ `tc_posix_memalign`,
+ `tc_pvalloc`,
+ `tc_valloc`,
+ `tc_realloc`,
+ `tc_new`,
+ `tc_delete`,
+ `tc_newarray`,
+ `tc_deletearray`,
+ `tc_new_nothrow`,
+ `tc_newarray_nothrow`,
+
+ // Memory-allocation routines on OS X.
+ `malloc_zone_malloc`,
+ `malloc_zone_calloc`,
+ `malloc_zone_valloc`,
+ `malloc_zone_realloc`,
+ `malloc_zone_memalign`,
+ `malloc_zone_free`,
+
+ // Go runtime
+ `runtime\..*`,
+
+ // Other misc. memory allocation routines
+ `BaseArena::.*`,
+ `(::)?do_malloc_no_errno`,
+ `(::)?do_malloc_pages`,
+ `(::)?do_malloc`,
+ `DoSampledAllocation`,
+ `MallocedMemBlock::MallocedMemBlock`,
+ `_M_allocate`,
+ `__builtin_(vec_)?delete`,
+ `__builtin_(vec_)?new`,
+ `__gnu_cxx::new_allocator::allocate`,
+ `__libc_malloc`,
+ `__malloc_alloc_template::allocate`,
+ `allocate`,
+ `cpp_alloc`,
+ `operator new(\[\])?`,
+ `simple_alloc::allocate`,
+}, `|`)
+
+var allocSkipRxStr = strings.Join([]string{
+ // Preserve Go runtime frames that appear in the middle/bottom of
+ // the stack.
+ `runtime\.panic`,
+ `runtime\.reflectcall`,
+ `runtime\.call[0-9]*`,
+}, `|`)
+
+var cpuProfilerRxStr = strings.Join([]string{
+ `ProfileData::Add`,
+ `ProfileData::prof_handler`,
+ `CpuProfiler::prof_handler`,
+ `__pthread_sighandler`,
+ `__restore`,
+}, `|`)
+
+var lockRxStr = strings.Join([]string{
+ `RecordLockProfileData`,
+ `(base::)?RecordLockProfileData.*`,
+ `(base::)?SubmitMutexProfileData.*`,
+ `(base::)?SubmitSpinLockProfileData.*`,
+ `(Mutex::)?AwaitCommon.*`,
+ `(Mutex::)?Unlock.*`,
+ `(Mutex::)?UnlockSlow.*`,
+ `(Mutex::)?ReaderUnlock.*`,
+ `(MutexLock::)?~MutexLock.*`,
+ `(SpinLock::)?Unlock.*`,
+ `(SpinLock::)?SlowUnlock.*`,
+ `(SpinLockHolder::)?~SpinLockHolder.*`,
+}, `|`)
diff --git a/libgo/go/internal/pprof/profile/profile.go b/libgo/go/internal/pprof/profile/profile.go
new file mode 100644
index 00000000000..28e713d7beb
--- /dev/null
+++ b/libgo/go/internal/pprof/profile/profile.go
@@ -0,0 +1,572 @@
+// 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 profile provides a representation of profile.proto and
+// methods to encode/decode profiles in this format.
+package profile
+
+import (
+ "bytes"
+ "compress/gzip"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "regexp"
+ "strings"
+ "time"
+)
+
+// Profile is an in-memory representation of profile.proto.
+type Profile struct {
+ SampleType []*ValueType
+ Sample []*Sample
+ Mapping []*Mapping
+ Location []*Location
+ Function []*Function
+
+ DropFrames string
+ KeepFrames string
+
+ TimeNanos int64
+ DurationNanos int64
+ PeriodType *ValueType
+ Period int64
+
+ dropFramesX int64
+ keepFramesX int64
+ stringTable []string
+}
+
+// ValueType corresponds to Profile.ValueType
+type ValueType struct {
+ Type string // cpu, wall, inuse_space, etc
+ Unit string // seconds, nanoseconds, bytes, etc
+
+ typeX int64
+ unitX int64
+}
+
+// Sample corresponds to Profile.Sample
+type Sample struct {
+ Location []*Location
+ Value []int64
+ Label map[string][]string
+ NumLabel map[string][]int64
+
+ locationIDX []uint64
+ labelX []Label
+}
+
+// Label corresponds to Profile.Label
+type Label struct {
+ keyX int64
+ // Exactly one of the two following values must be set
+ strX int64
+ numX int64 // Integer value for this label
+}
+
+// Mapping corresponds to Profile.Mapping
+type Mapping struct {
+ ID uint64
+ Start uint64
+ Limit uint64
+ Offset uint64
+ File string
+ BuildID string
+ HasFunctions bool
+ HasFilenames bool
+ HasLineNumbers bool
+ HasInlineFrames bool
+
+ fileX int64
+ buildIDX int64
+}
+
+// Location corresponds to Profile.Location
+type Location struct {
+ ID uint64
+ Mapping *Mapping
+ Address uint64
+ Line []Line
+
+ mappingIDX uint64
+}
+
+// Line corresponds to Profile.Line
+type Line struct {
+ Function *Function
+ Line int64
+
+ functionIDX uint64
+}
+
+// Function corresponds to Profile.Function
+type Function struct {
+ ID uint64
+ Name string
+ SystemName string
+ Filename string
+ StartLine int64
+
+ nameX int64
+ systemNameX int64
+ filenameX int64
+}
+
+// Parse parses a profile and checks for its validity. The input
+// may be a gzip-compressed encoded protobuf or one of many legacy
+// profile formats which may be unsupported in the future.
+func Parse(r io.Reader) (*Profile, error) {
+ orig, err := ioutil.ReadAll(r)
+ if err != nil {
+ return nil, err
+ }
+
+ var p *Profile
+ if len(orig) >= 2 && orig[0] == 0x1f && orig[1] == 0x8b {
+ gz, err := gzip.NewReader(bytes.NewBuffer(orig))
+ if err != nil {
+ return nil, fmt.Errorf("decompressing profile: %v", err)
+ }
+ data, err := ioutil.ReadAll(gz)
+ if err != nil {
+ return nil, fmt.Errorf("decompressing profile: %v", err)
+ }
+ orig = data
+ }
+ if p, err = parseUncompressed(orig); err != nil {
+ if p, err = parseLegacy(orig); err != nil {
+ return nil, fmt.Errorf("parsing profile: %v", err)
+ }
+ }
+
+ if err := p.CheckValid(); err != nil {
+ return nil, fmt.Errorf("malformed profile: %v", err)
+ }
+ return p, nil
+}
+
+var errUnrecognized = fmt.Errorf("unrecognized profile format")
+var errMalformed = fmt.Errorf("malformed profile format")
+
+func parseLegacy(data []byte) (*Profile, error) {
+ parsers := []func([]byte) (*Profile, error){
+ parseCPU,
+ parseHeap,
+ parseGoCount, // goroutine, threadcreate
+ parseThread,
+ parseContention,
+ }
+
+ for _, parser := range parsers {
+ p, err := parser(data)
+ if err == nil {
+ p.setMain()
+ p.addLegacyFrameInfo()
+ return p, nil
+ }
+ if err != errUnrecognized {
+ return nil, err
+ }
+ }
+ return nil, errUnrecognized
+}
+
+func parseUncompressed(data []byte) (*Profile, error) {
+ p := &Profile{}
+ if err := unmarshal(data, p); err != nil {
+ return nil, err
+ }
+
+ if err := p.postDecode(); err != nil {
+ return nil, err
+ }
+
+ return p, nil
+}
+
+var libRx = regexp.MustCompile(`([.]so$|[.]so[._][0-9]+)`)
+
+// setMain scans Mapping entries and guesses which entry is main
+// because legacy profiles don't obey the convention of putting main
+// first.
+func (p *Profile) setMain() {
+ for i := 0; i < len(p.Mapping); i++ {
+ file := strings.TrimSpace(strings.Replace(p.Mapping[i].File, "(deleted)", "", -1))
+ if len(file) == 0 {
+ continue
+ }
+ if len(libRx.FindStringSubmatch(file)) > 0 {
+ continue
+ }
+ if strings.HasPrefix(file, "[") {
+ continue
+ }
+ // Swap what we guess is main to position 0.
+ tmp := p.Mapping[i]
+ p.Mapping[i] = p.Mapping[0]
+ p.Mapping[0] = tmp
+ break
+ }
+}
+
+// Write writes the profile as a gzip-compressed marshaled protobuf.
+func (p *Profile) Write(w io.Writer) error {
+ p.preEncode()
+ b := marshal(p)
+ zw := gzip.NewWriter(w)
+ defer zw.Close()
+ _, err := zw.Write(b)
+ return err
+}
+
+// CheckValid tests whether the profile is valid. Checks include, but are
+// not limited to:
+// - len(Profile.Sample[n].value) == len(Profile.value_unit)
+// - Sample.id has a corresponding Profile.Location
+func (p *Profile) CheckValid() error {
+ // Check that sample values are consistent
+ sampleLen := len(p.SampleType)
+ if sampleLen == 0 && len(p.Sample) != 0 {
+ return fmt.Errorf("missing sample type information")
+ }
+ for _, s := range p.Sample {
+ if len(s.Value) != sampleLen {
+ return fmt.Errorf("mismatch: sample has: %d values vs. %d types", len(s.Value), len(p.SampleType))
+ }
+ }
+
+ // Check that all mappings/locations/functions are in the tables
+ // Check that there are no duplicate ids
+ mappings := make(map[uint64]*Mapping, len(p.Mapping))
+ for _, m := range p.Mapping {
+ if m.ID == 0 {
+ return fmt.Errorf("found mapping with reserved ID=0")
+ }
+ if mappings[m.ID] != nil {
+ return fmt.Errorf("multiple mappings with same id: %d", m.ID)
+ }
+ mappings[m.ID] = m
+ }
+ functions := make(map[uint64]*Function, len(p.Function))
+ for _, f := range p.Function {
+ if f.ID == 0 {
+ return fmt.Errorf("found function with reserved ID=0")
+ }
+ if functions[f.ID] != nil {
+ return fmt.Errorf("multiple functions with same id: %d", f.ID)
+ }
+ functions[f.ID] = f
+ }
+ locations := make(map[uint64]*Location, len(p.Location))
+ for _, l := range p.Location {
+ if l.ID == 0 {
+ return fmt.Errorf("found location with reserved id=0")
+ }
+ if locations[l.ID] != nil {
+ return fmt.Errorf("multiple locations with same id: %d", l.ID)
+ }
+ locations[l.ID] = l
+ if m := l.Mapping; m != nil {
+ if m.ID == 0 || mappings[m.ID] != m {
+ return fmt.Errorf("inconsistent mapping %p: %d", m, m.ID)
+ }
+ }
+ for _, ln := range l.Line {
+ if f := ln.Function; f != nil {
+ if f.ID == 0 || functions[f.ID] != f {
+ return fmt.Errorf("inconsistent function %p: %d", f, f.ID)
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// Aggregate merges the locations in the profile into equivalence
+// classes preserving the request attributes. It also updates the
+// samples to point to the merged locations.
+func (p *Profile) Aggregate(inlineFrame, function, filename, linenumber, address bool) error {
+ for _, m := range p.Mapping {
+ m.HasInlineFrames = m.HasInlineFrames && inlineFrame
+ m.HasFunctions = m.HasFunctions && function
+ m.HasFilenames = m.HasFilenames && filename
+ m.HasLineNumbers = m.HasLineNumbers && linenumber
+ }
+
+ // Aggregate functions
+ if !function || !filename {
+ for _, f := range p.Function {
+ if !function {
+ f.Name = ""
+ f.SystemName = ""
+ }
+ if !filename {
+ f.Filename = ""
+ }
+ }
+ }
+
+ // Aggregate locations
+ if !inlineFrame || !address || !linenumber {
+ for _, l := range p.Location {
+ if !inlineFrame && len(l.Line) > 1 {
+ l.Line = l.Line[len(l.Line)-1:]
+ }
+ if !linenumber {
+ for i := range l.Line {
+ l.Line[i].Line = 0
+ }
+ }
+ if !address {
+ l.Address = 0
+ }
+ }
+ }
+
+ return p.CheckValid()
+}
+
+// Print dumps a text representation of a profile. Intended mainly
+// for debugging purposes.
+func (p *Profile) String() string {
+
+ ss := make([]string, 0, len(p.Sample)+len(p.Mapping)+len(p.Location))
+ if pt := p.PeriodType; pt != nil {
+ ss = append(ss, fmt.Sprintf("PeriodType: %s %s", pt.Type, pt.Unit))
+ }
+ ss = append(ss, fmt.Sprintf("Period: %d", p.Period))
+ if p.TimeNanos != 0 {
+ ss = append(ss, fmt.Sprintf("Time: %v", time.Unix(0, p.TimeNanos)))
+ }
+ if p.DurationNanos != 0 {
+ ss = append(ss, fmt.Sprintf("Duration: %v", time.Duration(p.DurationNanos)))
+ }
+
+ ss = append(ss, "Samples:")
+ var sh1 string
+ for _, s := range p.SampleType {
+ sh1 = sh1 + fmt.Sprintf("%s/%s ", s.Type, s.Unit)
+ }
+ ss = append(ss, strings.TrimSpace(sh1))
+ for _, s := range p.Sample {
+ var sv string
+ for _, v := range s.Value {
+ sv = fmt.Sprintf("%s %10d", sv, v)
+ }
+ sv = sv + ": "
+ for _, l := range s.Location {
+ sv = sv + fmt.Sprintf("%d ", l.ID)
+ }
+ ss = append(ss, sv)
+ const labelHeader = " "
+ if len(s.Label) > 0 {
+ ls := labelHeader
+ for k, v := range s.Label {
+ ls = ls + fmt.Sprintf("%s:%v ", k, v)
+ }
+ ss = append(ss, ls)
+ }
+ if len(s.NumLabel) > 0 {
+ ls := labelHeader
+ for k, v := range s.NumLabel {
+ ls = ls + fmt.Sprintf("%s:%v ", k, v)
+ }
+ ss = append(ss, ls)
+ }
+ }
+
+ ss = append(ss, "Locations")
+ for _, l := range p.Location {
+ locStr := fmt.Sprintf("%6d: %#x ", l.ID, l.Address)
+ if m := l.Mapping; m != nil {
+ locStr = locStr + fmt.Sprintf("M=%d ", m.ID)
+ }
+ if len(l.Line) == 0 {
+ ss = append(ss, locStr)
+ }
+ for li := range l.Line {
+ lnStr := "??"
+ if fn := l.Line[li].Function; fn != nil {
+ lnStr = fmt.Sprintf("%s %s:%d s=%d",
+ fn.Name,
+ fn.Filename,
+ l.Line[li].Line,
+ fn.StartLine)
+ if fn.Name != fn.SystemName {
+ lnStr = lnStr + "(" + fn.SystemName + ")"
+ }
+ }
+ ss = append(ss, locStr+lnStr)
+ // Do not print location details past the first line
+ locStr = " "
+ }
+ }
+
+ ss = append(ss, "Mappings")
+ for _, m := range p.Mapping {
+ bits := ""
+ if m.HasFunctions {
+ bits = bits + "[FN]"
+ }
+ if m.HasFilenames {
+ bits = bits + "[FL]"
+ }
+ if m.HasLineNumbers {
+ bits = bits + "[LN]"
+ }
+ if m.HasInlineFrames {
+ bits = bits + "[IN]"
+ }
+ ss = append(ss, fmt.Sprintf("%d: %#x/%#x/%#x %s %s %s",
+ m.ID,
+ m.Start, m.Limit, m.Offset,
+ m.File,
+ m.BuildID,
+ bits))
+ }
+
+ return strings.Join(ss, "\n") + "\n"
+}
+
+// Merge adds profile p adjusted by ratio r into profile p. Profiles
+// must be compatible (same Type and SampleType).
+// TODO(rsilvera): consider normalizing the profiles based on the
+// total samples collected.
+func (p *Profile) Merge(pb *Profile, r float64) error {
+ if err := p.Compatible(pb); err != nil {
+ return err
+ }
+
+ pb = pb.Copy()
+
+ // Keep the largest of the two periods.
+ if pb.Period > p.Period {
+ p.Period = pb.Period
+ }
+
+ p.DurationNanos += pb.DurationNanos
+
+ p.Mapping = append(p.Mapping, pb.Mapping...)
+ for i, m := range p.Mapping {
+ m.ID = uint64(i + 1)
+ }
+ p.Location = append(p.Location, pb.Location...)
+ for i, l := range p.Location {
+ l.ID = uint64(i + 1)
+ }
+ p.Function = append(p.Function, pb.Function...)
+ for i, f := range p.Function {
+ f.ID = uint64(i + 1)
+ }
+
+ if r != 1.0 {
+ for _, s := range pb.Sample {
+ for i, v := range s.Value {
+ s.Value[i] = int64((float64(v) * r))
+ }
+ }
+ }
+ p.Sample = append(p.Sample, pb.Sample...)
+ return p.CheckValid()
+}
+
+// Compatible determines if two profiles can be compared/merged.
+// returns nil if the profiles are compatible; otherwise an error with
+// details on the incompatibility.
+func (p *Profile) Compatible(pb *Profile) error {
+ if !compatibleValueTypes(p.PeriodType, pb.PeriodType) {
+ return fmt.Errorf("incompatible period types %v and %v", p.PeriodType, pb.PeriodType)
+ }
+
+ if len(p.SampleType) != len(pb.SampleType) {
+ return fmt.Errorf("incompatible sample types %v and %v", p.SampleType, pb.SampleType)
+ }
+
+ for i := range p.SampleType {
+ if !compatibleValueTypes(p.SampleType[i], pb.SampleType[i]) {
+ return fmt.Errorf("incompatible sample types %v and %v", p.SampleType, pb.SampleType)
+ }
+ }
+
+ return nil
+}
+
+// HasFunctions determines if all locations in this profile have
+// symbolized function information.
+func (p *Profile) HasFunctions() bool {
+ for _, l := range p.Location {
+ if l.Mapping == nil || !l.Mapping.HasFunctions {
+ return false
+ }
+ }
+ return true
+}
+
+// HasFileLines determines if all locations in this profile have
+// symbolized file and line number information.
+func (p *Profile) HasFileLines() bool {
+ for _, l := range p.Location {
+ if l.Mapping == nil || (!l.Mapping.HasFilenames || !l.Mapping.HasLineNumbers) {
+ return false
+ }
+ }
+ return true
+}
+
+func compatibleValueTypes(v1, v2 *ValueType) bool {
+ if v1 == nil || v2 == nil {
+ return true // No grounds to disqualify.
+ }
+ return v1.Type == v2.Type && v1.Unit == v2.Unit
+}
+
+// Copy makes a fully independent copy of a profile.
+func (p *Profile) Copy() *Profile {
+ p.preEncode()
+ b := marshal(p)
+
+ pp := &Profile{}
+ if err := unmarshal(b, pp); err != nil {
+ panic(err)
+ }
+ if err := pp.postDecode(); err != nil {
+ panic(err)
+ }
+
+ return pp
+}
+
+// Demangler maps symbol names to a human-readable form. This may
+// include C++ demangling and additional simplification. Names that
+// are not demangled may be missing from the resulting map.
+type Demangler func(name []string) (map[string]string, error)
+
+// Demangle attempts to demangle and optionally simplify any function
+// names referenced in the profile. It works on a best-effort basis:
+// it will silently preserve the original names in case of any errors.
+func (p *Profile) Demangle(d Demangler) error {
+ // Collect names to demangle.
+ var names []string
+ for _, fn := range p.Function {
+ names = append(names, fn.SystemName)
+ }
+
+ // Update profile with demangled names.
+ demangled, err := d(names)
+ if err != nil {
+ return err
+ }
+ for _, fn := range p.Function {
+ if dd, ok := demangled[fn.SystemName]; ok {
+ fn.Name = dd
+ }
+ }
+ return nil
+}
+
+// Empty returns true if the profile contains no samples.
+func (p *Profile) Empty() bool {
+ return len(p.Sample) == 0
+}
diff --git a/libgo/go/internal/pprof/profile/profile_test.go b/libgo/go/internal/pprof/profile/profile_test.go
new file mode 100644
index 00000000000..e1963f33515
--- /dev/null
+++ b/libgo/go/internal/pprof/profile/profile_test.go
@@ -0,0 +1,79 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package profile
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestEmptyProfile(t *testing.T) {
+ var buf bytes.Buffer
+ p, err := Parse(&buf)
+ if err != nil {
+ t.Error("Want no error, got", err)
+ }
+ if p == nil {
+ t.Fatal("Want a valid profile, got <nil>")
+ }
+ if !p.Empty() {
+ t.Errorf("Profile should be empty, got %#v", p)
+ }
+}
+
+func TestParseContention(t *testing.T) {
+ tests := []struct {
+ name string
+ in string
+ wantErr bool
+ }{
+ {
+ name: "valid",
+ in: `--- mutex:
+cycles/second=3491920901
+sampling period=1
+43227965305 1659640 @ 0x45e851 0x45f764 0x4a2be1 0x44ea31
+34035731690 15760 @ 0x45e851 0x45f764 0x4a2b17 0x44ea31
+`,
+ },
+ {
+ name: "valid with comment",
+ in: `--- mutex:
+cycles/second=3491920901
+sampling period=1
+43227965305 1659640 @ 0x45e851 0x45f764 0x4a2be1 0x44ea31
+# 0x45e850 sync.(*Mutex).Unlock+0x80 /go/src/sync/mutex.go:126
+# 0x45f763 sync.(*RWMutex).Unlock+0x83 /go/src/sync/rwmutex.go:125
+# 0x4a2be0 main.main.func3+0x70 /go/src/internal/pprof/profile/a_binary.go:58
+
+34035731690 15760 @ 0x45e851 0x45f764 0x4a2b17 0x44ea31
+# 0x45e850 sync.(*Mutex).Unlock+0x80 /go/src/sync/mutex.go:126
+# 0x45f763 sync.(*RWMutex).Unlock+0x83 /go/src/sync/rwmutex.go:125
+# 0x4a2b16 main.main.func2+0xd6 /go/src/internal/pprof/profile/a_binary.go:48
+`,
+ },
+ {
+ name: "empty",
+ in: `--- mutex:`,
+ wantErr: true,
+ },
+ {
+ name: "invalid header",
+ in: `--- channel:
+43227965305 1659640 @ 0x45e851 0x45f764 0x4a2be1 0x44ea31`,
+ wantErr: true,
+ },
+ }
+ for _, tc := range tests {
+ _, err := parseContention([]byte(tc.in))
+ if tc.wantErr && err == nil {
+ t.Errorf("parseContention(%q) succeeded unexpectedly", tc.name)
+ }
+ if !tc.wantErr && err != nil {
+ t.Errorf("parseContention(%q) failed unexpectedly: %v", tc.name, err)
+ }
+ }
+
+}
diff --git a/libgo/go/internal/pprof/profile/proto.go b/libgo/go/internal/pprof/profile/proto.go
new file mode 100644
index 00000000000..11d7f9ff9b3
--- /dev/null
+++ b/libgo/go/internal/pprof/profile/proto.go
@@ -0,0 +1,360 @@
+// 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 is a simple protocol buffer encoder and decoder.
+//
+// A protocol message must implement the message interface:
+// decoder() []decoder
+// encode(*buffer)
+//
+// The decode method returns a slice indexed by field number that gives the
+// function to decode that field.
+// The encode method encodes its receiver into the given buffer.
+//
+// The two methods are simple enough to be implemented by hand rather than
+// by using a protocol compiler.
+//
+// See profile.go for examples of messages implementing this interface.
+//
+// There is no support for groups, message sets, or "has" bits.
+
+package profile
+
+import "errors"
+
+type buffer struct {
+ field int
+ typ int
+ u64 uint64
+ data []byte
+ tmp [16]byte
+}
+
+type decoder func(*buffer, message) error
+
+type message interface {
+ decoder() []decoder
+ encode(*buffer)
+}
+
+func marshal(m message) []byte {
+ var b buffer
+ m.encode(&b)
+ return b.data
+}
+
+func encodeVarint(b *buffer, x uint64) {
+ for x >= 128 {
+ b.data = append(b.data, byte(x)|0x80)
+ x >>= 7
+ }
+ b.data = append(b.data, byte(x))
+}
+
+func encodeLength(b *buffer, tag int, len int) {
+ encodeVarint(b, uint64(tag)<<3|2)
+ encodeVarint(b, uint64(len))
+}
+
+func encodeUint64(b *buffer, tag int, x uint64) {
+ // append varint to b.data
+ encodeVarint(b, uint64(tag)<<3|0)
+ encodeVarint(b, x)
+}
+
+func encodeUint64s(b *buffer, tag int, x []uint64) {
+ if len(x) > 2 {
+ // Use packed encoding
+ n1 := len(b.data)
+ for _, u := range x {
+ encodeVarint(b, u)
+ }
+ n2 := len(b.data)
+ encodeLength(b, tag, n2-n1)
+ n3 := len(b.data)
+ copy(b.tmp[:], b.data[n2:n3])
+ copy(b.data[n1+(n3-n2):], b.data[n1:n2])
+ copy(b.data[n1:], b.tmp[:n3-n2])
+ return
+ }
+ for _, u := range x {
+ encodeUint64(b, tag, u)
+ }
+}
+
+func encodeUint64Opt(b *buffer, tag int, x uint64) {
+ if x == 0 {
+ return
+ }
+ encodeUint64(b, tag, x)
+}
+
+func encodeInt64(b *buffer, tag int, x int64) {
+ u := uint64(x)
+ encodeUint64(b, tag, u)
+}
+
+func encodeInt64Opt(b *buffer, tag int, x int64) {
+ if x == 0 {
+ return
+ }
+ encodeInt64(b, tag, x)
+}
+
+func encodeInt64s(b *buffer, tag int, x []int64) {
+ if len(x) > 2 {
+ // Use packed encoding
+ n1 := len(b.data)
+ for _, u := range x {
+ encodeVarint(b, uint64(u))
+ }
+ n2 := len(b.data)
+ encodeLength(b, tag, n2-n1)
+ n3 := len(b.data)
+ copy(b.tmp[:], b.data[n2:n3])
+ copy(b.data[n1+(n3-n2):], b.data[n1:n2])
+ copy(b.data[n1:], b.tmp[:n3-n2])
+ return
+ }
+ for _, u := range x {
+ encodeInt64(b, tag, u)
+ }
+}
+
+func encodeString(b *buffer, tag int, x string) {
+ encodeLength(b, tag, len(x))
+ b.data = append(b.data, x...)
+}
+
+func encodeStrings(b *buffer, tag int, x []string) {
+ for _, s := range x {
+ encodeString(b, tag, s)
+ }
+}
+
+func encodeStringOpt(b *buffer, tag int, x string) {
+ if x == "" {
+ return
+ }
+ encodeString(b, tag, x)
+}
+
+func encodeBool(b *buffer, tag int, x bool) {
+ if x {
+ encodeUint64(b, tag, 1)
+ } else {
+ encodeUint64(b, tag, 0)
+ }
+}
+
+func encodeBoolOpt(b *buffer, tag int, x bool) {
+ if x == false {
+ return
+ }
+ encodeBool(b, tag, x)
+}
+
+func encodeMessage(b *buffer, tag int, m message) {
+ n1 := len(b.data)
+ m.encode(b)
+ n2 := len(b.data)
+ encodeLength(b, tag, n2-n1)
+ n3 := len(b.data)
+ copy(b.tmp[:], b.data[n2:n3])
+ copy(b.data[n1+(n3-n2):], b.data[n1:n2])
+ copy(b.data[n1:], b.tmp[:n3-n2])
+}
+
+func unmarshal(data []byte, m message) (err error) {
+ b := buffer{data: data, typ: 2}
+ return decodeMessage(&b, m)
+}
+
+func le64(p []byte) uint64 {
+ return uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 | uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56
+}
+
+func le32(p []byte) uint32 {
+ return uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
+}
+
+func decodeVarint(data []byte) (uint64, []byte, error) {
+ var i int
+ var u uint64
+ for i = 0; ; i++ {
+ if i >= 10 || i >= len(data) {
+ return 0, nil, errors.New("bad varint")
+ }
+ u |= uint64(data[i]&0x7F) << uint(7*i)
+ if data[i]&0x80 == 0 {
+ return u, data[i+1:], nil
+ }
+ }
+}
+
+func decodeField(b *buffer, data []byte) ([]byte, error) {
+ x, data, err := decodeVarint(data)
+ if err != nil {
+ return nil, err
+ }
+ b.field = int(x >> 3)
+ b.typ = int(x & 7)
+ b.data = nil
+ b.u64 = 0
+ switch b.typ {
+ case 0:
+ b.u64, data, err = decodeVarint(data)
+ if err != nil {
+ return nil, err
+ }
+ case 1:
+ if len(data) < 8 {
+ return nil, errors.New("not enough data")
+ }
+ b.u64 = le64(data[:8])
+ data = data[8:]
+ case 2:
+ var n uint64
+ n, data, err = decodeVarint(data)
+ if err != nil {
+ return nil, err
+ }
+ if n > uint64(len(data)) {
+ return nil, errors.New("too much data")
+ }
+ b.data = data[:n]
+ data = data[n:]
+ case 5:
+ if len(data) < 4 {
+ return nil, errors.New("not enough data")
+ }
+ b.u64 = uint64(le32(data[:4]))
+ data = data[4:]
+ default:
+ return nil, errors.New("unknown type: " + string(b.typ))
+ }
+
+ return data, nil
+}
+
+func checkType(b *buffer, typ int) error {
+ if b.typ != typ {
+ return errors.New("type mismatch")
+ }
+ return nil
+}
+
+func decodeMessage(b *buffer, m message) error {
+ if err := checkType(b, 2); err != nil {
+ return err
+ }
+ dec := m.decoder()
+ data := b.data
+ for len(data) > 0 {
+ // pull varint field# + type
+ var err error
+ data, err = decodeField(b, data)
+ if err != nil {
+ return err
+ }
+ if b.field >= len(dec) || dec[b.field] == nil {
+ continue
+ }
+ if err := dec[b.field](b, m); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func decodeInt64(b *buffer, x *int64) error {
+ if err := checkType(b, 0); err != nil {
+ return err
+ }
+ *x = int64(b.u64)
+ return nil
+}
+
+func decodeInt64s(b *buffer, x *[]int64) error {
+ if b.typ == 2 {
+ // Packed encoding
+ data := b.data
+ for len(data) > 0 {
+ var u uint64
+ var err error
+
+ if u, data, err = decodeVarint(data); err != nil {
+ return err
+ }
+ *x = append(*x, int64(u))
+ }
+ return nil
+ }
+ var i int64
+ if err := decodeInt64(b, &i); err != nil {
+ return err
+ }
+ *x = append(*x, i)
+ return nil
+}
+
+func decodeUint64(b *buffer, x *uint64) error {
+ if err := checkType(b, 0); err != nil {
+ return err
+ }
+ *x = b.u64
+ return nil
+}
+
+func decodeUint64s(b *buffer, x *[]uint64) error {
+ if b.typ == 2 {
+ data := b.data
+ // Packed encoding
+ for len(data) > 0 {
+ var u uint64
+ var err error
+
+ if u, data, err = decodeVarint(data); err != nil {
+ return err
+ }
+ *x = append(*x, u)
+ }
+ return nil
+ }
+ var u uint64
+ if err := decodeUint64(b, &u); err != nil {
+ return err
+ }
+ *x = append(*x, u)
+ return nil
+}
+
+func decodeString(b *buffer, x *string) error {
+ if err := checkType(b, 2); err != nil {
+ return err
+ }
+ *x = string(b.data)
+ return nil
+}
+
+func decodeStrings(b *buffer, x *[]string) error {
+ var s string
+ if err := decodeString(b, &s); err != nil {
+ return err
+ }
+ *x = append(*x, s)
+ return nil
+}
+
+func decodeBool(b *buffer, x *bool) error {
+ if err := checkType(b, 0); err != nil {
+ return err
+ }
+ if int64(b.u64) == 0 {
+ *x = false
+ } else {
+ *x = true
+ }
+ return nil
+}
diff --git a/libgo/go/internal/pprof/profile/proto_test.go b/libgo/go/internal/pprof/profile/proto_test.go
new file mode 100644
index 00000000000..c2613fc375a
--- /dev/null
+++ b/libgo/go/internal/pprof/profile/proto_test.go
@@ -0,0 +1,67 @@
+package profile
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestPackedEncoding(t *testing.T) {
+
+ type testcase struct {
+ uint64s []uint64
+ int64s []int64
+ encoded []byte
+ }
+ for i, tc := range []testcase{
+ {
+ []uint64{0, 1, 10, 100, 1000, 10000},
+ []int64{1000, 0, 1000},
+ []byte{10, 8, 0, 1, 10, 100, 232, 7, 144, 78, 18, 5, 232, 7, 0, 232, 7},
+ },
+ {
+ []uint64{10000},
+ nil,
+ []byte{8, 144, 78},
+ },
+ {
+ nil,
+ []int64{-10000},
+ []byte{16, 240, 177, 255, 255, 255, 255, 255, 255, 255, 1},
+ },
+ } {
+ source := &packedInts{tc.uint64s, tc.int64s}
+ if got, want := marshal(source), tc.encoded; !reflect.DeepEqual(got, want) {
+ t.Errorf("failed encode %d, got %v, want %v", i, got, want)
+ }
+
+ dest := new(packedInts)
+ if err := unmarshal(tc.encoded, dest); err != nil {
+ t.Errorf("failed decode %d: %v", i, err)
+ continue
+ }
+ if got, want := dest.uint64s, tc.uint64s; !reflect.DeepEqual(got, want) {
+ t.Errorf("failed decode uint64s %d, got %v, want %v", i, got, want)
+ }
+ if got, want := dest.int64s, tc.int64s; !reflect.DeepEqual(got, want) {
+ t.Errorf("failed decode int64s %d, got %v, want %v", i, got, want)
+ }
+ }
+}
+
+type packedInts struct {
+ uint64s []uint64
+ int64s []int64
+}
+
+func (u *packedInts) decoder() []decoder {
+ return []decoder{
+ nil,
+ func(b *buffer, m message) error { return decodeUint64s(b, &m.(*packedInts).uint64s) },
+ func(b *buffer, m message) error { return decodeInt64s(b, &m.(*packedInts).int64s) },
+ }
+}
+
+func (u *packedInts) encode(b *buffer) {
+ encodeUint64s(b, 1, u.uint64s)
+ encodeInt64s(b, 2, u.int64s)
+}
diff --git a/libgo/go/internal/pprof/profile/prune.go b/libgo/go/internal/pprof/profile/prune.go
new file mode 100644
index 00000000000..1924fada7a5
--- /dev/null
+++ b/libgo/go/internal/pprof/profile/prune.go
@@ -0,0 +1,97 @@
+// 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.
+
+// Implements methods to remove frames from profiles.
+
+package profile
+
+import (
+ "fmt"
+ "regexp"
+)
+
+// Prune removes all nodes beneath a node matching dropRx, and not
+// matching keepRx. If the root node of a Sample matches, the sample
+// will have an empty stack.
+func (p *Profile) Prune(dropRx, keepRx *regexp.Regexp) {
+ prune := make(map[uint64]bool)
+ pruneBeneath := make(map[uint64]bool)
+
+ for _, loc := range p.Location {
+ var i int
+ for i = len(loc.Line) - 1; i >= 0; i-- {
+ if fn := loc.Line[i].Function; fn != nil && fn.Name != "" {
+ funcName := fn.Name
+ // Account for leading '.' on the PPC ELF v1 ABI.
+ if funcName[0] == '.' {
+ funcName = funcName[1:]
+ }
+ if dropRx.MatchString(funcName) {
+ if keepRx == nil || !keepRx.MatchString(funcName) {
+ break
+ }
+ }
+ }
+ }
+
+ if i >= 0 {
+ // Found matching entry to prune.
+ pruneBeneath[loc.ID] = true
+
+ // Remove the matching location.
+ if i == len(loc.Line)-1 {
+ // Matched the top entry: prune the whole location.
+ prune[loc.ID] = true
+ } else {
+ loc.Line = loc.Line[i+1:]
+ }
+ }
+ }
+
+ // Prune locs from each Sample
+ for _, sample := range p.Sample {
+ // Scan from the root to the leaves to find the prune location.
+ // Do not prune frames before the first user frame, to avoid
+ // pruning everything.
+ foundUser := false
+ for i := len(sample.Location) - 1; i >= 0; i-- {
+ id := sample.Location[i].ID
+ if !prune[id] && !pruneBeneath[id] {
+ foundUser = true
+ continue
+ }
+ if !foundUser {
+ continue
+ }
+ if prune[id] {
+ sample.Location = sample.Location[i+1:]
+ break
+ }
+ if pruneBeneath[id] {
+ sample.Location = sample.Location[i:]
+ break
+ }
+ }
+ }
+}
+
+// RemoveUninteresting prunes and elides profiles using built-in
+// tables of uninteresting function names.
+func (p *Profile) RemoveUninteresting() error {
+ var keep, drop *regexp.Regexp
+ var err error
+
+ if p.DropFrames != "" {
+ if drop, err = regexp.Compile("^(" + p.DropFrames + ")$"); err != nil {
+ return fmt.Errorf("failed to compile regexp %s: %v", p.DropFrames, err)
+ }
+ if p.KeepFrames != "" {
+ if keep, err = regexp.Compile("^(" + p.KeepFrames + ")$"); err != nil {
+ return fmt.Errorf("failed to compile regexp %s: %v", p.KeepFrames, err)
+ }
+ }
+ p.Prune(drop, keep)
+ }
+ return nil
+}
diff --git a/libgo/go/internal/race/norace.go b/libgo/go/internal/race/norace.go
index 7ef5912901f..d83c0165b22 100644
--- a/libgo/go/internal/race/norace.go
+++ b/libgo/go/internal/race/norace.go
@@ -38,3 +38,5 @@ func ReadRange(addr unsafe.Pointer, len int) {
func WriteRange(addr unsafe.Pointer, len int) {
}
+
+func Errors() int { return 0 }
diff --git a/libgo/go/internal/race/race.go b/libgo/go/internal/race/race.go
index 6c721f6f1dd..2e7d97beaa2 100644
--- a/libgo/go/internal/race/race.go
+++ b/libgo/go/internal/race/race.go
@@ -48,3 +48,7 @@ func ReadRange(addr unsafe.Pointer, len int) {
func WriteRange(addr unsafe.Pointer, len int) {
runtime.RaceWriteRange(addr, len)
}
+
+func Errors() int {
+ return runtime.RaceErrors()
+}
diff --git a/libgo/go/internal/syscall/unix/getrandom_linux_mipsx.go b/libgo/go/internal/syscall/unix/getrandom_linux_mipsx.go
new file mode 100644
index 00000000000..af7b7229b1b
--- /dev/null
+++ b/libgo/go/internal/syscall/unix/getrandom_linux_mipsx.go
@@ -0,0 +1,11 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build mips mipsle
+
+package unix
+
+// Linux getrandom system call number.
+// See GetRandom in getrandom_linux.go.
+const randomTrap uintptr = 4353
diff --git a/libgo/go/internal/syscall/windows/mksyscall.go b/libgo/go/internal/syscall/windows/mksyscall.go
new file mode 100644
index 00000000000..91fa2b3b81f
--- /dev/null
+++ b/libgo/go/internal/syscall/windows/mksyscall.go
@@ -0,0 +1,7 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package windows
+
+//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go security_windows.go
diff --git a/libgo/go/internal/syscall/windows/registry/mksyscall.go b/libgo/go/internal/syscall/windows/registry/mksyscall.go
new file mode 100644
index 00000000000..077215351ef
--- /dev/null
+++ b/libgo/go/internal/syscall/windows/registry/mksyscall.go
@@ -0,0 +1,7 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package registry
+
+//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall.go
diff --git a/libgo/go/internal/syscall/windows/registry/syscall.go b/libgo/go/internal/syscall/windows/registry/syscall.go
index 5426cae9096..a6525dac5d9 100644
--- a/libgo/go/internal/syscall/windows/registry/syscall.go
+++ b/libgo/go/internal/syscall/windows/registry/syscall.go
@@ -8,8 +8,6 @@ package registry
import "syscall"
-//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall.go
-
const (
_REG_OPTION_NON_VOLATILE = 0
diff --git a/libgo/go/internal/syscall/windows/registry/zsyscall_windows.go b/libgo/go/internal/syscall/windows/registry/zsyscall_windows.go
index 62affc0b50b..a3a1f5fc8f5 100644
--- a/libgo/go/internal/syscall/windows/registry/zsyscall_windows.go
+++ b/libgo/go/internal/syscall/windows/registry/zsyscall_windows.go
@@ -10,6 +10,31 @@ import (
var _ unsafe.Pointer
+// Do the interface allocations only once for common
+// Errno values.
+const (
+ errnoERROR_IO_PENDING = 997
+)
+
+var (
+ errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
+)
+
+// errnoErr returns common boxed Errno values, to prevent
+// allocations at runtime.
+func errnoErr(e syscall.Errno) error {
+ switch e {
+ case 0:
+ return nil
+ case errnoERROR_IO_PENDING:
+ return errERROR_IO_PENDING
+ }
+ // TODO: add more here, after collecting data on the common
+ // error values see on Windows. (perhaps when running
+ // all.bat?)
+ return e
+}
+
var (
modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
@@ -76,7 +101,7 @@ func expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32,
n = uint32(r0)
if n == 0 {
if e1 != 0 {
- err = error(e1)
+ err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
diff --git a/libgo/go/internal/syscall/windows/reparse_windows.go b/libgo/go/internal/syscall/windows/reparse_windows.go
new file mode 100644
index 00000000000..7c6ad8fb7e0
--- /dev/null
+++ b/libgo/go/internal/syscall/windows/reparse_windows.go
@@ -0,0 +1,64 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package windows
+
+const (
+ FSCTL_SET_REPARSE_POINT = 0x000900A4
+ IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003
+
+ SYMLINK_FLAG_RELATIVE = 1
+)
+
+// These structures are described
+// in https://msdn.microsoft.com/en-us/library/cc232007.aspx
+// and https://msdn.microsoft.com/en-us/library/cc232006.aspx.
+
+// REPARSE_DATA_BUFFER_HEADER is a common part of REPARSE_DATA_BUFFER structure.
+type REPARSE_DATA_BUFFER_HEADER struct {
+ ReparseTag uint32
+ // The size, in bytes, of the reparse data that follows
+ // the common portion of the REPARSE_DATA_BUFFER element.
+ // This value is the length of the data starting at the
+ // SubstituteNameOffset field.
+ ReparseDataLength uint16
+ Reserved uint16
+}
+
+type SymbolicLinkReparseBuffer struct {
+ // The integer that contains the offset, in bytes,
+ // of the substitute name string in the PathBuffer array,
+ // computed as an offset from byte 0 of PathBuffer. Note that
+ // this offset must be divided by 2 to get the array index.
+ SubstituteNameOffset uint16
+ // The integer that contains the length, in bytes, of the
+ // substitute name string. If this string is null-terminated,
+ // SubstituteNameLength does not include the Unicode null character.
+ SubstituteNameLength uint16
+ // PrintNameOffset is similar to SubstituteNameOffset.
+ PrintNameOffset uint16
+ // PrintNameLength is similar to SubstituteNameLength.
+ PrintNameLength uint16
+ // Flags specifies whether the substitute name is a full path name or
+ // a path name relative to the directory containing the symbolic link.
+ Flags uint32
+ PathBuffer [1]uint16
+}
+
+type MountPointReparseBuffer struct {
+ // The integer that contains the offset, in bytes,
+ // of the substitute name string in the PathBuffer array,
+ // computed as an offset from byte 0 of PathBuffer. Note that
+ // this offset must be divided by 2 to get the array index.
+ SubstituteNameOffset uint16
+ // The integer that contains the length, in bytes, of the
+ // substitute name string. If this string is null-terminated,
+ // SubstituteNameLength does not include the Unicode null character.
+ SubstituteNameLength uint16
+ // PrintNameOffset is similar to SubstituteNameOffset.
+ PrintNameOffset uint16
+ // PrintNameLength is similar to SubstituteNameLength.
+ PrintNameLength uint16
+ PathBuffer [1]uint16
+}
diff --git a/libgo/go/internal/syscall/windows/security_windows.go b/libgo/go/internal/syscall/windows/security_windows.go
new file mode 100644
index 00000000000..2c145e160f7
--- /dev/null
+++ b/libgo/go/internal/syscall/windows/security_windows.go
@@ -0,0 +1,57 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package windows
+
+import (
+ "syscall"
+)
+
+const (
+ SecurityAnonymous = 0
+ SecurityIdentification = 1
+ SecurityImpersonation = 2
+ SecurityDelegation = 3
+)
+
+//sys ImpersonateSelf(impersonationlevel uint32) (err error) = advapi32.ImpersonateSelf
+//sys RevertToSelf() (err error) = advapi32.RevertToSelf
+
+const (
+ TOKEN_ADJUST_PRIVILEGES = 0x0020
+ SE_PRIVILEGE_ENABLED = 0x00000002
+)
+
+type LUID struct {
+ LowPart uint32
+ HighPart int32
+}
+
+type LUID_AND_ATTRIBUTES struct {
+ Luid LUID
+ Attributes uint32
+}
+
+type TOKEN_PRIVILEGES struct {
+ PrivilegeCount uint32
+ Privileges [1]LUID_AND_ATTRIBUTES
+}
+
+//sys OpenThreadToken(h syscall.Handle, access uint32, openasself bool, token *syscall.Token) (err error) = advapi32.OpenThreadToken
+//sys LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) = advapi32.LookupPrivilegeValueW
+//sys adjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newstate *TOKEN_PRIVILEGES, buflen uint32, prevstate *TOKEN_PRIVILEGES, returnlen *uint32) (ret uint32, err error) [true] = advapi32.AdjustTokenPrivileges
+
+func AdjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newstate *TOKEN_PRIVILEGES, buflen uint32, prevstate *TOKEN_PRIVILEGES, returnlen *uint32) error {
+ ret, err := adjustTokenPrivileges(token, disableAllPrivileges, newstate, buflen, prevstate, returnlen)
+ if ret == 0 {
+ // AdjustTokenPrivileges call failed
+ return err
+ }
+ // AdjustTokenPrivileges call succeeded
+ if err == syscall.EINVAL {
+ // GetLastError returned ERROR_SUCCESS
+ return nil
+ }
+ return err
+}
diff --git a/libgo/go/internal/syscall/windows/syscall_windows.go b/libgo/go/internal/syscall/windows/syscall_windows.go
index 7b2bc79cebe..ec08a5a92c6 100644
--- a/libgo/go/internal/syscall/windows/syscall_windows.go
+++ b/libgo/go/internal/syscall/windows/syscall_windows.go
@@ -6,7 +6,10 @@ package windows
import "syscall"
-//go:generate go run ../../../syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go
+const (
+ ERROR_SHARING_VIOLATION syscall.Errno = 32
+ ERROR_NO_UNICODE_TRANSLATION syscall.Errno = 1113
+)
const GAA_FLAG_INCLUDE_PREFIX = 0x00000010
@@ -107,6 +110,7 @@ const (
//sys GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses
//sys GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
//sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
+//sys GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
const (
ComputerNameNetBIOS = 0
@@ -139,5 +143,25 @@ func Rename(oldpath, newpath string) error {
return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)
}
+const MB_ERR_INVALID_CHARS = 8
+
//sys GetACP() (acp uint32) = kernel32.GetACP
+//sys GetConsoleCP() (ccp uint32) = kernel32.GetConsoleCP
//sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
+//sys GetCurrentThread() (pseudoHandle syscall.Handle, err error) = kernel32.GetCurrentThread
+
+const STYPE_DISKTREE = 0x00
+
+type SHARE_INFO_2 struct {
+ Netname *uint16
+ Type uint32
+ Remark *uint16
+ Permissions uint32
+ MaxUses uint32
+ CurrentUses uint32
+ Path *uint16
+ Passwd *uint16
+}
+
+//sys NetShareAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint16) (neterr error) = netapi32.NetShareAdd
+//sys NetShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr error) = netapi32.NetShareDel
diff --git a/libgo/go/internal/syscall/windows/zsyscall_windows.go b/libgo/go/internal/syscall/windows/zsyscall_windows.go
index 6929acfa728..7a2ffeeffaf 100644
--- a/libgo/go/internal/syscall/windows/zsyscall_windows.go
+++ b/libgo/go/internal/syscall/windows/zsyscall_windows.go
@@ -10,15 +10,52 @@ import (
var _ unsafe.Pointer
+// Do the interface allocations only once for common
+// Errno values.
+const (
+ errnoERROR_IO_PENDING = 997
+)
+
+var (
+ errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
+)
+
+// errnoErr returns common boxed Errno values, to prevent
+// allocations at runtime.
+func errnoErr(e syscall.Errno) error {
+ switch e {
+ case 0:
+ return nil
+ case errnoERROR_IO_PENDING:
+ return errERROR_IO_PENDING
+ }
+ // TODO: add more here, after collecting data on the common
+ // error values see on Windows. (perhaps when running
+ // all.bat?)
+ return e
+}
+
var (
modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll"))
modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll"))
+ modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll"))
+ modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll"))
- procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
- procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
- procMoveFileExW = modkernel32.NewProc("MoveFileExW")
- procGetACP = modkernel32.NewProc("GetACP")
- procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar")
+ procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
+ procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW")
+ procMoveFileExW = modkernel32.NewProc("MoveFileExW")
+ procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW")
+ procGetACP = modkernel32.NewProc("GetACP")
+ procGetConsoleCP = modkernel32.NewProc("GetConsoleCP")
+ procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar")
+ procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
+ procNetShareAdd = modnetapi32.NewProc("NetShareAdd")
+ procNetShareDel = modnetapi32.NewProc("NetShareDel")
+ procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
+ procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
+ procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
+ procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
+ procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
)
func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
@@ -33,7 +70,7 @@ func GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) {
r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nameformat), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)))
if r1 == 0 {
if e1 != 0 {
- err = error(e1)
+ err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
@@ -45,7 +82,20 @@ func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) {
r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags))
if r1 == 0 {
if e1 != 0 {
- err = error(e1)
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) {
+ r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(fn)), uintptr(len))
+ n = uint32(r0)
+ if n == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
@@ -59,12 +109,120 @@ func GetACP() (acp uint32) {
return
}
+func GetConsoleCP() (ccp uint32) {
+ r0, _, _ := syscall.Syscall(procGetConsoleCP.Addr(), 0, 0, 0, 0)
+ ccp = uint32(r0)
+ return
+}
+
func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) {
r0, _, e1 := syscall.Syscall6(procMultiByteToWideChar.Addr(), 6, uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar))
nwrite = int32(r0)
if nwrite == 0 {
if e1 != 0 {
- err = error(e1)
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func GetCurrentThread() (pseudoHandle syscall.Handle, err error) {
+ r0, _, e1 := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0)
+ pseudoHandle = syscall.Handle(r0)
+ if pseudoHandle == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func NetShareAdd(serverName *uint16, level uint32, buf *byte, parmErr *uint16) (neterr error) {
+ r0, _, _ := syscall.Syscall6(procNetShareAdd.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(level), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(parmErr)), 0, 0)
+ if r0 != 0 {
+ neterr = syscall.Errno(r0)
+ }
+ return
+}
+
+func NetShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr error) {
+ r0, _, _ := syscall.Syscall(procNetShareDel.Addr(), 3, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(netName)), uintptr(reserved))
+ if r0 != 0 {
+ neterr = syscall.Errno(r0)
+ }
+ return
+}
+
+func ImpersonateSelf(impersonationlevel uint32) (err error) {
+ r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func RevertToSelf() (err error) {
+ r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func OpenThreadToken(h syscall.Handle, access uint32, openasself bool, token *syscall.Token) (err error) {
+ var _p0 uint32
+ if openasself {
+ _p0 = 1
+ } else {
+ _p0 = 0
+ }
+ r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(h), uintptr(access), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) {
+ r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemname)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func adjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newstate *TOKEN_PRIVILEGES, buflen uint32, prevstate *TOKEN_PRIVILEGES, returnlen *uint32) (ret uint32, err error) {
+ var _p0 uint32
+ if disableAllPrivileges {
+ _p0 = 1
+ } else {
+ _p0 = 0
+ }
+ r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen)))
+ ret = uint32(r0)
+ if true {
+ if e1 != 0 {
+ err = errnoErr(e1)
} else {
err = syscall.EINVAL
}
diff --git a/libgo/go/internal/testenv/testenv.go b/libgo/go/internal/testenv/testenv.go
index e76e33956d1..fdba8b25c3a 100644
--- a/libgo/go/internal/testenv/testenv.go
+++ b/libgo/go/internal/testenv/testenv.go
@@ -11,6 +11,7 @@
package testenv
import (
+ "errors"
"flag"
"os"
"os/exec"
@@ -70,26 +71,36 @@ func MustHaveGoRun(t *testing.T) {
}
// GoToolPath reports the path to the Go tool.
+// It is a convenience wrapper around GoTool.
// If the tool is unavailable GoToolPath calls t.Skip.
// If the tool should be available and isn't, GoToolPath calls t.Fatal.
func GoToolPath(t *testing.T) string {
MustHaveGoBuild(t)
+ path, err := GoTool()
+ if err != nil {
+ t.Fatal(err)
+ }
+ return path
+}
+// GoTool reports the path to the Go tool.
+func GoTool() (string, error) {
+ if !HasGoBuild() {
+ return "", errors.New("platform cannot run go tool")
+ }
var exeSuffix string
if runtime.GOOS == "windows" {
exeSuffix = ".exe"
}
-
path := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix)
if _, err := os.Stat(path); err == nil {
- return path
+ return path, nil
}
-
goBin, err := exec.LookPath("go" + exeSuffix)
if err != nil {
- t.Fatalf("cannot find go tool: %v", err)
+ return "", errors.New("cannot find go tool: " + err.Error())
}
- return goBin
+ return goBin, nil
}
// HasExec reports whether the current system can start new processes
@@ -130,6 +141,37 @@ func MustHaveExternalNetwork(t *testing.T) {
}
}
+// HasSymlink reports whether the current system can use os.Symlink.
+func HasSymlink() bool {
+ ok, _ := hasSymlink()
+ return ok
+}
+
+// MustHaveSymlink reports whether the current system can use os.Symlink.
+// If not, MustHaveSymlink calls t.Skip with an explanation.
+func MustHaveSymlink(t *testing.T) {
+ ok, reason := hasSymlink()
+ if !ok {
+ t.Skipf("skipping test: cannot make symlinks on %s/%s%s", runtime.GOOS, runtime.GOARCH, reason)
+ }
+}
+
+// HasLink reports whether the current system can use os.Link.
+func HasLink() bool {
+ // From Android release M (Marshmallow), hard linking files is blocked
+ // and an attempt to call link() on a file will return EACCES.
+ // - https://code.google.com/p/android-developer-preview/issues/detail?id=3150
+ return runtime.GOOS != "plan9" && runtime.GOOS != "android"
+}
+
+// MustHaveLink reports whether the current system can use os.Link.
+// If not, MustHaveLink calls t.Skip with an explanation.
+func MustHaveLink(t *testing.T) {
+ if !HasLink() {
+ t.Skipf("skipping test: hardlinks are not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
+ }
+}
+
var flaky = flag.Bool("flaky", false, "run known-flaky tests too")
func SkipFlaky(t *testing.T, issue int) {
diff --git a/libgo/go/internal/testenv/testenv_notwin.go b/libgo/go/internal/testenv/testenv_notwin.go
new file mode 100644
index 00000000000..d8ce6cd3853
--- /dev/null
+++ b/libgo/go/internal/testenv/testenv_notwin.go
@@ -0,0 +1,20 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !windows
+
+package testenv
+
+import (
+ "runtime"
+)
+
+func hasSymlink() (ok bool, reason string) {
+ switch runtime.GOOS {
+ case "android", "nacl", "plan9":
+ return false, ""
+ }
+
+ return true, ""
+}
diff --git a/libgo/go/internal/testenv/testenv_windows.go b/libgo/go/internal/testenv/testenv_windows.go
new file mode 100644
index 00000000000..e593f64711c
--- /dev/null
+++ b/libgo/go/internal/testenv/testenv_windows.go
@@ -0,0 +1,49 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package testenv
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sync"
+ "syscall"
+)
+
+var symlinkOnce sync.Once
+var winSymlinkErr error
+
+func initWinHasSymlink() {
+ tmpdir, err := ioutil.TempDir("", "symtest")
+ if err != nil {
+ panic("failed to create temp directory: " + err.Error())
+ }
+ defer os.RemoveAll(tmpdir)
+
+ err = os.Symlink("target", filepath.Join(tmpdir, "symlink"))
+ if err != nil {
+ err = err.(*os.LinkError).Err
+ switch err {
+ case syscall.EWINDOWS, syscall.ERROR_PRIVILEGE_NOT_HELD:
+ winSymlinkErr = err
+ }
+ }
+ os.Remove("target")
+}
+
+func hasSymlink() (ok bool, reason string) {
+ symlinkOnce.Do(initWinHasSymlink)
+
+ switch winSymlinkErr {
+ case nil:
+ return true, ""
+ case syscall.EWINDOWS:
+ return false, ": symlinks are not supported on your version of Windows"
+ case syscall.ERROR_PRIVILEGE_NOT_HELD:
+ return false, ": you don't have enough privileges to create symlinks"
+ }
+
+ return false, ""
+}
diff --git a/libgo/go/internal/trace/goroutines.go b/libgo/go/internal/trace/goroutines.go
index f8673e20bc2..923a157416f 100644
--- a/libgo/go/internal/trace/goroutines.go
+++ b/libgo/go/internal/trace/goroutines.go
@@ -48,7 +48,7 @@ func GoroutineStats(events []*Event) map[uint64]*GDesc {
g := &GDesc{ID: ev.Args[0], CreationTime: ev.Ts, gdesc: new(gdesc)}
g.blockSchedTime = ev.Ts
gs[g.ID] = g
- case EvGoStart:
+ case EvGoStart, EvGoStartLabel:
g := gs[ev.G]
if g.PC == 0 {
g.PC = ev.Stk[0].PC
@@ -83,6 +83,10 @@ func GoroutineStats(events []*Event) map[uint64]*GDesc {
g := gs[ev.G]
g.ExecTime += ev.Ts - g.lastStartTime
g.blockNetTime = ev.Ts
+ case EvGoBlockGC:
+ g := gs[ev.G]
+ g.ExecTime += ev.Ts - g.lastStartTime
+ g.blockGCTime = ev.Ts
case EvGoUnblock:
g := gs[ev.Args[0]]
if g.blockNetTime != 0 {
diff --git a/libgo/go/internal/trace/mkcanned.bash b/libgo/go/internal/trace/mkcanned.bash
new file mode 100644
index 00000000000..78c55720653
--- /dev/null
+++ b/libgo/go/internal/trace/mkcanned.bash
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+# Copyright 2016 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# mkcanned.bash creates canned traces for the trace test suite using
+# the current Go version.
+
+set -e
+
+if [ $# != 1 ]; then
+ echo "usage: $0 <label>" >&2
+ exit 1
+fi
+
+go test -run ClientServerParallel4 -trace "testdata/http_$1_good" net/http
+go test -run 'TraceStress$|TraceStressStartStop$' runtime/trace -savetraces
+mv ../../runtime/trace/TestTraceStress.trace "testdata/stress_$1_good"
+mv ../../runtime/trace/TestTraceStressStartStop.trace "testdata/stress_start_stop_$1_good"
diff --git a/libgo/go/internal/trace/order.go b/libgo/go/internal/trace/order.go
index 8ca2da52aa6..36ed58d675a 100644
--- a/libgo/go/internal/trace/order.go
+++ b/libgo/go/internal/trace/order.go
@@ -150,7 +150,7 @@ func stateTransition(ev *Event) (g uint64, init, next gState) {
g = ev.G
init = gState{1, gRunnable}
next = gState{2, gWaiting}
- case EvGoStart:
+ case EvGoStart, EvGoStartLabel:
g = ev.G
init = gState{ev.Args[1], gRunnable}
next = gState{ev.Args[1] + 1, gRunning}
@@ -165,7 +165,8 @@ func stateTransition(ev *Event) (g uint64, init, next gState) {
init = gState{noseq, gRunnable}
next = gState{seqinc, gRunning}
case EvGoBlock, EvGoBlockSend, EvGoBlockRecv, EvGoBlockSelect,
- EvGoBlockSync, EvGoBlockCond, EvGoBlockNet, EvGoSleep, EvGoSysBlock:
+ EvGoBlockSync, EvGoBlockCond, EvGoBlockNet, EvGoSleep,
+ EvGoSysBlock, EvGoBlockGC:
g = ev.G
init = gState{noseq, gRunning}
next = gState{noseq, gWaiting}
diff --git a/libgo/go/internal/trace/parser.go b/libgo/go/internal/trace/parser.go
index c31517f683f..efa85409a21 100644
--- a/libgo/go/internal/trace/parser.go
+++ b/libgo/go/internal/trace/parser.go
@@ -28,12 +28,13 @@ type Event struct {
StkID uint64 // unique stack ID
Stk []*Frame // stack trace (can be empty)
Args [3]uint64 // event-type-specific arguments
+ SArgs []string // event-type-specific string args
// linked event (can be nil), depends on event type:
// for GCStart: the GCStop
// for GCScanStart: the GCScanDone
// for GCSweepStart: the GCSweepDone
// for GoCreate: first GoStart of the created goroutine
- // for GoStart: the associated GoEnd, GoBlock or other blocking event
+ // for GoStart/GoStartLabel: the associated GoEnd, GoBlock or other blocking event
// for GoSched/GoPreempt: the next GoStart
// for GoBlock and other blocking events: the unblock event
// for GoUnblock: the associated GoStart
@@ -56,6 +57,7 @@ const (
TimerP // depicts timer unblocks
NetpollP // depicts network unblocks
SyscallP // depicts returns from syscalls
+ GCP // depicts GC state
)
// Parse parses, post-processes and verifies the trace.
@@ -125,7 +127,9 @@ func readTrace(r io.Reader) (ver int, events []rawEvent, strings map[uint64]stri
return
}
switch ver {
- case 1005, 1007:
+ case 1005, 1007, 1008:
+ // Note: When adding a new version, add canned traces
+ // from the old version to the test suite using mkcanned.bash.
break
default:
err = fmt.Errorf("unsupported trace file version %v.%v (update Go toolchain) %v", ver/1000, ver%1000, ver)
@@ -362,15 +366,18 @@ func parseEvents(ver int, rawEvents []rawEvent, strings map[uint64]string) (even
}
}
switch raw.typ {
- case EvGoStart, EvGoStartLocal:
+ case EvGoStart, EvGoStartLocal, EvGoStartLabel:
lastG = e.Args[0]
e.G = lastG
+ if raw.typ == EvGoStartLabel {
+ e.SArgs = []string{strings[e.Args[2]]}
+ }
case EvGCStart, EvGCDone, EvGCScanStart, EvGCScanDone:
e.G = 0
case EvGoEnd, EvGoStop, EvGoSched, EvGoPreempt,
EvGoSleep, EvGoBlock, EvGoBlockSend, EvGoBlockRecv,
EvGoBlockSelect, EvGoBlockSync, EvGoBlockCond, EvGoBlockNet,
- EvGoSysBlock:
+ EvGoSysBlock, EvGoBlockGC:
lastG = 0
case EvGoSysExit, EvGoWaiting, EvGoInSyscall:
e.G = e.Args[0]
@@ -548,6 +555,8 @@ func postProcessTrace(ver int, events []*Event) error {
return fmt.Errorf("previous GC is not ended before a new one (offset %v, time %v)", ev.Off, ev.Ts)
}
evGC = ev
+ // Attribute this to the global GC state.
+ ev.P = GCP
case EvGCDone:
if evGC == nil {
return fmt.Errorf("bogus GC end (offset %v, time %v)", ev.Off, ev.Ts)
@@ -581,11 +590,13 @@ func postProcessTrace(ver int, events []*Event) error {
return fmt.Errorf("g %v is not runnable before EvGoWaiting (offset %v, time %v)", ev.G, ev.Off, ev.Ts)
}
g.state = gWaiting
+ g.ev = ev
case EvGoInSyscall:
if g.state != gRunnable {
return fmt.Errorf("g %v is not runnable before EvGoInSyscall (offset %v, time %v)", ev.G, ev.Off, ev.Ts)
}
g.state = gWaiting
+ g.ev = ev
case EvGoCreate:
if err := checkRunning(p, g, ev, true); err != nil {
return err
@@ -594,7 +605,7 @@ func postProcessTrace(ver int, events []*Event) error {
return fmt.Errorf("g %v already exists (offset %v, time %v)", ev.Args[0], ev.Off, ev.Ts)
}
gs[ev.Args[0]] = gdesc{state: gRunnable, ev: ev, evCreate: ev}
- case EvGoStart:
+ case EvGoStart, EvGoStartLabel:
if g.state != gRunnable {
return fmt.Errorf("g %v is not runnable before start (offset %v, time %v)", ev.G, ev.Off, ev.Ts)
}
@@ -678,7 +689,7 @@ func postProcessTrace(ver int, events []*Event) error {
g.state = gRunnable
g.ev = ev
case EvGoSleep, EvGoBlock, EvGoBlockSend, EvGoBlockRecv,
- EvGoBlockSelect, EvGoBlockSync, EvGoBlockCond, EvGoBlockNet:
+ EvGoBlockSelect, EvGoBlockSync, EvGoBlockCond, EvGoBlockNet, EvGoBlockGC:
if err := checkRunning(p, g, ev, false); err != nil {
return err
}
@@ -853,8 +864,8 @@ const (
EvProcStop = 6 // stop of P [timestamp]
EvGCStart = 7 // GC start [timestamp, seq, stack id]
EvGCDone = 8 // GC done [timestamp]
- EvGCScanStart = 9 // GC scan start [timestamp]
- EvGCScanDone = 10 // GC scan done [timestamp]
+ EvGCScanStart = 9 // GC mark termination start [timestamp]
+ EvGCScanDone = 10 // GC mark termination done [timestamp]
EvGCSweepStart = 11 // GC sweep start [timestamp, stack id]
EvGCSweepDone = 12 // GC sweep done [timestamp]
EvGoCreate = 13 // goroutine creation [timestamp, new goroutine id, new stack id, stack id]
@@ -885,7 +896,9 @@ const (
EvGoStartLocal = 38 // goroutine starts running on the same P as the last event [timestamp, goroutine id]
EvGoUnblockLocal = 39 // goroutine is unblocked on the same P as the last event [timestamp, goroutine id, stack]
EvGoSysExitLocal = 40 // syscall exit on the same P as the last event [timestamp, goroutine id, real timestamp]
- EvCount = 41
+ EvGoStartLabel = 41 // goroutine starts running with label [timestamp, goroutine id, seq, label string id]
+ EvGoBlockGC = 42 // goroutine blocks on GC assist [timestamp, stack]
+ EvCount = 43
)
var EventDescriptions = [EvCount]struct {
@@ -935,4 +948,6 @@ var EventDescriptions = [EvCount]struct {
EvGoStartLocal: {"GoStartLocal", 1007, false, []string{"g"}},
EvGoUnblockLocal: {"GoUnblockLocal", 1007, true, []string{"g"}},
EvGoSysExitLocal: {"GoSysExitLocal", 1007, false, []string{"g", "ts"}},
+ EvGoStartLabel: {"GoStartLabel", 1008, false, []string{"g", "seq", "label"}},
+ EvGoBlockGC: {"GoBlockGC", 1008, true, []string{}},
}
diff --git a/libgo/go/internal/trace/parser_test.go b/libgo/go/internal/trace/parser_test.go
index daad3e3ad7e..d6f580aed5a 100644
--- a/libgo/go/internal/trace/parser_test.go
+++ b/libgo/go/internal/trace/parser_test.go
@@ -90,52 +90,13 @@ func TestParseVersion(t *testing.T) {
func TestTimestampOverflow(t *testing.T) {
// Test that parser correctly handles large timestamps (long tracing).
- w := newWriter()
- w.emit(EvBatch, 0, 0)
- w.emit(EvFrequency, 1e9)
+ w := NewWriter()
+ w.Emit(EvBatch, 0, 0)
+ w.Emit(EvFrequency, 1e9)
for ts := uint64(1); ts < 1e16; ts *= 2 {
- w.emit(EvGoCreate, ts, ts, 0, 0)
+ w.Emit(EvGoCreate, ts, ts, 0, 0)
}
if _, err := Parse(w, ""); err != nil {
t.Fatalf("failed to parse: %v", err)
}
}
-
-type writer struct {
- bytes.Buffer
-}
-
-func newWriter() *writer {
- w := new(writer)
- w.Write([]byte("go 1.7 trace\x00\x00\x00\x00"))
- return w
-}
-
-func (w *writer) emit(typ byte, args ...uint64) {
- nargs := byte(len(args)) - 1
- if nargs > 3 {
- nargs = 3
- }
- buf := []byte{typ | nargs<<6}
- if nargs == 3 {
- buf = append(buf, 0)
- }
- for _, a := range args {
- buf = appendVarint(buf, a)
- }
- if nargs == 3 {
- buf[1] = byte(len(buf) - 2)
- }
- n, err := w.Write(buf)
- if n != len(buf) || err != nil {
- panic("failed to write")
- }
-}
-
-func appendVarint(buf []byte, v uint64) []byte {
- for ; v >= 0x80; v >>= 7 {
- buf = append(buf, 0x80|byte(v))
- }
- buf = append(buf, byte(v))
- return buf
-}
diff --git a/libgo/go/internal/trace/testdata/http_1_7_good b/libgo/go/internal/trace/testdata/http_1_7_good
new file mode 100644
index 00000000000..b0e318e9a44
--- /dev/null
+++ b/libgo/go/internal/trace/testdata/http_1_7_good
Binary files differ
diff --git a/libgo/go/internal/trace/testdata/stress_1_7_good b/libgo/go/internal/trace/testdata/stress_1_7_good
new file mode 100644
index 00000000000..b4d927de341
--- /dev/null
+++ b/libgo/go/internal/trace/testdata/stress_1_7_good
Binary files differ
diff --git a/libgo/go/internal/trace/testdata/stress_start_stop_1_7_good b/libgo/go/internal/trace/testdata/stress_start_stop_1_7_good
new file mode 100644
index 00000000000..c23ed7dc087
--- /dev/null
+++ b/libgo/go/internal/trace/testdata/stress_start_stop_1_7_good
Binary files differ
diff --git a/libgo/go/internal/trace/writer.go b/libgo/go/internal/trace/writer.go
new file mode 100644
index 00000000000..a481f50a7ee
--- /dev/null
+++ b/libgo/go/internal/trace/writer.go
@@ -0,0 +1,45 @@
+package trace
+
+import "bytes"
+
+// Writer is a test trace writer.
+type Writer struct {
+ bytes.Buffer
+}
+
+func NewWriter() *Writer {
+ w := new(Writer)
+ w.Write([]byte("go 1.7 trace\x00\x00\x00\x00"))
+ return w
+}
+
+// Emit writes an event record to the trace.
+// See Event types for valid types and required arguments.
+func (w *Writer) Emit(typ byte, args ...uint64) {
+ nargs := byte(len(args)) - 1
+ if nargs > 3 {
+ nargs = 3
+ }
+ buf := []byte{typ | nargs<<6}
+ if nargs == 3 {
+ buf = append(buf, 0)
+ }
+ for _, a := range args {
+ buf = appendVarint(buf, a)
+ }
+ if nargs == 3 {
+ buf[1] = byte(len(buf) - 2)
+ }
+ n, err := w.Write(buf)
+ if n != len(buf) || err != nil {
+ panic("failed to write")
+ }
+}
+
+func appendVarint(buf []byte, v uint64) []byte {
+ for ; v >= 0x80; v >>= 7 {
+ buf = append(buf, 0x80|byte(v))
+ }
+ buf = append(buf, byte(v))
+ return buf
+}
diff --git a/libgo/go/io/io.go b/libgo/go/io/io.go
index 19d0ae5addb..9e4b86594d8 100644
--- a/libgo/go/io/io.go
+++ b/libgo/go/io/io.go
@@ -402,11 +402,10 @@ func copyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) {
break
}
}
- if er == EOF {
- break
- }
if er != nil {
- err = er
+ if er != EOF {
+ err = er
+ }
break
}
}
@@ -421,6 +420,7 @@ func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n} }
// A LimitedReader reads from R but limits the amount of
// data returned to just N bytes. Each call to Read
// updates N to reflect the new amount remaining.
+// Read returns EOF when N <= 0 or when the underlying R returns EOF.
type LimitedReader struct {
R Reader // underlying reader
N int64 // max bytes remaining
diff --git a/libgo/go/io/ioutil/ioutil.go b/libgo/go/io/ioutil/ioutil.go
index 8ecbb2de764..f0da6168305 100644
--- a/libgo/go/io/ioutil/ioutil.go
+++ b/libgo/go/io/ioutil/ioutil.go
@@ -88,13 +88,6 @@ func WriteFile(filename string, data []byte, perm os.FileMode) error {
return err
}
-// byName implements sort.Interface.
-type byName []os.FileInfo
-
-func (f byName) Len() int { return len(f) }
-func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
-func (f byName) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
-
// ReadDir reads the directory named by dirname and returns
// a list of directory entries sorted by filename.
func ReadDir(dirname string) ([]os.FileInfo, error) {
@@ -107,7 +100,7 @@ func ReadDir(dirname string) ([]os.FileInfo, error) {
if err != nil {
return nil, err
}
- sort.Sort(byName(list))
+ sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() })
return list, nil
}
diff --git a/libgo/go/io/ioutil/tempfile.go b/libgo/go/io/ioutil/tempfile.go
index 42718cc73d3..e5e315cfb7d 100644
--- a/libgo/go/io/ioutil/tempfile.go
+++ b/libgo/go/io/ioutil/tempfile.go
@@ -90,6 +90,11 @@ func TempDir(dir, prefix string) (name string, err error) {
}
continue
}
+ if os.IsNotExist(err) {
+ if _, err := os.Stat(dir); os.IsNotExist(err) {
+ return "", err
+ }
+ }
if err == nil {
name = try
}
diff --git a/libgo/go/io/ioutil/tempfile_test.go b/libgo/go/io/ioutil/tempfile_test.go
index d2a132a110a..6a70aedc324 100644
--- a/libgo/go/io/ioutil/tempfile_test.go
+++ b/libgo/go/io/ioutil/tempfile_test.go
@@ -51,3 +51,19 @@ func TestTempDir(t *testing.T) {
}
}
}
+
+// test that we return a nice error message if the dir argument to TempDir doesn't
+// exist (or that it's empty and os.TempDir doesn't exist)
+func TestTempDir_BadDir(t *testing.T) {
+ dir, err := TempDir("", "TestTempDir_BadDir")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(dir)
+
+ badDir := filepath.Join(dir, "not-exist")
+ _, err = TempDir(badDir, "foo")
+ if pe, ok := err.(*os.PathError); !ok || !os.IsNotExist(err) || pe.Path != badDir {
+ t.Errorf("TempDir error = %#v; want PathError for path %q satisifying os.IsNotExist", err, badDir)
+ }
+}
diff --git a/libgo/go/io/multi.go b/libgo/go/io/multi.go
index 3a9d03652b0..d784846862c 100644
--- a/libgo/go/io/multi.go
+++ b/libgo/go/io/multi.go
@@ -4,13 +4,19 @@
package io
+type eofReader struct{}
+
+func (eofReader) Read([]byte) (int, error) {
+ return 0, EOF
+}
+
type multiReader struct {
readers []Reader
}
func (mr *multiReader) Read(p []byte) (n int, err error) {
for len(mr.readers) > 0 {
- // Optimization to flatten nested multiReaders (Issue 13558)
+ // Optimization to flatten nested multiReaders (Issue 13558).
if len(mr.readers) == 1 {
if r, ok := mr.readers[0].(*multiReader); ok {
mr.readers = r.readers
@@ -19,6 +25,9 @@ func (mr *multiReader) Read(p []byte) (n int, err error) {
}
n, err = mr.readers[0].Read(p)
if err == EOF {
+ // Use eofReader instead of nil to avoid nil panic
+ // after performing flatten (Issue 18232).
+ mr.readers[0] = eofReader{} // permit earlier GC
mr.readers = mr.readers[1:]
}
if n > 0 || err != EOF {
diff --git a/libgo/go/io/multi_test.go b/libgo/go/io/multi_test.go
index 447e7f59635..70f2a48e9ea 100644
--- a/libgo/go/io/multi_test.go
+++ b/libgo/go/io/multi_test.go
@@ -14,6 +14,7 @@ import (
"runtime"
"strings"
"testing"
+ "time"
)
func TestMultiReader(t *testing.T) {
@@ -212,7 +213,7 @@ func (b byteAndEOFReader) Read(p []byte) (n int, err error) {
return 1, EOF
}
-// In Go 1.7, this yielded bytes forever.
+// This used to yield bytes forever; issue 16795.
func TestMultiReaderSingleByteWithEOF(t *testing.T) {
got, err := ioutil.ReadAll(LimitReader(MultiReader(byteAndEOFReader('a'), byteAndEOFReader('b')), 10))
if err != nil {
@@ -235,3 +236,60 @@ func TestMultiReaderFinalEOF(t *testing.T) {
t.Errorf("got %v, %v; want 1, EOF", n, err)
}
}
+
+func TestMultiReaderFreesExhaustedReaders(t *testing.T) {
+ if runtime.Compiler == "gccgo" {
+ t.Skip("skipping finalizer test on gccgo with conservative GC")
+ }
+
+ var mr Reader
+ closed := make(chan struct{})
+ {
+ buf1 := bytes.NewReader([]byte("foo"))
+ buf2 := bytes.NewReader([]byte("bar"))
+ mr = MultiReader(buf1, buf2)
+ runtime.SetFinalizer(buf1, func(*bytes.Reader) {
+ close(closed)
+ })
+ }
+
+ buf := make([]byte, 4)
+ if n, err := ReadFull(mr, buf); err != nil || string(buf) != "foob" {
+ t.Fatalf(`ReadFull = %d (%q), %v; want 3, "foo", nil`, n, buf[:n], err)
+ }
+
+ runtime.GC()
+ select {
+ case <-closed:
+ case <-time.After(5 * time.Second):
+ t.Fatal("timeout waiting for collection of buf1")
+ }
+
+ if n, err := ReadFull(mr, buf[:2]); err != nil || string(buf[:2]) != "ar" {
+ t.Fatalf(`ReadFull = %d (%q), %v; want 2, "ar", nil`, n, buf[:n], err)
+ }
+}
+
+func TestInterleavedMultiReader(t *testing.T) {
+ r1 := strings.NewReader("123")
+ r2 := strings.NewReader("45678")
+
+ mr1 := MultiReader(r1, r2)
+ mr2 := MultiReader(mr1)
+
+ buf := make([]byte, 4)
+
+ // Have mr2 use mr1's []Readers.
+ // Consume r1 (and clear it for GC to handle) and consume part of r2.
+ n, err := ReadFull(mr2, buf)
+ if got := string(buf[:n]); got != "1234" || err != nil {
+ t.Errorf(`ReadFull(mr2) = (%q, %v), want ("1234", nil)`, got, err)
+ }
+
+ // Consume the rest of r2 via mr1.
+ // This should not panic even though mr2 cleared r1.
+ n, err = ReadFull(mr1, buf)
+ if got := string(buf[:n]); got != "5678" || err != nil {
+ t.Errorf(`ReadFull(mr1) = (%q, %v), want ("5678", nil)`, got, err)
+ }
+}
diff --git a/libgo/go/io/pipe.go b/libgo/go/io/pipe.go
index 7e98cd2eb78..b6e7755f64c 100644
--- a/libgo/go/io/pipe.go
+++ b/libgo/go/io/pipe.go
@@ -85,6 +85,7 @@ func (p *pipe) write(b []byte) (n int, err error) {
}
if p.werr != nil {
err = ErrClosedPipe
+ break
}
p.wwait.Wait()
}
@@ -148,7 +149,7 @@ type PipeWriter struct {
}
// Write implements the standard Write interface:
-// it writes data to the pipe, blocking until readers
+// it writes data to the pipe, blocking until one or more readers
// have consumed all the data or the read end is closed.
// If the read end is closed with an error, that err is
// returned as err; otherwise err is ErrClosedPipe.
@@ -175,11 +176,17 @@ func (w *PipeWriter) CloseWithError(err error) error {
// Pipe creates a synchronous in-memory pipe.
// It can be used to connect code expecting an io.Reader
// with code expecting an io.Writer.
-// Reads on one end are matched with writes on the other,
-// copying data directly between the two; there is no internal buffering.
-// It is safe to call Read and Write in parallel with each other or with
-// Close. Close will complete once pending I/O is done. Parallel calls to
-// Read, and parallel calls to Write, are also safe:
+//
+// Reads and Writes on the pipe are matched one to one
+// except when multiple Reads are needed to consume a single Write.
+// That is, each Write to the PipeWriter blocks until it has satisfied
+// one or more Reads from the PipeReader that fully consume
+// the written data.
+// The data is copied directly from the Write to the corresponding
+// Read (or Reads); there is no internal buffering.
+//
+// It is safe to call Read and Write in parallel with each other or with Close.
+// Parallel calls to Read and parallel calls to Write are also safe:
// the individual calls will be gated sequentially.
func Pipe() (*PipeReader, *PipeWriter) {
p := new(pipe)
diff --git a/libgo/go/io/pipe_test.go b/libgo/go/io/pipe_test.go
index b16e6530693..95930e86a4e 100644
--- a/libgo/go/io/pipe_test.go
+++ b/libgo/go/io/pipe_test.go
@@ -247,6 +247,18 @@ func TestPipeWriteClose(t *testing.T) {
}
}
+// Test close on Write side during Write.
+func TestPipeWriteClose2(t *testing.T) {
+ c := make(chan int, 1)
+ _, w := Pipe()
+ go delayClose(t, w, c, pipeTest{})
+ n, err := w.Write(make([]byte, 64))
+ <-c
+ if n != 0 || err != ErrClosedPipe {
+ t.Errorf("write to closed pipe: %v, %v want %v, %v", n, err, 0, ErrClosedPipe)
+ }
+}
+
func TestWriteEmpty(t *testing.T) {
r, w := Pipe()
go func() {
diff --git a/libgo/go/log/log.go b/libgo/go/log/log.go
index 26cdb532dfc..58b8788be4a 100644
--- a/libgo/go/log/log.go
+++ b/libgo/go/log/log.go
@@ -8,6 +8,8 @@
// Panic[f|ln], which are easier to use than creating a Logger manually.
// That logger writes to standard error and prints the date and time
// of each logged message.
+// Every log message is output on a separate line: if the message being
+// printed does not end in a newline, the logger will add one.
// The Fatal functions call os.Exit(1) after writing the log message.
// The Panic functions call panic after writing the log message.
package log
diff --git a/libgo/go/log/syslog/doc.go b/libgo/go/log/syslog/doc.go
index dfcc2dde34f..54585232498 100644
--- a/libgo/go/log/syslog/doc.go
+++ b/libgo/go/log/syslog/doc.go
@@ -10,7 +10,7 @@
// the syslog client will attempt to reconnect to the server
// and write again.
//
-// The syslog package is frozen and not accepting new features.
+// The syslog package is frozen and is not accepting new features.
// Some external packages provide more functionality. See:
//
// https://godoc.org/?q=syslog
diff --git a/libgo/go/log/syslog/example_test.go b/libgo/go/log/syslog/example_test.go
new file mode 100644
index 00000000000..0513b26da17
--- /dev/null
+++ b/libgo/go/log/syslog/example_test.go
@@ -0,0 +1,24 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+// +build !windows,!nacl,!plan9
+
+package syslog_test
+
+import (
+ "fmt"
+ "log"
+ "log/syslog"
+)
+
+func ExampleDial() {
+ sysLog, err := syslog.Dial("tcp", "localhost:1234",
+ syslog.LOG_WARNING|syslog.LOG_DAEMON, "demotag")
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Fprintf(sysLog, "This is a daemon warning with demotag.")
+ sysLog.Emerg("And this is a daemon emergency with demotag.")
+}
diff --git a/libgo/go/log/syslog/syslog.go b/libgo/go/log/syslog/syslog.go
index 9e888dd1d9d..df9ffb8e331 100644
--- a/libgo/go/log/syslog/syslog.go
+++ b/libgo/go/log/syslog/syslog.go
@@ -112,6 +112,8 @@ func New(priority Priority, tag string) (*Writer, error) {
// writer sends a log message with the given facility, severity and
// tag.
// If network is empty, Dial will connect to the local syslog server.
+// Otherwise, see the documentation for net.Dial for valid values
+// of network and raddr.
func Dial(network, raddr string, priority Priority, tag string) (*Writer, error) {
if priority < 0 || priority > LOG_LOCAL7|LOG_DEBUG {
return nil, errors.New("log/syslog: invalid priority")
diff --git a/libgo/go/log/syslog/syslog_test.go b/libgo/go/log/syslog/syslog_test.go
index 52363f9f7c2..1263be6d783 100644
--- a/libgo/go/log/syslog/syslog_test.go
+++ b/libgo/go/log/syslog/syslog_test.go
@@ -134,6 +134,7 @@ func startServer(n, la string, done chan<- string) (addr string, sock io.Closer,
}
func TestWithSimulated(t *testing.T) {
+ t.Parallel()
msg := "Test 123"
var transport []string
for _, n := range []string{"unix", "unixgram", "udp", "tcp"} {
@@ -262,6 +263,7 @@ func check(t *testing.T, in, out string) {
}
func TestWrite(t *testing.T) {
+ t.Parallel()
tests := []struct {
pri Priority
pre string
@@ -367,7 +369,8 @@ func TestConcurrentReconnect(t *testing.T) {
defer wg.Done()
w, err := Dial(net, addr, LOG_USER|LOG_ERR, "tag")
if err != nil {
- t.Fatalf("syslog.Dial() failed: %v", err)
+ t.Errorf("syslog.Dial() failed: %v", err)
+ return
}
defer w.Close()
for i := 0; i < M; i++ {
diff --git a/libgo/go/math/all_test.go b/libgo/go/math/all_test.go
index d9ea1fdb51a..3d8cd7223de 100644
--- a/libgo/go/math/all_test.go
+++ b/libgo/go/math/all_test.go
@@ -1165,21 +1165,88 @@ var frexpSC = []fi{
{NaN(), 0},
}
-var vfgammaSC = []float64{
- Inf(-1),
- -3,
- Copysign(0, -1),
- 0,
- Inf(1),
- NaN(),
-}
-var gammaSC = []float64{
- NaN(),
- NaN(),
- Inf(-1),
- Inf(1),
- Inf(1),
- NaN(),
+var vfgamma = [][2]float64{
+ {Inf(1), Inf(1)},
+ {Inf(-1), NaN()},
+ {0, Inf(1)},
+ {Copysign(0, -1), Inf(-1)},
+ {NaN(), NaN()},
+ {-1, NaN()},
+ {-2, NaN()},
+ {-3, NaN()},
+ {-1e16, NaN()},
+ {-1e300, NaN()},
+ {1.7e308, Inf(1)},
+
+ // Test inputs inspired by Python test suite.
+ // Outputs computed at high precision by PARI/GP.
+ // If recomputing table entries, be careful to use
+ // high-precision (%.1000g) formatting of the float64 inputs.
+ // For example, -2.0000000000000004 is the float64 with exact value
+ // -2.00000000000000044408920985626161695, and
+ // gamma(-2.0000000000000004) = -1249999999999999.5386078562728167651513, while
+ // gamma(-2.00000000000000044408920985626161695) = -1125899906826907.2044875028130093136826.
+ // Thus the table lists -1.1258999068426235e+15 as the answer.
+ {0.5, 1.772453850905516},
+ {1.5, 0.886226925452758},
+ {2.5, 1.329340388179137},
+ {3.5, 3.3233509704478426},
+ {-0.5, -3.544907701811032},
+ {-1.5, 2.363271801207355},
+ {-2.5, -0.9453087204829419},
+ {-3.5, 0.2700882058522691},
+ {0.1, 9.51350769866873},
+ {0.01, 99.4325851191506},
+ {1e-08, 9.999999942278434e+07},
+ {1e-16, 1e+16},
+ {0.001, 999.4237724845955},
+ {1e-16, 1e+16},
+ {1e-308, 1e+308},
+ {5.6e-309, 1.7857142857142864e+308},
+ {5.5e-309, Inf(1)},
+ {1e-309, Inf(1)},
+ {1e-323, Inf(1)},
+ {5e-324, Inf(1)},
+ {-0.1, -10.686287021193193},
+ {-0.01, -100.58719796441078},
+ {-1e-08, -1.0000000057721567e+08},
+ {-1e-16, -1e+16},
+ {-0.001, -1000.5782056293586},
+ {-1e-16, -1e+16},
+ {-1e-308, -1e+308},
+ {-5.6e-309, -1.7857142857142864e+308},
+ {-5.5e-309, Inf(-1)},
+ {-1e-309, Inf(-1)},
+ {-1e-323, Inf(-1)},
+ {-5e-324, Inf(-1)},
+ {-0.9999999999999999, -9.007199254740992e+15},
+ {-1.0000000000000002, 4.5035996273704955e+15},
+ {-1.9999999999999998, 2.2517998136852485e+15},
+ {-2.0000000000000004, -1.1258999068426235e+15},
+ {-100.00000000000001, -7.540083334883109e-145},
+ {-99.99999999999999, 7.540083334884096e-145},
+ {17, 2.0922789888e+13},
+ {171, 7.257415615307999e+306},
+ {171.6, 1.5858969096672565e+308},
+ {171.624, 1.7942117599248104e+308},
+ {171.625, Inf(1)},
+ {172, Inf(1)},
+ {2000, Inf(1)},
+ {-100.5, -3.3536908198076787e-159},
+ {-160.5, -5.255546447007829e-286},
+ {-170.5, -3.3127395215386074e-308},
+ {-171.5, 1.9316265431712e-310},
+ {-176.5, -1.196e-321},
+ {-177.5, 5e-324},
+ {-178.5, Copysign(0, -1)},
+ {-179.5, 0},
+ {-201.0001, 0},
+ {-202.9999, Copysign(0, -1)},
+ {-1000.5, Copysign(0, -1)},
+ {-1.0000000003e+09, Copysign(0, -1)},
+ {-4.5035996273704955e+15, 0},
+ {-63.349078729022985, 4.177797167776188e-88},
+ {-127.45117632943295, 1.183111089623681e-214},
}
var vfhypotSC = [][2]float64{
@@ -1735,6 +1802,12 @@ var logbBC = []float64{
}
func tolerance(a, b, e float64) bool {
+ // Multiplying by e here can underflow denormal values to zero.
+ // Check a==b so that at least if a and b are small and identical
+ // we say they match.
+ if a == b {
+ return true
+ }
d := a - b
if d < 0 {
d = -d
@@ -1974,7 +2047,7 @@ func TestExp(t *testing.T) {
func testExp(t *testing.T, Exp func(float64) float64, name string) {
for i := 0; i < len(vf); i++ {
- if f := Exp(vf[i]); !close(exp[i], f) {
+ if f := Exp(vf[i]); !veryclose(exp[i], f) {
t.Errorf("%s(%g) = %g, want %g", name, vf[i], f, exp[i])
}
}
@@ -2147,9 +2220,18 @@ func TestGamma(t *testing.T) {
t.Errorf("Gamma(%g) = %g, want %g", vf[i], f, gamma[i])
}
}
- for i := 0; i < len(vfgammaSC); i++ {
- if f := Gamma(vfgammaSC[i]); !alike(gammaSC[i], f) {
- t.Errorf("Gamma(%g) = %g, want %g", vfgammaSC[i], f, gammaSC[i])
+ for _, g := range vfgamma {
+ f := Gamma(g[0])
+ var ok bool
+ if IsNaN(g[1]) || IsInf(g[1], 0) || g[1] == 0 || f == 0 {
+ ok = alike(g[1], f)
+ } else if g[0] > -50 && g[0] <= 171 {
+ ok = veryclose(g[1], f)
+ } else {
+ ok = close(g[1], f)
+ }
+ if !ok {
+ t.Errorf("Gamma(%g) = %g, want %g", g[0], f, g[1])
}
}
}
@@ -3000,27 +3082,36 @@ func BenchmarkSinh(b *testing.B) {
var Global float64
-func BenchmarkSqrt(b *testing.B) {
+func BenchmarkSqrtIndirect(b *testing.B) {
x, y := 0.0, 10.0
+ f := Sqrt
for i := 0; i < b.N; i++ {
- x += Sqrt(y)
+ x += f(y)
}
Global = x
}
-func BenchmarkSqrtIndirect(b *testing.B) {
- x, y := 0.0, 10.0
+func BenchmarkSqrtLatency(b *testing.B) {
+ x := 10.0
+ for i := 0; i < b.N; i++ {
+ x = Sqrt(x)
+ }
+ Global = x
+}
+
+func BenchmarkSqrtIndirectLatency(b *testing.B) {
+ x := 10.0
f := Sqrt
for i := 0; i < b.N; i++ {
- x += f(y)
+ x = f(x)
}
Global = x
}
-func BenchmarkSqrtGo(b *testing.B) {
- x, y := 0.0, 10.0
+func BenchmarkSqrtGoLatency(b *testing.B) {
+ x := 10.0
for i := 0; i < b.N; i++ {
- x += SqrtGo(y)
+ x = SqrtGo(x)
}
Global = x
}
diff --git a/libgo/go/math/arith_s390x.go b/libgo/go/math/arith_s390x.go
new file mode 100644
index 00000000000..937f25faace
--- /dev/null
+++ b/libgo/go/math/arith_s390x.go
@@ -0,0 +1,31 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package math
+
+func log10TrampolineSetup(x float64) float64
+func log10Asm(x float64) float64
+
+func cosTrampolineSetup(x float64) float64
+func cosAsm(x float64) float64
+
+func coshTrampolineSetup(x float64) float64
+func coshAsm(x float64) float64
+
+func sinTrampolineSetup(x float64) float64
+func sinAsm(x float64) float64
+
+func sinhTrampolineSetup(x float64) float64
+func sinhAsm(x float64) float64
+
+func tanhTrampolineSetup(x float64) float64
+func tanhAsm(x float64) float64
+
+// hasVectorFacility reports whether the machine has the z/Architecture
+// vector facility installed and enabled.
+func hasVectorFacility() bool
+
+var hasVX = hasVectorFacility()
diff --git a/libgo/go/math/arith_s390x_test.go b/libgo/go/math/arith_s390x_test.go
new file mode 100644
index 00000000000..fd3e8ca4281
--- /dev/null
+++ b/libgo/go/math/arith_s390x_test.go
@@ -0,0 +1,146 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// Tests whether the non vector routines are working, even when the tests are run on a
+// vector-capable machine.
+package math_test
+
+import (
+ . "math"
+ "testing"
+)
+
+func TestCosNovec(t *testing.T) {
+ if !HasVX {
+ t.Skipf("no vector support")
+ }
+ for i := 0; i < len(vf); i++ {
+ if f := CosNoVec(vf[i]); !veryclose(cos[i], f) {
+ t.Errorf("Cos(%g) = %g, want %g", vf[i], f, cos[i])
+ }
+ }
+ for i := 0; i < len(vfcosSC); i++ {
+ if f := CosNoVec(vfcosSC[i]); !alike(cosSC[i], f) {
+ t.Errorf("Cos(%g) = %g, want %g", vfcosSC[i], f, cosSC[i])
+ }
+ }
+}
+
+func TestCoshNovec(t *testing.T) {
+ if !HasVX {
+ t.Skipf("no vector support")
+ }
+ for i := 0; i < len(vf); i++ {
+ if f := CoshNoVec(vf[i]); !close(cosh[i], f) {
+ t.Errorf("Cosh(%g) = %g, want %g", vf[i], f, cosh[i])
+ }
+ }
+ for i := 0; i < len(vfcoshSC); i++ {
+ if f := CoshNoVec(vfcoshSC[i]); !alike(coshSC[i], f) {
+ t.Errorf("Cosh(%g) = %g, want %g", vfcoshSC[i], f, coshSC[i])
+ }
+ }
+}
+func TestSinNovec(t *testing.T) {
+ if !HasVX {
+ t.Skipf("no vector support")
+ }
+ for i := 0; i < len(vf); i++ {
+ if f := SinNoVec(vf[i]); !veryclose(sin[i], f) {
+ t.Errorf("Sin(%g) = %g, want %g", vf[i], f, sin[i])
+ }
+ }
+ for i := 0; i < len(vfsinSC); i++ {
+ if f := SinNoVec(vfsinSC[i]); !alike(sinSC[i], f) {
+ t.Errorf("Sin(%g) = %g, want %g", vfsinSC[i], f, sinSC[i])
+ }
+ }
+}
+
+func TestSinhNovec(t *testing.T) {
+ if !HasVX {
+ t.Skipf("no vector support")
+ }
+ for i := 0; i < len(vf); i++ {
+ if f := SinhNoVec(vf[i]); !close(sinh[i], f) {
+ t.Errorf("Sinh(%g) = %g, want %g", vf[i], f, sinh[i])
+ }
+ }
+ for i := 0; i < len(vfsinhSC); i++ {
+ if f := SinhNoVec(vfsinhSC[i]); !alike(sinhSC[i], f) {
+ t.Errorf("Sinh(%g) = %g, want %g", vfsinhSC[i], f, sinhSC[i])
+ }
+ }
+}
+
+// Check that math functions of high angle values
+// return accurate results. [Since (vf[i] + large) - large != vf[i],
+// testing for Trig(vf[i] + large) == Trig(vf[i]), where large is
+// a multiple of 2*Pi, is misleading.]
+func TestLargeCosNovec(t *testing.T) {
+ if !HasVX {
+ t.Skipf("no vector support")
+ }
+ large := float64(100000 * Pi)
+ for i := 0; i < len(vf); i++ {
+ f1 := cosLarge[i]
+ f2 := CosNoVec(vf[i] + large)
+ if !close(f1, f2) {
+ t.Errorf("Cos(%g) = %g, want %g", vf[i]+large, f2, f1)
+ }
+ }
+}
+
+func TestLargeSinNovec(t *testing.T) {
+ if !HasVX {
+ t.Skipf("no vector support")
+ }
+ large := float64(100000 * Pi)
+ for i := 0; i < len(vf); i++ {
+ f1 := sinLarge[i]
+ f2 := SinNoVec(vf[i] + large)
+ if !close(f1, f2) {
+ t.Errorf("Sin(%g) = %g, want %g", vf[i]+large, f2, f1)
+ }
+ }
+}
+
+func TestTanhNovec(t *testing.T) {
+ if !HasVX {
+ t.Skipf("no vector support")
+ }
+ for i := 0; i < len(vf); i++ {
+ if f := TanhNoVec(vf[i]); !veryclose(tanh[i], f) {
+ t.Errorf("Tanh(%g) = %g, want %g", vf[i], f, tanh[i])
+ }
+ }
+ for i := 0; i < len(vftanhSC); i++ {
+ if f := TanhNoVec(vftanhSC[i]); !alike(tanhSC[i], f) {
+ t.Errorf("Tanh(%g) = %g, want %g", vftanhSC[i], f, tanhSC[i])
+ }
+ }
+
+}
+
+func TestLog10Novec(t *testing.T) {
+ if !HasVX {
+ t.Skipf("no vector support")
+ }
+ for i := 0; i < len(vf); i++ {
+ a := Abs(vf[i])
+ if f := Log10NoVec(a); !veryclose(log10[i], f) {
+ t.Errorf("Log10(%g) = %g, want %g", a, f, log10[i])
+ }
+ }
+ if f := Log10NoVec(E); f != Log10E {
+ t.Errorf("Log10(%g) = %g, want %g", E, f, Log10E)
+ }
+ for i := 0; i < len(vflogSC); i++ {
+ if f := Log10NoVec(vflogSC[i]); !alike(logSC[i], f) {
+ t.Errorf("Log10(%g) = %g, want %g", vflogSC[i], f, logSC[i])
+ }
+ }
+}
diff --git a/libgo/go/math/big/arith_decl_s390x.go b/libgo/go/math/big/arith_decl_s390x.go
new file mode 100644
index 00000000000..0f11481f6d2
--- /dev/null
+++ b/libgo/go/math/big/arith_decl_s390x.go
@@ -0,0 +1,23 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !math_big_pure_go
+
+package big
+
+func addVV_check(z, x, y []Word) (c Word)
+func addVV_vec(z, x, y []Word) (c Word)
+func addVV_novec(z, x, y []Word) (c Word)
+func subVV_check(z, x, y []Word) (c Word)
+func subVV_vec(z, x, y []Word) (c Word)
+func subVV_novec(z, x, y []Word) (c Word)
+func addVW_check(z, x []Word, y Word) (c Word)
+func addVW_vec(z, x []Word, y Word) (c Word)
+func addVW_novec(z, x []Word, y Word) (c Word)
+func subVW_check(z, x []Word, y Word) (c Word)
+func subVW_vec(z, x []Word, y Word) (c Word)
+func subVW_novec(z, x []Word, y Word) (c Word)
+func hasVectorFacility() bool
+
+var hasVX = hasVectorFacility()
diff --git a/libgo/go/math/big/arith_s390x_test.go b/libgo/go/math/big/arith_s390x_test.go
new file mode 100644
index 00000000000..ee127a4fc92
--- /dev/null
+++ b/libgo/go/math/big/arith_s390x_test.go
@@ -0,0 +1,45 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+// +build s390x !math_big_pure_go
+
+package big
+
+import (
+ "testing"
+)
+
+// Tests whether the non vector routines are working, even when the tests are run on a
+// vector-capable machine
+
+func TestFunVVnovec(t *testing.T) {
+ if hasVX == true {
+ for _, a := range sumVV {
+ arg := a
+ testFunVV(t, "addVV_novec", addVV_novec, arg)
+
+ arg = argVV{a.z, a.y, a.x, a.c}
+ testFunVV(t, "addVV_novec symmetric", addVV_novec, arg)
+
+ arg = argVV{a.x, a.z, a.y, a.c}
+ testFunVV(t, "subVV_novec", subVV_novec, arg)
+
+ arg = argVV{a.y, a.z, a.x, a.c}
+ testFunVV(t, "subVV_novec symmetric", subVV_novec, arg)
+ }
+ }
+}
+
+func TestFunVWnovec(t *testing.T) {
+ if hasVX == true {
+ for _, a := range sumVW {
+ arg := a
+ testFunVW(t, "addVW_novec", addVW_novec, arg)
+
+ arg = argVW{a.x, a.z, a.y, a.c}
+ testFunVW(t, "subVW_novec", subVW_novec, arg)
+ }
+ }
+}
diff --git a/libgo/go/math/big/arith_test.go b/libgo/go/math/big/arith_test.go
index 75862b4951f..f2b30830009 100644
--- a/libgo/go/math/big/arith_test.go
+++ b/libgo/go/math/big/arith_test.go
@@ -6,10 +6,14 @@ package big
import (
"fmt"
+ "internal/testenv"
"math/rand"
+ "strings"
"testing"
)
+var isRaceBuilder = strings.HasSuffix(testenv.Builder(), "-race")
+
type funWW func(x, y, c Word) (z1, z0 Word)
type argWW struct {
x, y, c, z1, z0 Word
@@ -123,6 +127,9 @@ var benchSizes = []int{1, 2, 3, 4, 5, 1e1, 1e2, 1e3, 1e4, 1e5}
func BenchmarkAddVV(b *testing.B) {
for _, n := range benchSizes {
+ if isRaceBuilder && n > 1e3 {
+ continue
+ }
x := rndV(n)
y := rndV(n)
z := make([]Word, n)
@@ -233,6 +240,9 @@ func TestFunVW(t *testing.T) {
func BenchmarkAddVW(b *testing.B) {
for _, n := range benchSizes {
+ if isRaceBuilder && n > 1e3 {
+ continue
+ }
x := rndV(n)
y := rndW()
z := make([]Word, n)
@@ -371,6 +381,9 @@ func TestMulAddWWW(t *testing.T) {
func BenchmarkAddMulVVW(b *testing.B) {
for _, n := range benchSizes {
+ if isRaceBuilder && n > 1e3 {
+ continue
+ }
x := rndV(n)
y := rndW()
z := make([]Word, n)
diff --git a/libgo/go/math/big/decimal.go b/libgo/go/math/big/decimal.go
index 2c0c9daebc1..2dfa032c776 100644
--- a/libgo/go/math/big/decimal.go
+++ b/libgo/go/math/big/decimal.go
@@ -125,11 +125,12 @@ func shr(x *decimal, s uint) {
// read a digit, write a digit
w := 0 // write index
+ mask := Word(1)<<s - 1
for r < len(x.mant) {
ch := Word(x.mant[r])
r++
d := n >> s
- n -= d << s
+ n &= mask // n -= d << s
x.mant[w] = byte(d + '0')
w++
n = n*10 + ch - '0'
@@ -138,7 +139,7 @@ func shr(x *decimal, s uint) {
// write extra digits that still fit
for n > 0 && w < len(x.mant) {
d := n >> s
- n -= d << s
+ n &= mask
x.mant[w] = byte(d + '0')
w++
n = n * 10
@@ -148,7 +149,7 @@ func shr(x *decimal, s uint) {
// append additional digits that didn't fit
for n > 0 {
d := n >> s
- n -= d << s
+ n &= mask
x.mant = append(x.mant, byte(d+'0'))
n = n * 10
}
diff --git a/libgo/go/math/big/decimal_test.go b/libgo/go/math/big/decimal_test.go
index 15bdb181e72..424811e15af 100644
--- a/libgo/go/math/big/decimal_test.go
+++ b/libgo/go/math/big/decimal_test.go
@@ -4,7 +4,10 @@
package big
-import "testing"
+import (
+ "fmt"
+ "testing"
+)
func TestDecimalString(t *testing.T) {
for _, test := range []struct {
@@ -105,12 +108,27 @@ func TestDecimalRounding(t *testing.T) {
}
}
+var sink string
+
func BenchmarkDecimalConversion(b *testing.B) {
for i := 0; i < b.N; i++ {
for shift := -100; shift <= +100; shift++ {
var d decimal
d.init(natOne, shift)
- d.String()
+ sink = d.String()
}
}
}
+
+func BenchmarkFloatString(b *testing.B) {
+ x := new(Float)
+ for _, prec := range []uint{1e2, 1e3, 1e4, 1e5} {
+ x.SetPrec(prec).SetRat(NewRat(1, 3))
+ b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) {
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ sink = x.String()
+ }
+ })
+ }
+}
diff --git a/libgo/go/math/big/doc.go b/libgo/go/math/big/doc.go
index a3c23751ba4..65ed019b741 100644
--- a/libgo/go/math/big/doc.go
+++ b/libgo/go/math/big/doc.go
@@ -31,7 +31,7 @@ setters, for instance:
var z1 Int
z1.SetUint64(123) // z1 := 123
- z2 := new(Rat).SetFloat64(1.2) // z2 := 6/5
+ z2 := new(Rat).SetFloat64(1.25) // z2 := 5/4
z3 := new(Float).SetInt(z1) // z3 := 123.0
Setters, numeric operations and predicates are represented as methods of
diff --git a/libgo/go/math/big/float.go b/libgo/go/math/big/float.go
index 7a9c2b3dfb2..aabd7b44777 100644
--- a/libgo/go/math/big/float.go
+++ b/libgo/go/math/big/float.go
@@ -1210,20 +1210,30 @@ func (z *Float) uadd(x, y *Float) {
ex := int64(x.exp) - int64(len(x.mant))*_W
ey := int64(y.exp) - int64(len(y.mant))*_W
+ al := alias(z.mant, x.mant) || alias(z.mant, y.mant)
+
// TODO(gri) having a combined add-and-shift primitive
// could make this code significantly faster
switch {
case ex < ey:
- // cannot re-use z.mant w/o testing for aliasing
- t := nat(nil).shl(y.mant, uint(ey-ex))
- z.mant = z.mant.add(x.mant, t)
+ if al {
+ t := nat(nil).shl(y.mant, uint(ey-ex))
+ z.mant = z.mant.add(x.mant, t)
+ } else {
+ z.mant = z.mant.shl(y.mant, uint(ey-ex))
+ z.mant = z.mant.add(x.mant, z.mant)
+ }
default:
// ex == ey, no shift needed
z.mant = z.mant.add(x.mant, y.mant)
case ex > ey:
- // cannot re-use z.mant w/o testing for aliasing
- t := nat(nil).shl(x.mant, uint(ex-ey))
- z.mant = z.mant.add(t, y.mant)
+ if al {
+ t := nat(nil).shl(x.mant, uint(ex-ey))
+ z.mant = z.mant.add(t, y.mant)
+ } else {
+ z.mant = z.mant.shl(x.mant, uint(ex-ey))
+ z.mant = z.mant.add(z.mant, y.mant)
+ }
ex = ey
}
// len(z.mant) > 0
@@ -1247,18 +1257,28 @@ func (z *Float) usub(x, y *Float) {
ex := int64(x.exp) - int64(len(x.mant))*_W
ey := int64(y.exp) - int64(len(y.mant))*_W
+ al := alias(z.mant, x.mant) || alias(z.mant, y.mant)
+
switch {
case ex < ey:
- // cannot re-use z.mant w/o testing for aliasing
- t := nat(nil).shl(y.mant, uint(ey-ex))
- z.mant = t.sub(x.mant, t)
+ if al {
+ t := nat(nil).shl(y.mant, uint(ey-ex))
+ z.mant = t.sub(x.mant, t)
+ } else {
+ z.mant = z.mant.shl(y.mant, uint(ey-ex))
+ z.mant = z.mant.sub(x.mant, z.mant)
+ }
default:
// ex == ey, no shift needed
z.mant = z.mant.sub(x.mant, y.mant)
case ex > ey:
- // cannot re-use z.mant w/o testing for aliasing
- t := nat(nil).shl(x.mant, uint(ex-ey))
- z.mant = t.sub(t, y.mant)
+ if al {
+ t := nat(nil).shl(x.mant, uint(ex-ey))
+ z.mant = t.sub(t, y.mant)
+ } else {
+ z.mant = z.mant.shl(x.mant, uint(ex-ey))
+ z.mant = z.mant.sub(z.mant, y.mant)
+ }
ex = ey
}
diff --git a/libgo/go/math/big/float_test.go b/libgo/go/math/big/float_test.go
index 464619b3380..7d4bd312c9b 100644
--- a/libgo/go/math/big/float_test.go
+++ b/libgo/go/math/big/float_test.go
@@ -5,6 +5,7 @@
package big
import (
+ "flag"
"fmt"
"math"
"strconv"
@@ -1495,12 +1496,14 @@ func TestFloatQuo(t *testing.T) {
}
}
+var long = flag.Bool("long", false, "run very long tests")
+
// TestFloatQuoSmoke tests all divisions x/y for values x, y in the range [-n, +n];
// it serves as a smoke test for basic correctness of division.
func TestFloatQuoSmoke(t *testing.T) {
- n := 1000
- if testing.Short() {
- n = 10
+ n := 10
+ if *long {
+ n = 1000
}
const dprec = 3 // max. precision variation
@@ -1762,3 +1765,41 @@ func TestFloatCmpSpecialValues(t *testing.T) {
}
}
}
+
+func BenchmarkFloatAdd(b *testing.B) {
+ x := new(Float)
+ y := new(Float)
+ z := new(Float)
+
+ for _, prec := range []uint{10, 1e2, 1e3, 1e4, 1e5} {
+ x.SetPrec(prec).SetRat(NewRat(1, 3))
+ y.SetPrec(prec).SetRat(NewRat(1, 6))
+ z.SetPrec(prec)
+
+ b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) {
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ z.Add(x, y)
+ }
+ })
+ }
+}
+
+func BenchmarkFloatSub(b *testing.B) {
+ x := new(Float)
+ y := new(Float)
+ z := new(Float)
+
+ for _, prec := range []uint{10, 1e2, 1e3, 1e4, 1e5} {
+ x.SetPrec(prec).SetRat(NewRat(1, 3))
+ y.SetPrec(prec).SetRat(NewRat(1, 6))
+ z.SetPrec(prec)
+
+ b.Run(fmt.Sprintf("%v", prec), func(b *testing.B) {
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ z.Sub(x, y)
+ }
+ })
+ }
+}
diff --git a/libgo/go/math/big/floatconv.go b/libgo/go/math/big/floatconv.go
index a884df6fe1c..95d1bf84e24 100644
--- a/libgo/go/math/big/floatconv.go
+++ b/libgo/go/math/big/floatconv.go
@@ -12,9 +12,13 @@ import (
"strings"
)
+var floatZero Float
+
// SetString sets z to the value of s and returns z and a boolean indicating
// success. s must be a floating-point number of the same format as accepted
-// by Parse, with base argument 0.
+// by Parse, with base argument 0. The entire string (not just a prefix) must
+// be valid for success. If the operation failed, the value of z is undefined
+// but the returned value is nil.
func (z *Float) SetString(s string) (*Float, bool) {
if f, _, err := z.Parse(s, 0); err == nil {
return f, true
@@ -212,17 +216,18 @@ func (z *Float) pow5(n uint64) *Float {
//
// It sets z to the (possibly rounded) value of the corresponding floating-
// point value, and returns z, the actual base b, and an error err, if any.
+// The entire string (not just a prefix) must be consumed for success.
// If z's precision is 0, it is changed to 64 before rounding takes effect.
// The number must be of the form:
//
// number = [ sign ] [ prefix ] mantissa [ exponent ] | infinity .
// sign = "+" | "-" .
-// prefix = "0" ( "x" | "X" | "b" | "B" ) .
+// prefix = "0" ( "x" | "X" | "b" | "B" ) .
// mantissa = digits | digits "." [ digits ] | "." digits .
// exponent = ( "E" | "e" | "p" ) [ sign ] digits .
// digits = digit { digit } .
// digit = "0" ... "9" | "a" ... "z" | "A" ... "Z" .
-// infinity = [ sign ] ( "inf" | "Inf" ) .
+// infinity = [ sign ] ( "inf" | "Inf" ) .
//
// The base argument must be 0, 2, 10, or 16. Providing an invalid base
// argument will lead to a run-time panic.
@@ -273,3 +278,16 @@ func (z *Float) Parse(s string, base int) (f *Float, b int, err error) {
func ParseFloat(s string, base int, prec uint, mode RoundingMode) (f *Float, b int, err error) {
return new(Float).SetPrec(prec).SetMode(mode).Parse(s, base)
}
+
+var _ fmt.Scanner = &floatZero // *Float must implement fmt.Scanner
+
+// Scan is a support routine for fmt.Scanner; it sets z to the value of
+// the scanned number. It accepts formats whose verbs are supported by
+// fmt.Scan for floating point values, which are:
+// 'b' (binary), 'e', 'E', 'f', 'F', 'g' and 'G'.
+// Scan doesn't handle ±Inf.
+func (z *Float) Scan(s fmt.ScanState, ch rune) error {
+ s.SkipSpace()
+ _, _, err := z.scan(byteReader{s}, 0)
+ return err
+}
diff --git a/libgo/go/math/big/floatconv_test.go b/libgo/go/math/big/floatconv_test.go
index b2a1ab05fcc..edcb2eb1050 100644
--- a/libgo/go/math/big/floatconv_test.go
+++ b/libgo/go/math/big/floatconv_test.go
@@ -5,6 +5,7 @@
package big
import (
+ "bytes"
"fmt"
"math"
"strconv"
@@ -665,3 +666,54 @@ func BenchmarkParseFloatLargeExp(b *testing.B) {
}
}
}
+
+func TestFloatScan(t *testing.T) {
+ var floatScanTests = []struct {
+ input string
+ format string
+ output string
+ remaining int
+ wantErr bool
+ }{
+ 0: {"10.0", "%f", "10", 0, false},
+ 1: {"23.98+2.0", "%v", "23.98", 4, false},
+ 2: {"-1+1", "%v", "-1", 2, false},
+ 3: {" 00000", "%v", "0", 0, false},
+ 4: {"-123456p-78", "%b", "-4.084816388e-19", 0, false},
+ 5: {"+123", "%b", "123", 0, false},
+ 6: {"-1.234e+56", "%e", "-1.234e+56", 0, false},
+ 7: {"-1.234E-56", "%E", "-1.234e-56", 0, false},
+ 8: {"-1.234e+567", "%g", "-1.234e+567", 0, false},
+ 9: {"+1234567891011.234", "%G", "1.234567891e+12", 0, false},
+
+ // Scan doesn't handle ±Inf.
+ 10: {"Inf", "%v", "", 3, true},
+ 11: {"-Inf", "%v", "", 3, true},
+ 12: {"-Inf", "%v", "", 3, true},
+ }
+
+ var buf bytes.Buffer
+ for i, test := range floatScanTests {
+ x := new(Float)
+ buf.Reset()
+ buf.WriteString(test.input)
+ _, err := fmt.Fscanf(&buf, test.format, x)
+ if test.wantErr {
+ if err == nil {
+ t.Errorf("#%d want non-nil err", i)
+ }
+ continue
+ }
+
+ if err != nil {
+ t.Errorf("#%d error: %s", i, err)
+ }
+
+ if x.String() != test.output {
+ t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
+ }
+ if buf.Len() != test.remaining {
+ t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
+ }
+ }
+}
diff --git a/libgo/go/math/big/floatexample_test.go b/libgo/go/math/big/floatexample_test.go
index 05bce613a80..8645c44f103 100644
--- a/libgo/go/math/big/floatexample_test.go
+++ b/libgo/go/math/big/floatexample_test.go
@@ -13,7 +13,7 @@ import (
)
func ExampleFloat_Add() {
- // Operating on numbers of different precision.
+ // Operate on numbers of different precision.
var x, y, z big.Float
x.SetInt64(1000) // x is automatically set to 64bit precision
y.SetFloat64(2.718281828) // y is automatically set to 53bit precision
@@ -28,8 +28,8 @@ func ExampleFloat_Add() {
// z = 1002.718282 (0x.faadf854p+10, prec = 32, acc = Below)
}
-func Example_Shift() {
- // Implementing Float "shift" by modifying the (binary) exponents directly.
+func ExampleFloat_shift() {
+ // Implement Float "shift" by modifying the (binary) exponents directly.
for s := -5; s <= 5; s++ {
x := big.NewFloat(0.5)
x.SetMantExp(x, x.MantExp(nil)+s) // shift x by s
diff --git a/libgo/go/math/big/floatmarsh.go b/libgo/go/math/big/floatmarsh.go
index 3725d4b8345..d1c1dab0691 100644
--- a/libgo/go/math/big/floatmarsh.go
+++ b/libgo/go/math/big/floatmarsh.go
@@ -16,7 +16,7 @@ const floatGobVersion byte = 1
// GobEncode implements the gob.GobEncoder interface.
// The Float value and all its attributes (precision,
-// rounding mode, accuracy) are marshalled.
+// rounding mode, accuracy) are marshaled.
func (x *Float) GobEncode() ([]byte, error) {
if x == nil {
return nil, nil
diff --git a/libgo/go/math/big/ftoa.go b/libgo/go/math/big/ftoa.go
index 57b16e1ad1f..d2a85886c72 100644
--- a/libgo/go/math/big/ftoa.go
+++ b/libgo/go/math/big/ftoa.go
@@ -376,6 +376,8 @@ func min(x, y int) int {
return y
}
+var _ fmt.Formatter = &floatZero // *Float must implement fmt.Formatter
+
// Format implements fmt.Formatter. It accepts all the regular
// formats for floating-point numbers ('b', 'e', 'E', 'f', 'F',
// 'g', 'G') as well as 'p' and 'v'. See (*Float).Text for the
diff --git a/libgo/go/math/big/gcd_test.go b/libgo/go/math/big/gcd_test.go
index a929bf597f4..3cca2ecd0c8 100644
--- a/libgo/go/math/big/gcd_test.go
+++ b/libgo/go/math/big/gcd_test.go
@@ -20,6 +20,9 @@ func randInt(r *rand.Rand, size uint) *Int {
}
func runGCD(b *testing.B, aSize, bSize uint) {
+ if isRaceBuilder && (aSize > 1000 || bSize > 1000) {
+ b.Skip("skipping on race builder")
+ }
b.Run("WithoutXY", func(b *testing.B) {
runGCDExt(b, aSize, bSize, false)
})
diff --git a/libgo/go/math/big/int.go b/libgo/go/math/big/int.go
index f2a75d1cd50..1d8dabce12b 100644
--- a/libgo/go/math/big/int.go
+++ b/libgo/go/math/big/int.go
@@ -361,7 +361,8 @@ func (x *Int) Uint64() uint64 {
}
// SetString sets z to the value of s, interpreted in the given base,
-// and returns z and a boolean indicating success. If SetString fails,
+// and returns z and a boolean indicating success. The entire string
+// (not just a prefix) must be valid for success. If SetString fails,
// the value of z is undefined but the returned value is nil.
//
// The base argument must be 0 or a value between 2 and MaxBase. If the base
@@ -371,12 +372,11 @@ func (x *Int) Uint64() uint64 {
//
func (z *Int) SetString(s string, base int) (*Int, bool) {
r := strings.NewReader(s)
- _, _, err := z.scan(r, base)
- if err != nil {
+ if _, _, err := z.scan(r, base); err != nil {
return nil, false
}
- _, err = r.ReadByte()
- if err != io.EOF {
+ // entire string must have been consumed
+ if _, err := r.ReadByte(); err != io.EOF {
return nil, false
}
return z, true // err == io.EOF => scan consumed all of s
@@ -404,8 +404,11 @@ func (x *Int) BitLen() int {
// Exp sets z = x**y mod |m| (i.e. the sign of m is ignored), and returns z.
// If y <= 0, the result is 1 mod |m|; if m == nil or m == 0, z = x**y.
-// See Knuth, volume 2, section 4.6.3.
+//
+// Modular exponentation of inputs of a particular size is not a
+// cryptographically constant-time operation.
func (z *Int) Exp(x, y, m *Int) *Int {
+ // See Knuth, volume 2, section 4.6.3.
var yWords nat
if !y.neg {
yWords = y.abs
@@ -550,19 +553,6 @@ func (z *Int) binaryGCD(a, b *Int) *Int {
return z.Lsh(u, k)
}
-// ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
-// If x is prime, it returns true.
-// If x is not prime, it returns false with probability at least 1 - ¼ⁿ.
-//
-// It is not suitable for judging primes that an adversary may have crafted
-// to fool this test.
-func (x *Int) ProbablyPrime(n int) bool {
- if n <= 0 {
- panic("non-positive n for ProbablyPrime")
- }
- return !x.neg && x.abs.probablyPrime(n)
-}
-
// Rand sets z to a pseudo-random number in [0, n) and returns z.
func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int {
z.neg = false
@@ -577,6 +567,11 @@ func (z *Int) Rand(rnd *rand.Rand, n *Int) *Int {
// ModInverse sets z to the multiplicative inverse of g in the ring ℤ/nℤ
// and returns z. If g and n are not relatively prime, the result is undefined.
func (z *Int) ModInverse(g, n *Int) *Int {
+ if g.neg {
+ // GCD expects parameters a and b to be > 0.
+ var g2 Int
+ g = g2.Mod(g, n)
+ }
var d Int
d.GCD(z, nil, g, n)
// x and y are such that g*x + n*y = d. Since g and n are
@@ -932,3 +927,14 @@ func (z *Int) Not(x *Int) *Int {
z.neg = true // z cannot be zero if x is positive
return z
}
+
+// Sqrt sets z to ⌊√x⌋, the largest integer such that z² ≤ x, and returns z.
+// It panics if x is negative.
+func (z *Int) Sqrt(x *Int) *Int {
+ if x.neg {
+ panic("square root of negative number")
+ }
+ z.neg = false
+ z.abs = z.abs.sqrt(x.abs)
+ return z
+}
diff --git a/libgo/go/math/big/int_test.go b/libgo/go/math/big/int_test.go
index 45a3765d3ee..b8e0778ca32 100644
--- a/libgo/go/math/big/int_test.go
+++ b/libgo/go/math/big/int_test.go
@@ -9,6 +9,7 @@ import (
"encoding/hex"
"fmt"
"math/rand"
+ "strings"
"testing"
"testing/quick"
)
@@ -478,6 +479,18 @@ func TestQuoStepD6(t *testing.T) {
}
}
+func BenchmarkQuoRem(b *testing.B) {
+ x, _ := new(Int).SetString("153980389784927331788354528594524332344709972855165340650588877572729725338415474372475094155672066328274535240275856844648695200875763869073572078279316458648124537905600131008790701752441155668003033945258023841165089852359980273279085783159654751552359397986180318708491098942831252291841441726305535546071", 0)
+ y, _ := new(Int).SetString("7746362281539803897849273317883545285945243323447099728551653406505888775727297253384154743724750941556720663282745352402758568446486952008757638690735720782793164586481245379056001310087907017524411556680030339452580238411650898523599802732790857831596547515523593979861803187084910989428312522918414417263055355460715745539358014631136245887418412633787074173796862711588221766398229333338511838891484974940633857861775630560092874987828057333663969469797013996401149696897591265769095952887917296740109742927689053276850469671231961384715398038978492733178835452859452433234470997285516534065058887757272972533841547437247509415567206632827453524027585684464869520087576386907357207827931645864812453790560013100879070175244115566800303394525802384116508985235998027327908578315965475155235939798618031870849109894283125229184144172630553554607112725169432413343763989564437170644270643461665184965150423819594083121075825", 0)
+ q := new(Int)
+ r := new(Int)
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ q.QuoRem(y, x, r)
+ }
+}
+
var bitLenTests = []struct {
in string
out int
@@ -572,6 +585,19 @@ var expTests = []struct {
{"0xffffffffffffffff00000001", "0xffffffffffffffff00000001", "0xffffffffffffffff00000001", "0"},
{"0xffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffff00000001", "0"},
{"0xffffffffffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffffffffffff00000001", "0"},
+
+ {
+ "2",
+ "0xB08FFB20760FFED58FADA86DFEF71AD72AA0FA763219618FE022C197E54708BB1191C66470250FCE8879487507CEE41381CA4D932F81C2B3F1AB20B539D50DCD",
+ "0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73", // odd
+ "0x6AADD3E3E424D5B713FCAA8D8945B1E055166132038C57BBD2D51C833F0C5EA2007A2324CE514F8E8C2F008A2F36F44005A4039CB55830986F734C93DAF0EB4BAB54A6A8C7081864F44346E9BC6F0A3EB9F2C0146A00C6A05187D0C101E1F2D038CDB70CB5E9E05A2D188AB6CBB46286624D4415E7D4DBFAD3BCC6009D915C406EED38F468B940F41E6BEDC0430DD78E6F19A7DA3A27498A4181E24D738B0072D8F6ADB8C9809A5B033A09785814FD9919F6EF9F83EEA519BEC593855C4C10CBEEC582D4AE0792158823B0275E6AEC35242740468FAF3D5C60FD1E376362B6322F78B7ED0CA1C5BBCD2B49734A56C0967A1D01A100932C837B91D592CE08ABFF",
+ },
+ {
+ "2",
+ "0xB08FFB20760FFED58FADA86DFEF71AD72AA0FA763219618FE022C197E54708BB1191C66470250FCE8879487507CEE41381CA4D932F81C2B3F1AB20B539D50DCD",
+ "0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF72", // even
+ "0x7858794B5897C29F4ED0B40913416AB6C48588484E6A45F2ED3E26C941D878E923575AAC434EE2750E6439A6976F9BB4D64CEDB2A53CE8D04DD48CADCDF8E46F22747C6B81C6CEA86C0D873FBF7CEF262BAAC43A522BD7F32F3CDAC52B9337C77B3DCFB3DB3EDD80476331E82F4B1DF8EFDC1220C92656DFC9197BDC1877804E28D928A2A284B8DED506CBA304435C9D0133C246C98A7D890D1DE60CBC53A024361DA83A9B8775019083D22AC6820ED7C3C68F8E801DD4EC779EE0A05C6EB682EF9840D285B838369BA7E148FA27691D524FAEAF7C6ECE2A4B99A294B9F2C241857B5B90CC8BFFCFCF18DFA7D676131D5CD3855A5A3E8EBFA0CDFADB4D198B4A",
+ },
}
func TestExp(t *testing.T) {
@@ -614,6 +640,26 @@ func TestExp(t *testing.T) {
}
}
+func BenchmarkExp(b *testing.B) {
+ x, _ := new(Int).SetString("11001289118363089646017359372117963499250546375269047542777928006103246876688756735760905680604646624353196869572752623285140408755420374049317646428185270079555372763503115646054602867593662923894140940837479507194934267532831694565516466765025434902348314525627418515646588160955862839022051353653052947073136084780742729727874803457643848197499548297570026926927502505634297079527299004267769780768565695459945235586892627059178884998772989397505061206395455591503771677500931269477503508150175717121828518985901959919560700853226255420793148986854391552859459511723547532575574664944815966793196961286234040892865", 0)
+ y, _ := new(Int).SetString("0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF72", 0)
+ n, _ := new(Int).SetString("0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73", 0)
+ out := new(Int)
+ for i := 0; i < b.N; i++ {
+ out.Exp(x, y, n)
+ }
+}
+
+func BenchmarkExp2(b *testing.B) {
+ x, _ := new(Int).SetString("2", 0)
+ y, _ := new(Int).SetString("0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF72", 0)
+ n, _ := new(Int).SetString("0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73", 0)
+ out := new(Int)
+ for i := 0; i < b.N; i++ {
+ out.Exp(x, y, n)
+ }
+}
+
func checkGcd(aBytes, bBytes []byte) bool {
x := new(Int)
y := new(Int)
@@ -715,85 +761,6 @@ func TestGcd(t *testing.T) {
}
}
-var primes = []string{
- "2",
- "3",
- "5",
- "7",
- "11",
-
- "13756265695458089029",
- "13496181268022124907",
- "10953742525620032441",
- "17908251027575790097",
-
- // https://golang.org/issue/638
- "18699199384836356663",
-
- "98920366548084643601728869055592650835572950932266967461790948584315647051443",
- "94560208308847015747498523884063394671606671904944666360068158221458669711639",
-
- // http://primes.utm.edu/lists/small/small3.html
- "449417999055441493994709297093108513015373787049558499205492347871729927573118262811508386655998299074566974373711472560655026288668094291699357843464363003144674940345912431129144354948751003607115263071543163",
- "230975859993204150666423538988557839555560243929065415434980904258310530753006723857139742334640122533598517597674807096648905501653461687601339782814316124971547968912893214002992086353183070342498989426570593",
- "5521712099665906221540423207019333379125265462121169655563495403888449493493629943498064604536961775110765377745550377067893607246020694972959780839151452457728855382113555867743022746090187341871655890805971735385789993",
- "203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123",
-
- // ECC primes: http://tools.ietf.org/html/draft-ladd-safecurves-02
- "3618502788666131106986593281521497120414687020801267626233049500247285301239", // Curve1174: 2^251-9
- "57896044618658097711785492504343953926634992332820282019728792003956564819949", // Curve25519: 2^255-19
- "9850501549098619803069760025035903451269934817616361666987073351061430442874302652853566563721228910201656997576599", // E-382: 2^382-105
- "42307582002575910332922579714097346549017899709713998034217522897561970639123926132812109468141778230245837569601494931472367", // Curve41417: 2^414-17
- "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", // E-521: 2^521-1
-}
-
-var composites = []string{
- "0",
- "1",
- "21284175091214687912771199898307297748211672914763848041968395774954376176754",
- "6084766654921918907427900243509372380954290099172559290432744450051395395951",
- "84594350493221918389213352992032324280367711247940675652888030554255915464401",
- "82793403787388584738507275144194252681",
-}
-
-func TestProbablyPrime(t *testing.T) {
- nreps := 20
- if testing.Short() {
- nreps = 1
- }
- for i, s := range primes {
- p, _ := new(Int).SetString(s, 10)
- if !p.ProbablyPrime(nreps) {
- t.Errorf("#%d prime found to be non-prime (%s)", i, s)
- }
- }
-
- for i, s := range composites {
- c, _ := new(Int).SetString(s, 10)
- if c.ProbablyPrime(nreps) {
- t.Errorf("#%d composite found to be prime (%s)", i, s)
- }
- if testing.Short() {
- break
- }
- }
-
- // check that ProbablyPrime panics if n <= 0
- c := NewInt(11) // a prime
- for _, n := range []int{-1, 0, 1} {
- func() {
- defer func() {
- if n <= 0 && recover() == nil {
- t.Fatalf("expected panic from ProbablyPrime(%d)", n)
- }
- }()
- if !c.ProbablyPrime(n) {
- t.Fatalf("%v should be a prime", c)
- }
- }()
- }
-}
-
type intShiftTest struct {
in string
shift uint
@@ -1229,6 +1196,9 @@ func BenchmarkModSqrt224_3Mod4(b *testing.B) {
}
func BenchmarkModSqrt5430_Tonelli(b *testing.B) {
+ if isRaceBuilder {
+ b.Skip("skipping on race builder")
+ }
p := tri(5430)
x := new(Int).SetUint64(2)
for i := 0; i < b.N; i++ {
@@ -1238,6 +1208,9 @@ func BenchmarkModSqrt5430_Tonelli(b *testing.B) {
}
func BenchmarkModSqrt5430_3Mod4(b *testing.B) {
+ if isRaceBuilder {
+ b.Skip("skipping on race builder")
+ }
p := tri(5430)
x := new(Int).SetUint64(2)
for i := 0; i < b.N; i++ {
@@ -1303,6 +1276,7 @@ var modInverseTests = []struct {
}{
{"1234567", "458948883992"},
{"239487239847", "2410312426921032588552076022197566074856950548502459942654116941958108831682612228890093858261341614673227141477904012196503648957050582631942730706805009223062734745341073406696246014589361659774041027169249453200378729434170325843778659198143763193776859869524088940195577346119843545301547043747207749969763750084308926339295559968882457872412993810129130294592999947926365264059284647209730384947211681434464714438488520940127459844288859336526896320919633919"},
+ {"-10", "13"}, // issue #16984
}
func TestModInverse(t *testing.T) {
@@ -1480,3 +1454,44 @@ func TestIssue2607(t *testing.T) {
n := NewInt(10)
n.Rand(rand.New(rand.NewSource(9)), n)
}
+
+func TestSqrt(t *testing.T) {
+ root := 0
+ r := new(Int)
+ for i := 0; i < 10000; i++ {
+ if (root+1)*(root+1) <= i {
+ root++
+ }
+ n := NewInt(int64(i))
+ r.SetInt64(-2)
+ r.Sqrt(n)
+ if r.Cmp(NewInt(int64(root))) != 0 {
+ t.Errorf("Sqrt(%v) = %v, want %v", n, r, root)
+ }
+ }
+
+ for i := 0; i < 1000; i += 10 {
+ n, _ := new(Int).SetString("1"+strings.Repeat("0", i), 10)
+ r := new(Int).Sqrt(n)
+ root, _ := new(Int).SetString("1"+strings.Repeat("0", i/2), 10)
+ if r.Cmp(root) != 0 {
+ t.Errorf("Sqrt(1e%d) = %v, want 1e%d", i, r, i/2)
+ }
+ }
+
+ // Test aliasing.
+ r.SetInt64(100)
+ r.Sqrt(r)
+ if r.Int64() != 10 {
+ t.Errorf("Sqrt(100) = %v, want 10 (aliased output)", r.Int64())
+ }
+}
+
+func BenchmarkSqrt(b *testing.B) {
+ n, _ := new(Int).SetString("1"+strings.Repeat("0", 1001), 10)
+ b.ResetTimer()
+ t := new(Int)
+ for i := 0; i < b.N; i++ {
+ t.Sqrt(n)
+ }
+}
diff --git a/libgo/go/math/big/intconv.go b/libgo/go/math/big/intconv.go
index daf674aef4e..91a62ce04e1 100644
--- a/libgo/go/math/big/intconv.go
+++ b/libgo/go/math/big/intconv.go
@@ -52,6 +52,8 @@ func writeMultiple(s fmt.State, text string, count int) {
}
}
+var _ fmt.Formatter = intOne // *Int must implement fmt.Formatter
+
// Format implements fmt.Formatter. It accepts the formats
// 'b' (binary), 'o' (octal), 'd' (decimal), 'x' (lowercase
// hexadecimal), and 'X' (uppercase hexadecimal).
@@ -223,6 +225,8 @@ func (r byteReader) UnreadByte() error {
return r.UnreadRune()
}
+var _ fmt.Scanner = intOne // *Int must implement fmt.Scanner
+
// Scan is a support routine for fmt.Scanner; it sets z to the value of
// the scanned number. It accepts the formats 'b' (binary), 'o' (octal),
// 'd' (decimal), 'x' (lowercase hexadecimal), and 'X' (uppercase hexadecimal).
diff --git a/libgo/go/math/big/intmarsh.go b/libgo/go/math/big/intmarsh.go
index 4ff57b6464e..ee1e4143ed9 100644
--- a/libgo/go/math/big/intmarsh.go
+++ b/libgo/go/math/big/intmarsh.go
@@ -59,7 +59,7 @@ func (z *Int) UnmarshalText(text []byte) error {
return nil
}
-// The JSON marshallers are only here for API backward compatibility
+// The JSON marshalers are only here for API backward compatibility
// (programs that explicitly look for these two methods). JSON works
// fine with the TextMarshaler only.
@@ -70,5 +70,9 @@ func (x *Int) MarshalJSON() ([]byte, error) {
// UnmarshalJSON implements the json.Unmarshaler interface.
func (z *Int) UnmarshalJSON(text []byte) error {
+ // Ignore null, like in the main JSON package.
+ if string(text) == "null" {
+ return nil
+ }
return z.UnmarshalText(text)
}
diff --git a/libgo/go/math/big/nat.go b/libgo/go/math/big/nat.go
index 2e65d2a7ef7..9b1a626c4cf 100644
--- a/libgo/go/math/big/nat.go
+++ b/libgo/go/math/big/nat.go
@@ -542,16 +542,21 @@ func (z nat) div(z2, u, v nat) (q, r nat) {
return
}
-// getNat returns a nat of len n. The contents may not be zero.
-func getNat(n int) nat {
- var z nat
+// getNat returns a *nat of len n. The contents may not be zero.
+// The pool holds *nat to avoid allocation when converting to interface{}.
+func getNat(n int) *nat {
+ var z *nat
if v := natPool.Get(); v != nil {
- z = v.(nat)
+ z = v.(*nat)
}
- return z.make(n)
+ if z == nil {
+ z = new(nat)
+ }
+ *z = z.make(n)
+ return z
}
-func putNat(x nat) {
+func putNat(x *nat) {
natPool.Put(x)
}
@@ -575,7 +580,8 @@ func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
}
q = z.make(m + 1)
- qhatv := getNat(n + 1)
+ qhatvp := getNat(n + 1)
+ qhatv := *qhatvp
if alias(u, uIn) || alias(u, v) {
u = nil // u is an alias for uIn or v - cannot reuse
}
@@ -583,36 +589,40 @@ func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
u.clear() // TODO(gri) no need to clear if we allocated a new u
// D1.
- var v1 nat
+ var v1p *nat
shift := nlz(v[n-1])
if shift > 0 {
// do not modify v, it may be used by another goroutine simultaneously
- v1 = getNat(n)
+ v1p = getNat(n)
+ v1 := *v1p
shlVU(v1, v, shift)
v = v1
}
u[len(uIn)] = shlVU(u[0:len(uIn)], uIn, shift)
// D2.
+ vn1 := v[n-1]
for j := m; j >= 0; j-- {
// D3.
qhat := Word(_M)
- if u[j+n] != v[n-1] {
+ if ujn := u[j+n]; ujn != vn1 {
var rhat Word
- qhat, rhat = divWW(u[j+n], u[j+n-1], v[n-1])
+ qhat, rhat = divWW(ujn, u[j+n-1], vn1)
// x1 | x2 = q̂v_{n-2}
- x1, x2 := mulWW(qhat, v[n-2])
+ vn2 := v[n-2]
+ x1, x2 := mulWW(qhat, vn2)
// test if q̂v_{n-2} > br̂ + u_{j+n-2}
- for greaterThan(x1, x2, rhat, u[j+n-2]) {
+ ujn2 := u[j+n-2]
+ for greaterThan(x1, x2, rhat, ujn2) {
qhat--
prevRhat := rhat
- rhat += v[n-1]
+ rhat += vn1
// v[n-1] >= 0, so this tests for overflow.
if rhat < prevRhat {
break
}
- x1, x2 = mulWW(qhat, v[n-2])
+ x1, x2 = mulWW(qhat, vn2)
}
}
@@ -628,10 +638,10 @@ func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
q[j] = qhat
}
- if v1 != nil {
- putNat(v1)
+ if v1p != nil {
+ putNat(v1p)
}
- putNat(qhatv)
+ putNat(qhatvp)
q = q.norm()
shrVU(u, u, shift)
@@ -650,14 +660,14 @@ func (x nat) bitLen() int {
const deBruijn32 = 0x077CB531
-var deBruijn32Lookup = []byte{
+var deBruijn32Lookup = [...]byte{
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9,
}
const deBruijn64 = 0x03f79d71b4ca8b09
-var deBruijn64Lookup = []byte{
+var deBruijn64Lookup = [...]byte{
0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
@@ -950,7 +960,7 @@ func (z nat) expNN(x, y, m nat) nat {
// (x^2...x^15) but then reduces the number of multiply-reduces by a
// third. Even for a 32-bit exponent, this reduces the number of
// operations. Uses Montgomery method for odd moduli.
- if len(x) > 1 && len(y) > 1 && len(m) > 0 {
+ if x.cmp(natOne) > 0 && len(y) > 1 && len(m) > 0 {
if m[0]&1 == 1 {
return z.expNNMontgomery(x, y, m)
}
@@ -1169,96 +1179,6 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
return zz.norm()
}
-// probablyPrime performs n Miller-Rabin tests to check whether x is prime.
-// If x is prime, it returns true.
-// If x is not prime, it returns false with probability at least 1 - ¼ⁿ.
-//
-// It is not suitable for judging primes that an adversary may have crafted
-// to fool this test.
-func (n nat) probablyPrime(reps int) bool {
- if len(n) == 0 {
- return false
- }
-
- if len(n) == 1 {
- if n[0] < 2 {
- return false
- }
-
- if n[0]%2 == 0 {
- return n[0] == 2
- }
-
- // We have to exclude these cases because we reject all
- // multiples of these numbers below.
- switch n[0] {
- case 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53:
- return true
- }
- }
-
- if n[0]&1 == 0 {
- return false // n is even
- }
-
- const primesProduct32 = 0xC0CFD797 // Π {p ∈ primes, 2 < p <= 29}
- const primesProduct64 = 0xE221F97C30E94E1D // Π {p ∈ primes, 2 < p <= 53}
-
- var r Word
- switch _W {
- case 32:
- r = n.modW(primesProduct32)
- case 64:
- r = n.modW(primesProduct64 & _M)
- default:
- panic("Unknown word size")
- }
-
- if r%3 == 0 || r%5 == 0 || r%7 == 0 || r%11 == 0 ||
- r%13 == 0 || r%17 == 0 || r%19 == 0 || r%23 == 0 || r%29 == 0 {
- return false
- }
-
- if _W == 64 && (r%31 == 0 || r%37 == 0 || r%41 == 0 ||
- r%43 == 0 || r%47 == 0 || r%53 == 0) {
- return false
- }
-
- nm1 := nat(nil).sub(n, natOne)
- // determine q, k such that nm1 = q << k
- k := nm1.trailingZeroBits()
- q := nat(nil).shr(nm1, k)
-
- nm3 := nat(nil).sub(nm1, natTwo)
- rand := rand.New(rand.NewSource(int64(n[0])))
-
- var x, y, quotient nat
- nm3Len := nm3.bitLen()
-
-NextRandom:
- for i := 0; i < reps; i++ {
- x = x.random(rand, nm3, nm3Len)
- x = x.add(x, natTwo)
- y = y.expNN(x, q, n)
- if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 {
- continue
- }
- for j := uint(1); j < k; j++ {
- y = y.mul(y, y)
- quotient, y = quotient.div(y, y, n)
- if y.cmp(nm1) == 0 {
- continue NextRandom
- }
- if y.cmp(natOne) == 0 {
- return false
- }
- }
- return false
- }
-
- return true
-}
-
// bytes writes the value of z into buf using big-endian encoding.
// len(buf) must be >= len(z)*_S. The value of z is encoded in the
// slice buf[i:]. The number i of unused bytes at the beginning of
@@ -1303,3 +1223,37 @@ func (z nat) setBytes(buf []byte) nat {
return z.norm()
}
+
+// sqrt sets z = ⌊√x⌋
+func (z nat) sqrt(x nat) nat {
+ if x.cmp(natOne) <= 0 {
+ return z.set(x)
+ }
+ if alias(z, x) {
+ z = nil
+ }
+
+ // Start with value known to be too large and repeat "z = ⌊(z + ⌊x/z⌋)/2⌋" until it stops getting smaller.
+ // See Brent and Zimmermann, Modern Computer Arithmetic, Algorithm 1.13 (SqrtInt).
+ // https://members.loria.fr/PZimmermann/mca/pub226.html
+ // If x is one less than a perfect square, the sequence oscillates between the correct z and z+1;
+ // otherwise it converges to the correct z and stays there.
+ var z1, z2 nat
+ z1 = z
+ z1 = z1.setUint64(1)
+ z1 = z1.shl(z1, uint(x.bitLen()/2+1)) // must be ≥ √x
+ for n := 0; ; n++ {
+ z2, _ = z2.div(nil, x, z1)
+ z2 = z2.add(z2, z1)
+ z2 = z2.shr(z2, 1)
+ if z2.cmp(z1) >= 0 {
+ // z1 is answer.
+ // Figure out whether z1 or z2 is currently aliased to z by looking at loop count.
+ if n&1 == 0 {
+ return z1
+ }
+ return z.set(z1)
+ }
+ z1, z2 = z2, z1
+ }
+}
diff --git a/libgo/go/math/big/natconv_test.go b/libgo/go/math/big/natconv_test.go
index 79901d18804..bdb60e68e0a 100644
--- a/libgo/go/math/big/natconv_test.go
+++ b/libgo/go/math/big/natconv_test.go
@@ -278,6 +278,9 @@ func BenchmarkScan(b *testing.B) {
const x = 10
for _, base := range []int{2, 8, 10, 16} {
for _, y := range []Word{10, 100, 1000, 10000, 100000} {
+ if isRaceBuilder && y > 1000 {
+ continue
+ }
b.Run(fmt.Sprintf("%d/Base%d", y, base), func(b *testing.B) {
b.StopTimer()
var z nat
@@ -301,6 +304,9 @@ func BenchmarkString(b *testing.B) {
const x = 10
for _, base := range []int{2, 8, 10, 16} {
for _, y := range []Word{10, 100, 1000, 10000, 100000} {
+ if isRaceBuilder && y > 1000 {
+ continue
+ }
b.Run(fmt.Sprintf("%d/Base%d", y, base), func(b *testing.B) {
b.StopTimer()
var z nat
diff --git a/libgo/go/math/big/prime.go b/libgo/go/math/big/prime.go
new file mode 100644
index 00000000000..3e9690e55e6
--- /dev/null
+++ b/libgo/go/math/big/prime.go
@@ -0,0 +1,320 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import "math/rand"
+
+// ProbablyPrime reports whether x is probably prime,
+// applying the Miller-Rabin test with n pseudorandomly chosen bases
+// as well as a Baillie-PSW test.
+//
+// If x is prime, ProbablyPrime returns true.
+// If x is chosen randomly and not prime, ProbablyPrime probably returns false.
+// The probability of returning true for a randomly chosen non-prime is at most ¼ⁿ.
+//
+// ProbablyPrime is 100% accurate for inputs less than 2⁶⁴.
+// See Menezes et al., Handbook of Applied Cryptography, 1997, pp. 145-149,
+// and FIPS 186-4 Appendix F for further discussion of the error probabilities.
+//
+// ProbablyPrime is not suitable for judging primes that an adversary may
+// have crafted to fool the test.
+//
+// As of Go 1.8, ProbablyPrime(0) is allowed and applies only a Baillie-PSW test.
+// Before Go 1.8, ProbablyPrime applied only the Miller-Rabin tests, and ProbablyPrime(0) panicked.
+func (x *Int) ProbablyPrime(n int) bool {
+ // Note regarding the doc comment above:
+ // It would be more precise to say that the Baillie-PSW test uses the
+ // extra strong Lucas test as its Lucas test, but since no one knows
+ // how to tell any of the Lucas tests apart inside a Baillie-PSW test
+ // (they all work equally well empirically), that detail need not be
+ // documented or implicitly guaranteed.
+ // The comment does avoid saying "the" Baillie-PSW test
+ // because of this general ambiguity.
+
+ if n < 0 {
+ panic("negative n for ProbablyPrime")
+ }
+ if x.neg || len(x.abs) == 0 {
+ return false
+ }
+
+ // primeBitMask records the primes < 64.
+ const primeBitMask uint64 = 1<<2 | 1<<3 | 1<<5 | 1<<7 |
+ 1<<11 | 1<<13 | 1<<17 | 1<<19 | 1<<23 | 1<<29 | 1<<31 |
+ 1<<37 | 1<<41 | 1<<43 | 1<<47 | 1<<53 | 1<<59 | 1<<61
+
+ w := x.abs[0]
+ if len(x.abs) == 1 && w < 64 {
+ return primeBitMask&(1<<w) != 0
+ }
+
+ if w&1 == 0 {
+ return false // n is even
+ }
+
+ const primesA = 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 37
+ const primesB = 29 * 31 * 41 * 43 * 47 * 53
+
+ var rA, rB uint32
+ switch _W {
+ case 32:
+ rA = uint32(x.abs.modW(primesA))
+ rB = uint32(x.abs.modW(primesB))
+ case 64:
+ r := x.abs.modW((primesA * primesB) & _M)
+ rA = uint32(r % primesA)
+ rB = uint32(r % primesB)
+ default:
+ panic("math/big: invalid word size")
+ }
+
+ if rA%3 == 0 || rA%5 == 0 || rA%7 == 0 || rA%11 == 0 || rA%13 == 0 || rA%17 == 0 || rA%19 == 0 || rA%23 == 0 || rA%37 == 0 ||
+ rB%29 == 0 || rB%31 == 0 || rB%41 == 0 || rB%43 == 0 || rB%47 == 0 || rB%53 == 0 {
+ return false
+ }
+
+ return x.abs.probablyPrimeMillerRabin(n+1, true) && x.abs.probablyPrimeLucas()
+}
+
+// probablyPrimeMillerRabin reports whether n passes reps rounds of the
+// Miller-Rabin primality test, using pseudo-randomly chosen bases.
+// If force2 is true, one of the rounds is forced to use base 2.
+// See Handbook of Applied Cryptography, p. 139, Algorithm 4.24.
+// The number n is known to be non-zero.
+func (n nat) probablyPrimeMillerRabin(reps int, force2 bool) bool {
+ nm1 := nat(nil).sub(n, natOne)
+ // determine q, k such that nm1 = q << k
+ k := nm1.trailingZeroBits()
+ q := nat(nil).shr(nm1, k)
+
+ nm3 := nat(nil).sub(nm1, natTwo)
+ rand := rand.New(rand.NewSource(int64(n[0])))
+
+ var x, y, quotient nat
+ nm3Len := nm3.bitLen()
+
+NextRandom:
+ for i := 0; i < reps; i++ {
+ if i == reps-1 && force2 {
+ x = x.set(natTwo)
+ } else {
+ x = x.random(rand, nm3, nm3Len)
+ x = x.add(x, natTwo)
+ }
+ y = y.expNN(x, q, n)
+ if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 {
+ continue
+ }
+ for j := uint(1); j < k; j++ {
+ y = y.mul(y, y)
+ quotient, y = quotient.div(y, y, n)
+ if y.cmp(nm1) == 0 {
+ continue NextRandom
+ }
+ if y.cmp(natOne) == 0 {
+ return false
+ }
+ }
+ return false
+ }
+
+ return true
+}
+
+// probablyPrimeLucas reports whether n passes the "almost extra strong" Lucas probable prime test,
+// using Baillie-OEIS parameter selection. This corresponds to "AESLPSP" on Jacobsen's tables (link below).
+// The combination of this test and a Miller-Rabin/Fermat test with base 2 gives a Baillie-PSW test.
+//
+// References:
+//
+// Baillie and Wagstaff, "Lucas Pseudoprimes", Mathematics of Computation 35(152),
+// October 1980, pp. 1391-1417, especially page 1401.
+// http://www.ams.org/journals/mcom/1980-35-152/S0025-5718-1980-0583518-6/S0025-5718-1980-0583518-6.pdf
+//
+// Grantham, "Frobenius Pseudoprimes", Mathematics of Computation 70(234),
+// March 2000, pp. 873-891.
+// http://www.ams.org/journals/mcom/2001-70-234/S0025-5718-00-01197-2/S0025-5718-00-01197-2.pdf
+//
+// Baillie, "Extra strong Lucas pseudoprimes", OEIS A217719, https://oeis.org/A217719.
+//
+// Jacobsen, "Pseudoprime Statistics, Tables, and Data", http://ntheory.org/pseudoprimes.html.
+//
+// Nicely, "The Baillie-PSW Primality Test", http://www.trnicely.net/misc/bpsw.html.
+// (Note that Nicely's definition of the "extra strong" test gives the wrong Jacobi condition,
+// as pointed out by Jacobsen.)
+//
+// Crandall and Pomerance, Prime Numbers: A Computational Perspective, 2nd ed.
+// Springer, 2005.
+func (n nat) probablyPrimeLucas() bool {
+ // Discard 0, 1.
+ if len(n) == 0 || n.cmp(natOne) == 0 {
+ return false
+ }
+ // Two is the only even prime.
+ // Already checked by caller, but here to allow testing in isolation.
+ if n[0]&1 == 0 {
+ return n.cmp(natTwo) == 0
+ }
+
+ // Baillie-OEIS "method C" for choosing D, P, Q,
+ // as in https://oeis.org/A217719/a217719.txt:
+ // try increasing P ≥ 3 such that D = P² - 4 (so Q = 1)
+ // until Jacobi(D, n) = -1.
+ // The search is expected to succeed for non-square n after just a few trials.
+ // After more than expected failures, check whether n is square
+ // (which would cause Jacobi(D, n) = 1 for all D not dividing n).
+ p := Word(3)
+ d := nat{1}
+ t1 := nat(nil) // temp
+ intD := &Int{abs: d}
+ intN := &Int{abs: n}
+ for ; ; p++ {
+ if p > 10000 {
+ // This is widely believed to be impossible.
+ // If we get a report, we'll want the exact number n.
+ panic("math/big: internal error: cannot find (D/n) = -1 for " + intN.String())
+ }
+ d[0] = p*p - 4
+ j := Jacobi(intD, intN)
+ if j == -1 {
+ break
+ }
+ if j == 0 {
+ // d = p²-4 = (p-2)(p+2).
+ // If (d/n) == 0 then d shares a prime factor with n.
+ // Since the loop proceeds in increasing p and starts with p-2==1,
+ // the shared prime factor must be p+2.
+ // If p+2 == n, then n is prime; otherwise p+2 is a proper factor of n.
+ return len(n) == 1 && n[0] == p+2
+ }
+ if p == 40 {
+ // We'll never find (d/n) = -1 if n is a square.
+ // If n is a non-square we expect to find a d in just a few attempts on average.
+ // After 40 attempts, take a moment to check if n is indeed a square.
+ t1 = t1.sqrt(n)
+ t1 = t1.mul(t1, t1)
+ if t1.cmp(n) == 0 {
+ return false
+ }
+ }
+ }
+
+ // Grantham definition of "extra strong Lucas pseudoprime", after Thm 2.3 on p. 876
+ // (D, P, Q above have become Δ, b, 1):
+ //
+ // Let U_n = U_n(b, 1), V_n = V_n(b, 1), and Δ = b²-4.
+ // An extra strong Lucas pseudoprime to base b is a composite n = 2^r s + Jacobi(Δ, n),
+ // where s is odd and gcd(n, 2*Δ) = 1, such that either (i) U_s ≡ 0 mod n and V_s ≡ ±2 mod n,
+ // or (ii) V_{2^t s} ≡ 0 mod n for some 0 ≤ t < r-1.
+ //
+ // We know gcd(n, Δ) = 1 or else we'd have found Jacobi(d, n) == 0 above.
+ // We know gcd(n, 2) = 1 because n is odd.
+ //
+ // Arrange s = (n - Jacobi(Δ, n)) / 2^r = (n+1) / 2^r.
+ s := nat(nil).add(n, natOne)
+ r := int(s.trailingZeroBits())
+ s = s.shr(s, uint(r))
+ nm2 := nat(nil).sub(n, natTwo) // n-2
+
+ // We apply the "almost extra strong" test, which checks the above conditions
+ // except for U_s ≡ 0 mod n, which allows us to avoid computing any U_k values.
+ // Jacobsen points out that maybe we should just do the full extra strong test:
+ // "It is also possible to recover U_n using Crandall and Pomerance equation 3.13:
+ // U_n = D^-1 (2V_{n+1} - PV_n) allowing us to run the full extra-strong test
+ // at the cost of a single modular inversion. This computation is easy and fast in GMP,
+ // so we can get the full extra-strong test at essentially the same performance as the
+ // almost extra strong test."
+
+ // Compute Lucas sequence V_s(b, 1), where:
+ //
+ // V(0) = 2
+ // V(1) = P
+ // V(k) = P V(k-1) - Q V(k-2).
+ //
+ // (Remember that due to method C above, P = b, Q = 1.)
+ //
+ // In general V(k) = α^k + β^k, where α and β are roots of x² - Px + Q.
+ // Crandall and Pomerance (p.147) observe that for 0 ≤ j ≤ k,
+ //
+ // V(j+k) = V(j)V(k) - V(k-j).
+ //
+ // So in particular, to quickly double the subscript:
+ //
+ // V(2k) = V(k)² - 2
+ // V(2k+1) = V(k) V(k+1) - P
+ //
+ // We can therefore start with k=0 and build up to k=s in log₂(s) steps.
+ natP := nat(nil).setWord(p)
+ vk := nat(nil).setWord(2)
+ vk1 := nat(nil).setWord(p)
+ t2 := nat(nil) // temp
+ for i := int(s.bitLen()); i >= 0; i-- {
+ if s.bit(uint(i)) != 0 {
+ // k' = 2k+1
+ // V(k') = V(2k+1) = V(k) V(k+1) - P.
+ t1 = t1.mul(vk, vk1)
+ t1 = t1.add(t1, n)
+ t1 = t1.sub(t1, natP)
+ t2, vk = t2.div(vk, t1, n)
+ // V(k'+1) = V(2k+2) = V(k+1)² - 2.
+ t1 = t1.mul(vk1, vk1)
+ t1 = t1.add(t1, nm2)
+ t2, vk1 = t2.div(vk1, t1, n)
+ } else {
+ // k' = 2k
+ // V(k'+1) = V(2k+1) = V(k) V(k+1) - P.
+ t1 = t1.mul(vk, vk1)
+ t1 = t1.add(t1, n)
+ t1 = t1.sub(t1, natP)
+ t2, vk1 = t2.div(vk1, t1, n)
+ // V(k') = V(2k) = V(k)² - 2
+ t1 = t1.mul(vk, vk)
+ t1 = t1.add(t1, nm2)
+ t2, vk = t2.div(vk, t1, n)
+ }
+ }
+
+ // Now k=s, so vk = V(s). Check V(s) ≡ ±2 (mod n).
+ if vk.cmp(natTwo) == 0 || vk.cmp(nm2) == 0 {
+ // Check U(s) ≡ 0.
+ // As suggested by Jacobsen, apply Crandall and Pomerance equation 3.13:
+ //
+ // U(k) = D⁻¹ (2 V(k+1) - P V(k))
+ //
+ // Since we are checking for U(k) == 0 it suffices to check 2 V(k+1) == P V(k) mod n,
+ // or P V(k) - 2 V(k+1) == 0 mod n.
+ t1 := t1.mul(vk, natP)
+ t2 := t2.shl(vk1, 1)
+ if t1.cmp(t2) < 0 {
+ t1, t2 = t2, t1
+ }
+ t1 = t1.sub(t1, t2)
+ t3 := vk1 // steal vk1, no longer needed below
+ vk1 = nil
+ _ = vk1
+ t2, t3 = t2.div(t3, t1, n)
+ if len(t3) == 0 {
+ return true
+ }
+ }
+
+ // Check V(2^t s) ≡ 0 mod n for some 0 ≤ t < r-1.
+ for t := 0; t < r-1; t++ {
+ if len(vk) == 0 { // vk == 0
+ return true
+ }
+ // Optimization: V(k) = 2 is a fixed point for V(k') = V(k)² - 2,
+ // so if V(k) = 2, we can stop: we will never find a future V(k) == 0.
+ if len(vk) == 1 && vk[0] == 2 { // vk == 2
+ return false
+ }
+ // k' = 2k
+ // V(k') = V(2k) = V(k)² - 2
+ t1 = t1.mul(vk, vk)
+ t1 = t1.sub(t1, natTwo)
+ t2, vk = t2.div(vk, t1, n)
+ }
+ return false
+}
diff --git a/libgo/go/math/big/prime_test.go b/libgo/go/math/big/prime_test.go
new file mode 100644
index 00000000000..a2d3d18f8f4
--- /dev/null
+++ b/libgo/go/math/big/prime_test.go
@@ -0,0 +1,214 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package big
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+ "unicode"
+)
+
+var primes = []string{
+ "2",
+ "3",
+ "5",
+ "7",
+ "11",
+
+ "13756265695458089029",
+ "13496181268022124907",
+ "10953742525620032441",
+ "17908251027575790097",
+
+ // https://golang.org/issue/638
+ "18699199384836356663",
+
+ "98920366548084643601728869055592650835572950932266967461790948584315647051443",
+ "94560208308847015747498523884063394671606671904944666360068158221458669711639",
+
+ // http://primes.utm.edu/lists/small/small3.html
+ "449417999055441493994709297093108513015373787049558499205492347871729927573118262811508386655998299074566974373711472560655026288668094291699357843464363003144674940345912431129144354948751003607115263071543163",
+ "230975859993204150666423538988557839555560243929065415434980904258310530753006723857139742334640122533598517597674807096648905501653461687601339782814316124971547968912893214002992086353183070342498989426570593",
+ "5521712099665906221540423207019333379125265462121169655563495403888449493493629943498064604536961775110765377745550377067893607246020694972959780839151452457728855382113555867743022746090187341871655890805971735385789993",
+ "203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123",
+
+ // ECC primes: http://tools.ietf.org/html/draft-ladd-safecurves-02
+ "3618502788666131106986593281521497120414687020801267626233049500247285301239", // Curve1174: 2^251-9
+ "57896044618658097711785492504343953926634992332820282019728792003956564819949", // Curve25519: 2^255-19
+ "9850501549098619803069760025035903451269934817616361666987073351061430442874302652853566563721228910201656997576599", // E-382: 2^382-105
+ "42307582002575910332922579714097346549017899709713998034217522897561970639123926132812109468141778230245837569601494931472367", // Curve41417: 2^414-17
+ "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", // E-521: 2^521-1
+}
+
+var composites = []string{
+ "0",
+ "1",
+ "21284175091214687912771199898307297748211672914763848041968395774954376176754",
+ "6084766654921918907427900243509372380954290099172559290432744450051395395951",
+ "84594350493221918389213352992032324280367711247940675652888030554255915464401",
+ "82793403787388584738507275144194252681",
+
+ // Arnault, "Rabin-Miller Primality Test: Composite Numbers Which Pass It",
+ // Mathematics of Computation, 64(209) (January 1995), pp. 335-361.
+ "1195068768795265792518361315725116351898245581", // strong pseudoprime to prime bases 2 through 29
+ // strong pseudoprime to all prime bases up to 200
+ `
+ 80383745745363949125707961434194210813883768828755814583748891752229
+ 74273765333652186502336163960045457915042023603208766569966760987284
+ 0439654082329287387918508691668573282677617710293896977394701670823
+ 0428687109997439976544144845341155872450633409279022275296229414984
+ 2306881685404326457534018329786111298960644845216191652872597534901`,
+
+ // Extra-strong Lucas pseudoprimes. https://oeis.org/A217719
+ "989",
+ "3239",
+ "5777",
+ "10877",
+ "27971",
+ "29681",
+ "30739",
+ "31631",
+ "39059",
+ "72389",
+ "73919",
+ "75077",
+ "100127",
+ "113573",
+ "125249",
+ "137549",
+ "137801",
+ "153931",
+ "155819",
+ "161027",
+ "162133",
+ "189419",
+ "218321",
+ "231703",
+ "249331",
+ "370229",
+ "429479",
+ "430127",
+ "459191",
+ "473891",
+ "480689",
+ "600059",
+ "621781",
+ "632249",
+ "635627",
+
+ "3673744903",
+ "3281593591",
+ "2385076987",
+ "2738053141",
+ "2009621503",
+ "1502682721",
+ "255866131",
+ "117987841",
+ "587861",
+
+ "6368689",
+ "8725753",
+ "80579735209",
+ "105919633",
+}
+
+func cutSpace(r rune) rune {
+ if unicode.IsSpace(r) {
+ return -1
+ }
+ return r
+}
+
+func TestProbablyPrime(t *testing.T) {
+ nreps := 20
+ if testing.Short() {
+ nreps = 3
+ }
+ for i, s := range primes {
+ p, _ := new(Int).SetString(s, 10)
+ if !p.ProbablyPrime(nreps) || !p.ProbablyPrime(1) || !p.ProbablyPrime(0) {
+ t.Errorf("#%d prime found to be non-prime (%s)", i, s)
+ }
+ }
+
+ for i, s := range composites {
+ s = strings.Map(cutSpace, s)
+ c, _ := new(Int).SetString(s, 10)
+ if c.ProbablyPrime(nreps) || c.ProbablyPrime(1) || c.ProbablyPrime(0) {
+ t.Errorf("#%d composite found to be prime (%s)", i, s)
+ }
+ }
+
+ // check that ProbablyPrime panics if n <= 0
+ c := NewInt(11) // a prime
+ for _, n := range []int{-1, 0, 1} {
+ func() {
+ defer func() {
+ if n < 0 && recover() == nil {
+ t.Fatalf("expected panic from ProbablyPrime(%d)", n)
+ }
+ }()
+ if !c.ProbablyPrime(n) {
+ t.Fatalf("%v should be a prime", c)
+ }
+ }()
+ }
+}
+
+func BenchmarkProbablyPrime(b *testing.B) {
+ p, _ := new(Int).SetString("203956878356401977405765866929034577280193993314348263094772646453283062722701277632936616063144088173312372882677123879538709400158306567338328279154499698366071906766440037074217117805690872792848149112022286332144876183376326512083574821647933992961249917319836219304274280243803104015000563790123", 10)
+ for _, n := range []int{0, 1, 5, 10, 20} {
+ b.Run(fmt.Sprintf("n=%d", n), func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ p.ProbablyPrime(n)
+ }
+ })
+ }
+
+ b.Run("Lucas", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ p.abs.probablyPrimeLucas()
+ }
+ })
+ b.Run("MillerRabinBase2", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ p.abs.probablyPrimeMillerRabin(1, true)
+ }
+ })
+}
+
+func TestMillerRabinPseudoprimes(t *testing.T) {
+ testPseudoprimes(t, "probablyPrimeMillerRabin",
+ func(n nat) bool { return n.probablyPrimeMillerRabin(1, true) && !n.probablyPrimeLucas() },
+ // https://oeis.org/A001262
+ []int{2047, 3277, 4033, 4681, 8321, 15841, 29341, 42799, 49141, 52633, 65281, 74665, 80581, 85489, 88357, 90751})
+}
+
+func TestLucasPseudoprimes(t *testing.T) {
+ testPseudoprimes(t, "probablyPrimeLucas",
+ func(n nat) bool { return n.probablyPrimeLucas() && !n.probablyPrimeMillerRabin(1, true) },
+ // https://oeis.org/A217719
+ []int{989, 3239, 5777, 10877, 27971, 29681, 30739, 31631, 39059, 72389, 73919, 75077})
+}
+
+func testPseudoprimes(t *testing.T, name string, cond func(nat) bool, want []int) {
+ n := nat{1}
+ for i := 3; i < 100000; i += 2 {
+ n[0] = Word(i)
+ pseudo := cond(n)
+ if pseudo && (len(want) == 0 || i != want[0]) {
+ t.Errorf("%s(%v, base=2) = %v, want false", name, i)
+ } else if !pseudo && len(want) >= 1 && i == want[0] {
+ t.Errorf("%s(%v, base=2) = false, want true", name, i)
+ }
+ if len(want) > 0 && i == want[0] {
+ want = want[1:]
+ }
+ }
+ if len(want) > 0 {
+ t.Fatalf("forgot to test %v", want)
+ }
+}
diff --git a/libgo/go/math/big/rat_test.go b/libgo/go/math/big/rat_test.go
index 3a06fca3c34..afda68658f7 100644
--- a/libgo/go/math/big/rat_test.go
+++ b/libgo/go/math/big/rat_test.go
@@ -382,9 +382,9 @@ func TestFloat32Distribution(t *testing.T) {
9,
11,
}
- var winc, einc = uint64(1), 1 // soak test (~1.5s on x86-64)
- if testing.Short() {
- winc, einc = 5, 15 // quick test (~60ms on x86-64)
+ var winc, einc = uint64(5), 15 // quick test (~60ms on x86-64)
+ if *long {
+ winc, einc = uint64(1), 1 // soak test (~1.5s on x86-64)
}
for _, sign := range "+-" {
@@ -430,9 +430,9 @@ func TestFloat64Distribution(t *testing.T) {
9,
11,
}
- var winc, einc = uint64(1), 1 // soak test (~75s on x86-64)
- if testing.Short() {
- winc, einc = 10, 500 // quick test (~12ms on x86-64)
+ var winc, einc = uint64(10), 500 // quick test (~12ms on x86-64)
+ if *long {
+ winc, einc = uint64(1), 1 // soak test (~75s on x86-64)
}
for _, sign := range "+-" {
diff --git a/libgo/go/math/big/ratconv.go b/libgo/go/math/big/ratconv.go
index ef2b6750d0c..a6a401c8576 100644
--- a/libgo/go/math/big/ratconv.go
+++ b/libgo/go/math/big/ratconv.go
@@ -18,6 +18,9 @@ func ratTok(ch rune) bool {
return strings.ContainsRune("+-/0123456789.eE", ch)
}
+var ratZero Rat
+var _ fmt.Scanner = &ratZero // *Rat must implement fmt.Scanner
+
// Scan is a support routine for fmt.Scanner. It accepts the formats
// 'e', 'E', 'f', 'F', 'g', 'G', and 'v'. All formats are equivalent.
func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
@@ -36,8 +39,9 @@ func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
// SetString sets z to the value of s and returns z and a boolean indicating
// success. s can be given as a fraction "a/b" or as a floating-point number
-// optionally followed by an exponent. If the operation failed, the value of
-// z is undefined but the returned value is nil.
+// optionally followed by an exponent. The entire string (not just a prefix)
+// must be valid for success. If the operation failed, the value of z is un-
+// defined but the returned value is nil.
func (z *Rat) SetString(s string) (*Rat, bool) {
if len(s) == 0 {
return nil, false
@@ -49,9 +53,13 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
if _, ok := z.a.SetString(s[:sep], 0); !ok {
return nil, false
}
- s = s[sep+1:]
+ r := strings.NewReader(s[sep+1:])
var err error
- if z.b.abs, _, _, err = z.b.abs.scan(strings.NewReader(s), 0, false); err != nil {
+ if z.b.abs, _, _, err = z.b.abs.scan(r, 0, false); err != nil {
+ return nil, false
+ }
+ // entire string must have been consumed
+ if _, err = r.ReadByte(); err != io.EOF {
return nil, false
}
if len(z.b.abs) == 0 {
diff --git a/libgo/go/math/big/ratconv_test.go b/libgo/go/math/big/ratconv_test.go
index 35ad6ccea77..56ac8d7aa3a 100644
--- a/libgo/go/math/big/ratconv_test.go
+++ b/libgo/go/math/big/ratconv_test.go
@@ -50,6 +50,10 @@ var setStringTests = []StringTest{
{"204211327800791583.81095", "4084226556015831676219/20000", true},
{"0e9999999999", "0", true}, // issue #16176
{in: "1/0"},
+ {in: "4/3/2"}, // issue 17001
+ {in: "4/3/"},
+ {in: "4/3."},
+ {in: "4/"},
}
// These are not supported by fmt.Fscanf.
@@ -59,6 +63,7 @@ var setStringTests2 = []StringTest{
{"-010.", "-10", true},
{"0x10/0x20", "1/2", true},
{"0b1000/3", "8/3", true},
+ {in: "4/3x"},
// TODO(gri) add more tests
}
@@ -139,7 +144,7 @@ func TestFloatString(t *testing.T) {
}
// Test inputs to Rat.SetString. The prefix "long:" causes the test
-// to be skipped in --test.short mode. (The threshold is about 500us.)
+// to be skipped except in -long mode. (The threshold is about 500us.)
var float64inputs = []string{
// Constants plundered from strconv/testfp.txt.
@@ -345,7 +350,7 @@ func isFinite(f float64) bool {
func TestFloat32SpecialCases(t *testing.T) {
for _, input := range float64inputs {
if strings.HasPrefix(input, "long:") {
- if testing.Short() {
+ if !*long {
continue
}
input = input[len("long:"):]
@@ -401,7 +406,7 @@ func TestFloat32SpecialCases(t *testing.T) {
func TestFloat64SpecialCases(t *testing.T) {
for _, input := range float64inputs {
if strings.HasPrefix(input, "long:") {
- if testing.Short() {
+ if !*long {
continue
}
input = input[len("long:"):]
diff --git a/libgo/go/math/cmplx/cmath_test.go b/libgo/go/math/cmplx/cmath_test.go
index d904be880d8..7a5c485a310 100644
--- a/libgo/go/math/cmplx/cmath_test.go
+++ b/libgo/go/math/cmplx/cmath_test.go
@@ -759,6 +759,14 @@ func TestTanh(t *testing.T) {
}
}
+// See issue 17577
+func TestInfiniteLoopIntanSeries(t *testing.T) {
+ want := Inf()
+ if got := Cot(0); got != want {
+ t.Errorf("Cot(0): got %g, want %g", got, want)
+ }
+}
+
func BenchmarkAbs(b *testing.B) {
for i := 0; i < b.N; i++ {
Abs(complex(2.5, 3.5))
diff --git a/libgo/go/math/cmplx/example_test.go b/libgo/go/math/cmplx/example_test.go
new file mode 100644
index 00000000000..be87cff5ef1
--- /dev/null
+++ b/libgo/go/math/cmplx/example_test.go
@@ -0,0 +1,30 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package cmplx_test
+
+import (
+ "fmt"
+ "math"
+ "math/cmplx"
+)
+
+func ExampleAbs() {
+ fmt.Printf("%.1f", cmplx.Abs(3+4i))
+ // Output: 5.0
+}
+
+// ExampleExp computes Euler's identity.
+func ExampleExp() {
+ fmt.Printf("%.1f", cmplx.Exp(1i*math.Pi)+1)
+ // Output: (0.0+0.0i)
+}
+
+func ExamplePolar() {
+ r, theta := cmplx.Polar(2i)
+ fmt.Printf("r: %.1f, θ: %.1f*π", r, theta/math.Pi)
+ // Output: r: 2.0, θ: 0.5*π
+}
diff --git a/libgo/go/math/cmplx/tan.go b/libgo/go/math/cmplx/tan.go
index 9485315d8d0..29905521559 100644
--- a/libgo/go/math/cmplx/tan.go
+++ b/libgo/go/math/cmplx/tan.go
@@ -120,9 +120,9 @@ func tanSeries(z complex128) float64 {
rn := 0.0
d := 0.0
for {
- rn += 1
+ rn++
f *= rn
- rn += 1
+ rn++
f *= rn
x2 *= x
y2 *= y
@@ -130,16 +130,18 @@ func tanSeries(z complex128) float64 {
t /= f
d += t
- rn += 1
+ rn++
f *= rn
- rn += 1
+ rn++
f *= rn
x2 *= x
y2 *= y
t = y2 - x2
t /= f
d += t
- if math.Abs(t/d) <= MACHEP {
+ if !(math.Abs(t/d) > MACHEP) {
+ // Caution: Use ! and > instead of <= for correct behavior if t/d is NaN.
+ // See issue 17577.
break
}
}
diff --git a/libgo/go/math/expm1.go b/libgo/go/math/expm1.go
index 5a962180e5d..a0a62d10c96 100644
--- a/libgo/go/math/expm1.go
+++ b/libgo/go/math/expm1.go
@@ -235,7 +235,7 @@ func expm1(x float64) float64 {
}
t := Float64frombits(uint64(0x3ff-k) << 52) // 2**-k
y := x - (e + t)
- y += 1
+ y++
y = Float64frombits(Float64bits(y) + uint64(k)<<52) // add k to y's exponent
return y
}
diff --git a/libgo/go/math/export_s390x_test.go b/libgo/go/math/export_s390x_test.go
new file mode 100644
index 00000000000..3fdbd8640fe
--- /dev/null
+++ b/libgo/go/math/export_s390x_test.go
@@ -0,0 +1,14 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math
+
+// Export internal functions and variable for testing.
+var Log10NoVec = log10
+var CosNoVec = cos
+var CoshNoVec = cosh
+var SinNoVec = sin
+var SinhNoVec = sinh
+var TanhNoVec = tanh
+var HasVX = hasVX
diff --git a/libgo/go/math/gamma.go b/libgo/go/math/gamma.go
index 841ec114a0a..cc9e869496b 100644
--- a/libgo/go/math/gamma.go
+++ b/libgo/go/math/gamma.go
@@ -91,23 +91,31 @@ var _gamS = [...]float64{
}
// Gamma function computed by Stirling's formula.
-// The polynomial is valid for 33 <= x <= 172.
-func stirling(x float64) float64 {
+// The pair of results must be multiplied together to get the actual answer.
+// The multiplication is left to the caller so that, if careful, the caller can avoid
+// infinity for 172 <= x <= 180.
+// The polynomial is valid for 33 <= x <= 172; larger values are only used
+// in reciprocal and produce denormalized floats. The lower precision there
+// masks any imprecision in the polynomial.
+func stirling(x float64) (float64, float64) {
+ if x > 200 {
+ return Inf(1), 1
+ }
const (
SqrtTwoPi = 2.506628274631000502417
MaxStirling = 143.01608
)
w := 1 / x
w = 1 + w*((((_gamS[0]*w+_gamS[1])*w+_gamS[2])*w+_gamS[3])*w+_gamS[4])
- y := Exp(x)
+ y1 := Exp(x)
+ y2 := 1.0
if x > MaxStirling { // avoid Pow() overflow
v := Pow(x, 0.5*x-0.25)
- y = v * (v / y)
+ y1, y2 = v, v/y1
} else {
- y = Pow(x, x-0.5) / y
+ y1 = Pow(x, x-0.5) / y1
}
- y = SqrtTwoPi * y * w
- return y
+ return y1, SqrtTwoPi * w * y2
}
// Gamma returns the Gamma function of x.
@@ -125,22 +133,26 @@ func Gamma(x float64) float64 {
switch {
case isNegInt(x) || IsInf(x, -1) || IsNaN(x):
return NaN()
+ case IsInf(x, 1):
+ return Inf(1)
case x == 0:
if Signbit(x) {
return Inf(-1)
}
return Inf(1)
- case x < -170.5674972726612 || x > 171.61447887182298:
- return Inf(1)
}
q := Abs(x)
p := Floor(q)
if q > 33 {
if x >= 0 {
- return stirling(x)
+ y1, y2 := stirling(x)
+ return y1 * y2
}
+ // Note: x is negative but (checked above) not a negative integer,
+ // so x must be small enough to be in range for conversion to int64.
+ // If |x| were >= 2⁶³ it would have to be an integer.
signgam := 1
- if ip := int(p); ip&1 == 0 {
+ if ip := int64(p); ip&1 == 0 {
signgam = -1
}
z := q - p
@@ -152,7 +164,14 @@ func Gamma(x float64) float64 {
if z == 0 {
return Inf(signgam)
}
- z = Pi / (Abs(z) * stirling(q))
+ sq1, sq2 := stirling(q)
+ absz := Abs(z)
+ d := absz * sq1 * sq2
+ if IsInf(d, 0) {
+ z = Pi / absz / sq1 / sq2
+ } else {
+ z = Pi / d
+ }
return float64(signgam) * z
}
diff --git a/libgo/go/math/j0.go b/libgo/go/math/j0.go
index cbef7aa7d6e..fe267911751 100644
--- a/libgo/go/math/j0.go
+++ b/libgo/go/math/j0.go
@@ -305,20 +305,20 @@ var p0S2 = [5]float64{
}
func pzero(x float64) float64 {
- var p [6]float64
- var q [5]float64
+ var p *[6]float64
+ var q *[5]float64
if x >= 8 {
- p = p0R8
- q = p0S8
+ p = &p0R8
+ q = &p0S8
} else if x >= 4.5454 {
- p = p0R5
- q = p0S5
+ p = &p0R5
+ q = &p0S5
} else if x >= 2.8571 {
- p = p0R3
- q = p0S3
+ p = &p0R3
+ q = &p0S3
} else if x >= 2 {
- p = p0R2
- q = p0S2
+ p = &p0R2
+ q = &p0S2
}
z := 1 / (x * x)
r := p[0] + z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))))
@@ -408,19 +408,19 @@ var q0S2 = [6]float64{
}
func qzero(x float64) float64 {
- var p, q [6]float64
+ var p, q *[6]float64
if x >= 8 {
- p = q0R8
- q = q0S8
+ p = &q0R8
+ q = &q0S8
} else if x >= 4.5454 {
- p = q0R5
- q = q0S5
+ p = &q0R5
+ q = &q0S5
} else if x >= 2.8571 {
- p = q0R3
- q = q0S3
+ p = &q0R3
+ q = &q0S3
} else if x >= 2 {
- p = q0R2
- q = q0S2
+ p = &q0R2
+ q = &q0S2
}
z := 1 / (x * x)
r := p[0] + z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))))
diff --git a/libgo/go/math/j1.go b/libgo/go/math/j1.go
index d359d9072e3..f1adcb6f416 100644
--- a/libgo/go/math/j1.go
+++ b/libgo/go/math/j1.go
@@ -298,20 +298,20 @@ var p1S2 = [5]float64{
}
func pone(x float64) float64 {
- var p [6]float64
- var q [5]float64
+ var p *[6]float64
+ var q *[5]float64
if x >= 8 {
- p = p1R8
- q = p1S8
+ p = &p1R8
+ q = &p1S8
} else if x >= 4.5454 {
- p = p1R5
- q = p1S5
+ p = &p1R5
+ q = &p1S5
} else if x >= 2.8571 {
- p = p1R3
- q = p1S3
+ p = &p1R3
+ q = &p1S3
} else if x >= 2 {
- p = p1R2
- q = p1S2
+ p = &p1R2
+ q = &p1S2
}
z := 1 / (x * x)
r := p[0] + z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))))
@@ -401,19 +401,19 @@ var q1S2 = [6]float64{
}
func qone(x float64) float64 {
- var p, q [6]float64
+ var p, q *[6]float64
if x >= 8 {
- p = q1R8
- q = q1S8
+ p = &q1R8
+ q = &q1S8
} else if x >= 4.5454 {
- p = q1R5
- q = q1S5
+ p = &q1R5
+ q = &q1S5
} else if x >= 2.8571 {
- p = q1R3
- q = q1S3
+ p = &q1R3
+ q = &q1S3
} else if x >= 2 {
- p = q1R2
- q = q1S2
+ p = &q1R2
+ q = &q1S2
}
z := 1 / (x * x)
r := p[0] + z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))))
diff --git a/libgo/go/math/jn.go b/libgo/go/math/jn.go
index 721112f77c4..342278257ad 100644
--- a/libgo/go/math/jn.go
+++ b/libgo/go/math/jn.go
@@ -174,7 +174,7 @@ func Jn(n int, x float64) float64 {
q1 := w*z - 1
k := 1
for q1 < 1e9 {
- k += 1
+ k++
z += h
q0, q1 = q1, z*q1-q0
}
diff --git a/libgo/go/math/log1p.go b/libgo/go/math/log1p.go
index 6834caedcef..ef1c7defeb2 100644
--- a/libgo/go/math/log1p.go
+++ b/libgo/go/math/log1p.go
@@ -173,7 +173,7 @@ func log1p(x float64) float64 {
if iu < 0x0006a09e667f3bcd { // mantissa of Sqrt(2)
u = Float64frombits(iu | 0x3ff0000000000000) // normalize u
} else {
- k += 1
+ k++
u = Float64frombits(iu | 0x3fe0000000000000) // normalize u/2
iu = (0x0010000000000000 - iu) >> 2
}
@@ -185,10 +185,9 @@ func log1p(x float64) float64 {
if f == 0 {
if k == 0 {
return 0
- } else {
- c += float64(k) * Ln2Lo
- return float64(k)*Ln2Hi + c
}
+ c += float64(k) * Ln2Lo
+ return float64(k)*Ln2Hi + c
}
R = hfsq * (1.0 - 0.66666666666666666*f) // avoid division
if k == 0 {
diff --git a/libgo/go/math/rand/gen_cooked.go b/libgo/go/math/rand/gen_cooked.go
new file mode 100644
index 00000000000..567b7a8d14c
--- /dev/null
+++ b/libgo/go/math/rand/gen_cooked.go
@@ -0,0 +1,89 @@
+// 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
+
+// This program computes the value of rng_cooked in rng.go,
+// which is used for seeding all instances of rand.Source.
+// a 64bit and a 63bit version of the array is printed to
+// the standard output.
+
+package main
+
+import "fmt"
+
+const (
+ length = 607
+ tap = 273
+ mask = (1 << 63) - 1
+ a = 48271
+ m = (1 << 31) - 1
+ q = 44488
+ r = 3399
+)
+
+var (
+ rngVec [length]int64
+ rngTap, rngFeed int
+)
+
+func seedrand(x int32) int32 {
+ hi := x / q
+ lo := x % q
+ x = a*lo - r*hi
+ if x < 0 {
+ x += m
+ }
+ return x
+}
+
+func srand(seed int32) {
+ rngTap = 0
+ rngFeed = length - tap
+ seed %= m
+ if seed < 0 {
+ seed += m
+ } else if seed == 0 {
+ seed = 89482311
+ }
+ x := seed
+ for i := -20; i < length; i++ {
+ x = seedrand(x)
+ if i >= 0 {
+ var u int64
+ u = int64(x) << 20
+ x = seedrand(x)
+ u ^= int64(x) << 10
+ x = seedrand(x)
+ u ^= int64(x)
+ rngVec[i] = u
+ }
+ }
+}
+
+func vrand() int64 {
+ rngTap--
+ if rngTap < 0 {
+ rngTap += length
+ }
+ rngFeed--
+ if rngFeed < 0 {
+ rngFeed += length
+ }
+ x := (rngVec[rngFeed] + rngVec[rngTap])
+ rngVec[rngFeed] = x
+ return x
+}
+
+func main() {
+ srand(1)
+ for i := uint64(0); i < 7.8e12; i++ {
+ vrand()
+ }
+ fmt.Printf("rngVec after 7.8e12 calls to vrand:\n%#v\n", rngVec)
+ for i := range rngVec {
+ rngVec[i] &= mask
+ }
+ fmt.Printf("lower 63bit of rngVec after 7.8e12 calls to vrand:\n%#v\n", rngVec)
+}
diff --git a/libgo/go/math/rand/race_test.go b/libgo/go/math/rand/race_test.go
index 48f6c290b98..186c7169d82 100644
--- a/libgo/go/math/rand/race_test.go
+++ b/libgo/go/math/rand/race_test.go
@@ -33,6 +33,7 @@ func TestConcurrent(t *testing.T) {
seed += int64(Int63n(Int63()))
seed += int64(NormFloat64())
seed += int64(Uint32())
+ seed += int64(Uint64())
for _, p := range Perm(10) {
seed += int64(p)
}
diff --git a/libgo/go/math/rand/rand.go b/libgo/go/math/rand/rand.go
index dd8d43cca1c..9fe1cbd61e1 100644
--- a/libgo/go/math/rand/rand.go
+++ b/libgo/go/math/rand/rand.go
@@ -23,7 +23,20 @@ type Source interface {
Seed(seed int64)
}
+// A Source64 is a Source that can also generate
+// uniformly-distributed pseudo-random uint64 values in
+// the range [0, 1<<64) directly.
+// If a Rand r's underlying Source s implements Source64,
+// then r.Uint64 returns the result of one call to s.Uint64
+// instead of making two calls to s.Int63.
+type Source64 interface {
+ Source
+ Uint64() uint64
+}
+
// NewSource returns a new pseudo-random Source seeded with the given value.
+// Unlike the default Source used by top-level functions, this source is not
+// safe for concurrent use by multiple goroutines.
func NewSource(seed int64) Source {
var rng rngSource
rng.Seed(seed)
@@ -33,6 +46,7 @@ func NewSource(seed int64) Source {
// A Rand is a source of random numbers.
type Rand struct {
src Source
+ s64 Source64 // non-nil if src is source64
// readVal contains remainder of 63-bit integer used for bytes
// generation during most recent Read call.
@@ -46,7 +60,10 @@ type Rand struct {
// New returns a new Rand that uses random values from src
// to generate other random values.
-func New(src Source) *Rand { return &Rand{src: src} }
+func New(src Source) *Rand {
+ s64, _ := src.(Source64)
+ return &Rand{src: src, s64: s64}
+}
// Seed uses the provided seed value to initialize the generator to a deterministic state.
// Seed should not be called concurrently with any other Rand method.
@@ -66,6 +83,14 @@ func (r *Rand) Int63() int64 { return r.src.Int63() }
// Uint32 returns a pseudo-random 32-bit value as a uint32.
func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }
+// Uint64 returns a pseudo-random 64-bit value as a uint64.
+func (r *Rand) Uint64() uint64 {
+ if r.s64 != nil {
+ return r.s64.Uint64()
+ }
+ return uint64(r.Int63())>>31 | uint64(r.Int63())<<32
+}
+
// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }
@@ -207,7 +232,7 @@ func read(p []byte, int63 func() int64, readVal *int64, readPos *int8) (n int, e
* Top-level convenience functions
*/
-var globalRand = New(&lockedSource{src: NewSource(1)})
+var globalRand = New(&lockedSource{src: NewSource(1).(Source64)})
// Seed uses the provided seed value to initialize the default Source to a
// deterministic state. If Seed is not called, the generator behaves as
@@ -224,6 +249,10 @@ func Int63() int64 { return globalRand.Int63() }
// from the default Source.
func Uint32() uint32 { return globalRand.Uint32() }
+// Uint64 returns a pseudo-random 64-bit value as a uint64
+// from the default Source.
+func Uint64() uint64 { return globalRand.Uint64() }
+
// Int31 returns a non-negative pseudo-random 31-bit integer as an int32
// from the default Source.
func Int31() int32 { return globalRand.Int31() }
@@ -286,7 +315,7 @@ func ExpFloat64() float64 { return globalRand.ExpFloat64() }
type lockedSource struct {
lk sync.Mutex
- src Source
+ src Source64
}
func (r *lockedSource) Int63() (n int64) {
@@ -296,6 +325,13 @@ func (r *lockedSource) Int63() (n int64) {
return
}
+func (r *lockedSource) Uint64() (n uint64) {
+ r.lk.Lock()
+ n = r.src.Uint64()
+ r.lk.Unlock()
+ return
+}
+
func (r *lockedSource) Seed(seed int64) {
r.lk.Lock()
r.src.Seed(seed)
diff --git a/libgo/go/math/rand/rand_test.go b/libgo/go/math/rand/rand_test.go
index 6f312792d0b..bf509e06bec 100644
--- a/libgo/go/math/rand/rand_test.go
+++ b/libgo/go/math/rand/rand_test.go
@@ -328,13 +328,26 @@ func TestExpTables(t *testing.T) {
}
}
+func hasSlowFloatingPoint() bool {
+ switch runtime.GOARCH {
+ case "arm":
+ return os.Getenv("GOARM") == "5"
+ case "mips", "mipsle", "mips64", "mips64le":
+ // Be conservative and assume that all mips boards
+ // have emulated floating point.
+ // TODO: detect what it actually has.
+ return true
+ }
+ return false
+}
+
func TestFloat32(t *testing.T) {
// For issue 6721, the problem came after 7533753 calls, so check 10e6.
num := int(10e6)
// But do the full amount only on builders (not locally).
// But ARM5 floating point emulation is slow (Issue 10749), so
// do less for that builder:
- if testing.Short() && (testenv.Builder() == "" || runtime.GOARCH == "arm" && os.Getenv("GOARM") == "5") {
+ if testing.Short() && (testenv.Builder() == "" || hasSlowFloatingPoint()) {
num /= 100 // 1.72 seconds instead of 172 seconds
}
diff --git a/libgo/go/math/rand/regress_test.go b/libgo/go/math/rand/regress_test.go
index 4dd965ce1e3..e31e6c5af02 100644
--- a/libgo/go/math/rand/regress_test.go
+++ b/libgo/go/math/rand/regress_test.go
@@ -381,4 +381,24 @@ var regressGolden = []interface{}{
uint32(75079301), // Uint32()
uint32(3380456901), // Uint32()
uint32(3433369789), // Uint32()
+ uint64(8717895732742165505), // Uint64()
+ uint64(2259404117704393152), // Uint64()
+ uint64(6050128673802995827), // Uint64()
+ uint64(9724605487393973602), // Uint64()
+ uint64(12613765599614152010), // Uint64()
+ uint64(11893357769247901871), // Uint64()
+ uint64(1774932891286980153), // Uint64()
+ uint64(15267744271532198264), // Uint64()
+ uint64(17498302081433670737), // Uint64()
+ uint64(1543572285742637646), // Uint64()
+ uint64(11885104867954719224), // Uint64()
+ uint64(17548432336275752516), // Uint64()
+ uint64(7837839688282259259), // Uint64()
+ uint64(2518412263346885298), // Uint64()
+ uint64(5617773211005988520), // Uint64()
+ uint64(11562935753659892057), // Uint64()
+ uint64(16368296284793757383), // Uint64()
+ uint64(161231572858529631), // Uint64()
+ uint64(16482847956365694147), // Uint64()
+ uint64(16596477517051940556), // Uint64()
}
diff --git a/libgo/go/math/rand/rng.go b/libgo/go/math/rand/rng.go
index 947c49f0f26..f922417cdc4 100644
--- a/libgo/go/math/rand/rng.go
+++ b/libgo/go/math/rand/rng.go
@@ -23,161 +23,159 @@ const (
)
var (
- // cooked random numbers
- // the state of the rng
- // after 780e10 iterations
+ // Used for seeding. See gen_cooked.go for details.
rng_cooked [_LEN]int64 = [...]int64{
- 5041579894721019882, 4646389086726545243, 1395769623340756751, 5333664234075297259,
- 2875692520355975054, 9033628115061424579, 7143218595135194537, 4812947590706362721,
- 7937252194349799378, 5307299880338848416, 8209348851763925077, 2115741599318814044,
- 4593015457530856296, 8140875735541888011, 3319429241265089026, 8619815648190321034,
- 1727074043483619500, 113108499721038619, 4569519971459345583, 5062833859075314731,
- 2387618771259064424, 2716131344356686112, 6559392774825876886, 7650093201692370310,
- 7684323884043752161, 257867835996031390, 6593456519409015164, 271327514973697897,
- 2789386447340118284, 1065192797246149621, 3344507881999356393, 4459797941780066633,
- 7465081662728599889, 1014950805555097187, 4449440729345990775, 3481109366438502643,
+ -4181792142133755926, -4576982950128230565, 1395769623340756751, 5333664234075297259,
+ -6347679516498800754, 9033628115061424579, 7143218595135194537, 4812947590706362721,
+ 7937252194349799378, 5307299880338848416, 8209348851763925077, -7107630437535961764,
+ 4593015457530856296, 8140875735541888011, -5903942795589686782, -603556388664454774,
+ -7496297993371156308, 113108499721038619, 4569519971459345583, -4160538177779461077,
+ -6835753265595711384, -6507240692498089696, 6559392774825876886, 7650093201692370310,
+ 7684323884043752161, -8965504200858744418, -2629915517445760644, 271327514973697897,
+ -6433985589514657524, 1065192797246149621, 3344507881999356393, -4763574095074709175,
+ 7465081662728599889, 1014950805555097187, -4773931307508785033, -5742262670416273165,
2418672789110888383, 5796562887576294778, 4484266064449540171, 3738982361971787048,
- 4523597184512354423, 10530508058128498, 8633833783282346118, 2625309929628791628,
- 8660405965245884302, 10162832508971942, 6540714680961817391, 7031802312784620857,
- 6240911277345944669, 831864355460801054, 8004434137542152891, 2116287251661052151,
+ -4699774852342421385, 10530508058128498, -589538253572429690, -6598062107225984180,
+ 8660405965245884302, 10162832508971942, -2682657355892958417, 7031802312784620857,
+ 6240911277345944669, 831864355460801054, -1218937899312622917, 2116287251661052151,
2202309800992166967, 9161020366945053561, 4069299552407763864, 4936383537992622449,
- 457351505131524928, 342195045928179354, 2847771682816600509, 2068020115986376518,
- 4368649989588021065, 887231587095185257, 5563591506886576496, 6816225200251950296,
- 5616972787034086048, 8471809303394836566, 1686575021641186857, 4045484338074262002,
- 4244156215201778923, 7848217333783577387, 5632136521049761902, 833283142057835272,
- 9029726508369077193, 3243583134664087292, 4316371101804477087, 8937849979965997980,
- 6446940406810434101, 1679342092332374735, 6050638460742422078, 6993520719509581582,
- 7640877852514293609, 5881353426285907985, 812786550756860885, 4541845584483343330,
- 2725470216277009086, 4980675660146853729, 5210769080603236061, 8894283318990530821,
- 6326442804750084282, 1495812843684243920, 7069751578799128019, 7370257291860230865,
- 6756929275356942261, 4706794511633873654, 7824520467827898663, 8549875090542453214,
- 33650829478596156, 1328918435751322643, 7297902601803624459, 1011190183918857495,
- 2238025036817854944, 5147159997473910359, 896512091560522982, 2659470849286379941,
- 6097729358393448602, 1731725986304753684, 4106255841983812711, 8327155210721535508,
- 8477511620686074402, 5803876044675762232, 8435417780860221662, 5988852856651071244,
- 4715837297103951910, 7566171971264485114, 505808562678895611, 5070098180695063370,
- 842110666775871513, 572156825025677802, 1791881013492340891, 3393267094866038768,
- 3778721850472236509, 2352769483186201278, 1292459583847367458, 8897907043675088419,
- 5781809037144163536, 2733958794029492513, 5092019688680754699, 8996124554772526841,
- 4234737173186232084, 5027558287275472836, 4635198586344772304, 8687338893267139351,
- 5907508150730407386, 784756255473944452, 972392927514829904, 5422057694808175112,
- 5158420642969283891, 9048531678558643225, 2407211146698877100, 7583282216521099569,
- 3940796514530962282, 3341174631045206375, 3095313889586102949, 7405321895688238710,
- 5832080132947175283, 7890064875145919662, 8184139210799583195, 1149859861409226130,
- 1464597243840211302, 4641648007187991873, 3516491885471466898, 956288521791657692,
+ 457351505131524928, -8881176990926596454, -6375600354038175299, -7155351920868399290,
+ 4368649989588021065, 887231587095185257, -3659780529968199312, -2407146836602825512,
+ 5616972787034086048, -751562733459939242, 1686575021641186857, -5177887698780513806,
+ -4979215821652996885, -1375154703071198421, 5632136521049761902, -8390088894796940536,
+ -193645528485698615, -5979788902190688516, -4907000935050298721, -285522056888777828,
+ -2776431630044341707, 1679342092332374735, 6050638460742422078, -2229851317345194226,
+ -1582494184340482199, 5881353426285907985, 812786550756860885, 4541845584483343330,
+ -6497901820577766722, 4980675660146853729, -4012602956251539747, -329088717864244987,
+ -2896929232104691526, 1495812843684243920, -2153620458055647789, 7370257291860230865,
+ -2466442761497833547, 4706794511633873654, -1398851569026877145, 8549875090542453214,
+ -9189721207376179652, -7894453601103453165, 7297902601803624459, 1011190183918857495,
+ -6985347000036920864, 5147159997473910359, -8326859945294252826, 2659470849286379941,
+ 6097729358393448602, -7491646050550022124, -5117116194870963097, -896216826133240300,
+ -745860416168701406, 5803876044675762232, -787954255994554146, -3234519180203704564,
+ -4507534739750823898, -1657200065590290694, 505808562678895611, -4153273856159712438,
+ -8381261370078904295, 572156825025677802, 1791881013492340891, 3393267094866038768,
+ -5444650186382539299, 2352769483186201278, -7930912453007408350, -325464993179687389,
+ -3441562999710612272, -6489413242825283295, 5092019688680754699, -227247482082248967,
+ 4234737173186232084, 5027558287275472836, 4635198586344772304, -536033143587636457,
+ 5907508150730407386, -8438615781380831356, 972392927514829904, -3801314342046600696,
+ -4064951393885491917, -174840358296132583, 2407211146698877100, -1640089820333676239,
+ 3940796514530962282, -5882197405809569433, 3095313889586102949, -1818050141166537098,
+ 5832080132947175283, 7890064875145919662, 8184139210799583195, -8073512175445549678,
+ -7758774793014564506, -4581724029666783935, 3516491885471466898, -8267083515063118116,
6657089965014657519, 5220884358887979358, 1796677326474620641, 5340761970648932916,
1147977171614181568, 5066037465548252321, 2574765911837859848, 1085848279845204775,
- 3350107529868390359, 6116438694366558490, 2107701075971293812, 1803294065921269267,
- 2469478054175558874, 7368243281019965984, 3791908367843677526, 185046971116456637,
- 2257095756513439648, 7217693971077460129, 909049953079504259, 7196649268545224266,
- 5637660345400869599, 3955544945427965183, 8057528650917418961, 4139268440301127643,
- 6621926588513568059, 1373361136802681441, 6527366231383600011, 3507654575162700890,
- 9202058512774729859, 1954818376891585542, 6640380907130175705, 8299563319178235687,
- 3901867355218954373, 7046310742295574065, 6847195391333990232, 1572638100518868053,
- 8850422670118399721, 3631909142291992901, 5158881091950831288, 2882958317343121593,
- 4763258931815816403, 6280052734341785344, 4243789408204964850, 2043464728020827976,
- 6545300466022085465, 4562580375758598164, 5495451168795427352, 1738312861590151095,
- 553004618757816492, 6895160632757959823, 8233623922264685171, 7139506338801360852,
- 8550891222387991669, 5535668688139305547, 2430933853350256242, 5401941257863201076,
- 8159640039107728799, 6157493831600770366, 7632066283658143750, 6308328381617103346,
+ -5873264506986385449, 6116438694366558490, 2107701075971293812, -7420077970933506541,
+ 2469478054175558874, -1855128755834809824, -5431463669011098282, -9038325065738319171,
+ -6966276280341336160, 7217693971077460129, -8314322083775271549, 7196649268545224266,
+ -3585711691453906209, -5267827091426810625, 8057528650917418961, -5084103596553648165,
+ -2601445448341207749, -7850010900052094367, 6527366231383600011, 3507654575162700890,
+ 9202058512774729859, 1954818376891585542, -2582991129724600103, 8299563319178235687,
+ -5321504681635821435, 7046310742295574065, -2376176645520785576, -7650733936335907755,
+ 8850422670118399721, 3631909142291992901, 5158881091950831288, -6340413719511654215,
+ 4763258931815816403, 6280052734341785344, -4979582628649810958, 2043464728020827976,
+ -2678071570832690343, 4562580375758598164, 5495451168795427352, -7485059175264624713,
+ 553004618757816492, 6895160632757959823, -989748114590090637, 7139506338801360852,
+ -672480814466784139, 5535668688139305547, 2430933853350256242, -3821430778991574732,
+ -1063731997747047009, -3065878205254005442, 7632066283658143750, 6308328381617103346,
3681878764086140361, 3289686137190109749, 6587997200611086848, 244714774258135476,
- 4079788377417136100, 8090302575944624335, 2945117363431356361, 864324395848741045,
- 3009039260312620700, 8430027460082534031, 401084700045993341, 7254622446438694921,
- 4707864159563588614, 5640248530963493951, 5982507712689997893, 3315098242282210105,
- 5503847578771918426, 3941971367175193882, 8118566580304798074, 3839261274019871296,
- 7062410411742090847, 741381002980207668, 6027994129690250817, 2497829994150063930,
- 6251390334426228834, 1368930247903518833, 8809096399316380241, 6492004350391900708,
- 2462145737463489636, 404828418920299174, 4153026434231690595, 261785715255475940,
- 5464715384600071357, 592710404378763017, 6764129236657751224, 8513655718539357449,
- 5820343663801914208, 385298524683789911, 5224135003438199467, 6303131641338802145,
- 7150122561309371392, 368107899140673753, 3115186834558311558, 2915636353584281051,
+ -5143583659437639708, 8090302575944624335, 2945117363431356361, -8359047641006034763,
+ 3009039260312620700, -793344576772241777, 401084700045993341, -1968749590416080887,
+ 4707864159563588614, -3583123505891281857, -3240864324164777915, -5908273794572565703,
+ -3719524458082857382, -5281400669679581926, 8118566580304798074, 3839261274019871296,
+ 7062410411742090847, -8481991033874568140, 6027994129690250817, -6725542042704711878,
+ -2971981702428546974, -7854441788951256975, 8809096399316380241, 6492004350391900708,
+ 2462145737463489636, -8818543617934476634, -5070345602623085213, -8961586321599299868,
+ -3758656652254704451, -8630661632476012791, 6764129236657751224, -709716318315418359,
+ -3403028373052861600, -8838073512170985897, -3999237033416576341, -2920240395515973663,
+ -2073249475545404416, 368107899140673753, -6108185202296464250, -6307735683270494757,
4782583894627718279, 6718292300699989587, 8387085186914375220, 3387513132024756289,
- 4654329375432538231, 8930667561363381602, 5374373436876319273, 7623042350483453954,
- 7725442901813263321, 9186225467561587250, 4091027289597503355, 2357631606492579800,
- 2530936820058611833, 1636551876240043639, 5564664674334965799, 1452244145334316253,
- 2061642381019690829, 1279580266495294036, 9108481583171221009, 6023278686734049809,
- 5007630032676973346, 2153168792952589781, 6720334534964750538, 6041546491134794105,
- 3433922409283786309, 2285479922797300912, 3110614940896576130, 6366559590722842893,
- 5418791419666136509, 7163298419643543757, 4891138053923696990, 580618510277907015,
- 1684034065251686769, 4429514767357295841, 330346578555450005, 1119637995812174675,
- 7177515271653460134, 4589042248470800257, 7693288629059004563, 143607045258444228,
- 246994305896273627, 866417324803099287, 6473547110565816071, 3092379936208876896,
- 2058427839513754051, 5133784708526867938, 8785882556301281247, 6149332666841167611,
- 8585842181454472135, 6137678347805511274, 2070447184436970006, 5708223427705576541,
- 5999657892458244504, 4358391411789012426, 325123008708389849, 6837621693887290924,
- 4843721905315627004, 6010651222149276415, 5398352198963874652, 4602025990114250980,
- 1044646352569048800, 9106614159853161675, 829256115228593269, 4919284369102997000,
- 2681532557646850893, 3681559472488511871, 5307999518958214035, 6334130388442829274,
- 2658708232916537604, 1163313865052186287, 581945337509520675, 3648778920718647903,
- 4423673246306544414, 1620799783996955743, 220828013409515943, 8150384699999389761,
- 4287360518296753003, 4590000184845883843, 5513660857261085186, 6964829100392774275,
- 478991688350776035, 8746140185685648781, 228500091334420247, 1356187007457302238,
- 3019253992034194581, 3152601605678500003, 430152752706002213, 5559581553696971176,
- 4916432985369275664, 663574931734554391, 3420773838927732076, 2868348622579915573,
- 1999319134044418520, 3328689518636282723, 2587672709781371173, 1517255313529399333,
- 3092343956317362483, 3662252519007064108, 972445599196498113, 7664865435875959367,
- 1708913533482282562, 6917817162668868494, 3217629022545312900, 2570043027221707107,
- 8739788839543624613, 2488075924621352812, 4694002395387436668, 4559628481798514356,
+ 4654329375432538231, -292704475491394206, -3848998599978456535, 7623042350483453954,
+ 7725442901813263321, 9186225467561587250, -5132344747257272453, -6865740430362196008,
+ 2530936820058611833, 1636551876240043639, -3658707362519810009, 1452244145334316253,
+ -7161729655835084979, -7943791770359481772, 9108481583171221009, -3200093350120725999,
+ 5007630032676973346, 2153168792952589781, 6720334534964750538, -3181825545719981703,
+ 3433922409283786309, 2285479922797300912, 3110614940896576130, -2856812446131932915,
+ -3804580617188639299, 7163298419643543757, 4891138053923696990, 580618510277907015,
+ 1684034065251686769, 4429514767357295841, -8893025458299325803, -8103734041042601133,
+ 7177515271653460134, 4589042248470800257, -1530083407795771245, 143607045258444228,
+ 246994305896273627, -8356954712051676521, 6473547110565816071, 3092379936208876896,
+ 2058427839513754051, -4089587328327907870, 8785882556301281247, -3074039370013608197,
+ -637529855400303673, 6137678347805511274, -7152924852417805802, 5708223427705576541,
+ -3223714144396531304, 4358391411789012426, 325123008708389849, 6837621693887290924,
+ 4843721905315627004, -3212720814705499393, -3825019837890901156, 4602025990114250980,
+ 1044646352569048800, 9106614159853161675, -8394115921626182539, -4304087667751778808,
+ 2681532557646850893, 3681559472488511871, -3915372517896561773, -2889241648411946534,
+ -6564663803938238204, -8060058171802589521, 581945337509520675, 3648778920718647903,
+ -4799698790548231394, -7602572252857820065, 220828013409515943, -1072987336855386047,
+ 4287360518296753003, -4633371852008891965, 5513660857261085186, -2258542936462001533,
+ -8744380348503999773, 8746140185685648781, 228500091334420247, 1356187007457302238,
+ 3019253992034194581, 3152601605678500003, -8793219284148773595, 5559581553696971176,
+ 4916432985369275664, -8559797105120221417, -5802598197927043732, 2868348622579915573,
+ -7224052902810357288, -5894682518218493085, 2587672709781371173, -7706116723325376475,
+ 3092343956317362483, -5561119517847711700, 972445599196498113, -1558506600978816441,
+ 1708913533482282562, -2305554874185907314, -6005743014309462908, -6653329009633068701,
+ -483583197311151195, 2488075924621352812, -4529369641467339140, -4663743555056261452,
2997203966153298104, 1282559373026354493, 240113143146674385, 8665713329246516443,
- 628141331766346752, 4571950817186770476, 1472811188152235408, 7596648026010355826,
- 6091219417754424743, 7834161864828164065, 7103445518877254909, 4390861237357459201,
- 4442653864240571734, 8903482404847331368, 622261699494173647, 6037261250297213248,
- 504404948065709118, 7275215526217113061, 1011176780856001400, 2194750105623461063,
- 2623071828615234808, 5157313728073836108, 3738405111966602044, 2539767524076729570,
- 2467284396349269342, 5256026990536851868, 7841086888628396109, 6640857538655893162,
- 1202087339038317498, 2113514992440715978, 7534350895342931403, 4925284734898484745,
- 5145623771477493805, 8225140880134972332, 2719520354384050532, 9132346697815513771,
- 4332154495710163773, 7137789594094346916, 6994721091344268833, 6667228574869048934,
- 655440045726677499, 59934747298466858, 6124974028078036405, 8957774780655365418,
- 2332206071942466437, 1701056712286369627, 3154897383618636503, 1637766181387607527,
- 2460521277767576533, 197309393502684135, 643677854385267315, 2543179307861934850,
- 4350769010207485119, 4754652089410667672, 2015595502641514512, 7999059458976458608,
- 4287946071480840813, 8362686366770308971, 6486469209321732151, 3617727845841796026,
- 7554353525834302244, 4450022655153542367, 1605195740213535749, 5327014565305508387,
- 4626575813550328320, 2692222020597705149, 241045573717249868, 5098046974627094010,
- 7916882295460730264, 884817090297530579, 5329160409530630596, 7790979528857726136,
- 4955070238059373407, 4918537275422674302, 3008076183950404629, 3007769226071157901,
- 2470346235617803020, 8928702772696731736, 7856187920214445904, 4474874585391974885,
- 7900176660600710914, 2140571127916226672, 2425445057265199971, 2486055153341847830,
- 4186670094382025798, 1883939007446035042, 8808666044074867985, 3734134241178479257,
- 4065968871360089196, 6953124200385847784, 1305686814738899057, 1637739099014457647,
- 3656125660947993209, 3966759634633167020, 3106378204088556331, 6328899822778449810,
- 4565385105440252958, 1979884289539493806, 2331793186920865425, 3783206694208922581,
- 8464961209802336085, 2843963751609577687, 3030678195484896323, 4793717574095772604,
+ 628141331766346752, -4651421219668005332, -7750560848702540400, 7596648026010355826,
+ -3132152619100351065, 7834161864828164065, 7103445518877254909, 4390861237357459201,
+ -4780718172614204074, -319889632007444440, 622261699494173647, -3186110786557562560,
+ -8718967088789066690, -1948156510637662747, -8212195255998774408, -7028621931231314745,
+ 2623071828615234808, -4066058308780939700, -5484966924888173764, -6683604512778046238,
+ -6756087640505506466, 5256026990536851868, 7841086888628396109, 6640857538655893162,
+ -8021284697816458310, -7109857044414059830, -1689021141511844405, -4298087301956291063,
+ -4077748265377282003, -998231156719803476, 2719520354384050532, 9132346697815513771,
+ 4332154495710163773, -2085582442760428892, 6994721091344268833, -2556143461985726874,
+ -8567931991128098309, 59934747298466858, -3098398008776739403, -265597256199410390,
+ 2332206071942466437, -7522315324568406181, 3154897383618636503, -7585605855467168281,
+ -6762850759087199275, 197309393502684135, -8579694182469508493, 2543179307861934850,
+ 4350769010207485119, -4468719947444108136, -7207776534213261296, -1224312577878317200,
+ 4287946071480840813, 8362686366770308971, 6486469209321732151, -5605644191012979782,
+ -1669018511020473564, 4450022655153542367, -7618176296641240059, -3896357471549267421,
+ -4596796223304447488, -6531150016257070659, -8982326463137525940, -4125325062227681798,
+ -1306489741394045544, -8338554946557245229, 5329160409530630596, 7790979528857726136,
+ 4955070238059373407, -4304834761432101506, -6215295852904371179, 3007769226071157901,
+ -6753025801236972788, 8928702772696731736, 7856187920214445904, -4748497451462800923,
+ 7900176660600710914, -7082800908938549136, -6797926979589575837, -6737316883512927978,
+ 4186670094382025798, 1883939007446035042, -414705992779907823, 3734134241178479257,
+ 4065968871360089196, 6953124200385847784, -7917685222115876751, -7585632937840318161,
+ -5567246375906782599, -5256612402221608788, 3106378204088556331, -2894472214076325998,
+ 4565385105440252958, 1979884289539493806, -6891578849933910383, 3783206694208922581,
+ 8464961209802336085, 2843963751609577687, 3030678195484896323, -4429654462759003204,
4459239494808162889, 402587895800087237, 8057891408711167515, 4541888170938985079,
- 1042662272908816815, 5557303057122568958, 2647678726283249984, 2144477441549833761,
- 5806352215355387087, 7117771003473903623, 5916597177708541638, 462597715452321361,
- 8833658097025758785, 5970273481425315300, 563813119381731307, 2768349550652697015,
- 1598828206250873866, 5206393647403558110, 6235043485709261823, 3152217402014639496,
- 8469693267274066490, 125672920241807416, 5311079624024060938, 6663754932310491587,
- 8736848295048751716, 4488039774992061878, 5923302823487327109, 140891791083103236,
- 7414942793393574290, 7990420780896957397, 4317817392807076702, 3625184369705367340,
- 2740722765288122703, 5743100009702758344, 5997898640509039159, 8854493341352484163,
- 5242208035432907801, 701338899890987198, 7609280429197514109, 3020985755112334161,
- 6651322707055512866, 2635195723621160615, 5144520864246028816, 1035086515727829828,
- 1567242097116389047, 8172389260191636581, 6337820351429292273, 2163012566996458925,
- 2743190902890262681, 1906367633221323427, 6011544915663598137, 5932255307352610768,
- 2241128460406315459, 895504896216695588, 3094483003111372717, 4583857460292963101,
- 9079887171656594975, 8839289181930711403, 5762740387243057873, 4225072055348026230,
- 1838220598389033063, 3801620336801580414, 8823526620080073856, 1776617605585100335,
- 7899055018877642622, 5421679761463003041, 5521102963086275121, 4248279443559365898,
- 8735487530905098534, 1760527091573692978, 7142485049657745894, 8222656872927218123,
- 4969531564923704323, 3394475942196872480, 6424174453260338141, 359248545074932887,
- 3273651282831730598, 6797106199797138596, 3030918217665093212, 145600834617314036,
- 6036575856065626233, 740416251634527158, 7080427635449935582, 6951781370868335478,
- 399922722363687927, 294902314447253185, 7844950936339178523, 880320858634709042,
- 6192655680808675579, 411604686384710388, 9026808440365124461, 6440783557497587732,
+ 1042662272908816815, -3666068979732206850, 2647678726283249984, 2144477441549833761,
+ -3417019821499388721, -2105601033380872185, 5916597177708541638, -8760774321402454447,
+ 8833658097025758785, 5970273481425315300, 563813119381731307, -6455022486202078793,
+ 1598828206250873866, -4016978389451217698, -2988328551145513985, -6071154634840136312,
+ 8469693267274066490, 125672920241807416, -3912292412830714870, -2559617104544284221,
+ -486523741806024092, -4735332261862713930, 5923302823487327109, -9082480245771672572,
+ -1808429243461201518, 7990420780896957397, 4317817392807076702, 3625184369705367340,
+ -6482649271566653105, -3480272027152017464, -3225473396345736649, -368878695502291645,
+ -3981164001421868007, -8522033136963788610, 7609280429197514109, 3020985755112334161,
+ -2572049329799262942, 2635195723621160615, 5144520864246028816, -8188285521126945980,
+ 1567242097116389047, 8172389260191636581, -2885551685425483535, -7060359469858316883,
+ -6480181133964513127, -7317004403633452381, 6011544915663598137, 5932255307352610768,
+ 2241128460406315459, -8327867140638080220, 3094483003111372717, 4583857460292963101,
+ 9079887171656594975, -384082854924064405, -3460631649611717935, 4225072055348026230,
+ -7385151438465742745, 3801620336801580414, -399845416774701952, -7446754431269675473,
+ 7899055018877642622, 5421679761463003041, 5521102963086275121, -4975092593295409910,
+ 8735487530905098534, -7462844945281082830, -2080886987197029914, -1000715163927557685,
+ -4253840471931071485, -5828896094657903328, 6424174453260338141, 359248545074932887,
+ -5949720754023045210, -2426265837057637212, 3030918217665093212, -9077771202237461772,
+ -3186796180789149575, 740416251634527158, -2142944401404840226, 6951781370868335478,
+ 399922722363687927, -8928469722407522623, -1378421100515597285, -8343051178220066766,
+ -3030716356046100229, -8811767350470065420, 9026808440365124461, 6440783557497587732,
4615674634722404292, 539897290441580544, 2096238225866883852, 8751955639408182687,
- 1907224908052289603, 7381039757301768559, 6157238513393239656, 7749994231914157575,
+ -7316147128802486205, 7381039757301768559, 6157238513393239656, -1473377804940618233,
8629571604380892756, 5280433031239081479, 7101611890139813254, 2479018537985767835,
- 7169176924412769570, 7942066497793203302, 1357759729055557688, 2278447439451174845,
- 3625338785743880657, 6477479539006708521, 8976185375579272206, 5511371554711836120,
+ 7169176924412769570, -1281305539061572506, -7865612307799218120, 2278447439451174845,
+ 3625338785743880657, 6477479539006708521, 8976185375579272206, -3712000482142939688,
1326024180520890843, 7537449876596048829, 5464680203499696154, 3189671183162196045,
- 6346751753565857109, 241159987320630307, 3095793449658682053, 8978332846736310159,
- 2902794662273147216, 7208698530190629697, 7276901792339343736, 1732385229314443140,
- 4133292154170828382, 2918308698224194548, 1519461397937144458, 5293934712616591764,
- 4922828954023452664, 2879211533496425641, 5896236396443472108, 8465043815351752425,
- 7329020396871624740, 8915471717014488588, 2944902635677463047, 7052079073493465134,
+ 6346751753565857109, -8982212049534145501, -6127578587196093755, -245039190118465649,
+ -6320577374581628592, 7208698530190629697, 7276901792339343736, -7490986807540332668,
+ 4133292154170828382, 2918308698224194548, -7703910638917631350, -3929437324238184044,
+ -4300543082831323144, -6344160503358350167, 5896236396443472108, -758328221503023383,
+ -1894351639983151068, -307900319840287220, -6278469401177312761, -2171292963361310674,
8382142935188824023, 9103922860780351547, 4152330101494654406,
}
)
@@ -223,13 +221,18 @@ func (rng *rngSource) Seed(seed int64) {
x = seedrand(x)
u ^= int64(x)
u ^= rng_cooked[i]
- rng.vec[i] = u & _MASK
+ rng.vec[i] = u
}
}
}
// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
func (rng *rngSource) Int63() int64 {
+ return int64(rng.Uint64() & _MASK)
+}
+
+// Uint64 returns a non-negative pseudo-random 64-bit integer as an uint64.
+func (rng *rngSource) Uint64() uint64 {
rng.tap--
if rng.tap < 0 {
rng.tap += _LEN
@@ -240,7 +243,7 @@ func (rng *rngSource) Int63() int64 {
rng.feed += _LEN
}
- x := (rng.vec[rng.feed] + rng.vec[rng.tap]) & _MASK
+ x := rng.vec[rng.feed] + rng.vec[rng.tap]
rng.vec[rng.feed] = x
- return x
+ return uint64(x)
}
diff --git a/libgo/go/math/sin.go b/libgo/go/math/sin.go
index 1c5491f6dc4..75579ab4edf 100644
--- a/libgo/go/math/sin.go
+++ b/libgo/go/math/sin.go
@@ -146,8 +146,8 @@ func cos(x float64) float64 {
// map zeros to origin
if j&1 == 1 {
- j += 1
- y += 1
+ j++
+ y++
}
j &= 7 // octant modulo 2Pi radians (360 degrees)
if j > 3 {
@@ -212,8 +212,8 @@ func sin(x float64) float64 {
// map zeros to origin
if j&1 == 1 {
- j += 1
- y += 1
+ j++
+ y++
}
j &= 7 // octant modulo 2Pi radians (360 degrees)
// reflect in x axis
diff --git a/libgo/go/math/sincos.go b/libgo/go/math/sincos.go
index b3a2f8a8619..89db81e7fa5 100644
--- a/libgo/go/math/sincos.go
+++ b/libgo/go/math/sincos.go
@@ -42,8 +42,8 @@ func sincos(x float64) (sin, cos float64) {
y := float64(j) // integer part of x/(Pi/4), as float
if j&1 == 1 { // map zeros to origin
- j += 1
- y += 1
+ j++
+ y++
}
j &= 7 // octant modulo 2Pi radians (360 degrees)
if j > 3 { // reflect in x axis
diff --git a/libgo/go/math/tan.go b/libgo/go/math/tan.go
index e544b276b5d..f5230d3f1f9 100644
--- a/libgo/go/math/tan.go
+++ b/libgo/go/math/tan.go
@@ -114,8 +114,8 @@ func tan(x float64) float64 {
/* map zeros and singularities to origin */
if j&1 == 1 {
- j += 1
- y += 1
+ j++
+ y++
}
z := ((x - y*PI4A) - y*PI4B) - y*PI4C
diff --git a/libgo/go/mime/mediatype.go b/libgo/go/mime/mediatype.go
index 18454011273..75cc90310f1 100644
--- a/libgo/go/mime/mediatype.go
+++ b/libgo/go/mime/mediatype.go
@@ -248,24 +248,33 @@ func consumeValue(v string) (value, rest string) {
}
// parse a quoted-string
- rest = v[1:] // consume the leading quote
buffer := new(bytes.Buffer)
- var nextIsLiteral bool
- for idx, r := range rest {
- switch {
- case nextIsLiteral:
- buffer.WriteRune(r)
- nextIsLiteral = false
- case r == '"':
- return buffer.String(), rest[idx+1:]
- case r == '\\':
- nextIsLiteral = true
- case r != '\r' && r != '\n':
- buffer.WriteRune(r)
- default:
+ for i := 1; i < len(v); i++ {
+ r := v[i]
+ if r == '"' {
+ return buffer.String(), v[i+1:]
+ }
+ // When MSIE sends a full file path (in "intranet mode"), it does not
+ // escape backslashes: "C:\dev\go\foo.txt", not "C:\\dev\\go\\foo.txt".
+ //
+ // No known MIME generators emit unnecessary backslash escapes
+ // for simple token characters like numbers and letters.
+ //
+ // If we see an unnecessary backslash escape, assume it is from MSIE
+ // and intended as a literal backslash. This makes Go servers deal better
+ // with MSIE without affecting the way they handle conforming MIME
+ // generators.
+ if r == '\\' && i+1 < len(v) && !isTokenChar(rune(v[i+1])) {
+ buffer.WriteByte(v[i+1])
+ i++
+ continue
+ }
+ if r == '\r' || r == '\n' {
return "", v
}
+ buffer.WriteByte(v[i])
}
+ // Did not find end quote.
return "", v
}
diff --git a/libgo/go/mime/mediatype_test.go b/libgo/go/mime/mediatype_test.go
index 9afa55825fe..c5fc906d6af 100644
--- a/libgo/go/mime/mediatype_test.go
+++ b/libgo/go/mime/mediatype_test.go
@@ -138,10 +138,11 @@ func TestParseMediaType(t *testing.T) {
m("title", "This is even more ***fun*** isn't it!")},
// Tests from http://greenbytes.de/tech/tc2231/
+ // Note: Backslash escape handling is a bit loose, like MSIE.
// TODO(bradfitz): add the rest of the tests from that site.
{`attachment; filename="f\oo.html"`,
"attachment",
- m("filename", "foo.html")},
+ m("filename", "f\\oo.html")},
{`attachment; filename="\"quoting\" tested.html"`,
"attachment",
m("filename", `"quoting" tested.html`)},
@@ -165,7 +166,7 @@ func TestParseMediaType(t *testing.T) {
m("filename", "foo-%41.html")},
{`attachment; filename="foo-%\41.html"`,
"attachment",
- m("filename", "foo-%41.html")},
+ m("filename", "foo-%\\41.html")},
{`filename=foo.html`,
"", m()},
{`x=y; filename=foo.html`,
@@ -220,18 +221,21 @@ func TestParseMediaType(t *testing.T) {
// Empty string used to be mishandled.
{`foo; bar=""`, "foo", m("bar", "")},
+
+ // Microsoft browers in intranet mode do not think they need to escape \ in file name.
+ {`form-data; name="file"; filename="C:\dev\go\robots.txt"`, "form-data", m("name", "file", "filename", `C:\dev\go\robots.txt`)},
}
for _, test := range tests {
mt, params, err := ParseMediaType(test.in)
if err != nil {
if test.t != "" {
- t.Errorf("for input %q, unexpected error: %v", test.in, err)
+ t.Errorf("for input %#q, unexpected error: %v", test.in, err)
continue
}
continue
}
if g, e := mt, test.t; g != e {
- t.Errorf("for input %q, expected type %q, got %q",
+ t.Errorf("for input %#q, expected type %q, got %q",
test.in, e, g)
continue
}
@@ -239,7 +243,7 @@ func TestParseMediaType(t *testing.T) {
continue
}
if !reflect.DeepEqual(params, test.p) {
- t.Errorf("for input %q, wrong params.\n"+
+ t.Errorf("for input %#q, wrong params.\n"+
"expected: %#v\n"+
" got: %#v",
test.in, test.p, params)
diff --git a/libgo/go/mime/multipart/formdata.go b/libgo/go/mime/multipart/formdata.go
index 8085bd3975b..c9e3188c33a 100644
--- a/libgo/go/mime/multipart/formdata.go
+++ b/libgo/go/mime/multipart/formdata.go
@@ -79,8 +79,10 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
if err != nil {
return nil, err
}
- defer file.Close()
_, err = io.Copy(file, io.MultiReader(&b, p))
+ if cerr := file.Close(); err == nil {
+ err = cerr
+ }
if err != nil {
os.Remove(file.Name())
return nil, err
diff --git a/libgo/go/mime/multipart/multipart.go b/libgo/go/mime/multipart/multipart.go
index 205348ca89d..19548081769 100644
--- a/libgo/go/mime/multipart/multipart.go
+++ b/libgo/go/mime/multipart/multipart.go
@@ -42,9 +42,7 @@ type Part struct {
// during Read calls.
Header textproto.MIMEHeader
- buffer *bytes.Buffer
- mr *Reader
- bytesRead int
+ mr *Reader
disposition string
dispositionParams map[string]string
@@ -53,6 +51,11 @@ type Part struct {
// wrapper around such a reader, decoding the
// Content-Transfer-Encoding
r io.Reader
+
+ n int // known data bytes waiting in mr.bufReader
+ total int64 // total data bytes read already
+ err error // error to return when n == 0
+ readErr error // read error observed from mr.bufReader
}
// FormName returns the name parameter if p has a Content-Disposition
@@ -126,7 +129,6 @@ func newPart(mr *Reader) (*Part, error) {
bp := &Part{
Header: make(map[string][]string),
mr: mr,
- buffer: new(bytes.Buffer),
}
if err := bp.populateHeaders(); err != nil {
return nil, err
@@ -161,65 +163,118 @@ type partReader struct {
p *Part
}
-func (pr partReader) Read(d []byte) (n int, err error) {
+func (pr partReader) Read(d []byte) (int, error) {
p := pr.p
- defer func() {
- p.bytesRead += n
- }()
- if p.buffer.Len() >= len(d) {
- // Internal buffer of unconsumed data is large enough for
- // the read request. No need to parse more at the moment.
- return p.buffer.Read(d)
+ br := p.mr.bufReader
+
+ // Read into buffer until we identify some data to return,
+ // or we find a reason to stop (boundary or read error).
+ for p.n == 0 && p.err == nil {
+ peek, _ := br.Peek(br.Buffered())
+ p.n, p.err = scanUntilBoundary(peek, p.mr.dashBoundary, p.mr.nlDashBoundary, p.total, p.readErr)
+ if p.n == 0 && p.err == nil {
+ // Force buffered I/O to read more into buffer.
+ _, p.readErr = br.Peek(len(peek) + 1)
+ if p.readErr == io.EOF {
+ p.readErr = io.ErrUnexpectedEOF
+ }
+ }
}
- peek, err := p.mr.bufReader.Peek(peekBufferSize) // TODO(bradfitz): add buffer size accessor
-
- // Look for an immediate empty part without a leading \r\n
- // before the boundary separator. Some MIME code makes empty
- // parts like this. Most browsers, however, write the \r\n
- // before the subsequent boundary even for empty parts and
- // won't hit this path.
- if p.bytesRead == 0 && p.mr.peekBufferIsEmptyPart(peek) {
- return 0, io.EOF
+
+ // Read out from "data to return" part of buffer.
+ if p.n == 0 {
+ return 0, p.err
}
- unexpectedEOF := err == io.EOF
- if err != nil && !unexpectedEOF {
- return 0, fmt.Errorf("multipart: Part Read: %v", err)
+ n := len(d)
+ if n > p.n {
+ n = p.n
}
- if peek == nil {
- panic("nil peek buf")
+ n, _ = br.Read(d[:n])
+ p.total += int64(n)
+ p.n -= n
+ if p.n == 0 {
+ return n, p.err
}
- // Search the peek buffer for "\r\n--boundary". If found,
- // consume everything up to the boundary. If not, consume only
- // as much of the peek buffer as cannot hold the boundary
- // string.
- nCopy := 0
- foundBoundary := false
- if idx, isEnd := p.mr.peekBufferSeparatorIndex(peek); idx != -1 {
- nCopy = idx
- foundBoundary = isEnd
- if !isEnd && nCopy == 0 {
- nCopy = 1 // make some progress.
+ return n, nil
+}
+
+// scanUntilBoundary scans buf to identify how much of it can be safely
+// returned as part of the Part body.
+// dashBoundary is "--boundary".
+// nlDashBoundary is "\r\n--boundary" or "\n--boundary", depending on what mode we are in.
+// The comments below (and the name) assume "\n--boundary", but either is accepted.
+// total is the number of bytes read out so far. If total == 0, then a leading "--boundary" is recognized.
+// readErr is the read error, if any, that followed reading the bytes in buf.
+// scanUntilBoundary returns the number of data bytes from buf that can be
+// returned as part of the Part body and also the error to return (if any)
+// once those data bytes are done.
+func scanUntilBoundary(buf, dashBoundary, nlDashBoundary []byte, total int64, readErr error) (int, error) {
+ if total == 0 {
+ // At beginning of body, allow dashBoundary.
+ if bytes.HasPrefix(buf, dashBoundary) {
+ switch matchAfterPrefix(buf, dashBoundary, readErr) {
+ case -1:
+ return len(dashBoundary), nil
+ case 0:
+ return 0, nil
+ case +1:
+ return 0, io.EOF
+ }
+ }
+ if bytes.HasPrefix(dashBoundary, buf) {
+ return 0, readErr
}
- } else if safeCount := len(peek) - len(p.mr.nlDashBoundary); safeCount > 0 {
- nCopy = safeCount
- } else if unexpectedEOF {
- // If we've run out of peek buffer and the boundary
- // wasn't found (and can't possibly fit), we must have
- // hit the end of the file unexpectedly.
- return 0, io.ErrUnexpectedEOF
}
- if nCopy > 0 {
- if _, err := io.CopyN(p.buffer, p.mr.bufReader, int64(nCopy)); err != nil {
- return 0, err
+
+ // Search for "\n--boundary".
+ if i := bytes.Index(buf, nlDashBoundary); i >= 0 {
+ switch matchAfterPrefix(buf[i:], nlDashBoundary, readErr) {
+ case -1:
+ return i + len(nlDashBoundary), nil
+ case 0:
+ return i, nil
+ case +1:
+ return i, io.EOF
+ }
+ }
+ if bytes.HasPrefix(nlDashBoundary, buf) {
+ return 0, readErr
+ }
+
+ // Otherwise, anything up to the final \n is not part of the boundary
+ // and so must be part of the body.
+ // Also if the section from the final \n onward is not a prefix of the boundary,
+ // it too must be part of the body.
+ i := bytes.LastIndexByte(buf, nlDashBoundary[0])
+ if i >= 0 && bytes.HasPrefix(nlDashBoundary, buf[i:]) {
+ return i, nil
+ }
+ return len(buf), readErr
+}
+
+// matchAfterPrefix checks whether buf should be considered to match the boundary.
+// The prefix is "--boundary" or "\r\n--boundary" or "\n--boundary",
+// and the caller has verified already that bytes.HasPrefix(buf, prefix) is true.
+//
+// matchAfterPrefix returns +1 if the buffer does match the boundary,
+// meaning the prefix is followed by a dash, space, tab, cr, nl, or end of input.
+// It returns -1 if the buffer definitely does NOT match the boundary,
+// meaning the prefix is followed by some other character.
+// For example, "--foobar" does not match "--foo".
+// It returns 0 more input needs to be read to make the decision,
+// meaning that len(buf) == len(prefix) and readErr == nil.
+func matchAfterPrefix(buf, prefix []byte, readErr error) int {
+ if len(buf) == len(prefix) {
+ if readErr != nil {
+ return +1
}
+ return 0
}
- n, err = p.buffer.Read(d)
- if err == io.EOF && !foundBoundary {
- // If the boundary hasn't been reached there's more to
- // read, so don't pass through an EOF from the buffer
- err = nil
+ c := buf[len(prefix)]
+ if c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '-' {
+ return +1
}
- return
+ return -1
}
func (p *Part) Close() error {
@@ -337,64 +392,6 @@ func (mr *Reader) isBoundaryDelimiterLine(line []byte) (ret bool) {
return bytes.Equal(rest, mr.nl)
}
-// peekBufferIsEmptyPart reports whether the provided peek-ahead
-// buffer represents an empty part. It is called only if we've not
-// already read any bytes in this part and checks for the case of MIME
-// software not writing the \r\n on empty parts. Some does, some
-// doesn't.
-//
-// This checks that what follows the "--boundary" is actually the end
-// ("--boundary--" with optional whitespace) or optional whitespace
-// and then a newline, so we don't catch "--boundaryFAKE", in which
-// case the whole line is part of the data.
-func (mr *Reader) peekBufferIsEmptyPart(peek []byte) bool {
- // End of parts case.
- // Test whether peek matches `^--boundary--[ \t]*(?:\r\n|$)`
- if bytes.HasPrefix(peek, mr.dashBoundaryDash) {
- rest := peek[len(mr.dashBoundaryDash):]
- rest = skipLWSPChar(rest)
- return bytes.HasPrefix(rest, mr.nl) || len(rest) == 0
- }
- if !bytes.HasPrefix(peek, mr.dashBoundary) {
- return false
- }
- // Test whether rest matches `^[ \t]*\r\n`)
- rest := peek[len(mr.dashBoundary):]
- rest = skipLWSPChar(rest)
- return bytes.HasPrefix(rest, mr.nl)
-}
-
-// peekBufferSeparatorIndex returns the index of mr.nlDashBoundary in
-// peek and whether it is a real boundary (and not a prefix of an
-// unrelated separator). To be the end, the peek buffer must contain a
-// newline after the boundary or contain the ending boundary (--separator--).
-func (mr *Reader) peekBufferSeparatorIndex(peek []byte) (idx int, isEnd bool) {
- idx = bytes.Index(peek, mr.nlDashBoundary)
- if idx == -1 {
- return
- }
-
- peek = peek[idx+len(mr.nlDashBoundary):]
- if len(peek) == 0 || len(peek) == 1 && peek[0] == '-' {
- return idx, false
- }
- if len(peek) > 1 && peek[0] == '-' && peek[1] == '-' {
- return idx, true
- }
- peek = skipLWSPChar(peek)
- // Don't have a complete line after the peek.
- if bytes.IndexByte(peek, '\n') == -1 {
- return idx, false
- }
- if len(peek) > 0 && peek[0] == '\n' {
- return idx, true
- }
- if len(peek) > 1 && peek[0] == '\r' && peek[1] == '\n' {
- return idx, true
- }
- return idx, false
-}
-
// skipLWSPChar returns b with leading spaces and tabs removed.
// RFC 822 defines:
// LWSP-char = SPACE / HTAB
diff --git a/libgo/go/mime/multipart/multipart_test.go b/libgo/go/mime/multipart/multipart_test.go
index 82a7f86e67c..7fbee90ac38 100644
--- a/libgo/go/mime/multipart/multipart_test.go
+++ b/libgo/go/mime/multipart/multipart_test.go
@@ -125,6 +125,7 @@ func TestMultipartSlowInput(t *testing.T) {
}
func testMultipart(t *testing.T, r io.Reader, onlyNewlines bool) {
+ t.Parallel()
reader := NewReader(r, "MyBoundary")
buf := new(bytes.Buffer)
@@ -323,6 +324,73 @@ func (s *slowReader) Read(p []byte) (int, error) {
return s.r.Read(p[:1])
}
+type sentinelReader struct {
+ // done is closed when this reader is read from.
+ done chan struct{}
+}
+
+func (s *sentinelReader) Read([]byte) (int, error) {
+ if s.done != nil {
+ close(s.done)
+ s.done = nil
+ }
+ return 0, io.EOF
+}
+
+// TestMultipartStreamReadahead tests that PartReader does not block
+// on reading past the end of a part, ensuring that it can be used on
+// a stream like multipart/x-mixed-replace. See golang.org/issue/15431
+func TestMultipartStreamReadahead(t *testing.T) {
+ testBody1 := `
+This is a multi-part message. This line is ignored.
+--MyBoundary
+foo-bar: baz
+
+Body
+--MyBoundary
+`
+ testBody2 := `foo-bar: bop
+
+Body 2
+--MyBoundary--
+`
+ done1 := make(chan struct{})
+ reader := NewReader(
+ io.MultiReader(
+ strings.NewReader(testBody1),
+ &sentinelReader{done1},
+ strings.NewReader(testBody2)),
+ "MyBoundary")
+
+ var i int
+ readPart := func(hdr textproto.MIMEHeader, body string) {
+ part, err := reader.NextPart()
+ if part == nil || err != nil {
+ t.Fatalf("Part %d: NextPart failed: %v", i, err)
+ }
+
+ if !reflect.DeepEqual(part.Header, hdr) {
+ t.Errorf("Part %d: part.Header = %v, want %v", i, part.Header, hdr)
+ }
+ data, err := ioutil.ReadAll(part)
+ expectEq(t, body, string(data), fmt.Sprintf("Part %d body", i))
+ if err != nil {
+ t.Fatalf("Part %d: ReadAll failed: %v", i, err)
+ }
+ i++
+ }
+
+ readPart(textproto.MIMEHeader{"Foo-Bar": {"baz"}}, "Body")
+
+ select {
+ case <-done1:
+ t.Errorf("Reader read past second boundary")
+ default:
+ }
+
+ readPart(textproto.MIMEHeader{"Foo-Bar": {"bop"}}, "Body 2")
+}
+
func TestLineContinuation(t *testing.T) {
// This body, extracted from an email, contains headers that span multiple
// lines.
@@ -755,6 +823,7 @@ func partsFromReader(r *Reader) ([]headerBody, error) {
}
func TestParseAllSizes(t *testing.T) {
+ t.Parallel()
const maxSize = 5 << 10
var buf bytes.Buffer
body := strings.Repeat("a", maxSize)
diff --git a/libgo/go/mime/quotedprintable/example_test.go b/libgo/go/mime/quotedprintable/example_test.go
new file mode 100644
index 00000000000..0593b049355
--- /dev/null
+++ b/libgo/go/mime/quotedprintable/example_test.go
@@ -0,0 +1,39 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package quotedprintable_test
+
+import (
+ "fmt"
+ "io/ioutil"
+ "mime/quotedprintable"
+ "os"
+ "strings"
+)
+
+func ExampleNewReader() {
+ for _, s := range []string{
+ `=48=65=6C=6C=6F=2C=20=47=6F=70=68=65=72=73=21`,
+ `invalid escape: <b style="font-size: 200%">hello</b>`,
+ "Hello, Gophers! This symbol will be unescaped: =3D and this will be written in =\r\none line.",
+ } {
+ b, err := ioutil.ReadAll(quotedprintable.NewReader(strings.NewReader(s)))
+ fmt.Printf("%s %v\n", b, err)
+ }
+ // Output:
+ // Hello, Gophers! <nil>
+ // invalid escape: <b style="font-size: 200%">hello</b> <nil>
+ // Hello, Gophers! This symbol will be unescaped: = and this will be written in one line. <nil>
+}
+
+func ExampleNewWriter() {
+ w := quotedprintable.NewWriter(os.Stdout)
+ w.Write([]byte("These symbols will be escaped: = \t"))
+ w.Close()
+
+ // Output:
+ // These symbols will be escaped: =3D =09
+}
diff --git a/libgo/go/mime/quotedprintable/reader.go b/libgo/go/mime/quotedprintable/reader.go
index 3bd6833da5f..b1422403430 100644
--- a/libgo/go/mime/quotedprintable/reader.go
+++ b/libgo/go/mime/quotedprintable/reader.go
@@ -74,6 +74,11 @@ func (r *Reader) Read(p []byte) (n int, err error) {
// 1. in addition to "=\r\n", "=\n" is also treated as soft line break.
// 2. it will pass through a '\r' or '\n' not preceded by '=', consistent
// with other broken QP encoders & decoders.
+ // 3. it accepts soft line-break (=) at end of message (issue 15486); i.e.
+ // the final byte read from the underlying reader is allowed to be '=',
+ // and it will be silently ignored.
+ // 4. it takes = as literal = if not followed by two hex digits
+ // but not at end of line (issue 13219).
for len(p) > 0 {
if len(r.line) == 0 {
if r.rerr != nil {
@@ -89,7 +94,8 @@ func (r *Reader) Read(p []byte) (n int, err error) {
if bytes.HasSuffix(r.line, softSuffix) {
rightStripped := wholeLine[len(r.line):]
r.line = r.line[:len(r.line)-1]
- if !bytes.HasPrefix(rightStripped, lf) && !bytes.HasPrefix(rightStripped, crlf) {
+ if !bytes.HasPrefix(rightStripped, lf) && !bytes.HasPrefix(rightStripped, crlf) &&
+ !(len(rightStripped) == 0 && len(r.line) > 0 && r.rerr == io.EOF) {
r.rerr = fmt.Errorf("quotedprintable: invalid bytes after =: %q", rightStripped)
}
} else if hasLF {
@@ -107,6 +113,11 @@ func (r *Reader) Read(p []byte) (n int, err error) {
case b == '=':
b, err = readHexByte(r.line[1:])
if err != nil {
+ if len(r.line) >= 2 && r.line[1] != '\r' && r.line[1] != '\n' {
+ // Take the = as a literal =.
+ b = '='
+ break
+ }
return n, err
}
r.line = r.line[2:] // 2 of the 3; other 1 is done below
diff --git a/libgo/go/mime/quotedprintable/reader_test.go b/libgo/go/mime/quotedprintable/reader_test.go
index e77b2610ec1..ca016f969a4 100644
--- a/libgo/go/mime/quotedprintable/reader_test.go
+++ b/libgo/go/mime/quotedprintable/reader_test.go
@@ -30,7 +30,7 @@ func TestReader(t *testing.T) {
{in: "foo bar=3d", want: "foo bar="}, // lax.
{in: "foo bar=\n", want: "foo bar"},
{in: "foo bar\n", want: "foo bar\n"}, // somewhat lax.
- {in: "foo bar=0", want: "foo bar", err: io.ErrUnexpectedEOF},
+ {in: "foo bar=0", want: "foo bar=0"}, // lax
{in: "foo bar=0D=0A", want: "foo bar\r\n"},
{in: " A B \r\n C ", want: " A B\r\n C"},
{in: " A B =\r\n C ", want: " A B C"},
@@ -58,6 +58,9 @@ func TestReader(t *testing.T) {
{in: "foo=\nbar", want: "foobar"},
{in: "foo=\rbar", want: "foo", err: "quotedprintable: invalid hex byte 0x0d"},
{in: "foo=\r\r\r \nbar", want: "foo", err: `quotedprintable: invalid bytes after =: "\r\r\r \n"`},
+ // Issue 15486, accept trailing soft line-break at end of input.
+ {in: "foo=", want: "foo"},
+ {in: "=", want: "", err: `quotedprintable: invalid bytes after =: ""`},
// Example from RFC 2045:
{in: "Now's the time =\n" + "for all folk to come=\n" + " to the aid of their country.",
@@ -191,13 +194,10 @@ func TestExhaustive(t *testing.T) {
}
sort.Strings(outcomes)
got := strings.Join(outcomes, "\n")
- want := `OK: 21576
-invalid bytes after =: 3397
-quotedprintable: invalid hex byte 0x0a: 1400
-quotedprintable: invalid hex byte 0x0d: 2700
-quotedprintable: invalid hex byte 0x20: 2490
-quotedprintable: invalid hex byte 0x3d: 440
-unexpected EOF: 3122`
+ want := `OK: 28934
+invalid bytes after =: 3949
+quotedprintable: invalid hex byte 0x0d: 2048
+unexpected EOF: 194`
if got != want {
t.Errorf("Got:\n%s\nWant:\n%s", got, want)
}
diff --git a/libgo/go/net/addrselect.go b/libgo/go/net/addrselect.go
index 0b9d160fd43..1ab9fc53261 100644
--- a/libgo/go/net/addrselect.go
+++ b/libgo/go/net/addrselect.go
@@ -188,33 +188,17 @@ func (s *byRFC6724) Less(i, j int) bool {
// Rule 9: Use longest matching prefix.
// When DA and DB belong to the same address family (both are IPv6 or
- // both are IPv4): If CommonPrefixLen(Source(DA), DA) >
+ // both are IPv4 [but see below]): If CommonPrefixLen(Source(DA), DA) >
// CommonPrefixLen(Source(DB), DB), then prefer DA. Similarly, if
// CommonPrefixLen(Source(DA), DA) < CommonPrefixLen(Source(DB), DB),
// then prefer DB.
- da4 := DA.To4() != nil
- db4 := DB.To4() != nil
- if da4 == db4 {
+ //
+ // However, applying this rule to IPv4 addresses causes
+ // problems (see issues 13283 and 18518), so limit to IPv6.
+ if DA.To4() == nil && DB.To4() == nil {
commonA := commonPrefixLen(SourceDA, DA)
commonB := commonPrefixLen(SourceDB, DB)
- // CommonPrefixLen doesn't really make sense for IPv4, and even
- // causes problems for common load balancing practices
- // (e.g., https://golang.org/issue/13283). Glibc instead only
- // uses CommonPrefixLen for IPv4 when the source and destination
- // addresses are on the same subnet, but that requires extra
- // work to find the netmask for our source addresses. As a
- // simpler heuristic, we limit its use to when the source and
- // destination belong to the same special purpose block.
- if da4 {
- if !sameIPv4SpecialPurposeBlock(SourceDA, DA) {
- commonA = 0
- }
- if !sameIPv4SpecialPurposeBlock(SourceDB, DB) {
- commonB = 0
- }
- }
-
if commonA > commonB {
return preferDA
}
@@ -404,28 +388,3 @@ func commonPrefixLen(a, b IP) (cpl int) {
}
return
}
-
-// sameIPv4SpecialPurposeBlock reports whether a and b belong to the same
-// address block reserved by the IANA IPv4 Special-Purpose Address Registry:
-// http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
-func sameIPv4SpecialPurposeBlock(a, b IP) bool {
- a, b = a.To4(), b.To4()
- if a == nil || b == nil || a[0] != b[0] {
- return false
- }
- // IANA defines more special-purpose blocks, but these are the only
- // ones likely to be relevant to typical Go systems.
- switch a[0] {
- case 10: // 10.0.0.0/8: Private-Use
- return true
- case 127: // 127.0.0.0/8: Loopback
- return true
- case 169: // 169.254.0.0/16: Link Local
- return a[1] == 254 && b[1] == 254
- case 172: // 172.16.0.0/12: Private-Use
- return a[1]&0xf0 == 16 && b[1]&0xf0 == 16
- case 192: // 192.168.0.0/16: Private-Use
- return a[1] == 168 && b[1] == 168
- }
- return false
-}
diff --git a/libgo/go/net/addrselect_test.go b/libgo/go/net/addrselect_test.go
index 80aa4eb195b..d6e0e63c3b5 100644
--- a/libgo/go/net/addrselect_test.go
+++ b/libgo/go/net/addrselect_test.go
@@ -117,27 +117,6 @@ func TestSortByRFC6724(t *testing.T) {
},
reverse: false,
},
-
- // Prefer longer common prefixes, but only for IPv4 address
- // pairs in the same special-purpose block.
- {
- in: []IPAddr{
- {IP: ParseIP("1.2.3.4")},
- {IP: ParseIP("10.55.0.1")},
- {IP: ParseIP("10.66.0.1")},
- },
- srcs: []IP{
- ParseIP("1.2.3.5"),
- ParseIP("10.66.1.2"),
- ParseIP("10.66.1.2"),
- },
- want: []IPAddr{
- {IP: ParseIP("10.66.0.1")},
- {IP: ParseIP("10.55.0.1")},
- {IP: ParseIP("1.2.3.4")},
- },
- reverse: true,
- },
}
for i, tt := range tests {
inCopy := make([]IPAddr, len(tt.in))
@@ -268,67 +247,3 @@ func TestRFC6724CommonPrefixLength(t *testing.T) {
}
}
-
-func mustParseCIDRs(t *testing.T, blocks ...string) []*IPNet {
- res := make([]*IPNet, len(blocks))
- for i, block := range blocks {
- var err error
- _, res[i], err = ParseCIDR(block)
- if err != nil {
- t.Fatalf("ParseCIDR(%s) failed: %v", block, err)
- }
- }
- return res
-}
-
-func TestSameIPv4SpecialPurposeBlock(t *testing.T) {
- blocks := mustParseCIDRs(t,
- "10.0.0.0/8",
- "127.0.0.0/8",
- "169.254.0.0/16",
- "172.16.0.0/12",
- "192.168.0.0/16",
- )
-
- addrs := []struct {
- ip IP
- block int // index or -1
- }{
- {IP{1, 2, 3, 4}, -1},
- {IP{2, 3, 4, 5}, -1},
- {IP{10, 2, 3, 4}, 0},
- {IP{10, 6, 7, 8}, 0},
- {IP{127, 0, 0, 1}, 1},
- {IP{127, 255, 255, 255}, 1},
- {IP{169, 254, 77, 99}, 2},
- {IP{169, 254, 44, 22}, 2},
- {IP{169, 255, 0, 1}, -1},
- {IP{172, 15, 5, 6}, -1},
- {IP{172, 16, 32, 41}, 3},
- {IP{172, 31, 128, 9}, 3},
- {IP{172, 32, 88, 100}, -1},
- {IP{192, 168, 1, 1}, 4},
- {IP{192, 168, 128, 42}, 4},
- {IP{192, 169, 1, 1}, -1},
- }
-
- for i, addr := range addrs {
- for j, block := range blocks {
- got := block.Contains(addr.ip)
- want := addr.block == j
- if got != want {
- t.Errorf("%d/%d. %s.Contains(%s): got %v, want %v", i, j, block, addr.ip, got, want)
- }
- }
- }
-
- for i, addr1 := range addrs {
- for j, addr2 := range addrs {
- got := sameIPv4SpecialPurposeBlock(addr1.ip, addr2.ip)
- want := addr1.block >= 0 && addr1.block == addr2.block
- if got != want {
- t.Errorf("%d/%d. sameIPv4SpecialPurposeBlock(%s, %s): got %v, want %v", i, j, addr1.ip, addr2.ip, got, want)
- }
- }
- }
-}
diff --git a/libgo/go/net/cgo_unix.go b/libgo/go/net/cgo_unix.go
index 525c63c18d2..a90aaa904ed 100644
--- a/libgo/go/net/cgo_unix.go
+++ b/libgo/go/net/cgo_unix.go
@@ -114,7 +114,15 @@ func cgoLookupPort(ctx context.Context, network, service string) (port int, err
}
func cgoLookupServicePort(hints *syscall.Addrinfo, network, service string) (port int, err error) {
- s := syscall.StringBytePtr(service)
+ s, err := syscall.BytePtrFromString(service)
+ if err != nil {
+ return 0, err
+ }
+ // Lowercase the service name in the memory passed to C.
+ for i := 0; i < len(service); i++ {
+ bp := (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(s)) + uintptr(i)))
+ *bp = lowerASCII(*bp)
+ }
var res *syscall.Addrinfo
syscall.Entersyscall()
gerrno := libc_getaddrinfo(nil, s, hints, &res)
diff --git a/libgo/go/net/conf.go b/libgo/go/net/conf.go
index eb729167f5b..c10aafe63ab 100644
--- a/libgo/go/net/conf.go
+++ b/libgo/go/net/conf.go
@@ -179,8 +179,6 @@ func (c *conf) hostLookupOrder(hostname string) (ret hostLookupOrder) {
}
}
- hasDot := byteIndex(hostname, '.') != -1
-
// Canonicalize the hostname by removing any trailing dot.
if stringsHasSuffix(hostname, ".") {
hostname = hostname[:len(hostname)-1]
@@ -220,10 +218,14 @@ func (c *conf) hostLookupOrder(hostname string) (ret hostLookupOrder) {
var first string
for _, src := range srcs {
if src.source == "myhostname" {
- if hostname == "" || hasDot {
- continue
+ if isLocalhost(hostname) || isGateway(hostname) {
+ return fallbackOrder
}
- return fallbackOrder
+ hn, err := getHostname()
+ if err != nil || stringsEqualFold(hostname, hn) {
+ return fallbackOrder
+ }
+ continue
}
if src.source == "files" || src.source == "dns" {
if !src.standardCriteria() {
@@ -293,7 +295,7 @@ func goDebugNetDNS() (dnsMode string, debugLevel int) {
return
}
if '0' <= s[0] && s[0] <= '9' {
- debugLevel, _, _ = dtoi(s, 0)
+ debugLevel, _, _ = dtoi(s)
} else {
dnsMode = s
}
@@ -306,3 +308,15 @@ func goDebugNetDNS() (dnsMode string, debugLevel int) {
parsePart(goDebug)
return
}
+
+// isLocalhost reports whether h should be considered a "localhost"
+// name for the myhostname NSS module.
+func isLocalhost(h string) bool {
+ return stringsEqualFold(h, "localhost") || stringsEqualFold(h, "localhost.localdomain") || stringsHasSuffixFold(h, ".localhost") || stringsHasSuffixFold(h, ".localhost.localdomain")
+}
+
+// isGateway reports whether h should be considered a "gateway"
+// name for the myhostname NSS module.
+func isGateway(h string) bool {
+ return stringsEqualFold(h, "gateway")
+}
diff --git a/libgo/go/net/conf_test.go b/libgo/go/net/conf_test.go
index ec8814b845b..17d03f4b5fc 100644
--- a/libgo/go/net/conf_test.go
+++ b/libgo/go/net/conf_test.go
@@ -13,8 +13,9 @@ import (
)
type nssHostTest struct {
- host string
- want hostLookupOrder
+ host string
+ localhost string
+ want hostLookupOrder
}
func nssStr(s string) *nssConf { return parseNSSConf(strings.NewReader(s)) }
@@ -42,8 +43,8 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"foo.local", hostLookupCgo},
- {"google.com", hostLookupCgo},
+ {"foo.local", "myhostname", hostLookupCgo},
+ {"google.com", "myhostname", hostLookupCgo},
},
},
{
@@ -54,7 +55,7 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"x.com", hostLookupDNSFiles},
+ {"x.com", "myhostname", hostLookupDNSFiles},
},
},
{
@@ -65,7 +66,7 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"x.com", hostLookupFilesDNS},
+ {"x.com", "myhostname", hostLookupFilesDNS},
},
},
{
@@ -75,11 +76,11 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"foo.local", hostLookupCgo},
- {"foo.local.", hostLookupCgo},
- {"foo.LOCAL", hostLookupCgo},
- {"foo.LOCAL.", hostLookupCgo},
- {"google.com", hostLookupFilesDNS},
+ {"foo.local", "myhostname", hostLookupCgo},
+ {"foo.local.", "myhostname", hostLookupCgo},
+ {"foo.LOCAL", "myhostname", hostLookupCgo},
+ {"foo.LOCAL.", "myhostname", hostLookupCgo},
+ {"google.com", "myhostname", hostLookupFilesDNS},
},
},
{
@@ -89,7 +90,7 @@ func TestConfHostLookupOrder(t *testing.T) {
nss: nssStr("foo: bar"),
resolv: defaultResolvConf,
},
- hostTests: []nssHostTest{{"google.com", hostLookupFilesDNS}},
+ hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFilesDNS}},
},
// On OpenBSD, no resolv.conf means no DNS.
{
@@ -98,7 +99,7 @@ func TestConfHostLookupOrder(t *testing.T) {
goos: "openbsd",
resolv: defaultResolvConf,
},
- hostTests: []nssHostTest{{"google.com", hostLookupFiles}},
+ hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFiles}},
},
{
name: "solaris_no_nsswitch",
@@ -107,7 +108,7 @@ func TestConfHostLookupOrder(t *testing.T) {
nss: &nssConf{err: os.ErrNotExist},
resolv: defaultResolvConf,
},
- hostTests: []nssHostTest{{"google.com", hostLookupCgo}},
+ hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}},
},
{
name: "openbsd_lookup_bind_file",
@@ -116,8 +117,8 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: &dnsConfig{lookup: []string{"bind", "file"}},
},
hostTests: []nssHostTest{
- {"google.com", hostLookupDNSFiles},
- {"foo.local", hostLookupDNSFiles},
+ {"google.com", "myhostname", hostLookupDNSFiles},
+ {"foo.local", "myhostname", hostLookupDNSFiles},
},
},
{
@@ -126,7 +127,7 @@ func TestConfHostLookupOrder(t *testing.T) {
goos: "openbsd",
resolv: &dnsConfig{lookup: []string{"file", "bind"}},
},
- hostTests: []nssHostTest{{"google.com", hostLookupFilesDNS}},
+ hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFilesDNS}},
},
{
name: "openbsd_lookup_bind",
@@ -134,7 +135,7 @@ func TestConfHostLookupOrder(t *testing.T) {
goos: "openbsd",
resolv: &dnsConfig{lookup: []string{"bind"}},
},
- hostTests: []nssHostTest{{"google.com", hostLookupDNS}},
+ hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupDNS}},
},
{
name: "openbsd_lookup_file",
@@ -142,7 +143,7 @@ func TestConfHostLookupOrder(t *testing.T) {
goos: "openbsd",
resolv: &dnsConfig{lookup: []string{"file"}},
},
- hostTests: []nssHostTest{{"google.com", hostLookupFiles}},
+ hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFiles}},
},
{
name: "openbsd_lookup_yp",
@@ -150,7 +151,7 @@ func TestConfHostLookupOrder(t *testing.T) {
goos: "openbsd",
resolv: &dnsConfig{lookup: []string{"file", "bind", "yp"}},
},
- hostTests: []nssHostTest{{"google.com", hostLookupCgo}},
+ hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}},
},
{
name: "openbsd_lookup_two",
@@ -158,7 +159,7 @@ func TestConfHostLookupOrder(t *testing.T) {
goos: "openbsd",
resolv: &dnsConfig{lookup: []string{"file", "foo"}},
},
- hostTests: []nssHostTest{{"google.com", hostLookupCgo}},
+ hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}},
},
{
name: "openbsd_lookup_empty",
@@ -166,7 +167,7 @@ func TestConfHostLookupOrder(t *testing.T) {
goos: "openbsd",
resolv: &dnsConfig{lookup: nil},
},
- hostTests: []nssHostTest{{"google.com", hostLookupDNSFiles}},
+ hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupDNSFiles}},
},
// glibc lacking an nsswitch.conf, per
// http://www.gnu.org/software/libc/manual/html_node/Notes-on-NSS-Configuration-File.html
@@ -177,7 +178,7 @@ func TestConfHostLookupOrder(t *testing.T) {
nss: &nssConf{err: os.ErrNotExist},
resolv: defaultResolvConf,
},
- hostTests: []nssHostTest{{"google.com", hostLookupDNSFiles}},
+ hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupDNSFiles}},
},
{
name: "files_mdns_dns",
@@ -186,8 +187,8 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"x.com", hostLookupFilesDNS},
- {"x.local", hostLookupCgo},
+ {"x.com", "myhostname", hostLookupFilesDNS},
+ {"x.local", "myhostname", hostLookupCgo},
},
},
{
@@ -197,9 +198,9 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"x.com", hostLookupDNS},
- {"x\\.com", hostLookupCgo}, // punt on weird glibc escape
- {"foo.com%en0", hostLookupCgo}, // and IPv6 zones
+ {"x.com", "myhostname", hostLookupDNS},
+ {"x\\.com", "myhostname", hostLookupCgo}, // punt on weird glibc escape
+ {"foo.com%en0", "myhostname", hostLookupCgo}, // and IPv6 zones
},
},
{
@@ -210,8 +211,8 @@ func TestConfHostLookupOrder(t *testing.T) {
hasMDNSAllow: true,
},
hostTests: []nssHostTest{
- {"x.com", hostLookupCgo},
- {"x.local", hostLookupCgo},
+ {"x.com", "myhostname", hostLookupCgo},
+ {"x.local", "myhostname", hostLookupCgo},
},
},
{
@@ -221,9 +222,9 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"x.com", hostLookupFilesDNS},
- {"x", hostLookupFilesDNS},
- {"x.local", hostLookupCgo},
+ {"x.com", "myhostname", hostLookupFilesDNS},
+ {"x", "myhostname", hostLookupFilesDNS},
+ {"x.local", "myhostname", hostLookupCgo},
},
},
{
@@ -233,9 +234,9 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"x.com", hostLookupDNSFiles},
- {"x", hostLookupDNSFiles},
- {"x.local", hostLookupCgo},
+ {"x.com", "myhostname", hostLookupDNSFiles},
+ {"x", "myhostname", hostLookupDNSFiles},
+ {"x.local", "myhostname", hostLookupCgo},
},
},
{
@@ -245,7 +246,7 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"x.com", hostLookupCgo},
+ {"x.com", "myhostname", hostLookupCgo},
},
},
{
@@ -255,9 +256,23 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"x.com", hostLookupFilesDNS},
- {"somehostname", hostLookupCgo},
- {"", hostLookupFilesDNS}, // Issue 13623
+ {"x.com", "myhostname", hostLookupFilesDNS},
+ {"myhostname", "myhostname", hostLookupCgo},
+ {"myHostname", "myhostname", hostLookupCgo},
+ {"myhostname.dot", "myhostname.dot", hostLookupCgo},
+ {"myHostname.dot", "myhostname.dot", hostLookupCgo},
+ {"gateway", "myhostname", hostLookupCgo},
+ {"Gateway", "myhostname", hostLookupCgo},
+ {"localhost", "myhostname", hostLookupCgo},
+ {"Localhost", "myhostname", hostLookupCgo},
+ {"anything.localhost", "myhostname", hostLookupCgo},
+ {"Anything.localhost", "myhostname", hostLookupCgo},
+ {"localhost.localdomain", "myhostname", hostLookupCgo},
+ {"Localhost.Localdomain", "myhostname", hostLookupCgo},
+ {"anything.localhost.localdomain", "myhostname", hostLookupCgo},
+ {"Anything.Localhost.Localdomain", "myhostname", hostLookupCgo},
+ {"somehostname", "myhostname", hostLookupFilesDNS},
+ {"", "myhostname", hostLookupFilesDNS}, // Issue 13623
},
},
{
@@ -267,8 +282,9 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"x.com", hostLookupFilesDNS},
- {"somehostname", hostLookupCgo},
+ {"x.com", "myhostname", hostLookupFilesDNS},
+ {"somehostname", "myhostname", hostLookupFilesDNS},
+ {"myhostname", "myhostname", hostLookupCgo},
},
},
// Debian Squeeze is just "dns,files", but lists all
@@ -282,8 +298,8 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"x.com", hostLookupDNSFiles},
- {"somehostname", hostLookupDNSFiles},
+ {"x.com", "myhostname", hostLookupDNSFiles},
+ {"somehostname", "myhostname", hostLookupDNSFiles},
},
},
{
@@ -292,7 +308,7 @@ func TestConfHostLookupOrder(t *testing.T) {
nss: nssStr("foo: bar"),
resolv: &dnsConfig{servers: defaultNS, ndots: 1, timeout: 5, attempts: 2, unknownOpt: true},
},
- hostTests: []nssHostTest{{"google.com", hostLookupCgo}},
+ hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}},
},
// Android should always use cgo.
{
@@ -303,12 +319,18 @@ func TestConfHostLookupOrder(t *testing.T) {
resolv: defaultResolvConf,
},
hostTests: []nssHostTest{
- {"x.com", hostLookupCgo},
+ {"x.com", "myhostname", hostLookupCgo},
},
},
}
+
+ origGetHostname := getHostname
+ defer func() { getHostname = origGetHostname }()
+
for _, tt := range tests {
for _, ht := range tt.hostTests {
+ getHostname = func() (string, error) { return ht.localhost, nil }
+
gotOrder := tt.c.hostLookupOrder(ht.host)
if gotOrder != ht.want {
t.Errorf("%s: hostLookupOrder(%q) = %v; want %v", tt.name, ht.host, gotOrder, ht.want)
diff --git a/libgo/go/net/dial.go b/libgo/go/net/dial.go
index 55edb433953..50bba5a49e4 100644
--- a/libgo/go/net/dial.go
+++ b/libgo/go/net/dial.go
@@ -59,6 +59,9 @@ type Dialer struct {
// that do not support keep-alives ignore this field.
KeepAlive time.Duration
+ // Resolver optionally specifies an alternate resolver to use.
+ Resolver *Resolver
+
// Cancel is an optional channel whose closure indicates that
// the dial should be canceled. Not all types of dials support
// cancelation.
@@ -92,6 +95,13 @@ func (d *Dialer) deadline(ctx context.Context, now time.Time) (earliest time.Tim
return minNonzeroTime(earliest, d.Deadline)
}
+func (d *Dialer) resolver() *Resolver {
+ if d.Resolver != nil {
+ return d.Resolver
+ }
+ return DefaultResolver
+}
+
// partialDeadline returns the deadline to use for a single address,
// when multiple addresses are pending.
func partialDeadline(now, deadline time.Time, addrsRemaining int) (time.Time, error) {
@@ -141,7 +151,7 @@ func parseNetwork(ctx context.Context, net string) (afnet string, proto int, err
switch afnet {
case "ip", "ip4", "ip6":
protostr := net[i+1:]
- proto, i, ok := dtoi(protostr, 0)
+ proto, i, ok := dtoi(protostr)
if !ok || i != len(protostr) {
proto, err = lookupProtocol(ctx, protostr)
if err != nil {
@@ -153,10 +163,10 @@ func parseNetwork(ctx context.Context, net string) (afnet string, proto int, err
return "", 0, UnknownNetworkError(net)
}
-// resolverAddrList resolves addr using hint and returns a list of
+// resolveAddrList resolves addr using hint and returns a list of
// addresses. The result contains at least one address when error is
// nil.
-func resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) (addrList, error) {
+func (r *Resolver) resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) (addrList, error) {
afnet, _, err := parseNetwork(ctx, network)
if err != nil {
return nil, err
@@ -166,7 +176,6 @@ func resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) (
}
switch afnet {
case "unix", "unixgram", "unixpacket":
- // TODO(bradfitz): push down context
addr, err := ResolveUnixAddr(afnet, addr)
if err != nil {
return nil, err
@@ -176,7 +185,7 @@ func resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) (
}
return addrList{addr}, nil
}
- addrs, err := internetAddrList(ctx, afnet, addr)
+ addrs, err := r.internetAddrList(ctx, afnet, addr)
if err != nil || op != "dial" || hint == nil {
return addrs, err
}
@@ -221,7 +230,7 @@ func resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) (
}
}
if len(naddrs) == 0 {
- return nil, errNoSuitableAddress
+ return nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: hint.String()}
}
return naddrs, nil
}
@@ -256,6 +265,9 @@ func resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) (
// Dial("ip6:ipv6-icmp", "2001:db8::1")
//
// For Unix networks, the address must be a file system path.
+//
+// If the host is resolved to multiple addresses,
+// Dial will try each address in order until one succeeds.
func Dial(network, address string) (Conn, error) {
var d Dialer
return d.Dial(network, address)
@@ -290,6 +302,14 @@ func (d *Dialer) Dial(network, address string) (Conn, error) {
// connected, any expiration of the context will not affect the
// connection.
//
+// When using TCP, and the host in the address parameter resolves to multiple
+// network addresses, any dial timeout (from d.Timeout or ctx) is spread
+// over each consecutive dial, such that each is given an appropriate
+// fraction of the time to connect.
+// For example, if a host has 4 IP addresses and the timeout is 1 minute,
+// the connect to each single address will be given 15 seconds to complete
+// before trying the next one.
+//
// See func Dial for a description of the network and address
// parameters.
func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn, error) {
@@ -326,7 +346,7 @@ func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn
resolveCtx = context.WithValue(resolveCtx, nettrace.TraceKey{}, &shadow)
}
- addrs, err := resolveAddrList(resolveCtx, "dial", network, address, d.LocalAddr)
+ addrs, err := d.resolver().resolveAddrList(resolveCtx, "dial", network, address, d.LocalAddr)
if err != nil {
return nil, &OpError{Op: "dial", Net: network, Source: nil, Addr: nil, Err: err}
}
@@ -524,8 +544,11 @@ func dialSingle(ctx context.Context, dp *dialParam, ra Addr) (c Conn, err error)
// If host is omitted, as in ":8080", Listen listens on all available interfaces
// instead of just the interface with the given host address.
// See Dial for more details about address syntax.
+//
+// Listening on a hostname is not recommended because this creates a socket
+// for at most one of its IP addresses.
func Listen(net, laddr string) (Listener, error) {
- addrs, err := resolveAddrList(context.Background(), "listen", net, laddr, nil)
+ addrs, err := DefaultResolver.resolveAddrList(context.Background(), "listen", net, laddr, nil)
if err != nil {
return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: nil, Err: err}
}
@@ -551,8 +574,11 @@ func Listen(net, laddr string) (Listener, error) {
// If host is omitted, as in ":8080", ListenPacket listens on all available interfaces
// instead of just the interface with the given host address.
// See Dial for the syntax of laddr.
+//
+// Listening on a hostname is not recommended because this creates a socket
+// for at most one of its IP addresses.
func ListenPacket(net, laddr string) (PacketConn, error) {
- addrs, err := resolveAddrList(context.Background(), "listen", net, laddr, nil)
+ addrs, err := DefaultResolver.resolveAddrList(context.Background(), "listen", net, laddr, nil)
if err != nil {
return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: nil, Err: err}
}
diff --git a/libgo/go/net/dial_test.go b/libgo/go/net/dial_test.go
index 8b21e6b0886..9919d72ce3b 100644
--- a/libgo/go/net/dial_test.go
+++ b/libgo/go/net/dial_test.go
@@ -55,6 +55,23 @@ func TestProhibitionaryDialArg(t *testing.T) {
}
}
+func TestDialLocal(t *testing.T) {
+ ln, err := newLocalListener("tcp")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln.Close()
+ _, port, err := SplitHostPort(ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ c, err := Dial("tcp", JoinHostPort("", port))
+ if err != nil {
+ t.Fatal(err)
+ }
+ c.Close()
+}
+
func TestDialTimeoutFDLeak(t *testing.T) {
switch runtime.GOOS {
case "plan9":
@@ -125,6 +142,8 @@ func TestDialerDualStackFDLeak(t *testing.T) {
t.Skipf("%s does not have full support of socktest", runtime.GOOS)
case "windows":
t.Skipf("not implemented a way to cancel dial racers in TCP SYN-SENT state on %s", runtime.GOOS)
+ case "openbsd":
+ testenv.SkipFlaky(t, 15157)
}
if !supportsIPv4 || !supportsIPv6 {
t.Skip("both IPv4 and IPv6 are required")
diff --git a/libgo/go/net/dnsclient.go b/libgo/go/net/dnsclient.go
index f1835b8c060..2ab5639d623 100644
--- a/libgo/go/net/dnsclient.go
+++ b/libgo/go/net/dnsclient.go
@@ -113,12 +113,20 @@ func equalASCIILabel(x, y string) bool {
return true
}
+// isDomainName checks if a string is a presentation-format domain name
+// (currently restricted to hostname-compatible "preferred name" LDH labels and
+// SRV-like "underscore labels"; see golang.org/issue/12421).
func isDomainName(s string) bool {
// See RFC 1035, RFC 3696.
- if len(s) == 0 {
- return false
- }
- if len(s) > 255 {
+ // Presentation format has dots before every label except the first, and the
+ // terminal empty label is optional here because we assume fully-qualified
+ // (absolute) input. We must therefore reserve space for the first and last
+ // labels' length octets in wire format, where they are necessary and the
+ // maximum total length is 255.
+ // So our _effective_ maximum is 253, but 254 is not rejected if the last
+ // character is a dot.
+ l := len(s)
+ if l == 0 || l > 254 || l == 254 && s[l-1] != '.' {
return false
}
diff --git a/libgo/go/net/dnsclient_unix.go b/libgo/go/net/dnsclient_unix.go
index b5b6ffb1c50..4dd4e16b0fd 100644
--- a/libgo/go/net/dnsclient_unix.go
+++ b/libgo/go/net/dnsclient_unix.go
@@ -125,7 +125,7 @@ func (d *Dialer) dialDNS(ctx context.Context, network, server string) (dnsConn,
// Calling Dial here is scary -- we have to be sure not to
// dial a name that will require a DNS lookup, or Dial will
// call back here to translate it. The DNS config parser has
- // already checked that all the cfg.servers[i] are IP
+ // already checked that all the cfg.servers are IP
// addresses, which Dial will use without a DNS lookup.
c, err := d.DialContext(ctx, network, server)
if err != nil {
@@ -182,13 +182,14 @@ func exchange(ctx context.Context, server, name string, qtype uint16, timeout ti
// Do a lookup for a single name, which must be rooted
// (otherwise answer will not find the answers).
func tryOneName(ctx context.Context, cfg *dnsConfig, name string, qtype uint16) (string, []dnsRR, error) {
- if len(cfg.servers) == 0 {
- return "", nil, &DNSError{Err: "no DNS servers", Name: name}
- }
-
var lastErr error
+ serverOffset := cfg.serverOffset()
+ sLen := uint32(len(cfg.servers))
+
for i := 0; i < cfg.attempts; i++ {
- for _, server := range cfg.servers {
+ for j := uint32(0); j < sLen; j++ {
+ server := cfg.servers[(serverOffset+j)%sLen]
+
msg, err := exchange(ctx, server, name, qtype, cfg.timeout)
if err != nil {
lastErr = &DNSError{
@@ -315,7 +316,12 @@ func (conf *resolverConfig) releaseSema() {
func lookup(ctx context.Context, name string, qtype uint16) (cname string, rrs []dnsRR, err error) {
if !isDomainName(name) {
- return "", nil, &DNSError{Err: "invalid domain name", Name: name}
+ // We used to use "invalid domain name" as the error,
+ // but that is a detail of the specific lookup mechanism.
+ // Other lookups might allow broader name syntax
+ // (for example Multicast DNS allows UTF-8; see RFC 6762).
+ // For consistency with libc resolvers, report no such host.
+ return "", nil, &DNSError{Err: errNoSuchHost.Error(), Name: name}
}
resolvConf.tryUpdate("/etc/resolv.conf")
resolvConf.mu.RLock()
@@ -356,14 +362,21 @@ func (conf *dnsConfig) nameList(name string) []string {
return nil
}
+ // Check name length (see isDomainName).
+ l := len(name)
+ rooted := l > 0 && name[l-1] == '.'
+ if l > 254 || l == 254 && rooted {
+ return nil
+ }
+
// If name is rooted (trailing dot), try only that name.
- rooted := len(name) > 0 && name[len(name)-1] == '.'
if rooted {
return []string{name}
}
hasNdots := count(name, '.') >= conf.ndots
name += "."
+ l++
// Build list of search choices.
names := make([]string, 0, 1+len(conf.search))
@@ -371,9 +384,11 @@ func (conf *dnsConfig) nameList(name string) []string {
if hasNdots {
names = append(names, name)
}
- // Try suffixes.
+ // Try suffixes that are not too long (see isDomainName).
for _, suffix := range conf.search {
- names = append(names, name+suffix)
+ if l+len(suffix) <= 254 {
+ names = append(names, name+suffix)
+ }
}
// Try unsuffixed, if not tried first above.
if !hasNdots {
@@ -429,7 +444,7 @@ func goLookupHostOrder(ctx context.Context, name string, order hostLookupOrder)
return
}
}
- ips, err := goLookupIPOrder(ctx, name, order)
+ ips, _, err := goLookupIPCNAMEOrder(ctx, name, order)
if err != nil {
return
}
@@ -455,27 +470,30 @@ func goLookupIPFiles(name string) (addrs []IPAddr) {
// goLookupIP is the native Go implementation of LookupIP.
// The libc versions are in cgo_*.go.
-func goLookupIP(ctx context.Context, name string) (addrs []IPAddr, err error) {
- return goLookupIPOrder(ctx, name, hostLookupFilesDNS)
+func goLookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
+ order := systemConf().hostLookupOrder(host)
+ addrs, _, err = goLookupIPCNAMEOrder(ctx, host, order)
+ return
}
-func goLookupIPOrder(ctx context.Context, name string, order hostLookupOrder) (addrs []IPAddr, err error) {
+func goLookupIPCNAMEOrder(ctx context.Context, name string, order hostLookupOrder) (addrs []IPAddr, cname string, err error) {
if order == hostLookupFilesDNS || order == hostLookupFiles {
addrs = goLookupIPFiles(name)
if len(addrs) > 0 || order == hostLookupFiles {
- return addrs, nil
+ return addrs, name, nil
}
}
if !isDomainName(name) {
- return nil, &DNSError{Err: "invalid domain name", Name: name}
+ // See comment in func lookup above about use of errNoSuchHost.
+ return nil, "", &DNSError{Err: errNoSuchHost.Error(), Name: name}
}
resolvConf.tryUpdate("/etc/resolv.conf")
resolvConf.mu.RLock()
conf := resolvConf.dnsConfig
resolvConf.mu.RUnlock()
type racer struct {
- fqdn string
- rrs []dnsRR
+ cname string
+ rrs []dnsRR
error
}
lane := make(chan racer, 1)
@@ -484,20 +502,23 @@ func goLookupIPOrder(ctx context.Context, name string, order hostLookupOrder) (a
for _, fqdn := range conf.nameList(name) {
for _, qtype := range qtypes {
go func(qtype uint16) {
- _, rrs, err := tryOneName(ctx, conf, fqdn, qtype)
- lane <- racer{fqdn, rrs, err}
+ cname, rrs, err := tryOneName(ctx, conf, fqdn, qtype)
+ lane <- racer{cname, rrs, err}
}(qtype)
}
for range qtypes {
racer := <-lane
if racer.error != nil {
// Prefer error for original name.
- if lastErr == nil || racer.fqdn == name+"." {
+ if lastErr == nil || fqdn == name+"." {
lastErr = racer.error
}
continue
}
addrs = append(addrs, addrRecordList(racer.rrs)...)
+ if cname == "" {
+ cname = racer.cname
+ }
}
if len(addrs) > 0 {
break
@@ -515,24 +536,16 @@ func goLookupIPOrder(ctx context.Context, name string, order hostLookupOrder) (a
addrs = goLookupIPFiles(name)
}
if len(addrs) == 0 && lastErr != nil {
- return nil, lastErr
+ return nil, "", lastErr
}
}
- return addrs, nil
+ return addrs, cname, nil
}
-// goLookupCNAME is the native Go implementation of LookupCNAME.
-// Used only if cgoLookupCNAME refuses to handle the request
-// (that is, only if cgoLookupCNAME is the stub in cgo_stub.go).
-// Normally we let cgo use the C library resolver instead of
-// depending on our lookup code, so that Go and C get the same
-// answers.
-func goLookupCNAME(ctx context.Context, name string) (cname string, err error) {
- _, rrs, err := lookup(ctx, name, dnsTypeCNAME)
- if err != nil {
- return
- }
- cname = rrs[0].(*dnsRR_CNAME).Cname
+// goLookupCNAME is the native Go (non-cgo) implementation of LookupCNAME.
+func goLookupCNAME(ctx context.Context, host string) (cname string, err error) {
+ order := systemConf().hostLookupOrder(host)
+ _, cname, err = goLookupIPCNAMEOrder(ctx, host, order)
return
}
diff --git a/libgo/go/net/dnsclient_unix_test.go b/libgo/go/net/dnsclient_unix_test.go
index 6ebeeaeb8f4..85267bbddc0 100644
--- a/libgo/go/net/dnsclient_unix_test.go
+++ b/libgo/go/net/dnsclient_unix_test.go
@@ -411,7 +411,7 @@ func TestGoLookupIPWithResolverConfig(t *testing.T) {
// We need to take care with errors on both
// DNS message exchange layer and DNS
// transport layer because goLookupIP may fail
- // when the IP connectivty on node under test
+ // when the IP connectivity on node under test
// gets lost during its run.
if err, ok := err.(*DNSError); !ok || tt.error != nil && (err.Name != tt.error.(*DNSError).Name || err.Server != tt.error.(*DNSError).Server || err.IsTimeout != tt.error.(*DNSError).IsTimeout) {
t.Errorf("got %v; want %v", err, tt.error)
@@ -455,14 +455,14 @@ func TestGoLookupIPOrderFallbackToFile(t *testing.T) {
name := fmt.Sprintf("order %v", order)
// First ensure that we get an error when contacting a non-existent host.
- _, err := goLookupIPOrder(context.Background(), "notarealhost", order)
+ _, _, err := goLookupIPCNAMEOrder(context.Background(), "notarealhost", order)
if err == nil {
t.Errorf("%s: expected error while looking up name not in hosts file", name)
continue
}
// Now check that we get an address when the name appears in the hosts file.
- addrs, err := goLookupIPOrder(context.Background(), "thor", order) // entry is in "testdata/hosts"
+ addrs, _, err := goLookupIPCNAMEOrder(context.Background(), "thor", order) // entry is in "testdata/hosts"
if err != nil {
t.Errorf("%s: expected to successfully lookup host entry", name)
continue
@@ -668,12 +668,14 @@ func TestIgnoreDNSForgeries(t *testing.T) {
b := make([]byte, 512)
n, err := s.Read(b)
if err != nil {
- t.Fatal(err)
+ t.Error(err)
+ return
}
msg := &dnsMsg{}
if !msg.Unpack(b[:n]) {
- t.Fatal("invalid DNS query")
+ t.Error("invalid DNS query")
+ return
}
s.Write([]byte("garbage DNS response packet"))
@@ -682,7 +684,8 @@ func TestIgnoreDNSForgeries(t *testing.T) {
msg.id++ // make invalid ID
b, ok := msg.Pack()
if !ok {
- t.Fatal("failed to pack DNS response")
+ t.Error("failed to pack DNS response")
+ return
}
s.Write(b)
@@ -701,7 +704,8 @@ func TestIgnoreDNSForgeries(t *testing.T) {
b, ok = msg.Pack()
if !ok {
- t.Fatal("failed to pack DNS response")
+ t.Error("failed to pack DNS response")
+ return
}
s.Write(b)
}()
@@ -740,8 +744,11 @@ func TestRetryTimeout(t *testing.T) {
}
defer conf.teardown()
- if err := conf.writeAndUpdate([]string{"nameserver 192.0.2.1", // the one that will timeout
- "nameserver 192.0.2.2"}); err != nil {
+ testConf := []string{
+ "nameserver 192.0.2.1", // the one that will timeout
+ "nameserver 192.0.2.2",
+ }
+ if err := conf.writeAndUpdate(testConf); err != nil {
t.Fatal(err)
}
@@ -767,28 +774,10 @@ func TestRetryTimeout(t *testing.T) {
t.Error("deadline didn't change")
}
- r := &dnsMsg{
- dnsMsgHdr: dnsMsgHdr{
- id: q.id,
- response: true,
- recursion_available: true,
- },
- question: q.question,
- answer: []dnsRR{
- &dnsRR_CNAME{
- Hdr: dnsRR_Header{
- Name: q.question[0].Name,
- Rrtype: dnsTypeCNAME,
- Class: dnsClassINET,
- },
- Cname: "golang.org",
- },
- },
- }
- return r, nil
+ return mockTXTResponse(q), nil
}
- _, err = goLookupCNAME(context.Background(), "www.golang.org")
+ _, err = LookupTXT("www.golang.org")
if err != nil {
t.Fatal(err)
}
@@ -797,3 +786,77 @@ func TestRetryTimeout(t *testing.T) {
t.Error("deadline0 still zero", deadline0)
}
}
+
+func TestRotate(t *testing.T) {
+ // without rotation, always uses the first server
+ testRotate(t, false, []string{"192.0.2.1", "192.0.2.2"}, []string{"192.0.2.1:53", "192.0.2.1:53", "192.0.2.1:53"})
+
+ // with rotation, rotates through back to first
+ testRotate(t, true, []string{"192.0.2.1", "192.0.2.2"}, []string{"192.0.2.1:53", "192.0.2.2:53", "192.0.2.1:53"})
+}
+
+func testRotate(t *testing.T, rotate bool, nameservers, wantServers []string) {
+ origTestHookDNSDialer := testHookDNSDialer
+ defer func() { testHookDNSDialer = origTestHookDNSDialer }()
+
+ conf, err := newResolvConfTest()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer conf.teardown()
+
+ var confLines []string
+ for _, ns := range nameservers {
+ confLines = append(confLines, "nameserver "+ns)
+ }
+ if rotate {
+ confLines = append(confLines, "options rotate")
+ }
+
+ if err := conf.writeAndUpdate(confLines); err != nil {
+ t.Fatal(err)
+ }
+
+ d := &fakeDNSDialer{}
+ testHookDNSDialer = func() dnsDialer { return d }
+
+ var usedServers []string
+ d.rh = func(s string, q *dnsMsg, _ time.Time) (*dnsMsg, error) {
+ usedServers = append(usedServers, s)
+ return mockTXTResponse(q), nil
+ }
+
+ // len(nameservers) + 1 to allow rotation to get back to start
+ for i := 0; i < len(nameservers)+1; i++ {
+ if _, err := LookupTXT("www.golang.org"); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ if !reflect.DeepEqual(usedServers, wantServers) {
+ t.Errorf("rotate=%t got used servers:\n%v\nwant:\n%v", rotate, usedServers, wantServers)
+ }
+}
+
+func mockTXTResponse(q *dnsMsg) *dnsMsg {
+ r := &dnsMsg{
+ dnsMsgHdr: dnsMsgHdr{
+ id: q.id,
+ response: true,
+ recursion_available: true,
+ },
+ question: q.question,
+ answer: []dnsRR{
+ &dnsRR_TXT{
+ Hdr: dnsRR_Header{
+ Name: q.question[0].Name,
+ Rrtype: dnsTypeTXT,
+ Class: dnsClassINET,
+ },
+ Txt: "ok",
+ },
+ },
+ }
+
+ return r
+}
diff --git a/libgo/go/net/dnsconfig_unix.go b/libgo/go/net/dnsconfig_unix.go
index aec575e8541..9c8108d11cb 100644
--- a/libgo/go/net/dnsconfig_unix.go
+++ b/libgo/go/net/dnsconfig_unix.go
@@ -10,6 +10,7 @@ package net
import (
"os"
+ "sync/atomic"
"time"
)
@@ -29,6 +30,7 @@ type dnsConfig struct {
lookup []string // OpenBSD top-level database "lookup" order
err error // any error that occurs during open of resolv.conf
mtime time.Time // time of resolv.conf modification
+ soffset uint32 // used by serverOffset
}
// See resolv.conf(5) on a Linux machine.
@@ -91,19 +93,21 @@ func dnsReadConfig(filename string) *dnsConfig {
for _, s := range f[1:] {
switch {
case hasPrefix(s, "ndots:"):
- n, _, _ := dtoi(s, 6)
- if n < 1 {
- n = 1
+ n, _, _ := dtoi(s[6:])
+ if n < 0 {
+ n = 0
+ } else if n > 15 {
+ n = 15
}
conf.ndots = n
case hasPrefix(s, "timeout:"):
- n, _, _ := dtoi(s, 8)
+ n, _, _ := dtoi(s[8:])
if n < 1 {
n = 1
}
conf.timeout = time.Duration(n) * time.Second
case hasPrefix(s, "attempts:"):
- n, _, _ := dtoi(s, 9)
+ n, _, _ := dtoi(s[9:])
if n < 1 {
n = 1
}
@@ -134,6 +138,17 @@ func dnsReadConfig(filename string) *dnsConfig {
return conf
}
+// serverOffset returns an offset that can be used to determine
+// indices of servers in c.servers when making queries.
+// When the rotate option is enabled, this offset increases.
+// Otherwise it is always 0.
+func (c *dnsConfig) serverOffset() uint32 {
+ if c.rotate {
+ return atomic.AddUint32(&c.soffset, 1) - 1 // return 0 to start
+ }
+ return 0
+}
+
func dnsDefaultSearch() []string {
hn, err := getHostname()
if err != nil {
diff --git a/libgo/go/net/dnsconfig_unix_test.go b/libgo/go/net/dnsconfig_unix_test.go
index 9fd6dbf982a..37bdeb04c87 100644
--- a/libgo/go/net/dnsconfig_unix_test.go
+++ b/libgo/go/net/dnsconfig_unix_test.go
@@ -10,6 +10,7 @@ import (
"errors"
"os"
"reflect"
+ "strings"
"testing"
"time"
)
@@ -61,6 +62,36 @@ var dnsReadConfigTests = []struct {
},
},
{
+ name: "testdata/invalid-ndots-resolv.conf",
+ want: &dnsConfig{
+ servers: defaultNS,
+ ndots: 0,
+ timeout: 5 * time.Second,
+ attempts: 2,
+ search: []string{"domain.local."},
+ },
+ },
+ {
+ name: "testdata/large-ndots-resolv.conf",
+ want: &dnsConfig{
+ servers: defaultNS,
+ ndots: 15,
+ timeout: 5 * time.Second,
+ attempts: 2,
+ search: []string{"domain.local."},
+ },
+ },
+ {
+ name: "testdata/negative-ndots-resolv.conf",
+ want: &dnsConfig{
+ servers: defaultNS,
+ ndots: 0,
+ timeout: 5 * time.Second,
+ attempts: 2,
+ search: []string{"domain.local."},
+ },
+ },
+ {
name: "testdata/openbsd-resolv.conf",
want: &dnsConfig{
ndots: 1,
@@ -154,3 +185,55 @@ func TestDNSDefaultSearch(t *testing.T) {
}
}
}
+
+func TestDNSNameLength(t *testing.T) {
+ origGetHostname := getHostname
+ defer func() { getHostname = origGetHostname }()
+ getHostname = func() (string, error) { return "host.domain.local", nil }
+
+ var char63 = ""
+ for i := 0; i < 63; i++ {
+ char63 += "a"
+ }
+ longDomain := strings.Repeat(char63+".", 5) + "example"
+
+ for _, tt := range dnsReadConfigTests {
+ conf := dnsReadConfig(tt.name)
+ if conf.err != nil {
+ t.Fatal(conf.err)
+ }
+
+ var shortestSuffix int
+ for _, suffix := range tt.want.search {
+ if shortestSuffix == 0 || len(suffix) < shortestSuffix {
+ shortestSuffix = len(suffix)
+ }
+ }
+
+ // Test a name that will be maximally long when prefixing the shortest
+ // suffix (accounting for the intervening dot).
+ longName := longDomain[len(longDomain)-254+1+shortestSuffix:]
+ if longName[0] == '.' || longName[1] == '.' {
+ longName = "aa." + longName[3:]
+ }
+ for _, fqdn := range conf.nameList(longName) {
+ if len(fqdn) > 254 {
+ t.Errorf("got %d; want less than or equal to 254", len(fqdn))
+ }
+ }
+
+ // Now test a name that's too long for suffixing.
+ unsuffixable := "a." + longName[1:]
+ unsuffixableResults := conf.nameList(unsuffixable)
+ if len(unsuffixableResults) != 1 {
+ t.Errorf("suffixed names %v; want []", unsuffixableResults[1:])
+ }
+
+ // Now test a name that's too long for DNS.
+ tooLong := "a." + longDomain
+ tooLongResults := conf.nameList(tooLong)
+ if tooLongResults != nil {
+ t.Errorf("suffixed names %v; want nil", tooLongResults)
+ }
+ }
+}
diff --git a/libgo/go/net/dnsmsg.go b/libgo/go/net/dnsmsg.go
index afdb44c0ea5..8f6c7b6350c 100644
--- a/libgo/go/net/dnsmsg.go
+++ b/libgo/go/net/dnsmsg.go
@@ -69,7 +69,7 @@ const (
)
// A dnsStruct describes how to iterate over its fields to emulate
-// reflective marshalling.
+// reflective marshaling.
type dnsStruct interface {
// Walk iterates over fields of a structure and calls f
// with a reference to that field, the name of the field
diff --git a/libgo/go/net/dnsmsg_test.go b/libgo/go/net/dnsmsg_test.go
index 25bd98cff76..2a25a21d4c6 100644
--- a/libgo/go/net/dnsmsg_test.go
+++ b/libgo/go/net/dnsmsg_test.go
@@ -117,7 +117,7 @@ func TestDNSParseSRVReply(t *testing.T) {
if !ok {
t.Fatal("unpacking packet failed")
}
- msg.String() // exercise this code path
+ _ = msg.String() // exercise this code path
if g, e := len(msg.answer), 5; g != e {
t.Errorf("len(msg.answer) = %d; want %d", g, e)
}
@@ -165,7 +165,7 @@ func TestDNSParseCorruptSRVReply(t *testing.T) {
if !ok {
t.Fatal("unpacking packet failed")
}
- msg.String() // exercise this code path
+ _ = msg.String() // exercise this code path
if g, e := len(msg.answer), 5; g != e {
t.Errorf("len(msg.answer) = %d; want %d", g, e)
}
@@ -393,7 +393,7 @@ func TestIsResponseTo(t *testing.T) {
for i := range badResponses {
if badResponses[i].IsResponseTo(&query) {
- t.Error("%v: got true, want false", i)
+ t.Errorf("%v: got true, want false", i)
}
}
}
diff --git a/libgo/go/net/dnsname_test.go b/libgo/go/net/dnsname_test.go
index bc777b855e1..e0f786dec87 100644
--- a/libgo/go/net/dnsname_test.go
+++ b/libgo/go/net/dnsname_test.go
@@ -32,14 +32,12 @@ var dnsNameTests = []dnsNameTest{
func emitDNSNameTest(ch chan<- dnsNameTest) {
defer close(ch)
- var char59 = ""
var char63 = ""
- var char64 = ""
- for i := 0; i < 59; i++ {
- char59 += "a"
+ for i := 0; i < 63; i++ {
+ char63 += "a"
}
- char63 = char59 + "aaaa"
- char64 = char63 + "a"
+ char64 := char63 + "a"
+ longDomain := strings.Repeat(char63+".", 5) + "example"
for _, tc := range dnsNameTests {
ch <- tc
@@ -47,14 +45,15 @@ func emitDNSNameTest(ch chan<- dnsNameTest) {
ch <- dnsNameTest{char63 + ".com", true}
ch <- dnsNameTest{char64 + ".com", false}
- // 255 char name is fine:
- ch <- dnsNameTest{char59 + "." + char63 + "." + char63 + "." +
- char63 + ".com",
- true}
- // 256 char name is bad:
- ch <- dnsNameTest{char59 + "a." + char63 + "." + char63 + "." +
- char63 + ".com",
- false}
+
+ // Remember: wire format is two octets longer than presentation
+ // (length octets for the first and [root] last labels).
+ // 253 is fine:
+ ch <- dnsNameTest{longDomain[len(longDomain)-253:], true}
+ // A terminal dot doesn't contribute to length:
+ ch <- dnsNameTest{longDomain[len(longDomain)-253:] + ".", true}
+ // 254 is bad:
+ ch <- dnsNameTest{longDomain[len(longDomain)-254:], false}
}
func TestDNSName(t *testing.T) {
diff --git a/libgo/go/net/error_test.go b/libgo/go/net/error_test.go
index d6de5a3e68f..c23da49fad9 100644
--- a/libgo/go/net/error_test.go
+++ b/libgo/go/net/error_test.go
@@ -97,7 +97,8 @@ second:
goto third
}
switch nestedErr {
- case errCanceled, errClosing, errMissingAddress, errNoSuitableAddress:
+ case errCanceled, errClosing, errMissingAddress, errNoSuitableAddress,
+ context.DeadlineExceeded, context.Canceled:
return nil
}
return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
@@ -230,23 +231,27 @@ func TestDialAddrError(t *testing.T) {
} {
var err error
var c Conn
+ var op string
if tt.lit != "" {
c, err = Dial(tt.network, JoinHostPort(tt.lit, "0"))
+ op = fmt.Sprintf("Dial(%q, %q)", tt.network, JoinHostPort(tt.lit, "0"))
} else {
c, err = DialTCP(tt.network, nil, tt.addr)
+ op = fmt.Sprintf("DialTCP(%q, %q)", tt.network, tt.addr)
}
if err == nil {
c.Close()
- t.Errorf("%s %q/%v: should fail", tt.network, tt.lit, tt.addr)
+ t.Errorf("%s succeeded, want error", op)
continue
}
if perr := parseDialError(err); perr != nil {
- t.Error(perr)
+ t.Errorf("%s: %v", op, perr)
continue
}
- aerr, ok := err.(*OpError).Err.(*AddrError)
+ operr := err.(*OpError).Err
+ aerr, ok := operr.(*AddrError)
if !ok {
- t.Errorf("%s %q/%v: should be AddrError: %v", tt.network, tt.lit, tt.addr, err)
+ t.Errorf("%s: %v is %T, want *AddrError", op, err, operr)
continue
}
want := tt.lit
@@ -254,7 +259,7 @@ func TestDialAddrError(t *testing.T) {
want = tt.addr.IP.String()
}
if aerr.Addr != want {
- t.Fatalf("%s: got %q; want %q", tt.network, aerr.Addr, want)
+ t.Errorf("%s: %v, error Addr=%q, want %q", op, err, aerr.Addr, want)
}
}
}
@@ -521,6 +526,10 @@ third:
if isPlatformError(nestedErr) {
return nil
}
+ switch nestedErr {
+ case os.ErrClosed: // for Plan 9
+ return nil
+ }
return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
}
diff --git a/libgo/go/net/fd_io_plan9.go b/libgo/go/net/fd_io_plan9.go
new file mode 100644
index 00000000000..76da0c546cf
--- /dev/null
+++ b/libgo/go/net/fd_io_plan9.go
@@ -0,0 +1,93 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "os"
+ "runtime"
+ "sync"
+ "syscall"
+)
+
+// asyncIO implements asynchronous cancelable I/O.
+// An asyncIO represents a single asynchronous Read or Write
+// operation. The result is returned on the result channel.
+// The undergoing I/O system call can either complete or be
+// interrupted by a note.
+type asyncIO struct {
+ res chan result
+
+ // mu guards the pid field.
+ mu sync.Mutex
+
+ // pid holds the process id of
+ // the process running the IO operation.
+ pid int
+}
+
+// result is the return value of a Read or Write operation.
+type result struct {
+ n int
+ err error
+}
+
+// newAsyncIO returns a new asyncIO that performs an I/O
+// operation by calling fn, which must do one and only one
+// interruptible system call.
+func newAsyncIO(fn func([]byte) (int, error), b []byte) *asyncIO {
+ aio := &asyncIO{
+ res: make(chan result, 0),
+ }
+ aio.mu.Lock()
+ go func() {
+ // Lock the current goroutine to its process
+ // and store the pid in io so that Cancel can
+ // interrupt it. We ignore the "hangup" signal,
+ // so the signal does not take down the entire
+ // Go runtime.
+ runtime.LockOSThread()
+ runtime_ignoreHangup()
+ aio.pid = os.Getpid()
+ aio.mu.Unlock()
+
+ n, err := fn(b)
+
+ aio.mu.Lock()
+ aio.pid = -1
+ runtime_unignoreHangup()
+ aio.mu.Unlock()
+
+ aio.res <- result{n, err}
+ }()
+ return aio
+}
+
+var hangupNote os.Signal = syscall.Note("hangup")
+
+// Cancel interrupts the I/O operation, causing
+// the Wait function to return.
+func (aio *asyncIO) Cancel() {
+ aio.mu.Lock()
+ defer aio.mu.Unlock()
+ if aio.pid == -1 {
+ return
+ }
+ proc, err := os.FindProcess(aio.pid)
+ if err != nil {
+ return
+ }
+ proc.Signal(hangupNote)
+}
+
+// Wait for the I/O operation to complete.
+func (aio *asyncIO) Wait() (int, error) {
+ res := <-aio.res
+ return res.n, res.err
+}
+
+// The following functions, provided by the runtime, are used to
+// ignore and unignore the "hangup" signal received by the process.
+func runtime_ignoreHangup()
+func runtime_unignoreHangup()
diff --git a/libgo/go/net/fd_plan9.go b/libgo/go/net/fd_plan9.go
index 7533232dc9b..300d8c4543e 100644
--- a/libgo/go/net/fd_plan9.go
+++ b/libgo/go/net/fd_plan9.go
@@ -7,21 +7,37 @@ package net
import (
"io"
"os"
+ "sync/atomic"
"syscall"
"time"
)
+type atomicBool int32
+
+func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
+func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) }
+func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) }
+
// Network file descriptor.
type netFD struct {
// locking/lifetime of sysfd + serialize access to Read and Write methods
fdmu fdMutex
// immutable until Close
- net string
- n string
- dir string
- ctl, data *os.File
- laddr, raddr Addr
+ net string
+ n string
+ dir string
+ listen, ctl, data *os.File
+ laddr, raddr Addr
+ isStream bool
+
+ // deadlines
+ raio *asyncIO
+ waio *asyncIO
+ rtimer *time.Timer
+ wtimer *time.Timer
+ rtimedout atomicBool // set true when read deadline has been reached
+ wtimedout atomicBool // set true when write deadline has been reached
}
var (
@@ -32,8 +48,16 @@ func sysInit() {
netdir = "/net"
}
-func newFD(net, name string, ctl, data *os.File, laddr, raddr Addr) (*netFD, error) {
- return &netFD{net: net, n: name, dir: netdir + "/" + net + "/" + name, ctl: ctl, data: data, laddr: laddr, raddr: raddr}, nil
+func newFD(net, name string, listen, ctl, data *os.File, laddr, raddr Addr) (*netFD, error) {
+ return &netFD{
+ net: net,
+ n: name,
+ dir: netdir + "/" + net + "/" + name,
+ listen: listen,
+ ctl: ctl, data: data,
+ laddr: laddr,
+ raddr: raddr,
+ }, nil
}
func (fd *netFD) init() error {
@@ -64,11 +88,20 @@ func (fd *netFD) destroy() {
err = err1
}
}
+ if fd.listen != nil {
+ if err1 := fd.listen.Close(); err1 != nil && err == nil {
+ err = err1
+ }
+ }
fd.ctl = nil
fd.data = nil
+ fd.listen = nil
}
func (fd *netFD) Read(b []byte) (n int, err error) {
+ if fd.rtimedout.isSet() {
+ return 0, errTimeout
+ }
if !fd.ok() || fd.data == nil {
return 0, syscall.EINVAL
}
@@ -79,10 +112,15 @@ func (fd *netFD) Read(b []byte) (n int, err error) {
if len(b) == 0 {
return 0, nil
}
- n, err = fd.data.Read(b)
+ fd.raio = newAsyncIO(fd.data.Read, b)
+ n, err = fd.raio.Wait()
+ fd.raio = nil
if isHangup(err) {
err = io.EOF
}
+ if isInterrupted(err) {
+ err = errTimeout
+ }
if fd.net == "udp" && err == io.EOF {
n = 0
err = nil
@@ -91,6 +129,9 @@ func (fd *netFD) Read(b []byte) (n int, err error) {
}
func (fd *netFD) Write(b []byte) (n int, err error) {
+ if fd.wtimedout.isSet() {
+ return 0, errTimeout
+ }
if !fd.ok() || fd.data == nil {
return 0, syscall.EINVAL
}
@@ -98,7 +139,13 @@ func (fd *netFD) Write(b []byte) (n int, err error) {
return 0, err
}
defer fd.writeUnlock()
- return fd.data.Write(b)
+ fd.waio = newAsyncIO(fd.data.Write, b)
+ n, err = fd.waio.Wait()
+ fd.waio = nil
+ if isInterrupted(err) {
+ err = errTimeout
+ }
+ return
}
func (fd *netFD) closeRead() error {
@@ -124,11 +171,10 @@ func (fd *netFD) Close() error {
}
if fd.net == "tcp" {
// The following line is required to unblock Reads.
- // For some reason, WriteString returns an error:
- // "write /net/tcp/39/listen: inappropriate use of fd"
- // But without it, Reads on dead conns hang forever.
- // See Issue 9554.
- fd.ctl.WriteString("hangup")
+ _, err := fd.ctl.WriteString("close")
+ if err != nil {
+ return err
+ }
}
err := fd.ctl.Close()
if fd.data != nil {
@@ -136,8 +182,14 @@ func (fd *netFD) Close() error {
err = err1
}
}
+ if fd.listen != nil {
+ if err1 := fd.listen.Close(); err1 != nil && err == nil {
+ err = err1
+ }
+ }
fd.ctl = nil
fd.data = nil
+ fd.listen = nil
return err
}
@@ -165,15 +217,74 @@ func (fd *netFD) file(f *os.File, s string) (*os.File, error) {
}
func (fd *netFD) setDeadline(t time.Time) error {
- return syscall.EPLAN9
+ return setDeadlineImpl(fd, t, 'r'+'w')
}
func (fd *netFD) setReadDeadline(t time.Time) error {
- return syscall.EPLAN9
+ return setDeadlineImpl(fd, t, 'r')
}
func (fd *netFD) setWriteDeadline(t time.Time) error {
- return syscall.EPLAN9
+ return setDeadlineImpl(fd, t, 'w')
+}
+
+func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
+ d := t.Sub(time.Now())
+ if mode == 'r' || mode == 'r'+'w' {
+ fd.rtimedout.setFalse()
+ }
+ if mode == 'w' || mode == 'r'+'w' {
+ fd.wtimedout.setFalse()
+ }
+ if t.IsZero() || d < 0 {
+ // Stop timer
+ if mode == 'r' || mode == 'r'+'w' {
+ if fd.rtimer != nil {
+ fd.rtimer.Stop()
+ }
+ fd.rtimer = nil
+ }
+ if mode == 'w' || mode == 'r'+'w' {
+ if fd.wtimer != nil {
+ fd.wtimer.Stop()
+ }
+ fd.wtimer = nil
+ }
+ } else {
+ // Interrupt I/O operation once timer has expired
+ if mode == 'r' || mode == 'r'+'w' {
+ fd.rtimer = time.AfterFunc(d, func() {
+ fd.rtimedout.setTrue()
+ if fd.raio != nil {
+ fd.raio.Cancel()
+ }
+ })
+ }
+ if mode == 'w' || mode == 'r'+'w' {
+ fd.wtimer = time.AfterFunc(d, func() {
+ fd.wtimedout.setTrue()
+ if fd.waio != nil {
+ fd.waio.Cancel()
+ }
+ })
+ }
+ }
+ if !t.IsZero() && d < 0 {
+ // Interrupt current I/O operation
+ if mode == 'r' || mode == 'r'+'w' {
+ fd.rtimedout.setTrue()
+ if fd.raio != nil {
+ fd.raio.Cancel()
+ }
+ }
+ if mode == 'w' || mode == 'r'+'w' {
+ fd.wtimedout.setTrue()
+ if fd.waio != nil {
+ fd.waio.Cancel()
+ }
+ }
+ }
+ return nil
}
func setReadBuffer(fd *netFD, bytes int) error {
@@ -187,3 +298,7 @@ func setWriteBuffer(fd *netFD, bytes int) error {
func isHangup(err error) bool {
return err != nil && stringsHasSuffix(err.Error(), "Hangup")
}
+
+func isInterrupted(err error) bool {
+ return err != nil && stringsHasSuffix(err.Error(), "interrupted")
+}
diff --git a/libgo/go/net/fd_poll_nacl.go b/libgo/go/net/fd_poll_nacl.go
index cda8b82c131..83987602a58 100644
--- a/libgo/go/net/fd_poll_nacl.go
+++ b/libgo/go/net/fd_poll_nacl.go
@@ -5,6 +5,7 @@
package net
import (
+ "runtime"
"syscall"
"time"
)
@@ -22,6 +23,7 @@ func (pd *pollDesc) evict() {
pd.closing = true
if pd.fd != nil {
syscall.StopIO(pd.fd.sysfd)
+ runtime.KeepAlive(pd.fd)
}
}
diff --git a/libgo/go/net/fd_poll_runtime.go b/libgo/go/net/fd_poll_runtime.go
index 6c1d095bd7f..62b69fcbf15 100644
--- a/libgo/go/net/fd_poll_runtime.go
+++ b/libgo/go/net/fd_poll_runtime.go
@@ -7,6 +7,7 @@
package net
import (
+ "runtime"
"sync"
"syscall"
"time"
@@ -33,6 +34,7 @@ var serverInit sync.Once
func (pd *pollDesc) init(fd *netFD) error {
serverInit.Do(runtime_pollServerInit)
ctx, errno := runtime_pollOpen(uintptr(fd.sysfd))
+ runtime.KeepAlive(fd)
if errno != 0 {
return syscall.Errno(errno)
}
@@ -120,7 +122,7 @@ func (fd *netFD) setWriteDeadline(t time.Time) error {
}
func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
- diff := int64(t.Sub(time.Now()))
+ diff := int64(time.Until(t))
d := runtimeNano() + diff
if d <= 0 && diff > 0 {
// If the user has a deadline in the future, but the delay calculation
diff --git a/libgo/go/net/fd_unix.go b/libgo/go/net/fd_unix.go
index 0309db08ebc..9bc5ebc7a0d 100644
--- a/libgo/go/net/fd_unix.go
+++ b/libgo/go/net/fd_unix.go
@@ -24,11 +24,15 @@ type netFD struct {
sysfd int
family int
sotype int
+ isStream bool
isConnected bool
net string
laddr Addr
raddr Addr
+ // writev cache.
+ iovecs *[]syscall.Iovec
+
// wait server
pd pollDesc
}
@@ -37,7 +41,7 @@ func sysInit() {
}
func newFD(sysfd, family, sotype int, net string) (*netFD, error) {
- return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil
+ return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net, isStream: sotype == syscall.SOCK_STREAM}, nil
}
func (fd *netFD) init() error {
@@ -235,6 +239,9 @@ func (fd *netFD) Read(p []byte) (n int, err error) {
if err := fd.pd.prepareRead(); err != nil {
return 0, err
}
+ if fd.isStream && len(p) > 1<<30 {
+ p = p[:1<<30]
+ }
for {
n, err = syscall.Read(fd.sysfd, p)
if err != nil {
@@ -318,7 +325,11 @@ func (fd *netFD) Write(p []byte) (nn int, err error) {
}
for {
var n int
- n, err = syscall.Write(fd.sysfd, p[nn:])
+ max := len(p)
+ if fd.isStream && max-nn > 1<<30 {
+ max = nn + 1<<30
+ }
+ n, err = syscall.Write(fd.sysfd, p[nn:max])
if n > 0 {
nn += n
}
diff --git a/libgo/go/net/fd_windows.go b/libgo/go/net/fd_windows.go
index b0b6769eb3c..a976f2ac7f9 100644
--- a/libgo/go/net/fd_windows.go
+++ b/libgo/go/net/fd_windows.go
@@ -96,6 +96,7 @@ type operation struct {
rsan int32
handle syscall.Handle
flags uint32
+ bufs []syscall.WSABuf
}
func (o *operation) InitBuf(buf []byte) {
@@ -106,6 +107,30 @@ func (o *operation) InitBuf(buf []byte) {
}
}
+func (o *operation) InitBufs(buf *Buffers) {
+ if o.bufs == nil {
+ o.bufs = make([]syscall.WSABuf, 0, len(*buf))
+ } else {
+ o.bufs = o.bufs[:0]
+ }
+ for _, b := range *buf {
+ var p *byte
+ if len(b) > 0 {
+ p = &b[0]
+ }
+ o.bufs = append(o.bufs, syscall.WSABuf{Len: uint32(len(b)), Buf: p})
+ }
+}
+
+// ClearBufs clears all pointers to Buffers parameter captured
+// by InitBufs, so it can be released by garbage collector.
+func (o *operation) ClearBufs() {
+ for i := range o.bufs {
+ o.bufs[i].Buf = nil
+ }
+ o.bufs = o.bufs[:0]
+}
+
// ioSrv executes net IO requests.
type ioSrv struct {
req chan ioSrvReq
@@ -239,6 +264,7 @@ type netFD struct {
sysfd syscall.Handle
family int
sotype int
+ isStream bool
isConnected bool
skipSyncNotif bool
net string
@@ -257,7 +283,7 @@ func newFD(sysfd syscall.Handle, family, sotype int, net string) (*netFD, error)
return nil, initErr
}
onceStartServer.Do(startServer)
- return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil
+ return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net, isStream: sotype == syscall.SOCK_STREAM}, nil
}
func (fd *netFD) init() error {
@@ -483,6 +509,42 @@ func (fd *netFD) Write(buf []byte) (int, error) {
return n, err
}
+func (c *conn) writeBuffers(v *Buffers) (int64, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ n, err := c.fd.writeBuffers(v)
+ if err != nil {
+ return n, &OpError{Op: "WSASend", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
+ }
+ return n, nil
+}
+
+func (fd *netFD) writeBuffers(buf *Buffers) (int64, error) {
+ if len(*buf) == 0 {
+ return 0, nil
+ }
+ if err := fd.writeLock(); err != nil {
+ return 0, err
+ }
+ defer fd.writeUnlock()
+ if race.Enabled {
+ race.ReleaseMerge(unsafe.Pointer(&ioSync))
+ }
+ o := &fd.wop
+ o.InitBufs(buf)
+ n, err := wsrv.ExecIO(o, "WSASend", func(o *operation) error {
+ return syscall.WSASend(o.fd.sysfd, &o.bufs[0], uint32(len(*buf)), &o.qty, 0, &o.o, nil)
+ })
+ o.ClearBufs()
+ if _, ok := err.(syscall.Errno); ok {
+ err = os.NewSyscallError("wsasend", err)
+ }
+ testHookDidWritev(n)
+ buf.consume(int64(n))
+ return int64(n), err
+}
+
func (fd *netFD) writeTo(buf []byte, sa syscall.Sockaddr) (int, error) {
if len(buf) == 0 {
return 0, nil
@@ -541,7 +603,7 @@ func (fd *netFD) acceptOne(rawsa []syscall.RawSockaddrAny, o *operation) (*netFD
netfd.Close()
return nil, os.NewSyscallError("setsockopt", err)
}
-
+ runtime.KeepAlive(fd)
return netfd, nil
}
diff --git a/libgo/go/net/file.go b/libgo/go/net/file.go
index 1aad477400c..07099851cbf 100644
--- a/libgo/go/net/file.go
+++ b/libgo/go/net/file.go
@@ -6,6 +6,9 @@ package net
import "os"
+// BUG(mikio): On NaCl and Windows, the FileConn, FileListener and
+// FilePacketConn functions are not implemented.
+
type fileAddr string
func (fileAddr) Network() string { return "file+net" }
diff --git a/libgo/go/net/file_plan9.go b/libgo/go/net/file_plan9.go
index 2939c09a430..d16e5a166c3 100644
--- a/libgo/go/net/file_plan9.go
+++ b/libgo/go/net/file_plan9.go
@@ -81,7 +81,7 @@ func newFileFD(f *os.File) (net *netFD, err error) {
if err != nil {
return nil, err
}
- return newFD(comp[1], name, ctl, nil, laddr, nil)
+ return newFD(comp[1], name, nil, ctl, nil, laddr, nil)
}
func fileConn(f *os.File) (Conn, error) {
diff --git a/libgo/go/net/http/client.go b/libgo/go/net/http/client.go
index 993c247eef5..d368bae861e 100644
--- a/libgo/go/net/http/client.go
+++ b/libgo/go/net/http/client.go
@@ -18,6 +18,7 @@ import (
"io/ioutil"
"log"
"net/url"
+ "sort"
"strings"
"sync"
"time"
@@ -33,6 +34,25 @@ import (
// A Client is higher-level than a RoundTripper (such as Transport)
// and additionally handles HTTP details such as cookies and
// redirects.
+//
+// When following redirects, the Client will forward all headers set on the
+// initial Request except:
+//
+// * when forwarding sensitive headers like "Authorization",
+// "WWW-Authenticate", and "Cookie" to untrusted targets.
+// These headers will be ignored when following a redirect to a domain
+// that is not a subdomain match or exact match of the initial domain.
+// For example, a redirect from "foo.com" to either "foo.com" or "sub.foo.com"
+// will forward the sensitive headers, but a redirect to "bar.com" will not.
+//
+// * when forwarding the "Cookie" header with a non-nil cookie Jar.
+// Since each redirect may mutate the state of the cookie jar,
+// a redirect may possibly alter a cookie set in the initial request.
+// When forwarding the "Cookie" header, any mutated cookies will be omitted,
+// with the expectation that the Jar will insert those mutated cookies
+// with the updated values (assuming the origin matches).
+// If Jar is nil, the initial cookies are forwarded without change.
+//
type Client struct {
// Transport specifies the mechanism by which individual
// HTTP requests are made.
@@ -56,8 +76,14 @@ type Client struct {
CheckRedirect func(req *Request, via []*Request) error
// Jar specifies the cookie jar.
- // If Jar is nil, cookies are not sent in requests and ignored
- // in responses.
+ //
+ // The Jar is used to insert relevant cookies into every
+ // outbound Request and is updated with the cookie values
+ // of every inbound Response. The Jar is consulted for every
+ // redirect that the Client follows.
+ //
+ // If Jar is nil, cookies are only sent if they are explicitly
+ // set on the Request.
Jar CookieJar
// Timeout specifies a time limit for requests made by this
@@ -137,56 +163,23 @@ func refererForURL(lastReq, newReq *url.URL) string {
return referer
}
-func (c *Client) send(req *Request, deadline time.Time) (*Response, error) {
+// didTimeout is non-nil only if err != nil.
+func (c *Client) send(req *Request, deadline time.Time) (resp *Response, didTimeout func() bool, err error) {
if c.Jar != nil {
for _, cookie := range c.Jar.Cookies(req.URL) {
req.AddCookie(cookie)
}
}
- resp, err := send(req, c.transport(), deadline)
+ resp, didTimeout, err = send(req, c.transport(), deadline)
if err != nil {
- return nil, err
+ return nil, didTimeout, err
}
if c.Jar != nil {
if rc := resp.Cookies(); len(rc) > 0 {
c.Jar.SetCookies(req.URL, rc)
}
}
- return resp, nil
-}
-
-// Do sends an HTTP request and returns an HTTP response, following
-// policy (such as redirects, cookies, auth) as configured on the
-// client.
-//
-// An error is returned if caused by client policy (such as
-// CheckRedirect), or failure to speak HTTP (such as a network
-// connectivity problem). A non-2xx status code doesn't cause an
-// error.
-//
-// If the returned error is nil, the Response will contain a non-nil
-// Body which the user is expected to close. If the Body is not
-// closed, the Client's underlying RoundTripper (typically Transport)
-// may not be able to re-use a persistent TCP connection to the server
-// for a subsequent "keep-alive" request.
-//
-// The request Body, if non-nil, will be closed by the underlying
-// Transport, even on errors.
-//
-// On error, any Response can be ignored. A non-nil Response with a
-// non-nil error only occurs when CheckRedirect fails, and even then
-// the returned Response.Body is already closed.
-//
-// Generally Get, Post, or PostForm will be used instead of Do.
-func (c *Client) Do(req *Request) (*Response, error) {
- method := valueOrDefault(req.Method, "GET")
- if method == "GET" || method == "HEAD" {
- return c.doFollowingRedirects(req, shouldRedirectGet)
- }
- if method == "POST" || method == "PUT" {
- return c.doFollowingRedirects(req, shouldRedirectPost)
- }
- return c.send(req, c.deadline())
+ return resp, nil, nil
}
func (c *Client) deadline() time.Time {
@@ -205,22 +198,22 @@ func (c *Client) transport() RoundTripper {
// send issues an HTTP request.
// Caller should close resp.Body when done reading from it.
-func send(ireq *Request, rt RoundTripper, deadline time.Time) (*Response, error) {
+func send(ireq *Request, rt RoundTripper, deadline time.Time) (resp *Response, didTimeout func() bool, err error) {
req := ireq // req is either the original request, or a modified fork
if rt == nil {
req.closeBody()
- return nil, errors.New("http: no Client.Transport or DefaultTransport")
+ return nil, alwaysFalse, errors.New("http: no Client.Transport or DefaultTransport")
}
if req.URL == nil {
req.closeBody()
- return nil, errors.New("http: nil Request.URL")
+ return nil, alwaysFalse, errors.New("http: nil Request.URL")
}
if req.RequestURI != "" {
req.closeBody()
- return nil, errors.New("http: Request.RequestURI can't be set in client requests.")
+ return nil, alwaysFalse, errors.New("http: Request.RequestURI can't be set in client requests.")
}
// forkReq forks req into a shallow clone of ireq the first
@@ -251,9 +244,9 @@ func send(ireq *Request, rt RoundTripper, deadline time.Time) (*Response, error)
if !deadline.IsZero() {
forkReq()
}
- stopTimer, wasCanceled := setRequestCancel(req, rt, deadline)
+ stopTimer, didTimeout := setRequestCancel(req, rt, deadline)
- resp, err := rt.RoundTrip(req)
+ resp, err = rt.RoundTrip(req)
if err != nil {
stopTimer()
if resp != nil {
@@ -267,22 +260,27 @@ func send(ireq *Request, rt RoundTripper, deadline time.Time) (*Response, error)
err = errors.New("http: server gave HTTP response to HTTPS client")
}
}
- return nil, err
+ return nil, didTimeout, err
}
if !deadline.IsZero() {
resp.Body = &cancelTimerBody{
- stop: stopTimer,
- rc: resp.Body,
- reqWasCanceled: wasCanceled,
+ stop: stopTimer,
+ rc: resp.Body,
+ reqDidTimeout: didTimeout,
}
}
- return resp, nil
+ return resp, nil, nil
}
// setRequestCancel sets the Cancel field of req, if deadline is
// non-zero. The RoundTripper's type is used to determine whether the legacy
// CancelRequest behavior should be used.
-func setRequestCancel(req *Request, rt RoundTripper, deadline time.Time) (stopTimer func(), wasCanceled func() bool) {
+//
+// As background, there are three ways to cancel a request:
+// First was Transport.CancelRequest. (deprecated)
+// Second was Request.Cancel (this mechanism).
+// Third was Request.Context.
+func setRequestCancel(req *Request, rt RoundTripper, deadline time.Time) (stopTimer func(), didTimeout func() bool) {
if deadline.IsZero() {
return nop, alwaysFalse
}
@@ -292,17 +290,8 @@ func setRequestCancel(req *Request, rt RoundTripper, deadline time.Time) (stopTi
cancel := make(chan struct{})
req.Cancel = cancel
- wasCanceled = func() bool {
- select {
- case <-cancel:
- return true
- default:
- return false
- }
- }
-
doCancel := func() {
- // The new way:
+ // The newer way (the second way in the func comment):
close(cancel)
// The legacy compatibility way, used only
@@ -324,19 +313,23 @@ func setRequestCancel(req *Request, rt RoundTripper, deadline time.Time) (stopTi
var once sync.Once
stopTimer = func() { once.Do(func() { close(stopTimerCh) }) }
- timer := time.NewTimer(deadline.Sub(time.Now()))
+ timer := time.NewTimer(time.Until(deadline))
+ var timedOut atomicBool
+
go func() {
select {
case <-initialReqCancel:
doCancel()
+ timer.Stop()
case <-timer.C:
+ timedOut.setTrue()
doCancel()
case <-stopTimerCh:
timer.Stop()
}
}()
- return stopTimer, wasCanceled
+ return stopTimer, timedOut.isSet
}
// See 2 (end of page 4) http://www.ietf.org/rfc/rfc2617.txt
@@ -349,26 +342,6 @@ func basicAuth(username, password string) string {
return base64.StdEncoding.EncodeToString([]byte(auth))
}
-// True if the specified HTTP status code is one for which the Get utility should
-// automatically redirect.
-func shouldRedirectGet(statusCode int) bool {
- switch statusCode {
- case StatusMovedPermanently, StatusFound, StatusSeeOther, StatusTemporaryRedirect:
- return true
- }
- return false
-}
-
-// True if the specified HTTP status code is one for which the Post utility should
-// automatically redirect.
-func shouldRedirectPost(statusCode int) bool {
- switch statusCode {
- case StatusFound, StatusSeeOther:
- return true
- }
- return false
-}
-
// Get issues a GET to the specified URL. If the response is one of
// the following redirect codes, Get follows the redirect, up to a
// maximum of 10 redirects:
@@ -377,6 +350,7 @@ func shouldRedirectPost(statusCode int) bool {
// 302 (Found)
// 303 (See Other)
// 307 (Temporary Redirect)
+// 308 (Permanent Redirect)
//
// An error is returned if there were too many redirects or if there
// was an HTTP protocol error. A non-2xx response doesn't cause an
@@ -401,6 +375,7 @@ func Get(url string) (resp *Response, err error) {
// 302 (Found)
// 303 (See Other)
// 307 (Temporary Redirect)
+// 308 (Permanent Redirect)
//
// An error is returned if the Client's CheckRedirect function fails
// or if there was an HTTP protocol error. A non-2xx response doesn't
@@ -415,7 +390,7 @@ func (c *Client) Get(url string) (resp *Response, err error) {
if err != nil {
return nil, err
}
- return c.doFollowingRedirects(req, shouldRedirectGet)
+ return c.Do(req)
}
func alwaysFalse() bool { return false }
@@ -436,16 +411,92 @@ func (c *Client) checkRedirect(req *Request, via []*Request) error {
return fn(req, via)
}
-func (c *Client) doFollowingRedirects(req *Request, shouldRedirect func(int) bool) (*Response, error) {
+// redirectBehavior describes what should happen when the
+// client encounters a 3xx status code from the server
+func redirectBehavior(reqMethod string, resp *Response, ireq *Request) (redirectMethod string, shouldRedirect bool) {
+ switch resp.StatusCode {
+ case 301, 302, 303:
+ redirectMethod = reqMethod
+ shouldRedirect = true
+
+ // RFC 2616 allowed automatic redirection only with GET and
+ // HEAD requests. RFC 7231 lifts this restriction, but we still
+ // restrict other methods to GET to maintain compatibility.
+ // See Issue 18570.
+ if reqMethod != "GET" && reqMethod != "HEAD" {
+ redirectMethod = "GET"
+ }
+ case 307, 308:
+ redirectMethod = reqMethod
+ shouldRedirect = true
+
+ // Treat 307 and 308 specially, since they're new in
+ // Go 1.8, and they also require re-sending the request body.
+ if resp.Header.Get("Location") == "" {
+ // 308s have been observed in the wild being served
+ // without Location headers. Since Go 1.7 and earlier
+ // didn't follow these codes, just stop here instead
+ // of returning an error.
+ // See Issue 17773.
+ shouldRedirect = false
+ break
+ }
+ if ireq.GetBody == nil && ireq.outgoingLength() != 0 {
+ // We had a request body, and 307/308 require
+ // re-sending it, but GetBody is not defined. So just
+ // return this response to the user instead of an
+ // error, like we did in Go 1.7 and earlier.
+ shouldRedirect = false
+ }
+ }
+ return redirectMethod, shouldRedirect
+}
+
+// Do sends an HTTP request and returns an HTTP response, following
+// policy (such as redirects, cookies, auth) as configured on the
+// client.
+//
+// An error is returned if caused by client policy (such as
+// CheckRedirect), or failure to speak HTTP (such as a network
+// connectivity problem). A non-2xx status code doesn't cause an
+// error.
+//
+// If the returned error is nil, the Response will contain a non-nil
+// Body which the user is expected to close. If the Body is not
+// closed, the Client's underlying RoundTripper (typically Transport)
+// may not be able to re-use a persistent TCP connection to the server
+// for a subsequent "keep-alive" request.
+//
+// The request Body, if non-nil, will be closed by the underlying
+// Transport, even on errors.
+//
+// On error, any Response can be ignored. A non-nil Response with a
+// non-nil error only occurs when CheckRedirect fails, and even then
+// the returned Response.Body is already closed.
+//
+// Generally Get, Post, or PostForm will be used instead of Do.
+//
+// If the server replies with a redirect, the Client first uses the
+// CheckRedirect function to determine whether the redirect should be
+// followed. If permitted, a 301, 302, or 303 redirect causes
+// subsequent requests to use HTTP method GET
+// (or HEAD if the original request was HEAD), with no body.
+// A 307 or 308 redirect preserves the original HTTP method and body,
+// provided that the Request.GetBody function is defined.
+// The NewRequest function automatically sets GetBody for common
+// standard library body types.
+func (c *Client) Do(req *Request) (*Response, error) {
if req.URL == nil {
req.closeBody()
return nil, errors.New("http: nil Request.URL")
}
var (
- deadline = c.deadline()
- reqs []*Request
- resp *Response
+ deadline = c.deadline()
+ reqs []*Request
+ resp *Response
+ copyHeaders = c.makeHeadersCopier(req)
+ redirectMethod string
)
uerr := func(err error) error {
req.closeBody()
@@ -476,16 +527,27 @@ func (c *Client) doFollowingRedirects(req *Request, shouldRedirect func(int) boo
}
ireq := reqs[0]
req = &Request{
- Method: ireq.Method,
+ Method: redirectMethod,
Response: resp,
URL: u,
Header: make(Header),
Cancel: ireq.Cancel,
ctx: ireq.ctx,
}
- if ireq.Method == "POST" || ireq.Method == "PUT" {
- req.Method = "GET"
+ if ireq.GetBody != nil {
+ req.Body, err = ireq.GetBody()
+ if err != nil {
+ return nil, uerr(err)
+ }
+ req.ContentLength = ireq.ContentLength
}
+
+ // Copy original headers before setting the Referer,
+ // in case the user set Referer on their first request.
+ // If they really want to override, they can do it in
+ // their CheckRedirect func.
+ copyHeaders(req)
+
// Add the Referer header from the most recent
// request URL to the new one, if it's not https->http:
if ref := refererForURL(reqs[len(reqs)-1].URL, req.URL); ref != "" {
@@ -523,10 +585,10 @@ func (c *Client) doFollowingRedirects(req *Request, shouldRedirect func(int) boo
}
reqs = append(reqs, req)
-
var err error
- if resp, err = c.send(req, deadline); err != nil {
- if !deadline.IsZero() && !time.Now().Before(deadline) {
+ var didTimeout func() bool
+ if resp, didTimeout, err = c.send(req, deadline); err != nil {
+ if !deadline.IsZero() && didTimeout() {
err = &httpError{
err: err.Error() + " (Client.Timeout exceeded while awaiting headers)",
timeout: true,
@@ -535,9 +597,77 @@ func (c *Client) doFollowingRedirects(req *Request, shouldRedirect func(int) boo
return nil, uerr(err)
}
- if !shouldRedirect(resp.StatusCode) {
+ var shouldRedirect bool
+ redirectMethod, shouldRedirect = redirectBehavior(req.Method, resp, reqs[0])
+ if !shouldRedirect {
return resp, nil
}
+
+ req.closeBody()
+ }
+}
+
+// makeHeadersCopier makes a function that copies headers from the
+// initial Request, ireq. For every redirect, this function must be called
+// so that it can copy headers into the upcoming Request.
+func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) {
+ // The headers to copy are from the very initial request.
+ // We use a closured callback to keep a reference to these original headers.
+ var (
+ ireqhdr = ireq.Header.clone()
+ icookies map[string][]*Cookie
+ )
+ if c.Jar != nil && ireq.Header.Get("Cookie") != "" {
+ icookies = make(map[string][]*Cookie)
+ for _, c := range ireq.Cookies() {
+ icookies[c.Name] = append(icookies[c.Name], c)
+ }
+ }
+
+ preq := ireq // The previous request
+ return func(req *Request) {
+ // If Jar is present and there was some initial cookies provided
+ // via the request header, then we may need to alter the initial
+ // cookies as we follow redirects since each redirect may end up
+ // modifying a pre-existing cookie.
+ //
+ // Since cookies already set in the request header do not contain
+ // information about the original domain and path, the logic below
+ // assumes any new set cookies override the original cookie
+ // regardless of domain or path.
+ //
+ // See https://golang.org/issue/17494
+ if c.Jar != nil && icookies != nil {
+ var changed bool
+ resp := req.Response // The response that caused the upcoming redirect
+ for _, c := range resp.Cookies() {
+ if _, ok := icookies[c.Name]; ok {
+ delete(icookies, c.Name)
+ changed = true
+ }
+ }
+ if changed {
+ ireqhdr.Del("Cookie")
+ var ss []string
+ for _, cs := range icookies {
+ for _, c := range cs {
+ ss = append(ss, c.Name+"="+c.Value)
+ }
+ }
+ sort.Strings(ss) // Ensure deterministic headers
+ ireqhdr.Set("Cookie", strings.Join(ss, "; "))
+ }
+ }
+
+ // Copy the initial request's Header values
+ // (at least the safe ones).
+ for k, vv := range ireqhdr {
+ if shouldCopyHeaderOnRedirect(k, preq.URL, req.URL) {
+ req.Header[k] = vv
+ }
+ }
+
+ preq = req // Update previous Request with the current request
}
}
@@ -558,8 +688,11 @@ func defaultCheckRedirect(req *Request, via []*Request) error {
// Post is a wrapper around DefaultClient.Post.
//
// To set custom headers, use NewRequest and DefaultClient.Do.
-func Post(url string, bodyType string, body io.Reader) (resp *Response, err error) {
- return DefaultClient.Post(url, bodyType, body)
+//
+// See the Client.Do method documentation for details on how redirects
+// are handled.
+func Post(url string, contentType string, body io.Reader) (resp *Response, err error) {
+ return DefaultClient.Post(url, contentType, body)
}
// Post issues a POST to the specified URL.
@@ -570,13 +703,16 @@ func Post(url string, bodyType string, body io.Reader) (resp *Response, err erro
// request.
//
// To set custom headers, use NewRequest and Client.Do.
-func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *Response, err error) {
+//
+// See the Client.Do method documentation for details on how redirects
+// are handled.
+func (c *Client) Post(url string, contentType string, body io.Reader) (resp *Response, err error) {
req, err := NewRequest("POST", url, body)
if err != nil {
return nil, err
}
- req.Header.Set("Content-Type", bodyType)
- return c.doFollowingRedirects(req, shouldRedirectPost)
+ req.Header.Set("Content-Type", contentType)
+ return c.Do(req)
}
// PostForm issues a POST to the specified URL, with data's keys and
@@ -589,6 +725,9 @@ func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *Respon
// Caller should close resp.Body when done reading from it.
//
// PostForm is a wrapper around DefaultClient.PostForm.
+//
+// See the Client.Do method documentation for details on how redirects
+// are handled.
func PostForm(url string, data url.Values) (resp *Response, err error) {
return DefaultClient.PostForm(url, data)
}
@@ -601,11 +740,14 @@ func PostForm(url string, data url.Values) (resp *Response, err error) {
//
// When err is nil, resp always contains a non-nil resp.Body.
// Caller should close resp.Body when done reading from it.
+//
+// See the Client.Do method documentation for details on how redirects
+// are handled.
func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) {
return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}
-// Head issues a HEAD to the specified URL. If the response is one of
+// Head issues a HEAD to the specified URL. If the response is one of
// the following redirect codes, Head follows the redirect, up to a
// maximum of 10 redirects:
//
@@ -613,13 +755,14 @@ func (c *Client) PostForm(url string, data url.Values) (resp *Response, err erro
// 302 (Found)
// 303 (See Other)
// 307 (Temporary Redirect)
+// 308 (Permanent Redirect)
//
// Head is a wrapper around DefaultClient.Head
func Head(url string) (resp *Response, err error) {
return DefaultClient.Head(url)
}
-// Head issues a HEAD to the specified URL. If the response is one of the
+// Head issues a HEAD to the specified URL. If the response is one of the
// following redirect codes, Head follows the redirect after calling the
// Client's CheckRedirect function:
//
@@ -627,22 +770,23 @@ func Head(url string) (resp *Response, err error) {
// 302 (Found)
// 303 (See Other)
// 307 (Temporary Redirect)
+// 308 (Permanent Redirect)
func (c *Client) Head(url string) (resp *Response, err error) {
req, err := NewRequest("HEAD", url, nil)
if err != nil {
return nil, err
}
- return c.doFollowingRedirects(req, shouldRedirectGet)
+ return c.Do(req)
}
// cancelTimerBody is an io.ReadCloser that wraps rc with two features:
// 1) on Read error or close, the stop func is called.
-// 2) On Read failure, if reqWasCanceled is true, the error is wrapped and
+// 2) On Read failure, if reqDidTimeout is true, the error is wrapped and
// marked as net.Error that hit its timeout.
type cancelTimerBody struct {
- stop func() // stops the time.Timer waiting to cancel the request
- rc io.ReadCloser
- reqWasCanceled func() bool
+ stop func() // stops the time.Timer waiting to cancel the request
+ rc io.ReadCloser
+ reqDidTimeout func() bool
}
func (b *cancelTimerBody) Read(p []byte) (n int, err error) {
@@ -654,7 +798,7 @@ func (b *cancelTimerBody) Read(p []byte) (n int, err error) {
if err == io.EOF {
return n, err
}
- if b.reqWasCanceled() {
+ if b.reqDidTimeout() {
err = &httpError{
err: err.Error() + " (Client.Timeout exceeded while reading body)",
timeout: true,
@@ -668,3 +812,52 @@ func (b *cancelTimerBody) Close() error {
b.stop()
return err
}
+
+func shouldCopyHeaderOnRedirect(headerKey string, initial, dest *url.URL) bool {
+ switch CanonicalHeaderKey(headerKey) {
+ case "Authorization", "Www-Authenticate", "Cookie", "Cookie2":
+ // Permit sending auth/cookie headers from "foo.com"
+ // to "sub.foo.com".
+
+ // Note that we don't send all cookies to subdomains
+ // automatically. This function is only used for
+ // Cookies set explicitly on the initial outgoing
+ // client request. Cookies automatically added via the
+ // CookieJar mechanism continue to follow each
+ // cookie's scope as set by Set-Cookie. But for
+ // outgoing requests with the Cookie header set
+ // directly, we don't know their scope, so we assume
+ // it's for *.domain.com.
+
+ // TODO(bradfitz): once issue 16142 is fixed, make
+ // this code use those URL accessors, and consider
+ // "http://foo.com" and "http://foo.com:80" as
+ // equivalent?
+
+ // TODO(bradfitz): better hostname canonicalization,
+ // at least once we figure out IDNA/Punycode (issue
+ // 13835).
+ ihost := strings.ToLower(initial.Host)
+ dhost := strings.ToLower(dest.Host)
+ return isDomainOrSubdomain(dhost, ihost)
+ }
+ // All other headers are copied:
+ return true
+}
+
+// isDomainOrSubdomain reports whether sub is a subdomain (or exact
+// match) of the parent domain.
+//
+// Both domains must already be in canonical form.
+func isDomainOrSubdomain(sub, parent string) bool {
+ if sub == parent {
+ return true
+ }
+ // If sub is "foo.example.com" and parent is "example.com",
+ // that means sub must end in "."+parent.
+ // Do it without allocating.
+ if !strings.HasSuffix(sub, parent) {
+ return false
+ }
+ return sub[len(sub)-len(parent)-1] == '.'
+}
diff --git a/libgo/go/net/http/client_test.go b/libgo/go/net/http/client_test.go
index a9b1948005c..eaf2cdca8ee 100644
--- a/libgo/go/net/http/client_test.go
+++ b/libgo/go/net/http/client_test.go
@@ -19,11 +19,14 @@ import (
"log"
"net"
. "net/http"
+ "net/http/cookiejar"
"net/http/httptest"
"net/url"
+ "reflect"
"strconv"
"strings"
"sync"
+ "sync/atomic"
"testing"
"time"
)
@@ -65,11 +68,13 @@ func (w chanWriter) Write(p []byte) (n int, err error) {
}
func TestClient(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewServer(robotsTxtHandler)
defer ts.Close()
- r, err := Get(ts.URL)
+ c := &Client{Transport: &Transport{DisableKeepAlives: true}}
+ r, err := c.Get(ts.URL)
var b []byte
if err == nil {
b, err = pedanticReadAll(r.Body)
@@ -109,6 +114,7 @@ func (t *recordingTransport) RoundTrip(req *Request) (resp *Response, err error)
}
func TestGetRequestFormat(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
tr := &recordingTransport{}
client := &Client{Transport: tr}
@@ -195,6 +201,7 @@ func TestPostFormRequestFormat(t *testing.T) {
}
func TestClientRedirects(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
var ts *httptest.Server
ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -206,14 +213,17 @@ func TestClientRedirects(t *testing.T) {
}
}
if n < 15 {
- Redirect(w, r, fmt.Sprintf("/?n=%d", n+1), StatusFound)
+ Redirect(w, r, fmt.Sprintf("/?n=%d", n+1), StatusTemporaryRedirect)
return
}
fmt.Fprintf(w, "n=%d", n)
}))
defer ts.Close()
- c := &Client{}
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+
+ c := &Client{Transport: tr}
_, err := c.Get(ts.URL)
if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
t.Errorf("with default client Get, expected error %q, got %q", e, g)
@@ -242,11 +252,14 @@ func TestClientRedirects(t *testing.T) {
var checkErr error
var lastVia []*Request
var lastReq *Request
- c = &Client{CheckRedirect: func(req *Request, via []*Request) error {
- lastReq = req
- lastVia = via
- return checkErr
- }}
+ c = &Client{
+ Transport: tr,
+ CheckRedirect: func(req *Request, via []*Request) error {
+ lastReq = req
+ lastVia = via
+ return checkErr
+ },
+ }
res, err := c.Get(ts.URL)
if err != nil {
t.Fatalf("Get error: %v", err)
@@ -292,20 +305,27 @@ func TestClientRedirects(t *testing.T) {
}
func TestClientRedirectContext(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
- Redirect(w, r, "/", StatusFound)
+ Redirect(w, r, "/", StatusTemporaryRedirect)
}))
defer ts.Close()
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+
ctx, cancel := context.WithCancel(context.Background())
- c := &Client{CheckRedirect: func(req *Request, via []*Request) error {
- cancel()
- if len(via) > 2 {
- return errors.New("too many redirects")
- }
- return nil
- }}
+ c := &Client{
+ Transport: tr,
+ CheckRedirect: func(req *Request, via []*Request) error {
+ cancel()
+ if len(via) > 2 {
+ return errors.New("too many redirects")
+ }
+ return nil
+ },
+ }
req, _ := NewRequest("GET", ts.URL, nil)
req = req.WithContext(ctx)
_, err := c.Do(req)
@@ -313,12 +333,96 @@ func TestClientRedirectContext(t *testing.T) {
if !ok {
t.Fatalf("got error %T; want *url.Error", err)
}
- if ue.Err != ExportErrRequestCanceled && ue.Err != ExportErrRequestCanceledConn {
- t.Errorf("url.Error.Err = %v; want errRequestCanceled or errRequestCanceledConn", ue.Err)
+ if ue.Err != context.Canceled {
+ t.Errorf("url.Error.Err = %v; want %v", ue.Err, context.Canceled)
}
}
+type redirectTest struct {
+ suffix string
+ want int // response code
+ redirectBody string
+}
+
func TestPostRedirects(t *testing.T) {
+ postRedirectTests := []redirectTest{
+ {"/", 200, "first"},
+ {"/?code=301&next=302", 200, "c301"},
+ {"/?code=302&next=302", 200, "c302"},
+ {"/?code=303&next=301", 200, "c303wc301"}, // Issue 9348
+ {"/?code=304", 304, "c304"},
+ {"/?code=305", 305, "c305"},
+ {"/?code=307&next=303,308,302", 200, "c307"},
+ {"/?code=308&next=302,301", 200, "c308"},
+ {"/?code=404", 404, "c404"},
+ }
+
+ wantSegments := []string{
+ `POST / "first"`,
+ `POST /?code=301&next=302 "c301"`,
+ `GET /?code=302 "c301"`,
+ `GET / "c301"`,
+ `POST /?code=302&next=302 "c302"`,
+ `GET /?code=302 "c302"`,
+ `GET / "c302"`,
+ `POST /?code=303&next=301 "c303wc301"`,
+ `GET /?code=301 "c303wc301"`,
+ `GET / "c303wc301"`,
+ `POST /?code=304 "c304"`,
+ `POST /?code=305 "c305"`,
+ `POST /?code=307&next=303,308,302 "c307"`,
+ `POST /?code=303&next=308,302 "c307"`,
+ `GET /?code=308&next=302 "c307"`,
+ `GET /?code=302 "c307"`,
+ `GET / "c307"`,
+ `POST /?code=308&next=302,301 "c308"`,
+ `POST /?code=302&next=301 "c308"`,
+ `GET /?code=301 "c308"`,
+ `GET / "c308"`,
+ `POST /?code=404 "c404"`,
+ }
+ want := strings.Join(wantSegments, "\n")
+ testRedirectsByMethod(t, "POST", postRedirectTests, want)
+}
+
+func TestDeleteRedirects(t *testing.T) {
+ deleteRedirectTests := []redirectTest{
+ {"/", 200, "first"},
+ {"/?code=301&next=302,308", 200, "c301"},
+ {"/?code=302&next=302", 200, "c302"},
+ {"/?code=303", 200, "c303"},
+ {"/?code=307&next=301,308,303,302,304", 304, "c307"},
+ {"/?code=308&next=307", 200, "c308"},
+ {"/?code=404", 404, "c404"},
+ }
+
+ wantSegments := []string{
+ `DELETE / "first"`,
+ `DELETE /?code=301&next=302,308 "c301"`,
+ `GET /?code=302&next=308 "c301"`,
+ `GET /?code=308 "c301"`,
+ `GET / "c301"`,
+ `DELETE /?code=302&next=302 "c302"`,
+ `GET /?code=302 "c302"`,
+ `GET / "c302"`,
+ `DELETE /?code=303 "c303"`,
+ `GET / "c303"`,
+ `DELETE /?code=307&next=301,308,303,302,304 "c307"`,
+ `DELETE /?code=301&next=308,303,302,304 "c307"`,
+ `GET /?code=308&next=303,302,304 "c307"`,
+ `GET /?code=303&next=302,304 "c307"`,
+ `GET /?code=302&next=304 "c307"`,
+ `GET /?code=304 "c307"`,
+ `DELETE /?code=308&next=307 "c308"`,
+ `DELETE /?code=307 "c308"`,
+ `DELETE / "c308"`,
+ `DELETE /?code=404 "c404"`,
+ }
+ want := strings.Join(wantSegments, "\n")
+ testRedirectsByMethod(t, "DELETE", deleteRedirectTests, want)
+}
+
+func testRedirectsByMethod(t *testing.T, method string, table []redirectTest, want string) {
defer afterTest(t)
var log struct {
sync.Mutex
@@ -327,29 +431,35 @@ func TestPostRedirects(t *testing.T) {
var ts *httptest.Server
ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
log.Lock()
- fmt.Fprintf(&log.Buffer, "%s %s ", r.Method, r.RequestURI)
+ slurp, _ := ioutil.ReadAll(r.Body)
+ fmt.Fprintf(&log.Buffer, "%s %s %q\n", r.Method, r.RequestURI, slurp)
log.Unlock()
- if v := r.URL.Query().Get("code"); v != "" {
+ urlQuery := r.URL.Query()
+ if v := urlQuery.Get("code"); v != "" {
+ location := ts.URL
+ if final := urlQuery.Get("next"); final != "" {
+ splits := strings.Split(final, ",")
+ first, rest := splits[0], splits[1:]
+ location = fmt.Sprintf("%s?code=%s", location, first)
+ if len(rest) > 0 {
+ location = fmt.Sprintf("%s&next=%s", location, strings.Join(rest, ","))
+ }
+ }
code, _ := strconv.Atoi(v)
if code/100 == 3 {
- w.Header().Set("Location", ts.URL)
+ w.Header().Set("Location", location)
}
w.WriteHeader(code)
}
}))
defer ts.Close()
- tests := []struct {
- suffix string
- want int // response code
- }{
- {"/", 200},
- {"/?code=301", 301},
- {"/?code=302", 200},
- {"/?code=303", 200},
- {"/?code=404", 404},
- }
- for _, tt := range tests {
- res, err := Post(ts.URL+tt.suffix, "text/plain", strings.NewReader("Some content"))
+
+ for _, tt := range table {
+ content := tt.redirectBody
+ req, _ := NewRequest(method, ts.URL+tt.suffix, strings.NewReader(content))
+ req.GetBody = func() (io.ReadCloser, error) { return ioutil.NopCloser(strings.NewReader(content)), nil }
+ res, err := DefaultClient.Do(req)
+
if err != nil {
t.Fatal(err)
}
@@ -360,13 +470,17 @@ func TestPostRedirects(t *testing.T) {
log.Lock()
got := log.String()
log.Unlock()
- want := "POST / POST /?code=301 POST /?code=302 GET / POST /?code=303 GET / POST /?code=404 "
+
+ got = strings.TrimSpace(got)
+ want = strings.TrimSpace(want)
+
if got != want {
- t.Errorf("Log differs.\n Got: %q\nWant: %q", got, want)
+ t.Errorf("Log differs.\n Got:\n%s\nWant:\n%s\n", got, want)
}
}
func TestClientRedirectUseResponse(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
const body = "Hello, world."
var ts *httptest.Server
@@ -381,12 +495,18 @@ func TestClientRedirectUseResponse(t *testing.T) {
}))
defer ts.Close()
- c := &Client{CheckRedirect: func(req *Request, via []*Request) error {
- if req.Response == nil {
- t.Error("expected non-nil Request.Response")
- }
- return ErrUseLastResponse
- }}
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+
+ c := &Client{
+ Transport: tr,
+ CheckRedirect: func(req *Request, via []*Request) error {
+ if req.Response == nil {
+ t.Error("expected non-nil Request.Response")
+ }
+ return ErrUseLastResponse
+ },
+ }
res, err := c.Get(ts.URL)
if err != nil {
t.Fatal(err)
@@ -404,6 +524,57 @@ func TestClientRedirectUseResponse(t *testing.T) {
}
}
+// Issue 17773: don't follow a 308 (or 307) if the response doesn't
+// have a Location header.
+func TestClientRedirect308NoLocation(t *testing.T) {
+ setParallel(t)
+ defer afterTest(t)
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.Header().Set("Foo", "Bar")
+ w.WriteHeader(308)
+ }))
+ defer ts.Close()
+ res, err := Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+ if res.StatusCode != 308 {
+ t.Errorf("status = %d; want %d", res.StatusCode, 308)
+ }
+ if got := res.Header.Get("Foo"); got != "Bar" {
+ t.Errorf("Foo header = %q; want Bar", got)
+ }
+}
+
+// Don't follow a 307/308 if we can't resent the request body.
+func TestClientRedirect308NoGetBody(t *testing.T) {
+ setParallel(t)
+ defer afterTest(t)
+ const fakeURL = "https://localhost:1234/" // won't be hit
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.Header().Set("Location", fakeURL)
+ w.WriteHeader(308)
+ }))
+ defer ts.Close()
+ req, err := NewRequest("POST", ts.URL, strings.NewReader("some body"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ req.GetBody = nil // so it can't rewind.
+ res, err := DefaultClient.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+ if res.StatusCode != 308 {
+ t.Errorf("status = %d; want %d", res.StatusCode, 308)
+ }
+ if got := res.Header.Get("Location"); got != fakeURL {
+ t.Errorf("Location header = %q; want %q", got, fakeURL)
+ }
+}
+
var expectedCookies = []*Cookie{
{Name: "ChocolateChip", Value: "tasty"},
{Name: "First", Value: "Hit"},
@@ -476,12 +647,16 @@ func (j *TestJar) Cookies(u *url.URL) []*Cookie {
}
func TestRedirectCookiesJar(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
var ts *httptest.Server
ts = httptest.NewServer(echoCookiesRedirectHandler)
defer ts.Close()
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
c := &Client{
- Jar: new(TestJar),
+ Transport: tr,
+ Jar: new(TestJar),
}
u, _ := url.Parse(ts.URL)
c.Jar.SetCookies(u, []*Cookie{expectedCookies[0]})
@@ -665,6 +840,7 @@ func TestClientWrites(t *testing.T) {
}
func TestClientInsecureTransport(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
w.Write([]byte("Hello"))
@@ -842,6 +1018,7 @@ func TestResponseSetsTLSConnectionState(t *testing.T) {
func TestHTTPSClientDetectsHTTPServer(t *testing.T) {
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+ ts.Config.ErrorLog = quietLog
defer ts.Close()
_, err := Get(strings.Replace(ts.URL, "http", "https", 1))
@@ -895,6 +1072,7 @@ func testClientHeadContentLength(t *testing.T, h2 bool) {
}
func TestEmptyPasswordAuth(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
gopher := "gopher"
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -915,7 +1093,9 @@ func TestEmptyPasswordAuth(t *testing.T) {
}
}))
defer ts.Close()
- c := &Client{}
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+ c := &Client{Transport: tr}
req, err := NewRequest("GET", ts.URL, nil)
if err != nil {
t.Fatal(err)
@@ -1007,10 +1187,10 @@ func TestClientTimeout_h1(t *testing.T) { testClientTimeout(t, h1Mode) }
func TestClientTimeout_h2(t *testing.T) { testClientTimeout(t, h2Mode) }
func testClientTimeout(t *testing.T, h2 bool) {
- if testing.Short() {
- t.Skip("skipping in short mode")
- }
+ setParallel(t)
defer afterTest(t)
+ testDone := make(chan struct{}) // closed in defer below
+
sawRoot := make(chan bool, 1)
sawSlow := make(chan bool, 1)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -1020,19 +1200,26 @@ func testClientTimeout(t *testing.T, h2 bool) {
return
}
if r.URL.Path == "/slow" {
+ sawSlow <- true
w.Write([]byte("Hello"))
w.(Flusher).Flush()
- sawSlow <- true
- time.Sleep(2 * time.Second)
+ <-testDone
return
}
}))
defer cst.close()
- const timeout = 500 * time.Millisecond
+ defer close(testDone) // before cst.close, to unblock /slow handler
+
+ // 200ms should be long enough to get a normal request (the /
+ // handler), but not so long that it makes the test slow.
+ const timeout = 200 * time.Millisecond
cst.c.Timeout = timeout
res, err := cst.c.Get(cst.ts.URL)
if err != nil {
+ if strings.Contains(err.Error(), "Client.Timeout") {
+ t.Skipf("host too slow to get fast resource in %v", timeout)
+ }
t.Fatal(err)
}
@@ -1057,7 +1244,7 @@ func testClientTimeout(t *testing.T, h2 bool) {
res.Body.Close()
}()
- const failTime = timeout * 2
+ const failTime = 5 * time.Second
select {
case err := <-errc:
if err == nil {
@@ -1082,11 +1269,9 @@ func TestClientTimeout_Headers_h2(t *testing.T) { testClientTimeout_Headers(t, h
// Client.Timeout firing before getting to the body
func testClientTimeout_Headers(t *testing.T, h2 bool) {
- if testing.Short() {
- t.Skip("skipping in short mode")
- }
+ setParallel(t)
defer afterTest(t)
- donec := make(chan bool)
+ donec := make(chan bool, 1)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
<-donec
}))
@@ -1100,9 +1285,10 @@ func testClientTimeout_Headers(t *testing.T, h2 bool) {
// doesn't know this, so synchronize explicitly.
defer func() { donec <- true }()
- cst.c.Timeout = 500 * time.Millisecond
- _, err := cst.c.Get(cst.ts.URL)
+ cst.c.Timeout = 5 * time.Millisecond
+ res, err := cst.c.Get(cst.ts.URL)
if err == nil {
+ res.Body.Close()
t.Fatal("got response from Get; expected error")
}
if _, ok := err.(*url.Error); !ok {
@@ -1120,9 +1306,40 @@ func testClientTimeout_Headers(t *testing.T, h2 bool) {
}
}
+// Issue 16094: if Client.Timeout is set but not hit, a Timeout error shouldn't be
+// returned.
+func TestClientTimeoutCancel(t *testing.T) {
+ setParallel(t)
+ defer afterTest(t)
+
+ testDone := make(chan struct{})
+ ctx, cancel := context.WithCancel(context.Background())
+
+ cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.(Flusher).Flush()
+ <-testDone
+ }))
+ defer cst.close()
+ defer close(testDone)
+
+ cst.c.Timeout = 1 * time.Hour
+ req, _ := NewRequest("GET", cst.ts.URL, nil)
+ req.Cancel = ctx.Done()
+ res, err := cst.c.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ cancel()
+ _, err = io.Copy(ioutil.Discard, res.Body)
+ if err != ExportErrRequestCanceled {
+ t.Fatalf("error = %v; want errRequestCanceled", err)
+ }
+}
+
func TestClientRedirectEatsBody_h1(t *testing.T) { testClientRedirectEatsBody(t, h1Mode) }
func TestClientRedirectEatsBody_h2(t *testing.T) { testClientRedirectEatsBody(t, h2Mode) }
func testClientRedirectEatsBody(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
saw := make(chan string, 2)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -1138,10 +1355,10 @@ func testClientRedirectEatsBody(t *testing.T, h2 bool) {
t.Fatal(err)
}
_, err = ioutil.ReadAll(res.Body)
+ res.Body.Close()
if err != nil {
t.Fatal(err)
}
- res.Body.Close()
var first string
select {
@@ -1229,3 +1446,369 @@ func TestClientRedirectResponseWithoutRequest(t *testing.T) {
// Check that this doesn't crash:
c.Get("http://dummy.tld")
}
+
+// Issue 4800: copy (some) headers when Client follows a redirect
+func TestClientCopyHeadersOnRedirect(t *testing.T) {
+ const (
+ ua = "some-agent/1.2"
+ xfoo = "foo-val"
+ )
+ var ts2URL string
+ ts1 := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ want := Header{
+ "User-Agent": []string{ua},
+ "X-Foo": []string{xfoo},
+ "Referer": []string{ts2URL},
+ "Accept-Encoding": []string{"gzip"},
+ }
+ if !reflect.DeepEqual(r.Header, want) {
+ t.Errorf("Request.Header = %#v; want %#v", r.Header, want)
+ }
+ if t.Failed() {
+ w.Header().Set("Result", "got errors")
+ } else {
+ w.Header().Set("Result", "ok")
+ }
+ }))
+ defer ts1.Close()
+ ts2 := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ Redirect(w, r, ts1.URL, StatusFound)
+ }))
+ defer ts2.Close()
+ ts2URL = ts2.URL
+
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+ c := &Client{
+ Transport: tr,
+ CheckRedirect: func(r *Request, via []*Request) error {
+ want := Header{
+ "User-Agent": []string{ua},
+ "X-Foo": []string{xfoo},
+ "Referer": []string{ts2URL},
+ }
+ if !reflect.DeepEqual(r.Header, want) {
+ t.Errorf("CheckRedirect Request.Header = %#v; want %#v", r.Header, want)
+ }
+ return nil
+ },
+ }
+
+ req, _ := NewRequest("GET", ts2.URL, nil)
+ req.Header.Add("User-Agent", ua)
+ req.Header.Add("X-Foo", xfoo)
+ req.Header.Add("Cookie", "foo=bar")
+ req.Header.Add("Authorization", "secretpassword")
+ res, err := c.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ if res.StatusCode != 200 {
+ t.Fatal(res.Status)
+ }
+ if got := res.Header.Get("Result"); got != "ok" {
+ t.Errorf("result = %q; want ok", got)
+ }
+}
+
+// Issue 17494: cookies should be altered when Client follows redirects.
+func TestClientAltersCookiesOnRedirect(t *testing.T) {
+ cookieMap := func(cs []*Cookie) map[string][]string {
+ m := make(map[string][]string)
+ for _, c := range cs {
+ m[c.Name] = append(m[c.Name], c.Value)
+ }
+ return m
+ }
+
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ var want map[string][]string
+ got := cookieMap(r.Cookies())
+
+ c, _ := r.Cookie("Cycle")
+ switch c.Value {
+ case "0":
+ want = map[string][]string{
+ "Cookie1": {"OldValue1a", "OldValue1b"},
+ "Cookie2": {"OldValue2"},
+ "Cookie3": {"OldValue3a", "OldValue3b"},
+ "Cookie4": {"OldValue4"},
+ "Cycle": {"0"},
+ }
+ SetCookie(w, &Cookie{Name: "Cycle", Value: "1", Path: "/"})
+ SetCookie(w, &Cookie{Name: "Cookie2", Path: "/", MaxAge: -1}) // Delete cookie from Header
+ Redirect(w, r, "/", StatusFound)
+ case "1":
+ want = map[string][]string{
+ "Cookie1": {"OldValue1a", "OldValue1b"},
+ "Cookie3": {"OldValue3a", "OldValue3b"},
+ "Cookie4": {"OldValue4"},
+ "Cycle": {"1"},
+ }
+ SetCookie(w, &Cookie{Name: "Cycle", Value: "2", Path: "/"})
+ SetCookie(w, &Cookie{Name: "Cookie3", Value: "NewValue3", Path: "/"}) // Modify cookie in Header
+ SetCookie(w, &Cookie{Name: "Cookie4", Value: "NewValue4", Path: "/"}) // Modify cookie in Jar
+ Redirect(w, r, "/", StatusFound)
+ case "2":
+ want = map[string][]string{
+ "Cookie1": {"OldValue1a", "OldValue1b"},
+ "Cookie3": {"NewValue3"},
+ "Cookie4": {"NewValue4"},
+ "Cycle": {"2"},
+ }
+ SetCookie(w, &Cookie{Name: "Cycle", Value: "3", Path: "/"})
+ SetCookie(w, &Cookie{Name: "Cookie5", Value: "NewValue5", Path: "/"}) // Insert cookie into Jar
+ Redirect(w, r, "/", StatusFound)
+ case "3":
+ want = map[string][]string{
+ "Cookie1": {"OldValue1a", "OldValue1b"},
+ "Cookie3": {"NewValue3"},
+ "Cookie4": {"NewValue4"},
+ "Cookie5": {"NewValue5"},
+ "Cycle": {"3"},
+ }
+ // Don't redirect to ensure the loop ends.
+ default:
+ t.Errorf("unexpected redirect cycle")
+ return
+ }
+
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("redirect %s, Cookie = %v, want %v", c.Value, got, want)
+ }
+ }))
+ defer ts.Close()
+
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+ jar, _ := cookiejar.New(nil)
+ c := &Client{
+ Transport: tr,
+ Jar: jar,
+ }
+
+ u, _ := url.Parse(ts.URL)
+ req, _ := NewRequest("GET", ts.URL, nil)
+ req.AddCookie(&Cookie{Name: "Cookie1", Value: "OldValue1a"})
+ req.AddCookie(&Cookie{Name: "Cookie1", Value: "OldValue1b"})
+ req.AddCookie(&Cookie{Name: "Cookie2", Value: "OldValue2"})
+ req.AddCookie(&Cookie{Name: "Cookie3", Value: "OldValue3a"})
+ req.AddCookie(&Cookie{Name: "Cookie3", Value: "OldValue3b"})
+ jar.SetCookies(u, []*Cookie{{Name: "Cookie4", Value: "OldValue4", Path: "/"}})
+ jar.SetCookies(u, []*Cookie{{Name: "Cycle", Value: "0", Path: "/"}})
+ res, err := c.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ if res.StatusCode != 200 {
+ t.Fatal(res.Status)
+ }
+}
+
+// Part of Issue 4800
+func TestShouldCopyHeaderOnRedirect(t *testing.T) {
+ tests := []struct {
+ header string
+ initialURL string
+ destURL string
+ want bool
+ }{
+ {"User-Agent", "http://foo.com/", "http://bar.com/", true},
+ {"X-Foo", "http://foo.com/", "http://bar.com/", true},
+
+ // Sensitive headers:
+ {"cookie", "http://foo.com/", "http://bar.com/", false},
+ {"cookie2", "http://foo.com/", "http://bar.com/", false},
+ {"authorization", "http://foo.com/", "http://bar.com/", false},
+ {"www-authenticate", "http://foo.com/", "http://bar.com/", false},
+
+ // But subdomains should work:
+ {"www-authenticate", "http://foo.com/", "http://foo.com/", true},
+ {"www-authenticate", "http://foo.com/", "http://sub.foo.com/", true},
+ {"www-authenticate", "http://foo.com/", "http://notfoo.com/", false},
+ // TODO(bradfitz): make this test work, once issue 16142 is fixed:
+ // {"www-authenticate", "http://foo.com:80/", "http://foo.com/", true},
+ }
+ for i, tt := range tests {
+ u0, err := url.Parse(tt.initialURL)
+ if err != nil {
+ t.Errorf("%d. initial URL %q parse error: %v", i, tt.initialURL, err)
+ continue
+ }
+ u1, err := url.Parse(tt.destURL)
+ if err != nil {
+ t.Errorf("%d. dest URL %q parse error: %v", i, tt.destURL, err)
+ continue
+ }
+ got := Export_shouldCopyHeaderOnRedirect(tt.header, u0, u1)
+ if got != tt.want {
+ t.Errorf("%d. shouldCopyHeaderOnRedirect(%q, %q => %q) = %v; want %v",
+ i, tt.header, tt.initialURL, tt.destURL, got, tt.want)
+ }
+ }
+}
+
+func TestClientRedirectTypes(t *testing.T) {
+ setParallel(t)
+ defer afterTest(t)
+
+ tests := [...]struct {
+ method string
+ serverStatus int
+ wantMethod string // desired subsequent client method
+ }{
+ 0: {method: "POST", serverStatus: 301, wantMethod: "GET"},
+ 1: {method: "POST", serverStatus: 302, wantMethod: "GET"},
+ 2: {method: "POST", serverStatus: 303, wantMethod: "GET"},
+ 3: {method: "POST", serverStatus: 307, wantMethod: "POST"},
+ 4: {method: "POST", serverStatus: 308, wantMethod: "POST"},
+
+ 5: {method: "HEAD", serverStatus: 301, wantMethod: "HEAD"},
+ 6: {method: "HEAD", serverStatus: 302, wantMethod: "HEAD"},
+ 7: {method: "HEAD", serverStatus: 303, wantMethod: "HEAD"},
+ 8: {method: "HEAD", serverStatus: 307, wantMethod: "HEAD"},
+ 9: {method: "HEAD", serverStatus: 308, wantMethod: "HEAD"},
+
+ 10: {method: "GET", serverStatus: 301, wantMethod: "GET"},
+ 11: {method: "GET", serverStatus: 302, wantMethod: "GET"},
+ 12: {method: "GET", serverStatus: 303, wantMethod: "GET"},
+ 13: {method: "GET", serverStatus: 307, wantMethod: "GET"},
+ 14: {method: "GET", serverStatus: 308, wantMethod: "GET"},
+
+ 15: {method: "DELETE", serverStatus: 301, wantMethod: "GET"},
+ 16: {method: "DELETE", serverStatus: 302, wantMethod: "GET"},
+ 17: {method: "DELETE", serverStatus: 303, wantMethod: "GET"},
+ 18: {method: "DELETE", serverStatus: 307, wantMethod: "DELETE"},
+ 19: {method: "DELETE", serverStatus: 308, wantMethod: "DELETE"},
+
+ 20: {method: "PUT", serverStatus: 301, wantMethod: "GET"},
+ 21: {method: "PUT", serverStatus: 302, wantMethod: "GET"},
+ 22: {method: "PUT", serverStatus: 303, wantMethod: "GET"},
+ 23: {method: "PUT", serverStatus: 307, wantMethod: "PUT"},
+ 24: {method: "PUT", serverStatus: 308, wantMethod: "PUT"},
+
+ 25: {method: "MADEUPMETHOD", serverStatus: 301, wantMethod: "GET"},
+ 26: {method: "MADEUPMETHOD", serverStatus: 302, wantMethod: "GET"},
+ 27: {method: "MADEUPMETHOD", serverStatus: 303, wantMethod: "GET"},
+ 28: {method: "MADEUPMETHOD", serverStatus: 307, wantMethod: "MADEUPMETHOD"},
+ 29: {method: "MADEUPMETHOD", serverStatus: 308, wantMethod: "MADEUPMETHOD"},
+ }
+
+ handlerc := make(chan HandlerFunc, 1)
+
+ ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+ h := <-handlerc
+ h(rw, req)
+ }))
+ defer ts.Close()
+
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+
+ for i, tt := range tests {
+ handlerc <- func(w ResponseWriter, r *Request) {
+ w.Header().Set("Location", ts.URL)
+ w.WriteHeader(tt.serverStatus)
+ }
+
+ req, err := NewRequest(tt.method, ts.URL, nil)
+ if err != nil {
+ t.Errorf("#%d: NewRequest: %v", i, err)
+ continue
+ }
+
+ c := &Client{Transport: tr}
+ c.CheckRedirect = func(req *Request, via []*Request) error {
+ if got, want := req.Method, tt.wantMethod; got != want {
+ return fmt.Errorf("#%d: got next method %q; want %q", i, got, want)
+ }
+ handlerc <- func(rw ResponseWriter, req *Request) {
+ // TODO: Check that the body is valid when we do 307 and 308 support
+ }
+ return nil
+ }
+
+ res, err := c.Do(req)
+ if err != nil {
+ t.Errorf("#%d: Response: %v", i, err)
+ continue
+ }
+
+ res.Body.Close()
+ }
+}
+
+// issue18239Body is an io.ReadCloser for TestTransportBodyReadError.
+// Its Read returns readErr and increments *readCalls atomically.
+// Its Close returns nil and increments *closeCalls atomically.
+type issue18239Body struct {
+ readCalls *int32
+ closeCalls *int32
+ readErr error
+}
+
+func (b issue18239Body) Read([]byte) (int, error) {
+ atomic.AddInt32(b.readCalls, 1)
+ return 0, b.readErr
+}
+
+func (b issue18239Body) Close() error {
+ atomic.AddInt32(b.closeCalls, 1)
+ return nil
+}
+
+// Issue 18239: make sure the Transport doesn't retry requests with bodies.
+// (Especially if Request.GetBody is not defined.)
+func TestTransportBodyReadError(t *testing.T) {
+ setParallel(t)
+ defer afterTest(t)
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ if r.URL.Path == "/ping" {
+ return
+ }
+ buf := make([]byte, 1)
+ n, err := r.Body.Read(buf)
+ w.Header().Set("X-Body-Read", fmt.Sprintf("%v, %v", n, err))
+ }))
+ defer ts.Close()
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+ c := &Client{Transport: tr}
+
+ // Do one initial successful request to create an idle TCP connection
+ // for the subsequent request to reuse. (The Transport only retries
+ // requests on reused connections.)
+ res, err := c.Get(ts.URL + "/ping")
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+
+ var readCallsAtomic int32
+ var closeCallsAtomic int32 // atomic
+ someErr := errors.New("some body read error")
+ body := issue18239Body{&readCallsAtomic, &closeCallsAtomic, someErr}
+
+ req, err := NewRequest("POST", ts.URL, body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = tr.RoundTrip(req)
+ if err != someErr {
+ t.Errorf("Got error: %v; want Request.Body read error: %v", err, someErr)
+ }
+
+ // And verify that our Body wasn't used multiple times, which
+ // would indicate retries. (as it buggily was during part of
+ // Go 1.8's dev cycle)
+ readCalls := atomic.LoadInt32(&readCallsAtomic)
+ closeCalls := atomic.LoadInt32(&closeCallsAtomic)
+ if readCalls != 1 {
+ t.Errorf("read calls = %d; want 1", readCalls)
+ }
+ if closeCalls != 1 {
+ t.Errorf("close calls = %d; want 1", closeCalls)
+ }
+}
diff --git a/libgo/go/net/http/clientserver_test.go b/libgo/go/net/http/clientserver_test.go
index 3d1f09cae83..580115ca9c0 100644
--- a/libgo/go/net/http/clientserver_test.go
+++ b/libgo/go/net/http/clientserver_test.go
@@ -44,6 +44,19 @@ func (t *clientServerTest) close() {
t.ts.Close()
}
+func (t *clientServerTest) getURL(u string) string {
+ res, err := t.c.Get(u)
+ if err != nil {
+ t.t.Fatal(err)
+ }
+ defer res.Body.Close()
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.t.Fatal(err)
+ }
+ return string(slurp)
+}
+
func (t *clientServerTest) scheme() string {
if t.h2 {
return "https"
@@ -56,6 +69,10 @@ const (
h2Mode = true
)
+var optQuietLog = func(ts *httptest.Server) {
+ ts.Config.ErrorLog = quietLog
+}
+
func newClientServerTest(t *testing.T, h2 bool, h Handler, opts ...interface{}) *clientServerTest {
cst := &clientServerTest{
t: t,
@@ -64,21 +81,23 @@ func newClientServerTest(t *testing.T, h2 bool, h Handler, opts ...interface{})
tr: &Transport{},
}
cst.c = &Client{Transport: cst.tr}
+ cst.ts = httptest.NewUnstartedServer(h)
for _, opt := range opts {
switch opt := opt.(type) {
case func(*Transport):
opt(cst.tr)
+ case func(*httptest.Server):
+ opt(cst.ts)
default:
t.Fatalf("unhandled option type %T", opt)
}
}
if !h2 {
- cst.ts = httptest.NewServer(h)
+ cst.ts.Start()
return cst
}
- cst.ts = httptest.NewUnstartedServer(h)
ExportHttp2ConfigureServer(cst.ts.Config, nil)
cst.ts.TLS = cst.ts.Config.TLSConfig
cst.ts.StartTLS()
@@ -170,6 +189,7 @@ func (tt h12Compare) reqFunc() reqFunc {
}
func (tt h12Compare) run(t *testing.T) {
+ setParallel(t)
cst1 := newClientServerTest(t, false, HandlerFunc(tt.Handler), tt.Opts...)
defer cst1.close()
cst2 := newClientServerTest(t, true, HandlerFunc(tt.Handler), tt.Opts...)
@@ -468,7 +488,7 @@ func TestH12_RequestContentLength_Known_NonZero(t *testing.T) {
}
func TestH12_RequestContentLength_Known_Zero(t *testing.T) {
- h12requestContentLength(t, func() io.Reader { return strings.NewReader("") }, 0)
+ h12requestContentLength(t, func() io.Reader { return nil }, 0)
}
func TestH12_RequestContentLength_Unknown(t *testing.T) {
@@ -938,6 +958,7 @@ func testStarRequest(t *testing.T, method string, h2 bool) {
// Issue 13957
func TestTransportDiscardsUnneededConns(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "Hello, %v", r.RemoteAddr)
@@ -1026,6 +1047,7 @@ func testTransportGCRequest(t *testing.T, h2, body bool) {
t.Skip("skipping on gccgo because conservative GC means that finalizer may never run")
}
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
ioutil.ReadAll(r.Body)
@@ -1072,10 +1094,11 @@ func TestTransportRejectsInvalidHeaders_h2(t *testing.T) {
testTransportRejectsInvalidHeaders(t, h2Mode)
}
func testTransportRejectsInvalidHeaders(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "Handler saw headers: %q", r.Header)
- }))
+ }), optQuietLog)
defer cst.close()
cst.tr.DisableKeepAlives = true
@@ -1143,24 +1166,44 @@ func testBogusStatusWorks(t *testing.T, h2 bool) {
}
}
-func TestInterruptWithPanic_h1(t *testing.T) { testInterruptWithPanic(t, h1Mode) }
-func TestInterruptWithPanic_h2(t *testing.T) { testInterruptWithPanic(t, h2Mode) }
-func testInterruptWithPanic(t *testing.T, h2 bool) {
- log.SetOutput(ioutil.Discard) // is noisy otherwise
- defer log.SetOutput(os.Stderr)
-
+func TestInterruptWithPanic_h1(t *testing.T) { testInterruptWithPanic(t, h1Mode, "boom") }
+func TestInterruptWithPanic_h2(t *testing.T) { testInterruptWithPanic(t, h2Mode, "boom") }
+func TestInterruptWithPanic_nil_h1(t *testing.T) { testInterruptWithPanic(t, h1Mode, nil) }
+func TestInterruptWithPanic_nil_h2(t *testing.T) { testInterruptWithPanic(t, h2Mode, nil) }
+func TestInterruptWithPanic_ErrAbortHandler_h1(t *testing.T) {
+ testInterruptWithPanic(t, h1Mode, ErrAbortHandler)
+}
+func TestInterruptWithPanic_ErrAbortHandler_h2(t *testing.T) {
+ testInterruptWithPanic(t, h2Mode, ErrAbortHandler)
+}
+func testInterruptWithPanic(t *testing.T, h2 bool, panicValue interface{}) {
+ setParallel(t)
const msg = "hello"
defer afterTest(t)
+
+ testDone := make(chan struct{})
+ defer close(testDone)
+
+ var errorLog lockedBytesBuffer
+ gotHeaders := make(chan bool, 1)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
io.WriteString(w, msg)
w.(Flusher).Flush()
- panic("no more")
- }))
+
+ select {
+ case <-gotHeaders:
+ case <-testDone:
+ }
+ panic(panicValue)
+ }), func(ts *httptest.Server) {
+ ts.Config.ErrorLog = log.New(&errorLog, "", 0)
+ })
defer cst.close()
res, err := cst.c.Get(cst.ts.URL)
if err != nil {
t.Fatal(err)
}
+ gotHeaders <- true
defer res.Body.Close()
slurp, err := ioutil.ReadAll(res.Body)
if string(slurp) != msg {
@@ -1169,6 +1212,42 @@ func testInterruptWithPanic(t *testing.T, h2 bool) {
if err == nil {
t.Errorf("client read all successfully; want some error")
}
+ logOutput := func() string {
+ errorLog.Lock()
+ defer errorLog.Unlock()
+ return errorLog.String()
+ }
+ wantStackLogged := panicValue != nil && panicValue != ErrAbortHandler
+
+ if err := waitErrCondition(5*time.Second, 10*time.Millisecond, func() error {
+ gotLog := logOutput()
+ if !wantStackLogged {
+ if gotLog == "" {
+ return nil
+ }
+ return fmt.Errorf("want no log output; got: %s", gotLog)
+ }
+ if gotLog == "" {
+ return fmt.Errorf("wanted a stack trace logged; got nothing")
+ }
+ if !strings.Contains(gotLog, "created by ") && strings.Count(gotLog, "\n") < 6 {
+ return fmt.Errorf("output doesn't look like a panic stack trace. Got: %s", gotLog)
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+}
+
+type lockedBytesBuffer struct {
+ sync.Mutex
+ bytes.Buffer
+}
+
+func (b *lockedBytesBuffer) Write(p []byte) (int, error) {
+ b.Lock()
+ defer b.Unlock()
+ return b.Buffer.Write(p)
}
// Issue 15366
@@ -1204,6 +1283,7 @@ func TestH12_AutoGzipWithDumpResponse(t *testing.T) {
func TestCloseIdleConnections_h1(t *testing.T) { testCloseIdleConnections(t, h1Mode) }
func TestCloseIdleConnections_h2(t *testing.T) { testCloseIdleConnections(t, h2Mode) }
func testCloseIdleConnections(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("X-Addr", r.RemoteAddr)
@@ -1238,3 +1318,70 @@ func (x noteCloseConn) Close() error {
x.closeFunc()
return x.Conn.Close()
}
+
+type testErrorReader struct{ t *testing.T }
+
+func (r testErrorReader) Read(p []byte) (n int, err error) {
+ r.t.Error("unexpected Read call")
+ return 0, io.EOF
+}
+
+func TestNoSniffExpectRequestBody_h1(t *testing.T) { testNoSniffExpectRequestBody(t, h1Mode) }
+func TestNoSniffExpectRequestBody_h2(t *testing.T) { testNoSniffExpectRequestBody(t, h2Mode) }
+
+func testNoSniffExpectRequestBody(t *testing.T, h2 bool) {
+ defer afterTest(t)
+ cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.WriteHeader(StatusUnauthorized)
+ }))
+ defer cst.close()
+
+ // Set ExpectContinueTimeout non-zero so RoundTrip won't try to write it.
+ cst.tr.ExpectContinueTimeout = 10 * time.Second
+
+ req, err := NewRequest("POST", cst.ts.URL, testErrorReader{t})
+ if err != nil {
+ t.Fatal(err)
+ }
+ req.ContentLength = 0 // so transport is tempted to sniff it
+ req.Header.Set("Expect", "100-continue")
+ res, err := cst.tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ if res.StatusCode != StatusUnauthorized {
+ t.Errorf("status code = %v; want %v", res.StatusCode, StatusUnauthorized)
+ }
+}
+
+func TestServerUndeclaredTrailers_h1(t *testing.T) { testServerUndeclaredTrailers(t, h1Mode) }
+func TestServerUndeclaredTrailers_h2(t *testing.T) { testServerUndeclaredTrailers(t, h2Mode) }
+func testServerUndeclaredTrailers(t *testing.T, h2 bool) {
+ defer afterTest(t)
+ cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+ w.Header().Set("Foo", "Bar")
+ w.Header().Set("Trailer:Foo", "Baz")
+ w.(Flusher).Flush()
+ w.Header().Add("Trailer:Foo", "Baz2")
+ w.Header().Set("Trailer:Bar", "Quux")
+ }))
+ defer cst.close()
+ res, err := cst.c.Get(cst.ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+ delete(res.Header, "Date")
+ delete(res.Header, "Content-Type")
+
+ if want := (Header{"Foo": {"Bar"}}); !reflect.DeepEqual(res.Header, want) {
+ t.Errorf("Header = %#v; want %#v", res.Header, want)
+ }
+ if want := (Header{"Foo": {"Baz", "Baz2"}, "Bar": {"Quux"}}); !reflect.DeepEqual(res.Trailer, want) {
+ t.Errorf("Trailer = %#v; want %#v", res.Trailer, want)
+ }
+}
diff --git a/libgo/go/net/http/cookie.go b/libgo/go/net/http/cookie.go
index 1ea0e9397a3..5a67476cd42 100644
--- a/libgo/go/net/http/cookie.go
+++ b/libgo/go/net/http/cookie.go
@@ -6,7 +6,6 @@ package http
import (
"bytes"
- "fmt"
"log"
"net"
"strconv"
@@ -40,7 +39,11 @@ type Cookie struct {
// readSetCookies parses all "Set-Cookie" values from
// the header h and returns the successfully parsed Cookies.
func readSetCookies(h Header) []*Cookie {
- cookies := []*Cookie{}
+ cookieCount := len(h["Set-Cookie"])
+ if cookieCount == 0 {
+ return []*Cookie{}
+ }
+ cookies := make([]*Cookie, 0, cookieCount)
for _, line := range h["Set-Cookie"] {
parts := strings.Split(strings.TrimSpace(line), ";")
if len(parts) == 1 && parts[0] == "" {
@@ -55,8 +58,8 @@ func readSetCookies(h Header) []*Cookie {
if !isCookieNameValid(name) {
continue
}
- value, success := parseCookieValue(value, true)
- if !success {
+ value, ok := parseCookieValue(value, true)
+ if !ok {
continue
}
c := &Cookie{
@@ -75,8 +78,8 @@ func readSetCookies(h Header) []*Cookie {
attr, val = attr[:j], attr[j+1:]
}
lowerAttr := strings.ToLower(attr)
- val, success = parseCookieValue(val, false)
- if !success {
+ val, ok = parseCookieValue(val, false)
+ if !ok {
c.Unparsed = append(c.Unparsed, parts[i])
continue
}
@@ -96,10 +99,9 @@ func readSetCookies(h Header) []*Cookie {
break
}
if secs <= 0 {
- c.MaxAge = -1
- } else {
- c.MaxAge = secs
+ secs = -1
}
+ c.MaxAge = secs
continue
case "expires":
c.RawExpires = val
@@ -142,9 +144,13 @@ func (c *Cookie) String() string {
return ""
}
var b bytes.Buffer
- fmt.Fprintf(&b, "%s=%s", sanitizeCookieName(c.Name), sanitizeCookieValue(c.Value))
+ b.WriteString(sanitizeCookieName(c.Name))
+ b.WriteRune('=')
+ b.WriteString(sanitizeCookieValue(c.Value))
+
if len(c.Path) > 0 {
- fmt.Fprintf(&b, "; Path=%s", sanitizeCookiePath(c.Path))
+ b.WriteString("; Path=")
+ b.WriteString(sanitizeCookiePath(c.Path))
}
if len(c.Domain) > 0 {
if validCookieDomain(c.Domain) {
@@ -156,25 +162,31 @@ func (c *Cookie) String() string {
if d[0] == '.' {
d = d[1:]
}
- fmt.Fprintf(&b, "; Domain=%s", d)
+ b.WriteString("; Domain=")
+ b.WriteString(d)
} else {
- log.Printf("net/http: invalid Cookie.Domain %q; dropping domain attribute",
- c.Domain)
+ log.Printf("net/http: invalid Cookie.Domain %q; dropping domain attribute", c.Domain)
}
}
- if c.Expires.Unix() > 0 {
- fmt.Fprintf(&b, "; Expires=%s", c.Expires.UTC().Format(TimeFormat))
+ if validCookieExpires(c.Expires) {
+ b.WriteString("; Expires=")
+ b2 := b.Bytes()
+ b.Reset()
+ b.Write(c.Expires.UTC().AppendFormat(b2, TimeFormat))
}
if c.MaxAge > 0 {
- fmt.Fprintf(&b, "; Max-Age=%d", c.MaxAge)
+ b.WriteString("; Max-Age=")
+ b2 := b.Bytes()
+ b.Reset()
+ b.Write(strconv.AppendInt(b2, int64(c.MaxAge), 10))
} else if c.MaxAge < 0 {
- fmt.Fprintf(&b, "; Max-Age=0")
+ b.WriteString("; Max-Age=0")
}
if c.HttpOnly {
- fmt.Fprintf(&b, "; HttpOnly")
+ b.WriteString("; HttpOnly")
}
if c.Secure {
- fmt.Fprintf(&b, "; Secure")
+ b.WriteString("; Secure")
}
return b.String()
}
@@ -184,12 +196,12 @@ func (c *Cookie) String() string {
//
// if filter isn't empty, only cookies of that name are returned
func readCookies(h Header, filter string) []*Cookie {
- cookies := []*Cookie{}
lines, ok := h["Cookie"]
if !ok {
- return cookies
+ return []*Cookie{}
}
+ cookies := []*Cookie{}
for _, line := range lines {
parts := strings.Split(strings.TrimSpace(line), ";")
if len(parts) == 1 && parts[0] == "" {
@@ -212,8 +224,8 @@ func readCookies(h Header, filter string) []*Cookie {
if filter != "" && filter != name {
continue
}
- val, success := parseCookieValue(val, true)
- if !success {
+ val, ok := parseCookieValue(val, true)
+ if !ok {
continue
}
cookies = append(cookies, &Cookie{Name: name, Value: val})
@@ -234,6 +246,12 @@ func validCookieDomain(v string) bool {
return false
}
+// validCookieExpires returns whether v is a valid cookie expires-value.
+func validCookieExpires(t time.Time) bool {
+ // IETF RFC 6265 Section 5.1.1.5, the year must not be less than 1601
+ return t.Year() >= 1601
+}
+
// isCookieDomainName returns whether s is a valid domain name or a valid
// domain name with a leading dot '.'. It is almost a direct copy of
// package net's isDomainName.
diff --git a/libgo/go/net/http/cookie_test.go b/libgo/go/net/http/cookie_test.go
index 95e61479a15..b3e54f8db32 100644
--- a/libgo/go/net/http/cookie_test.go
+++ b/libgo/go/net/http/cookie_test.go
@@ -56,6 +56,15 @@ var writeSetCookiesTests = []struct {
&Cookie{Name: "cookie-9", Value: "expiring", Expires: time.Unix(1257894000, 0)},
"cookie-9=expiring; Expires=Tue, 10 Nov 2009 23:00:00 GMT",
},
+ // According to IETF 6265 Section 5.1.1.5, the year cannot be less than 1601
+ {
+ &Cookie{Name: "cookie-10", Value: "expiring-1601", Expires: time.Date(1601, 1, 1, 1, 1, 1, 1, time.UTC)},
+ "cookie-10=expiring-1601; Expires=Mon, 01 Jan 1601 01:01:01 GMT",
+ },
+ {
+ &Cookie{Name: "cookie-11", Value: "invalid-expiry", Expires: time.Date(1600, 1, 1, 1, 1, 1, 1, time.UTC)},
+ "cookie-11=invalid-expiry",
+ },
// The "special" cookies have values containing commas or spaces which
// are disallowed by RFC 6265 but are common in the wild.
{
@@ -426,3 +435,92 @@ func TestCookieSanitizePath(t *testing.T) {
t.Errorf("Expected substring %q in log output. Got:\n%s", sub, got)
}
}
+
+func BenchmarkCookieString(b *testing.B) {
+ const wantCookieString = `cookie-9=i3e01nf61b6t23bvfmplnanol3; Path=/restricted/; Domain=example.com; Expires=Tue, 10 Nov 2009 23:00:00 GMT; Max-Age=3600`
+ c := &Cookie{
+ Name: "cookie-9",
+ Value: "i3e01nf61b6t23bvfmplnanol3",
+ Expires: time.Unix(1257894000, 0),
+ Path: "/restricted/",
+ Domain: ".example.com",
+ MaxAge: 3600,
+ }
+ var benchmarkCookieString string
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ benchmarkCookieString = c.String()
+ }
+ if have, want := benchmarkCookieString, wantCookieString; have != want {
+ b.Fatalf("Have: %v Want: %v", have, want)
+ }
+}
+
+func BenchmarkReadSetCookies(b *testing.B) {
+ header := Header{
+ "Set-Cookie": {
+ "NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
+ ".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly",
+ },
+ }
+ wantCookies := []*Cookie{
+ {
+ Name: "NID",
+ Value: "99=YsDT5i3E-CXax-",
+ Path: "/",
+ Domain: ".google.ch",
+ HttpOnly: true,
+ Expires: time.Date(2011, 11, 23, 1, 5, 3, 0, time.UTC),
+ RawExpires: "Wed, 23-Nov-2011 01:05:03 GMT",
+ Raw: "NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
+ },
+ {
+ Name: ".ASPXAUTH",
+ Value: "7E3AA",
+ Path: "/",
+ Expires: time.Date(2012, 3, 7, 14, 25, 6, 0, time.UTC),
+ RawExpires: "Wed, 07-Mar-2012 14:25:06 GMT",
+ HttpOnly: true,
+ Raw: ".ASPXAUTH=7E3AA; expires=Wed, 07-Mar-2012 14:25:06 GMT; path=/; HttpOnly",
+ },
+ }
+ var c []*Cookie
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ c = readSetCookies(header)
+ }
+ if !reflect.DeepEqual(c, wantCookies) {
+ b.Fatalf("readSetCookies:\nhave: %s\nwant: %s\n", toJSON(c), toJSON(wantCookies))
+ }
+}
+
+func BenchmarkReadCookies(b *testing.B) {
+ header := Header{
+ "Cookie": {
+ `de=; client_region=0; rpld1=0:hispeed.ch|20:che|21:zh|22:zurich|23:47.36|24:8.53|; rpld0=1:08|; backplane-channel=newspaper.com:1471; devicetype=0; osfam=0; rplmct=2; s_pers=%20s_vmonthnum%3D1472680800496%2526vn%253D1%7C1472680800496%3B%20s_nr%3D1471686767664-New%7C1474278767664%3B%20s_lv%3D1471686767669%7C1566294767669%3B%20s_lv_s%3DFirst%2520Visit%7C1471688567669%3B%20s_monthinvisit%3Dtrue%7C1471688567677%3B%20gvp_p5%3Dsports%253Ablog%253Aearly-lead%2520-%2520184693%2520-%252020160820%2520-%2520u-s%7C1471688567681%3B%20gvp_p51%3Dwp%2520-%2520sports%7C1471688567684%3B; s_sess=%20s_wp_ep%3Dhomepage%3B%20s._ref%3Dhttps%253A%252F%252Fwww.google.ch%252F%3B%20s_cc%3Dtrue%3B%20s_ppvl%3Dsports%25253Ablog%25253Aearly-lead%252520-%252520184693%252520-%25252020160820%252520-%252520u-lawyer%252C12%252C12%252C502%252C1231%252C502%252C1680%252C1050%252C2%252CP%3B%20s_ppv%3Dsports%25253Ablog%25253Aearly-lead%252520-%252520184693%252520-%25252020160820%252520-%252520u-s-lawyer%252C12%252C12%252C502%252C1231%252C502%252C1680%252C1050%252C2%252CP%3B%20s_dslv%3DFirst%2520Visit%3B%20s_sq%3Dwpninewspapercom%253D%252526pid%25253Dsports%2525253Ablog%2525253Aearly-lead%25252520-%25252520184693%25252520-%2525252020160820%25252520-%25252520u-s%252526pidt%25253D1%252526oid%25253Dhttps%2525253A%2525252F%2525252Fwww.newspaper.com%2525252F%2525253Fnid%2525253Dmenu_nav_homepage%252526ot%25253DA%3B`,
+ },
+ }
+ wantCookies := []*Cookie{
+ {Name: "de", Value: ""},
+ {Name: "client_region", Value: "0"},
+ {Name: "rpld1", Value: "0:hispeed.ch|20:che|21:zh|22:zurich|23:47.36|24:8.53|"},
+ {Name: "rpld0", Value: "1:08|"},
+ {Name: "backplane-channel", Value: "newspaper.com:1471"},
+ {Name: "devicetype", Value: "0"},
+ {Name: "osfam", Value: "0"},
+ {Name: "rplmct", Value: "2"},
+ {Name: "s_pers", Value: "%20s_vmonthnum%3D1472680800496%2526vn%253D1%7C1472680800496%3B%20s_nr%3D1471686767664-New%7C1474278767664%3B%20s_lv%3D1471686767669%7C1566294767669%3B%20s_lv_s%3DFirst%2520Visit%7C1471688567669%3B%20s_monthinvisit%3Dtrue%7C1471688567677%3B%20gvp_p5%3Dsports%253Ablog%253Aearly-lead%2520-%2520184693%2520-%252020160820%2520-%2520u-s%7C1471688567681%3B%20gvp_p51%3Dwp%2520-%2520sports%7C1471688567684%3B"},
+ {Name: "s_sess", Value: "%20s_wp_ep%3Dhomepage%3B%20s._ref%3Dhttps%253A%252F%252Fwww.google.ch%252F%3B%20s_cc%3Dtrue%3B%20s_ppvl%3Dsports%25253Ablog%25253Aearly-lead%252520-%252520184693%252520-%25252020160820%252520-%252520u-lawyer%252C12%252C12%252C502%252C1231%252C502%252C1680%252C1050%252C2%252CP%3B%20s_ppv%3Dsports%25253Ablog%25253Aearly-lead%252520-%252520184693%252520-%25252020160820%252520-%252520u-s-lawyer%252C12%252C12%252C502%252C1231%252C502%252C1680%252C1050%252C2%252CP%3B%20s_dslv%3DFirst%2520Visit%3B%20s_sq%3Dwpninewspapercom%253D%252526pid%25253Dsports%2525253Ablog%2525253Aearly-lead%25252520-%25252520184693%25252520-%2525252020160820%25252520-%25252520u-s%252526pidt%25253D1%252526oid%25253Dhttps%2525253A%2525252F%2525252Fwww.newspaper.com%2525252F%2525253Fnid%2525253Dmenu_nav_homepage%252526ot%25253DA%3B"},
+ }
+ var c []*Cookie
+ b.ReportAllocs()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ c = readCookies(header, "")
+ }
+ if !reflect.DeepEqual(c, wantCookies) {
+ b.Fatalf("readCookies:\nhave: %s\nwant: %s\n", toJSON(c), toJSON(wantCookies))
+ }
+}
diff --git a/libgo/go/net/http/cookiejar/dummy_publicsuffix_test.go b/libgo/go/net/http/cookiejar/dummy_publicsuffix_test.go
new file mode 100644
index 00000000000..748ec5cc431
--- /dev/null
+++ b/libgo/go/net/http/cookiejar/dummy_publicsuffix_test.go
@@ -0,0 +1,23 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package cookiejar_test
+
+import "net/http/cookiejar"
+
+type dummypsl struct {
+ List cookiejar.PublicSuffixList
+}
+
+func (dummypsl) PublicSuffix(domain string) string {
+ return domain
+}
+
+func (dummypsl) String() string {
+ return "dummy"
+}
+
+var publicsuffix = dummypsl{}
diff --git a/libgo/go/net/http/cookiejar/example_test.go b/libgo/go/net/http/cookiejar/example_test.go
new file mode 100644
index 00000000000..19a57465ff6
--- /dev/null
+++ b/libgo/go/net/http/cookiejar/example_test.go
@@ -0,0 +1,67 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package cookiejar_test
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+ "net/http/cookiejar"
+ "net/http/httptest"
+ "net/url"
+)
+
+func ExampleNew() {
+ // Start a server to give us cookies.
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if cookie, err := r.Cookie("Flavor"); err != nil {
+ http.SetCookie(w, &http.Cookie{Name: "Flavor", Value: "Chocolate Chip"})
+ } else {
+ cookie.Value = "Oatmeal Raisin"
+ http.SetCookie(w, cookie)
+ }
+ }))
+ defer ts.Close()
+
+ u, err := url.Parse(ts.URL)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // All users of cookiejar should import "golang.org/x/net/publicsuffix"
+ jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ client := &http.Client{
+ Jar: jar,
+ }
+
+ if _, err = client.Get(u.String()); err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println("After 1st request:")
+ for _, cookie := range jar.Cookies(u) {
+ fmt.Printf(" %s: %s\n", cookie.Name, cookie.Value)
+ }
+
+ if _, err = client.Get(u.String()); err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println("After 2nd request:")
+ for _, cookie := range jar.Cookies(u) {
+ fmt.Printf(" %s: %s\n", cookie.Name, cookie.Value)
+ }
+ // Output:
+ // After 1st request:
+ // Flavor: Chocolate Chip
+ // After 2nd request:
+ // Flavor: Oatmeal Raisin
+}
diff --git a/libgo/go/net/http/cookiejar/jar.go b/libgo/go/net/http/cookiejar/jar.go
index 0e0fac9286e..f89abbcd186 100644
--- a/libgo/go/net/http/cookiejar/jar.go
+++ b/libgo/go/net/http/cookiejar/jar.go
@@ -107,7 +107,7 @@ type entry struct {
seqNum uint64
}
-// Id returns the domain;path;name triple of e as an id.
+// id returns the domain;path;name triple of e as an id.
func (e *entry) id() string {
return fmt.Sprintf("%s;%s;%s", e.Domain, e.Path, e.Name)
}
@@ -147,24 +147,6 @@ func hasDotSuffix(s, suffix string) bool {
return len(s) > len(suffix) && s[len(s)-len(suffix)-1] == '.' && s[len(s)-len(suffix):] == suffix
}
-// byPathLength is a []entry sort.Interface that sorts according to RFC 6265
-// section 5.4 point 2: by longest path and then by earliest creation time.
-type byPathLength []entry
-
-func (s byPathLength) Len() int { return len(s) }
-
-func (s byPathLength) Less(i, j int) bool {
- if len(s[i].Path) != len(s[j].Path) {
- return len(s[i].Path) > len(s[j].Path)
- }
- if !s[i].Creation.Equal(s[j].Creation) {
- return s[i].Creation.Before(s[j].Creation)
- }
- return s[i].seqNum < s[j].seqNum
-}
-
-func (s byPathLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-
// Cookies implements the Cookies method of the http.CookieJar interface.
//
// It returns an empty slice if the URL's scheme is not HTTP or HTTPS.
@@ -221,7 +203,18 @@ func (j *Jar) cookies(u *url.URL, now time.Time) (cookies []*http.Cookie) {
}
}
- sort.Sort(byPathLength(selected))
+ // sort according to RFC 6265 section 5.4 point 2: by longest
+ // path and then by earliest creation time.
+ sort.Slice(selected, func(i, j int) bool {
+ s := selected
+ if len(s[i].Path) != len(s[j].Path) {
+ return len(s[i].Path) > len(s[j].Path)
+ }
+ if !s[i].Creation.Equal(s[j].Creation) {
+ return s[i].Creation.Before(s[j].Creation)
+ }
+ return s[i].seqNum < s[j].seqNum
+ })
for _, e := range selected {
cookies = append(cookies, &http.Cookie{Name: e.Name, Value: e.Value})
}
diff --git a/libgo/go/net/http/doc.go b/libgo/go/net/http/doc.go
index 4ec8272f628..7855feaaa99 100644
--- a/libgo/go/net/http/doc.go
+++ b/libgo/go/net/http/doc.go
@@ -44,7 +44,8 @@ For control over proxies, TLS configuration, keep-alives,
compression, and other settings, create a Transport:
tr := &http.Transport{
- TLSClientConfig: &tls.Config{RootCAs: pool},
+ MaxIdleConns: 10,
+ IdleConnTimeout: 30 * time.Second,
DisableCompression: true,
}
client := &http.Client{Transport: tr}
@@ -77,19 +78,30 @@ custom Server:
}
log.Fatal(s.ListenAndServe())
-The http package has transparent support for the HTTP/2 protocol when
-using HTTPS. Programs that must disable HTTP/2 can do so by setting
-Transport.TLSNextProto (for clients) or Server.TLSNextProto (for
-servers) to a non-nil, empty map. Alternatively, the following GODEBUG
-environment variables are currently supported:
+Starting with Go 1.6, the http package has transparent support for the
+HTTP/2 protocol when using HTTPS. Programs that must disable HTTP/2
+can do so by setting Transport.TLSNextProto (for clients) or
+Server.TLSNextProto (for servers) to a non-nil, empty
+map. Alternatively, the following GODEBUG environment variables are
+currently supported:
GODEBUG=http2client=0 # disable HTTP/2 client support
GODEBUG=http2server=0 # disable HTTP/2 server support
GODEBUG=http2debug=1 # enable verbose HTTP/2 debug logs
GODEBUG=http2debug=2 # ... even more verbose, with frame dumps
-The GODEBUG variables are not covered by Go's API compatibility promise.
-HTTP/2 support was added in Go 1.6. Please report any issues instead of
-disabling HTTP/2 support: https://golang.org/s/http2bug
+The GODEBUG variables are not covered by Go's API compatibility
+promise. Please report any issues before disabling HTTP/2
+support: https://golang.org/s/http2bug
+
+The http package's Transport and Server both automatically enable
+HTTP/2 support for simple configurations. To enable HTTP/2 for more
+complex configurations, to use lower-level HTTP/2 features, or to use
+a newer version of Go's http2 package, import "golang.org/x/net/http2"
+directly and use its ConfigureTransport and/or ConfigureServer
+functions. Manually configuring HTTP/2 via the golang.org/x/net/http2
+package takes precedence over the net/http package's built-in HTTP/2
+support.
+
*/
package http
diff --git a/libgo/go/net/http/export_test.go b/libgo/go/net/http/export_test.go
index 9c5ba0809ad..b61f58b2db4 100644
--- a/libgo/go/net/http/export_test.go
+++ b/libgo/go/net/http/export_test.go
@@ -24,6 +24,7 @@ var (
ExportErrRequestCanceled = errRequestCanceled
ExportErrRequestCanceledConn = errRequestCanceledConn
ExportServeFile = serveFile
+ ExportScanETag = scanETag
ExportHttp2ConfigureServer = http2ConfigureServer
)
@@ -87,6 +88,12 @@ func (t *Transport) IdleConnKeysForTesting() (keys []string) {
return
}
+func (t *Transport) IdleConnKeyCountForTesting() int {
+ t.idleMu.Lock()
+ defer t.idleMu.Unlock()
+ return len(t.idleConn)
+}
+
func (t *Transport) IdleConnStrsForTesting() []string {
var ret []string
t.idleMu.Lock()
@@ -100,6 +107,24 @@ func (t *Transport) IdleConnStrsForTesting() []string {
return ret
}
+func (t *Transport) IdleConnStrsForTesting_h2() []string {
+ var ret []string
+ noDialPool := t.h2transport.ConnPool.(http2noDialClientConnPool)
+ pool := noDialPool.http2clientConnPool
+
+ pool.mu.Lock()
+ defer pool.mu.Unlock()
+
+ for k, cc := range pool.conns {
+ for range cc {
+ ret = append(ret, k)
+ }
+ }
+
+ sort.Strings(ret)
+ return ret
+}
+
func (t *Transport) IdleConnCountForTesting(cacheKey string) int {
t.idleMu.Lock()
defer t.idleMu.Unlock()
@@ -160,3 +185,17 @@ func ExportHttp2ConfigureTransport(t *Transport) error {
t.h2transport = t2
return nil
}
+
+var Export_shouldCopyHeaderOnRedirect = shouldCopyHeaderOnRedirect
+
+func (s *Server) ExportAllConnsIdle() bool {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ for c := range s.activeConn {
+ st, ok := c.curState.Load().(ConnState)
+ if !ok || st != StateIdle {
+ return false
+ }
+ }
+ return true
+}
diff --git a/libgo/go/net/http/fcgi/fcgi.go b/libgo/go/net/http/fcgi/fcgi.go
index 337484139d3..5057d700981 100644
--- a/libgo/go/net/http/fcgi/fcgi.go
+++ b/libgo/go/net/http/fcgi/fcgi.go
@@ -3,8 +3,12 @@
// license that can be found in the LICENSE file.
// Package fcgi implements the FastCGI protocol.
+//
+// The protocol is not an official standard and the original
+// documentation is no longer online. See the Internet Archive's
+// mirror at: https://web.archive.org/web/20150420080736/http://www.fastcgi.com/drupal/node/6?q=node/22
+//
// Currently only the responder role is supported.
-// The protocol is defined at http://www.fastcgi.com/drupal/node/6?q=node/22
package fcgi
// This file defines the raw protocol and some utilities used by the child and
diff --git a/libgo/go/net/http/fs.go b/libgo/go/net/http/fs.go
index c7a58a61dff..bf63bb5441f 100644
--- a/libgo/go/net/http/fs.go
+++ b/libgo/go/net/http/fs.go
@@ -77,7 +77,7 @@ func dirList(w ResponseWriter, f File) {
Error(w, "Error reading directory", StatusInternalServerError)
return
}
- sort.Sort(byName(dirs))
+ sort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() })
w.Header().Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprintf(w, "<pre>\n")
@@ -98,7 +98,8 @@ func dirList(w ResponseWriter, f File) {
// ServeContent replies to the request using the content in the
// provided ReadSeeker. The main benefit of ServeContent over io.Copy
// is that it handles Range requests properly, sets the MIME type, and
-// handles If-Modified-Since requests.
+// handles If-Match, If-Unmodified-Since, If-None-Match, If-Modified-Since,
+// and If-Range requests.
//
// If the response's Content-Type header is not set, ServeContent
// first tries to deduce the type from name's file extension and,
@@ -115,8 +116,8 @@ func dirList(w ResponseWriter, f File) {
// The content's Seek method must work: ServeContent uses
// a seek to the end of the content to determine its size.
//
-// If the caller has set w's ETag header, ServeContent uses it to
-// handle requests using If-Range and If-None-Match.
+// If the caller has set w's ETag header formatted per RFC 7232, section 2.3,
+// ServeContent uses it to handle requests using If-Match, If-None-Match, or If-Range.
//
// Note that *os.File implements the io.ReadSeeker interface.
func ServeContent(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker) {
@@ -140,15 +141,17 @@ func ServeContent(w ResponseWriter, req *Request, name string, modtime time.Time
// users.
var errSeeker = errors.New("seeker can't seek")
+// errNoOverlap is returned by serveContent's parseRange if first-byte-pos of
+// all of the byte-range-spec values is greater than the content size.
+var errNoOverlap = errors.New("invalid range: failed to overlap")
+
// if name is empty, filename is unknown. (used for mime type, before sniffing)
// if modtime.IsZero(), modtime is unknown.
// content must be seeked to the beginning of the file.
// The sizeFunc is called at most once. Its error, if any, is sent in the HTTP response.
func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time, sizeFunc func() (int64, error), content io.ReadSeeker) {
- if checkLastModified(w, r, modtime) {
- return
- }
- rangeReq, done := checkETag(w, r, modtime)
+ setLastModified(w, modtime)
+ done, rangeReq := checkPreconditions(w, r, modtime)
if done {
return
}
@@ -189,6 +192,9 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
if size >= 0 {
ranges, err := parseRange(rangeReq, size)
if err != nil {
+ if err == errNoOverlap {
+ w.Header().Set("Content-Range", fmt.Sprintf("bytes */%d", size))
+ }
Error(w, err.Error(), StatusRequestedRangeNotSatisfiable)
return
}
@@ -263,90 +269,245 @@ func serveContent(w ResponseWriter, r *Request, name string, modtime time.Time,
}
}
-var unixEpochTime = time.Unix(0, 0)
-
-// modtime is the modification time of the resource to be served, or IsZero().
-// return value is whether this request is now complete.
-func checkLastModified(w ResponseWriter, r *Request, modtime time.Time) bool {
- if modtime.IsZero() || modtime.Equal(unixEpochTime) {
- // If the file doesn't have a modtime (IsZero), or the modtime
- // is obviously garbage (Unix time == 0), then ignore modtimes
- // and don't process the If-Modified-Since header.
- return false
+// scanETag determines if a syntactically valid ETag is present at s. If so,
+// the ETag and remaining text after consuming ETag is returned. Otherwise,
+// it returns "", "".
+func scanETag(s string) (etag string, remain string) {
+ s = textproto.TrimString(s)
+ start := 0
+ if strings.HasPrefix(s, "W/") {
+ start = 2
+ }
+ if len(s[start:]) < 2 || s[start] != '"' {
+ return "", ""
+ }
+ // ETag is either W/"text" or "text".
+ // See RFC 7232 2.3.
+ for i := start + 1; i < len(s); i++ {
+ c := s[i]
+ switch {
+ // Character values allowed in ETags.
+ case c == 0x21 || c >= 0x23 && c <= 0x7E || c >= 0x80:
+ case c == '"':
+ return string(s[:i+1]), s[i+1:]
+ default:
+ break
+ }
}
+ return "", ""
+}
- // The Date-Modified header truncates sub-second precision, so
- // use mtime < t+1s instead of mtime <= t to check for unmodified.
- if t, err := time.Parse(TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modtime.Before(t.Add(1*time.Second)) {
- h := w.Header()
- delete(h, "Content-Type")
- delete(h, "Content-Length")
- w.WriteHeader(StatusNotModified)
- return true
- }
- w.Header().Set("Last-Modified", modtime.UTC().Format(TimeFormat))
- return false
+// etagStrongMatch reports whether a and b match using strong ETag comparison.
+// Assumes a and b are valid ETags.
+func etagStrongMatch(a, b string) bool {
+ return a == b && a != "" && a[0] == '"'
}
-// checkETag implements If-None-Match and If-Range checks.
-//
-// The ETag or modtime must have been previously set in the
-// ResponseWriter's headers. The modtime is only compared at second
-// granularity and may be the zero value to mean unknown.
-//
-// The return value is the effective request "Range" header to use and
-// whether this request is now considered done.
-func checkETag(w ResponseWriter, r *Request, modtime time.Time) (rangeReq string, done bool) {
- etag := w.Header().get("Etag")
- rangeReq = r.Header.get("Range")
-
- // Invalidate the range request if the entity doesn't match the one
- // the client was expecting.
- // "If-Range: version" means "ignore the Range: header unless version matches the
- // current file."
- // We only support ETag versions.
- // The caller must have set the ETag on the response already.
- if ir := r.Header.get("If-Range"); ir != "" && ir != etag {
- // The If-Range value is typically the ETag value, but it may also be
- // the modtime date. See golang.org/issue/8367.
- timeMatches := false
- if !modtime.IsZero() {
- if t, err := ParseTime(ir); err == nil && t.Unix() == modtime.Unix() {
- timeMatches = true
- }
+// etagWeakMatch reports whether a and b match using weak ETag comparison.
+// Assumes a and b are valid ETags.
+func etagWeakMatch(a, b string) bool {
+ return strings.TrimPrefix(a, "W/") == strings.TrimPrefix(b, "W/")
+}
+
+// condResult is the result of an HTTP request precondition check.
+// See https://tools.ietf.org/html/rfc7232 section 3.
+type condResult int
+
+const (
+ condNone condResult = iota
+ condTrue
+ condFalse
+)
+
+func checkIfMatch(w ResponseWriter, r *Request) condResult {
+ im := r.Header.Get("If-Match")
+ if im == "" {
+ return condNone
+ }
+ for {
+ im = textproto.TrimString(im)
+ if len(im) == 0 {
+ break
+ }
+ if im[0] == ',' {
+ im = im[1:]
+ continue
+ }
+ if im[0] == '*' {
+ return condTrue
}
- if !timeMatches {
- rangeReq = ""
+ etag, remain := scanETag(im)
+ if etag == "" {
+ break
+ }
+ if etagStrongMatch(etag, w.Header().get("Etag")) {
+ return condTrue
}
+ im = remain
}
- if inm := r.Header.get("If-None-Match"); inm != "" {
- // Must know ETag.
+ return condFalse
+}
+
+func checkIfUnmodifiedSince(w ResponseWriter, r *Request, modtime time.Time) condResult {
+ ius := r.Header.Get("If-Unmodified-Since")
+ if ius == "" || isZeroTime(modtime) {
+ return condNone
+ }
+ if t, err := ParseTime(ius); err == nil {
+ // The Date-Modified header truncates sub-second precision, so
+ // use mtime < t+1s instead of mtime <= t to check for unmodified.
+ if modtime.Before(t.Add(1 * time.Second)) {
+ return condTrue
+ }
+ return condFalse
+ }
+ return condNone
+}
+
+func checkIfNoneMatch(w ResponseWriter, r *Request) condResult {
+ inm := r.Header.get("If-None-Match")
+ if inm == "" {
+ return condNone
+ }
+ buf := inm
+ for {
+ buf = textproto.TrimString(buf)
+ if len(buf) == 0 {
+ break
+ }
+ if buf[0] == ',' {
+ buf = buf[1:]
+ }
+ if buf[0] == '*' {
+ return condFalse
+ }
+ etag, remain := scanETag(buf)
if etag == "" {
- return rangeReq, false
+ break
+ }
+ if etagWeakMatch(etag, w.Header().get("Etag")) {
+ return condFalse
}
+ buf = remain
+ }
+ return condTrue
+}
+
+func checkIfModifiedSince(w ResponseWriter, r *Request, modtime time.Time) condResult {
+ if r.Method != "GET" && r.Method != "HEAD" {
+ return condNone
+ }
+ ims := r.Header.Get("If-Modified-Since")
+ if ims == "" || isZeroTime(modtime) {
+ return condNone
+ }
+ t, err := ParseTime(ims)
+ if err != nil {
+ return condNone
+ }
+ // The Date-Modified header truncates sub-second precision, so
+ // use mtime < t+1s instead of mtime <= t to check for unmodified.
+ if modtime.Before(t.Add(1 * time.Second)) {
+ return condFalse
+ }
+ return condTrue
+}
+
+func checkIfRange(w ResponseWriter, r *Request, modtime time.Time) condResult {
+ if r.Method != "GET" {
+ return condNone
+ }
+ ir := r.Header.get("If-Range")
+ if ir == "" {
+ return condNone
+ }
+ etag, _ := scanETag(ir)
+ if etag != "" {
+ if etagStrongMatch(etag, w.Header().Get("Etag")) {
+ return condTrue
+ } else {
+ return condFalse
+ }
+ }
+ // The If-Range value is typically the ETag value, but it may also be
+ // the modtime date. See golang.org/issue/8367.
+ if modtime.IsZero() {
+ return condFalse
+ }
+ t, err := ParseTime(ir)
+ if err != nil {
+ return condFalse
+ }
+ if t.Unix() == modtime.Unix() {
+ return condTrue
+ }
+ return condFalse
+}
+
+var unixEpochTime = time.Unix(0, 0)
+
+// isZeroTime reports whether t is obviously unspecified (either zero or Unix()=0).
+func isZeroTime(t time.Time) bool {
+ return t.IsZero() || t.Equal(unixEpochTime)
+}
+
+func setLastModified(w ResponseWriter, modtime time.Time) {
+ if !isZeroTime(modtime) {
+ w.Header().Set("Last-Modified", modtime.UTC().Format(TimeFormat))
+ }
+}
- // TODO(bradfitz): non-GET/HEAD requests require more work:
- // sending a different status code on matches, and
- // also can't use weak cache validators (those with a "W/
- // prefix). But most users of ServeContent will be using
- // it on GET or HEAD, so only support those for now.
- if r.Method != "GET" && r.Method != "HEAD" {
- return rangeReq, false
+func writeNotModified(w ResponseWriter) {
+ // RFC 7232 section 4.1:
+ // a sender SHOULD NOT generate representation metadata other than the
+ // above listed fields unless said metadata exists for the purpose of
+ // guiding cache updates (e.g., Last-Modified might be useful if the
+ // response does not have an ETag field).
+ h := w.Header()
+ delete(h, "Content-Type")
+ delete(h, "Content-Length")
+ if h.Get("Etag") != "" {
+ delete(h, "Last-Modified")
+ }
+ w.WriteHeader(StatusNotModified)
+}
+
+// checkPreconditions evaluates request preconditions and reports whether a precondition
+// resulted in sending StatusNotModified or StatusPreconditionFailed.
+func checkPreconditions(w ResponseWriter, r *Request, modtime time.Time) (done bool, rangeHeader string) {
+ // This function carefully follows RFC 7232 section 6.
+ ch := checkIfMatch(w, r)
+ if ch == condNone {
+ ch = checkIfUnmodifiedSince(w, r, modtime)
+ }
+ if ch == condFalse {
+ w.WriteHeader(StatusPreconditionFailed)
+ return true, ""
+ }
+ switch checkIfNoneMatch(w, r) {
+ case condFalse:
+ if r.Method == "GET" || r.Method == "HEAD" {
+ writeNotModified(w)
+ return true, ""
+ } else {
+ w.WriteHeader(StatusPreconditionFailed)
+ return true, ""
}
+ case condNone:
+ if checkIfModifiedSince(w, r, modtime) == condFalse {
+ writeNotModified(w)
+ return true, ""
+ }
+ }
- // TODO(bradfitz): deal with comma-separated or multiple-valued
- // list of If-None-match values. For now just handle the common
- // case of a single item.
- if inm == etag || inm == "*" {
- h := w.Header()
- delete(h, "Content-Type")
- delete(h, "Content-Length")
- w.WriteHeader(StatusNotModified)
- return "", true
+ rangeHeader = r.Header.get("Range")
+ if rangeHeader != "" {
+ if checkIfRange(w, r, modtime) == condFalse {
+ rangeHeader = ""
}
}
- return rangeReq, false
+ return false, rangeHeader
}
// name is '/'-separated, not filepath.Separator.
@@ -419,9 +580,11 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
// Still a directory? (we didn't find an index.html file)
if d.IsDir() {
- if checkLastModified(w, r, d.ModTime()) {
+ if checkIfModifiedSince(w, r, d.ModTime()) == condFalse {
+ writeNotModified(w)
return
}
+ w.Header().Set("Last-Modified", d.ModTime().UTC().Format(TimeFormat))
dirList(w, f)
return
}
@@ -543,6 +706,7 @@ func (r httpRange) mimeHeader(contentType string, size int64) textproto.MIMEHead
}
// parseRange parses a Range header string as per RFC 2616.
+// errNoOverlap is returned if none of the ranges overlap.
func parseRange(s string, size int64) ([]httpRange, error) {
if s == "" {
return nil, nil // header not present
@@ -552,6 +716,7 @@ func parseRange(s string, size int64) ([]httpRange, error) {
return nil, errors.New("invalid range")
}
var ranges []httpRange
+ noOverlap := false
for _, ra := range strings.Split(s[len(b):], ",") {
ra = strings.TrimSpace(ra)
if ra == "" {
@@ -577,9 +742,15 @@ func parseRange(s string, size int64) ([]httpRange, error) {
r.length = size - r.start
} else {
i, err := strconv.ParseInt(start, 10, 64)
- if err != nil || i >= size || i < 0 {
+ if err != nil || i < 0 {
return nil, errors.New("invalid range")
}
+ if i >= size {
+ // If the range begins after the size of the content,
+ // then it does not overlap.
+ noOverlap = true
+ continue
+ }
r.start = i
if end == "" {
// If no end is specified, range extends to end of the file.
@@ -597,6 +768,10 @@ func parseRange(s string, size int64) ([]httpRange, error) {
}
ranges = append(ranges, r)
}
+ if noOverlap && len(ranges) == 0 {
+ // The specified ranges did not overlap with the content.
+ return nil, errNoOverlap
+ }
return ranges, nil
}
@@ -628,9 +803,3 @@ func sumRangesSize(ranges []httpRange) (size int64) {
}
return
}
-
-type byName []os.FileInfo
-
-func (s byName) Len() int { return len(s) }
-func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }
-func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
diff --git a/libgo/go/net/http/fs_test.go b/libgo/go/net/http/fs_test.go
index 22be3899223..bba56821156 100644
--- a/libgo/go/net/http/fs_test.go
+++ b/libgo/go/net/http/fs_test.go
@@ -68,6 +68,7 @@ var ServeFileRangeTests = []struct {
}
func TestServeFile(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
ServeFile(w, r, "testdata/file")
@@ -274,6 +275,7 @@ func TestFileServerEscapesNames(t *testing.T) {
{`"'<>&`, `<a href="%22%27%3C%3E&">&#34;&#39;&lt;&gt;&amp;</a>`},
{`?foo=bar#baz`, `<a href="%3Ffoo=bar%23baz">?foo=bar#baz</a>`},
{`<combo>?foo`, `<a href="%3Ccombo%3E%3Ffoo">&lt;combo&gt;?foo</a>`},
+ {`foo:bar`, `<a href="./foo:bar">foo:bar</a>`},
}
// We put each test file in its own directory in the fakeFS so we can look at it in isolation.
@@ -765,6 +767,7 @@ func TestServeContent(t *testing.T) {
reqHeader map[string]string
wantLastMod string
wantContentType string
+ wantContentRange string
wantStatus int
}
htmlModTime := mustStat(t, "testdata/index.html").ModTime()
@@ -782,8 +785,9 @@ func TestServeContent(t *testing.T) {
wantStatus: 200,
},
"not_modified_modtime": {
- file: "testdata/style.css",
- modtime: htmlModTime,
+ file: "testdata/style.css",
+ serveETag: `"foo"`, // Last-Modified sent only when no ETag
+ modtime: htmlModTime,
reqHeader: map[string]string{
"If-Modified-Since": htmlModTime.UTC().Format(TimeFormat),
},
@@ -792,6 +796,7 @@ func TestServeContent(t *testing.T) {
"not_modified_modtime_with_contenttype": {
file: "testdata/style.css",
serveContentType: "text/css", // explicit content type
+ serveETag: `"foo"`, // Last-Modified sent only when no ETag
modtime: htmlModTime,
reqHeader: map[string]string{
"If-Modified-Since": htmlModTime.UTC().Format(TimeFormat),
@@ -808,21 +813,62 @@ func TestServeContent(t *testing.T) {
},
"not_modified_etag_no_seek": {
content: panicOnSeek{nil}, // should never be called
- serveETag: `"foo"`,
+ serveETag: `W/"foo"`, // If-None-Match uses weak ETag comparison
reqHeader: map[string]string{
- "If-None-Match": `"foo"`,
+ "If-None-Match": `"baz", W/"foo"`,
},
wantStatus: 304,
},
+ "if_none_match_mismatch": {
+ file: "testdata/style.css",
+ serveETag: `"foo"`,
+ reqHeader: map[string]string{
+ "If-None-Match": `"Foo"`,
+ },
+ wantStatus: 200,
+ wantContentType: "text/css; charset=utf-8",
+ },
"range_good": {
file: "testdata/style.css",
serveETag: `"A"`,
reqHeader: map[string]string{
"Range": "bytes=0-4",
},
- wantStatus: StatusPartialContent,
+ wantStatus: StatusPartialContent,
+ wantContentType: "text/css; charset=utf-8",
+ wantContentRange: "bytes 0-4/8",
+ },
+ "range_match": {
+ file: "testdata/style.css",
+ serveETag: `"A"`,
+ reqHeader: map[string]string{
+ "Range": "bytes=0-4",
+ "If-Range": `"A"`,
+ },
+ wantStatus: StatusPartialContent,
+ wantContentType: "text/css; charset=utf-8",
+ wantContentRange: "bytes 0-4/8",
+ },
+ "range_match_weak_etag": {
+ file: "testdata/style.css",
+ serveETag: `W/"A"`,
+ reqHeader: map[string]string{
+ "Range": "bytes=0-4",
+ "If-Range": `W/"A"`,
+ },
+ wantStatus: 200,
wantContentType: "text/css; charset=utf-8",
},
+ "range_no_overlap": {
+ file: "testdata/style.css",
+ serveETag: `"A"`,
+ reqHeader: map[string]string{
+ "Range": "bytes=10-20",
+ },
+ wantStatus: StatusRequestedRangeNotSatisfiable,
+ wantContentType: "text/plain; charset=utf-8",
+ wantContentRange: "bytes */8",
+ },
// An If-Range resource for entity "A", but entity "B" is now current.
// The Range request should be ignored.
"range_no_match": {
@@ -842,9 +888,10 @@ func TestServeContent(t *testing.T) {
"Range": "bytes=0-4",
"If-Range": "Wed, 25 Jun 2014 17:12:18 GMT",
},
- wantStatus: StatusPartialContent,
- wantContentType: "text/css; charset=utf-8",
- wantLastMod: "Wed, 25 Jun 2014 17:12:18 GMT",
+ wantStatus: StatusPartialContent,
+ wantContentType: "text/css; charset=utf-8",
+ wantContentRange: "bytes 0-4/8",
+ wantLastMod: "Wed, 25 Jun 2014 17:12:18 GMT",
},
"range_with_modtime_nanos": {
file: "testdata/style.css",
@@ -853,9 +900,10 @@ func TestServeContent(t *testing.T) {
"Range": "bytes=0-4",
"If-Range": "Wed, 25 Jun 2014 17:12:18 GMT",
},
- wantStatus: StatusPartialContent,
- wantContentType: "text/css; charset=utf-8",
- wantLastMod: "Wed, 25 Jun 2014 17:12:18 GMT",
+ wantStatus: StatusPartialContent,
+ wantContentType: "text/css; charset=utf-8",
+ wantContentRange: "bytes 0-4/8",
+ wantLastMod: "Wed, 25 Jun 2014 17:12:18 GMT",
},
"unix_zero_modtime": {
content: strings.NewReader("<html>foo"),
@@ -863,6 +911,62 @@ func TestServeContent(t *testing.T) {
wantStatus: StatusOK,
wantContentType: "text/html; charset=utf-8",
},
+ "ifmatch_matches": {
+ file: "testdata/style.css",
+ serveETag: `"A"`,
+ reqHeader: map[string]string{
+ "If-Match": `"Z", "A"`,
+ },
+ wantStatus: 200,
+ wantContentType: "text/css; charset=utf-8",
+ },
+ "ifmatch_star": {
+ file: "testdata/style.css",
+ serveETag: `"A"`,
+ reqHeader: map[string]string{
+ "If-Match": `*`,
+ },
+ wantStatus: 200,
+ wantContentType: "text/css; charset=utf-8",
+ },
+ "ifmatch_failed": {
+ file: "testdata/style.css",
+ serveETag: `"A"`,
+ reqHeader: map[string]string{
+ "If-Match": `"B"`,
+ },
+ wantStatus: 412,
+ wantContentType: "text/plain; charset=utf-8",
+ },
+ "ifmatch_fails_on_weak_etag": {
+ file: "testdata/style.css",
+ serveETag: `W/"A"`,
+ reqHeader: map[string]string{
+ "If-Match": `W/"A"`,
+ },
+ wantStatus: 412,
+ wantContentType: "text/plain; charset=utf-8",
+ },
+ "if_unmodified_since_true": {
+ file: "testdata/style.css",
+ modtime: htmlModTime,
+ reqHeader: map[string]string{
+ "If-Unmodified-Since": htmlModTime.UTC().Format(TimeFormat),
+ },
+ wantStatus: 200,
+ wantContentType: "text/css; charset=utf-8",
+ wantLastMod: htmlModTime.UTC().Format(TimeFormat),
+ },
+ "if_unmodified_since_false": {
+ file: "testdata/style.css",
+ modtime: htmlModTime,
+ reqHeader: map[string]string{
+ "If-Unmodified-Since": htmlModTime.Add(-2 * time.Second).UTC().Format(TimeFormat),
+ },
+ wantStatus: 412,
+ wantContentType: "text/plain; charset=utf-8",
+ wantLastMod: htmlModTime.UTC().Format(TimeFormat),
+ },
}
for testName, tt := range tests {
var content io.ReadSeeker
@@ -903,6 +1007,9 @@ func TestServeContent(t *testing.T) {
if g, e := res.Header.Get("Content-Type"), tt.wantContentType; g != e {
t.Errorf("test %q: content-type = %q, want %q", testName, g, e)
}
+ if g, e := res.Header.Get("Content-Range"), tt.wantContentRange; g != e {
+ t.Errorf("test %q: content-range = %q, want %q", testName, g, e)
+ }
if g, e := res.Header.Get("Last-Modified"), tt.wantLastMod; g != e {
t.Errorf("test %q: last-modified = %q, want %q", testName, g, e)
}
@@ -958,6 +1065,7 @@ func TestServeContentErrorMessages(t *testing.T) {
// verifies that sendfile is being used on Linux
func TestLinuxSendfile(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
if runtime.GOOS != "linux" {
t.Skip("skipping; linux-only test")
@@ -982,6 +1090,8 @@ func TestLinuxSendfile(t *testing.T) {
// strace on the above platforms doesn't support sendfile64
// and will error out if we specify that with `-e trace='.
syscalls = "sendfile"
+ case "mips64":
+ t.Skip("TODO: update this test to be robust against various versions of strace on mips64. See golang.org/issue/33430")
}
var buf bytes.Buffer
@@ -1008,10 +1118,9 @@ func TestLinuxSendfile(t *testing.T) {
Post(fmt.Sprintf("http://%s/quit", ln.Addr()), "", nil)
child.Wait()
- rx := regexp.MustCompile(`sendfile(64)?\(\d+,\s*\d+,\s*NULL,\s*\d+\)\s*=\s*\d+\s*\n`)
- rxResume := regexp.MustCompile(`<\.\.\. sendfile(64)? resumed> \)\s*=\s*\d+\s*\n`)
+ rx := regexp.MustCompile(`sendfile(64)?\(\d+,\s*\d+,\s*NULL,\s*\d+`)
out := buf.String()
- if !rx.MatchString(out) && !rxResume.MatchString(out) {
+ if !rx.MatchString(out) {
t.Errorf("no sendfile system call found in:\n%s", out)
}
}
@@ -1090,3 +1199,26 @@ func (d fileServerCleanPathDir) Open(path string) (File, error) {
}
type panicOnSeek struct{ io.ReadSeeker }
+
+func Test_scanETag(t *testing.T) {
+ tests := []struct {
+ in string
+ wantETag string
+ wantRemain string
+ }{
+ {`W/"etag-1"`, `W/"etag-1"`, ""},
+ {`"etag-2"`, `"etag-2"`, ""},
+ {`"etag-1", "etag-2"`, `"etag-1"`, `, "etag-2"`},
+ {"", "", ""},
+ {"", "", ""},
+ {"W/", "", ""},
+ {`W/"truc`, "", ""},
+ {`w/"case-sensitive"`, "", ""},
+ }
+ for _, test := range tests {
+ etag, remain := ExportScanETag(test.in)
+ if etag != test.wantETag || remain != test.wantRemain {
+ t.Errorf("scanETag(%q)=%q %q, want %q %q", test.in, etag, remain, test.wantETag, test.wantRemain)
+ }
+ }
+}
diff --git a/libgo/go/net/http/h2_bundle.go b/libgo/go/net/http/h2_bundle.go
index 5826bb7d858..25fdf09d92b 100644
--- a/libgo/go/net/http/h2_bundle.go
+++ b/libgo/go/net/http/h2_bundle.go
@@ -1,5 +1,5 @@
// Code generated by golang.org/x/tools/cmd/bundle.
-//go:generate bundle -o h2_bundle.go -prefix http2 golang.org/x/net/http2
+//go:generate bundle -o h2_bundle.go -prefix http2 -underscore golang.org/x/net/http2
// Package http2 implements the HTTP/2 protocol.
//
@@ -21,6 +21,7 @@ import (
"bytes"
"compress/gzip"
"context"
+ "crypto/rand"
"crypto/tls"
"encoding/binary"
"errors"
@@ -43,6 +44,7 @@ import (
"time"
"golang_org/x/net/http2/hpack"
+ "golang_org/x/net/idna"
"golang_org/x/net/lex/httplex"
)
@@ -853,10 +855,12 @@ type http2Framer struct {
// If the limit is hit, MetaHeadersFrame.Truncated is set true.
MaxHeaderListSize uint32
- logReads bool
+ logReads, logWrites bool
- debugFramer *http2Framer // only use for logging written writes
- debugFramerBuf *bytes.Buffer
+ debugFramer *http2Framer // only use for logging written writes
+ debugFramerBuf *bytes.Buffer
+ debugReadLoggerf func(string, ...interface{})
+ debugWriteLoggerf func(string, ...interface{})
}
func (fr *http2Framer) maxHeaderListSize() uint32 {
@@ -890,7 +894,7 @@ func (f *http2Framer) endWrite() error {
byte(length>>16),
byte(length>>8),
byte(length))
- if http2logFrameWrites {
+ if f.logWrites {
f.logWrite()
}
@@ -912,10 +916,10 @@ func (f *http2Framer) logWrite() {
f.debugFramerBuf.Write(f.wbuf)
fr, err := f.debugFramer.ReadFrame()
if err != nil {
- log.Printf("http2: Framer %p: failed to decode just-written frame", f)
+ f.debugWriteLoggerf("http2: Framer %p: failed to decode just-written frame", f)
return
}
- log.Printf("http2: Framer %p: wrote %v", f, http2summarizeFrame(fr))
+ f.debugWriteLoggerf("http2: Framer %p: wrote %v", f, http2summarizeFrame(fr))
}
func (f *http2Framer) writeByte(v byte) { f.wbuf = append(f.wbuf, v) }
@@ -936,9 +940,12 @@ const (
// NewFramer returns a Framer that writes frames to w and reads them from r.
func http2NewFramer(w io.Writer, r io.Reader) *http2Framer {
fr := &http2Framer{
- w: w,
- r: r,
- logReads: http2logFrameReads,
+ w: w,
+ r: r,
+ logReads: http2logFrameReads,
+ logWrites: http2logFrameWrites,
+ debugReadLoggerf: log.Printf,
+ debugWriteLoggerf: log.Printf,
}
fr.getReadBuf = func(size uint32) []byte {
if cap(fr.readBuf) >= int(size) {
@@ -1020,7 +1027,7 @@ func (fr *http2Framer) ReadFrame() (http2Frame, error) {
return nil, err
}
if fr.logReads {
- log.Printf("http2: Framer %p: read %v", fr, http2summarizeFrame(f))
+ fr.debugReadLoggerf("http2: Framer %p: read %v", fr, http2summarizeFrame(f))
}
if fh.Type == http2FrameHeaders && fr.ReadMetaHeaders != nil {
return fr.readMetaFrame(f.(*http2HeadersFrame))
@@ -1254,7 +1261,7 @@ func (f *http2Framer) WriteSettings(settings ...http2Setting) error {
return f.endWrite()
}
-// WriteSettings writes an empty SETTINGS frame with the ACK bit set.
+// WriteSettingsAck writes an empty SETTINGS frame with the ACK bit set.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
@@ -1920,8 +1927,8 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr
hdec.SetEmitEnabled(true)
hdec.SetMaxStringLength(fr.maxHeaderStringLen())
hdec.SetEmitFunc(func(hf hpack.HeaderField) {
- if http2VerboseLogs && http2logFrameReads {
- log.Printf("http2: decoded hpack field %+v", hf)
+ if http2VerboseLogs && fr.logReads {
+ fr.debugReadLoggerf("http2: decoded hpack field %+v", hf)
}
if !httplex.ValidHeaderFieldValue(hf.Value) {
invalid = http2headerFieldValueError(hf.Value)
@@ -2091,6 +2098,13 @@ type http2clientTrace httptrace.ClientTrace
func http2reqContext(r *Request) context.Context { return r.Context() }
+func (t *http2Transport) idleConnTimeout() time.Duration {
+ if t.t1 != nil {
+ return t.t1.IdleConnTimeout
+ }
+ return 0
+}
+
func http2setResponseUncompressed(res *Response) { res.Uncompressed = true }
func http2traceGotConn(req *Request, cc *http2ClientConn) {
@@ -2145,6 +2159,48 @@ func http2requestTrace(req *Request) *http2clientTrace {
return (*http2clientTrace)(trace)
}
+// Ping sends a PING frame to the server and waits for the ack.
+func (cc *http2ClientConn) Ping(ctx context.Context) error {
+ return cc.ping(ctx)
+}
+
+func http2cloneTLSConfig(c *tls.Config) *tls.Config { return c.Clone() }
+
+var _ Pusher = (*http2responseWriter)(nil)
+
+// Push implements http.Pusher.
+func (w *http2responseWriter) Push(target string, opts *PushOptions) error {
+ internalOpts := http2pushOptions{}
+ if opts != nil {
+ internalOpts.Method = opts.Method
+ internalOpts.Header = opts.Header
+ }
+ return w.push(target, internalOpts)
+}
+
+func http2configureServer18(h1 *Server, h2 *http2Server) error {
+ if h2.IdleTimeout == 0 {
+ if h1.IdleTimeout != 0 {
+ h2.IdleTimeout = h1.IdleTimeout
+ } else {
+ h2.IdleTimeout = h1.ReadTimeout
+ }
+ }
+ return nil
+}
+
+func http2shouldLogPanic(panicValue interface{}) bool {
+ return panicValue != nil && panicValue != ErrAbortHandler
+}
+
+func http2reqGetBody(req *Request) func() (io.ReadCloser, error) {
+ return req.GetBody
+}
+
+func http2reqBodyIsNoBody(body io.ReadCloser) bool {
+ return body == NoBody
+}
+
var http2DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
type http2goroutineLock uint64
@@ -2368,6 +2424,7 @@ var (
http2VerboseLogs bool
http2logFrameWrites bool
http2logFrameReads bool
+ http2inTests bool
)
func init() {
@@ -2409,13 +2466,23 @@ var (
type http2streamState int
+// HTTP/2 stream states.
+//
+// See http://tools.ietf.org/html/rfc7540#section-5.1.
+//
+// For simplicity, the server code merges "reserved (local)" into
+// "half-closed (remote)". This is one less state transition to track.
+// The only downside is that we send PUSH_PROMISEs slightly less
+// liberally than allowable. More discussion here:
+// https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
+//
+// "reserved (remote)" is omitted since the client code does not
+// support server push.
const (
http2stateIdle http2streamState = iota
http2stateOpen
http2stateHalfClosedLocal
http2stateHalfClosedRemote
- http2stateResvLocal
- http2stateResvRemote
http2stateClosed
)
@@ -2424,8 +2491,6 @@ var http2stateName = [...]string{
http2stateOpen: "Open",
http2stateHalfClosedLocal: "HalfClosedLocal",
http2stateHalfClosedRemote: "HalfClosedRemote",
- http2stateResvLocal: "ResvLocal",
- http2stateResvRemote: "ResvRemote",
http2stateClosed: "Closed",
}
@@ -2586,13 +2651,27 @@ func http2newBufferedWriter(w io.Writer) *http2bufferedWriter {
return &http2bufferedWriter{w: w}
}
+// bufWriterPoolBufferSize is the size of bufio.Writer's
+// buffers created using bufWriterPool.
+//
+// TODO: pick a less arbitrary value? this is a bit under
+// (3 x typical 1500 byte MTU) at least. Other than that,
+// not much thought went into it.
+const http2bufWriterPoolBufferSize = 4 << 10
+
var http2bufWriterPool = sync.Pool{
New: func() interface{} {
-
- return bufio.NewWriterSize(nil, 4<<10)
+ return bufio.NewWriterSize(nil, http2bufWriterPoolBufferSize)
},
}
+func (w *http2bufferedWriter) Available() int {
+ if w.bw == nil {
+ return http2bufWriterPoolBufferSize
+ }
+ return w.bw.Available()
+}
+
func (w *http2bufferedWriter) Write(p []byte) (n int, err error) {
if w.bw == nil {
bw := http2bufWriterPool.Get().(*bufio.Writer)
@@ -2686,6 +2765,19 @@ func (s *http2sorter) SortStrings(ss []string) {
s.v = save
}
+// validPseudoPath reports whether v is a valid :path pseudo-header
+// value. It must be either:
+//
+// *) a non-empty string starting with '/', but not with with "//",
+// *) the string '*', for OPTIONS requests.
+//
+// For now this is only used a quick check for deciding when to clean
+// up Opaque URLs before sending requests from the Transport.
+// See golang.org/issue/16847
+func http2validPseudoPath(v string) bool {
+ return (len(v) > 0 && v[0] == '/' && (len(v) == 1 || v[1] != '/')) || v == "*"
+}
+
// pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
// io.Pipe except there are no PipeReader/PipeWriter halves, and the
// underlying buffer is an interface. (io.Pipe is always unbuffered)
@@ -2882,6 +2974,15 @@ type http2Server struct {
// PermitProhibitedCipherSuites, if true, permits the use of
// cipher suites prohibited by the HTTP/2 spec.
PermitProhibitedCipherSuites bool
+
+ // IdleTimeout specifies how long until idle clients should be
+ // closed with a GOAWAY frame. PING frames are not considered
+ // activity for the purposes of IdleTimeout.
+ IdleTimeout time.Duration
+
+ // NewWriteScheduler constructs a write scheduler for a connection.
+ // If nil, a default scheduler is chosen.
+ NewWriteScheduler func() http2WriteScheduler
}
func (s *http2Server) maxReadFrameSize() uint32 {
@@ -2904,9 +3005,15 @@ func (s *http2Server) maxConcurrentStreams() uint32 {
//
// ConfigureServer must be called before s begins serving.
func http2ConfigureServer(s *Server, conf *http2Server) error {
+ if s == nil {
+ panic("nil *http.Server")
+ }
if conf == nil {
conf = new(http2Server)
}
+ if err := http2configureServer18(s, conf); err != nil {
+ return err
+ }
if s.TLSConfig == nil {
s.TLSConfig = new(tls.Config)
@@ -2945,8 +3052,6 @@ func http2ConfigureServer(s *Server, conf *http2Server) error {
s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, http2NextProtoTLS)
}
- s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, "h2-14")
-
if s.TLSNextProto == nil {
s.TLSNextProto = map[string]func(*Server, *tls.Conn, Handler){}
}
@@ -2960,7 +3065,6 @@ func http2ConfigureServer(s *Server, conf *http2Server) error {
})
}
s.TLSNextProto[http2NextProtoTLS] = protoHandler
- s.TLSNextProto["h2-14"] = protoHandler
return nil
}
@@ -3014,29 +3118,39 @@ func (s *http2Server) ServeConn(c net.Conn, opts *http2ServeConnOpts) {
defer cancel()
sc := &http2serverConn{
- srv: s,
- hs: opts.baseConfig(),
- conn: c,
- baseCtx: baseCtx,
- remoteAddrStr: c.RemoteAddr().String(),
- bw: http2newBufferedWriter(c),
- handler: opts.handler(),
- streams: make(map[uint32]*http2stream),
- readFrameCh: make(chan http2readFrameResult),
- wantWriteFrameCh: make(chan http2frameWriteMsg, 8),
- wroteFrameCh: make(chan http2frameWriteResult, 1),
- bodyReadCh: make(chan http2bodyReadMsg),
- doneServing: make(chan struct{}),
- advMaxStreams: s.maxConcurrentStreams(),
- writeSched: http2writeScheduler{
- maxFrameSize: http2initialMaxFrameSize,
- },
+ srv: s,
+ hs: opts.baseConfig(),
+ conn: c,
+ baseCtx: baseCtx,
+ remoteAddrStr: c.RemoteAddr().String(),
+ bw: http2newBufferedWriter(c),
+ handler: opts.handler(),
+ streams: make(map[uint32]*http2stream),
+ readFrameCh: make(chan http2readFrameResult),
+ wantWriteFrameCh: make(chan http2FrameWriteRequest, 8),
+ wantStartPushCh: make(chan http2startPushRequest, 8),
+ wroteFrameCh: make(chan http2frameWriteResult, 1),
+ bodyReadCh: make(chan http2bodyReadMsg),
+ doneServing: make(chan struct{}),
+ clientMaxStreams: math.MaxUint32,
+ advMaxStreams: s.maxConcurrentStreams(),
initialWindowSize: http2initialWindowSize,
+ maxFrameSize: http2initialMaxFrameSize,
headerTableSize: http2initialHeaderTableSize,
serveG: http2newGoroutineLock(),
pushEnabled: true,
}
+ if sc.hs.WriteTimeout != 0 {
+ sc.conn.SetWriteDeadline(time.Time{})
+ }
+
+ if s.NewWriteScheduler != nil {
+ sc.writeSched = s.NewWriteScheduler()
+ } else {
+ sc.writeSched = http2NewRandomWriteScheduler()
+ }
+
sc.flow.add(http2initialWindowSize)
sc.inflow.add(http2initialWindowSize)
sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
@@ -3090,16 +3204,18 @@ type http2serverConn struct {
handler Handler
baseCtx http2contextContext
framer *http2Framer
- doneServing chan struct{} // closed when serverConn.serve ends
- readFrameCh chan http2readFrameResult // written by serverConn.readFrames
- wantWriteFrameCh chan http2frameWriteMsg // from handlers -> serve
- wroteFrameCh chan http2frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
- bodyReadCh chan http2bodyReadMsg // from handlers -> serve
- testHookCh chan func(int) // code to run on the serve loop
- flow http2flow // conn-wide (not stream-specific) outbound flow control
- inflow http2flow // conn-wide inbound flow control
- tlsState *tls.ConnectionState // shared by all handlers, like net/http
+ doneServing chan struct{} // closed when serverConn.serve ends
+ readFrameCh chan http2readFrameResult // written by serverConn.readFrames
+ wantWriteFrameCh chan http2FrameWriteRequest // from handlers -> serve
+ wantStartPushCh chan http2startPushRequest // from handlers -> serve
+ wroteFrameCh chan http2frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
+ bodyReadCh chan http2bodyReadMsg // from handlers -> serve
+ testHookCh chan func(int) // code to run on the serve loop
+ flow http2flow // conn-wide (not stream-specific) outbound flow control
+ inflow http2flow // conn-wide inbound flow control
+ tlsState *tls.ConnectionState // shared by all handlers, like net/http
remoteAddrStr string
+ writeSched http2WriteScheduler
// Everything following is owned by the serve loop; use serveG.check():
serveG http2goroutineLock // used to verify funcs are on serve()
@@ -3109,22 +3225,27 @@ type http2serverConn struct {
unackedSettings int // how many SETTINGS have we sent without ACKs?
clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
- curOpenStreams uint32 // client's number of open streams
- maxStreamID uint32 // max ever seen
+ curClientStreams uint32 // number of open streams initiated by the client
+ curPushedStreams uint32 // number of open streams initiated by server push
+ maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
+ maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
streams map[uint32]*http2stream
initialWindowSize int32
+ maxFrameSize int32
headerTableSize uint32
peerMaxHeaderListSize uint32 // zero means unknown (default)
canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
- writingFrame bool // started write goroutine but haven't heard back on wroteFrameCh
+ writingFrame bool // started writing a frame (on serve goroutine or separate)
+ writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
needsFrameFlush bool // last frame write wasn't a flush
- writeSched http2writeScheduler
- inGoAway bool // we've started to or sent GOAWAY
- needToSendGoAway bool // we need to schedule a GOAWAY frame write
+ inGoAway bool // we've started to or sent GOAWAY
+ inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
+ needToSendGoAway bool // we need to schedule a GOAWAY frame write
goAwayCode http2ErrCode
shutdownTimerCh <-chan time.Time // nil until used
shutdownTimer *time.Timer // nil until used
- freeRequestBodyBuf []byte // if non-nil, a free initialWindowSize buffer for getRequestBodyBuf
+ idleTimer *time.Timer // nil if unused
+ idleTimerCh <-chan time.Time // nil if unused
// Owned by the writeFrameAsync goroutine:
headerWriteBuf bytes.Buffer
@@ -3143,6 +3264,11 @@ func (sc *http2serverConn) maxHeaderListSize() uint32 {
return uint32(n + typicalHeaders*perFieldOverhead)
}
+func (sc *http2serverConn) curOpenStreams() uint32 {
+ sc.serveG.check()
+ return sc.curClientStreams + sc.curPushedStreams
+}
+
// stream represents a stream. This is the minimal metadata needed by
// the serve goroutine. Most of the actual stream state is owned by
// the http.Handler's goroutine in the responseWriter. Because the
@@ -3168,11 +3294,10 @@ type http2stream struct {
numTrailerValues int64
weight uint8
state http2streamState
- sentReset bool // only true once detached from streams map
- gotReset bool // only true once detacted from streams map
- gotTrailerHeader bool // HEADER frame for trailers was seen
- wroteHeaders bool // whether we wrote headers (not status 100)
- reqBuf []byte
+ resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
+ gotTrailerHeader bool // HEADER frame for trailers was seen
+ wroteHeaders bool // whether we wrote headers (not status 100)
+ reqBuf []byte // if non-nil, body pipe buffer to return later at EOF
trailer Header // accumulated trailers
reqTrailer Header // handler's Request.Trailer
@@ -3195,8 +3320,14 @@ func (sc *http2serverConn) state(streamID uint32) (http2streamState, *http2strea
return st.state, st
}
- if streamID <= sc.maxStreamID {
- return http2stateClosed, nil
+ if streamID%2 == 1 {
+ if streamID <= sc.maxClientStreamID {
+ return http2stateClosed, nil
+ }
+ } else {
+ if streamID <= sc.maxPushPromiseID {
+ return http2stateClosed, nil
+ }
}
return http2stateIdle, nil
}
@@ -3328,17 +3459,17 @@ func (sc *http2serverConn) readFrames() {
// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
type http2frameWriteResult struct {
- wm http2frameWriteMsg // what was written (or attempted)
- err error // result of the writeFrame call
+ wr http2FrameWriteRequest // what was written (or attempted)
+ err error // result of the writeFrame call
}
// writeFrameAsync runs in its own goroutine and writes a single frame
// and then reports when it's done.
// At most one goroutine can be running writeFrameAsync at a time per
// serverConn.
-func (sc *http2serverConn) writeFrameAsync(wm http2frameWriteMsg) {
- err := wm.write.writeFrame(sc)
- sc.wroteFrameCh <- http2frameWriteResult{wm, err}
+func (sc *http2serverConn) writeFrameAsync(wr http2FrameWriteRequest) {
+ err := wr.write.writeFrame(sc)
+ sc.wroteFrameCh <- http2frameWriteResult{wr, err}
}
func (sc *http2serverConn) closeAllStreamsOnConnClose() {
@@ -3382,7 +3513,7 @@ func (sc *http2serverConn) serve() {
sc.vlogf("http2: server connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
}
- sc.writeFrame(http2frameWriteMsg{
+ sc.writeFrame(http2FrameWriteRequest{
write: http2writeSettings{
{http2SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
{http2SettingMaxConcurrentStreams, sc.advMaxStreams},
@@ -3399,6 +3530,17 @@ func (sc *http2serverConn) serve() {
sc.setConnState(StateActive)
sc.setConnState(StateIdle)
+ if sc.srv.IdleTimeout != 0 {
+ sc.idleTimer = time.NewTimer(sc.srv.IdleTimeout)
+ defer sc.idleTimer.Stop()
+ sc.idleTimerCh = sc.idleTimer.C
+ }
+
+ var gracefulShutdownCh <-chan struct{}
+ if sc.hs != nil {
+ gracefulShutdownCh = http2h1ServerShutdownChan(sc.hs)
+ }
+
go sc.readFrames()
settingsTimer := time.NewTimer(http2firstSettingsTimeout)
@@ -3406,8 +3548,10 @@ func (sc *http2serverConn) serve() {
for {
loopNum++
select {
- case wm := <-sc.wantWriteFrameCh:
- sc.writeFrame(wm)
+ case wr := <-sc.wantWriteFrameCh:
+ sc.writeFrame(wr)
+ case spr := <-sc.wantStartPushCh:
+ sc.startPush(spr)
case res := <-sc.wroteFrameCh:
sc.wroteFrame(res)
case res := <-sc.readFrameCh:
@@ -3424,12 +3568,22 @@ func (sc *http2serverConn) serve() {
case <-settingsTimer.C:
sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
return
+ case <-gracefulShutdownCh:
+ gracefulShutdownCh = nil
+ sc.startGracefulShutdown()
case <-sc.shutdownTimerCh:
sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
return
+ case <-sc.idleTimerCh:
+ sc.vlogf("connection is idle")
+ sc.goAway(http2ErrCodeNo)
case fn := <-sc.testHookCh:
fn(loopNum)
}
+
+ if sc.inGoAway && sc.curOpenStreams() == 0 && !sc.needToSendGoAway && !sc.writingFrame {
+ return
+ }
}
}
@@ -3477,7 +3631,7 @@ func (sc *http2serverConn) writeDataFromHandler(stream *http2stream, data []byte
ch := http2errChanPool.Get().(chan error)
writeArg := http2writeDataPool.Get().(*http2writeData)
*writeArg = http2writeData{stream.id, data, endStream}
- err := sc.writeFrameFromHandler(http2frameWriteMsg{
+ err := sc.writeFrameFromHandler(http2FrameWriteRequest{
write: writeArg,
stream: stream,
done: ch,
@@ -3507,17 +3661,17 @@ func (sc *http2serverConn) writeDataFromHandler(stream *http2stream, data []byte
return err
}
-// writeFrameFromHandler sends wm to sc.wantWriteFrameCh, but aborts
+// writeFrameFromHandler sends wr to sc.wantWriteFrameCh, but aborts
// if the connection has gone away.
//
// This must not be run from the serve goroutine itself, else it might
// deadlock writing to sc.wantWriteFrameCh (which is only mildly
// buffered and is read by serve itself). If you're on the serve
// goroutine, call writeFrame instead.
-func (sc *http2serverConn) writeFrameFromHandler(wm http2frameWriteMsg) error {
+func (sc *http2serverConn) writeFrameFromHandler(wr http2FrameWriteRequest) error {
sc.serveG.checkNotOn()
select {
- case sc.wantWriteFrameCh <- wm:
+ case sc.wantWriteFrameCh <- wr:
return nil
case <-sc.doneServing:
@@ -3533,53 +3687,81 @@ func (sc *http2serverConn) writeFrameFromHandler(wm http2frameWriteMsg) error {
// make it onto the wire
//
// If you're not on the serve goroutine, use writeFrameFromHandler instead.
-func (sc *http2serverConn) writeFrame(wm http2frameWriteMsg) {
+func (sc *http2serverConn) writeFrame(wr http2FrameWriteRequest) {
sc.serveG.check()
+ // If true, wr will not be written and wr.done will not be signaled.
var ignoreWrite bool
- switch wm.write.(type) {
+ if wr.StreamID() != 0 {
+ _, isReset := wr.write.(http2StreamError)
+ if state, _ := sc.state(wr.StreamID()); state == http2stateClosed && !isReset {
+ ignoreWrite = true
+ }
+ }
+
+ switch wr.write.(type) {
case *http2writeResHeaders:
- wm.stream.wroteHeaders = true
+ wr.stream.wroteHeaders = true
case http2write100ContinueHeadersFrame:
- if wm.stream.wroteHeaders {
+ if wr.stream.wroteHeaders {
+
+ if wr.done != nil {
+ panic("wr.done != nil for write100ContinueHeadersFrame")
+ }
ignoreWrite = true
}
}
if !ignoreWrite {
- sc.writeSched.add(wm)
+ sc.writeSched.Push(wr)
}
sc.scheduleFrameWrite()
}
-// startFrameWrite starts a goroutine to write wm (in a separate
+// startFrameWrite starts a goroutine to write wr (in a separate
// goroutine since that might block on the network), and updates the
-// serve goroutine's state about the world, updated from info in wm.
-func (sc *http2serverConn) startFrameWrite(wm http2frameWriteMsg) {
+// serve goroutine's state about the world, updated from info in wr.
+func (sc *http2serverConn) startFrameWrite(wr http2FrameWriteRequest) {
sc.serveG.check()
if sc.writingFrame {
panic("internal error: can only be writing one frame at a time")
}
- st := wm.stream
+ st := wr.stream
if st != nil {
switch st.state {
case http2stateHalfClosedLocal:
- panic("internal error: attempt to send frame on half-closed-local stream")
- case http2stateClosed:
- if st.sentReset || st.gotReset {
+ switch wr.write.(type) {
+ case http2StreamError, http2handlerPanicRST, http2writeWindowUpdate:
- sc.scheduleFrameWrite()
- return
+ default:
+ panic(fmt.Sprintf("internal error: attempt to send frame on a half-closed-local stream: %v", wr))
}
- panic(fmt.Sprintf("internal error: attempt to send a write %v on a closed stream", wm))
+ case http2stateClosed:
+ panic(fmt.Sprintf("internal error: attempt to send frame on a closed stream: %v", wr))
+ }
+ }
+ if wpp, ok := wr.write.(*http2writePushPromise); ok {
+ var err error
+ wpp.promisedID, err = wpp.allocatePromisedID()
+ if err != nil {
+ sc.writingFrameAsync = false
+ wr.replyToWriter(err)
+ return
}
}
sc.writingFrame = true
sc.needsFrameFlush = true
- go sc.writeFrameAsync(wm)
+ if wr.write.staysWithinBuffer(sc.bw.Available()) {
+ sc.writingFrameAsync = false
+ err := wr.write.writeFrame(sc)
+ sc.wroteFrame(http2frameWriteResult{wr, err})
+ } else {
+ sc.writingFrameAsync = true
+ go sc.writeFrameAsync(wr)
+ }
}
// errHandlerPanicked is the error given to any callers blocked in a read from
@@ -3595,26 +3777,12 @@ func (sc *http2serverConn) wroteFrame(res http2frameWriteResult) {
panic("internal error: expected to be already writing a frame")
}
sc.writingFrame = false
+ sc.writingFrameAsync = false
- wm := res.wm
- st := wm.stream
-
- closeStream := http2endsStream(wm.write)
-
- if _, ok := wm.write.(http2handlerPanicRST); ok {
- sc.closeStream(st, http2errHandlerPanicked)
- }
+ wr := res.wr
- if ch := wm.done; ch != nil {
- select {
- case ch <- res.err:
- default:
- panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wm.write))
- }
- }
- wm.write = nil
-
- if closeStream {
+ if http2writeEndsStream(wr.write) {
+ st := wr.stream
if st == nil {
panic("internal error: expecting non-nil stream")
}
@@ -3622,13 +3790,24 @@ func (sc *http2serverConn) wroteFrame(res http2frameWriteResult) {
case http2stateOpen:
st.state = http2stateHalfClosedLocal
- errCancel := http2streamError(st.id, http2ErrCodeCancel)
- sc.resetStream(errCancel)
+ sc.resetStream(http2streamError(st.id, http2ErrCodeCancel))
case http2stateHalfClosedRemote:
sc.closeStream(st, http2errHandlerComplete)
}
+ } else {
+ switch v := wr.write.(type) {
+ case http2StreamError:
+
+ if st, ok := sc.streams[v.StreamID]; ok {
+ sc.closeStream(st, v)
+ }
+ case http2handlerPanicRST:
+ sc.closeStream(wr.stream, http2errHandlerPanicked)
+ }
}
+ wr.replyToWriter(res.err)
+
sc.scheduleFrameWrite()
}
@@ -3646,47 +3825,68 @@ func (sc *http2serverConn) wroteFrame(res http2frameWriteResult) {
// flush the write buffer.
func (sc *http2serverConn) scheduleFrameWrite() {
sc.serveG.check()
- if sc.writingFrame {
- return
- }
- if sc.needToSendGoAway {
- sc.needToSendGoAway = false
- sc.startFrameWrite(http2frameWriteMsg{
- write: &http2writeGoAway{
- maxStreamID: sc.maxStreamID,
- code: sc.goAwayCode,
- },
- })
- return
- }
- if sc.needToSendSettingsAck {
- sc.needToSendSettingsAck = false
- sc.startFrameWrite(http2frameWriteMsg{write: http2writeSettingsAck{}})
+ if sc.writingFrame || sc.inFrameScheduleLoop {
return
}
- if !sc.inGoAway {
- if wm, ok := sc.writeSched.take(); ok {
- sc.startFrameWrite(wm)
- return
+ sc.inFrameScheduleLoop = true
+ for !sc.writingFrameAsync {
+ if sc.needToSendGoAway {
+ sc.needToSendGoAway = false
+ sc.startFrameWrite(http2FrameWriteRequest{
+ write: &http2writeGoAway{
+ maxStreamID: sc.maxClientStreamID,
+ code: sc.goAwayCode,
+ },
+ })
+ continue
}
+ if sc.needToSendSettingsAck {
+ sc.needToSendSettingsAck = false
+ sc.startFrameWrite(http2FrameWriteRequest{write: http2writeSettingsAck{}})
+ continue
+ }
+ if !sc.inGoAway || sc.goAwayCode == http2ErrCodeNo {
+ if wr, ok := sc.writeSched.Pop(); ok {
+ sc.startFrameWrite(wr)
+ continue
+ }
+ }
+ if sc.needsFrameFlush {
+ sc.startFrameWrite(http2FrameWriteRequest{write: http2flushFrameWriter{}})
+ sc.needsFrameFlush = false
+ continue
+ }
+ break
}
- if sc.needsFrameFlush {
- sc.startFrameWrite(http2frameWriteMsg{write: http2flushFrameWriter{}})
- sc.needsFrameFlush = false
- return
- }
+ sc.inFrameScheduleLoop = false
+}
+
+// startGracefulShutdown sends a GOAWAY with ErrCodeNo to tell the
+// client we're gracefully shutting down. The connection isn't closed
+// until all current streams are done.
+func (sc *http2serverConn) startGracefulShutdown() {
+ sc.goAwayIn(http2ErrCodeNo, 0)
}
func (sc *http2serverConn) goAway(code http2ErrCode) {
sc.serveG.check()
- if sc.inGoAway {
- return
- }
+ var forceCloseIn time.Duration
if code != http2ErrCodeNo {
- sc.shutDownIn(250 * time.Millisecond)
+ forceCloseIn = 250 * time.Millisecond
} else {
- sc.shutDownIn(1 * time.Second)
+ forceCloseIn = 1 * time.Second
+ }
+ sc.goAwayIn(code, forceCloseIn)
+}
+
+func (sc *http2serverConn) goAwayIn(code http2ErrCode, forceCloseIn time.Duration) {
+ sc.serveG.check()
+ if sc.inGoAway {
+ return
+ }
+ if forceCloseIn != 0 {
+ sc.shutDownIn(forceCloseIn)
}
sc.inGoAway = true
sc.needToSendGoAway = true
@@ -3702,10 +3902,9 @@ func (sc *http2serverConn) shutDownIn(d time.Duration) {
func (sc *http2serverConn) resetStream(se http2StreamError) {
sc.serveG.check()
- sc.writeFrame(http2frameWriteMsg{write: se})
+ sc.writeFrame(http2FrameWriteRequest{write: se})
if st, ok := sc.streams[se.StreamID]; ok {
- st.sentReset = true
- sc.closeStream(st, se)
+ st.resetQueued = true
}
}
@@ -3782,6 +3981,8 @@ func (sc *http2serverConn) processFrame(f http2Frame) error {
return sc.processResetStream(f)
case *http2PriorityFrame:
return sc.processPriority(f)
+ case *http2GoAwayFrame:
+ return sc.processGoAway(f)
case *http2PushPromiseFrame:
return http2ConnectionError(http2ErrCodeProtocol)
@@ -3801,7 +4002,10 @@ func (sc *http2serverConn) processPing(f *http2PingFrame) error {
return http2ConnectionError(http2ErrCodeProtocol)
}
- sc.writeFrame(http2frameWriteMsg{write: http2writePingAck{f}})
+ if sc.inGoAway && sc.goAwayCode != http2ErrCodeNo {
+ return nil
+ }
+ sc.writeFrame(http2FrameWriteRequest{write: http2writePingAck{f}})
return nil
}
@@ -3809,7 +4013,11 @@ func (sc *http2serverConn) processWindowUpdate(f *http2WindowUpdateFrame) error
sc.serveG.check()
switch {
case f.StreamID != 0:
- st := sc.streams[f.StreamID]
+ state, st := sc.state(f.StreamID)
+ if state == http2stateIdle {
+
+ return http2ConnectionError(http2ErrCodeProtocol)
+ }
if st == nil {
return nil
@@ -3835,7 +4043,6 @@ func (sc *http2serverConn) processResetStream(f *http2RSTStreamFrame) error {
return http2ConnectionError(http2ErrCodeProtocol)
}
if st != nil {
- st.gotReset = true
st.cancelCtx()
sc.closeStream(st, http2streamError(f.StreamID, f.ErrCode))
}
@@ -3848,11 +4055,21 @@ func (sc *http2serverConn) closeStream(st *http2stream, err error) {
panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
}
st.state = http2stateClosed
- sc.curOpenStreams--
- if sc.curOpenStreams == 0 {
- sc.setConnState(StateIdle)
+ if st.isPushed() {
+ sc.curPushedStreams--
+ } else {
+ sc.curClientStreams--
}
delete(sc.streams, st.id)
+ if len(sc.streams) == 0 {
+ sc.setConnState(StateIdle)
+ if sc.srv.IdleTimeout != 0 {
+ sc.idleTimer.Reset(sc.srv.IdleTimeout)
+ }
+ if http2h1ServerKeepAlivesDisabled(sc.hs) {
+ sc.startGracefulShutdown()
+ }
+ }
if p := st.body; p != nil {
sc.sendWindowUpdate(nil, p.Len())
@@ -3860,11 +4077,7 @@ func (sc *http2serverConn) closeStream(st *http2stream, err error) {
p.CloseWithError(err)
}
st.cw.Close()
- sc.writeSched.forgetStream(st.id)
- if st.reqBuf != nil {
-
- sc.freeRequestBodyBuf = st.reqBuf
- }
+ sc.writeSched.CloseStream(st.id)
}
func (sc *http2serverConn) processSettings(f *http2SettingsFrame) error {
@@ -3904,7 +4117,7 @@ func (sc *http2serverConn) processSetting(s http2Setting) error {
case http2SettingInitialWindowSize:
return sc.processSettingInitialWindowSize(s.Val)
case http2SettingMaxFrameSize:
- sc.writeSched.maxFrameSize = s.Val
+ sc.maxFrameSize = int32(s.Val)
case http2SettingMaxHeaderListSize:
sc.peerMaxHeaderListSize = s.Val
default:
@@ -3933,11 +4146,18 @@ func (sc *http2serverConn) processSettingInitialWindowSize(val uint32) error {
func (sc *http2serverConn) processData(f *http2DataFrame) error {
sc.serveG.check()
+ if sc.inGoAway && sc.goAwayCode != http2ErrCodeNo {
+ return nil
+ }
data := f.Data()
id := f.Header().StreamID
- st, ok := sc.streams[id]
- if !ok || st.state != http2stateOpen || st.gotTrailerHeader {
+ state, st := sc.state(id)
+ if id == 0 || state == http2stateIdle {
+
+ return http2ConnectionError(http2ErrCodeProtocol)
+ }
+ if st == nil || state != http2stateOpen || st.gotTrailerHeader || st.resetQueued {
if sc.inflow.available() < int32(f.Length) {
return http2streamError(id, http2ErrCodeFlowControl)
@@ -3946,6 +4166,10 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error {
sc.inflow.take(int32(f.Length))
sc.sendWindowUpdate(nil, int(f.Length))
+ if st != nil && st.resetQueued {
+
+ return nil
+ }
return http2streamError(id, http2ErrCodeStreamClosed)
}
if st.body == nil {
@@ -3985,6 +4209,24 @@ func (sc *http2serverConn) processData(f *http2DataFrame) error {
return nil
}
+func (sc *http2serverConn) processGoAway(f *http2GoAwayFrame) error {
+ sc.serveG.check()
+ if f.ErrCode != http2ErrCodeNo {
+ sc.logf("http2: received GOAWAY %+v, starting graceful shutdown", f)
+ } else {
+ sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f)
+ }
+ sc.startGracefulShutdown()
+
+ sc.pushEnabled = false
+ return nil
+}
+
+// isPushed reports whether the stream is server-initiated.
+func (st *http2stream) isPushed() bool {
+ return st.id%2 == 0
+}
+
// endStream closes a Request.Body's pipe. It is called when a DATA
// frame says a request body is over (or after trailers).
func (st *http2stream) endStream() {
@@ -4014,7 +4256,7 @@ func (st *http2stream) copyTrailersToHandlerRequest() {
func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
sc.serveG.check()
- id := f.Header().StreamID
+ id := f.StreamID
if sc.inGoAway {
return nil
@@ -4024,50 +4266,43 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
return http2ConnectionError(http2ErrCodeProtocol)
}
- st := sc.streams[f.Header().StreamID]
- if st != nil {
+ if st := sc.streams[f.StreamID]; st != nil {
+ if st.resetQueued {
+
+ return nil
+ }
return st.processTrailerHeaders(f)
}
- if id <= sc.maxStreamID {
+ if id <= sc.maxClientStreamID {
return http2ConnectionError(http2ErrCodeProtocol)
}
- sc.maxStreamID = id
+ sc.maxClientStreamID = id
- ctx, cancelCtx := http2contextWithCancel(sc.baseCtx)
- st = &http2stream{
- sc: sc,
- id: id,
- state: http2stateOpen,
- ctx: ctx,
- cancelCtx: cancelCtx,
- }
- if f.StreamEnded() {
- st.state = http2stateHalfClosedRemote
+ if sc.idleTimer != nil {
+ sc.idleTimer.Stop()
}
- st.cw.Init()
- st.flow.conn = &sc.flow
- st.flow.add(sc.initialWindowSize)
- st.inflow.conn = &sc.inflow
- st.inflow.add(http2initialWindowSize)
+ if sc.curClientStreams+1 > sc.advMaxStreams {
+ if sc.unackedSettings == 0 {
- sc.streams[id] = st
- if f.HasPriority() {
- http2adjustStreamPriority(sc.streams, st.id, f.Priority)
- }
- sc.curOpenStreams++
- if sc.curOpenStreams == 1 {
- sc.setConnState(StateActive)
+ return http2streamError(id, http2ErrCodeProtocol)
+ }
+
+ return http2streamError(id, http2ErrCodeRefusedStream)
}
- if sc.curOpenStreams > sc.advMaxStreams {
- if sc.unackedSettings == 0 {
+ initialState := http2stateOpen
+ if f.StreamEnded() {
+ initialState = http2stateHalfClosedRemote
+ }
+ st := sc.newStream(id, 0, initialState)
- return http2streamError(st.id, http2ErrCodeProtocol)
+ if f.HasPriority() {
+ if err := http2checkPriority(f.StreamID, f.Priority); err != nil {
+ return err
}
-
- return http2streamError(st.id, http2ErrCodeRefusedStream)
+ sc.writeSched.AdjustStream(st.id, f.Priority)
}
rw, req, err := sc.newWriterAndRequest(st, f)
@@ -4085,10 +4320,14 @@ func (sc *http2serverConn) processHeaders(f *http2MetaHeadersFrame) error {
if f.Truncated {
handler = http2handleHeaderListTooLong
- } else if err := http2checkValidHTTP2Request(req); err != nil {
+ } else if err := http2checkValidHTTP2RequestHeaders(req.Header); err != nil {
handler = http2new400Handler(err)
}
+ if sc.hs.ReadTimeout != 0 {
+ sc.conn.SetReadDeadline(time.Time{})
+ }
+
go sc.runHandler(rw, req, handler)
return nil
}
@@ -4121,90 +4360,138 @@ func (st *http2stream) processTrailerHeaders(f *http2MetaHeadersFrame) error {
return nil
}
-func (sc *http2serverConn) processPriority(f *http2PriorityFrame) error {
- http2adjustStreamPriority(sc.streams, f.StreamID, f.http2PriorityParam)
+func http2checkPriority(streamID uint32, p http2PriorityParam) error {
+ if streamID == p.StreamDep {
+
+ return http2streamError(streamID, http2ErrCodeProtocol)
+ }
return nil
}
-func http2adjustStreamPriority(streams map[uint32]*http2stream, streamID uint32, priority http2PriorityParam) {
- st, ok := streams[streamID]
- if !ok {
+func (sc *http2serverConn) processPriority(f *http2PriorityFrame) error {
+ if sc.inGoAway {
+ return nil
+ }
+ if err := http2checkPriority(f.StreamID, f.http2PriorityParam); err != nil {
+ return err
+ }
+ sc.writeSched.AdjustStream(f.StreamID, f.http2PriorityParam)
+ return nil
+}
- return
+func (sc *http2serverConn) newStream(id, pusherID uint32, state http2streamState) *http2stream {
+ sc.serveG.check()
+ if id == 0 {
+ panic("internal error: cannot create stream with id 0")
}
- st.weight = priority.Weight
- parent := streams[priority.StreamDep]
- if parent == st {
- return
+ ctx, cancelCtx := http2contextWithCancel(sc.baseCtx)
+ st := &http2stream{
+ sc: sc,
+ id: id,
+ state: state,
+ ctx: ctx,
+ cancelCtx: cancelCtx,
}
+ st.cw.Init()
+ st.flow.conn = &sc.flow
+ st.flow.add(sc.initialWindowSize)
+ st.inflow.conn = &sc.inflow
+ st.inflow.add(http2initialWindowSize)
- for piter := parent; piter != nil; piter = piter.parent {
- if piter == st {
- parent.parent = st.parent
- break
- }
+ sc.streams[id] = st
+ sc.writeSched.OpenStream(st.id, http2OpenStreamOptions{PusherID: pusherID})
+ if st.isPushed() {
+ sc.curPushedStreams++
+ } else {
+ sc.curClientStreams++
}
- st.parent = parent
- if priority.Exclusive && (st.parent != nil || priority.StreamDep == 0) {
- for _, openStream := range streams {
- if openStream != st && openStream.parent == st.parent {
- openStream.parent = st
- }
- }
+ if sc.curOpenStreams() == 1 {
+ sc.setConnState(StateActive)
}
+
+ return st
}
func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHeadersFrame) (*http2responseWriter, *Request, error) {
sc.serveG.check()
- method := f.PseudoValue("method")
- path := f.PseudoValue("path")
- scheme := f.PseudoValue("scheme")
- authority := f.PseudoValue("authority")
+ rp := http2requestParam{
+ method: f.PseudoValue("method"),
+ scheme: f.PseudoValue("scheme"),
+ authority: f.PseudoValue("authority"),
+ path: f.PseudoValue("path"),
+ }
- isConnect := method == "CONNECT"
+ isConnect := rp.method == "CONNECT"
if isConnect {
- if path != "" || scheme != "" || authority == "" {
+ if rp.path != "" || rp.scheme != "" || rp.authority == "" {
return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol)
}
- } else if method == "" || path == "" ||
- (scheme != "https" && scheme != "http") {
+ } else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") {
return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol)
}
bodyOpen := !f.StreamEnded()
- if method == "HEAD" && bodyOpen {
+ if rp.method == "HEAD" && bodyOpen {
return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol)
}
- var tlsState *tls.ConnectionState // nil if not scheme https
- if scheme == "https" {
- tlsState = sc.tlsState
+ rp.header = make(Header)
+ for _, hf := range f.RegularFields() {
+ rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value)
+ }
+ if rp.authority == "" {
+ rp.authority = rp.header.Get("Host")
}
- header := make(Header)
- for _, hf := range f.RegularFields() {
- header.Add(sc.canonicalHeader(hf.Name), hf.Value)
+ rw, req, err := sc.newWriterAndRequestNoBody(st, rp)
+ if err != nil {
+ return nil, nil, err
}
+ if bodyOpen {
+ st.reqBuf = http2getRequestBodyBuf()
+ req.Body.(*http2requestBody).pipe = &http2pipe{
+ b: &http2fixedBuffer{buf: st.reqBuf},
+ }
- if authority == "" {
- authority = header.Get("Host")
+ if vv, ok := rp.header["Content-Length"]; ok {
+ req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
+ } else {
+ req.ContentLength = -1
+ }
}
- needsContinue := header.Get("Expect") == "100-continue"
+ return rw, req, nil
+}
+
+type http2requestParam struct {
+ method string
+ scheme, authority, path string
+ header Header
+}
+
+func (sc *http2serverConn) newWriterAndRequestNoBody(st *http2stream, rp http2requestParam) (*http2responseWriter, *Request, error) {
+ sc.serveG.check()
+
+ var tlsState *tls.ConnectionState // nil if not scheme https
+ if rp.scheme == "https" {
+ tlsState = sc.tlsState
+ }
+
+ needsContinue := rp.header.Get("Expect") == "100-continue"
if needsContinue {
- header.Del("Expect")
+ rp.header.Del("Expect")
}
- if cookies := header["Cookie"]; len(cookies) > 1 {
- header.Set("Cookie", strings.Join(cookies, "; "))
+ if cookies := rp.header["Cookie"]; len(cookies) > 1 {
+ rp.header.Set("Cookie", strings.Join(cookies, "; "))
}
// Setup Trailers
var trailer Header
- for _, v := range header["Trailer"] {
+ for _, v := range rp.header["Trailer"] {
for _, key := range strings.Split(v, ",") {
key = CanonicalHeaderKey(strings.TrimSpace(key))
switch key {
@@ -4218,55 +4505,42 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead
}
}
}
- delete(header, "Trailer")
+ delete(rp.header, "Trailer")
- body := &http2requestBody{
- conn: sc,
- stream: st,
- needsContinue: needsContinue,
- }
var url_ *url.URL
var requestURI string
- if isConnect {
- url_ = &url.URL{Host: authority}
- requestURI = authority
+ if rp.method == "CONNECT" {
+ url_ = &url.URL{Host: rp.authority}
+ requestURI = rp.authority
} else {
var err error
- url_, err = url.ParseRequestURI(path)
+ url_, err = url.ParseRequestURI(rp.path)
if err != nil {
- return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol)
+ return nil, nil, http2streamError(st.id, http2ErrCodeProtocol)
}
- requestURI = path
+ requestURI = rp.path
+ }
+
+ body := &http2requestBody{
+ conn: sc,
+ stream: st,
+ needsContinue: needsContinue,
}
req := &Request{
- Method: method,
+ Method: rp.method,
URL: url_,
RemoteAddr: sc.remoteAddrStr,
- Header: header,
+ Header: rp.header,
RequestURI: requestURI,
Proto: "HTTP/2.0",
ProtoMajor: 2,
ProtoMinor: 0,
TLS: tlsState,
- Host: authority,
+ Host: rp.authority,
Body: body,
Trailer: trailer,
}
req = http2requestWithContext(req, st.ctx)
- if bodyOpen {
-
- buf := make([]byte, http2initialWindowSize)
-
- body.pipe = &http2pipe{
- b: &http2fixedBuffer{buf: buf},
- }
-
- if vv, ok := header["Content-Length"]; ok {
- req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
- } else {
- req.ContentLength = -1
- }
- }
rws := http2responseWriterStatePool.Get().(*http2responseWriterState)
bwSave := rws.bw
@@ -4282,13 +4556,22 @@ func (sc *http2serverConn) newWriterAndRequest(st *http2stream, f *http2MetaHead
return rw, req, nil
}
-func (sc *http2serverConn) getRequestBodyBuf() []byte {
- sc.serveG.check()
- if buf := sc.freeRequestBodyBuf; buf != nil {
- sc.freeRequestBodyBuf = nil
- return buf
+var http2reqBodyCache = make(chan []byte, 8)
+
+func http2getRequestBodyBuf() []byte {
+ select {
+ case b := <-http2reqBodyCache:
+ return b
+ default:
+ return make([]byte, http2initialWindowSize)
+ }
+}
+
+func http2putRequestBodyBuf(b []byte) {
+ select {
+ case http2reqBodyCache <- b:
+ default:
}
- return make([]byte, http2initialWindowSize)
}
// Run on its own goroutine.
@@ -4298,15 +4581,17 @@ func (sc *http2serverConn) runHandler(rw *http2responseWriter, req *Request, han
rw.rws.stream.cancelCtx()
if didPanic {
e := recover()
- // Same as net/http:
- const size = 64 << 10
- buf := make([]byte, size)
- buf = buf[:runtime.Stack(buf, false)]
- sc.writeFrameFromHandler(http2frameWriteMsg{
+ sc.writeFrameFromHandler(http2FrameWriteRequest{
write: http2handlerPanicRST{rw.rws.stream.id},
stream: rw.rws.stream,
})
- sc.logf("http2: panic serving %v: %v\n%s", sc.conn.RemoteAddr(), e, buf)
+
+ if http2shouldLogPanic(e) {
+ const size = 64 << 10
+ buf := make([]byte, size)
+ buf = buf[:runtime.Stack(buf, false)]
+ sc.logf("http2: panic serving %v: %v\n%s", sc.conn.RemoteAddr(), e, buf)
+ }
return
}
rw.handlerDone()
@@ -4334,7 +4619,7 @@ func (sc *http2serverConn) writeHeaders(st *http2stream, headerData *http2writeR
errc = http2errChanPool.Get().(chan error)
}
- if err := sc.writeFrameFromHandler(http2frameWriteMsg{
+ if err := sc.writeFrameFromHandler(http2FrameWriteRequest{
write: headerData,
stream: st,
done: errc,
@@ -4357,7 +4642,7 @@ func (sc *http2serverConn) writeHeaders(st *http2stream, headerData *http2writeR
// called from handler goroutines.
func (sc *http2serverConn) write100ContinueHeaders(st *http2stream) {
- sc.writeFrameFromHandler(http2frameWriteMsg{
+ sc.writeFrameFromHandler(http2FrameWriteRequest{
write: http2write100ContinueHeadersFrame{st.id},
stream: st,
})
@@ -4373,11 +4658,19 @@ type http2bodyReadMsg struct {
// called from handler goroutines.
// Notes that the handler for the given stream ID read n bytes of its body
// and schedules flow control tokens to be sent.
-func (sc *http2serverConn) noteBodyReadFromHandler(st *http2stream, n int) {
+func (sc *http2serverConn) noteBodyReadFromHandler(st *http2stream, n int, err error) {
sc.serveG.checkNotOn()
- select {
- case sc.bodyReadCh <- http2bodyReadMsg{st, n}:
- case <-sc.doneServing:
+ if n > 0 {
+ select {
+ case sc.bodyReadCh <- http2bodyReadMsg{st, n}:
+ case <-sc.doneServing:
+ }
+ }
+ if err == io.EOF {
+ if buf := st.reqBuf; buf != nil {
+ st.reqBuf = nil
+ http2putRequestBodyBuf(buf)
+ }
}
}
@@ -4419,7 +4712,7 @@ func (sc *http2serverConn) sendWindowUpdate32(st *http2stream, n int32) {
if st != nil {
streamID = st.id
}
- sc.writeFrame(http2frameWriteMsg{
+ sc.writeFrame(http2FrameWriteRequest{
write: http2writeWindowUpdate{streamID: streamID, n: uint32(n)},
stream: st,
})
@@ -4434,16 +4727,19 @@ func (sc *http2serverConn) sendWindowUpdate32(st *http2stream, n int32) {
}
}
+// requestBody is the Handler's Request.Body type.
+// Read and Close may be called concurrently.
type http2requestBody struct {
stream *http2stream
conn *http2serverConn
- closed bool
+ closed bool // for use by Close only
+ sawEOF bool // for use by Read only
pipe *http2pipe // non-nil if we have a HTTP entity message body
needsContinue bool // need to send a 100-continue
}
func (b *http2requestBody) Close() error {
- if b.pipe != nil {
+ if b.pipe != nil && !b.closed {
b.pipe.BreakWithError(http2errClosedBody)
}
b.closed = true
@@ -4455,13 +4751,17 @@ func (b *http2requestBody) Read(p []byte) (n int, err error) {
b.needsContinue = false
b.conn.write100ContinueHeaders(b.stream)
}
- if b.pipe == nil {
+ if b.pipe == nil || b.sawEOF {
return 0, io.EOF
}
n, err = b.pipe.Read(p)
- if n > 0 {
- b.conn.noteBodyReadFromHandler(b.stream, n)
+ if err == io.EOF {
+ b.sawEOF = true
}
+ if b.conn == nil && http2inTests {
+ return
+ }
+ b.conn.noteBodyReadFromHandler(b.stream, n, err)
return
}
@@ -4696,8 +4996,9 @@ func (w *http2responseWriter) CloseNotify() <-chan bool {
if ch == nil {
ch = make(chan bool, 1)
rws.closeNotifierCh = ch
+ cw := rws.stream.cw
go func() {
- rws.stream.cw.Wait()
+ cw.Wait()
ch <- true
}()
}
@@ -4793,6 +5094,172 @@ func (w *http2responseWriter) handlerDone() {
http2responseWriterStatePool.Put(rws)
}
+// Push errors.
+var (
+ http2ErrRecursivePush = errors.New("http2: recursive push not allowed")
+ http2ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS")
+)
+
+// pushOptions is the internal version of http.PushOptions, which we
+// cannot include here because it's only defined in Go 1.8 and later.
+type http2pushOptions struct {
+ Method string
+ Header Header
+}
+
+func (w *http2responseWriter) push(target string, opts http2pushOptions) error {
+ st := w.rws.stream
+ sc := st.sc
+ sc.serveG.checkNotOn()
+
+ if st.isPushed() {
+ return http2ErrRecursivePush
+ }
+
+ if opts.Method == "" {
+ opts.Method = "GET"
+ }
+ if opts.Header == nil {
+ opts.Header = Header{}
+ }
+ wantScheme := "http"
+ if w.rws.req.TLS != nil {
+ wantScheme = "https"
+ }
+
+ u, err := url.Parse(target)
+ if err != nil {
+ return err
+ }
+ if u.Scheme == "" {
+ if !strings.HasPrefix(target, "/") {
+ return fmt.Errorf("target must be an absolute URL or an absolute path: %q", target)
+ }
+ u.Scheme = wantScheme
+ u.Host = w.rws.req.Host
+ } else {
+ if u.Scheme != wantScheme {
+ return fmt.Errorf("cannot push URL with scheme %q from request with scheme %q", u.Scheme, wantScheme)
+ }
+ if u.Host == "" {
+ return errors.New("URL must have a host")
+ }
+ }
+ for k := range opts.Header {
+ if strings.HasPrefix(k, ":") {
+ return fmt.Errorf("promised request headers cannot include pseudo header %q", k)
+ }
+
+ switch strings.ToLower(k) {
+ case "content-length", "content-encoding", "trailer", "te", "expect", "host":
+ return fmt.Errorf("promised request headers cannot include %q", k)
+ }
+ }
+ if err := http2checkValidHTTP2RequestHeaders(opts.Header); err != nil {
+ return err
+ }
+
+ if opts.Method != "GET" && opts.Method != "HEAD" {
+ return fmt.Errorf("method %q must be GET or HEAD", opts.Method)
+ }
+
+ msg := http2startPushRequest{
+ parent: st,
+ method: opts.Method,
+ url: u,
+ header: http2cloneHeader(opts.Header),
+ done: http2errChanPool.Get().(chan error),
+ }
+
+ select {
+ case <-sc.doneServing:
+ return http2errClientDisconnected
+ case <-st.cw:
+ return http2errStreamClosed
+ case sc.wantStartPushCh <- msg:
+ }
+
+ select {
+ case <-sc.doneServing:
+ return http2errClientDisconnected
+ case <-st.cw:
+ return http2errStreamClosed
+ case err := <-msg.done:
+ http2errChanPool.Put(msg.done)
+ return err
+ }
+}
+
+type http2startPushRequest struct {
+ parent *http2stream
+ method string
+ url *url.URL
+ header Header
+ done chan error
+}
+
+func (sc *http2serverConn) startPush(msg http2startPushRequest) {
+ sc.serveG.check()
+
+ if msg.parent.state != http2stateOpen && msg.parent.state != http2stateHalfClosedRemote {
+
+ msg.done <- http2errStreamClosed
+ return
+ }
+
+ if !sc.pushEnabled {
+ msg.done <- ErrNotSupported
+ return
+ }
+
+ allocatePromisedID := func() (uint32, error) {
+ sc.serveG.check()
+
+ if !sc.pushEnabled {
+ return 0, ErrNotSupported
+ }
+
+ if sc.curPushedStreams+1 > sc.clientMaxStreams {
+ return 0, http2ErrPushLimitReached
+ }
+
+ if sc.maxPushPromiseID+2 >= 1<<31 {
+ sc.startGracefulShutdown()
+ return 0, http2ErrPushLimitReached
+ }
+ sc.maxPushPromiseID += 2
+ promisedID := sc.maxPushPromiseID
+
+ promised := sc.newStream(promisedID, msg.parent.id, http2stateHalfClosedRemote)
+ rw, req, err := sc.newWriterAndRequestNoBody(promised, http2requestParam{
+ method: msg.method,
+ scheme: msg.url.Scheme,
+ authority: msg.url.Host,
+ path: msg.url.RequestURI(),
+ header: http2cloneHeader(msg.header),
+ })
+ if err != nil {
+
+ panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", msg.url, err))
+ }
+
+ go sc.runHandler(rw, req, sc.handler.ServeHTTP)
+ return promisedID, nil
+ }
+
+ sc.writeFrame(http2FrameWriteRequest{
+ write: &http2writePushPromise{
+ streamID: msg.parent.id,
+ method: msg.method,
+ url: msg.url,
+ h: msg.header,
+ allocatePromisedID: allocatePromisedID,
+ },
+ stream: msg.parent,
+ done: msg.done,
+ })
+}
+
// foreachHeaderElement splits v according to the "#rule" construction
// in RFC 2616 section 2.1 and calls fn for each non-empty element.
func http2foreachHeaderElement(v string, fn func(string)) {
@@ -4820,16 +5287,16 @@ var http2connHeaders = []string{
"Upgrade",
}
-// checkValidHTTP2Request checks whether req is a valid HTTP/2 request,
+// checkValidHTTP2RequestHeaders checks whether h is a valid HTTP/2 request,
// per RFC 7540 Section 8.1.2.2.
// The returned error is reported to users.
-func http2checkValidHTTP2Request(req *Request) error {
- for _, h := range http2connHeaders {
- if _, ok := req.Header[h]; ok {
- return fmt.Errorf("request header %q is not valid in HTTP/2", h)
+func http2checkValidHTTP2RequestHeaders(h Header) error {
+ for _, k := range http2connHeaders {
+ if _, ok := h[k]; ok {
+ return fmt.Errorf("request header %q is not valid in HTTP/2", k)
}
}
- te := req.Header["Te"]
+ te := h["Te"]
if len(te) > 0 && (len(te) > 1 || (te[0] != "trailers" && te[0] != "")) {
return errors.New(`request header "TE" may only be "trailers" in HTTP/2`)
}
@@ -4877,6 +5344,45 @@ var http2badTrailer = map[string]bool{
"Www-Authenticate": true,
}
+// h1ServerShutdownChan returns a channel that will be closed when the
+// provided *http.Server wants to shut down.
+//
+// This is a somewhat hacky way to get at http1 innards. It works
+// when the http2 code is bundled into the net/http package in the
+// standard library. The alternatives ended up making the cmd/go tool
+// depend on http Servers. This is the lightest option for now.
+// This is tested via the TestServeShutdown* tests in net/http.
+func http2h1ServerShutdownChan(hs *Server) <-chan struct{} {
+ if fn := http2testh1ServerShutdownChan; fn != nil {
+ return fn(hs)
+ }
+ var x interface{} = hs
+ type I interface {
+ getDoneChan() <-chan struct{}
+ }
+ if hs, ok := x.(I); ok {
+ return hs.getDoneChan()
+ }
+ return nil
+}
+
+// optional test hook for h1ServerShutdownChan.
+var http2testh1ServerShutdownChan func(hs *Server) <-chan struct{}
+
+// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
+// disabled. See comments on h1ServerShutdownChan above for why
+// the code is written this way.
+func http2h1ServerKeepAlivesDisabled(hs *Server) bool {
+ var x interface{} = hs
+ type I interface {
+ doKeepAlives() bool
+ }
+ if hs, ok := x.(I); ok {
+ return !hs.doKeepAlives()
+ }
+ return false
+}
+
const (
// transportDefaultConnFlow is how many connection-level flow control
// tokens we give the server at start-up, past the default 64k.
@@ -4997,6 +5503,9 @@ type http2ClientConn struct {
readerDone chan struct{} // closed on error
readerErr error // set before readerDone is closed
+ idleTimeout time.Duration // or 0 for never
+ idleTimer *time.Timer
+
mu sync.Mutex // guards following
cond *sync.Cond // hold mu; broadcast on flow/closed changes
flow http2flow // our conn-level flow control quota (cs.flow is per stream)
@@ -5007,6 +5516,7 @@ type http2ClientConn struct {
goAwayDebug string // goAway frame's debug data, retained as a string
streams map[uint32]*http2clientStream // client-initiated
nextStreamID uint32
+ pings map[[8]byte]chan struct{} // in flight ping data to notification channel
bw *bufio.Writer
br *bufio.Reader
fr *http2Framer
@@ -5033,6 +5543,7 @@ type http2clientStream struct {
ID uint32
resc chan http2resAndError
bufPipe http2pipe // buffered pipe with the flow-controlled response payload
+ startedWrite bool // started request body write; guarded by cc.mu
requestedGzip bool
on100 func() // optional code to run if get a 100 continue response
@@ -5041,6 +5552,7 @@ type http2clientStream struct {
bytesRemain int64 // -1 means unknown; owned by transportResponseBody.Read
readErr error // sticky read error; owned by transportResponseBody.Read
stopReqBody error // if non-nil, stop writing req body; guarded by cc.mu
+ didReset bool // whether we sent a RST_STREAM to the server; guarded by cc.mu
peerReset chan struct{} // closed on peer reset
resetErr error // populated before peerReset is closed
@@ -5068,15 +5580,26 @@ func (cs *http2clientStream) awaitRequestCancel(req *Request) {
}
select {
case <-req.Cancel:
+ cs.cancelStream()
cs.bufPipe.CloseWithError(http2errRequestCanceled)
- cs.cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil)
case <-ctx.Done():
+ cs.cancelStream()
cs.bufPipe.CloseWithError(ctx.Err())
- cs.cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil)
case <-cs.done:
}
}
+func (cs *http2clientStream) cancelStream() {
+ cs.cc.mu.Lock()
+ didReset := cs.didReset
+ cs.didReset = true
+ cs.cc.mu.Unlock()
+
+ if !didReset {
+ cs.cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil)
+ }
+}
+
// checkResetOrDone reports any error sent in a RST_STREAM frame by the
// server, or errStreamClosed if the stream is complete.
func (cs *http2clientStream) checkResetOrDone() error {
@@ -5133,14 +5656,22 @@ func (t *http2Transport) RoundTrip(req *Request) (*Response, error) {
// authorityAddr returns a given authority (a host/IP, or host:port / ip:port)
// and returns a host:port. The port 443 is added if needed.
func http2authorityAddr(scheme string, authority string) (addr string) {
- if _, _, err := net.SplitHostPort(authority); err == nil {
- return authority
+ host, port, err := net.SplitHostPort(authority)
+ if err != nil {
+ port = "443"
+ if scheme == "http" {
+ port = "80"
+ }
+ host = authority
+ }
+ if a, err := idna.ToASCII(host); err == nil {
+ host = a
}
- port := "443"
- if scheme == "http" {
- port = "80"
+
+ if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
+ return host + ":" + port
}
- return net.JoinHostPort(authority, port)
+ return net.JoinHostPort(host, port)
}
// RoundTripOpt is like RoundTrip, but takes options.
@@ -5158,8 +5689,10 @@ func (t *http2Transport) RoundTripOpt(req *Request, opt http2RoundTripOpt) (*Res
}
http2traceGotConn(req, cc)
res, err := cc.RoundTrip(req)
- if http2shouldRetryRequest(req, err) {
- continue
+ if err != nil {
+ if req, err = http2shouldRetryRequest(req, err); err == nil {
+ continue
+ }
}
if err != nil {
t.vlogf("RoundTrip failure: %v", err)
@@ -5181,11 +5714,39 @@ func (t *http2Transport) CloseIdleConnections() {
var (
http2errClientConnClosed = errors.New("http2: client conn is closed")
http2errClientConnUnusable = errors.New("http2: client conn not usable")
+
+ http2errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
+ http2errClientConnGotGoAwayAfterSomeReqBody = errors.New("http2: Transport received Server's graceful shutdown GOAWAY; some request body already written")
)
-func http2shouldRetryRequest(req *Request, err error) bool {
+// shouldRetryRequest is called by RoundTrip when a request fails to get
+// response headers. It is always called with a non-nil error.
+// It returns either a request to retry (either the same request, or a
+// modified clone), or an error if the request can't be replayed.
+func http2shouldRetryRequest(req *Request, err error) (*Request, error) {
+ switch err {
+ default:
+ return nil, err
+ case http2errClientConnUnusable, http2errClientConnGotGoAway:
+ return req, nil
+ case http2errClientConnGotGoAwayAfterSomeReqBody:
+
+ if req.Body == nil || http2reqBodyIsNoBody(req.Body) {
+ return req, nil
+ }
- return err == http2errClientConnUnusable
+ getBody := http2reqGetBody(req)
+ if getBody == nil {
+ return nil, errors.New("http2: Transport: peer server initiated graceful shutdown after some of Request.Body was written; define Request.GetBody to avoid this error")
+ }
+ body, err := getBody()
+ if err != nil {
+ return nil, err
+ }
+ newReq := *req
+ newReq.Body = body
+ return &newReq, nil
+ }
}
func (t *http2Transport) dialClientConn(addr string, singleUse bool) (*http2ClientConn, error) {
@@ -5203,7 +5764,7 @@ func (t *http2Transport) dialClientConn(addr string, singleUse bool) (*http2Clie
func (t *http2Transport) newTLSConfig(host string) *tls.Config {
cfg := new(tls.Config)
if t.TLSClientConfig != nil {
- *cfg = *t.TLSClientConfig
+ *cfg = *http2cloneTLSConfig(t.TLSClientConfig)
}
if !http2strSliceContains(cfg.NextProtos, http2NextProtoTLS) {
cfg.NextProtos = append([]string{http2NextProtoTLS}, cfg.NextProtos...)
@@ -5273,6 +5834,11 @@ func (t *http2Transport) newClientConn(c net.Conn, singleUse bool) (*http2Client
streams: make(map[uint32]*http2clientStream),
singleUse: singleUse,
wantSettingsAck: true,
+ pings: make(map[[8]byte]chan struct{}),
+ }
+ if d := t.idleConnTimeout(); d != 0 {
+ cc.idleTimeout = d
+ cc.idleTimer = time.AfterFunc(d, cc.onIdleTimeout)
}
if http2VerboseLogs {
t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
@@ -5328,6 +5894,15 @@ func (cc *http2ClientConn) setGoAway(f *http2GoAwayFrame) {
if old != nil && old.ErrCode != http2ErrCodeNo {
cc.goAway.ErrCode = old.ErrCode
}
+ last := f.LastStreamID
+ for streamID, cs := range cc.streams {
+ if streamID > last {
+ select {
+ case cs.resc <- http2resAndError{err: http2errClientConnGotGoAway}:
+ default:
+ }
+ }
+ }
}
func (cc *http2ClientConn) CanTakeNewRequest() bool {
@@ -5345,6 +5920,16 @@ func (cc *http2ClientConn) canTakeNewRequestLocked() bool {
cc.nextStreamID < math.MaxInt32
}
+// onIdleTimeout is called from a time.AfterFunc goroutine. It will
+// only be called when we're idle, but because we're coming from a new
+// goroutine, there could be a new request coming in at the same time,
+// so this simply calls the synchronized closeIfIdle to shut down this
+// connection. The timer could just call closeIfIdle, but this is more
+// clear.
+func (cc *http2ClientConn) onIdleTimeout() {
+ cc.closeIfIdle()
+}
+
func (cc *http2ClientConn) closeIfIdle() {
cc.mu.Lock()
if len(cc.streams) > 0 {
@@ -5437,48 +6022,37 @@ func (cc *http2ClientConn) responseHeaderTimeout() time.Duration {
// Certain headers are special-cased as okay but not transmitted later.
func http2checkConnHeaders(req *Request) error {
if v := req.Header.Get("Upgrade"); v != "" {
- return errors.New("http2: invalid Upgrade request header")
+ return fmt.Errorf("http2: invalid Upgrade request header: %q", req.Header["Upgrade"])
}
- if v := req.Header.Get("Transfer-Encoding"); (v != "" && v != "chunked") || len(req.Header["Transfer-Encoding"]) > 1 {
- return errors.New("http2: invalid Transfer-Encoding request header")
+ if vv := req.Header["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") {
+ return fmt.Errorf("http2: invalid Transfer-Encoding request header: %q", vv)
}
- if v := req.Header.Get("Connection"); (v != "" && v != "close" && v != "keep-alive") || len(req.Header["Connection"]) > 1 {
- return errors.New("http2: invalid Connection request header")
+ if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "close" && vv[0] != "keep-alive") {
+ return fmt.Errorf("http2: invalid Connection request header: %q", vv)
}
return nil
}
-func http2bodyAndLength(req *Request) (body io.Reader, contentLen int64) {
- body = req.Body
- if body == nil {
- return nil, 0
+// actualContentLength returns a sanitized version of
+// req.ContentLength, where 0 actually means zero (not unknown) and -1
+// means unknown.
+func http2actualContentLength(req *Request) int64 {
+ if req.Body == nil {
+ return 0
}
if req.ContentLength != 0 {
- return req.Body, req.ContentLength
- }
-
- // We have a body but a zero content length. Test to see if
- // it's actually zero or just unset.
- var buf [1]byte
- n, rerr := body.Read(buf[:])
- if rerr != nil && rerr != io.EOF {
- return http2errorReader{rerr}, -1
- }
- if n == 1 {
-
- if rerr == io.EOF {
- return bytes.NewReader(buf[:]), 1
- }
- return io.MultiReader(bytes.NewReader(buf[:]), body), -1
+ return req.ContentLength
}
-
- return nil, 0
+ return -1
}
func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
if err := http2checkConnHeaders(req); err != nil {
return nil, err
}
+ if cc.idleTimer != nil {
+ cc.idleTimer.Stop()
+ }
trailers, err := http2commaSeparatedTrailers(req)
if err != nil {
@@ -5486,9 +6060,6 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
}
hasTrailers := trailers != ""
- body, contentLen := http2bodyAndLength(req)
- hasBody := body != nil
-
cc.mu.Lock()
cc.lastActive = time.Now()
if cc.closed || !cc.canTakeNewRequestLocked() {
@@ -5496,6 +6067,10 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
return nil, http2errClientConnUnusable
}
+ body := req.Body
+ hasBody := body != nil
+ contentLen := http2actualContentLength(req)
+
// TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
var requestedGzip bool
if !cc.t.disableCompression() &&
@@ -5561,6 +6136,13 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
cs.abortRequestBodyWrite(http2errStopReqBodyWrite)
}
if re.err != nil {
+ if re.err == http2errClientConnGotGoAway {
+ cc.mu.Lock()
+ if cs.startedWrite {
+ re.err = http2errClientConnGotGoAwayAfterSomeReqBody
+ }
+ cc.mu.Unlock()
+ }
cc.forgetStreamID(cs.ID)
return nil, re.err
}
@@ -5806,6 +6388,26 @@ func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trail
if host == "" {
host = req.URL.Host
}
+ host, err := httplex.PunycodeHostPort(host)
+ if err != nil {
+ return nil, err
+ }
+
+ var path string
+ if req.Method != "CONNECT" {
+ path = req.URL.RequestURI()
+ if !http2validPseudoPath(path) {
+ orig := path
+ path = strings.TrimPrefix(path, req.URL.Scheme+"://"+host)
+ if !http2validPseudoPath(path) {
+ if req.URL.Opaque != "" {
+ return nil, fmt.Errorf("invalid request :path %q from URL.Opaque = %q", orig, req.URL.Opaque)
+ } else {
+ return nil, fmt.Errorf("invalid request :path %q", orig)
+ }
+ }
+ }
+ }
for k, vv := range req.Header {
if !httplex.ValidHeaderFieldName(k) {
@@ -5821,8 +6423,8 @@ func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trail
cc.writeHeader(":authority", host)
cc.writeHeader(":method", req.Method)
if req.Method != "CONNECT" {
- cc.writeHeader(":path", req.URL.RequestURI())
- cc.writeHeader(":scheme", "https")
+ cc.writeHeader(":path", path)
+ cc.writeHeader(":scheme", req.URL.Scheme)
}
if trailers != "" {
cc.writeHeader("trailer", trailers)
@@ -5940,6 +6542,9 @@ func (cc *http2ClientConn) streamByID(id uint32, andRemove bool) *http2clientStr
if andRemove && cs != nil && !cc.closed {
cc.lastActive = time.Now()
delete(cc.streams, id)
+ if len(cc.streams) == 0 && cc.idleTimer != nil {
+ cc.idleTimer.Reset(cc.idleTimeout)
+ }
close(cs.done)
cc.cond.Broadcast()
}
@@ -5996,6 +6601,10 @@ func (rl *http2clientConnReadLoop) cleanup() {
defer cc.t.connPool().MarkDead(cc)
defer close(cc.readerDone)
+ if cc.idleTimer != nil {
+ cc.idleTimer.Stop()
+ }
+
err := cc.readerErr
cc.mu.Lock()
if cc.goAway != nil && http2isEOFOrNetReadError(err) {
@@ -6398,9 +7007,10 @@ func (rl *http2clientConnReadLoop) processData(f *http2DataFrame) error {
cc.bw.Flush()
cc.wmu.Unlock()
}
+ didReset := cs.didReset
cc.mu.Unlock()
- if len(data) > 0 {
+ if len(data) > 0 && !didReset {
if _, err := cs.bufPipe.Write(data); err != nil {
rl.endStreamError(cs, err)
return err
@@ -6551,9 +7161,56 @@ func (rl *http2clientConnReadLoop) processResetStream(f *http2RSTStreamFrame) er
return nil
}
+// Ping sends a PING frame to the server and waits for the ack.
+// Public implementation is in go17.go and not_go17.go
+func (cc *http2ClientConn) ping(ctx http2contextContext) error {
+ c := make(chan struct{})
+ // Generate a random payload
+ var p [8]byte
+ for {
+ if _, err := rand.Read(p[:]); err != nil {
+ return err
+ }
+ cc.mu.Lock()
+
+ if _, found := cc.pings[p]; !found {
+ cc.pings[p] = c
+ cc.mu.Unlock()
+ break
+ }
+ cc.mu.Unlock()
+ }
+ cc.wmu.Lock()
+ if err := cc.fr.WritePing(false, p); err != nil {
+ cc.wmu.Unlock()
+ return err
+ }
+ if err := cc.bw.Flush(); err != nil {
+ cc.wmu.Unlock()
+ return err
+ }
+ cc.wmu.Unlock()
+ select {
+ case <-c:
+ return nil
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-cc.readerDone:
+
+ return cc.readerErr
+ }
+}
+
func (rl *http2clientConnReadLoop) processPing(f *http2PingFrame) error {
if f.IsAck() {
+ cc := rl.cc
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ if c, ok := cc.pings[f.Data]; ok {
+ close(c)
+ delete(cc.pings, f.Data)
+ }
return nil
}
cc := rl.cc
@@ -6666,6 +7323,9 @@ func (t *http2Transport) getBodyWriterState(cs *http2clientStream, body io.Reade
resc := make(chan error, 1)
s.resc = resc
s.fn = func() {
+ cs.cc.mu.Lock()
+ cs.startedWrite = true
+ cs.cc.mu.Unlock()
resc <- cs.writeRequestBody(body, cs.req.Body)
}
s.delay = t.expectContinueTimeout()
@@ -6728,6 +7388,11 @@ func http2isConnectionCloseRequest(req *Request) bool {
// writeFramer is implemented by any type that is used to write frames.
type http2writeFramer interface {
writeFrame(http2writeContext) error
+
+ // staysWithinBuffer reports whether this writer promises that
+ // it will only write less than or equal to size bytes, and it
+ // won't Flush the write context.
+ staysWithinBuffer(size int) bool
}
// writeContext is the interface needed by the various frame writer
@@ -6749,9 +7414,10 @@ type http2writeContext interface {
HeaderEncoder() (*hpack.Encoder, *bytes.Buffer)
}
-// endsStream reports whether the given frame writer w will locally
-// close the stream.
-func http2endsStream(w http2writeFramer) bool {
+// writeEndsStream reports whether w writes a frame that will transition
+// the stream to a half-closed local state. This returns false for RST_STREAM,
+// which closes the entire stream (not just the local half).
+func http2writeEndsStream(w http2writeFramer) bool {
switch v := w.(type) {
case *http2writeData:
return v.endStream
@@ -6759,7 +7425,7 @@ func http2endsStream(w http2writeFramer) bool {
return v.endStream
case nil:
- panic("endsStream called on nil writeFramer")
+ panic("writeEndsStream called on nil writeFramer")
}
return false
}
@@ -6770,8 +7436,16 @@ func (http2flushFrameWriter) writeFrame(ctx http2writeContext) error {
return ctx.Flush()
}
+func (http2flushFrameWriter) staysWithinBuffer(max int) bool { return false }
+
type http2writeSettings []http2Setting
+func (s http2writeSettings) staysWithinBuffer(max int) bool {
+ const settingSize = 6 // uint16 + uint32
+ return http2frameHeaderLen+settingSize*len(s) <= max
+
+}
+
func (s http2writeSettings) writeFrame(ctx http2writeContext) error {
return ctx.Framer().WriteSettings([]http2Setting(s)...)
}
@@ -6791,6 +7465,8 @@ func (p *http2writeGoAway) writeFrame(ctx http2writeContext) error {
return err
}
+func (*http2writeGoAway) staysWithinBuffer(max int) bool { return false }
+
type http2writeData struct {
streamID uint32
p []byte
@@ -6805,6 +7481,10 @@ func (w *http2writeData) writeFrame(ctx http2writeContext) error {
return ctx.Framer().WriteData(w.streamID, w.endStream, w.p)
}
+func (w *http2writeData) staysWithinBuffer(max int) bool {
+ return http2frameHeaderLen+len(w.p) <= max
+}
+
// handlerPanicRST is the message sent from handler goroutines when
// the handler panics.
type http2handlerPanicRST struct {
@@ -6815,22 +7495,59 @@ func (hp http2handlerPanicRST) writeFrame(ctx http2writeContext) error {
return ctx.Framer().WriteRSTStream(hp.StreamID, http2ErrCodeInternal)
}
+func (hp http2handlerPanicRST) staysWithinBuffer(max int) bool { return http2frameHeaderLen+4 <= max }
+
func (se http2StreamError) writeFrame(ctx http2writeContext) error {
return ctx.Framer().WriteRSTStream(se.StreamID, se.Code)
}
+func (se http2StreamError) staysWithinBuffer(max int) bool { return http2frameHeaderLen+4 <= max }
+
type http2writePingAck struct{ pf *http2PingFrame }
func (w http2writePingAck) writeFrame(ctx http2writeContext) error {
return ctx.Framer().WritePing(true, w.pf.Data)
}
+func (w http2writePingAck) staysWithinBuffer(max int) bool {
+ return http2frameHeaderLen+len(w.pf.Data) <= max
+}
+
type http2writeSettingsAck struct{}
func (http2writeSettingsAck) writeFrame(ctx http2writeContext) error {
return ctx.Framer().WriteSettingsAck()
}
+func (http2writeSettingsAck) staysWithinBuffer(max int) bool { return http2frameHeaderLen <= max }
+
+// splitHeaderBlock splits headerBlock into fragments so that each fragment fits
+// in a single frame, then calls fn for each fragment. firstFrag/lastFrag are true
+// for the first/last fragment, respectively.
+func http2splitHeaderBlock(ctx http2writeContext, headerBlock []byte, fn func(ctx http2writeContext, frag []byte, firstFrag, lastFrag bool) error) error {
+ // For now we're lazy and just pick the minimum MAX_FRAME_SIZE
+ // that all peers must support (16KB). Later we could care
+ // more and send larger frames if the peer advertised it, but
+ // there's little point. Most headers are small anyway (so we
+ // generally won't have CONTINUATION frames), and extra frames
+ // only waste 9 bytes anyway.
+ const maxFrameSize = 16384
+
+ first := true
+ for len(headerBlock) > 0 {
+ frag := headerBlock
+ if len(frag) > maxFrameSize {
+ frag = frag[:maxFrameSize]
+ }
+ headerBlock = headerBlock[len(frag):]
+ if err := fn(ctx, frag, first, len(headerBlock) == 0); err != nil {
+ return err
+ }
+ first = false
+ }
+ return nil
+}
+
// writeResHeaders is a request to write a HEADERS and 0+ CONTINUATION frames
// for HTTP response headers or trailers from a server handler.
type http2writeResHeaders struct {
@@ -6852,6 +7569,11 @@ func http2encKV(enc *hpack.Encoder, k, v string) {
enc.WriteField(hpack.HeaderField{Name: k, Value: v})
}
+func (w *http2writeResHeaders) staysWithinBuffer(max int) bool {
+
+ return false
+}
+
func (w *http2writeResHeaders) writeFrame(ctx http2writeContext) error {
enc, buf := ctx.HeaderEncoder()
buf.Reset()
@@ -6877,39 +7599,69 @@ func (w *http2writeResHeaders) writeFrame(ctx http2writeContext) error {
panic("unexpected empty hpack")
}
- // For now we're lazy and just pick the minimum MAX_FRAME_SIZE
- // that all peers must support (16KB). Later we could care
- // more and send larger frames if the peer advertised it, but
- // there's little point. Most headers are small anyway (so we
- // generally won't have CONTINUATION frames), and extra frames
- // only waste 9 bytes anyway.
- const maxFrameSize = 16384
+ return http2splitHeaderBlock(ctx, headerBlock, w.writeHeaderBlock)
+}
- first := true
- for len(headerBlock) > 0 {
- frag := headerBlock
- if len(frag) > maxFrameSize {
- frag = frag[:maxFrameSize]
- }
- headerBlock = headerBlock[len(frag):]
- endHeaders := len(headerBlock) == 0
- var err error
- if first {
- first = false
- err = ctx.Framer().WriteHeaders(http2HeadersFrameParam{
- StreamID: w.streamID,
- BlockFragment: frag,
- EndStream: w.endStream,
- EndHeaders: endHeaders,
- })
- } else {
- err = ctx.Framer().WriteContinuation(w.streamID, endHeaders, frag)
- }
- if err != nil {
- return err
- }
+func (w *http2writeResHeaders) writeHeaderBlock(ctx http2writeContext, frag []byte, firstFrag, lastFrag bool) error {
+ if firstFrag {
+ return ctx.Framer().WriteHeaders(http2HeadersFrameParam{
+ StreamID: w.streamID,
+ BlockFragment: frag,
+ EndStream: w.endStream,
+ EndHeaders: lastFrag,
+ })
+ } else {
+ return ctx.Framer().WriteContinuation(w.streamID, lastFrag, frag)
+ }
+}
+
+// writePushPromise is a request to write a PUSH_PROMISE and 0+ CONTINUATION frames.
+type http2writePushPromise struct {
+ streamID uint32 // pusher stream
+ method string // for :method
+ url *url.URL // for :scheme, :authority, :path
+ h Header
+
+ // Creates an ID for a pushed stream. This runs on serveG just before
+ // the frame is written. The returned ID is copied to promisedID.
+ allocatePromisedID func() (uint32, error)
+ promisedID uint32
+}
+
+func (w *http2writePushPromise) staysWithinBuffer(max int) bool {
+
+ return false
+}
+
+func (w *http2writePushPromise) writeFrame(ctx http2writeContext) error {
+ enc, buf := ctx.HeaderEncoder()
+ buf.Reset()
+
+ http2encKV(enc, ":method", w.method)
+ http2encKV(enc, ":scheme", w.url.Scheme)
+ http2encKV(enc, ":authority", w.url.Host)
+ http2encKV(enc, ":path", w.url.RequestURI())
+ http2encodeHeaders(enc, w.h, nil)
+
+ headerBlock := buf.Bytes()
+ if len(headerBlock) == 0 {
+ panic("unexpected empty hpack")
+ }
+
+ return http2splitHeaderBlock(ctx, headerBlock, w.writeHeaderBlock)
+}
+
+func (w *http2writePushPromise) writeHeaderBlock(ctx http2writeContext, frag []byte, firstFrag, lastFrag bool) error {
+ if firstFrag {
+ return ctx.Framer().WritePushPromise(http2PushPromiseParam{
+ StreamID: w.streamID,
+ PromiseID: w.promisedID,
+ BlockFragment: frag,
+ EndHeaders: lastFrag,
+ })
+ } else {
+ return ctx.Framer().WriteContinuation(w.streamID, lastFrag, frag)
}
- return nil
}
type http2write100ContinueHeadersFrame struct {
@@ -6928,15 +7680,24 @@ func (w http2write100ContinueHeadersFrame) writeFrame(ctx http2writeContext) err
})
}
+func (w http2write100ContinueHeadersFrame) staysWithinBuffer(max int) bool {
+
+ return 9+2*(len(":status")+len("100")) <= max
+}
+
type http2writeWindowUpdate struct {
streamID uint32 // or 0 for conn-level
n uint32
}
+func (wu http2writeWindowUpdate) staysWithinBuffer(max int) bool { return http2frameHeaderLen+4 <= max }
+
func (wu http2writeWindowUpdate) writeFrame(ctx http2writeContext) error {
return ctx.Framer().WriteWindowUpdate(wu.streamID, wu.n)
}
+// encodeHeaders encodes an http.Header. If keys is not nil, then (k, h[k])
+// is encoded only only if k is in keys.
func http2encodeHeaders(enc *hpack.Encoder, h Header, keys []string) {
if keys == nil {
sorter := http2sorterPool.Get().(*http2sorter)
@@ -6966,14 +7727,53 @@ func http2encodeHeaders(enc *hpack.Encoder, h Header, keys []string) {
}
}
-// frameWriteMsg is a request to write a frame.
-type http2frameWriteMsg struct {
+// WriteScheduler is the interface implemented by HTTP/2 write schedulers.
+// Methods are never called concurrently.
+type http2WriteScheduler interface {
+ // OpenStream opens a new stream in the write scheduler.
+ // It is illegal to call this with streamID=0 or with a streamID that is
+ // already open -- the call may panic.
+ OpenStream(streamID uint32, options http2OpenStreamOptions)
+
+ // CloseStream closes a stream in the write scheduler. Any frames queued on
+ // this stream should be discarded. It is illegal to call this on a stream
+ // that is not open -- the call may panic.
+ CloseStream(streamID uint32)
+
+ // AdjustStream adjusts the priority of the given stream. This may be called
+ // on a stream that has not yet been opened or has been closed. Note that
+ // RFC 7540 allows PRIORITY frames to be sent on streams in any state. See:
+ // https://tools.ietf.org/html/rfc7540#section-5.1
+ AdjustStream(streamID uint32, priority http2PriorityParam)
+
+ // Push queues a frame in the scheduler. In most cases, this will not be
+ // called with wr.StreamID()!=0 unless that stream is currently open. The one
+ // exception is RST_STREAM frames, which may be sent on idle or closed streams.
+ Push(wr http2FrameWriteRequest)
+
+ // Pop dequeues the next frame to write. Returns false if no frames can
+ // be written. Frames with a given wr.StreamID() are Pop'd in the same
+ // order they are Push'd.
+ Pop() (wr http2FrameWriteRequest, ok bool)
+}
+
+// OpenStreamOptions specifies extra options for WriteScheduler.OpenStream.
+type http2OpenStreamOptions struct {
+ // PusherID is zero if the stream was initiated by the client. Otherwise,
+ // PusherID names the stream that pushed the newly opened stream.
+ PusherID uint32
+}
+
+// FrameWriteRequest is a request to write a frame.
+type http2FrameWriteRequest struct {
// write is the interface value that does the writing, once the
- // writeScheduler (below) has decided to select this frame
- // to write. The write functions are all defined in write.go.
+ // WriteScheduler has selected this frame to write. The write
+ // functions are all defined in write.go.
write http2writeFramer
- stream *http2stream // used for prioritization. nil for non-stream frames.
+ // stream is the stream on which this frame will be written.
+ // nil for non-stream frames like PING and SETTINGS.
+ stream *http2stream
// done, if non-nil, must be a buffered channel with space for
// 1 message and is sent the return value from write (or an
@@ -6981,247 +7781,644 @@ type http2frameWriteMsg struct {
done chan error
}
-// for debugging only:
-func (wm http2frameWriteMsg) String() string {
- var streamID uint32
- if wm.stream != nil {
- streamID = wm.stream.id
+// StreamID returns the id of the stream this frame will be written to.
+// 0 is used for non-stream frames such as PING and SETTINGS.
+func (wr http2FrameWriteRequest) StreamID() uint32 {
+ if wr.stream == nil {
+ if se, ok := wr.write.(http2StreamError); ok {
+
+ return se.StreamID
+ }
+ return 0
+ }
+ return wr.stream.id
+}
+
+// DataSize returns the number of flow control bytes that must be consumed
+// to write this entire frame. This is 0 for non-DATA frames.
+func (wr http2FrameWriteRequest) DataSize() int {
+ if wd, ok := wr.write.(*http2writeData); ok {
+ return len(wd.p)
+ }
+ return 0
+}
+
+// Consume consumes min(n, available) bytes from this frame, where available
+// is the number of flow control bytes available on the stream. Consume returns
+// 0, 1, or 2 frames, where the integer return value gives the number of frames
+// returned.
+//
+// If flow control prevents consuming any bytes, this returns (_, _, 0). If
+// the entire frame was consumed, this returns (wr, _, 1). Otherwise, this
+// returns (consumed, rest, 2), where 'consumed' contains the consumed bytes and
+// 'rest' contains the remaining bytes. The consumed bytes are deducted from the
+// underlying stream's flow control budget.
+func (wr http2FrameWriteRequest) Consume(n int32) (http2FrameWriteRequest, http2FrameWriteRequest, int) {
+ var empty http2FrameWriteRequest
+
+ wd, ok := wr.write.(*http2writeData)
+ if !ok || len(wd.p) == 0 {
+ return wr, empty, 1
+ }
+
+ allowed := wr.stream.flow.available()
+ if n < allowed {
+ allowed = n
+ }
+ if wr.stream.sc.maxFrameSize < allowed {
+ allowed = wr.stream.sc.maxFrameSize
+ }
+ if allowed <= 0 {
+ return empty, empty, 0
+ }
+ if len(wd.p) > int(allowed) {
+ wr.stream.flow.take(allowed)
+ consumed := http2FrameWriteRequest{
+ stream: wr.stream,
+ write: &http2writeData{
+ streamID: wd.streamID,
+ p: wd.p[:allowed],
+
+ endStream: false,
+ },
+
+ done: nil,
+ }
+ rest := http2FrameWriteRequest{
+ stream: wr.stream,
+ write: &http2writeData{
+ streamID: wd.streamID,
+ p: wd.p[allowed:],
+ endStream: wd.endStream,
+ },
+ done: wr.done,
+ }
+ return consumed, rest, 2
}
+
+ wr.stream.flow.take(int32(len(wd.p)))
+ return wr, empty, 1
+}
+
+// String is for debugging only.
+func (wr http2FrameWriteRequest) String() string {
var des string
- if s, ok := wm.write.(fmt.Stringer); ok {
+ if s, ok := wr.write.(fmt.Stringer); ok {
des = s.String()
} else {
- des = fmt.Sprintf("%T", wm.write)
+ des = fmt.Sprintf("%T", wr.write)
}
- return fmt.Sprintf("[frameWriteMsg stream=%d, ch=%v, type: %v]", streamID, wm.done != nil, des)
+ return fmt.Sprintf("[FrameWriteRequest stream=%d, ch=%v, writer=%v]", wr.StreamID(), wr.done != nil, des)
}
-// writeScheduler tracks pending frames to write, priorities, and decides
-// the next one to use. It is not thread-safe.
-type http2writeScheduler struct {
- // zero are frames not associated with a specific stream.
- // They're sent before any stream-specific freams.
- zero http2writeQueue
+// replyToWriter sends err to wr.done and panics if the send must block
+// This does nothing if wr.done is nil.
+func (wr *http2FrameWriteRequest) replyToWriter(err error) {
+ if wr.done == nil {
+ return
+ }
+ select {
+ case wr.done <- err:
+ default:
+ panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wr.write))
+ }
+ wr.write = nil
+}
- // maxFrameSize is the maximum size of a DATA frame
- // we'll write. Must be non-zero and between 16K-16M.
- maxFrameSize uint32
+// writeQueue is used by implementations of WriteScheduler.
+type http2writeQueue struct {
+ s []http2FrameWriteRequest
+}
- // sq contains the stream-specific queues, keyed by stream ID.
- // when a stream is idle, it's deleted from the map.
- sq map[uint32]*http2writeQueue
+func (q *http2writeQueue) empty() bool { return len(q.s) == 0 }
- // canSend is a slice of memory that's reused between frame
- // scheduling decisions to hold the list of writeQueues (from sq)
- // which have enough flow control data to send. After canSend is
- // built, the best is selected.
- canSend []*http2writeQueue
+func (q *http2writeQueue) push(wr http2FrameWriteRequest) {
+ q.s = append(q.s, wr)
+}
- // pool of empty queues for reuse.
- queuePool []*http2writeQueue
+func (q *http2writeQueue) shift() http2FrameWriteRequest {
+ if len(q.s) == 0 {
+ panic("invalid use of queue")
+ }
+ wr := q.s[0]
+
+ copy(q.s, q.s[1:])
+ q.s[len(q.s)-1] = http2FrameWriteRequest{}
+ q.s = q.s[:len(q.s)-1]
+ return wr
}
-func (ws *http2writeScheduler) putEmptyQueue(q *http2writeQueue) {
- if len(q.s) != 0 {
- panic("queue must be empty")
+// consume consumes up to n bytes from q.s[0]. If the frame is
+// entirely consumed, it is removed from the queue. If the frame
+// is partially consumed, the frame is kept with the consumed
+// bytes removed. Returns true iff any bytes were consumed.
+func (q *http2writeQueue) consume(n int32) (http2FrameWriteRequest, bool) {
+ if len(q.s) == 0 {
+ return http2FrameWriteRequest{}, false
}
- ws.queuePool = append(ws.queuePool, q)
+ consumed, rest, numresult := q.s[0].Consume(n)
+ switch numresult {
+ case 0:
+ return http2FrameWriteRequest{}, false
+ case 1:
+ q.shift()
+ case 2:
+ q.s[0] = rest
+ }
+ return consumed, true
}
-func (ws *http2writeScheduler) getEmptyQueue() *http2writeQueue {
- ln := len(ws.queuePool)
+type http2writeQueuePool []*http2writeQueue
+
+// put inserts an unused writeQueue into the pool.
+func (p *http2writeQueuePool) put(q *http2writeQueue) {
+ for i := range q.s {
+ q.s[i] = http2FrameWriteRequest{}
+ }
+ q.s = q.s[:0]
+ *p = append(*p, q)
+}
+
+// get returns an empty writeQueue.
+func (p *http2writeQueuePool) get() *http2writeQueue {
+ ln := len(*p)
if ln == 0 {
return new(http2writeQueue)
}
- q := ws.queuePool[ln-1]
- ws.queuePool = ws.queuePool[:ln-1]
+ x := ln - 1
+ q := (*p)[x]
+ (*p)[x] = nil
+ *p = (*p)[:x]
return q
}
-func (ws *http2writeScheduler) empty() bool { return ws.zero.empty() && len(ws.sq) == 0 }
+// RFC 7540, Section 5.3.5: the default weight is 16.
+const http2priorityDefaultWeight = 15 // 16 = 15 + 1
-func (ws *http2writeScheduler) add(wm http2frameWriteMsg) {
- st := wm.stream
- if st == nil {
- ws.zero.push(wm)
+// PriorityWriteSchedulerConfig configures a priorityWriteScheduler.
+type http2PriorityWriteSchedulerConfig struct {
+ // MaxClosedNodesInTree controls the maximum number of closed streams to
+ // retain in the priority tree. Setting this to zero saves a small amount
+ // of memory at the cost of performance.
+ //
+ // See RFC 7540, Section 5.3.4:
+ // "It is possible for a stream to become closed while prioritization
+ // information ... is in transit. ... This potentially creates suboptimal
+ // prioritization, since the stream could be given a priority that is
+ // different from what is intended. To avoid these problems, an endpoint
+ // SHOULD retain stream prioritization state for a period after streams
+ // become closed. The longer state is retained, the lower the chance that
+ // streams are assigned incorrect or default priority values."
+ MaxClosedNodesInTree int
+
+ // MaxIdleNodesInTree controls the maximum number of idle streams to
+ // retain in the priority tree. Setting this to zero saves a small amount
+ // of memory at the cost of performance.
+ //
+ // See RFC 7540, Section 5.3.4:
+ // Similarly, streams that are in the "idle" state can be assigned
+ // priority or become a parent of other streams. This allows for the
+ // creation of a grouping node in the dependency tree, which enables
+ // more flexible expressions of priority. Idle streams begin with a
+ // default priority (Section 5.3.5).
+ MaxIdleNodesInTree int
+
+ // ThrottleOutOfOrderWrites enables write throttling to help ensure that
+ // data is delivered in priority order. This works around a race where
+ // stream B depends on stream A and both streams are about to call Write
+ // to queue DATA frames. If B wins the race, a naive scheduler would eagerly
+ // write as much data from B as possible, but this is suboptimal because A
+ // is a higher-priority stream. With throttling enabled, we write a small
+ // amount of data from B to minimize the amount of bandwidth that B can
+ // steal from A.
+ ThrottleOutOfOrderWrites bool
+}
+
+// NewPriorityWriteScheduler constructs a WriteScheduler that schedules
+// frames by following HTTP/2 priorities as described in RFC 7340 Section 5.3.
+// If cfg is nil, default options are used.
+func http2NewPriorityWriteScheduler(cfg *http2PriorityWriteSchedulerConfig) http2WriteScheduler {
+ if cfg == nil {
+
+ cfg = &http2PriorityWriteSchedulerConfig{
+ MaxClosedNodesInTree: 10,
+ MaxIdleNodesInTree: 10,
+ ThrottleOutOfOrderWrites: false,
+ }
+ }
+
+ ws := &http2priorityWriteScheduler{
+ nodes: make(map[uint32]*http2priorityNode),
+ maxClosedNodesInTree: cfg.MaxClosedNodesInTree,
+ maxIdleNodesInTree: cfg.MaxIdleNodesInTree,
+ enableWriteThrottle: cfg.ThrottleOutOfOrderWrites,
+ }
+ ws.nodes[0] = &ws.root
+ if cfg.ThrottleOutOfOrderWrites {
+ ws.writeThrottleLimit = 1024
} else {
- ws.streamQueue(st.id).push(wm)
+ ws.writeThrottleLimit = math.MaxInt32
}
+ return ws
+}
+
+type http2priorityNodeState int
+
+const (
+ http2priorityNodeOpen http2priorityNodeState = iota
+ http2priorityNodeClosed
+ http2priorityNodeIdle
+)
+
+// priorityNode is a node in an HTTP/2 priority tree.
+// Each node is associated with a single stream ID.
+// See RFC 7540, Section 5.3.
+type http2priorityNode struct {
+ q http2writeQueue // queue of pending frames to write
+ id uint32 // id of the stream, or 0 for the root of the tree
+ weight uint8 // the actual weight is weight+1, so the value is in [1,256]
+ state http2priorityNodeState // open | closed | idle
+ bytes int64 // number of bytes written by this node, or 0 if closed
+ subtreeBytes int64 // sum(node.bytes) of all nodes in this subtree
+
+ // These links form the priority tree.
+ parent *http2priorityNode
+ kids *http2priorityNode // start of the kids list
+ prev, next *http2priorityNode // doubly-linked list of siblings
}
-func (ws *http2writeScheduler) streamQueue(streamID uint32) *http2writeQueue {
- if q, ok := ws.sq[streamID]; ok {
- return q
+func (n *http2priorityNode) setParent(parent *http2priorityNode) {
+ if n == parent {
+ panic("setParent to self")
}
- if ws.sq == nil {
- ws.sq = make(map[uint32]*http2writeQueue)
+ if n.parent == parent {
+ return
+ }
+
+ if parent := n.parent; parent != nil {
+ if n.prev == nil {
+ parent.kids = n.next
+ } else {
+ n.prev.next = n.next
+ }
+ if n.next != nil {
+ n.next.prev = n.prev
+ }
+ }
+
+ n.parent = parent
+ if parent == nil {
+ n.next = nil
+ n.prev = nil
+ } else {
+ n.next = parent.kids
+ n.prev = nil
+ if n.next != nil {
+ n.next.prev = n
+ }
+ parent.kids = n
}
- q := ws.getEmptyQueue()
- ws.sq[streamID] = q
- return q
}
-// take returns the most important frame to write and removes it from the scheduler.
-// It is illegal to call this if the scheduler is empty or if there are no connection-level
-// flow control bytes available.
-func (ws *http2writeScheduler) take() (wm http2frameWriteMsg, ok bool) {
- if ws.maxFrameSize == 0 {
- panic("internal error: ws.maxFrameSize not initialized or invalid")
+func (n *http2priorityNode) addBytes(b int64) {
+ n.bytes += b
+ for ; n != nil; n = n.parent {
+ n.subtreeBytes += b
}
+}
- if !ws.zero.empty() {
- return ws.zero.shift(), true
+// walkReadyInOrder iterates over the tree in priority order, calling f for each node
+// with a non-empty write queue. When f returns true, this funcion returns true and the
+// walk halts. tmp is used as scratch space for sorting.
+//
+// f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true
+// if any ancestor p of n is still open (ignoring the root node).
+func (n *http2priorityNode) walkReadyInOrder(openParent bool, tmp *[]*http2priorityNode, f func(*http2priorityNode, bool) bool) bool {
+ if !n.q.empty() && f(n, openParent) {
+ return true
}
- if len(ws.sq) == 0 {
- return
+ if n.kids == nil {
+ return false
+ }
+
+ if n.id != 0 {
+ openParent = openParent || (n.state == http2priorityNodeOpen)
}
- for id, q := range ws.sq {
- if q.firstIsNoCost() {
- return ws.takeFrom(id, q)
+ w := n.kids.weight
+ needSort := false
+ for k := n.kids.next; k != nil; k = k.next {
+ if k.weight != w {
+ needSort = true
+ break
}
}
+ if !needSort {
+ for k := n.kids; k != nil; k = k.next {
+ if k.walkReadyInOrder(openParent, tmp, f) {
+ return true
+ }
+ }
+ return false
+ }
- if len(ws.canSend) != 0 {
- panic("should be empty")
+ *tmp = (*tmp)[:0]
+ for n.kids != nil {
+ *tmp = append(*tmp, n.kids)
+ n.kids.setParent(nil)
}
- for _, q := range ws.sq {
- if n := ws.streamWritableBytes(q); n > 0 {
- ws.canSend = append(ws.canSend, q)
+ sort.Sort(http2sortPriorityNodeSiblings(*tmp))
+ for i := len(*tmp) - 1; i >= 0; i-- {
+ (*tmp)[i].setParent(n)
+ }
+ for k := n.kids; k != nil; k = k.next {
+ if k.walkReadyInOrder(openParent, tmp, f) {
+ return true
}
}
- if len(ws.canSend) == 0 {
- return
+ return false
+}
+
+type http2sortPriorityNodeSiblings []*http2priorityNode
+
+func (z http2sortPriorityNodeSiblings) Len() int { return len(z) }
+
+func (z http2sortPriorityNodeSiblings) Swap(i, k int) { z[i], z[k] = z[k], z[i] }
+
+func (z http2sortPriorityNodeSiblings) Less(i, k int) bool {
+
+ wi, bi := float64(z[i].weight+1), float64(z[i].subtreeBytes)
+ wk, bk := float64(z[k].weight+1), float64(z[k].subtreeBytes)
+ if bi == 0 && bk == 0 {
+ return wi >= wk
}
- defer ws.zeroCanSend()
+ if bk == 0 {
+ return false
+ }
+ return bi/bk <= wi/wk
+}
- q := ws.canSend[0]
+type http2priorityWriteScheduler struct {
+ // root is the root of the priority tree, where root.id = 0.
+ // The root queues control frames that are not associated with any stream.
+ root http2priorityNode
- return ws.takeFrom(q.streamID(), q)
+ // nodes maps stream ids to priority tree nodes.
+ nodes map[uint32]*http2priorityNode
+
+ // maxID is the maximum stream id in nodes.
+ maxID uint32
+
+ // lists of nodes that have been closed or are idle, but are kept in
+ // the tree for improved prioritization. When the lengths exceed either
+ // maxClosedNodesInTree or maxIdleNodesInTree, old nodes are discarded.
+ closedNodes, idleNodes []*http2priorityNode
+
+ // From the config.
+ maxClosedNodesInTree int
+ maxIdleNodesInTree int
+ writeThrottleLimit int32
+ enableWriteThrottle bool
+
+ // tmp is scratch space for priorityNode.walkReadyInOrder to reduce allocations.
+ tmp []*http2priorityNode
+
+ // pool of empty queues for reuse.
+ queuePool http2writeQueuePool
}
-// zeroCanSend is defered from take.
-func (ws *http2writeScheduler) zeroCanSend() {
- for i := range ws.canSend {
- ws.canSend[i] = nil
+func (ws *http2priorityWriteScheduler) OpenStream(streamID uint32, options http2OpenStreamOptions) {
+
+ if curr := ws.nodes[streamID]; curr != nil {
+ if curr.state != http2priorityNodeIdle {
+ panic(fmt.Sprintf("stream %d already opened", streamID))
+ }
+ curr.state = http2priorityNodeOpen
+ return
+ }
+
+ parent := ws.nodes[options.PusherID]
+ if parent == nil {
+ parent = &ws.root
+ }
+ n := &http2priorityNode{
+ q: *ws.queuePool.get(),
+ id: streamID,
+ weight: http2priorityDefaultWeight,
+ state: http2priorityNodeOpen,
+ }
+ n.setParent(parent)
+ ws.nodes[streamID] = n
+ if streamID > ws.maxID {
+ ws.maxID = streamID
}
- ws.canSend = ws.canSend[:0]
}
-// streamWritableBytes returns the number of DATA bytes we could write
-// from the given queue's stream, if this stream/queue were
-// selected. It is an error to call this if q's head isn't a
-// *writeData.
-func (ws *http2writeScheduler) streamWritableBytes(q *http2writeQueue) int32 {
- wm := q.head()
- ret := wm.stream.flow.available()
- if ret == 0 {
- return 0
+func (ws *http2priorityWriteScheduler) CloseStream(streamID uint32) {
+ if streamID == 0 {
+ panic("violation of WriteScheduler interface: cannot close stream 0")
}
- if int32(ws.maxFrameSize) < ret {
- ret = int32(ws.maxFrameSize)
+ if ws.nodes[streamID] == nil {
+ panic(fmt.Sprintf("violation of WriteScheduler interface: unknown stream %d", streamID))
}
- if ret == 0 {
- panic("internal error: ws.maxFrameSize not initialized or invalid")
+ if ws.nodes[streamID].state != http2priorityNodeOpen {
+ panic(fmt.Sprintf("violation of WriteScheduler interface: stream %d already closed", streamID))
}
- wd := wm.write.(*http2writeData)
- if len(wd.p) < int(ret) {
- ret = int32(len(wd.p))
+
+ n := ws.nodes[streamID]
+ n.state = http2priorityNodeClosed
+ n.addBytes(-n.bytes)
+
+ q := n.q
+ ws.queuePool.put(&q)
+ n.q.s = nil
+ if ws.maxClosedNodesInTree > 0 {
+ ws.addClosedOrIdleNode(&ws.closedNodes, ws.maxClosedNodesInTree, n)
+ } else {
+ ws.removeNode(n)
}
- return ret
}
-func (ws *http2writeScheduler) takeFrom(id uint32, q *http2writeQueue) (wm http2frameWriteMsg, ok bool) {
- wm = q.head()
-
- if wd, ok := wm.write.(*http2writeData); ok && len(wd.p) > 0 {
- allowed := wm.stream.flow.available()
- if allowed == 0 {
+func (ws *http2priorityWriteScheduler) AdjustStream(streamID uint32, priority http2PriorityParam) {
+ if streamID == 0 {
+ panic("adjustPriority on root")
+ }
- return http2frameWriteMsg{}, false
+ n := ws.nodes[streamID]
+ if n == nil {
+ if streamID <= ws.maxID || ws.maxIdleNodesInTree == 0 {
+ return
}
- if int32(ws.maxFrameSize) < allowed {
- allowed = int32(ws.maxFrameSize)
+ ws.maxID = streamID
+ n = &http2priorityNode{
+ q: *ws.queuePool.get(),
+ id: streamID,
+ weight: http2priorityDefaultWeight,
+ state: http2priorityNodeIdle,
}
+ n.setParent(&ws.root)
+ ws.nodes[streamID] = n
+ ws.addClosedOrIdleNode(&ws.idleNodes, ws.maxIdleNodesInTree, n)
+ }
- if len(wd.p) > int(allowed) {
- wm.stream.flow.take(allowed)
- chunk := wd.p[:allowed]
- wd.p = wd.p[allowed:]
+ parent := ws.nodes[priority.StreamDep]
+ if parent == nil {
+ n.setParent(&ws.root)
+ n.weight = http2priorityDefaultWeight
+ return
+ }
- return http2frameWriteMsg{
- stream: wm.stream,
- write: &http2writeData{
- streamID: wd.streamID,
- p: chunk,
+ if n == parent {
+ return
+ }
- endStream: false,
- },
+ for x := parent.parent; x != nil; x = x.parent {
+ if x == n {
+ parent.setParent(n.parent)
+ break
+ }
+ }
- done: nil,
- }, true
+ if priority.Exclusive {
+ k := parent.kids
+ for k != nil {
+ next := k.next
+ if k != n {
+ k.setParent(n)
+ }
+ k = next
}
- wm.stream.flow.take(int32(len(wd.p)))
}
- q.shift()
- if q.empty() {
- ws.putEmptyQueue(q)
- delete(ws.sq, id)
+ n.setParent(parent)
+ n.weight = priority.Weight
+}
+
+func (ws *http2priorityWriteScheduler) Push(wr http2FrameWriteRequest) {
+ var n *http2priorityNode
+ if id := wr.StreamID(); id == 0 {
+ n = &ws.root
+ } else {
+ n = ws.nodes[id]
+ if n == nil {
+
+ if wr.DataSize() > 0 {
+ panic("add DATA on non-open stream")
+ }
+ n = &ws.root
+ }
}
- return wm, true
+ n.q.push(wr)
}
-func (ws *http2writeScheduler) forgetStream(id uint32) {
- q, ok := ws.sq[id]
- if !ok {
+func (ws *http2priorityWriteScheduler) Pop() (wr http2FrameWriteRequest, ok bool) {
+ ws.root.walkReadyInOrder(false, &ws.tmp, func(n *http2priorityNode, openParent bool) bool {
+ limit := int32(math.MaxInt32)
+ if openParent {
+ limit = ws.writeThrottleLimit
+ }
+ wr, ok = n.q.consume(limit)
+ if !ok {
+ return false
+ }
+ n.addBytes(int64(wr.DataSize()))
+
+ if openParent {
+ ws.writeThrottleLimit += 1024
+ if ws.writeThrottleLimit < 0 {
+ ws.writeThrottleLimit = math.MaxInt32
+ }
+ } else if ws.enableWriteThrottle {
+ ws.writeThrottleLimit = 1024
+ }
+ return true
+ })
+ return wr, ok
+}
+
+func (ws *http2priorityWriteScheduler) addClosedOrIdleNode(list *[]*http2priorityNode, maxSize int, n *http2priorityNode) {
+ if maxSize == 0 {
return
}
- delete(ws.sq, id)
+ if len(*list) == maxSize {
- for i := range q.s {
- q.s[i] = http2frameWriteMsg{}
+ ws.removeNode((*list)[0])
+ x := (*list)[1:]
+ copy(*list, x)
+ *list = (*list)[:len(x)]
}
- q.s = q.s[:0]
- ws.putEmptyQueue(q)
+ *list = append(*list, n)
}
-type http2writeQueue struct {
- s []http2frameWriteMsg
+func (ws *http2priorityWriteScheduler) removeNode(n *http2priorityNode) {
+ for k := n.kids; k != nil; k = k.next {
+ k.setParent(n.parent)
+ }
+ n.setParent(nil)
+ delete(ws.nodes, n.id)
}
-// streamID returns the stream ID for a non-empty stream-specific queue.
-func (q *http2writeQueue) streamID() uint32 { return q.s[0].stream.id }
+// NewRandomWriteScheduler constructs a WriteScheduler that ignores HTTP/2
+// priorities. Control frames like SETTINGS and PING are written before DATA
+// frames, but if no control frames are queued and multiple streams have queued
+// HEADERS or DATA frames, Pop selects a ready stream arbitrarily.
+func http2NewRandomWriteScheduler() http2WriteScheduler {
+ return &http2randomWriteScheduler{sq: make(map[uint32]*http2writeQueue)}
+}
-func (q *http2writeQueue) empty() bool { return len(q.s) == 0 }
+type http2randomWriteScheduler struct {
+ // zero are frames not associated with a specific stream.
+ zero http2writeQueue
+
+ // sq contains the stream-specific queues, keyed by stream ID.
+ // When a stream is idle or closed, it's deleted from the map.
+ sq map[uint32]*http2writeQueue
-func (q *http2writeQueue) push(wm http2frameWriteMsg) {
- q.s = append(q.s, wm)
+ // pool of empty queues for reuse.
+ queuePool http2writeQueuePool
}
-// head returns the next item that would be removed by shift.
-func (q *http2writeQueue) head() http2frameWriteMsg {
- if len(q.s) == 0 {
- panic("invalid use of queue")
- }
- return q.s[0]
+func (ws *http2randomWriteScheduler) OpenStream(streamID uint32, options http2OpenStreamOptions) {
+
}
-func (q *http2writeQueue) shift() http2frameWriteMsg {
- if len(q.s) == 0 {
- panic("invalid use of queue")
+func (ws *http2randomWriteScheduler) CloseStream(streamID uint32) {
+ q, ok := ws.sq[streamID]
+ if !ok {
+ return
}
- wm := q.s[0]
+ delete(ws.sq, streamID)
+ ws.queuePool.put(q)
+}
+
+func (ws *http2randomWriteScheduler) AdjustStream(streamID uint32, priority http2PriorityParam) {
- copy(q.s, q.s[1:])
- q.s[len(q.s)-1] = http2frameWriteMsg{}
- q.s = q.s[:len(q.s)-1]
- return wm
}
-func (q *http2writeQueue) firstIsNoCost() bool {
- if df, ok := q.s[0].write.(*http2writeData); ok {
- return len(df.p) == 0
+func (ws *http2randomWriteScheduler) Push(wr http2FrameWriteRequest) {
+ id := wr.StreamID()
+ if id == 0 {
+ ws.zero.push(wr)
+ return
}
- return true
+ q, ok := ws.sq[id]
+ if !ok {
+ q = ws.queuePool.get()
+ ws.sq[id] = q
+ }
+ q.push(wr)
+}
+
+func (ws *http2randomWriteScheduler) Pop() (http2FrameWriteRequest, bool) {
+
+ if !ws.zero.empty() {
+ return ws.zero.shift(), true
+ }
+
+ for _, q := range ws.sq {
+ if wr, ok := q.consume(math.MaxInt32); ok {
+ return wr, true
+ }
+ }
+ return http2FrameWriteRequest{}, false
}
diff --git a/libgo/go/net/http/header.go b/libgo/go/net/http/header.go
index 6343165a840..832169247fe 100644
--- a/libgo/go/net/http/header.go
+++ b/libgo/go/net/http/header.go
@@ -32,9 +32,11 @@ func (h Header) Set(key, value string) {
}
// Get gets the first value associated with the given key.
+// It is case insensitive; textproto.CanonicalMIMEHeaderKey is used
+// to canonicalize the provided key.
// If there are no values associated with the key, Get returns "".
-// To access multiple values of a key, access the map directly
-// with CanonicalHeaderKey.
+// To access multiple values of a key, or to use non-canonical keys,
+// access the map directly.
func (h Header) Get(key string) string {
return textproto.MIMEHeader(h).Get(key)
}
diff --git a/libgo/go/net/http/http.go b/libgo/go/net/http/http.go
index b34ae41ec51..826f7ff3da5 100644
--- a/libgo/go/net/http/http.go
+++ b/libgo/go/net/http/http.go
@@ -5,7 +5,11 @@
package http
import (
+ "io"
+ "strconv"
"strings"
+ "time"
+ "unicode/utf8"
"golang_org/x/net/lex/httplex"
)
@@ -14,6 +18,10 @@ import (
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1
+// aLongTimeAgo is a non-zero time, far in the past, used for
+// immediate cancelation of network operations.
+var aLongTimeAgo = time.Unix(233431200, 0)
+
// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.
@@ -41,3 +49,93 @@ func removeEmptyPort(host string) string {
func isNotToken(r rune) bool {
return !httplex.IsTokenRune(r)
}
+
+func isASCII(s string) bool {
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ return false
+ }
+ }
+ return true
+}
+
+func hexEscapeNonASCII(s string) string {
+ newLen := 0
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ newLen += 3
+ } else {
+ newLen++
+ }
+ }
+ if newLen == len(s) {
+ return s
+ }
+ b := make([]byte, 0, newLen)
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ b = append(b, '%')
+ b = strconv.AppendInt(b, int64(s[i]), 16)
+ } else {
+ b = append(b, s[i])
+ }
+ }
+ return string(b)
+}
+
+// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
+// and Close always returns nil. It can be used in an outgoing client
+// request to explicitly signal that a request has zero bytes.
+// An alternative, however, is to simply set Request.Body to nil.
+var NoBody = noBody{}
+
+type noBody struct{}
+
+func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
+func (noBody) Close() error { return nil }
+func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
+
+var (
+ // verify that an io.Copy from NoBody won't require a buffer:
+ _ io.WriterTo = NoBody
+ _ io.ReadCloser = NoBody
+)
+
+// PushOptions describes options for Pusher.Push.
+type PushOptions struct {
+ // Method specifies the HTTP method for the promised request.
+ // If set, it must be "GET" or "HEAD". Empty means "GET".
+ Method string
+
+ // Header specifies additional promised request headers. This cannot
+ // include HTTP/2 pseudo header fields like ":path" and ":scheme",
+ // which will be added automatically.
+ Header Header
+}
+
+// Pusher is the interface implemented by ResponseWriters that support
+// HTTP/2 server push. For more background, see
+// https://tools.ietf.org/html/rfc7540#section-8.2.
+type Pusher interface {
+ // Push initiates an HTTP/2 server push. This constructs a synthetic
+ // request using the given target and options, serializes that request
+ // into a PUSH_PROMISE frame, then dispatches that request using the
+ // server's request handler. If opts is nil, default options are used.
+ //
+ // The target must either be an absolute path (like "/path") or an absolute
+ // URL that contains a valid host and the same scheme as the parent request.
+ // If the target is a path, it will inherit the scheme and host of the
+ // parent request.
+ //
+ // The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
+ // Push may or may not detect these invalid pushes; however, invalid
+ // pushes will be detected and canceled by conforming clients.
+ //
+ // Handlers that wish to push URL X should call Push before sending any
+ // data that may trigger a request for URL X. This avoids a race where the
+ // client issues requests for X before receiving the PUSH_PROMISE for X.
+ //
+ // Push returns ErrNotSupported if the client has disabled push or if push
+ // is not supported on the underlying connection.
+ Push(target string, opts *PushOptions) error
+}
diff --git a/libgo/go/net/http/http_test.go b/libgo/go/net/http/http_test.go
index 34da4bbb59e..8f466bb3668 100644
--- a/libgo/go/net/http/http_test.go
+++ b/libgo/go/net/http/http_test.go
@@ -12,8 +12,13 @@ import (
"os/exec"
"reflect"
"testing"
+ "time"
)
+func init() {
+ shutdownPollInterval = 5 * time.Millisecond
+}
+
func TestForeachHeaderElement(t *testing.T) {
tests := []struct {
in string
@@ -51,6 +56,18 @@ func TestCleanHost(t *testing.T) {
{"www.google.com foo", "www.google.com"},
{"www.google.com/foo", "www.google.com"},
{" first character is a space", ""},
+ {"[1::6]:8080", "[1::6]:8080"},
+
+ // Punycode:
+ {"гофер.рф/foo", "xn--c1ae0ajs.xn--p1ai"},
+ {"bücher.de", "xn--bcher-kva.de"},
+ {"bücher.de:8080", "xn--bcher-kva.de:8080"},
+ // Verify we convert to lowercase before punycode:
+ {"BÜCHER.de", "xn--bcher-kva.de"},
+ {"BÜCHER.de:8080", "xn--bcher-kva.de:8080"},
+ // Verify we normalize to NFC before punycode:
+ {"gophér.nfc", "xn--gophr-esa.nfc"}, // NFC input; no work needed
+ {"goph\u0065\u0301r.nfd", "xn--gophr-esa.nfd"}, // NFD input
}
for _, tt := range tests {
got := cleanHost(tt.in)
@@ -65,8 +82,9 @@ func TestCleanHost(t *testing.T) {
// This catches accidental dependencies between the HTTP transport and
// server code.
func TestCmdGoNoHTTPServer(t *testing.T) {
+ t.Parallel()
goBin := testenv.GoToolPath(t)
- out, err := exec.Command("go", "tool", "nm", goBin).CombinedOutput()
+ out, err := exec.Command(goBin, "tool", "nm", goBin).CombinedOutput()
if err != nil {
t.Fatalf("go tool nm: %v: %s", err, out)
}
diff --git a/libgo/go/net/http/httptest/httptest.go b/libgo/go/net/http/httptest/httptest.go
index e2148a659c1..f7202da92ff 100644
--- a/libgo/go/net/http/httptest/httptest.go
+++ b/libgo/go/net/http/httptest/httptest.go
@@ -35,6 +35,9 @@ import (
//
// NewRequest panics on error for ease of use in testing, where a
// panic is acceptable.
+//
+// To generate a client HTTP request instead of a server request, see
+// the NewRequest function in the net/http package.
func NewRequest(method, target string, body io.Reader) *http.Request {
if method == "" {
method = "GET"
diff --git a/libgo/go/net/http/httptest/recorder.go b/libgo/go/net/http/httptest/recorder.go
index 0ad26a3d418..5f1aa6af479 100644
--- a/libgo/go/net/http/httptest/recorder.go
+++ b/libgo/go/net/http/httptest/recorder.go
@@ -8,15 +8,33 @@ import (
"bytes"
"io/ioutil"
"net/http"
+ "strconv"
+ "strings"
)
// ResponseRecorder is an implementation of http.ResponseWriter that
// records its mutations for later inspection in tests.
type ResponseRecorder struct {
- Code int // the HTTP response code from WriteHeader
- HeaderMap http.Header // the HTTP response headers
- Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to
- Flushed bool
+ // Code is the HTTP response code set by WriteHeader.
+ //
+ // Note that if a Handler never calls WriteHeader or Write,
+ // this might end up being 0, rather than the implicit
+ // http.StatusOK. To get the implicit value, use the Result
+ // method.
+ Code int
+
+ // HeaderMap contains the headers explicitly set by the Handler.
+ //
+ // To get the implicit headers set by the server (such as
+ // automatic Content-Type), use the Result method.
+ HeaderMap http.Header
+
+ // Body is the buffer to which the Handler's Write calls are sent.
+ // If nil, the Writes are silently discarded.
+ Body *bytes.Buffer
+
+ // Flushed is whether the Handler called Flush.
+ Flushed bool
result *http.Response // cache of Result's return value
snapHeader http.Header // snapshot of HeaderMap at first Write
@@ -136,6 +154,9 @@ func (rw *ResponseRecorder) Flush() {
// first write call, or at the time of this call, if the handler never
// did a write.
//
+// The Response.Body is guaranteed to be non-nil and Body.Read call is
+// guaranteed to not return any error other than io.EOF.
+//
// Result must only be called after the handler has finished running.
func (rw *ResponseRecorder) Result() *http.Response {
if rw.result != nil {
@@ -159,6 +180,7 @@ func (rw *ResponseRecorder) Result() *http.Response {
if rw.Body != nil {
res.Body = ioutil.NopCloser(bytes.NewReader(rw.Body.Bytes()))
}
+ res.ContentLength = parseContentLength(res.Header.Get("Content-Length"))
if trailers, ok := rw.snapHeader["Trailer"]; ok {
res.Trailer = make(http.Header, len(trailers))
@@ -181,5 +203,33 @@ func (rw *ResponseRecorder) Result() *http.Response {
res.Trailer[k] = vv2
}
}
+ for k, vv := range rw.HeaderMap {
+ if !strings.HasPrefix(k, http.TrailerPrefix) {
+ continue
+ }
+ if res.Trailer == nil {
+ res.Trailer = make(http.Header)
+ }
+ for _, v := range vv {
+ res.Trailer.Add(strings.TrimPrefix(k, http.TrailerPrefix), v)
+ }
+ }
return res
}
+
+// parseContentLength trims whitespace from s and returns -1 if no value
+// is set, or the value if it's >= 0.
+//
+// This a modified version of same function found in net/http/transfer.go. This
+// one just ignores an invalid header.
+func parseContentLength(cl string) int64 {
+ cl = strings.TrimSpace(cl)
+ if cl == "" {
+ return -1
+ }
+ n, err := strconv.ParseInt(cl, 10, 64)
+ if err != nil {
+ return -1
+ }
+ return n
+}
diff --git a/libgo/go/net/http/httptest/recorder_test.go b/libgo/go/net/http/httptest/recorder_test.go
index d4e7137913e..9afba4e556a 100644
--- a/libgo/go/net/http/httptest/recorder_test.go
+++ b/libgo/go/net/http/httptest/recorder_test.go
@@ -94,6 +94,14 @@ func TestRecorder(t *testing.T) {
return nil
}
}
+ hasContentLength := func(length int64) checkFunc {
+ return func(rec *ResponseRecorder) error {
+ if got := rec.Result().ContentLength; got != length {
+ return fmt.Errorf("ContentLength = %d; want %d", got, length)
+ }
+ return nil
+ }
+ }
tests := []struct {
name string
@@ -141,7 +149,7 @@ func TestRecorder(t *testing.T) {
w.(http.Flusher).Flush() // also sends a 200
w.WriteHeader(201)
},
- check(hasStatus(200), hasFlush(true)),
+ check(hasStatus(200), hasFlush(true), hasContentLength(-1)),
},
{
"Content-Type detection",
@@ -199,6 +207,7 @@ func TestRecorder(t *testing.T) {
w.Header().Set("Trailer-A", "valuea")
w.Header().Set("Trailer-C", "valuec")
w.Header().Set("Trailer-NotDeclared", "should be omitted")
+ w.Header().Set("Trailer:Trailer-D", "with prefix")
},
check(
hasStatus(200),
@@ -208,6 +217,7 @@ func TestRecorder(t *testing.T) {
hasTrailer("Trailer-A", "valuea"),
hasTrailer("Trailer-C", "valuec"),
hasNotTrailers("Non-Trailer", "Trailer-B", "Trailer-NotDeclared"),
+ hasTrailer("Trailer-D", "with prefix"),
),
},
{
@@ -244,6 +254,16 @@ func TestRecorder(t *testing.T) {
hasNotHeaders("X-Bar"),
),
},
+ {
+ "setting Content-Length header",
+ func(w http.ResponseWriter, r *http.Request) {
+ body := "Some body"
+ contentLength := fmt.Sprintf("%d", len(body))
+ w.Header().Set("Content-Length", contentLength)
+ io.WriteString(w, body)
+ },
+ check(hasStatus(200), hasContents("Some body"), hasContentLength(9)),
+ },
}
r, _ := http.NewRequest("GET", "http://foo.com/", nil)
for _, tt := range tests {
diff --git a/libgo/go/net/http/httptest/server.go b/libgo/go/net/http/httptest/server.go
index e27526a937a..5e9ace591f3 100644
--- a/libgo/go/net/http/httptest/server.go
+++ b/libgo/go/net/http/httptest/server.go
@@ -16,7 +16,6 @@ import (
"net/http"
"net/http/internal"
"os"
- "runtime"
"sync"
"time"
)
@@ -114,9 +113,10 @@ func (s *Server) StartTLS() {
}
existingConfig := s.TLS
- s.TLS = new(tls.Config)
if existingConfig != nil {
- *s.TLS = *existingConfig
+ s.TLS = existingConfig.Clone()
+ } else {
+ s.TLS = new(tls.Config)
}
if s.TLS.NextProtos == nil {
s.TLS.NextProtos = []string{"http/1.1"}
@@ -293,15 +293,6 @@ func (s *Server) closeConn(c net.Conn) { s.closeConnChan(c, nil) }
// closeConnChan is like closeConn, but takes an optional channel to receive a value
// when the goroutine closing c is done.
func (s *Server) closeConnChan(c net.Conn, done chan<- struct{}) {
- if runtime.GOOS == "plan9" {
- // Go's Plan 9 net package isn't great at unblocking reads when
- // their underlying TCP connections are closed. Don't trust
- // that that the ConnState state machine will get to
- // StateClosed. Instead, just go there directly. Plan 9 may leak
- // resources if the syscall doesn't end up returning. Oh well.
- s.forgetConn(c)
- }
-
c.Close()
if done != nil {
done <- struct{}{}
diff --git a/libgo/go/net/http/httptrace/example_test.go b/libgo/go/net/http/httptrace/example_test.go
new file mode 100644
index 00000000000..27cdcdec31b
--- /dev/null
+++ b/libgo/go/net/http/httptrace/example_test.go
@@ -0,0 +1,31 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package httptrace_test
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+ "net/http/httptrace"
+)
+
+func Example() {
+ req, _ := http.NewRequest("GET", "http://example.com", nil)
+ trace := &httptrace.ClientTrace{
+ GotConn: func(connInfo httptrace.GotConnInfo) {
+ fmt.Printf("Got Conn: %+v\n", connInfo)
+ },
+ DNSDone: func(dnsInfo httptrace.DNSDoneInfo) {
+ fmt.Printf("DNS Info: %+v\n", dnsInfo)
+ },
+ }
+ req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
+ _, err := http.DefaultTransport.RoundTrip(req)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
diff --git a/libgo/go/net/http/httptrace/trace.go b/libgo/go/net/http/httptrace/trace.go
index 6f187a7b694..ea7b38c8fc6 100644
--- a/libgo/go/net/http/httptrace/trace.go
+++ b/libgo/go/net/http/httptrace/trace.go
@@ -1,6 +1,6 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.h
+// license that can be found in the LICENSE file.
// Package httptrace provides mechanisms to trace the events within
// HTTP client requests.
@@ -8,6 +8,7 @@ package httptrace
import (
"context"
+ "crypto/tls"
"internal/nettrace"
"net"
"reflect"
@@ -65,11 +66,16 @@ func WithClientTrace(ctx context.Context, trace *ClientTrace) context.Context {
return ctx
}
-// ClientTrace is a set of hooks to run at various stages of an HTTP
-// client request. Any particular hook may be nil. Functions may be
-// called concurrently from different goroutines, starting after the
-// call to Transport.RoundTrip and ending either when RoundTrip
-// returns an error, or when the Response.Body is closed.
+// ClientTrace is a set of hooks to run at various stages of an outgoing
+// HTTP request. Any particular hook may be nil. Functions may be
+// called concurrently from different goroutines and some may be called
+// after the request has completed or failed.
+//
+// ClientTrace currently traces a single HTTP request & response
+// during a single round trip and has no hooks that span a series
+// of redirected requests.
+//
+// See https://blog.golang.org/http-tracing for more.
type ClientTrace struct {
// GetConn is called before a connection is created or
// retrieved from an idle pool. The hostPort is the
@@ -119,6 +125,16 @@ type ClientTrace struct {
// enabled, this may be called multiple times.
ConnectDone func(network, addr string, err error)
+ // TLSHandshakeStart is called when the TLS handshake is started. When
+ // connecting to a HTTPS site via a HTTP proxy, the handshake happens after
+ // the CONNECT request is processed by the proxy.
+ TLSHandshakeStart func()
+
+ // TLSHandshakeDone is called after the TLS handshake with either the
+ // successful handshake's connection state, or a non-nil error on handshake
+ // failure.
+ TLSHandshakeDone func(tls.ConnectionState, error)
+
// WroteHeaders is called after the Transport has written
// the request headers.
WroteHeaders func()
@@ -130,7 +146,8 @@ type ClientTrace struct {
Wait100Continue func()
// WroteRequest is called with the result of writing the
- // request and any body.
+ // request and any body. It may be called multiple times
+ // in the case of retried requests.
WroteRequest func(WroteRequestInfo)
}
diff --git a/libgo/go/net/http/httptrace/trace_test.go b/libgo/go/net/http/httptrace/trace_test.go
index c7eaed83d47..bb57ada8531 100644
--- a/libgo/go/net/http/httptrace/trace_test.go
+++ b/libgo/go/net/http/httptrace/trace_test.go
@@ -1,14 +1,41 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.h
+// license that can be found in the LICENSE file.
package httptrace
import (
"bytes"
+ "context"
"testing"
)
+func TestWithClientTrace(t *testing.T) {
+ var buf bytes.Buffer
+ connectStart := func(b byte) func(network, addr string) {
+ return func(network, addr string) {
+ buf.WriteByte(b)
+ }
+ }
+
+ ctx := context.Background()
+ oldtrace := &ClientTrace{
+ ConnectStart: connectStart('O'),
+ }
+ ctx = WithClientTrace(ctx, oldtrace)
+ newtrace := &ClientTrace{
+ ConnectStart: connectStart('N'),
+ }
+ ctx = WithClientTrace(ctx, newtrace)
+ trace := ContextClientTrace(ctx)
+
+ buf.Reset()
+ trace.ConnectStart("net", "addr")
+ if got, want := buf.String(), "NO"; got != want {
+ t.Errorf("got %q; want %q", got, want)
+ }
+}
+
func TestCompose(t *testing.T) {
var buf bytes.Buffer
var testNum int
diff --git a/libgo/go/net/http/httputil/dump.go b/libgo/go/net/http/httputil/dump.go
index 15116816328..7104c374545 100644
--- a/libgo/go/net/http/httputil/dump.go
+++ b/libgo/go/net/http/httputil/dump.go
@@ -18,11 +18,16 @@ import (
"time"
)
-// One of the copies, say from b to r2, could be avoided by using a more
-// elaborate trick where the other copy is made during Request/Response.Write.
-// This would complicate things too much, given that these functions are for
-// debugging only.
+// drainBody reads all of b to memory and then returns two equivalent
+// ReadClosers yielding the same bytes.
+//
+// It returns an error if the initial slurp of all bytes fails. It does not attempt
+// to make the returned ReadClosers have identical error-matching behavior.
func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) {
+ if b == http.NoBody {
+ // No copying needed. Preserve the magic sentinel meaning of NoBody.
+ return http.NoBody, http.NoBody, nil
+ }
var buf bytes.Buffer
if _, err = buf.ReadFrom(b); err != nil {
return nil, b, err
diff --git a/libgo/go/net/http/httputil/dump_test.go b/libgo/go/net/http/httputil/dump_test.go
index 2e980d39f8a..f881020fef7 100644
--- a/libgo/go/net/http/httputil/dump_test.go
+++ b/libgo/go/net/http/httputil/dump_test.go
@@ -184,6 +184,18 @@ var dumpTests = []dumpTest{
WantDump: "POST /v2/api/?login HTTP/1.1\r\n" +
"Host: passport.myhost.com\r\n\r\n",
},
+
+ // Issue 18506: make drainBody recognize NoBody. Otherwise
+ // this was turning into a chunked request.
+ {
+ Req: *mustNewRequest("POST", "http://example.com/foo", http.NoBody),
+
+ WantDumpOut: "POST /foo HTTP/1.1\r\n" +
+ "Host: example.com\r\n" +
+ "User-Agent: Go-http-client/1.1\r\n" +
+ "Content-Length: 0\r\n" +
+ "Accept-Encoding: gzip\r\n\r\n",
+ },
}
func TestDumpRequest(t *testing.T) {
diff --git a/libgo/go/net/http/httputil/persist.go b/libgo/go/net/http/httputil/persist.go
index 87ddd52cd96..cbedf25ad1b 100644
--- a/libgo/go/net/http/httputil/persist.go
+++ b/libgo/go/net/http/httputil/persist.go
@@ -15,9 +15,14 @@ import (
)
var (
+ // Deprecated: No longer used.
ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"}
- ErrClosed = &http.ProtocolError{ErrorString: "connection closed by user"}
- ErrPipeline = &http.ProtocolError{ErrorString: "pipeline error"}
+
+ // Deprecated: No longer used.
+ ErrClosed = &http.ProtocolError{ErrorString: "connection closed by user"}
+
+ // Deprecated: No longer used.
+ ErrPipeline = &http.ProtocolError{ErrorString: "pipeline error"}
)
// This is an API usage error - the local side is closed.
diff --git a/libgo/go/net/http/httputil/reverseproxy.go b/libgo/go/net/http/httputil/reverseproxy.go
index 49c120afde1..79c8fe27702 100644
--- a/libgo/go/net/http/httputil/reverseproxy.go
+++ b/libgo/go/net/http/httputil/reverseproxy.go
@@ -7,6 +7,7 @@
package httputil
import (
+ "context"
"io"
"log"
"net"
@@ -29,6 +30,8 @@ type ReverseProxy struct {
// the request into a new request to be sent
// using Transport. Its response is then copied
// back to the original client unmodified.
+ // Director must not access the provided Request
+ // after returning.
Director func(*http.Request)
// The transport used to perform proxy requests.
@@ -51,6 +54,11 @@ type ReverseProxy struct {
// get byte slices for use by io.CopyBuffer when
// copying HTTP response bodies.
BufferPool BufferPool
+
+ // ModifyResponse is an optional function that
+ // modifies the Response from the backend.
+ // If it returns an error, the proxy returns a StatusBadGateway error.
+ ModifyResponse func(*http.Response) error
}
// A BufferPool is an interface for getting and returning temporary
@@ -120,76 +128,59 @@ var hopHeaders = []string{
"Upgrade",
}
-type requestCanceler interface {
- CancelRequest(*http.Request)
-}
-
-type runOnFirstRead struct {
- io.Reader // optional; nil means empty body
-
- fn func() // Run before first Read, then set to nil
-}
-
-func (c *runOnFirstRead) Read(bs []byte) (int, error) {
- if c.fn != nil {
- c.fn()
- c.fn = nil
- }
- if c.Reader == nil {
- return 0, io.EOF
- }
- return c.Reader.Read(bs)
-}
-
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
transport := p.Transport
if transport == nil {
transport = http.DefaultTransport
}
+ ctx := req.Context()
+ if cn, ok := rw.(http.CloseNotifier); ok {
+ var cancel context.CancelFunc
+ ctx, cancel = context.WithCancel(ctx)
+ defer cancel()
+ notifyChan := cn.CloseNotify()
+ go func() {
+ select {
+ case <-notifyChan:
+ cancel()
+ case <-ctx.Done():
+ }
+ }()
+ }
+
outreq := new(http.Request)
*outreq = *req // includes shallow copies of maps, but okay
-
- if closeNotifier, ok := rw.(http.CloseNotifier); ok {
- if requestCanceler, ok := transport.(requestCanceler); ok {
- reqDone := make(chan struct{})
- defer close(reqDone)
-
- clientGone := closeNotifier.CloseNotify()
-
- outreq.Body = struct {
- io.Reader
- io.Closer
- }{
- Reader: &runOnFirstRead{
- Reader: outreq.Body,
- fn: func() {
- go func() {
- select {
- case <-clientGone:
- requestCanceler.CancelRequest(outreq)
- case <-reqDone:
- }
- }()
- },
- },
- Closer: outreq.Body,
- }
- }
+ if req.ContentLength == 0 {
+ outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
}
+ outreq = outreq.WithContext(ctx)
p.Director(outreq)
- outreq.Proto = "HTTP/1.1"
- outreq.ProtoMajor = 1
- outreq.ProtoMinor = 1
outreq.Close = false
- // Remove hop-by-hop headers to the backend. Especially
- // important is "Connection" because we want a persistent
- // connection, regardless of what the client sent to us. This
- // is modifying the same underlying map from req (shallow
+ // We are modifying the same underlying map from req (shallow
// copied above) so we only copy it if necessary.
copiedHeaders := false
+
+ // Remove hop-by-hop headers listed in the "Connection" header.
+ // See RFC 2616, section 14.10.
+ if c := outreq.Header.Get("Connection"); c != "" {
+ for _, f := range strings.Split(c, ",") {
+ if f = strings.TrimSpace(f); f != "" {
+ if !copiedHeaders {
+ outreq.Header = make(http.Header)
+ copyHeader(outreq.Header, req.Header)
+ copiedHeaders = true
+ }
+ outreq.Header.Del(f)
+ }
+ }
+ }
+
+ // Remove hop-by-hop headers to the backend. Especially
+ // important is "Connection" because we want a persistent
+ // connection, regardless of what the client sent to us.
for _, h := range hopHeaders {
if outreq.Header.Get(h) != "" {
if !copiedHeaders {
@@ -218,16 +209,34 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
return
}
+ // Remove hop-by-hop headers listed in the
+ // "Connection" header of the response.
+ if c := res.Header.Get("Connection"); c != "" {
+ for _, f := range strings.Split(c, ",") {
+ if f = strings.TrimSpace(f); f != "" {
+ res.Header.Del(f)
+ }
+ }
+ }
+
for _, h := range hopHeaders {
res.Header.Del(h)
}
+ if p.ModifyResponse != nil {
+ if err := p.ModifyResponse(res); err != nil {
+ p.logf("http: proxy error: %v", err)
+ rw.WriteHeader(http.StatusBadGateway)
+ return
+ }
+ }
+
copyHeader(rw.Header(), res.Header)
// The "Trailer" header isn't included in the Transport's response,
// at least for *http.Transport. Build it up from Trailer.
if len(res.Trailer) > 0 {
- var trailerKeys []string
+ trailerKeys := make([]string, 0, len(res.Trailer))
for k := range res.Trailer {
trailerKeys = append(trailerKeys, k)
}
@@ -266,12 +275,40 @@ func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader) {
if p.BufferPool != nil {
buf = p.BufferPool.Get()
}
- io.CopyBuffer(dst, src, buf)
+ p.copyBuffer(dst, src, buf)
if p.BufferPool != nil {
p.BufferPool.Put(buf)
}
}
+func (p *ReverseProxy) copyBuffer(dst io.Writer, src io.Reader, buf []byte) (int64, error) {
+ if len(buf) == 0 {
+ buf = make([]byte, 32*1024)
+ }
+ var written int64
+ for {
+ nr, rerr := src.Read(buf)
+ if rerr != nil && rerr != io.EOF {
+ p.logf("httputil: ReverseProxy read error during body copy: %v", rerr)
+ }
+ if nr > 0 {
+ nw, werr := dst.Write(buf[:nr])
+ if nw > 0 {
+ written += int64(nw)
+ }
+ if werr != nil {
+ return written, werr
+ }
+ if nr != nw {
+ return written, io.ErrShortWrite
+ }
+ }
+ if rerr != nil {
+ return written, rerr
+ }
+ }
+}
+
func (p *ReverseProxy) logf(format string, args ...interface{}) {
if p.ErrorLog != nil {
p.ErrorLog.Printf(format, args...)
diff --git a/libgo/go/net/http/httputil/reverseproxy_test.go b/libgo/go/net/http/httputil/reverseproxy_test.go
index fe7cdb888f5..20c4e16bcb8 100644
--- a/libgo/go/net/http/httputil/reverseproxy_test.go
+++ b/libgo/go/net/http/httputil/reverseproxy_test.go
@@ -9,6 +9,8 @@ package httputil
import (
"bufio"
"bytes"
+ "errors"
+ "fmt"
"io"
"io/ioutil"
"log"
@@ -135,6 +137,61 @@ func TestReverseProxy(t *testing.T) {
}
+// Issue 16875: remove any proxied headers mentioned in the "Connection"
+// header value.
+func TestReverseProxyStripHeadersPresentInConnection(t *testing.T) {
+ const fakeConnectionToken = "X-Fake-Connection-Token"
+ const backendResponse = "I am the backend"
+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if c := r.Header.Get(fakeConnectionToken); c != "" {
+ t.Errorf("handler got header %q = %q; want empty", fakeConnectionToken, c)
+ }
+ if c := r.Header.Get("Upgrade"); c != "" {
+ t.Errorf("handler got header %q = %q; want empty", "Upgrade", c)
+ }
+ w.Header().Set("Connection", "Upgrade, "+fakeConnectionToken)
+ w.Header().Set("Upgrade", "should be deleted")
+ w.Header().Set(fakeConnectionToken, "should be deleted")
+ io.WriteString(w, backendResponse)
+ }))
+ defer backend.Close()
+ backendURL, err := url.Parse(backend.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ proxyHandler := NewSingleHostReverseProxy(backendURL)
+ frontend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ proxyHandler.ServeHTTP(w, r)
+ if c := r.Header.Get("Upgrade"); c != "original value" {
+ t.Errorf("handler modified header %q = %q; want %q", "Upgrade", c, "original value")
+ }
+ }))
+ defer frontend.Close()
+
+ getReq, _ := http.NewRequest("GET", frontend.URL, nil)
+ getReq.Header.Set("Connection", "Upgrade, "+fakeConnectionToken)
+ getReq.Header.Set("Upgrade", "original value")
+ getReq.Header.Set(fakeConnectionToken, "should be deleted")
+ res, err := http.DefaultClient.Do(getReq)
+ if err != nil {
+ t.Fatalf("Get: %v", err)
+ }
+ defer res.Body.Close()
+ bodyBytes, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatalf("reading body: %v", err)
+ }
+ if got, want := string(bodyBytes), backendResponse; got != want {
+ t.Errorf("got body %q; want %q", got, want)
+ }
+ if c := res.Header.Get("Upgrade"); c != "" {
+ t.Errorf("handler got header %q = %q; want empty", "Upgrade", c)
+ }
+ if c := res.Header.Get(fakeConnectionToken); c != "" {
+ t.Errorf("handler got header %q = %q; want empty", fakeConnectionToken, c)
+ }
+}
+
func TestXForwardedFor(t *testing.T) {
const prevForwardedFor = "client ip"
const backendResponse = "I am the backend"
@@ -260,14 +317,14 @@ func TestReverseProxyCancelation(t *testing.T) {
reqInFlight := make(chan struct{})
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- close(reqInFlight)
+ close(reqInFlight) // cause the client to cancel its request
select {
case <-time.After(10 * time.Second):
// Note: this should only happen in broken implementations, and the
// closenotify case should be instantaneous.
- t.Log("Failed to close backend connection")
- t.Fail()
+ t.Error("Handler never saw CloseNotify")
+ return
case <-w.(http.CloseNotifier).CloseNotify():
}
@@ -300,13 +357,13 @@ func TestReverseProxyCancelation(t *testing.T) {
}()
res, err := http.DefaultClient.Do(getReq)
if res != nil {
- t.Fatal("Non-nil response")
+ t.Errorf("got response %v; want nil", res.Status)
}
if err == nil {
// This should be an error like:
// Get http://127.0.0.1:58079: read tcp 127.0.0.1:58079:
// use of closed network connection
- t.Fatal("DefaultClient.Do() returned nil error")
+ t.Error("DefaultClient.Do() returned nil error; want non-nil error")
}
}
@@ -495,3 +552,115 @@ func TestReverseProxy_Post(t *testing.T) {
t.Errorf("got body %q; expected %q", g, e)
}
}
+
+type RoundTripperFunc func(*http.Request) (*http.Response, error)
+
+func (fn RoundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) {
+ return fn(req)
+}
+
+// Issue 16036: send a Request with a nil Body when possible
+func TestReverseProxy_NilBody(t *testing.T) {
+ backendURL, _ := url.Parse("http://fake.tld/")
+ proxyHandler := NewSingleHostReverseProxy(backendURL)
+ proxyHandler.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
+ proxyHandler.Transport = RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
+ if req.Body != nil {
+ t.Error("Body != nil; want a nil Body")
+ }
+ return nil, errors.New("done testing the interesting part; so force a 502 Gateway error")
+ })
+ frontend := httptest.NewServer(proxyHandler)
+ defer frontend.Close()
+
+ res, err := http.DefaultClient.Get(frontend.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ if res.StatusCode != 502 {
+ t.Errorf("status code = %v; want 502 (Gateway Error)", res.Status)
+ }
+}
+
+// Issue 14237. Test ModifyResponse and that an error from it
+// causes the proxy to return StatusBadGateway, or StatusOK otherwise.
+func TestReverseProxyModifyResponse(t *testing.T) {
+ backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("X-Hit-Mod", fmt.Sprintf("%v", r.URL.Path == "/mod"))
+ }))
+ defer backendServer.Close()
+
+ rpURL, _ := url.Parse(backendServer.URL)
+ rproxy := NewSingleHostReverseProxy(rpURL)
+ rproxy.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
+ rproxy.ModifyResponse = func(resp *http.Response) error {
+ if resp.Header.Get("X-Hit-Mod") != "true" {
+ return fmt.Errorf("tried to by-pass proxy")
+ }
+ return nil
+ }
+
+ frontendProxy := httptest.NewServer(rproxy)
+ defer frontendProxy.Close()
+
+ tests := []struct {
+ url string
+ wantCode int
+ }{
+ {frontendProxy.URL + "/mod", http.StatusOK},
+ {frontendProxy.URL + "/schedule", http.StatusBadGateway},
+ }
+
+ for i, tt := range tests {
+ resp, err := http.Get(tt.url)
+ if err != nil {
+ t.Fatalf("failed to reach proxy: %v", err)
+ }
+ if g, e := resp.StatusCode, tt.wantCode; g != e {
+ t.Errorf("#%d: got res.StatusCode %d; expected %d", i, g, e)
+ }
+ resp.Body.Close()
+ }
+}
+
+// Issue 16659: log errors from short read
+func TestReverseProxy_CopyBuffer(t *testing.T) {
+ backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ out := "this call was relayed by the reverse proxy"
+ // Coerce a wrong content length to induce io.UnexpectedEOF
+ w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out)*2))
+ fmt.Fprintln(w, out)
+ }))
+ defer backendServer.Close()
+
+ rpURL, err := url.Parse(backendServer.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var proxyLog bytes.Buffer
+ rproxy := NewSingleHostReverseProxy(rpURL)
+ rproxy.ErrorLog = log.New(&proxyLog, "", log.Lshortfile)
+ frontendProxy := httptest.NewServer(rproxy)
+ defer frontendProxy.Close()
+
+ resp, err := http.Get(frontendProxy.URL)
+ if err != nil {
+ t.Fatalf("failed to reach proxy: %v", err)
+ }
+ defer resp.Body.Close()
+
+ if _, err := ioutil.ReadAll(resp.Body); err == nil {
+ t.Fatalf("want non-nil error")
+ }
+ expected := []string{
+ "EOF",
+ "read",
+ }
+ for _, phrase := range expected {
+ if !bytes.Contains(proxyLog.Bytes(), []byte(phrase)) {
+ t.Errorf("expected log to contain phrase %q", phrase)
+ }
+ }
+}
diff --git a/libgo/go/net/http/internal/chunked.go b/libgo/go/net/http/internal/chunked.go
index 2e62c00d5db..63f321d03b9 100644
--- a/libgo/go/net/http/internal/chunked.go
+++ b/libgo/go/net/http/internal/chunked.go
@@ -35,10 +35,11 @@ func NewChunkedReader(r io.Reader) io.Reader {
}
type chunkedReader struct {
- r *bufio.Reader
- n uint64 // unread bytes in chunk
- err error
- buf [2]byte
+ r *bufio.Reader
+ n uint64 // unread bytes in chunk
+ err error
+ buf [2]byte
+ checkEnd bool // whether need to check for \r\n chunk footer
}
func (cr *chunkedReader) beginChunk() {
@@ -68,6 +69,21 @@ func (cr *chunkedReader) chunkHeaderAvailable() bool {
func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
for cr.err == nil {
+ if cr.checkEnd {
+ if n > 0 && cr.r.Buffered() < 2 {
+ // We have some data. Return early (per the io.Reader
+ // contract) instead of potentially blocking while
+ // reading more.
+ break
+ }
+ if _, cr.err = io.ReadFull(cr.r, cr.buf[:2]); cr.err == nil {
+ if string(cr.buf[:]) != "\r\n" {
+ cr.err = errors.New("malformed chunked encoding")
+ break
+ }
+ }
+ cr.checkEnd = false
+ }
if cr.n == 0 {
if n > 0 && !cr.chunkHeaderAvailable() {
// We've read enough. Don't potentially block
@@ -92,11 +108,7 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
// If we're at the end of a chunk, read the next two
// bytes to verify they are "\r\n".
if cr.n == 0 && cr.err == nil {
- if _, cr.err = io.ReadFull(cr.r, cr.buf[:2]); cr.err == nil {
- if cr.buf[0] != '\r' || cr.buf[1] != '\n' {
- cr.err = errors.New("malformed chunked encoding")
- }
- }
+ cr.checkEnd = true
}
}
return n, cr.err
diff --git a/libgo/go/net/http/internal/chunked_test.go b/libgo/go/net/http/internal/chunked_test.go
index 9abe1ab6d9d..d06716591ab 100644
--- a/libgo/go/net/http/internal/chunked_test.go
+++ b/libgo/go/net/http/internal/chunked_test.go
@@ -185,3 +185,30 @@ func TestChunkReadingIgnoresExtensions(t *testing.T) {
t.Errorf("read %q; want %q", g, e)
}
}
+
+// Issue 17355: ChunkedReader shouldn't block waiting for more data
+// if it can return something.
+func TestChunkReadPartial(t *testing.T) {
+ pr, pw := io.Pipe()
+ go func() {
+ pw.Write([]byte("7\r\n1234567"))
+ }()
+ cr := NewChunkedReader(pr)
+ readBuf := make([]byte, 7)
+ n, err := cr.Read(readBuf)
+ if err != nil {
+ t.Fatal(err)
+ }
+ want := "1234567"
+ if n != 7 || string(readBuf) != want {
+ t.Fatalf("Read: %v %q; want %d, %q", n, readBuf[:n], len(want), want)
+ }
+ go func() {
+ pw.Write([]byte("xx"))
+ }()
+ _, err = cr.Read(readBuf)
+ if got := fmt.Sprint(err); !strings.Contains(got, "malformed") {
+ t.Fatalf("second read = %v; want malformed error", err)
+ }
+
+}
diff --git a/libgo/go/net/http/main_test.go b/libgo/go/net/http/main_test.go
index aea6e12744b..438bd2e58fd 100644
--- a/libgo/go/net/http/main_test.go
+++ b/libgo/go/net/http/main_test.go
@@ -6,6 +6,8 @@ package http_test
import (
"fmt"
+ "io/ioutil"
+ "log"
"net/http"
"os"
"runtime"
@@ -15,6 +17,8 @@ import (
"time"
)
+var quietLog = log.New(ioutil.Discard, "", 0)
+
func TestMain(m *testing.M) {
v := m.Run()
if v == 0 && goroutineLeaked() {
@@ -134,3 +138,20 @@ func waitCondition(waitFor, checkEvery time.Duration, fn func() bool) bool {
}
return false
}
+
+// waitErrCondition is like waitCondition but with errors instead of bools.
+func waitErrCondition(waitFor, checkEvery time.Duration, fn func() error) error {
+ deadline := time.Now().Add(waitFor)
+ var err error
+ for time.Now().Before(deadline) {
+ if err = fn(); err == nil {
+ return nil
+ }
+ time.Sleep(checkEvery)
+ }
+ return err
+}
+
+func closeClient(c *http.Client) {
+ c.Transport.(*http.Transport).CloseIdleConnections()
+}
diff --git a/libgo/go/net/http/npn_test.go b/libgo/go/net/http/npn_test.go
index e2e911d3dd1..4c1f6b573df 100644
--- a/libgo/go/net/http/npn_test.go
+++ b/libgo/go/net/http/npn_test.go
@@ -18,6 +18,7 @@ import (
)
func TestNextProtoUpgrade(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "path=%s,proto=", r.URL.Path)
diff --git a/libgo/go/net/http/range_test.go b/libgo/go/net/http/range_test.go
index ef911af7b08..114987ed2c6 100644
--- a/libgo/go/net/http/range_test.go
+++ b/libgo/go/net/http/range_test.go
@@ -38,7 +38,7 @@ var ParseRangeTests = []struct {
{"bytes=0-", 10, []httpRange{{0, 10}}},
{"bytes=5-", 10, []httpRange{{5, 5}}},
{"bytes=0-20", 10, []httpRange{{0, 10}}},
- {"bytes=15-,0-5", 10, nil},
+ {"bytes=15-,0-5", 10, []httpRange{{0, 6}}},
{"bytes=1-2,5-", 10, []httpRange{{1, 2}, {5, 5}}},
{"bytes=-2 , 7-", 11, []httpRange{{9, 2}, {7, 4}}},
{"bytes=0-0 ,2-2, 7-", 11, []httpRange{{0, 1}, {2, 1}, {7, 4}}},
diff --git a/libgo/go/net/http/readrequest_test.go b/libgo/go/net/http/readrequest_test.go
index 4bf646b0a63..28a148b9acb 100644
--- a/libgo/go/net/http/readrequest_test.go
+++ b/libgo/go/net/http/readrequest_test.go
@@ -25,7 +25,7 @@ type reqTest struct {
}
var noError = ""
-var noBody = ""
+var noBodyStr = ""
var noTrailer Header = nil
var reqTests = []reqTest{
@@ -95,7 +95,7 @@ var reqTests = []reqTest{
RequestURI: "/",
},
- noBody,
+ noBodyStr,
noTrailer,
noError,
},
@@ -121,7 +121,7 @@ var reqTests = []reqTest{
RequestURI: "//user@host/is/actually/a/path/",
},
- noBody,
+ noBodyStr,
noTrailer,
noError,
},
@@ -131,7 +131,7 @@ var reqTests = []reqTest{
"GET ../../../../etc/passwd HTTP/1.1\r\n" +
"Host: test\r\n\r\n",
nil,
- noBody,
+ noBodyStr,
noTrailer,
"parse ../../../../etc/passwd: invalid URI for request",
},
@@ -141,7 +141,7 @@ var reqTests = []reqTest{
"GET HTTP/1.1\r\n" +
"Host: test\r\n\r\n",
nil,
- noBody,
+ noBodyStr,
noTrailer,
"parse : empty url",
},
@@ -227,7 +227,7 @@ var reqTests = []reqTest{
RequestURI: "www.google.com:443",
},
- noBody,
+ noBodyStr,
noTrailer,
noError,
},
@@ -251,7 +251,7 @@ var reqTests = []reqTest{
RequestURI: "127.0.0.1:6060",
},
- noBody,
+ noBodyStr,
noTrailer,
noError,
},
@@ -275,7 +275,7 @@ var reqTests = []reqTest{
RequestURI: "/_goRPC_",
},
- noBody,
+ noBodyStr,
noTrailer,
noError,
},
@@ -299,7 +299,7 @@ var reqTests = []reqTest{
RequestURI: "*",
},
- noBody,
+ noBodyStr,
noTrailer,
noError,
},
@@ -323,7 +323,7 @@ var reqTests = []reqTest{
RequestURI: "*",
},
- noBody,
+ noBodyStr,
noTrailer,
noError,
},
@@ -350,7 +350,7 @@ var reqTests = []reqTest{
RequestURI: "/",
},
- noBody,
+ noBodyStr,
noTrailer,
noError,
},
@@ -376,7 +376,7 @@ var reqTests = []reqTest{
RequestURI: "/",
},
- noBody,
+ noBodyStr,
noTrailer,
noError,
},
@@ -397,7 +397,7 @@ var reqTests = []reqTest{
ContentLength: -1,
Close: true,
},
- noBody,
+ noBodyStr,
noTrailer,
noError,
},
diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go
index dc5559282d0..fb6bb0aab58 100644
--- a/libgo/go/net/http/request.go
+++ b/libgo/go/net/http/request.go
@@ -18,12 +18,17 @@ import (
"io/ioutil"
"mime"
"mime/multipart"
+ "net"
"net/http/httptrace"
"net/textproto"
"net/url"
"strconv"
"strings"
"sync"
+
+ "golang_org/x/net/idna"
+ "golang_org/x/text/unicode/norm"
+ "golang_org/x/text/width"
)
const (
@@ -34,21 +39,40 @@ const (
// is either not present in the request or not a file field.
var ErrMissingFile = errors.New("http: no such file")
-// HTTP request parsing errors.
+// ProtocolError represents an HTTP protocol error.
+//
+// Deprecated: Not all errors in the http package related to protocol errors
+// are of type ProtocolError.
type ProtocolError struct {
ErrorString string
}
-func (err *ProtocolError) Error() string { return err.ErrorString }
+func (pe *ProtocolError) Error() string { return pe.ErrorString }
var (
- ErrHeaderTooLong = &ProtocolError{"header too long"}
- ErrShortBody = &ProtocolError{"entity body too short"}
- ErrNotSupported = &ProtocolError{"feature not supported"}
- ErrUnexpectedTrailer = &ProtocolError{"trailer header without chunked transfer encoding"}
+ // ErrNotSupported is returned by the Push method of Pusher
+ // implementations to indicate that HTTP/2 Push support is not
+ // available.
+ ErrNotSupported = &ProtocolError{"feature not supported"}
+
+ // ErrUnexpectedTrailer is returned by the Transport when a server
+ // replies with a Trailer header, but without a chunked reply.
+ ErrUnexpectedTrailer = &ProtocolError{"trailer header without chunked transfer encoding"}
+
+ // ErrMissingBoundary is returned by Request.MultipartReader when the
+ // request's Content-Type does not include a "boundary" parameter.
+ ErrMissingBoundary = &ProtocolError{"no multipart boundary param in Content-Type"}
+
+ // ErrNotMultipart is returned by Request.MultipartReader when the
+ // request's Content-Type is not multipart/form-data.
+ ErrNotMultipart = &ProtocolError{"request Content-Type isn't multipart/form-data"}
+
+ // Deprecated: ErrHeaderTooLong is not used.
+ ErrHeaderTooLong = &ProtocolError{"header too long"}
+ // Deprecated: ErrShortBody is not used.
+ ErrShortBody = &ProtocolError{"entity body too short"}
+ // Deprecated: ErrMissingContentLength is not used.
ErrMissingContentLength = &ProtocolError{"missing ContentLength in HEAD response"}
- ErrNotMultipart = &ProtocolError{"request Content-Type isn't multipart/form-data"}
- ErrMissingBoundary = &ProtocolError{"no multipart boundary param in Content-Type"}
)
type badStringError struct {
@@ -146,11 +170,20 @@ type Request struct {
// Handler does not need to.
Body io.ReadCloser
+ // GetBody defines an optional func to return a new copy of
+ // Body. It is used for client requests when a redirect requires
+ // reading the body more than once. Use of GetBody still
+ // requires setting Body.
+ //
+ // For server requests it is unused.
+ GetBody func() (io.ReadCloser, error)
+
// ContentLength records the length of the associated content.
// The value -1 indicates that the length is unknown.
// Values >= 0 indicate that the given number of bytes may
// be read from Body.
- // For client requests, a value of 0 means unknown if Body is not nil.
+ // For client requests, a value of 0 with a non-nil Body is
+ // also treated as unknown.
ContentLength int64
// TransferEncoding lists the transfer encodings from outermost to
@@ -175,11 +208,15 @@ type Request struct {
// For server requests Host specifies the host on which the
// URL is sought. Per RFC 2616, this is either the value of
// the "Host" header or the host name given in the URL itself.
- // It may be of the form "host:port".
+ // It may be of the form "host:port". For international domain
+ // names, Host may be in Punycode or Unicode form. Use
+ // golang.org/x/net/idna to convert it to either format if
+ // needed.
//
// For client requests Host optionally overrides the Host
// header to send. If empty, the Request.Write method uses
- // the value of URL.Host.
+ // the value of URL.Host. Host may contain an international
+ // domain name.
Host string
// Form contains the parsed form data, including both the URL
@@ -276,8 +313,8 @@ type Request struct {
// For outgoing client requests, the context controls cancelation.
//
// For incoming server requests, the context is canceled when the
-// ServeHTTP method returns. For its associated values, see
-// ServerContextKey and LocalAddrContextKey.
+// client's connection closes, the request is canceled (with HTTP/2),
+// or when the ServeHTTP method returns.
func (r *Request) Context() context.Context {
if r.ctx != nil {
return r.ctx
@@ -304,6 +341,18 @@ func (r *Request) ProtoAtLeast(major, minor int) bool {
r.ProtoMajor == major && r.ProtoMinor >= minor
}
+// protoAtLeastOutgoing is like ProtoAtLeast, but is for outgoing
+// requests (see issue 18407) where these fields aren't supposed to
+// matter. As a minor fix for Go 1.8, at least treat (0, 0) as
+// matching HTTP/1.1 or HTTP/1.0. Only HTTP/1.1 is used.
+// TODO(bradfitz): ideally remove this whole method. It shouldn't be used.
+func (r *Request) protoAtLeastOutgoing(major, minor int) bool {
+ if r.ProtoMajor == 0 && r.ProtoMinor == 0 && major == 1 && minor <= 1 {
+ return true
+ }
+ return r.ProtoAtLeast(major, minor)
+}
+
// UserAgent returns the client's User-Agent, if sent in the request.
func (r *Request) UserAgent() string {
return r.Header.Get("User-Agent")
@@ -319,6 +368,8 @@ var ErrNoCookie = errors.New("http: named cookie not present")
// Cookie returns the named cookie provided in the request or
// ErrNoCookie if not found.
+// If multiple cookies match the given name, only one cookie will
+// be returned.
func (r *Request) Cookie(name string) (*Cookie, error) {
for _, c := range readCookies(r.Header, name) {
return c, nil
@@ -561,6 +612,12 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, wai
}
}
+ if bw, ok := w.(*bufio.Writer); ok && tw.FlushHeaders {
+ if err := bw.Flush(); err != nil {
+ return err
+ }
+ }
+
// Write body and trailer
err = tw.WriteBody(w)
if err != nil {
@@ -573,7 +630,24 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, wai
return nil
}
-// cleanHost strips anything after '/' or ' '.
+func idnaASCII(v string) (string, error) {
+ if isASCII(v) {
+ return v, nil
+ }
+ // The idna package doesn't do everything from
+ // https://tools.ietf.org/html/rfc5895 so we do it here.
+ // TODO(bradfitz): should the idna package do this instead?
+ v = strings.ToLower(v)
+ v = width.Fold.String(v)
+ v = norm.NFC.String(v)
+ return idna.ToASCII(v)
+}
+
+// cleanHost cleans up the host sent in request's Host header.
+//
+// It both strips anything after '/' or ' ', and puts the value
+// into Punycode form, if necessary.
+//
// Ideally we'd clean the Host header according to the spec:
// https://tools.ietf.org/html/rfc7230#section-5.4 (Host = uri-host [ ":" port ]")
// https://tools.ietf.org/html/rfc7230#section-2.7 (uri-host -> rfc3986's host)
@@ -584,9 +658,21 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, wai
// first offending character.
func cleanHost(in string) string {
if i := strings.IndexAny(in, " /"); i != -1 {
- return in[:i]
+ in = in[:i]
+ }
+ host, port, err := net.SplitHostPort(in)
+ if err != nil { // input was just a host
+ a, err := idnaASCII(in)
+ if err != nil {
+ return in // garbage in, garbage out
+ }
+ return a
}
- return in
+ a, err := idnaASCII(host)
+ if err != nil {
+ return in // garbage in, garbage out
+ }
+ return net.JoinHostPort(a, port)
}
// removeZone removes IPv6 zone identifier from host.
@@ -658,11 +744,17 @@ func validMethod(method string) bool {
// methods Do, Post, and PostForm, and Transport.RoundTrip.
//
// NewRequest returns a Request suitable for use with Client.Do or
-// Transport.RoundTrip.
-// To create a request for use with testing a Server Handler use either
-// ReadRequest or manually update the Request fields. See the Request
-// type's documentation for the difference between inbound and outbound
-// request fields.
+// Transport.RoundTrip. To create a request for use with testing a
+// Server Handler, either use the NewRequest function in the
+// net/http/httptest package, use ReadRequest, or manually update the
+// Request fields. See the Request type's documentation for the
+// difference between inbound and outbound request fields.
+//
+// If body is of type *bytes.Buffer, *bytes.Reader, or
+// *strings.Reader, the returned request's ContentLength is set to its
+// exact value (instead of -1), GetBody is populated (so 307 and 308
+// redirects can replay the body), and Body is set to NoBody if the
+// ContentLength is 0.
func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
if method == "" {
// We document that "" means "GET" for Request.Method, and people have
@@ -697,10 +789,43 @@ func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
switch v := body.(type) {
case *bytes.Buffer:
req.ContentLength = int64(v.Len())
+ buf := v.Bytes()
+ req.GetBody = func() (io.ReadCloser, error) {
+ r := bytes.NewReader(buf)
+ return ioutil.NopCloser(r), nil
+ }
case *bytes.Reader:
req.ContentLength = int64(v.Len())
+ snapshot := *v
+ req.GetBody = func() (io.ReadCloser, error) {
+ r := snapshot
+ return ioutil.NopCloser(&r), nil
+ }
case *strings.Reader:
req.ContentLength = int64(v.Len())
+ snapshot := *v
+ req.GetBody = func() (io.ReadCloser, error) {
+ r := snapshot
+ return ioutil.NopCloser(&r), nil
+ }
+ default:
+ // This is where we'd set it to -1 (at least
+ // if body != NoBody) to mean unknown, but
+ // that broke people during the Go 1.8 testing
+ // period. People depend on it being 0 I
+ // guess. Maybe retry later. See Issue 18117.
+ }
+ // For client requests, Request.ContentLength of 0
+ // means either actually 0, or unknown. The only way
+ // to explicitly say that the ContentLength is zero is
+ // to set the Body to nil. But turns out too much code
+ // depends on NewRequest returning a non-nil Body,
+ // so we use a well-known ReadCloser variable instead
+ // and have the http package also treat that sentinel
+ // variable to mean explicitly zero.
+ if req.GetBody != nil && req.ContentLength == 0 {
+ req.Body = NoBody
+ req.GetBody = func() (io.ReadCloser, error) { return NoBody, nil }
}
}
@@ -1000,18 +1125,24 @@ func parsePostForm(r *Request) (vs url.Values, err error) {
return
}
-// ParseForm parses the raw query from the URL and updates r.Form.
+// ParseForm populates r.Form and r.PostForm.
+//
+// For all requests, ParseForm parses the raw query from the URL and updates
+// r.Form.
+//
+// For POST, PUT, and PATCH requests, it also parses the request body as a form
+// and puts the results into both r.PostForm and r.Form. Request body parameters
+// take precedence over URL query string values in r.Form.
//
-// For POST or PUT requests, it also parses the request body as a form and
-// put the results into both r.PostForm and r.Form.
-// POST and PUT body parameters take precedence over URL query string values
-// in r.Form.
+// For other HTTP methods, or when the Content-Type is not
+// application/x-www-form-urlencoded, the request Body is not read, and
+// r.PostForm is initialized to a non-nil, empty value.
//
// If the request Body's size has not already been limited by MaxBytesReader,
// the size is capped at 10MB.
//
// ParseMultipartForm calls ParseForm automatically.
-// It is idempotent.
+// ParseForm is idempotent.
func (r *Request) ParseForm() error {
var err error
if r.PostForm == nil {
@@ -1174,3 +1305,30 @@ func (r *Request) isReplayable() bool {
}
return false
}
+
+// outgoingLength reports the Content-Length of this outgoing (Client) request.
+// It maps 0 into -1 (unknown) when the Body is non-nil.
+func (r *Request) outgoingLength() int64 {
+ if r.Body == nil || r.Body == NoBody {
+ return 0
+ }
+ if r.ContentLength != 0 {
+ return r.ContentLength
+ }
+ return -1
+}
+
+// requestMethodUsuallyLacksBody reports whether the given request
+// method is one that typically does not involve a request body.
+// This is used by the Transport (via
+// transferWriter.shouldSendChunkedRequestBody) to determine whether
+// we try to test-read a byte from a non-nil Request.Body when
+// Request.outgoingLength() returns -1. See the comments in
+// shouldSendChunkedRequestBody.
+func requestMethodUsuallyLacksBody(method string) bool {
+ switch method {
+ case "GET", "HEAD", "DELETE", "OPTIONS", "PROPFIND", "SEARCH":
+ return true
+ }
+ return false
+}
diff --git a/libgo/go/net/http/request_test.go b/libgo/go/net/http/request_test.go
index a4c88c02915..e6748375b58 100644
--- a/libgo/go/net/http/request_test.go
+++ b/libgo/go/net/http/request_test.go
@@ -29,9 +29,9 @@ func TestQuery(t *testing.T) {
}
}
-func TestPostQuery(t *testing.T) {
- req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&empty=not",
- strings.NewReader("z=post&both=y&prio=2&empty="))
+func TestParseFormQuery(t *testing.T) {
+ req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&orphan=nope&empty=not",
+ strings.NewReader("z=post&both=y&prio=2&=nokey&orphan;empty=&"))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
if q := req.FormValue("q"); q != "foo" {
@@ -55,39 +55,30 @@ func TestPostQuery(t *testing.T) {
if prio := req.FormValue("prio"); prio != "2" {
t.Errorf(`req.FormValue("prio") = %q, want "2" (from body)`, prio)
}
- if empty := req.FormValue("empty"); empty != "" {
+ if orphan := req.Form["orphan"]; !reflect.DeepEqual(orphan, []string{"", "nope"}) {
+ t.Errorf(`req.FormValue("orphan") = %q, want "" (from body)`, orphan)
+ }
+ if empty := req.Form["empty"]; !reflect.DeepEqual(empty, []string{"", "not"}) {
t.Errorf(`req.FormValue("empty") = %q, want "" (from body)`, empty)
}
+ if nokey := req.Form[""]; !reflect.DeepEqual(nokey, []string{"nokey"}) {
+ t.Errorf(`req.FormValue("nokey") = %q, want "nokey" (from body)`, nokey)
+ }
}
-func TestPatchQuery(t *testing.T) {
- req, _ := NewRequest("PATCH", "http://www.google.com/search?q=foo&q=bar&both=x&prio=1&empty=not",
- strings.NewReader("z=post&both=y&prio=2&empty="))
- req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
-
- if q := req.FormValue("q"); q != "foo" {
- t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
- }
- if z := req.FormValue("z"); z != "post" {
- t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
- }
- if bq, found := req.PostForm["q"]; found {
- t.Errorf(`req.PostForm["q"] = %q, want no entry in map`, bq)
- }
- if bz := req.PostFormValue("z"); bz != "post" {
- t.Errorf(`req.PostFormValue("z") = %q, want "post"`, bz)
- }
- if qs := req.Form["q"]; !reflect.DeepEqual(qs, []string{"foo", "bar"}) {
- t.Errorf(`req.Form["q"] = %q, want ["foo", "bar"]`, qs)
- }
- if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"y", "x"}) {
- t.Errorf(`req.Form["both"] = %q, want ["y", "x"]`, both)
- }
- if prio := req.FormValue("prio"); prio != "2" {
- t.Errorf(`req.FormValue("prio") = %q, want "2" (from body)`, prio)
- }
- if empty := req.FormValue("empty"); empty != "" {
- t.Errorf(`req.FormValue("empty") = %q, want "" (from body)`, empty)
+// Tests that we only parse the form automatically for certain methods.
+func TestParseFormQueryMethods(t *testing.T) {
+ for _, method := range []string{"POST", "PATCH", "PUT", "FOO"} {
+ req, _ := NewRequest(method, "http://www.google.com/search",
+ strings.NewReader("foo=bar"))
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
+ want := "bar"
+ if method == "FOO" {
+ want = ""
+ }
+ if got := req.FormValue("foo"); got != want {
+ t.Errorf(`for method %s, FormValue("foo") = %q; want %q`, method, got, want)
+ }
}
}
@@ -374,18 +365,68 @@ func TestFormFileOrder(t *testing.T) {
var readRequestErrorTests = []struct {
in string
- err error
+ err string
+
+ header Header
}{
- {"GET / HTTP/1.1\r\nheader:foo\r\n\r\n", nil},
- {"GET / HTTP/1.1\r\nheader:foo\r\n", io.ErrUnexpectedEOF},
- {"", io.EOF},
+ 0: {"GET / HTTP/1.1\r\nheader:foo\r\n\r\n", "", Header{"Header": {"foo"}}},
+ 1: {"GET / HTTP/1.1\r\nheader:foo\r\n", io.ErrUnexpectedEOF.Error(), nil},
+ 2: {"", io.EOF.Error(), nil},
+ 3: {
+ in: "HEAD / HTTP/1.1\r\nContent-Length:4\r\n\r\n",
+ err: "http: method cannot contain a Content-Length",
+ },
+ 4: {
+ in: "HEAD / HTTP/1.1\r\n\r\n",
+ header: Header{},
+ },
+
+ // Multiple Content-Length values should either be
+ // deduplicated if same or reject otherwise
+ // See Issue 16490.
+ 5: {
+ in: "POST / HTTP/1.1\r\nContent-Length: 10\r\nContent-Length: 0\r\n\r\nGopher hey\r\n",
+ err: "cannot contain multiple Content-Length headers",
+ },
+ 6: {
+ in: "POST / HTTP/1.1\r\nContent-Length: 10\r\nContent-Length: 6\r\n\r\nGopher\r\n",
+ err: "cannot contain multiple Content-Length headers",
+ },
+ 7: {
+ in: "PUT / HTTP/1.1\r\nContent-Length: 6 \r\nContent-Length: 6\r\nContent-Length:6\r\n\r\nGopher\r\n",
+ err: "",
+ header: Header{"Content-Length": {"6"}},
+ },
+ 8: {
+ in: "PUT / HTTP/1.1\r\nContent-Length: 1\r\nContent-Length: 6 \r\n\r\n",
+ err: "cannot contain multiple Content-Length headers",
+ },
+ 9: {
+ in: "POST / HTTP/1.1\r\nContent-Length:\r\nContent-Length: 3\r\n\r\n",
+ err: "cannot contain multiple Content-Length headers",
+ },
+ 10: {
+ in: "HEAD / HTTP/1.1\r\nContent-Length:0\r\nContent-Length: 0\r\n\r\n",
+ header: Header{"Content-Length": {"0"}},
+ },
}
func TestReadRequestErrors(t *testing.T) {
for i, tt := range readRequestErrorTests {
- _, err := ReadRequest(bufio.NewReader(strings.NewReader(tt.in)))
- if err != tt.err {
- t.Errorf("%d. got error = %v; want %v", i, err, tt.err)
+ req, err := ReadRequest(bufio.NewReader(strings.NewReader(tt.in)))
+ if err == nil {
+ if tt.err != "" {
+ t.Errorf("#%d: got nil err; want %q", i, tt.err)
+ }
+
+ if !reflect.DeepEqual(tt.header, req.Header) {
+ t.Errorf("#%d: gotHeader: %q wantHeader: %q", i, req.Header, tt.header)
+ }
+ continue
+ }
+
+ if tt.err == "" || !strings.Contains(err.Error(), tt.err) {
+ t.Errorf("%d: got error = %v; want %v", i, err, tt.err)
}
}
}
@@ -456,18 +497,23 @@ func TestNewRequestContentLength(t *testing.T) {
{bytes.NewReader([]byte("123")), 3},
{bytes.NewBuffer([]byte("1234")), 4},
{strings.NewReader("12345"), 5},
- // Not detected:
+ {strings.NewReader(""), 0},
+ {NoBody, 0},
+
+ // Not detected. During Go 1.8 we tried to make these set to -1, but
+ // due to Issue 18117, we keep these returning 0, even though they're
+ // unknown.
{struct{ io.Reader }{strings.NewReader("xyz")}, 0},
{io.NewSectionReader(strings.NewReader("x"), 0, 6), 0},
{readByte(io.NewSectionReader(strings.NewReader("xy"), 0, 6)), 0},
}
- for _, tt := range tests {
+ for i, tt := range tests {
req, err := NewRequest("POST", "http://localhost/", tt.r)
if err != nil {
t.Fatal(err)
}
if req.ContentLength != tt.want {
- t.Errorf("ContentLength(%T) = %d; want %d", tt.r, req.ContentLength, tt.want)
+ t.Errorf("test[%d]: ContentLength(%T) = %d; want %d", i, tt.r, req.ContentLength, tt.want)
}
}
}
@@ -626,11 +672,31 @@ func TestStarRequest(t *testing.T) {
if err != nil {
return
}
+ if req.ContentLength != 0 {
+ t.Errorf("ContentLength = %d; want 0", req.ContentLength)
+ }
+ if req.Body == nil {
+ t.Errorf("Body = nil; want non-nil")
+ }
+
+ // Request.Write has Client semantics for Body/ContentLength,
+ // where ContentLength 0 means unknown if Body is non-nil, and
+ // thus chunking will happen unless we change semantics and
+ // signal that we want to serialize it as exactly zero. The
+ // only way to do that for outbound requests is with a nil
+ // Body:
+ clientReq := *req
+ clientReq.Body = nil
+
var out bytes.Buffer
- if err := req.Write(&out); err != nil {
+ if err := clientReq.Write(&out); err != nil {
t.Fatal(err)
}
- back, err := ReadRequest(bufio.NewReader(&out))
+
+ if strings.Contains(out.String(), "chunked") {
+ t.Error("wrote chunked request; want no body")
+ }
+ back, err := ReadRequest(bufio.NewReader(bytes.NewReader(out.Bytes())))
if err != nil {
t.Fatal(err)
}
@@ -719,6 +785,47 @@ func TestMaxBytesReaderStickyError(t *testing.T) {
}
}
+// verify that NewRequest sets Request.GetBody and that it works
+func TestNewRequestGetBody(t *testing.T) {
+ tests := []struct {
+ r io.Reader
+ }{
+ {r: strings.NewReader("hello")},
+ {r: bytes.NewReader([]byte("hello"))},
+ {r: bytes.NewBuffer([]byte("hello"))},
+ }
+ for i, tt := range tests {
+ req, err := NewRequest("POST", "http://foo.tld/", tt.r)
+ if err != nil {
+ t.Errorf("test[%d]: %v", i, err)
+ continue
+ }
+ if req.Body == nil {
+ t.Errorf("test[%d]: Body = nil", i)
+ continue
+ }
+ if req.GetBody == nil {
+ t.Errorf("test[%d]: GetBody = nil", i)
+ continue
+ }
+ slurp1, err := ioutil.ReadAll(req.Body)
+ if err != nil {
+ t.Errorf("test[%d]: ReadAll(Body) = %v", i, err)
+ }
+ newBody, err := req.GetBody()
+ if err != nil {
+ t.Errorf("test[%d]: GetBody = %v", i, err)
+ }
+ slurp2, err := ioutil.ReadAll(newBody)
+ if err != nil {
+ t.Errorf("test[%d]: ReadAll(GetBody()) = %v", i, err)
+ }
+ if string(slurp1) != string(slurp2) {
+ t.Errorf("test[%d]: Body %q != GetBody %q", i, slurp1, slurp2)
+ }
+ }
+}
+
func testMissingFile(t *testing.T, req *Request) {
f, fh, err := req.FormFile("missing")
if f != nil {
diff --git a/libgo/go/net/http/requestwrite_test.go b/libgo/go/net/http/requestwrite_test.go
index 2545f6f4c22..eb65b9f736f 100644
--- a/libgo/go/net/http/requestwrite_test.go
+++ b/libgo/go/net/http/requestwrite_test.go
@@ -5,14 +5,17 @@
package http
import (
+ "bufio"
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
+ "net"
"net/url"
"strings"
"testing"
+ "time"
)
type reqWriteTest struct {
@@ -28,7 +31,7 @@ type reqWriteTest struct {
var reqWriteTests = []reqWriteTest{
// HTTP/1.1 => chunked coding; no body; no trailer
- {
+ 0: {
Req: Request{
Method: "GET",
URL: &url.URL{
@@ -75,7 +78,7 @@ var reqWriteTests = []reqWriteTest{
"Proxy-Connection: keep-alive\r\n\r\n",
},
// HTTP/1.1 => chunked coding; body; empty trailer
- {
+ 1: {
Req: Request{
Method: "GET",
URL: &url.URL{
@@ -104,7 +107,7 @@ var reqWriteTests = []reqWriteTest{
chunk("abcdef") + chunk(""),
},
// HTTP/1.1 POST => chunked coding; body; empty trailer
- {
+ 2: {
Req: Request{
Method: "POST",
URL: &url.URL{
@@ -137,7 +140,7 @@ var reqWriteTests = []reqWriteTest{
},
// HTTP/1.1 POST with Content-Length, no chunking
- {
+ 3: {
Req: Request{
Method: "POST",
URL: &url.URL{
@@ -172,7 +175,7 @@ var reqWriteTests = []reqWriteTest{
},
// HTTP/1.1 POST with Content-Length in headers
- {
+ 4: {
Req: Request{
Method: "POST",
URL: mustParseURL("http://example.com/"),
@@ -201,7 +204,7 @@ var reqWriteTests = []reqWriteTest{
},
// default to HTTP/1.1
- {
+ 5: {
Req: Request{
Method: "GET",
URL: mustParseURL("/search"),
@@ -215,7 +218,7 @@ var reqWriteTests = []reqWriteTest{
},
// Request with a 0 ContentLength and a 0 byte body.
- {
+ 6: {
Req: Request{
Method: "POST",
URL: mustParseURL("/"),
@@ -227,9 +230,32 @@ var reqWriteTests = []reqWriteTest{
Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) },
- // RFC 2616 Section 14.13 says Content-Length should be specified
- // unless body is prohibited by the request method.
- // Also, nginx expects it for POST and PUT.
+ WantWrite: "POST / HTTP/1.1\r\n" +
+ "Host: example.com\r\n" +
+ "User-Agent: Go-http-client/1.1\r\n" +
+ "Transfer-Encoding: chunked\r\n" +
+ "\r\n0\r\n\r\n",
+
+ WantProxy: "POST / HTTP/1.1\r\n" +
+ "Host: example.com\r\n" +
+ "User-Agent: Go-http-client/1.1\r\n" +
+ "Transfer-Encoding: chunked\r\n" +
+ "\r\n0\r\n\r\n",
+ },
+
+ // Request with a 0 ContentLength and a nil body.
+ 7: {
+ Req: Request{
+ Method: "POST",
+ URL: mustParseURL("/"),
+ Host: "example.com",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ ContentLength: 0, // as if unset by user
+ },
+
+ Body: func() io.ReadCloser { return nil },
+
WantWrite: "POST / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
"User-Agent: Go-http-client/1.1\r\n" +
@@ -244,7 +270,7 @@ var reqWriteTests = []reqWriteTest{
},
// Request with a 0 ContentLength and a 1 byte body.
- {
+ 8: {
Req: Request{
Method: "POST",
URL: mustParseURL("/"),
@@ -270,7 +296,7 @@ var reqWriteTests = []reqWriteTest{
},
// Request with a ContentLength of 10 but a 5 byte body.
- {
+ 9: {
Req: Request{
Method: "POST",
URL: mustParseURL("/"),
@@ -284,7 +310,7 @@ var reqWriteTests = []reqWriteTest{
},
// Request with a ContentLength of 4 but an 8 byte body.
- {
+ 10: {
Req: Request{
Method: "POST",
URL: mustParseURL("/"),
@@ -298,7 +324,7 @@ var reqWriteTests = []reqWriteTest{
},
// Request with a 5 ContentLength and nil body.
- {
+ 11: {
Req: Request{
Method: "POST",
URL: mustParseURL("/"),
@@ -311,7 +337,7 @@ var reqWriteTests = []reqWriteTest{
},
// Request with a 0 ContentLength and a body with 1 byte content and an error.
- {
+ 12: {
Req: Request{
Method: "POST",
URL: mustParseURL("/"),
@@ -331,7 +357,7 @@ var reqWriteTests = []reqWriteTest{
},
// Request with a 0 ContentLength and a body without content and an error.
- {
+ 13: {
Req: Request{
Method: "POST",
URL: mustParseURL("/"),
@@ -352,7 +378,7 @@ var reqWriteTests = []reqWriteTest{
// Verify that DumpRequest preserves the HTTP version number, doesn't add a Host,
// and doesn't add a User-Agent.
- {
+ 14: {
Req: Request{
Method: "GET",
URL: mustParseURL("/foo"),
@@ -373,7 +399,7 @@ var reqWriteTests = []reqWriteTest{
// an empty Host header, and don't use
// Request.Header["Host"]. This is just testing that
// we don't change Go 1.0 behavior.
- {
+ 15: {
Req: Request{
Method: "GET",
Host: "",
@@ -395,7 +421,7 @@ var reqWriteTests = []reqWriteTest{
},
// Opaque test #1 from golang.org/issue/4860
- {
+ 16: {
Req: Request{
Method: "GET",
URL: &url.URL{
@@ -414,7 +440,7 @@ var reqWriteTests = []reqWriteTest{
},
// Opaque test #2 from golang.org/issue/4860
- {
+ 17: {
Req: Request{
Method: "GET",
URL: &url.URL{
@@ -433,7 +459,7 @@ var reqWriteTests = []reqWriteTest{
},
// Testing custom case in header keys. Issue 5022.
- {
+ 18: {
Req: Request{
Method: "GET",
URL: &url.URL{
@@ -457,7 +483,7 @@ var reqWriteTests = []reqWriteTest{
},
// Request with host header field; IPv6 address with zone identifier
- {
+ 19: {
Req: Request{
Method: "GET",
URL: &url.URL{
@@ -472,7 +498,7 @@ var reqWriteTests = []reqWriteTest{
},
// Request with optional host header field; IPv6 address with zone identifier
- {
+ 20: {
Req: Request{
Method: "GET",
URL: &url.URL{
@@ -543,6 +569,138 @@ func TestRequestWrite(t *testing.T) {
}
}
+func TestRequestWriteTransport(t *testing.T) {
+ t.Parallel()
+
+ matchSubstr := func(substr string) func(string) error {
+ return func(written string) error {
+ if !strings.Contains(written, substr) {
+ return fmt.Errorf("expected substring %q in request: %s", substr, written)
+ }
+ return nil
+ }
+ }
+
+ noContentLengthOrTransferEncoding := func(req string) error {
+ if strings.Contains(req, "Content-Length: ") {
+ return fmt.Errorf("unexpected Content-Length in request: %s", req)
+ }
+ if strings.Contains(req, "Transfer-Encoding: ") {
+ return fmt.Errorf("unexpected Transfer-Encoding in request: %s", req)
+ }
+ return nil
+ }
+
+ all := func(checks ...func(string) error) func(string) error {
+ return func(req string) error {
+ for _, c := range checks {
+ if err := c(req); err != nil {
+ return err
+ }
+ }
+ return nil
+ }
+ }
+
+ type testCase struct {
+ method string
+ clen int64 // ContentLength
+ body io.ReadCloser
+ want func(string) error
+
+ // optional:
+ init func(*testCase)
+ afterReqRead func()
+ }
+
+ tests := []testCase{
+ {
+ method: "GET",
+ want: noContentLengthOrTransferEncoding,
+ },
+ {
+ method: "GET",
+ body: ioutil.NopCloser(strings.NewReader("")),
+ want: noContentLengthOrTransferEncoding,
+ },
+ {
+ method: "GET",
+ clen: -1,
+ body: ioutil.NopCloser(strings.NewReader("")),
+ want: noContentLengthOrTransferEncoding,
+ },
+ // A GET with a body, with explicit content length:
+ {
+ method: "GET",
+ clen: 7,
+ body: ioutil.NopCloser(strings.NewReader("foobody")),
+ want: all(matchSubstr("Content-Length: 7"),
+ matchSubstr("foobody")),
+ },
+ // A GET with a body, sniffing the leading "f" from "foobody".
+ {
+ method: "GET",
+ clen: -1,
+ body: ioutil.NopCloser(strings.NewReader("foobody")),
+ want: all(matchSubstr("Transfer-Encoding: chunked"),
+ matchSubstr("\r\n1\r\nf\r\n"),
+ matchSubstr("oobody")),
+ },
+ // But a POST request is expected to have a body, so
+ // no sniffing happens:
+ {
+ method: "POST",
+ clen: -1,
+ body: ioutil.NopCloser(strings.NewReader("foobody")),
+ want: all(matchSubstr("Transfer-Encoding: chunked"),
+ matchSubstr("foobody")),
+ },
+ {
+ method: "POST",
+ clen: -1,
+ body: ioutil.NopCloser(strings.NewReader("")),
+ want: all(matchSubstr("Transfer-Encoding: chunked")),
+ },
+ // Verify that a blocking Request.Body doesn't block forever.
+ {
+ method: "GET",
+ clen: -1,
+ init: func(tt *testCase) {
+ pr, pw := io.Pipe()
+ tt.afterReqRead = func() {
+ pw.Close()
+ }
+ tt.body = ioutil.NopCloser(pr)
+ },
+ want: matchSubstr("Transfer-Encoding: chunked"),
+ },
+ }
+
+ for i, tt := range tests {
+ if tt.init != nil {
+ tt.init(&tt)
+ }
+ req := &Request{
+ Method: tt.method,
+ URL: &url.URL{
+ Scheme: "http",
+ Host: "example.com",
+ },
+ Header: make(Header),
+ ContentLength: tt.clen,
+ Body: tt.body,
+ }
+ got, err := dumpRequestOut(req, tt.afterReqRead)
+ if err != nil {
+ t.Errorf("test[%d]: %v", i, err)
+ continue
+ }
+ if err := tt.want(string(got)); err != nil {
+ t.Errorf("test[%d]: %v", i, err)
+ }
+ }
+}
+
type closeChecker struct {
io.Reader
closed bool
@@ -553,17 +711,19 @@ func (rc *closeChecker) Close() error {
return nil
}
-// TestRequestWriteClosesBody tests that Request.Write does close its request.Body.
+// TestRequestWriteClosesBody tests that Request.Write closes its request.Body.
// It also indirectly tests NewRequest and that it doesn't wrap an existing Closer
// inside a NopCloser, and that it serializes it correctly.
func TestRequestWriteClosesBody(t *testing.T) {
rc := &closeChecker{Reader: strings.NewReader("my body")}
- req, _ := NewRequest("POST", "http://foo.com/", rc)
- if req.ContentLength != 0 {
- t.Errorf("got req.ContentLength %d, want 0", req.ContentLength)
+ req, err := NewRequest("POST", "http://foo.com/", rc)
+ if err != nil {
+ t.Fatal(err)
}
buf := new(bytes.Buffer)
- req.Write(buf)
+ if err := req.Write(buf); err != nil {
+ t.Error(err)
+ }
if !rc.closed {
t.Error("body not closed after write")
}
@@ -571,12 +731,7 @@ func TestRequestWriteClosesBody(t *testing.T) {
"Host: foo.com\r\n" +
"User-Agent: Go-http-client/1.1\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
- // TODO: currently we don't buffer before chunking, so we get a
- // single "m" chunk before the other chunks, as this was the 1-byte
- // read from our MultiReader where we stitched the Body back together
- // after sniffing whether the Body was 0 bytes or not.
- chunk("m") +
- chunk("y body") +
+ chunk("my body") +
chunk("")
if buf.String() != expected {
t.Errorf("write:\n got: %s\nwant: %s", buf.String(), expected)
@@ -652,3 +807,76 @@ func TestRequestWriteError(t *testing.T) {
t.Fatalf("writeCalls constant is outdated in test")
}
}
+
+// dumpRequestOut is a modified copy of net/http/httputil.DumpRequestOut.
+// Unlike the original, this version doesn't mutate the req.Body and
+// try to restore it. It always dumps the whole body.
+// And it doesn't support https.
+func dumpRequestOut(req *Request, onReadHeaders func()) ([]byte, error) {
+
+ // Use the actual Transport code to record what we would send
+ // on the wire, but not using TCP. Use a Transport with a
+ // custom dialer that returns a fake net.Conn that waits
+ // for the full input (and recording it), and then responds
+ // with a dummy response.
+ var buf bytes.Buffer // records the output
+ pr, pw := io.Pipe()
+ defer pr.Close()
+ defer pw.Close()
+ dr := &delegateReader{c: make(chan io.Reader)}
+
+ t := &Transport{
+ Dial: func(net, addr string) (net.Conn, error) {
+ return &dumpConn{io.MultiWriter(&buf, pw), dr}, nil
+ },
+ }
+ defer t.CloseIdleConnections()
+
+ // Wait for the request before replying with a dummy response:
+ go func() {
+ req, err := ReadRequest(bufio.NewReader(pr))
+ if err == nil {
+ if onReadHeaders != nil {
+ onReadHeaders()
+ }
+ // Ensure all the body is read; otherwise
+ // we'll get a partial dump.
+ io.Copy(ioutil.Discard, req.Body)
+ req.Body.Close()
+ }
+ dr.c <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n")
+ }()
+
+ _, err := t.RoundTrip(req)
+ if err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// delegateReader is a reader that delegates to another reader,
+// once it arrives on a channel.
+type delegateReader struct {
+ c chan io.Reader
+ r io.Reader // nil until received from c
+}
+
+func (r *delegateReader) Read(p []byte) (int, error) {
+ if r.r == nil {
+ r.r = <-r.c
+ }
+ return r.r.Read(p)
+}
+
+// dumpConn is a net.Conn that writes to Writer and reads from Reader.
+type dumpConn struct {
+ io.Writer
+ io.Reader
+}
+
+func (c *dumpConn) Close() error { return nil }
+func (c *dumpConn) LocalAddr() net.Addr { return nil }
+func (c *dumpConn) RemoteAddr() net.Addr { return nil }
+func (c *dumpConn) SetDeadline(t time.Time) error { return nil }
+func (c *dumpConn) SetReadDeadline(t time.Time) error { return nil }
+func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil }
diff --git a/libgo/go/net/http/response.go b/libgo/go/net/http/response.go
index 5450d50c3ce..ae118fb386d 100644
--- a/libgo/go/net/http/response.go
+++ b/libgo/go/net/http/response.go
@@ -261,7 +261,7 @@ func (r *Response) Write(w io.Writer) error {
if n == 0 {
// Reset it to a known zero reader, in case underlying one
// is unhappy being read repeatedly.
- r1.Body = eofReader
+ r1.Body = NoBody
} else {
r1.ContentLength = -1
r1.Body = struct {
@@ -300,7 +300,7 @@ func (r *Response) Write(w io.Writer) error {
// contentLengthAlreadySent may have been already sent for
// POST/PUT requests, even if zero length. See Issue 8180.
contentLengthAlreadySent := tw.shouldSendContentLength()
- if r1.ContentLength == 0 && !chunked(r1.TransferEncoding) && !contentLengthAlreadySent {
+ if r1.ContentLength == 0 && !chunked(r1.TransferEncoding) && !contentLengthAlreadySent && bodyAllowedForStatus(r.StatusCode) {
if _, err := io.WriteString(w, "Content-Length: 0\r\n"); err != nil {
return err
}
diff --git a/libgo/go/net/http/response_test.go b/libgo/go/net/http/response_test.go
index 126da927355..660d51791b7 100644
--- a/libgo/go/net/http/response_test.go
+++ b/libgo/go/net/http/response_test.go
@@ -589,6 +589,7 @@ var readResponseCloseInMiddleTests = []struct {
// reading only part of its contents advances the read to the end of
// the request, right up until the next request.
func TestReadResponseCloseInMiddle(t *testing.T) {
+ t.Parallel()
for _, test := range readResponseCloseInMiddleTests {
fatalf := func(format string, args ...interface{}) {
args = append([]interface{}{test.chunked, test.compressed}, args...)
@@ -792,6 +793,7 @@ func TestReadResponseErrors(t *testing.T) {
type testCase struct {
name string // optional, defaults to in
in string
+ header Header
wantErr interface{} // nil, err value, or string substring
}
@@ -817,11 +819,22 @@ func TestReadResponseErrors(t *testing.T) {
}
}
+ contentLength := func(status, body string, wantErr interface{}, header Header) testCase {
+ return testCase{
+ name: fmt.Sprintf("status %q %q", status, body),
+ in: fmt.Sprintf("HTTP/1.1 %s\r\n%s", status, body),
+ wantErr: wantErr,
+ header: header,
+ }
+ }
+
+ errMultiCL := "message cannot contain multiple Content-Length headers"
+
tests := []testCase{
- {"", "", io.ErrUnexpectedEOF},
- {"", "HTTP/1.1 301 Moved Permanently\r\nFoo: bar", io.ErrUnexpectedEOF},
- {"", "HTTP/1.1", "malformed HTTP response"},
- {"", "HTTP/2.0", "malformed HTTP response"},
+ {"", "", nil, io.ErrUnexpectedEOF},
+ {"", "HTTP/1.1 301 Moved Permanently\r\nFoo: bar", nil, io.ErrUnexpectedEOF},
+ {"", "HTTP/1.1", nil, "malformed HTTP response"},
+ {"", "HTTP/2.0", nil, "malformed HTTP response"},
status("20X Unknown", true),
status("abcd Unknown", true),
status("二百/两百 OK", true),
@@ -846,7 +859,21 @@ func TestReadResponseErrors(t *testing.T) {
version("HTTP/A.B", true),
version("HTTP/1", true),
version("http/1.1", true),
+
+ contentLength("200 OK", "Content-Length: 10\r\nContent-Length: 7\r\n\r\nGopher hey\r\n", errMultiCL, nil),
+ contentLength("200 OK", "Content-Length: 7\r\nContent-Length: 7\r\n\r\nGophers\r\n", nil, Header{"Content-Length": {"7"}}),
+ contentLength("201 OK", "Content-Length: 0\r\nContent-Length: 7\r\n\r\nGophers\r\n", errMultiCL, nil),
+ contentLength("300 OK", "Content-Length: 0\r\nContent-Length: 0 \r\n\r\nGophers\r\n", nil, Header{"Content-Length": {"0"}}),
+ contentLength("200 OK", "Content-Length:\r\nContent-Length:\r\n\r\nGophers\r\n", nil, nil),
+ contentLength("206 OK", "Content-Length:\r\nContent-Length: 0 \r\nConnection: close\r\n\r\nGophers\r\n", errMultiCL, nil),
+
+ // multiple content-length headers for 204 and 304 should still be checked
+ contentLength("204 OK", "Content-Length: 7\r\nContent-Length: 8\r\n\r\n", errMultiCL, nil),
+ contentLength("204 OK", "Content-Length: 3\r\nContent-Length: 3\r\n\r\n", nil, nil),
+ contentLength("304 OK", "Content-Length: 880\r\nContent-Length: 1\r\n\r\n", errMultiCL, nil),
+ contentLength("304 OK", "Content-Length: 961\r\nContent-Length: 961\r\n\r\n", nil, nil),
}
+
for i, tt := range tests {
br := bufio.NewReader(strings.NewReader(tt.in))
_, rerr := ReadResponse(br, nil)
diff --git a/libgo/go/net/http/responsewrite_test.go b/libgo/go/net/http/responsewrite_test.go
index 90f6767d96b..d41d89896ef 100644
--- a/libgo/go/net/http/responsewrite_test.go
+++ b/libgo/go/net/http/responsewrite_test.go
@@ -241,7 +241,8 @@ func TestResponseWrite(t *testing.T) {
"HTTP/1.0 007 license to violate specs\r\nContent-Length: 0\r\n\r\n",
},
- // No stutter.
+ // No stutter. Status code in 1xx range response should
+ // not include a Content-Length header. See issue #16942.
{
Response{
StatusCode: 123,
@@ -253,7 +254,23 @@ func TestResponseWrite(t *testing.T) {
Body: nil,
},
- "HTTP/1.0 123 Sesame Street\r\nContent-Length: 0\r\n\r\n",
+ "HTTP/1.0 123 Sesame Street\r\n\r\n",
+ },
+
+ // Status code 204 (No content) response should not include a
+ // Content-Length header. See issue #16942.
+ {
+ Response{
+ StatusCode: 204,
+ Status: "No Content",
+ ProtoMajor: 1,
+ ProtoMinor: 0,
+ Request: dummyReq("GET"),
+ Header: Header{},
+ Body: nil,
+ },
+
+ "HTTP/1.0 204 No Content\r\n\r\n",
},
}
diff --git a/libgo/go/net/http/serve_test.go b/libgo/go/net/http/serve_test.go
index 13e5f283e4c..072da2552bc 100644
--- a/libgo/go/net/http/serve_test.go
+++ b/libgo/go/net/http/serve_test.go
@@ -156,6 +156,7 @@ func (ht handlerTest) rawResponse(req string) string {
}
func TestConsumingBodyOnNextConn(t *testing.T) {
+ t.Parallel()
defer afterTest(t)
conn := new(testConn)
for i := 0; i < 2; i++ {
@@ -237,6 +238,7 @@ var vtests = []struct {
}
func TestHostHandlers(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
mux := NewServeMux()
for _, h := range handlers {
@@ -353,6 +355,7 @@ var serveMuxTests = []struct {
}
func TestServeMuxHandler(t *testing.T) {
+ setParallel(t)
mux := NewServeMux()
for _, e := range serveMuxRegister {
mux.Handle(e.pattern, e.h)
@@ -390,15 +393,16 @@ var serveMuxTests2 = []struct {
// TestServeMuxHandlerRedirects tests that automatic redirects generated by
// mux.Handler() shouldn't clear the request's query string.
func TestServeMuxHandlerRedirects(t *testing.T) {
+ setParallel(t)
mux := NewServeMux()
for _, e := range serveMuxRegister {
mux.Handle(e.pattern, e.h)
}
for _, tt := range serveMuxTests2 {
- tries := 1
+ tries := 1 // expect at most 1 redirection if redirOk is true.
turl := tt.url
- for tries > 0 {
+ for {
u, e := url.Parse(turl)
if e != nil {
t.Fatal(e)
@@ -432,6 +436,7 @@ func TestServeMuxHandlerRedirects(t *testing.T) {
// Tests for https://golang.org/issue/900
func TestMuxRedirectLeadingSlashes(t *testing.T) {
+ setParallel(t)
paths := []string{"//foo.txt", "///foo.txt", "/../../foo.txt"}
for _, path := range paths {
req, err := ReadRequest(bufio.NewReader(strings.NewReader("GET " + path + " HTTP/1.1\r\nHost: test\r\n\r\n")))
@@ -456,9 +461,6 @@ func TestMuxRedirectLeadingSlashes(t *testing.T) {
}
func TestServerTimeouts(t *testing.T) {
- if runtime.GOOS == "plan9" {
- t.Skip("skipping test; see https://golang.org/issue/7237")
- }
setParallel(t)
defer afterTest(t)
reqNum := 0
@@ -479,11 +481,11 @@ func TestServerTimeouts(t *testing.T) {
if err != nil {
t.Fatalf("http Get #1: %v", err)
}
- got, _ := ioutil.ReadAll(r.Body)
+ got, err := ioutil.ReadAll(r.Body)
expected := "req=1"
- if string(got) != expected {
- t.Errorf("Unexpected response for request #1; got %q; expected %q",
- string(got), expected)
+ if string(got) != expected || err != nil {
+ t.Errorf("Unexpected response for request #1; got %q ,%v; expected %q, nil",
+ string(got), err, expected)
}
// Slow client that should timeout.
@@ -494,6 +496,7 @@ func TestServerTimeouts(t *testing.T) {
}
buf := make([]byte, 1)
n, err := conn.Read(buf)
+ conn.Close()
latency := time.Since(t1)
if n != 0 || err != io.EOF {
t.Errorf("Read = %v, %v, wanted %v, %v", n, err, 0, io.EOF)
@@ -505,14 +508,14 @@ func TestServerTimeouts(t *testing.T) {
// Hit the HTTP server successfully again, verifying that the
// previous slow connection didn't run our handler. (that we
// get "req=2", not "req=3")
- r, err = Get(ts.URL)
+ r, err = c.Get(ts.URL)
if err != nil {
t.Fatalf("http Get #2: %v", err)
}
- got, _ = ioutil.ReadAll(r.Body)
+ got, err = ioutil.ReadAll(r.Body)
expected = "req=2"
- if string(got) != expected {
- t.Errorf("Get #2 got %q, want %q", string(got), expected)
+ if string(got) != expected || err != nil {
+ t.Errorf("Get #2 got %q, %v, want %q, nil", string(got), err, expected)
}
if !testing.Short() {
@@ -532,13 +535,61 @@ func TestServerTimeouts(t *testing.T) {
}
}
+// Test that the HTTP/2 server handles Server.WriteTimeout (Issue 18437)
+func TestHTTP2WriteDeadlineExtendedOnNewRequest(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in short mode")
+ }
+ setParallel(t)
+ defer afterTest(t)
+ ts := httptest.NewUnstartedServer(HandlerFunc(func(res ResponseWriter, req *Request) {}))
+ ts.Config.WriteTimeout = 250 * time.Millisecond
+ ts.TLS = &tls.Config{NextProtos: []string{"h2"}}
+ ts.StartTLS()
+ defer ts.Close()
+
+ tr := newTLSTransport(t, ts)
+ defer tr.CloseIdleConnections()
+ if err := ExportHttp2ConfigureTransport(tr); err != nil {
+ t.Fatal(err)
+ }
+ c := &Client{Transport: tr}
+
+ for i := 1; i <= 3; i++ {
+ req, err := NewRequest("GET", ts.URL, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // fail test if no response after 1 second
+ ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
+ defer cancel()
+ req = req.WithContext(ctx)
+
+ r, err := c.Do(req)
+ select {
+ case <-ctx.Done():
+ if ctx.Err() == context.DeadlineExceeded {
+ t.Fatalf("http2 Get #%d response timed out", i)
+ }
+ default:
+ }
+ if err != nil {
+ t.Fatalf("http2 Get #%d: %v", i, err)
+ }
+ r.Body.Close()
+ if r.ProtoMajor != 2 {
+ t.Fatalf("http2 Get expected HTTP/2.0, got %q", r.Proto)
+ }
+ time.Sleep(ts.Config.WriteTimeout / 2)
+ }
+}
+
// golang.org/issue/4741 -- setting only a write timeout that triggers
// shouldn't cause a handler to block forever on reads (next HTTP
// request) that will never happen.
func TestOnlyWriteTimeout(t *testing.T) {
- if runtime.GOOS == "plan9" {
- t.Skip("skipping test; see https://golang.org/issue/7237")
- }
+ setParallel(t)
defer afterTest(t)
var conn net.Conn
var afterTimeoutErrc = make(chan error, 1)
@@ -598,6 +649,7 @@ func (l trackLastConnListener) Accept() (c net.Conn, err error) {
// TestIdentityResponse verifies that a handler can unset
func TestIdentityResponse(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
rw.Header().Set("Content-Length", "3")
@@ -619,13 +671,16 @@ func TestIdentityResponse(t *testing.T) {
ts := httptest.NewServer(handler)
defer ts.Close()
+ c := &Client{Transport: new(Transport)}
+ defer closeClient(c)
+
// Note: this relies on the assumption (which is true) that
// Get sends HTTP/1.1 or greater requests. Otherwise the
// server wouldn't have the choice to send back chunked
// responses.
for _, te := range []string{"", "identity"} {
url := ts.URL + "/?te=" + te
- res, err := Get(url)
+ res, err := c.Get(url)
if err != nil {
t.Fatalf("error with Get of %s: %v", url, err)
}
@@ -644,7 +699,7 @@ func TestIdentityResponse(t *testing.T) {
// Verify that ErrContentLength is returned
url := ts.URL + "/?overwrite=1"
- res, err := Get(url)
+ res, err := c.Get(url)
if err != nil {
t.Fatalf("error with Get of %s: %v", url, err)
}
@@ -674,6 +729,7 @@ func TestIdentityResponse(t *testing.T) {
}
func testTCPConnectionCloses(t *testing.T, req string, h Handler) {
+ setParallel(t)
defer afterTest(t)
s := httptest.NewServer(h)
defer s.Close()
@@ -717,6 +773,7 @@ func testTCPConnectionCloses(t *testing.T, req string, h Handler) {
}
func testTCPConnectionStaysOpen(t *testing.T, req string, handler Handler) {
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewServer(handler)
defer ts.Close()
@@ -750,7 +807,7 @@ func TestServeHTTP10Close(t *testing.T) {
// TestClientCanClose verifies that clients can also force a connection to close.
func TestClientCanClose(t *testing.T) {
- testTCPConnectionCloses(t, "GET / HTTP/1.1\r\nConnection: close\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+ testTCPConnectionCloses(t, "GET / HTTP/1.1\r\nHost: foo\r\nConnection: close\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
// Nothing.
}))
}
@@ -758,7 +815,7 @@ func TestClientCanClose(t *testing.T) {
// TestHandlersCanSetConnectionClose verifies that handlers can force a connection to close,
// even for HTTP/1.1 requests.
func TestHandlersCanSetConnectionClose11(t *testing.T) {
- testTCPConnectionCloses(t, "GET / HTTP/1.1\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
+ testTCPConnectionCloses(t, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n\r\n", HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("Connection", "close")
}))
}
@@ -796,6 +853,7 @@ func TestHTTP10KeepAlive304Response(t *testing.T) {
// Issue 15703
func TestKeepAliveFinalChunkWithEOF(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, false /* h1 */, HandlerFunc(func(w ResponseWriter, r *Request) {
w.(Flusher).Flush() // force chunked encoding
@@ -828,6 +886,7 @@ func TestSetsRemoteAddr_h1(t *testing.T) { testSetsRemoteAddr(t, h1Mode) }
func TestSetsRemoteAddr_h2(t *testing.T) { testSetsRemoteAddr(t, h2Mode) }
func testSetsRemoteAddr(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "%s", r.RemoteAddr)
@@ -877,6 +936,7 @@ func (c *blockingRemoteAddrConn) RemoteAddr() net.Addr {
// Issue 12943
func TestServerAllowsBlockingRemoteAddr(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
fmt.Fprintf(w, "RA:%s", r.RemoteAddr)
@@ -948,7 +1008,9 @@ func TestServerAllowsBlockingRemoteAddr(t *testing.T) {
t.Fatalf("response 1 addr = %q; want %q", g, e)
}
}
+
func TestIdentityResponseHeaders(t *testing.T) {
+ // Not parallel; changes log output.
defer afterTest(t)
log.SetOutput(ioutil.Discard) // is noisy otherwise
defer log.SetOutput(os.Stderr)
@@ -960,7 +1022,10 @@ func TestIdentityResponseHeaders(t *testing.T) {
}))
defer ts.Close()
- res, err := Get(ts.URL)
+ c := &Client{Transport: new(Transport)}
+ defer closeClient(c)
+
+ res, err := c.Get(ts.URL)
if err != nil {
t.Fatalf("Get error: %v", err)
}
@@ -983,6 +1048,7 @@ func TestHeadResponses_h1(t *testing.T) { testHeadResponses(t, h1Mode) }
func TestHeadResponses_h2(t *testing.T) { testHeadResponses(t, h2Mode) }
func testHeadResponses(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
_, err := w.Write([]byte("<html>"))
@@ -1020,9 +1086,6 @@ func testHeadResponses(t *testing.T, h2 bool) {
}
func TestTLSHandshakeTimeout(t *testing.T) {
- if runtime.GOOS == "plan9" {
- t.Skip("skipping test; see https://golang.org/issue/7237")
- }
setParallel(t)
defer afterTest(t)
ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
@@ -1054,6 +1117,7 @@ func TestTLSHandshakeTimeout(t *testing.T) {
}
func TestTLSServer(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if r.TLS != nil {
@@ -1121,6 +1185,7 @@ func TestAutomaticHTTP2_Serve_H2TLSConfig(t *testing.T) {
}
func testAutomaticHTTP2_Serve(t *testing.T, tlsConf *tls.Config, wantH2 bool) {
+ setParallel(t)
defer afterTest(t)
ln := newLocalListener(t)
ln.Close() // immediately (not a defer!)
@@ -1136,6 +1201,7 @@ func testAutomaticHTTP2_Serve(t *testing.T, tlsConf *tls.Config, wantH2 bool) {
}
func TestAutomaticHTTP2_Serve_WithTLSConfig(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ln := newLocalListener(t)
ln.Close() // immediately (not a defer!)
@@ -1177,6 +1243,7 @@ func TestAutomaticHTTP2_ListenAndServe_GetCertificate(t *testing.T) {
}
func testAutomaticHTTP2_ListenAndServe(t *testing.T, tlsConf *tls.Config) {
+ // Not parallel: uses global test hooks.
defer afterTest(t)
defer SetTestHookServerServe(nil)
var ok bool
@@ -1280,6 +1347,7 @@ var serverExpectTests = []serverExpectTest{
// correctly.
// http2 test: TestServer_Response_Automatic100Continue
func TestServerExpect(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
// Note using r.FormValue("readbody") because for POST
@@ -1373,6 +1441,7 @@ func TestServerExpect(t *testing.T) {
// Under a ~256KB (maxPostHandlerReadBytes) threshold, the server
// should consume client request bodies that a handler didn't read.
func TestServerUnreadRequestBodyLittle(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
conn := new(testConn)
body := strings.Repeat("x", 100<<10)
@@ -1413,6 +1482,7 @@ func TestServerUnreadRequestBodyLittle(t *testing.T) {
// should ignore client request bodies that a handler didn't read
// and close the connection.
func TestServerUnreadRequestBodyLarge(t *testing.T) {
+ setParallel(t)
if testing.Short() && testenv.Builder() == "" {
t.Log("skipping in short mode")
}
@@ -1546,6 +1616,7 @@ var handlerBodyCloseTests = [...]handlerBodyCloseTest{
}
func TestHandlerBodyClose(t *testing.T) {
+ setParallel(t)
if testing.Short() && testenv.Builder() == "" {
t.Skip("skipping in -short mode")
}
@@ -1625,6 +1696,7 @@ var testHandlerBodyConsumers = []testHandlerBodyConsumer{
}
func TestRequestBodyReadErrorClosesConnection(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
for _, handler := range testHandlerBodyConsumers {
conn := new(testConn)
@@ -1655,6 +1727,7 @@ func TestRequestBodyReadErrorClosesConnection(t *testing.T) {
}
func TestInvalidTrailerClosesConnection(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
for _, handler := range testHandlerBodyConsumers {
conn := new(testConn)
@@ -1737,7 +1810,7 @@ restart:
if !c.rd.IsZero() {
// If the deadline falls in the middle of our sleep window, deduct
// part of the sleep, then return a timeout.
- if remaining := c.rd.Sub(time.Now()); remaining < cue {
+ if remaining := time.Until(c.rd); remaining < cue {
c.script[0] = cue - remaining
time.Sleep(remaining)
return 0, syscall.ETIMEDOUT
@@ -1823,6 +1896,7 @@ func TestRequestBodyTimeoutClosesConnection(t *testing.T) {
func TestTimeoutHandler_h1(t *testing.T) { testTimeoutHandler(t, h1Mode) }
func TestTimeoutHandler_h2(t *testing.T) { testTimeoutHandler(t, h2Mode) }
func testTimeoutHandler(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
sendHi := make(chan bool, 1)
writeErrors := make(chan error, 1)
@@ -1876,6 +1950,7 @@ func testTimeoutHandler(t *testing.T, h2 bool) {
// See issues 8209 and 8414.
func TestTimeoutHandlerRace(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
delayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -1892,6 +1967,9 @@ func TestTimeoutHandlerRace(t *testing.T) {
ts := httptest.NewServer(TimeoutHandler(delayHi, 20*time.Millisecond, ""))
defer ts.Close()
+ c := &Client{Transport: new(Transport)}
+ defer closeClient(c)
+
var wg sync.WaitGroup
gate := make(chan bool, 10)
n := 50
@@ -1905,7 +1983,7 @@ func TestTimeoutHandlerRace(t *testing.T) {
go func() {
defer wg.Done()
defer func() { <-gate }()
- res, err := Get(fmt.Sprintf("%s/%d", ts.URL, rand.Intn(50)))
+ res, err := c.Get(fmt.Sprintf("%s/%d", ts.URL, rand.Intn(50)))
if err == nil {
io.Copy(ioutil.Discard, res.Body)
res.Body.Close()
@@ -1917,6 +1995,7 @@ func TestTimeoutHandlerRace(t *testing.T) {
// See issues 8209 and 8414.
func TestTimeoutHandlerRaceHeader(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
delay204 := HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -1932,13 +2011,15 @@ func TestTimeoutHandlerRaceHeader(t *testing.T) {
if testing.Short() {
n = 10
}
+ c := &Client{Transport: new(Transport)}
+ defer closeClient(c)
for i := 0; i < n; i++ {
gate <- true
wg.Add(1)
go func() {
defer wg.Done()
defer func() { <-gate }()
- res, err := Get(ts.URL)
+ res, err := c.Get(ts.URL)
if err != nil {
t.Error(err)
return
@@ -1952,6 +2033,7 @@ func TestTimeoutHandlerRaceHeader(t *testing.T) {
// Issue 9162
func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
sendHi := make(chan bool, 1)
writeErrors := make(chan error, 1)
@@ -2016,11 +2098,15 @@ func TestTimeoutHandlerStartTimerWhenServing(t *testing.T) {
timeout := 300 * time.Millisecond
ts := httptest.NewServer(TimeoutHandler(handler, timeout, ""))
defer ts.Close()
+
+ c := &Client{Transport: new(Transport)}
+ defer closeClient(c)
+
// Issue was caused by the timeout handler starting the timer when
// was created, not when the request. So wait for more than the timeout
// to ensure that's not the case.
time.Sleep(2 * timeout)
- res, err := Get(ts.URL)
+ res, err := c.Get(ts.URL)
if err != nil {
t.Fatal(err)
}
@@ -2032,6 +2118,7 @@ func TestTimeoutHandlerStartTimerWhenServing(t *testing.T) {
// https://golang.org/issue/15948
func TestTimeoutHandlerEmptyResponse(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
var handler HandlerFunc = func(w ResponseWriter, _ *Request) {
// No response.
@@ -2040,7 +2127,10 @@ func TestTimeoutHandlerEmptyResponse(t *testing.T) {
ts := httptest.NewServer(TimeoutHandler(handler, timeout, ""))
defer ts.Close()
- res, err := Get(ts.URL)
+ c := &Client{Transport: new(Transport)}
+ defer closeClient(c)
+
+ res, err := c.Get(ts.URL)
if err != nil {
t.Fatal(err)
}
@@ -2050,23 +2140,6 @@ func TestTimeoutHandlerEmptyResponse(t *testing.T) {
}
}
-// Verifies we don't path.Clean() on the wrong parts in redirects.
-func TestRedirectMunging(t *testing.T) {
- req, _ := NewRequest("GET", "http://example.com/", nil)
-
- resp := httptest.NewRecorder()
- Redirect(resp, req, "/foo?next=http://bar.com/", 302)
- if g, e := resp.Header().Get("Location"), "/foo?next=http://bar.com/"; g != e {
- t.Errorf("Location header was %q; want %q", g, e)
- }
-
- resp = httptest.NewRecorder()
- Redirect(resp, req, "http://localhost:8080/_ah/login?continue=http://localhost:8080/", 302)
- if g, e := resp.Header().Get("Location"), "http://localhost:8080/_ah/login?continue=http://localhost:8080/"; g != e {
- t.Errorf("Location header was %q; want %q", g, e)
- }
-}
-
func TestRedirectBadPath(t *testing.T) {
// This used to crash. It's not valid input (bad path), but it
// shouldn't crash.
@@ -2085,7 +2158,7 @@ func TestRedirectBadPath(t *testing.T) {
}
// Test different URL formats and schemes
-func TestRedirectURLFormat(t *testing.T) {
+func TestRedirect(t *testing.T) {
req, _ := NewRequest("GET", "http://example.com/qux/", nil)
var tests = []struct {
@@ -2108,6 +2181,14 @@ func TestRedirectURLFormat(t *testing.T) {
{"../quux/foobar.com/baz", "/quux/foobar.com/baz"},
// incorrect number of slashes
{"///foobar.com/baz", "/foobar.com/baz"},
+
+ // Verifies we don't path.Clean() on the wrong parts in redirects:
+ {"/foo?next=http://bar.com/", "/foo?next=http://bar.com/"},
+ {"http://localhost:8080/_ah/login?continue=http://localhost:8080/",
+ "http://localhost:8080/_ah/login?continue=http://localhost:8080/"},
+
+ {"/фубар", "/%d1%84%d1%83%d0%b1%d0%b0%d1%80"},
+ {"http://foo.com/фубар", "http://foo.com/%d1%84%d1%83%d0%b1%d0%b0%d1%80"},
}
for _, tt := range tests {
@@ -2133,6 +2214,7 @@ func TestZeroLengthPostAndResponse_h2(t *testing.T) {
}
func testZeroLengthPostAndResponse(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, r *Request) {
all, err := ioutil.ReadAll(r.Body)
@@ -2252,12 +2334,58 @@ func testHandlerPanic(t *testing.T, withHijack, h2 bool, panicValue interface{})
}
}
+type terrorWriter struct{ t *testing.T }
+
+func (w terrorWriter) Write(p []byte) (int, error) {
+ w.t.Errorf("%s", p)
+ return len(p), nil
+}
+
+// Issue 16456: allow writing 0 bytes on hijacked conn to test hijack
+// without any log spam.
+func TestServerWriteHijackZeroBytes(t *testing.T) {
+ defer afterTest(t)
+ done := make(chan struct{})
+ ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ defer close(done)
+ w.(Flusher).Flush()
+ conn, _, err := w.(Hijacker).Hijack()
+ if err != nil {
+ t.Errorf("Hijack: %v", err)
+ return
+ }
+ defer conn.Close()
+ _, err = w.Write(nil)
+ if err != ErrHijacked {
+ t.Errorf("Write error = %v; want ErrHijacked", err)
+ }
+ }))
+ ts.Config.ErrorLog = log.New(terrorWriter{t}, "Unexpected write: ", 0)
+ ts.Start()
+ defer ts.Close()
+
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+ c := &Client{Transport: tr}
+ res, err := c.Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+ select {
+ case <-done:
+ case <-time.After(5 * time.Second):
+ t.Fatal("timeout")
+ }
+}
+
func TestServerNoDate_h1(t *testing.T) { testServerNoHeader(t, h1Mode, "Date") }
func TestServerNoDate_h2(t *testing.T) { testServerNoHeader(t, h2Mode, "Date") }
func TestServerNoContentType_h1(t *testing.T) { testServerNoHeader(t, h1Mode, "Content-Type") }
func TestServerNoContentType_h2(t *testing.T) { testServerNoHeader(t, h2Mode, "Content-Type") }
func testServerNoHeader(t *testing.T, h2 bool, header string) {
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header()[header] = nil
@@ -2275,6 +2403,7 @@ func testServerNoHeader(t *testing.T, h2 bool, header string) {
}
func TestStripPrefix(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
h := HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("X-Path", r.URL.Path)
@@ -2282,7 +2411,10 @@ func TestStripPrefix(t *testing.T) {
ts := httptest.NewServer(StripPrefix("/foo", h))
defer ts.Close()
- res, err := Get(ts.URL + "/foo/bar")
+ c := &Client{Transport: new(Transport)}
+ defer closeClient(c)
+
+ res, err := c.Get(ts.URL + "/foo/bar")
if err != nil {
t.Fatal(err)
}
@@ -2304,10 +2436,11 @@ func TestStripPrefix(t *testing.T) {
func TestRequestLimit_h1(t *testing.T) { testRequestLimit(t, h1Mode) }
func TestRequestLimit_h2(t *testing.T) { testRequestLimit(t, h2Mode) }
func testRequestLimit(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
t.Fatalf("didn't expect to get request in Handler")
- }))
+ }), optQuietLog)
defer cst.close()
req, _ := NewRequest("GET", cst.ts.URL, nil)
var bytesPerHeader = len("header12345: val12345\r\n")
@@ -2350,6 +2483,7 @@ func (cr countReader) Read(p []byte) (n int, err error) {
func TestRequestBodyLimit_h1(t *testing.T) { testRequestBodyLimit(t, h1Mode) }
func TestRequestBodyLimit_h2(t *testing.T) { testRequestBodyLimit(t, h2Mode) }
func testRequestBodyLimit(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
const limit = 1 << 20
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -2399,14 +2533,14 @@ func TestClientWriteShutdown(t *testing.T) {
}
err = conn.(*net.TCPConn).CloseWrite()
if err != nil {
- t.Fatalf("Dial: %v", err)
+ t.Fatalf("CloseWrite: %v", err)
}
donec := make(chan bool)
go func() {
defer close(donec)
bs, err := ioutil.ReadAll(conn)
if err != nil {
- t.Fatalf("ReadAll: %v", err)
+ t.Errorf("ReadAll: %v", err)
}
got := string(bs)
if got != "" {
@@ -2445,6 +2579,7 @@ func TestServerBufferedChunking(t *testing.T) {
// closing the TCP connection, causing the client to get a RST.
// See https://golang.org/issue/3595
func TestServerGracefulClose(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
Error(w, "bye", StatusUnauthorized)
@@ -2557,7 +2692,8 @@ func TestCloseNotifier(t *testing.T) {
go func() {
_, err = fmt.Fprintf(conn, "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n")
if err != nil {
- t.Fatal(err)
+ t.Error(err)
+ return
}
<-diec
conn.Close()
@@ -2599,7 +2735,8 @@ func TestCloseNotifierPipelined(t *testing.T) {
const req = "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n"
_, err = io.WriteString(conn, req+req) // two requests
if err != nil {
- t.Fatal(err)
+ t.Error(err)
+ return
}
<-diec
conn.Close()
@@ -2707,6 +2844,7 @@ func TestHijackAfterCloseNotifier(t *testing.T) {
}
func TestHijackBeforeRequestBodyRead(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
var requestBody = bytes.Repeat([]byte("a"), 1<<20)
bodyOkay := make(chan bool, 1)
@@ -3028,15 +3166,18 @@ func (l *errorListener) Addr() net.Addr {
}
func TestAcceptMaxFds(t *testing.T) {
- log.SetOutput(ioutil.Discard) // is noisy otherwise
- defer log.SetOutput(os.Stderr)
+ setParallel(t)
ln := &errorListener{[]error{
&net.OpError{
Op: "accept",
Err: syscall.EMFILE,
}}}
- err := Serve(ln, HandlerFunc(HandlerFunc(func(ResponseWriter, *Request) {})))
+ server := &Server{
+ Handler: HandlerFunc(HandlerFunc(func(ResponseWriter, *Request) {})),
+ ErrorLog: log.New(ioutil.Discard, "", 0), // noisy otherwise
+ }
+ err := server.Serve(ln)
if err != io.EOF {
t.Errorf("got error %v, want EOF", err)
}
@@ -3161,6 +3302,7 @@ func TestHTTP10ConnectionHeader(t *testing.T) {
func TestServerReaderFromOrder_h1(t *testing.T) { testServerReaderFromOrder(t, h1Mode) }
func TestServerReaderFromOrder_h2(t *testing.T) { testServerReaderFromOrder(t, h2Mode) }
func testServerReaderFromOrder(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
pr, pw := io.Pipe()
const size = 3 << 20
@@ -3265,6 +3407,7 @@ func TestTransportAndServerSharedBodyRace_h2(t *testing.T) {
testTransportAndServerSharedBodyRace(t, h2Mode)
}
func testTransportAndServerSharedBodyRace(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
const bodySize = 1 << 20
@@ -3453,6 +3596,7 @@ func TestAppendTime(t *testing.T) {
}
func TestServerConnState(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
handler := map[string]func(w ResponseWriter, r *Request){
"/": func(w ResponseWriter, r *Request) {
@@ -3500,14 +3644,39 @@ func TestServerConnState(t *testing.T) {
}
ts.Start()
- mustGet(t, ts.URL+"/")
- mustGet(t, ts.URL+"/close")
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+ c := &Client{Transport: tr}
+
+ mustGet := func(url string, headers ...string) {
+ req, err := NewRequest("GET", url, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for len(headers) > 0 {
+ req.Header.Add(headers[0], headers[1])
+ headers = headers[2:]
+ }
+ res, err := c.Do(req)
+ if err != nil {
+ t.Errorf("Error fetching %s: %v", url, err)
+ return
+ }
+ _, err = ioutil.ReadAll(res.Body)
+ defer res.Body.Close()
+ if err != nil {
+ t.Errorf("Error reading %s: %v", url, err)
+ }
+ }
+
+ mustGet(ts.URL + "/")
+ mustGet(ts.URL + "/close")
- mustGet(t, ts.URL+"/")
- mustGet(t, ts.URL+"/", "Connection", "close")
+ mustGet(ts.URL + "/")
+ mustGet(ts.URL+"/", "Connection", "close")
- mustGet(t, ts.URL+"/hijack")
- mustGet(t, ts.URL+"/hijack-panic")
+ mustGet(ts.URL + "/hijack")
+ mustGet(ts.URL + "/hijack-panic")
// New->Closed
{
@@ -3587,31 +3756,10 @@ func TestServerConnState(t *testing.T) {
}
mu.Lock()
- t.Errorf("Unexpected events.\nGot log: %s\n Want: %s\n", logString(stateLog), logString(want))
+ t.Errorf("Unexpected events.\nGot log:\n%s\n Want:\n%s\n", logString(stateLog), logString(want))
mu.Unlock()
}
-func mustGet(t *testing.T, url string, headers ...string) {
- req, err := NewRequest("GET", url, nil)
- if err != nil {
- t.Fatal(err)
- }
- for len(headers) > 0 {
- req.Header.Add(headers[0], headers[1])
- headers = headers[2:]
- }
- res, err := DefaultClient.Do(req)
- if err != nil {
- t.Errorf("Error fetching %s: %v", url, err)
- return
- }
- _, err = ioutil.ReadAll(res.Body)
- defer res.Body.Close()
- if err != nil {
- t.Errorf("Error reading %s: %v", url, err)
- }
-}
-
func TestServerKeepAlivesEnabled(t *testing.T) {
defer afterTest(t)
ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
@@ -3632,6 +3780,7 @@ func TestServerKeepAlivesEnabled(t *testing.T) {
func TestServerEmptyBodyRace_h1(t *testing.T) { testServerEmptyBodyRace(t, h1Mode) }
func TestServerEmptyBodyRace_h2(t *testing.T) { testServerEmptyBodyRace(t, h2Mode) }
func testServerEmptyBodyRace(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
var n int32
cst := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, req *Request) {
@@ -3695,6 +3844,7 @@ func (c *closeWriteTestConn) CloseWrite() error {
}
func TestCloseWrite(t *testing.T) {
+ setParallel(t)
var srv Server
var testConn closeWriteTestConn
c := ExportServerNewConn(&srv, &testConn)
@@ -3935,6 +4085,7 @@ Host: foo
// If a Handler finishes and there's an unread request body,
// verify the server try to do implicit read on it before replying.
func TestHandlerFinishSkipBigContentLengthRead(t *testing.T) {
+ setParallel(t)
conn := &testConn{closec: make(chan bool)}
conn.readBuf.Write([]byte(fmt.Sprintf(
"POST / HTTP/1.1\r\n" +
@@ -4033,7 +4184,11 @@ func TestServerValidatesHostHeader(t *testing.T) {
io.WriteString(&conn.readBuf, methodTarget+tt.proto+"\r\n"+tt.host+"\r\n")
ln := &oneConnListener{conn}
- go Serve(ln, HandlerFunc(func(ResponseWriter, *Request) {}))
+ srv := Server{
+ ErrorLog: quietLog,
+ Handler: HandlerFunc(func(ResponseWriter, *Request) {}),
+ }
+ go srv.Serve(ln)
<-conn.closec
res, err := ReadResponse(bufio.NewReader(&conn.writeBuf), nil)
if err != nil {
@@ -4088,6 +4243,7 @@ func TestServerHandlersCanHandleH2PRI(t *testing.T) {
// Test that we validate the valid bytes in HTTP/1 headers.
// Issue 11207.
func TestServerValidatesHeaders(t *testing.T) {
+ setParallel(t)
tests := []struct {
header string
want int
@@ -4097,9 +4253,10 @@ func TestServerValidatesHeaders(t *testing.T) {
{"X-Foo: bar\r\n", 200},
{"Foo: a space\r\n", 200},
- {"A space: foo\r\n", 400}, // space in header
- {"foo\xffbar: foo\r\n", 400}, // binary in header
- {"foo\x00bar: foo\r\n", 400}, // binary in header
+ {"A space: foo\r\n", 400}, // space in header
+ {"foo\xffbar: foo\r\n", 400}, // binary in header
+ {"foo\x00bar: foo\r\n", 400}, // binary in header
+ {"Foo: " + strings.Repeat("x", 1<<21) + "\r\n", 431}, // header too large
{"foo: foo foo\r\n", 200}, // LWS space is okay
{"foo: foo\tfoo\r\n", 200}, // LWS tab is okay
@@ -4112,7 +4269,11 @@ func TestServerValidatesHeaders(t *testing.T) {
io.WriteString(&conn.readBuf, "GET / HTTP/1.1\r\nHost: foo\r\n"+tt.header+"\r\n")
ln := &oneConnListener{conn}
- go Serve(ln, HandlerFunc(func(ResponseWriter, *Request) {}))
+ srv := Server{
+ ErrorLog: quietLog,
+ Handler: HandlerFunc(func(ResponseWriter, *Request) {}),
+ }
+ go srv.Serve(ln)
<-conn.closec
res, err := ReadResponse(bufio.NewReader(&conn.writeBuf), nil)
if err != nil {
@@ -4132,6 +4293,7 @@ func TestServerRequestContextCancel_ServeHTTPDone_h2(t *testing.T) {
testServerRequestContextCancel_ServeHTTPDone(t, h2Mode)
}
func testServerRequestContextCancel_ServeHTTPDone(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
ctxc := make(chan context.Context, 1)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -4157,13 +4319,12 @@ func testServerRequestContextCancel_ServeHTTPDone(t *testing.T, h2 bool) {
}
}
+// Tests that the Request.Context available to the Handler is canceled
+// if the peer closes their TCP connection. This requires that the server
+// is always blocked in a Read call so it notices the EOF from the client.
+// See issues 15927 and 15224.
func TestServerRequestContextCancel_ConnClose(t *testing.T) {
- // Currently the context is not canceled when the connection
- // is closed because we're not reading from the connection
- // until after ServeHTTP for the previous handler is done.
- // Until the server code is modified to always be in a read
- // (Issue 15224), this test doesn't work yet.
- t.Skip("TODO(bradfitz): this test doesn't yet work; golang.org/issue/15224")
+ setParallel(t)
defer afterTest(t)
inHandler := make(chan struct{})
handlerDone := make(chan struct{})
@@ -4192,7 +4353,7 @@ func TestServerRequestContextCancel_ConnClose(t *testing.T) {
select {
case <-handlerDone:
- case <-time.After(3 * time.Second):
+ case <-time.After(4 * time.Second):
t.Fatalf("timeout waiting to see ServeHTTP exit")
}
}
@@ -4204,6 +4365,7 @@ func TestServerContext_ServerContextKey_h2(t *testing.T) {
testServerContext_ServerContextKey(t, h2Mode)
}
func testServerContext_ServerContextKey(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
ctx := r.Context()
@@ -4229,6 +4391,7 @@ func testServerContext_ServerContextKey(t *testing.T, h2 bool) {
// https://golang.org/issue/15960
func TestHandlerSetTransferEncodingChunked(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("Transfer-Encoding", "chunked")
@@ -4243,6 +4406,7 @@ func TestHandlerSetTransferEncodingChunked(t *testing.T) {
// https://golang.org/issue/16063
func TestHandlerSetTransferEncodingGzip(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ht := newHandlerTest(HandlerFunc(func(w ResponseWriter, r *Request) {
w.Header().Set("Transfer-Encoding", "gzip")
@@ -4416,13 +4580,19 @@ func BenchmarkClient(b *testing.B) {
b.StopTimer()
defer afterTest(b)
- port := os.Getenv("TEST_BENCH_SERVER_PORT") // can be set by user
- if port == "" {
- port = "39207"
- }
var data = []byte("Hello world.\n")
if server := os.Getenv("TEST_BENCH_SERVER"); server != "" {
// Server process mode.
+ port := os.Getenv("TEST_BENCH_SERVER_PORT") // can be set by user
+ if port == "" {
+ port = "0"
+ }
+ ln, err := net.Listen("tcp", "localhost:"+port)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ fmt.Println(ln.Addr().String())
HandleFunc("/", func(w ResponseWriter, r *Request) {
r.ParseForm()
if r.Form.Get("stop") != "" {
@@ -4431,33 +4601,44 @@ func BenchmarkClient(b *testing.B) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Write(data)
})
- log.Fatal(ListenAndServe("localhost:"+port, nil))
+ var srv Server
+ log.Fatal(srv.Serve(ln))
}
// Start server process.
cmd := exec.Command(os.Args[0], "-test.run=XXXX", "-test.bench=BenchmarkClient$")
cmd.Env = append(os.Environ(), "TEST_BENCH_SERVER=yes")
+ cmd.Stderr = os.Stderr
+ stdout, err := cmd.StdoutPipe()
+ if err != nil {
+ b.Fatal(err)
+ }
if err := cmd.Start(); err != nil {
b.Fatalf("subprocess failed to start: %v", err)
}
defer cmd.Process.Kill()
+
+ // Wait for the server in the child process to respond and tell us
+ // its listening address, once it's started listening:
+ timer := time.AfterFunc(10*time.Second, func() {
+ cmd.Process.Kill()
+ })
+ defer timer.Stop()
+ bs := bufio.NewScanner(stdout)
+ if !bs.Scan() {
+ b.Fatalf("failed to read listening URL from child: %v", bs.Err())
+ }
+ url := "http://" + strings.TrimSpace(bs.Text()) + "/"
+ timer.Stop()
+ if _, err := getNoBody(url); err != nil {
+ b.Fatalf("initial probe of child process failed: %v", err)
+ }
+
done := make(chan error)
go func() {
done <- cmd.Wait()
}()
- // Wait for the server process to respond.
- url := "http://localhost:" + port + "/"
- for i := 0; i < 100; i++ {
- time.Sleep(100 * time.Millisecond)
- if _, err := getNoBody(url); err == nil {
- break
- }
- if i == 99 {
- b.Fatalf("subprocess does not respond")
- }
- }
-
// Do b.N requests to the server.
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -4719,6 +4900,7 @@ func BenchmarkCloseNotifier(b *testing.B) {
// Verify this doesn't race (Issue 16505)
func TestConcurrentServerServe(t *testing.T) {
+ setParallel(t)
for i := 0; i < 100; i++ {
ln1 := &oneConnListener{conn: nil}
ln2 := &oneConnListener{conn: nil}
@@ -4727,3 +4909,267 @@ func TestConcurrentServerServe(t *testing.T) {
go func() { srv.Serve(ln2) }()
}
}
+
+func TestServerIdleTimeout(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in short mode")
+ }
+ setParallel(t)
+ defer afterTest(t)
+ ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ io.Copy(ioutil.Discard, r.Body)
+ io.WriteString(w, r.RemoteAddr)
+ }))
+ ts.Config.ReadHeaderTimeout = 1 * time.Second
+ ts.Config.IdleTimeout = 2 * time.Second
+ ts.Start()
+ defer ts.Close()
+
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+ c := &Client{Transport: tr}
+
+ get := func() string {
+ res, err := c.Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ return string(slurp)
+ }
+
+ a1, a2 := get(), get()
+ if a1 != a2 {
+ t.Fatalf("did requests on different connections")
+ }
+ time.Sleep(3 * time.Second)
+ a3 := get()
+ if a2 == a3 {
+ t.Fatal("request three unexpectedly on same connection")
+ }
+
+ // And test that ReadHeaderTimeout still works:
+ conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer conn.Close()
+ conn.Write([]byte("GET / HTTP/1.1\r\nHost: foo.com\r\n"))
+ time.Sleep(2 * time.Second)
+ if _, err := io.CopyN(ioutil.Discard, conn, 1); err == nil {
+ t.Fatal("copy byte succeeded; want err")
+ }
+}
+
+func get(t *testing.T, c *Client, url string) string {
+ res, err := c.Get(url)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ return string(slurp)
+}
+
+// Tests that calls to Server.SetKeepAlivesEnabled(false) closes any
+// currently-open connections.
+func TestServerSetKeepAlivesEnabledClosesConns(t *testing.T) {
+ setParallel(t)
+ defer afterTest(t)
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ io.WriteString(w, r.RemoteAddr)
+ }))
+ defer ts.Close()
+
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+ c := &Client{Transport: tr}
+
+ get := func() string { return get(t, c, ts.URL) }
+
+ a1, a2 := get(), get()
+ if a1 != a2 {
+ t.Fatal("expected first two requests on same connection")
+ }
+ var idle0 int
+ if !waitCondition(2*time.Second, 10*time.Millisecond, func() bool {
+ idle0 = tr.IdleConnKeyCountForTesting()
+ return idle0 == 1
+ }) {
+ t.Fatalf("idle count before SetKeepAlivesEnabled called = %v; want 1", idle0)
+ }
+
+ ts.Config.SetKeepAlivesEnabled(false)
+
+ var idle1 int
+ if !waitCondition(2*time.Second, 10*time.Millisecond, func() bool {
+ idle1 = tr.IdleConnKeyCountForTesting()
+ return idle1 == 0
+ }) {
+ t.Fatalf("idle count after SetKeepAlivesEnabled called = %v; want 0", idle1)
+ }
+
+ a3 := get()
+ if a3 == a2 {
+ t.Fatal("expected third request on new connection")
+ }
+}
+
+func TestServerShutdown_h1(t *testing.T) { testServerShutdown(t, h1Mode) }
+func TestServerShutdown_h2(t *testing.T) { testServerShutdown(t, h2Mode) }
+
+func testServerShutdown(t *testing.T, h2 bool) {
+ setParallel(t)
+ defer afterTest(t)
+ var doShutdown func() // set later
+ var shutdownRes = make(chan error, 1)
+ cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+ go doShutdown()
+ // Shutdown is graceful, so it should not interrupt
+ // this in-flight response. Add a tiny sleep here to
+ // increase the odds of a failure if shutdown has
+ // bugs.
+ time.Sleep(20 * time.Millisecond)
+ io.WriteString(w, r.RemoteAddr)
+ }))
+ defer cst.close()
+
+ doShutdown = func() {
+ shutdownRes <- cst.ts.Config.Shutdown(context.Background())
+ }
+ get(t, cst.c, cst.ts.URL) // calls t.Fail on failure
+
+ if err := <-shutdownRes; err != nil {
+ t.Fatalf("Shutdown: %v", err)
+ }
+
+ res, err := cst.c.Get(cst.ts.URL)
+ if err == nil {
+ res.Body.Close()
+ t.Fatal("second request should fail. server should be shut down")
+ }
+}
+
+// Issue 17878: tests that we can call Close twice.
+func TestServerCloseDeadlock(t *testing.T) {
+ var s Server
+ s.Close()
+ s.Close()
+}
+
+// Issue 17717: tests that Server.SetKeepAlivesEnabled is respected by
+// both HTTP/1 and HTTP/2.
+func TestServerKeepAlivesEnabled_h1(t *testing.T) { testServerKeepAlivesEnabled(t, h1Mode) }
+func TestServerKeepAlivesEnabled_h2(t *testing.T) { testServerKeepAlivesEnabled(t, h2Mode) }
+func testServerKeepAlivesEnabled(t *testing.T, h2 bool) {
+ setParallel(t)
+ defer afterTest(t)
+ cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+ fmt.Fprintf(w, "%v", r.RemoteAddr)
+ }))
+ defer cst.close()
+ srv := cst.ts.Config
+ srv.SetKeepAlivesEnabled(false)
+ a := cst.getURL(cst.ts.URL)
+ if !waitCondition(2*time.Second, 10*time.Millisecond, srv.ExportAllConnsIdle) {
+ t.Fatalf("test server has active conns")
+ }
+ b := cst.getURL(cst.ts.URL)
+ if a == b {
+ t.Errorf("got same connection between first and second requests")
+ }
+ if !waitCondition(2*time.Second, 10*time.Millisecond, srv.ExportAllConnsIdle) {
+ t.Fatalf("test server has active conns")
+ }
+}
+
+// Issue 18447: test that the Server's ReadTimeout is stopped while
+// the server's doing its 1-byte background read between requests,
+// waiting for the connection to maybe close.
+func TestServerCancelsReadTimeoutWhenIdle(t *testing.T) {
+ setParallel(t)
+ defer afterTest(t)
+ const timeout = 250 * time.Millisecond
+ ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ select {
+ case <-time.After(2 * timeout):
+ fmt.Fprint(w, "ok")
+ case <-r.Context().Done():
+ fmt.Fprint(w, r.Context().Err())
+ }
+ }))
+ ts.Config.ReadTimeout = timeout
+ ts.Start()
+ defer ts.Close()
+
+ tr := &Transport{}
+ defer tr.CloseIdleConnections()
+ c := &Client{Transport: tr}
+
+ res, err := c.Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ res.Body.Close()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(slurp) != "ok" {
+ t.Fatalf("Got: %q, want ok", slurp)
+ }
+}
+
+// Issue 18535: test that the Server doesn't try to do a background
+// read if it's already done one.
+func TestServerDuplicateBackgroundRead(t *testing.T) {
+ setParallel(t)
+ defer afterTest(t)
+
+ const goroutines = 5
+ const requests = 2000
+
+ hts := httptest.NewServer(HandlerFunc(NotFound))
+ defer hts.Close()
+
+ reqBytes := []byte("GET / HTTP/1.1\r\nHost: e.com\r\n\r\n")
+
+ var wg sync.WaitGroup
+ for i := 0; i < goroutines; i++ {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ cn, err := net.Dial("tcp", hts.Listener.Addr().String())
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer cn.Close()
+
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ io.Copy(ioutil.Discard, cn)
+ }()
+
+ for j := 0; j < requests; j++ {
+ if t.Failed() {
+ return
+ }
+ _, err := cn.Write(reqBytes)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ }
+ }()
+ }
+ wg.Wait()
+}
diff --git a/libgo/go/net/http/server.go b/libgo/go/net/http/server.go
index 89574a8b36e..96236489bd9 100644
--- a/libgo/go/net/http/server.go
+++ b/libgo/go/net/http/server.go
@@ -40,7 +40,9 @@ var (
// ErrHijacked is returned by ResponseWriter.Write calls when
// the underlying connection has been hijacked using the
- // Hijacker interfaced.
+ // Hijacker interface. A zero-byte write on a hijacked
+ // connection will return ErrHijacked without any other side
+ // effects.
ErrHijacked = errors.New("http: connection has been hijacked")
// ErrContentLength is returned by ResponseWriter.Write calls
@@ -73,7 +75,9 @@ var (
// If ServeHTTP panics, the server (the caller of ServeHTTP) assumes
// that the effect of the panic was isolated to the active request.
// It recovers the panic, logs a stack trace to the server error log,
-// and hangs up the connection.
+// and hangs up the connection. To abort a handler so the client sees
+// an interrupted response but the server doesn't log an error, panic
+// with the value ErrAbortHandler.
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
@@ -85,11 +89,25 @@ type Handler interface {
// has returned.
type ResponseWriter interface {
// Header returns the header map that will be sent by
- // WriteHeader. Changing the header after a call to
- // WriteHeader (or Write) has no effect unless the modified
- // headers were declared as trailers by setting the
- // "Trailer" header before the call to WriteHeader (see example).
- // To suppress implicit response headers, set their value to nil.
+ // WriteHeader. The Header map also is the mechanism with which
+ // Handlers can set HTTP trailers.
+ //
+ // Changing the header map after a call to WriteHeader (or
+ // Write) has no effect unless the modified headers are
+ // trailers.
+ //
+ // There are two ways to set Trailers. The preferred way is to
+ // predeclare in the headers which trailers you will later
+ // send by setting the "Trailer" header to the names of the
+ // trailer keys which will come later. In this case, those
+ // keys of the Header map are treated as if they were
+ // trailers. See the example. The second way, for trailer
+ // keys not known to the Handler until after the first Write,
+ // is to prefix the Header map keys with the TrailerPrefix
+ // constant value. See TrailerPrefix.
+ //
+ // To suppress implicit response headers (such as "Date"), set
+ // their value to nil.
Header() Header
// Write writes the data to the connection as part of an HTTP reply.
@@ -206,6 +224,9 @@ type conn struct {
// Immutable; never nil.
server *Server
+ // cancelCtx cancels the connection-level context.
+ cancelCtx context.CancelFunc
+
// rwc is the underlying network connection.
// This is never wrapped by other types and is the value given out
// to CloseNotifier callers. It is usually of type *net.TCPConn or
@@ -232,7 +253,6 @@ type conn struct {
r *connReader
// bufr reads from r.
- // Users of bufr must hold mu.
bufr *bufio.Reader
// bufw writes to checkConnErrorWriter{c}, which populates werr on error.
@@ -242,7 +262,11 @@ type conn struct {
// on this connection, if any.
lastMethod string
- // mu guards hijackedv, use of bufr, (*response).closeNotifyCh.
+ curReq atomic.Value // of *response (which has a Request in it)
+
+ curState atomic.Value // of ConnState
+
+ // mu guards hijackedv
mu sync.Mutex
// hijackedv is whether this connection has been hijacked
@@ -262,8 +286,12 @@ func (c *conn) hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
if c.hijackedv {
return nil, nil, ErrHijacked
}
+ c.r.abortPendingRead()
+
c.hijackedv = true
rwc = c.rwc
+ rwc.SetDeadline(time.Time{})
+
buf = bufio.NewReadWriter(c.bufr, bufio.NewWriter(rwc))
c.setState(rwc, StateHijacked)
return
@@ -346,13 +374,7 @@ func (cw *chunkWriter) close() {
bw := cw.res.conn.bufw // conn's bufio writer
// zero chunk to mark EOF
bw.WriteString("0\r\n")
- if len(cw.res.trailers) > 0 {
- trailers := make(Header)
- for _, h := range cw.res.trailers {
- if vv := cw.res.handlerHeader[h]; len(vv) > 0 {
- trailers[h] = vv
- }
- }
+ if trailers := cw.res.finalTrailers(); trailers != nil {
trailers.Write(bw) // the writer handles noting errors
}
// final blank line after the trailers (whether
@@ -413,9 +435,48 @@ type response struct {
dateBuf [len(TimeFormat)]byte
clenBuf [10]byte
- // closeNotifyCh is non-nil once CloseNotify is called.
- // Guarded by conn.mu
- closeNotifyCh <-chan bool
+ // closeNotifyCh is the channel returned by CloseNotify.
+ // TODO(bradfitz): this is currently (for Go 1.8) always
+ // non-nil. Make this lazily-created again as it used to be?
+ closeNotifyCh chan bool
+ didCloseNotify int32 // atomic (only 0->1 winner should send)
+}
+
+// TrailerPrefix is a magic prefix for ResponseWriter.Header map keys
+// that, if present, signals that the map entry is actually for
+// the response trailers, and not the response headers. The prefix
+// is stripped after the ServeHTTP call finishes and the values are
+// sent in the trailers.
+//
+// This mechanism is intended only for trailers that are not known
+// prior to the headers being written. If the set of trailers is fixed
+// or known before the header is written, the normal Go trailers mechanism
+// is preferred:
+// https://golang.org/pkg/net/http/#ResponseWriter
+// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
+const TrailerPrefix = "Trailer:"
+
+// finalTrailers is called after the Handler exits and returns a non-nil
+// value if the Handler set any trailers.
+func (w *response) finalTrailers() Header {
+ var t Header
+ for k, vv := range w.handlerHeader {
+ if strings.HasPrefix(k, TrailerPrefix) {
+ if t == nil {
+ t = make(Header)
+ }
+ t[strings.TrimPrefix(k, TrailerPrefix)] = vv
+ }
+ }
+ for _, k := range w.trailers {
+ if t == nil {
+ t = make(Header)
+ }
+ for _, v := range w.handlerHeader[k] {
+ t.Add(k, v)
+ }
+ }
+ return t
}
type atomicBool int32
@@ -548,60 +609,152 @@ type readResult struct {
// call blocked in a background goroutine to wait for activity and
// trigger a CloseNotifier channel.
type connReader struct {
- r io.Reader
- remain int64 // bytes remaining
+ conn *conn
- // ch is non-nil if a background read is in progress.
- // It is guarded by conn.mu.
- ch chan readResult
+ mu sync.Mutex // guards following
+ hasByte bool
+ byteBuf [1]byte
+ bgErr error // non-nil means error happened on background read
+ cond *sync.Cond
+ inRead bool
+ aborted bool // set true before conn.rwc deadline is set to past
+ remain int64 // bytes remaining
+}
+
+func (cr *connReader) lock() {
+ cr.mu.Lock()
+ if cr.cond == nil {
+ cr.cond = sync.NewCond(&cr.mu)
+ }
+}
+
+func (cr *connReader) unlock() { cr.mu.Unlock() }
+
+func (cr *connReader) startBackgroundRead() {
+ cr.lock()
+ defer cr.unlock()
+ if cr.inRead {
+ panic("invalid concurrent Body.Read call")
+ }
+ if cr.hasByte {
+ return
+ }
+ cr.inRead = true
+ cr.conn.rwc.SetReadDeadline(time.Time{})
+ go cr.backgroundRead()
+}
+
+func (cr *connReader) backgroundRead() {
+ n, err := cr.conn.rwc.Read(cr.byteBuf[:])
+ cr.lock()
+ if n == 1 {
+ cr.hasByte = true
+ // We were at EOF already (since we wouldn't be in a
+ // background read otherwise), so this is a pipelined
+ // HTTP request.
+ cr.closeNotifyFromPipelinedRequest()
+ }
+ if ne, ok := err.(net.Error); ok && cr.aborted && ne.Timeout() {
+ // Ignore this error. It's the expected error from
+ // another goroutine calling abortPendingRead.
+ } else if err != nil {
+ cr.handleReadError(err)
+ }
+ cr.aborted = false
+ cr.inRead = false
+ cr.unlock()
+ cr.cond.Broadcast()
+}
+
+func (cr *connReader) abortPendingRead() {
+ cr.lock()
+ defer cr.unlock()
+ if !cr.inRead {
+ return
+ }
+ cr.aborted = true
+ cr.conn.rwc.SetReadDeadline(aLongTimeAgo)
+ for cr.inRead {
+ cr.cond.Wait()
+ }
+ cr.conn.rwc.SetReadDeadline(time.Time{})
}
func (cr *connReader) setReadLimit(remain int64) { cr.remain = remain }
func (cr *connReader) setInfiniteReadLimit() { cr.remain = maxInt64 }
func (cr *connReader) hitReadLimit() bool { return cr.remain <= 0 }
+// may be called from multiple goroutines.
+func (cr *connReader) handleReadError(err error) {
+ cr.conn.cancelCtx()
+ cr.closeNotify()
+}
+
+// closeNotifyFromPipelinedRequest simply calls closeNotify.
+//
+// This method wrapper is here for documentation. The callers are the
+// cases where we send on the closenotify channel because of a
+// pipelined HTTP request, per the previous Go behavior and
+// documentation (that this "MAY" happen).
+//
+// TODO: consider changing this behavior and making context
+// cancelation and closenotify work the same.
+func (cr *connReader) closeNotifyFromPipelinedRequest() {
+ cr.closeNotify()
+}
+
+// may be called from multiple goroutines.
+func (cr *connReader) closeNotify() {
+ res, _ := cr.conn.curReq.Load().(*response)
+ if res != nil {
+ if atomic.CompareAndSwapInt32(&res.didCloseNotify, 0, 1) {
+ res.closeNotifyCh <- true
+ }
+ }
+}
+
func (cr *connReader) Read(p []byte) (n int, err error) {
+ cr.lock()
+ if cr.inRead {
+ cr.unlock()
+ panic("invalid concurrent Body.Read call")
+ }
if cr.hitReadLimit() {
+ cr.unlock()
return 0, io.EOF
}
+ if cr.bgErr != nil {
+ err = cr.bgErr
+ cr.unlock()
+ return 0, err
+ }
if len(p) == 0 {
- return
+ cr.unlock()
+ return 0, nil
}
if int64(len(p)) > cr.remain {
p = p[:cr.remain]
}
-
- // Is a background read (started by CloseNotifier) already in
- // flight? If so, wait for it and use its result.
- ch := cr.ch
- if ch != nil {
- cr.ch = nil
- res := <-ch
- if res.n == 1 {
- p[0] = res.b
- cr.remain -= 1
- }
- return res.n, res.err
+ if cr.hasByte {
+ p[0] = cr.byteBuf[0]
+ cr.hasByte = false
+ cr.unlock()
+ return 1, nil
}
- n, err = cr.r.Read(p)
- cr.remain -= int64(n)
- return
-}
+ cr.inRead = true
+ cr.unlock()
+ n, err = cr.conn.rwc.Read(p)
-func (cr *connReader) startBackgroundRead(onReadComplete func()) {
- if cr.ch != nil {
- // Background read already started.
- return
+ cr.lock()
+ cr.inRead = false
+ if err != nil {
+ cr.handleReadError(err)
}
- cr.ch = make(chan readResult, 1)
- go cr.closeNotifyAwaitActivityRead(cr.ch, onReadComplete)
-}
+ cr.remain -= int64(n)
+ cr.unlock()
-func (cr *connReader) closeNotifyAwaitActivityRead(ch chan<- readResult, onReadComplete func()) {
- var buf [1]byte
- n, err := cr.r.Read(buf[:1])
- onReadComplete()
- ch <- readResult{n, err, buf[0]}
+ cr.cond.Broadcast()
+ return n, err
}
var (
@@ -633,7 +786,7 @@ func newBufioReader(r io.Reader) *bufio.Reader {
br.Reset(r)
return br
}
- // Note: if this reader size is every changed, update
+ // Note: if this reader size is ever changed, update
// TestHandlerBodyClose's assumptions.
return bufio.NewReader(r)
}
@@ -746,9 +899,18 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
return nil, ErrHijacked
}
+ var (
+ wholeReqDeadline time.Time // or zero if none
+ hdrDeadline time.Time // or zero if none
+ )
+ t0 := time.Now()
+ if d := c.server.readHeaderTimeout(); d != 0 {
+ hdrDeadline = t0.Add(d)
+ }
if d := c.server.ReadTimeout; d != 0 {
- c.rwc.SetReadDeadline(time.Now().Add(d))
+ wholeReqDeadline = t0.Add(d)
}
+ c.rwc.SetReadDeadline(hdrDeadline)
if d := c.server.WriteTimeout; d != 0 {
defer func() {
c.rwc.SetWriteDeadline(time.Now().Add(d))
@@ -756,14 +918,12 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
}
c.r.setReadLimit(c.server.initialReadLimitSize())
- c.mu.Lock() // while using bufr
if c.lastMethod == "POST" {
// RFC 2616 section 4.1 tolerance for old buggy clients.
peek, _ := c.bufr.Peek(4) // ReadRequest will get err below
c.bufr.Discard(numLeadingCRorLF(peek))
}
req, err := readRequest(c.bufr, keepHostHeader)
- c.mu.Unlock()
if err != nil {
if c.r.hitReadLimit() {
return nil, errTooLarge
@@ -809,6 +969,11 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
body.doEarlyClose = true
}
+ // Adjust the read deadline if necessary.
+ if !hdrDeadline.Equal(wholeReqDeadline) {
+ c.rwc.SetReadDeadline(wholeReqDeadline)
+ }
+
w = &response{
conn: c,
cancelCtx: cancelCtx,
@@ -816,6 +981,7 @@ func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
reqBody: req.Body,
handlerHeader: make(Header),
contentLength: -1,
+ closeNotifyCh: make(chan bool, 1),
// We populate these ahead of time so we're not
// reading from req.Header after their Handler starts
@@ -990,7 +1156,17 @@ func (cw *chunkWriter) writeHeader(p []byte) {
}
var setHeader extraHeader
+ // Don't write out the fake "Trailer:foo" keys. See TrailerPrefix.
trailers := false
+ for k := range cw.header {
+ if strings.HasPrefix(k, TrailerPrefix) {
+ if excludeHeader == nil {
+ excludeHeader = make(map[string]bool)
+ }
+ excludeHeader[k] = true
+ trailers = true
+ }
+ }
for _, v := range cw.header["Trailer"] {
trailers = true
foreachHeaderElement(v, cw.res.declareTrailer)
@@ -1318,7 +1494,9 @@ func (w *response) WriteString(data string) (n int, err error) {
// either dataB or dataS is non-zero.
func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) {
if w.conn.hijacked() {
- w.conn.server.logf("http: response.Write on hijacked connection")
+ if lenData > 0 {
+ w.conn.server.logf("http: response.Write on hijacked connection")
+ }
return 0, ErrHijacked
}
if !w.wroteHeader {
@@ -1354,6 +1532,8 @@ func (w *response) finishRequest() {
w.cw.close()
w.conn.bufw.Flush()
+ w.conn.r.abortPendingRead()
+
// Close the body (regardless of w.closeAfterReply) so we can
// re-use its bufio.Reader later safely.
w.reqBody.Close()
@@ -1469,11 +1649,30 @@ func validNPN(proto string) bool {
}
func (c *conn) setState(nc net.Conn, state ConnState) {
- if hook := c.server.ConnState; hook != nil {
+ srv := c.server
+ switch state {
+ case StateNew:
+ srv.trackConn(c, true)
+ case StateHijacked, StateClosed:
+ srv.trackConn(c, false)
+ }
+ c.curState.Store(connStateInterface[state])
+ if hook := srv.ConnState; hook != nil {
hook(nc, state)
}
}
+// connStateInterface is an array of the interface{} versions of
+// ConnState values, so we can use them in atomic.Values later without
+// paying the cost of shoving their integers in an interface{}.
+var connStateInterface = [...]interface{}{
+ StateNew: StateNew,
+ StateActive: StateActive,
+ StateIdle: StateIdle,
+ StateHijacked: StateHijacked,
+ StateClosed: StateClosed,
+}
+
// badRequestError is a literal string (used by in the server in HTML,
// unescaped) to tell the user why their request was bad. It should
// be plain text without user info or other embedded errors.
@@ -1481,11 +1680,34 @@ type badRequestError string
func (e badRequestError) Error() string { return "Bad Request: " + string(e) }
+// ErrAbortHandler is a sentinel panic value to abort a handler.
+// While any panic from ServeHTTP aborts the response to the client,
+// panicking with ErrAbortHandler also suppresses logging of a stack
+// trace to the server's error log.
+var ErrAbortHandler = errors.New("net/http: abort Handler")
+
+// isCommonNetReadError reports whether err is a common error
+// encountered during reading a request off the network when the
+// client has gone away or had its read fail somehow. This is used to
+// determine which logs are interesting enough to log about.
+func isCommonNetReadError(err error) bool {
+ if err == io.EOF {
+ return true
+ }
+ if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
+ return true
+ }
+ if oe, ok := err.(*net.OpError); ok && oe.Op == "read" {
+ return true
+ }
+ return false
+}
+
// Serve a new connection.
func (c *conn) serve(ctx context.Context) {
c.remoteAddr = c.rwc.RemoteAddr().String()
defer func() {
- if err := recover(); err != nil {
+ if err := recover(); err != nil && err != ErrAbortHandler {
const size = 64 << 10
buf := make([]byte, size)
buf = buf[:runtime.Stack(buf, false)]
@@ -1521,13 +1743,14 @@ func (c *conn) serve(ctx context.Context) {
// HTTP/1.x from here on.
- c.r = &connReader{r: c.rwc}
- c.bufr = newBufioReader(c.r)
- c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)
-
ctx, cancelCtx := context.WithCancel(ctx)
+ c.cancelCtx = cancelCtx
defer cancelCtx()
+ c.r = &connReader{conn: c}
+ c.bufr = newBufioReader(c.r)
+ c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)
+
for {
w, err := c.readRequest(ctx)
if c.r.remain != c.server.initialReadLimitSize() {
@@ -1535,27 +1758,29 @@ func (c *conn) serve(ctx context.Context) {
c.setState(c.rwc, StateActive)
}
if err != nil {
+ const errorHeaders = "\r\nContent-Type: text/plain; charset=utf-8\r\nConnection: close\r\n\r\n"
+
if err == errTooLarge {
// Their HTTP client may or may not be
// able to read this if we're
// responding to them and hanging up
// while they're still writing their
// request. Undefined behavior.
- io.WriteString(c.rwc, "HTTP/1.1 431 Request Header Fields Too Large\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n431 Request Header Fields Too Large")
+ const publicErr = "431 Request Header Fields Too Large"
+ fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr)
c.closeWriteAndWait()
return
}
- if err == io.EOF {
- return // don't reply
- }
- if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
+ if isCommonNetReadError(err) {
return // don't reply
}
- var publicErr string
+
+ publicErr := "400 Bad Request"
if v, ok := err.(badRequestError); ok {
- publicErr = ": " + string(v)
+ publicErr = publicErr + ": " + string(v)
}
- io.WriteString(c.rwc, "HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n400 Bad Request"+publicErr)
+
+ fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr)
return
}
@@ -1571,11 +1796,24 @@ func (c *conn) serve(ctx context.Context) {
return
}
+ c.curReq.Store(w)
+
+ if requestBodyRemains(req.Body) {
+ registerOnHitEOF(req.Body, w.conn.r.startBackgroundRead)
+ } else {
+ if w.conn.bufr.Buffered() > 0 {
+ w.conn.r.closeNotifyFromPipelinedRequest()
+ }
+ w.conn.r.startBackgroundRead()
+ }
+
// HTTP cannot have multiple simultaneous active requests.[*]
// Until the server replies to this request, it can't read another,
// so we might as well run the handler in this goroutine.
// [*] Not strictly true: HTTP pipelining. We could let them all process
// in parallel even if their responses need to be serialized.
+ // But we're not going to implement HTTP pipelining because it
+ // was never deployed in the wild and the answer is HTTP/2.
serverHandler{c.server}.ServeHTTP(w, w.req)
w.cancelCtx()
if c.hijacked() {
@@ -1589,6 +1827,23 @@ func (c *conn) serve(ctx context.Context) {
return
}
c.setState(c.rwc, StateIdle)
+ c.curReq.Store((*response)(nil))
+
+ if !w.conn.server.doKeepAlives() {
+ // We're in shutdown mode. We might've replied
+ // to the user without "Connection: close" and
+ // they might think they can send another
+ // request, but such is life with HTTP/1.1.
+ return
+ }
+
+ if d := c.server.idleTimeout(); d != 0 {
+ c.rwc.SetReadDeadline(time.Now().Add(d))
+ if _, err := c.bufr.Peek(4); err != nil {
+ return
+ }
+ }
+ c.rwc.SetReadDeadline(time.Time{})
}
}
@@ -1624,10 +1879,6 @@ func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
c.mu.Lock()
defer c.mu.Unlock()
- if w.closeNotifyCh != nil {
- return nil, nil, errors.New("http: Hijack is incompatible with use of CloseNotifier in same ServeHTTP call")
- }
-
// Release the bufioWriter that writes to the chunk writer, it is not
// used after a connection has been hijacked.
rwc, buf, err = c.hijackLocked()
@@ -1642,50 +1893,7 @@ func (w *response) CloseNotify() <-chan bool {
if w.handlerDone.isSet() {
panic("net/http: CloseNotify called after ServeHTTP finished")
}
- c := w.conn
- c.mu.Lock()
- defer c.mu.Unlock()
-
- if w.closeNotifyCh != nil {
- return w.closeNotifyCh
- }
- ch := make(chan bool, 1)
- w.closeNotifyCh = ch
-
- if w.conn.hijackedv {
- // CloseNotify is undefined after a hijack, but we have
- // no place to return an error, so just return a channel,
- // even though it'll never receive a value.
- return ch
- }
-
- var once sync.Once
- notify := func() { once.Do(func() { ch <- true }) }
-
- if requestBodyRemains(w.reqBody) {
- // They're still consuming the request body, so we
- // shouldn't notify yet.
- registerOnHitEOF(w.reqBody, func() {
- c.mu.Lock()
- defer c.mu.Unlock()
- startCloseNotifyBackgroundRead(c, notify)
- })
- } else {
- startCloseNotifyBackgroundRead(c, notify)
- }
- return ch
-}
-
-// c.mu must be held.
-func startCloseNotifyBackgroundRead(c *conn, notify func()) {
- if c.bufr.Buffered() > 0 {
- // They've consumed the request body, so anything
- // remaining is a pipelined request, which we
- // document as firing on.
- notify()
- } else {
- c.r.startBackgroundRead(notify)
- }
+ return w.closeNotifyCh
}
func registerOnHitEOF(rc io.ReadCloser, fn func()) {
@@ -1702,7 +1910,7 @@ func registerOnHitEOF(rc io.ReadCloser, fn func()) {
// requestBodyRemains reports whether future calls to Read
// on rc might yield more data.
func requestBodyRemains(rc io.ReadCloser) bool {
- if rc == eofReader {
+ if rc == NoBody {
return false
}
switch v := rc.(type) {
@@ -1816,7 +2024,7 @@ func Redirect(w ResponseWriter, r *Request, urlStr string, code int) {
}
}
- w.Header().Set("Location", urlStr)
+ w.Header().Set("Location", hexEscapeNonASCII(urlStr))
w.WriteHeader(code)
// RFC 2616 recommends that a short note "SHOULD" be included in the
@@ -2094,11 +2302,36 @@ func Serve(l net.Listener, handler Handler) error {
// A Server defines parameters for running an HTTP server.
// The zero value for Server is a valid configuration.
type Server struct {
- Addr string // TCP address to listen on, ":http" if empty
- Handler Handler // handler to invoke, http.DefaultServeMux if nil
- ReadTimeout time.Duration // maximum duration before timing out read of the request
- WriteTimeout time.Duration // maximum duration before timing out write of the response
- TLSConfig *tls.Config // optional TLS config, used by ListenAndServeTLS
+ Addr string // TCP address to listen on, ":http" if empty
+ Handler Handler // handler to invoke, http.DefaultServeMux if nil
+ TLSConfig *tls.Config // optional TLS config, used by ListenAndServeTLS
+
+ // ReadTimeout is the maximum duration for reading the entire
+ // request, including the body.
+ //
+ // Because ReadTimeout does not let Handlers make per-request
+ // decisions on each request body's acceptable deadline or
+ // upload rate, most users will prefer to use
+ // ReadHeaderTimeout. It is valid to use them both.
+ ReadTimeout time.Duration
+
+ // ReadHeaderTimeout is the amount of time allowed to read
+ // request headers. The connection's read deadline is reset
+ // after reading the headers and the Handler can decide what
+ // is considered too slow for the body.
+ ReadHeaderTimeout time.Duration
+
+ // WriteTimeout is the maximum duration before timing out
+ // writes of the response. It is reset whenever a new
+ // request's header is read. Like ReadTimeout, it does not
+ // let Handlers make decisions on a per-request basis.
+ WriteTimeout time.Duration
+
+ // IdleTimeout is the maximum amount of time to wait for the
+ // next request when keep-alives are enabled. If IdleTimeout
+ // is zero, the value of ReadTimeout is used. If both are
+ // zero, there is no timeout.
+ IdleTimeout time.Duration
// MaxHeaderBytes controls the maximum number of bytes the
// server will read parsing the request header's keys and
@@ -2114,7 +2347,8 @@ type Server struct {
// handle HTTP requests and will initialize the Request's TLS
// and RemoteAddr if not already set. The connection is
// automatically closed when the function returns.
- // If TLSNextProto is nil, HTTP/2 support is enabled automatically.
+ // If TLSNextProto is not nil, HTTP/2 support is not enabled
+ // automatically.
TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
// ConnState specifies an optional callback function that is
@@ -2129,8 +2363,132 @@ type Server struct {
ErrorLog *log.Logger
disableKeepAlives int32 // accessed atomically.
+ inShutdown int32 // accessed atomically (non-zero means we're in Shutdown)
nextProtoOnce sync.Once // guards setupHTTP2_* init
nextProtoErr error // result of http2.ConfigureServer if used
+
+ mu sync.Mutex
+ listeners map[net.Listener]struct{}
+ activeConn map[*conn]struct{}
+ doneChan chan struct{}
+}
+
+func (s *Server) getDoneChan() <-chan struct{} {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.getDoneChanLocked()
+}
+
+func (s *Server) getDoneChanLocked() chan struct{} {
+ if s.doneChan == nil {
+ s.doneChan = make(chan struct{})
+ }
+ return s.doneChan
+}
+
+func (s *Server) closeDoneChanLocked() {
+ ch := s.getDoneChanLocked()
+ select {
+ case <-ch:
+ // Already closed. Don't close again.
+ default:
+ // Safe to close here. We're the only closer, guarded
+ // by s.mu.
+ close(ch)
+ }
+}
+
+// Close immediately closes all active net.Listeners and any
+// connections in state StateNew, StateActive, or StateIdle. For a
+// graceful shutdown, use Shutdown.
+//
+// Close does not attempt to close (and does not even know about)
+// any hijacked connections, such as WebSockets.
+//
+// Close returns any error returned from closing the Server's
+// underlying Listener(s).
+func (srv *Server) Close() error {
+ srv.mu.Lock()
+ defer srv.mu.Unlock()
+ srv.closeDoneChanLocked()
+ err := srv.closeListenersLocked()
+ for c := range srv.activeConn {
+ c.rwc.Close()
+ delete(srv.activeConn, c)
+ }
+ return err
+}
+
+// shutdownPollInterval is how often we poll for quiescence
+// during Server.Shutdown. This is lower during tests, to
+// speed up tests.
+// Ideally we could find a solution that doesn't involve polling,
+// but which also doesn't have a high runtime cost (and doesn't
+// involve any contentious mutexes), but that is left as an
+// exercise for the reader.
+var shutdownPollInterval = 500 * time.Millisecond
+
+// Shutdown gracefully shuts down the server without interrupting any
+// active connections. Shutdown works by first closing all open
+// listeners, then closing all idle connections, and then waiting
+// indefinitely for connections to return to idle and then shut down.
+// If the provided context expires before the shutdown is complete,
+// then the context's error is returned.
+//
+// Shutdown does not attempt to close nor wait for hijacked
+// connections such as WebSockets. The caller of Shutdown should
+// separately notify such long-lived connections of shutdown and wait
+// for them to close, if desired.
+func (srv *Server) Shutdown(ctx context.Context) error {
+ atomic.AddInt32(&srv.inShutdown, 1)
+ defer atomic.AddInt32(&srv.inShutdown, -1)
+
+ srv.mu.Lock()
+ lnerr := srv.closeListenersLocked()
+ srv.closeDoneChanLocked()
+ srv.mu.Unlock()
+
+ ticker := time.NewTicker(shutdownPollInterval)
+ defer ticker.Stop()
+ for {
+ if srv.closeIdleConns() {
+ return lnerr
+ }
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-ticker.C:
+ }
+ }
+}
+
+// closeIdleConns closes all idle connections and reports whether the
+// server is quiescent.
+func (s *Server) closeIdleConns() bool {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ quiescent := true
+ for c := range s.activeConn {
+ st, ok := c.curState.Load().(ConnState)
+ if !ok || st != StateIdle {
+ quiescent = false
+ continue
+ }
+ c.rwc.Close()
+ delete(s.activeConn, c)
+ }
+ return quiescent
+}
+
+func (s *Server) closeListenersLocked() error {
+ var err error
+ for ln := range s.listeners {
+ if cerr := ln.Close(); cerr != nil && err == nil {
+ err = cerr
+ }
+ delete(s.listeners, ln)
+ }
+ return err
}
// A ConnState represents the state of a client connection to a server.
@@ -2243,6 +2601,8 @@ func (srv *Server) shouldConfigureHTTP2ForServe() bool {
return strSliceContains(srv.TLSConfig.NextProtos, http2NextProtoTLS)
}
+var ErrServerClosed = errors.New("http: Server closed")
+
// Serve accepts incoming connections on the Listener l, creating a
// new service goroutine for each. The service goroutines read requests and
// then call srv.Handler to reply to them.
@@ -2252,7 +2612,8 @@ func (srv *Server) shouldConfigureHTTP2ForServe() bool {
// srv.TLSConfig is non-nil and doesn't include the string "h2" in
// Config.NextProtos, HTTP/2 support is not enabled.
//
-// Serve always returns a non-nil error.
+// Serve always returns a non-nil error. After Shutdown or Close, the
+// returned error is ErrServerClosed.
func (srv *Server) Serve(l net.Listener) error {
defer l.Close()
if fn := testHookServerServe; fn != nil {
@@ -2264,14 +2625,20 @@ func (srv *Server) Serve(l net.Listener) error {
return err
}
- // TODO: allow changing base context? can't imagine concrete
- // use cases yet.
- baseCtx := context.Background()
+ srv.trackListener(l, true)
+ defer srv.trackListener(l, false)
+
+ baseCtx := context.Background() // base is always background, per Issue 16220
ctx := context.WithValue(baseCtx, ServerContextKey, srv)
ctx = context.WithValue(ctx, LocalAddrContextKey, l.Addr())
for {
rw, e := l.Accept()
if e != nil {
+ select {
+ case <-srv.getDoneChan():
+ return ErrServerClosed
+ default:
+ }
if ne, ok := e.(net.Error); ok && ne.Temporary() {
if tempDelay == 0 {
tempDelay = 5 * time.Millisecond
@@ -2294,8 +2661,57 @@ func (srv *Server) Serve(l net.Listener) error {
}
}
+func (s *Server) trackListener(ln net.Listener, add bool) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if s.listeners == nil {
+ s.listeners = make(map[net.Listener]struct{})
+ }
+ if add {
+ // If the *Server is being reused after a previous
+ // Close or Shutdown, reset its doneChan:
+ if len(s.listeners) == 0 && len(s.activeConn) == 0 {
+ s.doneChan = nil
+ }
+ s.listeners[ln] = struct{}{}
+ } else {
+ delete(s.listeners, ln)
+ }
+}
+
+func (s *Server) trackConn(c *conn, add bool) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if s.activeConn == nil {
+ s.activeConn = make(map[*conn]struct{})
+ }
+ if add {
+ s.activeConn[c] = struct{}{}
+ } else {
+ delete(s.activeConn, c)
+ }
+}
+
+func (s *Server) idleTimeout() time.Duration {
+ if s.IdleTimeout != 0 {
+ return s.IdleTimeout
+ }
+ return s.ReadTimeout
+}
+
+func (s *Server) readHeaderTimeout() time.Duration {
+ if s.ReadHeaderTimeout != 0 {
+ return s.ReadHeaderTimeout
+ }
+ return s.ReadTimeout
+}
+
func (s *Server) doKeepAlives() bool {
- return atomic.LoadInt32(&s.disableKeepAlives) == 0
+ return atomic.LoadInt32(&s.disableKeepAlives) == 0 && !s.shuttingDown()
+}
+
+func (s *Server) shuttingDown() bool {
+ return atomic.LoadInt32(&s.inShutdown) != 0
}
// SetKeepAlivesEnabled controls whether HTTP keep-alives are enabled.
@@ -2305,9 +2721,21 @@ func (s *Server) doKeepAlives() bool {
func (srv *Server) SetKeepAlivesEnabled(v bool) {
if v {
atomic.StoreInt32(&srv.disableKeepAlives, 0)
- } else {
- atomic.StoreInt32(&srv.disableKeepAlives, 1)
+ return
}
+ atomic.StoreInt32(&srv.disableKeepAlives, 1)
+
+ // Close idle HTTP/1 conns:
+ srv.closeIdleConns()
+
+ // Close HTTP/2 conns, as soon as they become idle, but reset
+ // the chan so future conns (if the listener is still active)
+ // still work and don't get a GOAWAY immediately, before their
+ // first request:
+ srv.mu.Lock()
+ defer srv.mu.Unlock()
+ srv.closeDoneChanLocked() // closes http2 conns
+ srv.doneChan = nil
}
func (s *Server) logf(format string, args ...interface{}) {
@@ -2630,24 +3058,6 @@ func (globalOptionsHandler) ServeHTTP(w ResponseWriter, r *Request) {
}
}
-type eofReaderWithWriteTo struct{}
-
-func (eofReaderWithWriteTo) WriteTo(io.Writer) (int64, error) { return 0, nil }
-func (eofReaderWithWriteTo) Read([]byte) (int, error) { return 0, io.EOF }
-
-// eofReader is a non-nil io.ReadCloser that always returns EOF.
-// It has a WriteTo method so io.Copy won't need a buffer.
-var eofReader = &struct {
- eofReaderWithWriteTo
- io.Closer
-}{
- eofReaderWithWriteTo{},
- ioutil.NopCloser(nil),
-}
-
-// Verify that an io.Copy from an eofReader won't require a buffer.
-var _ io.WriterTo = eofReader
-
// initNPNRequest is an HTTP handler that initializes certain
// uninitialized fields in its *Request. Such partially-initialized
// Requests come from NPN protocol handlers.
@@ -2662,7 +3072,7 @@ func (h initNPNRequest) ServeHTTP(rw ResponseWriter, req *Request) {
*req.TLS = h.c.ConnectionState()
}
if req.Body == nil {
- req.Body = eofReader
+ req.Body = NoBody
}
if req.RemoteAddr == "" {
req.RemoteAddr = h.c.RemoteAddr().String()
@@ -2723,6 +3133,7 @@ func (w checkConnErrorWriter) Write(p []byte) (n int, err error) {
n, err = w.c.rwc.Write(p)
if err != nil && w.c.werr == nil {
w.c.werr = err
+ w.c.cancelCtx()
}
return
}
diff --git a/libgo/go/net/http/sniff_test.go b/libgo/go/net/http/sniff_test.go
index ac404bfa723..38f3f8197e9 100644
--- a/libgo/go/net/http/sniff_test.go
+++ b/libgo/go/net/http/sniff_test.go
@@ -66,6 +66,7 @@ func TestServerContentType_h1(t *testing.T) { testServerContentType(t, h1Mode) }
func TestServerContentType_h2(t *testing.T) { testServerContentType(t, h2Mode) }
func testServerContentType(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
i, _ := strconv.Atoi(r.FormValue("i"))
@@ -160,6 +161,7 @@ func testContentTypeWithCopy(t *testing.T, h2 bool) {
func TestSniffWriteSize_h1(t *testing.T) { testSniffWriteSize(t, h1Mode) }
func TestSniffWriteSize_h2(t *testing.T) { testSniffWriteSize(t, h2Mode) }
func testSniffWriteSize(t *testing.T, h2 bool) {
+ setParallel(t)
defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
size, _ := strconv.Atoi(r.FormValue("size"))
diff --git a/libgo/go/net/http/transfer.go b/libgo/go/net/http/transfer.go
index c653467098c..4f47637aa76 100644
--- a/libgo/go/net/http/transfer.go
+++ b/libgo/go/net/http/transfer.go
@@ -17,6 +17,7 @@ import (
"strconv"
"strings"
"sync"
+ "time"
"golang_org/x/net/lex/httplex"
)
@@ -33,6 +34,23 @@ func (r errorReader) Read(p []byte) (n int, err error) {
return 0, r.err
}
+type byteReader struct {
+ b byte
+ done bool
+}
+
+func (br *byteReader) Read(p []byte) (n int, err error) {
+ if br.done {
+ return 0, io.EOF
+ }
+ if len(p) == 0 {
+ return 0, nil
+ }
+ br.done = true
+ p[0] = br.b
+ return 1, io.EOF
+}
+
// transferWriter inspects the fields of a user-supplied Request or Response,
// sanitizes them without changing the user object and provides methods for
// writing the respective header, body and trailer in wire format.
@@ -46,6 +64,9 @@ type transferWriter struct {
TransferEncoding []string
Trailer Header
IsResponse bool
+
+ FlushHeaders bool // flush headers to network before body
+ ByteReadCh chan readResult // non-nil if probeRequestBody called
}
func newTransferWriter(r interface{}) (t *transferWriter, err error) {
@@ -59,37 +80,15 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
}
t.Method = valueOrDefault(rr.Method, "GET")
- t.Body = rr.Body
- t.BodyCloser = rr.Body
- t.ContentLength = rr.ContentLength
t.Close = rr.Close
t.TransferEncoding = rr.TransferEncoding
t.Trailer = rr.Trailer
- atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
- if t.Body != nil && len(t.TransferEncoding) == 0 && atLeastHTTP11 {
- if t.ContentLength == 0 {
- // Test to see if it's actually zero or just unset.
- var buf [1]byte
- n, rerr := io.ReadFull(t.Body, buf[:])
- if rerr != nil && rerr != io.EOF {
- t.ContentLength = -1
- t.Body = errorReader{rerr}
- } else if n == 1 {
- // Oh, guess there is data in this Body Reader after all.
- // The ContentLength field just wasn't set.
- // Stich the Body back together again, re-attaching our
- // consumed byte.
- t.ContentLength = -1
- t.Body = io.MultiReader(bytes.NewReader(buf[:]), t.Body)
- } else {
- // Body is actually empty.
- t.Body = nil
- t.BodyCloser = nil
- }
- }
- if t.ContentLength < 0 {
- t.TransferEncoding = []string{"chunked"}
- }
+ atLeastHTTP11 = rr.protoAtLeastOutgoing(1, 1)
+ t.Body = rr.Body
+ t.BodyCloser = rr.Body
+ t.ContentLength = rr.outgoingLength()
+ if t.ContentLength < 0 && len(t.TransferEncoding) == 0 && atLeastHTTP11 && t.shouldSendChunkedRequestBody() {
+ t.TransferEncoding = []string{"chunked"}
}
case *Response:
t.IsResponse = true
@@ -103,7 +102,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
t.TransferEncoding = rr.TransferEncoding
t.Trailer = rr.Trailer
atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
- t.ResponseToHEAD = noBodyExpected(t.Method)
+ t.ResponseToHEAD = noResponseBodyExpected(t.Method)
}
// Sanitize Body,ContentLength,TransferEncoding
@@ -131,7 +130,100 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
return t, nil
}
-func noBodyExpected(requestMethod string) bool {
+// shouldSendChunkedRequestBody reports whether we should try to send a
+// chunked request body to the server. In particular, the case we really
+// want to prevent is sending a GET or other typically-bodyless request to a
+// server with a chunked body when the body has zero bytes, since GETs with
+// bodies (while acceptable according to specs), even zero-byte chunked
+// bodies, are approximately never seen in the wild and confuse most
+// servers. See Issue 18257, as one example.
+//
+// The only reason we'd send such a request is if the user set the Body to a
+// non-nil value (say, ioutil.NopCloser(bytes.NewReader(nil))) and didn't
+// set ContentLength, or NewRequest set it to -1 (unknown), so then we assume
+// there's bytes to send.
+//
+// This code tries to read a byte from the Request.Body in such cases to see
+// whether the body actually has content (super rare) or is actually just
+// a non-nil content-less ReadCloser (the more common case). In that more
+// common case, we act as if their Body were nil instead, and don't send
+// a body.
+func (t *transferWriter) shouldSendChunkedRequestBody() bool {
+ // Note that t.ContentLength is the corrected content length
+ // from rr.outgoingLength, so 0 actually means zero, not unknown.
+ if t.ContentLength >= 0 || t.Body == nil { // redundant checks; caller did them
+ return false
+ }
+ if requestMethodUsuallyLacksBody(t.Method) {
+ // Only probe the Request.Body for GET/HEAD/DELETE/etc
+ // requests, because it's only those types of requests
+ // that confuse servers.
+ t.probeRequestBody() // adjusts t.Body, t.ContentLength
+ return t.Body != nil
+ }
+ // For all other request types (PUT, POST, PATCH, or anything
+ // made-up we've never heard of), assume it's normal and the server
+ // can deal with a chunked request body. Maybe we'll adjust this
+ // later.
+ return true
+}
+
+// probeRequestBody reads a byte from t.Body to see whether it's empty
+// (returns io.EOF right away).
+//
+// But because we've had problems with this blocking users in the past
+// (issue 17480) when the body is a pipe (perhaps waiting on the response
+// headers before the pipe is fed data), we need to be careful and bound how
+// long we wait for it. This delay will only affect users if all the following
+// are true:
+// * the request body blocks
+// * the content length is not set (or set to -1)
+// * the method doesn't usually have a body (GET, HEAD, DELETE, ...)
+// * there is no transfer-encoding=chunked already set.
+// In other words, this delay will not normally affect anybody, and there
+// are workarounds if it does.
+func (t *transferWriter) probeRequestBody() {
+ t.ByteReadCh = make(chan readResult, 1)
+ go func(body io.Reader) {
+ var buf [1]byte
+ var rres readResult
+ rres.n, rres.err = body.Read(buf[:])
+ if rres.n == 1 {
+ rres.b = buf[0]
+ }
+ t.ByteReadCh <- rres
+ }(t.Body)
+ timer := time.NewTimer(200 * time.Millisecond)
+ select {
+ case rres := <-t.ByteReadCh:
+ timer.Stop()
+ if rres.n == 0 && rres.err == io.EOF {
+ // It was empty.
+ t.Body = nil
+ t.ContentLength = 0
+ } else if rres.n == 1 {
+ if rres.err != nil {
+ t.Body = io.MultiReader(&byteReader{b: rres.b}, errorReader{rres.err})
+ } else {
+ t.Body = io.MultiReader(&byteReader{b: rres.b}, t.Body)
+ }
+ } else if rres.err != nil {
+ t.Body = errorReader{rres.err}
+ }
+ case <-timer.C:
+ // Too slow. Don't wait. Read it later, and keep
+ // assuming that this is ContentLength == -1
+ // (unknown), which means we'll send a
+ // "Transfer-Encoding: chunked" header.
+ t.Body = io.MultiReader(finishAsyncByteRead{t}, t.Body)
+ // Request that Request.Write flush the headers to the
+ // network before writing the body, since our body may not
+ // become readable until it's seen the response headers.
+ t.FlushHeaders = true
+ }
+}
+
+func noResponseBodyExpected(requestMethod string) bool {
return requestMethod == "HEAD"
}
@@ -214,7 +306,7 @@ func (t *transferWriter) WriteBody(w io.Writer) error {
if t.Body != nil {
if chunked(t.TransferEncoding) {
if bw, ok := w.(*bufio.Writer); ok && !t.IsResponse {
- w = &internal.FlushAfterChunkWriter{bw}
+ w = &internal.FlushAfterChunkWriter{Writer: bw}
}
cw := internal.NewChunkedWriter(w)
_, err = io.Copy(cw, t.Body)
@@ -235,7 +327,9 @@ func (t *transferWriter) WriteBody(w io.Writer) error {
if err != nil {
return err
}
- if err = t.BodyCloser.Close(); err != nil {
+ }
+ if t.BodyCloser != nil {
+ if err := t.BodyCloser.Close(); err != nil {
return err
}
}
@@ -385,13 +479,13 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
// or close connection when finished, since multipart is not supported yet
switch {
case chunked(t.TransferEncoding):
- if noBodyExpected(t.RequestMethod) {
- t.Body = eofReader
+ if noResponseBodyExpected(t.RequestMethod) {
+ t.Body = NoBody
} else {
t.Body = &body{src: internal.NewChunkedReader(r), hdr: msg, r: r, closing: t.Close}
}
case realLength == 0:
- t.Body = eofReader
+ t.Body = NoBody
case realLength > 0:
t.Body = &body{src: io.LimitReader(r, realLength), closing: t.Close}
default:
@@ -401,7 +495,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
t.Body = &body{src: r, closing: t.Close}
} else {
// Persistent connection (i.e. HTTP/1.1)
- t.Body = eofReader
+ t.Body = NoBody
}
}
@@ -493,10 +587,31 @@ func (t *transferReader) fixTransferEncoding() error {
// function is not a method, because ultimately it should be shared by
// ReadResponse and ReadRequest.
func fixLength(isResponse bool, status int, requestMethod string, header Header, te []string) (int64, error) {
- contentLens := header["Content-Length"]
isRequest := !isResponse
+ contentLens := header["Content-Length"]
+
+ // Hardening against HTTP request smuggling
+ if len(contentLens) > 1 {
+ // Per RFC 7230 Section 3.3.2, prevent multiple
+ // Content-Length headers if they differ in value.
+ // If there are dups of the value, remove the dups.
+ // See Issue 16490.
+ first := strings.TrimSpace(contentLens[0])
+ for _, ct := range contentLens[1:] {
+ if first != strings.TrimSpace(ct) {
+ return 0, fmt.Errorf("http: message cannot contain multiple Content-Length headers; got %q", contentLens)
+ }
+ }
+
+ // deduplicate Content-Length
+ header.Del("Content-Length")
+ header.Add("Content-Length", first)
+
+ contentLens = header["Content-Length"]
+ }
+
// Logic based on response type or status
- if noBodyExpected(requestMethod) {
+ if noResponseBodyExpected(requestMethod) {
// For HTTP requests, as part of hardening against request
// smuggling (RFC 7230), don't allow a Content-Length header for
// methods which don't permit bodies. As an exception, allow
@@ -514,11 +629,6 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
return 0, nil
}
- if len(contentLens) > 1 {
- // harden against HTTP request smuggling. See RFC 7230.
- return 0, errors.New("http: message cannot contain multiple Content-Length headers")
- }
-
// Logic based on Transfer-Encoding
if chunked(te) {
return -1, nil
@@ -539,7 +649,7 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
header.Del("Content-Length")
}
- if !isResponse {
+ if isRequest {
// RFC 2616 neither explicitly permits nor forbids an
// entity-body on a GET request so we permit one if
// declared, but we default to 0 here (not -1 below)
@@ -864,3 +974,21 @@ func parseContentLength(cl string) (int64, error) {
return n, nil
}
+
+// finishAsyncByteRead finishes reading the 1-byte sniff
+// from the ContentLength==0, Body!=nil case.
+type finishAsyncByteRead struct {
+ tw *transferWriter
+}
+
+func (fr finishAsyncByteRead) Read(p []byte) (n int, err error) {
+ if len(p) == 0 {
+ return
+ }
+ rres := <-fr.tw.ByteReadCh
+ n, err = rres.n, rres.err
+ if n == 1 {
+ p[0] = rres.b
+ }
+ return
+}
diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go
index 1f0763471b8..571943d6e5c 100644
--- a/libgo/go/net/http/transport.go
+++ b/libgo/go/net/http/transport.go
@@ -25,6 +25,7 @@ import (
"os"
"strings"
"sync"
+ "sync/atomic"
"time"
"golang_org/x/net/lex/httplex"
@@ -40,6 +41,7 @@ var DefaultTransport RoundTripper = &Transport{
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
+ DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
@@ -66,8 +68,10 @@ const DefaultMaxIdleConnsPerHost = 2
// For high-level functionality, such as cookies and redirects, see Client.
//
// Transport uses HTTP/1.1 for HTTP URLs and either HTTP/1.1 or HTTP/2
-// for HTTPS URLs, depending on whether the server supports HTTP/2.
-// See the package docs for more about HTTP/2.
+// for HTTPS URLs, depending on whether the server supports HTTP/2,
+// and how the Transport is configured. The DefaultTransport supports HTTP/2.
+// To explicitly enable HTTP/2 on a transport, use golang.org/x/net/http2
+// and call ConfigureTransport. See the package docs for more about HTTP/2.
type Transport struct {
idleMu sync.Mutex
wantIdle bool // user has requested to close all idle conns
@@ -76,10 +80,10 @@ type Transport struct {
idleLRU connLRU
reqMu sync.Mutex
- reqCanceler map[*Request]func()
+ reqCanceler map[*Request]func(error)
- altMu sync.RWMutex
- altProto map[string]RoundTripper // nil or map of URI scheme => RoundTripper
+ altMu sync.Mutex // guards changing altProto only
+ altProto atomic.Value // of nil or map[string]RoundTripper, key is URI scheme
// Proxy specifies a function to return a proxy for a given
// Request. If the function returns a non-nil error, the
@@ -111,7 +115,9 @@ type Transport struct {
DialTLS func(network, addr string) (net.Conn, error)
// TLSClientConfig specifies the TLS configuration to use with
- // tls.Client. If nil, the default configuration is used.
+ // tls.Client.
+ // If nil, the default configuration is used.
+ // If non-nil, HTTP/2 support may not be enabled by default.
TLSClientConfig *tls.Config
// TLSHandshakeTimeout specifies the maximum amount of time waiting to
@@ -156,7 +162,9 @@ type Transport struct {
// ExpectContinueTimeout, if non-zero, specifies the amount of
// time to wait for a server's first response headers after fully
// writing the request headers if the request has an
- // "Expect: 100-continue" header. Zero means no timeout.
+ // "Expect: 100-continue" header. Zero means no timeout and
+ // causes the body to be sent immediately, without
+ // waiting for the server to approve.
// This time does not include the time to send the request header.
ExpectContinueTimeout time.Duration
@@ -168,9 +176,14 @@ type Transport struct {
// called with the request's authority (such as "example.com"
// or "example.com:1234") and the TLS connection. The function
// must return a RoundTripper that then handles the request.
- // If TLSNextProto is nil, HTTP/2 support is enabled automatically.
+ // If TLSNextProto is not nil, HTTP/2 support is not enabled
+ // automatically.
TLSNextProto map[string]func(authority string, c *tls.Conn) RoundTripper
+ // ProxyConnectHeader optionally specifies headers to send to
+ // proxies during CONNECT requests.
+ ProxyConnectHeader Header
+
// MaxResponseHeaderBytes specifies a limit on how many
// response bytes are allowed in the server's response
// header.
@@ -330,11 +343,9 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) {
}
}
}
- // TODO(bradfitz): switch to atomic.Value for this map instead of RWMutex
- t.altMu.RLock()
- altRT := t.altProto[scheme]
- t.altMu.RUnlock()
- if altRT != nil {
+
+ altProto, _ := t.altProto.Load().(map[string]RoundTripper)
+ if altRT := altProto[scheme]; altRT != nil {
if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol {
return resp, err
}
@@ -421,19 +432,15 @@ func (pc *persistConn) shouldRetryRequest(req *Request, err error) bool {
// our request (as opposed to sending an error).
return false
}
+ if _, ok := err.(nothingWrittenError); ok {
+ // We never wrote anything, so it's safe to retry.
+ return true
+ }
if !req.isReplayable() {
// Don't retry non-idempotent requests.
-
- // TODO: swap the nothingWrittenError and isReplayable checks,
- // putting the "if nothingWrittenError => return true" case
- // first, per golang.org/issue/15723
return false
}
- switch err.(type) {
- case nothingWrittenError:
- // We never wrote anything, so it's safe to retry.
- return true
- case transportReadFromServerError:
+ if _, ok := err.(transportReadFromServerError); ok {
// We got some non-EOF net.Conn.Read failure reading
// the 1st response byte from the server.
return true
@@ -463,13 +470,16 @@ var ErrSkipAltProtocol = errors.New("net/http: skip alternate protocol")
func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
t.altMu.Lock()
defer t.altMu.Unlock()
- if t.altProto == nil {
- t.altProto = make(map[string]RoundTripper)
- }
- if _, exists := t.altProto[scheme]; exists {
+ oldMap, _ := t.altProto.Load().(map[string]RoundTripper)
+ if _, exists := oldMap[scheme]; exists {
panic("protocol " + scheme + " already registered")
}
- t.altProto[scheme] = rt
+ newMap := make(map[string]RoundTripper)
+ for k, v := range oldMap {
+ newMap[k] = v
+ }
+ newMap[scheme] = rt
+ t.altProto.Store(newMap)
}
// CloseIdleConnections closes any connections which were previously
@@ -502,12 +512,17 @@ func (t *Transport) CloseIdleConnections() {
// cancelable context instead. CancelRequest cannot cancel HTTP/2
// requests.
func (t *Transport) CancelRequest(req *Request) {
+ t.cancelRequest(req, errRequestCanceled)
+}
+
+// Cancel an in-flight request, recording the error value.
+func (t *Transport) cancelRequest(req *Request, err error) {
t.reqMu.Lock()
cancel := t.reqCanceler[req]
delete(t.reqCanceler, req)
t.reqMu.Unlock()
if cancel != nil {
- cancel()
+ cancel(err)
}
}
@@ -557,10 +572,18 @@ func (e *envOnce) reset() {
}
func (t *Transport) connectMethodForRequest(treq *transportRequest) (cm connectMethod, err error) {
+ if port := treq.URL.Port(); !validPort(port) {
+ return cm, fmt.Errorf("invalid URL port %q", port)
+ }
cm.targetScheme = treq.URL.Scheme
cm.targetAddr = canonicalAddr(treq.URL)
if t.Proxy != nil {
cm.proxyURL, err = t.Proxy(treq.Request)
+ if err == nil && cm.proxyURL != nil {
+ if port := cm.proxyURL.Port(); !validPort(port) {
+ return cm, fmt.Errorf("invalid proxy URL port %q", port)
+ }
+ }
}
return cm, err
}
@@ -787,11 +810,11 @@ func (t *Transport) removeIdleConnLocked(pconn *persistConn) {
}
}
-func (t *Transport) setReqCanceler(r *Request, fn func()) {
+func (t *Transport) setReqCanceler(r *Request, fn func(error)) {
t.reqMu.Lock()
defer t.reqMu.Unlock()
if t.reqCanceler == nil {
- t.reqCanceler = make(map[*Request]func())
+ t.reqCanceler = make(map[*Request]func(error))
}
if fn != nil {
t.reqCanceler[r] = fn
@@ -804,7 +827,7 @@ func (t *Transport) setReqCanceler(r *Request, fn func()) {
// for the request, we don't set the function and return false.
// Since CancelRequest will clear the canceler, we can use the return value to detect if
// the request was canceled since the last setReqCancel call.
-func (t *Transport) replaceReqCanceler(r *Request, fn func()) bool {
+func (t *Transport) replaceReqCanceler(r *Request, fn func(error)) bool {
t.reqMu.Lock()
defer t.reqMu.Unlock()
_, ok := t.reqCanceler[r]
@@ -853,7 +876,7 @@ func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (*persistC
// set request canceler to some non-nil function so we
// can detect whether it was cleared between now and when
// we enter roundTrip
- t.setReqCanceler(req, func() {})
+ t.setReqCanceler(req, func(error) {})
return pc, nil
}
@@ -878,8 +901,8 @@ func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (*persistC
}()
}
- cancelc := make(chan struct{})
- t.setReqCanceler(req, func() { close(cancelc) })
+ cancelc := make(chan error, 1)
+ t.setReqCanceler(req, func(err error) { cancelc <- err })
go func() {
pc, err := t.dialConn(ctx, cm)
@@ -900,16 +923,21 @@ func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (*persistC
// value.
select {
case <-req.Cancel:
+ // It was an error due to cancelation, so prioritize that
+ // error value. (Issue 16049)
+ return nil, errRequestCanceledConn
case <-req.Context().Done():
- case <-cancelc:
+ return nil, req.Context().Err()
+ case err := <-cancelc:
+ if err == errRequestCanceled {
+ err = errRequestCanceledConn
+ }
+ return nil, err
default:
// It wasn't an error due to cancelation, so
// return the original error message:
return nil, v.err
}
- // It was an error due to cancelation, so prioritize that
- // error value. (Issue 16049)
- return nil, errRequestCanceledConn
case pc := <-idleConnCh:
// Another request finished first and its net.Conn
// became available before our dial. Or somebody
@@ -926,10 +954,13 @@ func (t *Transport) getConn(treq *transportRequest, cm connectMethod) (*persistC
return nil, errRequestCanceledConn
case <-req.Context().Done():
handlePendingDial()
- return nil, errRequestCanceledConn
- case <-cancelc:
+ return nil, req.Context().Err()
+ case err := <-cancelc:
handlePendingDial()
- return nil, errRequestCanceledConn
+ if err == errRequestCanceled {
+ err = errRequestCanceledConn
+ }
+ return nil, err
}
}
@@ -943,6 +974,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (*persistCon
writeErrCh: make(chan error, 1),
writeLoopDone: make(chan struct{}),
}
+ trace := httptrace.ContextClientTrace(ctx)
tlsDial := t.DialTLS != nil && cm.targetScheme == "https" && cm.proxyURL == nil
if tlsDial {
var err error
@@ -956,18 +988,28 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (*persistCon
if tc, ok := pconn.conn.(*tls.Conn); ok {
// Handshake here, in case DialTLS didn't. TLSNextProto below
// depends on it for knowing the connection state.
+ if trace != nil && trace.TLSHandshakeStart != nil {
+ trace.TLSHandshakeStart()
+ }
if err := tc.Handshake(); err != nil {
go pconn.conn.Close()
+ if trace != nil && trace.TLSHandshakeDone != nil {
+ trace.TLSHandshakeDone(tls.ConnectionState{}, err)
+ }
return nil, err
}
cs := tc.ConnectionState()
+ if trace != nil && trace.TLSHandshakeDone != nil {
+ trace.TLSHandshakeDone(cs, nil)
+ }
pconn.tlsState = &cs
}
} else {
conn, err := t.dial(ctx, "tcp", cm.addr())
if err != nil {
if cm.proxyURL != nil {
- err = fmt.Errorf("http: error connecting to proxy %s: %v", cm.proxyURL, err)
+ // Return a typed error, per Issue 16997:
+ err = &net.OpError{Op: "proxyconnect", Net: "tcp", Err: err}
}
return nil, err
}
@@ -987,11 +1029,15 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (*persistCon
}
case cm.targetScheme == "https":
conn := pconn.conn
+ hdr := t.ProxyConnectHeader
+ if hdr == nil {
+ hdr = make(Header)
+ }
connectReq := &Request{
Method: "CONNECT",
URL: &url.URL{Opaque: cm.targetAddr},
Host: cm.targetAddr,
- Header: make(Header),
+ Header: hdr,
}
if pa := cm.proxyAuth(); pa != "" {
connectReq.Header.Set("Proxy-Authorization", pa)
@@ -1016,7 +1062,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (*persistCon
if cm.targetScheme == "https" && !tlsDial {
// Initiate TLS and check remote host name against certificate.
- cfg := cloneTLSClientConfig(t.TLSClientConfig)
+ cfg := cloneTLSConfig(t.TLSClientConfig)
if cfg.ServerName == "" {
cfg.ServerName = cm.tlsHost()
}
@@ -1030,6 +1076,9 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (*persistCon
})
}
go func() {
+ if trace != nil && trace.TLSHandshakeStart != nil {
+ trace.TLSHandshakeStart()
+ }
err := tlsConn.Handshake()
if timer != nil {
timer.Stop()
@@ -1038,6 +1087,9 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (*persistCon
}()
if err := <-errc; err != nil {
plainConn.Close()
+ if trace != nil && trace.TLSHandshakeDone != nil {
+ trace.TLSHandshakeDone(tls.ConnectionState{}, err)
+ }
return nil, err
}
if !cfg.InsecureSkipVerify {
@@ -1047,6 +1099,9 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (*persistCon
}
}
cs := tlsConn.ConnectionState()
+ if trace != nil && trace.TLSHandshakeDone != nil {
+ trace.TLSHandshakeDone(cs, nil)
+ }
pconn.tlsState = &cs
pconn.conn = tlsConn
}
@@ -1235,8 +1290,8 @@ type persistConn struct {
mu sync.Mutex // guards following fields
numExpectedResponses int
closed error // set non-nil when conn is closed, before closech is closed
+ canceledErr error // set non-nil if conn is canceled
broken bool // an error has happened on this connection; marked broken so it's not reused.
- canceled bool // whether this conn was broken due a CancelRequest
reused bool // whether conn has had successful request/response and is being reused.
// mutateHeaderFunc is an optional func to modify extra
// headers on each outbound request before it's written. (the
@@ -1274,11 +1329,12 @@ func (pc *persistConn) isBroken() bool {
return b
}
-// isCanceled reports whether this connection was closed due to CancelRequest.
-func (pc *persistConn) isCanceled() bool {
+// canceled returns non-nil if the connection was closed due to
+// CancelRequest or due to context cancelation.
+func (pc *persistConn) canceled() error {
pc.mu.Lock()
defer pc.mu.Unlock()
- return pc.canceled
+ return pc.canceledErr
}
// isReused reports whether this connection is in a known broken state.
@@ -1301,10 +1357,10 @@ func (pc *persistConn) gotIdleConnTrace(idleAt time.Time) (t httptrace.GotConnIn
return
}
-func (pc *persistConn) cancelRequest() {
+func (pc *persistConn) cancelRequest(err error) {
pc.mu.Lock()
defer pc.mu.Unlock()
- pc.canceled = true
+ pc.canceledErr = err
pc.closeLocked(errRequestCanceled)
}
@@ -1328,12 +1384,12 @@ func (pc *persistConn) closeConnIfStillIdle() {
//
// The startBytesWritten value should be the value of pc.nwrite before the roundTrip
// started writing the request.
-func (pc *persistConn) mapRoundTripErrorFromReadLoop(startBytesWritten int64, err error) (out error) {
+func (pc *persistConn) mapRoundTripErrorFromReadLoop(req *Request, startBytesWritten int64, err error) (out error) {
if err == nil {
return nil
}
- if pc.isCanceled() {
- return errRequestCanceled
+ if err := pc.canceled(); err != nil {
+ return err
}
if err == errServerClosedIdle {
return err
@@ -1343,7 +1399,7 @@ func (pc *persistConn) mapRoundTripErrorFromReadLoop(startBytesWritten int64, er
}
if pc.isBroken() {
<-pc.writeLoopDone
- if pc.nwrite == startBytesWritten {
+ if pc.nwrite == startBytesWritten && req.outgoingLength() == 0 {
return nothingWrittenError{err}
}
}
@@ -1354,9 +1410,9 @@ func (pc *persistConn) mapRoundTripErrorFromReadLoop(startBytesWritten int64, er
// up to Transport.RoundTrip method when persistConn.roundTrip sees
// its pc.closech channel close, indicating the persistConn is dead.
// (after closech is closed, pc.closed is valid).
-func (pc *persistConn) mapRoundTripErrorAfterClosed(startBytesWritten int64) error {
- if pc.isCanceled() {
- return errRequestCanceled
+func (pc *persistConn) mapRoundTripErrorAfterClosed(req *Request, startBytesWritten int64) error {
+ if err := pc.canceled(); err != nil {
+ return err
}
err := pc.closed
if err == errServerClosedIdle {
@@ -1372,7 +1428,7 @@ func (pc *persistConn) mapRoundTripErrorAfterClosed(startBytesWritten int64) err
// see if we actually managed to write anything. If not, we
// can retry the request.
<-pc.writeLoopDone
- if pc.nwrite == startBytesWritten {
+ if pc.nwrite == startBytesWritten && req.outgoingLength() == 0 {
return nothingWrittenError{err}
}
@@ -1513,8 +1569,10 @@ func (pc *persistConn) readLoop() {
waitForBodyRead <- isEOF
if isEOF {
<-eofc // see comment above eofc declaration
- } else if err != nil && pc.isCanceled() {
- return errRequestCanceled
+ } else if err != nil {
+ if cerr := pc.canceled(); cerr != nil {
+ return cerr
+ }
}
return err
},
@@ -1554,7 +1612,7 @@ func (pc *persistConn) readLoop() {
pc.t.CancelRequest(rc.req)
case <-rc.req.Context().Done():
alive = false
- pc.t.CancelRequest(rc.req)
+ pc.t.cancelRequest(rc.req, rc.req.Context().Err())
case <-pc.closech:
alive = false
}
@@ -1652,7 +1710,7 @@ func (pc *persistConn) writeLoop() {
}
if err != nil {
wr.req.Request.closeBody()
- if pc.nwrite == startBytesWritten {
+ if pc.nwrite == startBytesWritten && wr.req.outgoingLength() == 0 {
err = nothingWrittenError{err}
}
}
@@ -1840,8 +1898,8 @@ WaitResponse:
select {
case err := <-writeErrCh:
if err != nil {
- if pc.isCanceled() {
- err = errRequestCanceled
+ if cerr := pc.canceled(); cerr != nil {
+ err = cerr
}
re = responseAndError{err: err}
pc.close(fmt.Errorf("write error: %v", err))
@@ -1853,21 +1911,20 @@ WaitResponse:
respHeaderTimer = timer.C
}
case <-pc.closech:
- re = responseAndError{err: pc.mapRoundTripErrorAfterClosed(startBytesWritten)}
+ re = responseAndError{err: pc.mapRoundTripErrorAfterClosed(req.Request, startBytesWritten)}
break WaitResponse
case <-respHeaderTimer:
pc.close(errTimeout)
re = responseAndError{err: errTimeout}
break WaitResponse
case re = <-resc:
- re.err = pc.mapRoundTripErrorFromReadLoop(startBytesWritten, re.err)
+ re.err = pc.mapRoundTripErrorFromReadLoop(req.Request, startBytesWritten, re.err)
break WaitResponse
case <-cancelChan:
pc.t.CancelRequest(req.Request)
cancelChan = nil
- ctxDoneChan = nil
case <-ctxDoneChan:
- pc.t.CancelRequest(req.Request)
+ pc.t.cancelRequest(req.Request, req.Context().Err())
cancelChan = nil
ctxDoneChan = nil
}
@@ -1931,11 +1988,15 @@ var portMap = map[string]string{
// canonicalAddr returns url.Host but always with a ":port" suffix
func canonicalAddr(url *url.URL) string {
- addr := url.Host
- if !hasPort(addr) {
- return addr + ":" + portMap[url.Scheme]
+ addr := url.Hostname()
+ if v, err := idnaASCII(addr); err == nil {
+ addr = v
+ }
+ port := url.Port()
+ if port == "" {
+ port = portMap[url.Scheme]
}
- return addr
+ return net.JoinHostPort(addr, port)
}
// bodyEOFSignal is used by the HTTP/1 transport when reading response
@@ -2060,75 +2121,14 @@ type fakeLocker struct{}
func (fakeLocker) Lock() {}
func (fakeLocker) Unlock() {}
-// cloneTLSConfig returns a shallow clone of the exported
-// fields of cfg, ignoring the unexported sync.Once, which
-// contains a mutex and must not be copied.
-//
-// The cfg must not be in active use by tls.Server, or else
-// there can still be a race with tls.Server updating SessionTicketKey
-// and our copying it, and also a race with the server setting
-// SessionTicketsDisabled=false on failure to set the random
-// ticket key.
-//
-// If cfg is nil, a new zero tls.Config is returned.
+// clneTLSConfig returns a shallow clone of cfg, or a new zero tls.Config if
+// cfg is nil. This is safe to call even if cfg is in active use by a TLS
+// client or server.
func cloneTLSConfig(cfg *tls.Config) *tls.Config {
if cfg == nil {
return &tls.Config{}
}
- return &tls.Config{
- Rand: cfg.Rand,
- Time: cfg.Time,
- Certificates: cfg.Certificates,
- NameToCertificate: cfg.NameToCertificate,
- GetCertificate: cfg.GetCertificate,
- RootCAs: cfg.RootCAs,
- NextProtos: cfg.NextProtos,
- ServerName: cfg.ServerName,
- ClientAuth: cfg.ClientAuth,
- ClientCAs: cfg.ClientCAs,
- InsecureSkipVerify: cfg.InsecureSkipVerify,
- CipherSuites: cfg.CipherSuites,
- PreferServerCipherSuites: cfg.PreferServerCipherSuites,
- SessionTicketsDisabled: cfg.SessionTicketsDisabled,
- SessionTicketKey: cfg.SessionTicketKey,
- ClientSessionCache: cfg.ClientSessionCache,
- MinVersion: cfg.MinVersion,
- MaxVersion: cfg.MaxVersion,
- CurvePreferences: cfg.CurvePreferences,
- DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled,
- Renegotiation: cfg.Renegotiation,
- }
-}
-
-// cloneTLSClientConfig is like cloneTLSConfig but omits
-// the fields SessionTicketsDisabled and SessionTicketKey.
-// This makes it safe to call cloneTLSClientConfig on a config
-// in active use by a server.
-func cloneTLSClientConfig(cfg *tls.Config) *tls.Config {
- if cfg == nil {
- return &tls.Config{}
- }
- return &tls.Config{
- Rand: cfg.Rand,
- Time: cfg.Time,
- Certificates: cfg.Certificates,
- NameToCertificate: cfg.NameToCertificate,
- GetCertificate: cfg.GetCertificate,
- RootCAs: cfg.RootCAs,
- NextProtos: cfg.NextProtos,
- ServerName: cfg.ServerName,
- ClientAuth: cfg.ClientAuth,
- ClientCAs: cfg.ClientCAs,
- InsecureSkipVerify: cfg.InsecureSkipVerify,
- CipherSuites: cfg.CipherSuites,
- PreferServerCipherSuites: cfg.PreferServerCipherSuites,
- ClientSessionCache: cfg.ClientSessionCache,
- MinVersion: cfg.MinVersion,
- MaxVersion: cfg.MaxVersion,
- CurvePreferences: cfg.CurvePreferences,
- DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled,
- Renegotiation: cfg.Renegotiation,
- }
+ return cfg.Clone()
}
type connLRU struct {
@@ -2169,3 +2169,15 @@ func (cl *connLRU) remove(pc *persistConn) {
func (cl *connLRU) len() int {
return len(cl.m)
}
+
+// validPort reports whether p (without the colon) is a valid port in
+// a URL, per RFC 3986 Section 3.2.3, which says the port may be
+// empty, or only contain digits.
+func validPort(p string) bool {
+ for _, r := range []byte(p) {
+ if r < '0' || r > '9' {
+ return false
+ }
+ }
+ return true
+}
diff --git a/libgo/go/net/http/transport_internal_test.go b/libgo/go/net/http/transport_internal_test.go
index a05ca6ed0d8..3d24fc127d4 100644
--- a/libgo/go/net/http/transport_internal_test.go
+++ b/libgo/go/net/http/transport_internal_test.go
@@ -72,3 +72,70 @@ func newLocalListener(t *testing.T) net.Listener {
}
return ln
}
+
+func dummyRequest(method string) *Request {
+ req, err := NewRequest(method, "http://fake.tld/", nil)
+ if err != nil {
+ panic(err)
+ }
+ return req
+}
+
+func TestTransportShouldRetryRequest(t *testing.T) {
+ tests := []struct {
+ pc *persistConn
+ req *Request
+
+ err error
+ want bool
+ }{
+ 0: {
+ pc: &persistConn{reused: false},
+ req: dummyRequest("POST"),
+ err: nothingWrittenError{},
+ want: false,
+ },
+ 1: {
+ pc: &persistConn{reused: true},
+ req: dummyRequest("POST"),
+ err: nothingWrittenError{},
+ want: true,
+ },
+ 2: {
+ pc: &persistConn{reused: true},
+ req: dummyRequest("POST"),
+ err: http2ErrNoCachedConn,
+ want: true,
+ },
+ 3: {
+ pc: &persistConn{reused: true},
+ req: dummyRequest("POST"),
+ err: errMissingHost,
+ want: false,
+ },
+ 4: {
+ pc: &persistConn{reused: true},
+ req: dummyRequest("POST"),
+ err: transportReadFromServerError{},
+ want: false,
+ },
+ 5: {
+ pc: &persistConn{reused: true},
+ req: dummyRequest("GET"),
+ err: transportReadFromServerError{},
+ want: true,
+ },
+ 6: {
+ pc: &persistConn{reused: true},
+ req: dummyRequest("GET"),
+ err: errServerClosedIdle,
+ want: true,
+ },
+ }
+ for i, tt := range tests {
+ got := tt.pc.shouldRetryRequest(tt.req, tt.err)
+ if got != tt.want {
+ t.Errorf("%d. shouldRetryRequest = %v; want %v", i, got, tt.want)
+ }
+ }
+}
diff --git a/libgo/go/net/http/transport_test.go b/libgo/go/net/http/transport_test.go
index 298682d04de..d5ddf6a1232 100644
--- a/libgo/go/net/http/transport_test.go
+++ b/libgo/go/net/http/transport_test.go
@@ -441,9 +441,7 @@ func TestTransportMaxPerHostIdleConns(t *testing.T) {
}
func TestTransportRemovesDeadIdleConnections(t *testing.T) {
- if runtime.GOOS == "plan9" {
- t.Skip("skipping test; see https://golang.org/issue/15464")
- }
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
io.WriteString(w, r.RemoteAddr)
@@ -700,6 +698,7 @@ var roundTripTests = []struct {
// Test that the modification made to the Request by the RoundTripper is cleaned up
func TestRoundTripGzip(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
const responseBody = "test response body"
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
@@ -758,6 +757,7 @@ func TestRoundTripGzip(t *testing.T) {
}
func TestTransportGzip(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
const testString = "The test string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
const nRandBytes = 1024 * 1024
@@ -856,6 +856,7 @@ func TestTransportGzip(t *testing.T) {
// If a request has Expect:100-continue header, the request blocks sending body until the first response.
// Premature consumption of the request body should not be occurred.
func TestTransportExpect100Continue(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
@@ -966,6 +967,48 @@ func TestTransportProxy(t *testing.T) {
}
}
+// Issue 16997: test transport dial preserves typed errors
+func TestTransportDialPreservesNetOpProxyError(t *testing.T) {
+ defer afterTest(t)
+
+ var errDial = errors.New("some dial error")
+
+ tr := &Transport{
+ Proxy: func(*Request) (*url.URL, error) {
+ return url.Parse("http://proxy.fake.tld/")
+ },
+ Dial: func(string, string) (net.Conn, error) {
+ return nil, errDial
+ },
+ }
+ defer tr.CloseIdleConnections()
+
+ c := &Client{Transport: tr}
+ req, _ := NewRequest("GET", "http://fake.tld", nil)
+ res, err := c.Do(req)
+ if err == nil {
+ res.Body.Close()
+ t.Fatal("wanted a non-nil error")
+ }
+
+ uerr, ok := err.(*url.Error)
+ if !ok {
+ t.Fatalf("got %T, want *url.Error", err)
+ }
+ oe, ok := uerr.Err.(*net.OpError)
+ if !ok {
+ t.Fatalf("url.Error.Err = %T; want *net.OpError", uerr.Err)
+ }
+ want := &net.OpError{
+ Op: "proxyconnect",
+ Net: "tcp",
+ Err: errDial, // original error, unwrapped.
+ }
+ if !reflect.DeepEqual(oe, want) {
+ t.Errorf("Got error %#v; want %#v", oe, want)
+ }
+}
+
// TestTransportGzipRecursive sends a gzip quine and checks that the
// client gets the same value back. This is more cute than anything,
// but checks that we don't recurse forever, and checks that
@@ -1038,10 +1081,12 @@ func waitNumGoroutine(nmax int) int {
// tests that persistent goroutine connections shut down when no longer desired.
func TestTransportPersistConnLeak(t *testing.T) {
- setParallel(t)
+ // Not parallel: counts goroutines
defer afterTest(t)
- gotReqCh := make(chan bool)
- unblockCh := make(chan bool)
+
+ const numReq = 25
+ gotReqCh := make(chan bool, numReq)
+ unblockCh := make(chan bool, numReq)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
gotReqCh <- true
<-unblockCh
@@ -1055,14 +1100,15 @@ func TestTransportPersistConnLeak(t *testing.T) {
n0 := runtime.NumGoroutine()
- const numReq = 25
- didReqCh := make(chan bool)
+ didReqCh := make(chan bool, numReq)
+ failed := make(chan bool, numReq)
for i := 0; i < numReq; i++ {
go func() {
res, err := c.Get(ts.URL)
didReqCh <- true
if err != nil {
t.Errorf("client fetch error: %v", err)
+ failed <- true
return
}
res.Body.Close()
@@ -1071,7 +1117,13 @@ func TestTransportPersistConnLeak(t *testing.T) {
// Wait for all goroutines to be stuck in the Handler.
for i := 0; i < numReq; i++ {
- <-gotReqCh
+ select {
+ case <-gotReqCh:
+ // ok
+ case <-failed:
+ close(unblockCh)
+ return
+ }
}
nhigh := runtime.NumGoroutine()
@@ -1102,7 +1154,7 @@ func TestTransportPersistConnLeak(t *testing.T) {
// golang.org/issue/4531: Transport leaks goroutines when
// request.ContentLength is explicitly short
func TestTransportPersistConnLeakShortBody(t *testing.T) {
- setParallel(t)
+ // Not parallel: measures goroutines.
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
}))
@@ -1198,6 +1250,7 @@ func TestIssue3644(t *testing.T) {
// Test that a client receives a server's reply, even if the server doesn't read
// the entire request body.
func TestIssue3595(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
const deniedMsg = "sorry, denied."
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -1246,6 +1299,7 @@ func TestChunkedNoContent(t *testing.T) {
}
func TestTransportConcurrency(t *testing.T) {
+ // Not parallel: uses global test hooks.
defer afterTest(t)
maxProcs, numReqs := 16, 500
if testing.Short() {
@@ -1306,9 +1360,7 @@ func TestTransportConcurrency(t *testing.T) {
}
func TestIssue4191_InfiniteGetTimeout(t *testing.T) {
- if runtime.GOOS == "plan9" {
- t.Skip("skipping test; see https://golang.org/issue/7237")
- }
+ setParallel(t)
defer afterTest(t)
const debug = false
mux := NewServeMux()
@@ -1370,9 +1422,7 @@ func TestIssue4191_InfiniteGetTimeout(t *testing.T) {
}
func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) {
- if runtime.GOOS == "plan9" {
- t.Skip("skipping test; see https://golang.org/issue/7237")
- }
+ setParallel(t)
defer afterTest(t)
const debug = false
mux := NewServeMux()
@@ -1696,12 +1746,6 @@ func testCancelRequestWithChannelBeforeDo(t *testing.T, withCtx bool) {
defer ts.Close()
defer close(unblockc)
- // Don't interfere with the next test on plan9.
- // Cf. https://golang.org/issues/11476
- if runtime.GOOS == "plan9" {
- defer time.Sleep(500 * time.Millisecond)
- }
-
tr := &Transport{}
defer tr.CloseIdleConnections()
c := &Client{Transport: tr}
@@ -1718,8 +1762,17 @@ func testCancelRequestWithChannelBeforeDo(t *testing.T, withCtx bool) {
}
_, err := c.Do(req)
- if err == nil || !strings.Contains(err.Error(), "canceled") {
- t.Errorf("Do error = %v; want cancelation", err)
+ if ue, ok := err.(*url.Error); ok {
+ err = ue.Err
+ }
+ if withCtx {
+ if err != context.Canceled {
+ t.Errorf("Do error = %v; want %v", err, context.Canceled)
+ }
+ } else {
+ if err == nil || !strings.Contains(err.Error(), "canceled") {
+ t.Errorf("Do error = %v; want cancelation", err)
+ }
}
}
@@ -1888,6 +1941,7 @@ func TestTransportEmptyMethod(t *testing.T) {
}
func TestTransportSocketLateBinding(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
mux := NewServeMux()
@@ -2152,6 +2206,7 @@ func TestProxyFromEnvironment(t *testing.T) {
}
func TestIdleConnChannelLeak(t *testing.T) {
+ // Not parallel: uses global test hooks.
var mu sync.Mutex
var n int
@@ -2383,6 +2438,7 @@ func (c byteFromChanReader) Read(p []byte) (n int, err error) {
// questionable state.
// golang.org/issue/7569
func TestTransportNoReuseAfterEarlyResponse(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
var sconn struct {
sync.Mutex
@@ -2485,22 +2541,6 @@ type errorReader struct {
func (e errorReader) Read(p []byte) (int, error) { return 0, e.err }
-type plan9SleepReader struct{}
-
-func (plan9SleepReader) Read(p []byte) (int, error) {
- if runtime.GOOS == "plan9" {
- // After the fix to unblock TCP Reads in
- // https://golang.org/cl/15941, this sleep is required
- // on plan9 to make sure TCP Writes before an
- // immediate TCP close go out on the wire. On Plan 9,
- // it seems that a hangup of a TCP connection with
- // queued data doesn't send the queued data first.
- // https://golang.org/issue/9554
- time.Sleep(50 * time.Millisecond)
- }
- return 0, io.EOF
-}
-
type closerFunc func() error
func (f closerFunc) Close() error { return f() }
@@ -2595,7 +2635,7 @@ func TestTransportClosesBodyOnError(t *testing.T) {
io.Reader
io.Closer
}{
- io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), plan9SleepReader{}, errorReader{fakeErr}),
+ io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), errorReader{fakeErr}),
closerFunc(func() error {
select {
case didClose <- true:
@@ -2627,6 +2667,8 @@ func TestTransportClosesBodyOnError(t *testing.T) {
}
func TestTransportDialTLS(t *testing.T) {
+ setParallel(t)
+ defer afterTest(t)
var mu sync.Mutex // guards following
var gotReq, didDial bool
@@ -2904,14 +2946,8 @@ func TestTransportFlushesBodyChunks(t *testing.T) {
defer res.Body.Close()
want := []string{
- // Because Request.ContentLength = 0, the body is sniffed for 1 byte to determine whether there's content.
- // That explains the initial "num0" being split into "n" and "um0".
- // The first byte is included with the request headers Write. Perhaps in the future
- // we will want to flush the headers out early if the first byte of the request body is
- // taking a long time to arrive. But not yet.
"POST / HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: x\r\nTransfer-Encoding: chunked\r\nAccept-Encoding: gzip\r\n\r\n" +
- "1\r\nn\r\n",
- "4\r\num0\n\r\n",
+ "5\r\nnum0\n\r\n",
"5\r\nnum1\n\r\n",
"5\r\nnum2\n\r\n",
"0\r\n\r\n",
@@ -3150,6 +3186,7 @@ func TestTransportReuseConnection_Gzip_ContentLength(t *testing.T) {
// Make sure we re-use underlying TCP connection for gzipped responses too.
func testTransportReuseConnection_Gzip(t *testing.T, chunked bool) {
+ setParallel(t)
defer afterTest(t)
addr := make(chan string, 2)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -3185,6 +3222,7 @@ func testTransportReuseConnection_Gzip(t *testing.T, chunked bool) {
}
func TestTransportResponseHeaderLength(t *testing.T) {
+ setParallel(t)
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if r.URL.Path == "/long" {
@@ -3248,7 +3286,7 @@ func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) {
cst.tr.ExpectContinueTimeout = 1 * time.Second
- var mu sync.Mutex
+ var mu sync.Mutex // guards buf
var buf bytes.Buffer
logf := func(format string, args ...interface{}) {
mu.Lock()
@@ -3290,10 +3328,16 @@ func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) {
Wait100Continue: func() { logf("Wait100Continue") },
Got100Continue: func() { logf("Got100Continue") },
WroteRequest: func(e httptrace.WroteRequestInfo) {
- close(gotWroteReqEvent)
logf("WroteRequest: %+v", e)
+ close(gotWroteReqEvent)
},
}
+ if h2 {
+ trace.TLSHandshakeStart = func() { logf("tls handshake start") }
+ trace.TLSHandshakeDone = func(s tls.ConnectionState, err error) {
+ logf("tls handshake done. ConnectionState = %v \n err = %v", s, err)
+ }
+ }
if noHooks {
// zero out all func pointers, trying to get some path to crash
*trace = httptrace.ClientTrace{}
@@ -3323,7 +3367,10 @@ func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) {
return
}
+ mu.Lock()
got := buf.String()
+ mu.Unlock()
+
wantOnce := func(sub string) {
if strings.Count(got, sub) != 1 {
t.Errorf("expected substring %q exactly once in output.", sub)
@@ -3342,7 +3389,10 @@ func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) {
wantOnceOrMore("connected to tcp " + addrStr + " = <nil>")
wantOnce("Reused:false WasIdle:false IdleTime:0s")
wantOnce("first response byte")
- if !h2 {
+ if h2 {
+ wantOnce("tls handshake start")
+ wantOnce("tls handshake done")
+ } else {
wantOnce("PutIdleConn = <nil>")
}
wantOnce("Wait100Continue")
@@ -3357,12 +3407,21 @@ func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) {
}
func TestTransportEventTraceRealDNS(t *testing.T) {
+ if testing.Short() && testenv.Builder() == "" {
+ // Skip this test in short mode (the default for
+ // all.bash), in case the user is using a shady/ISP
+ // DNS server hijacking queries.
+ // See issues 16732, 16716.
+ // Our builders use 8.8.8.8, though, which correctly
+ // returns NXDOMAIN, so still run this test there.
+ t.Skip("skipping in short mode")
+ }
defer afterTest(t)
tr := &Transport{}
defer tr.CloseIdleConnections()
c := &Client{Transport: tr}
- var mu sync.Mutex
+ var mu sync.Mutex // guards buf
var buf bytes.Buffer
logf := func(format string, args ...interface{}) {
mu.Lock()
@@ -3386,7 +3445,10 @@ func TestTransportEventTraceRealDNS(t *testing.T) {
t.Fatal("expected error during DNS lookup")
}
+ mu.Lock()
got := buf.String()
+ mu.Unlock()
+
wantSub := func(sub string) {
if !strings.Contains(got, sub) {
t.Errorf("expected substring %q in output.", sub)
@@ -3402,6 +3464,73 @@ func TestTransportEventTraceRealDNS(t *testing.T) {
}
}
+// Issue 14353: port can only contain digits.
+func TestTransportRejectsAlphaPort(t *testing.T) {
+ res, err := Get("http://dummy.tld:123foo/bar")
+ if err == nil {
+ res.Body.Close()
+ t.Fatal("unexpected success")
+ }
+ ue, ok := err.(*url.Error)
+ if !ok {
+ t.Fatalf("got %#v; want *url.Error", err)
+ }
+ got := ue.Err.Error()
+ want := `invalid URL port "123foo"`
+ if got != want {
+ t.Errorf("got error %q; want %q", got, want)
+ }
+}
+
+// Test the httptrace.TLSHandshake{Start,Done} hooks with a https http1
+// connections. The http2 test is done in TestTransportEventTrace_h2
+func TestTLSHandshakeTrace(t *testing.T) {
+ defer afterTest(t)
+ s := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+ defer s.Close()
+
+ var mu sync.Mutex
+ var start, done bool
+ trace := &httptrace.ClientTrace{
+ TLSHandshakeStart: func() {
+ mu.Lock()
+ defer mu.Unlock()
+ start = true
+ },
+ TLSHandshakeDone: func(s tls.ConnectionState, err error) {
+ mu.Lock()
+ defer mu.Unlock()
+ done = true
+ if err != nil {
+ t.Fatal("Expected error to be nil but was:", err)
+ }
+ },
+ }
+
+ tr := &Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
+ defer tr.CloseIdleConnections()
+ c := &Client{Transport: tr}
+ req, err := NewRequest("GET", s.URL, nil)
+ if err != nil {
+ t.Fatal("Unable to construct test request:", err)
+ }
+ req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
+
+ r, err := c.Do(req)
+ if err != nil {
+ t.Fatal("Unexpected error making request:", err)
+ }
+ r.Body.Close()
+ mu.Lock()
+ defer mu.Unlock()
+ if !start {
+ t.Fatal("Expected TLSHandshakeStart to be called, but wasn't")
+ }
+ if !done {
+ t.Fatal("Expected TLSHandshakeDone to be called, but wasnt't")
+ }
+}
+
func TestTransportMaxIdleConns(t *testing.T) {
defer afterTest(t)
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -3457,27 +3586,36 @@ func TestTransportMaxIdleConns(t *testing.T) {
}
}
-func TestTransportIdleConnTimeout(t *testing.T) {
+func TestTransportIdleConnTimeout_h1(t *testing.T) { testTransportIdleConnTimeout(t, h1Mode) }
+func TestTransportIdleConnTimeout_h2(t *testing.T) { testTransportIdleConnTimeout(t, h2Mode) }
+func testTransportIdleConnTimeout(t *testing.T, h2 bool) {
if testing.Short() {
t.Skip("skipping in short mode")
}
defer afterTest(t)
- ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ const timeout = 1 * time.Second
+
+ cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
// No body for convenience.
}))
- defer ts.Close()
-
- const timeout = 1 * time.Second
- tr := &Transport{
- IdleConnTimeout: timeout,
- }
+ defer cst.close()
+ tr := cst.tr
+ tr.IdleConnTimeout = timeout
defer tr.CloseIdleConnections()
c := &Client{Transport: tr}
+ idleConns := func() []string {
+ if h2 {
+ return tr.IdleConnStrsForTesting_h2()
+ } else {
+ return tr.IdleConnStrsForTesting()
+ }
+ }
+
var conn string
doReq := func(n int) {
- req, _ := NewRequest("GET", ts.URL, nil)
+ req, _ := NewRequest("GET", cst.ts.URL, nil)
req = req.WithContext(httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
PutIdleConn: func(err error) {
if err != nil {
@@ -3490,7 +3628,7 @@ func TestTransportIdleConnTimeout(t *testing.T) {
t.Fatal(err)
}
res.Body.Close()
- conns := tr.IdleConnStrsForTesting()
+ conns := idleConns()
if len(conns) != 1 {
t.Fatalf("req %v: unexpected number of idle conns: %q", n, conns)
}
@@ -3506,7 +3644,7 @@ func TestTransportIdleConnTimeout(t *testing.T) {
time.Sleep(timeout / 2)
}
time.Sleep(timeout * 3 / 2)
- if got := tr.IdleConnStrsForTesting(); len(got) != 0 {
+ if got := idleConns(); len(got) != 0 {
t.Errorf("idle conns = %q; want none", got)
}
}
@@ -3523,6 +3661,7 @@ func TestTransportIdleConnTimeout(t *testing.T) {
// know the successful tls.Dial from DialTLS will need to go into the
// idle pool. Then we give it a of time to explode.
func TestIdleConnH2Crash(t *testing.T) {
+ setParallel(t)
cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
// nothing
}))
@@ -3531,12 +3670,12 @@ func TestIdleConnH2Crash(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
- gotErr := make(chan bool, 1)
+ sawDoErr := make(chan bool, 1)
+ testDone := make(chan struct{})
+ defer close(testDone)
cst.tr.IdleConnTimeout = 5 * time.Millisecond
cst.tr.DialTLS = func(network, addr string) (net.Conn, error) {
- cancel()
- <-gotErr
c, err := tls.Dial(network, addr, &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"h2"},
@@ -3550,6 +3689,17 @@ func TestIdleConnH2Crash(t *testing.T) {
c.Close()
return nil, errors.New("bogus")
}
+
+ cancel()
+
+ failTimer := time.NewTimer(5 * time.Second)
+ defer failTimer.Stop()
+ select {
+ case <-sawDoErr:
+ case <-testDone:
+ case <-failTimer.C:
+ t.Error("timeout in DialTLS, waiting too long for cst.c.Do to fail")
+ }
return c, nil
}
@@ -3560,7 +3710,7 @@ func TestIdleConnH2Crash(t *testing.T) {
res.Body.Close()
t.Fatal("unexpected success")
}
- gotErr <- true
+ sawDoErr <- true
// Wait for the explosion.
time.Sleep(cst.tr.IdleConnTimeout * 10)
@@ -3605,6 +3755,122 @@ func TestTransportReturnsPeekError(t *testing.T) {
}
}
+// Issue 13835: international domain names should work
+func TestTransportIDNA_h1(t *testing.T) { testTransportIDNA(t, h1Mode) }
+func TestTransportIDNA_h2(t *testing.T) { testTransportIDNA(t, h2Mode) }
+func testTransportIDNA(t *testing.T, h2 bool) {
+ defer afterTest(t)
+
+ const uniDomain = "гофер.го"
+ const punyDomain = "xn--c1ae0ajs.xn--c1aw"
+
+ var port string
+ cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+ want := punyDomain + ":" + port
+ if r.Host != want {
+ t.Errorf("Host header = %q; want %q", r.Host, want)
+ }
+ if h2 {
+ if r.TLS == nil {
+ t.Errorf("r.TLS == nil")
+ } else if r.TLS.ServerName != punyDomain {
+ t.Errorf("TLS.ServerName = %q; want %q", r.TLS.ServerName, punyDomain)
+ }
+ }
+ w.Header().Set("Hit-Handler", "1")
+ }))
+ defer cst.close()
+
+ ip, port, err := net.SplitHostPort(cst.ts.Listener.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Install a fake DNS server.
+ ctx := context.WithValue(context.Background(), nettrace.LookupIPAltResolverKey{}, func(ctx context.Context, host string) ([]net.IPAddr, error) {
+ if host != punyDomain {
+ t.Errorf("got DNS host lookup for %q; want %q", host, punyDomain)
+ return nil, nil
+ }
+ return []net.IPAddr{{IP: net.ParseIP(ip)}}, nil
+ })
+
+ req, _ := NewRequest("GET", cst.scheme()+"://"+uniDomain+":"+port, nil)
+ trace := &httptrace.ClientTrace{
+ GetConn: func(hostPort string) {
+ want := net.JoinHostPort(punyDomain, port)
+ if hostPort != want {
+ t.Errorf("getting conn for %q; want %q", hostPort, want)
+ }
+ },
+ DNSStart: func(e httptrace.DNSStartInfo) {
+ if e.Host != punyDomain {
+ t.Errorf("DNSStart Host = %q; want %q", e.Host, punyDomain)
+ }
+ },
+ }
+ req = req.WithContext(httptrace.WithClientTrace(ctx, trace))
+
+ res, err := cst.tr.RoundTrip(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ if res.Header.Get("Hit-Handler") != "1" {
+ out, err := httputil.DumpResponse(res, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Errorf("Response body wasn't from Handler. Got:\n%s\n", out)
+ }
+}
+
+// Issue 13290: send User-Agent in proxy CONNECT
+func TestTransportProxyConnectHeader(t *testing.T) {
+ defer afterTest(t)
+ reqc := make(chan *Request, 1)
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ if r.Method != "CONNECT" {
+ t.Errorf("method = %q; want CONNECT", r.Method)
+ }
+ reqc <- r
+ c, _, err := w.(Hijacker).Hijack()
+ if err != nil {
+ t.Errorf("Hijack: %v", err)
+ return
+ }
+ c.Close()
+ }))
+ defer ts.Close()
+ tr := &Transport{
+ ProxyConnectHeader: Header{
+ "User-Agent": {"foo"},
+ "Other": {"bar"},
+ },
+ Proxy: func(r *Request) (*url.URL, error) {
+ return url.Parse(ts.URL)
+ },
+ }
+ defer tr.CloseIdleConnections()
+ c := &Client{Transport: tr}
+ res, err := c.Get("https://dummy.tld/") // https to force a CONNECT
+ if err == nil {
+ res.Body.Close()
+ t.Errorf("unexpected success")
+ }
+ select {
+ case <-time.After(3 * time.Second):
+ t.Fatal("timeout")
+ case r := <-reqc:
+ if got, want := r.Header.Get("User-Agent"), "foo"; got != want {
+ t.Errorf("CONNECT request User-Agent = %q; want %q", got, want)
+ }
+ if got, want := r.Header.Get("Other"), "bar"; got != want {
+ t.Errorf("CONNECT request Other = %q; want %q", got, want)
+ }
+ }
+}
+
var errFakeRoundTrip = errors.New("fake roundtrip")
type funcRoundTripper func()
diff --git a/libgo/go/net/interface.go b/libgo/go/net/interface.go
index 52b857c65f1..b3297f249d6 100644
--- a/libgo/go/net/interface.go
+++ b/libgo/go/net/interface.go
@@ -10,6 +10,12 @@ import (
"time"
)
+// BUG(mikio): On NaCl, methods and functions related to
+// Interface are not implemented.
+
+// BUG(mikio): On DragonFly BSD, NetBSD, OpenBSD, Plan 9 and Solaris,
+// the MulticastAddrs method of Interface is not implemented.
+
var (
errInvalidInterface = errors.New("invalid network interface")
errInvalidInterfaceIndex = errors.New("invalid network interface index")
@@ -63,7 +69,8 @@ func (f Flags) String() string {
return s
}
-// Addrs returns interface addresses for a specific interface.
+// Addrs returns a list of unicast interface addresses for a specific
+// interface.
func (ifi *Interface) Addrs() ([]Addr, error) {
if ifi == nil {
return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
@@ -75,8 +82,8 @@ func (ifi *Interface) Addrs() ([]Addr, error) {
return ifat, err
}
-// MulticastAddrs returns multicast, joined group addresses for
-// a specific interface.
+// MulticastAddrs returns a list of multicast, joined group addresses
+// for a specific interface.
func (ifi *Interface) MulticastAddrs() ([]Addr, error) {
if ifi == nil {
return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterface}
@@ -100,8 +107,11 @@ func Interfaces() ([]Interface, error) {
return ift, nil
}
-// InterfaceAddrs returns a list of the system's network interface
+// InterfaceAddrs returns a list of the system's unicast interface
// addresses.
+//
+// The returned list does not identify the associated interface; use
+// Interfaces and Interface.Addrs for more detail.
func InterfaceAddrs() ([]Addr, error) {
ifat, err := interfaceAddrTable(nil)
if err != nil {
@@ -111,6 +121,10 @@ func InterfaceAddrs() ([]Addr, error) {
}
// InterfaceByIndex returns the interface specified by index.
+//
+// On Solaris, it returns one of the logical network interfaces
+// sharing the logical data link; for more precision use
+// InterfaceByName.
func InterfaceByIndex(index int) (*Interface, error) {
if index <= 0 {
return nil, &OpError{Op: "route", Net: "ip+net", Source: nil, Addr: nil, Err: errInvalidInterfaceIndex}
@@ -158,6 +172,9 @@ func InterfaceByName(name string) (*Interface, error) {
// An ipv6ZoneCache represents a cache holding partial network
// interface information. It is used for reducing the cost of IPv6
// addressing scope zone resolution.
+//
+// Multiple names sharing the index are managed by first-come
+// first-served basis for consistency.
type ipv6ZoneCache struct {
sync.RWMutex // guard the following
lastFetched time.Time // last time routing information was fetched
@@ -188,7 +205,9 @@ func (zc *ipv6ZoneCache) update(ift []Interface) {
zc.toName = make(map[int]string, len(ift))
for _, ifi := range ift {
zc.toIndex[ifi.Name] = ifi.Index
- zc.toName[ifi.Index] = ifi.Name
+ if _, ok := zc.toName[ifi.Index]; !ok {
+ zc.toName[ifi.Index] = ifi.Name
+ }
}
}
@@ -215,7 +234,7 @@ func zoneToInt(zone string) int {
defer zoneCache.RUnlock()
index, ok := zoneCache.toIndex[zone]
if !ok {
- index, _, _ = dtoi(zone, 0)
+ index, _, _ = dtoi(zone)
}
return index
}
diff --git a/libgo/go/net/interface_plan9.go b/libgo/go/net/interface_plan9.go
new file mode 100644
index 00000000000..e5d77390f86
--- /dev/null
+++ b/libgo/go/net/interface_plan9.go
@@ -0,0 +1,198 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "errors"
+ "os"
+)
+
+// If the ifindex is zero, interfaceTable returns mappings of all
+// network interfaces. Otherwise it returns a mapping of a specific
+// interface.
+func interfaceTable(ifindex int) ([]Interface, error) {
+ if ifindex == 0 {
+ n, err := interfaceCount()
+ if err != nil {
+ return nil, err
+ }
+ ifcs := make([]Interface, n)
+ for i := range ifcs {
+ ifc, err := readInterface(i)
+ if err != nil {
+ return nil, err
+ }
+ ifcs[i] = *ifc
+ }
+ return ifcs, nil
+ }
+
+ ifc, err := readInterface(ifindex - 1)
+ if err != nil {
+ return nil, err
+ }
+ return []Interface{*ifc}, nil
+}
+
+func readInterface(i int) (*Interface, error) {
+ ifc := &Interface{
+ Index: i + 1, // Offset the index by one to suit the contract
+ Name: netdir + "/ipifc/" + itoa(i), // Name is the full path to the interface path in plan9
+ }
+
+ ifcstat := ifc.Name + "/status"
+ ifcstatf, err := open(ifcstat)
+ if err != nil {
+ return nil, err
+ }
+ defer ifcstatf.close()
+
+ line, ok := ifcstatf.readLine()
+ if !ok {
+ return nil, errors.New("invalid interface status file: " + ifcstat)
+ }
+
+ fields := getFields(line)
+ if len(fields) < 4 {
+ return nil, errors.New("invalid interface status file: " + ifcstat)
+ }
+
+ device := fields[1]
+ mtustr := fields[3]
+
+ mtu, _, ok := dtoi(mtustr)
+ if !ok {
+ return nil, errors.New("invalid status file of interface: " + ifcstat)
+ }
+ ifc.MTU = mtu
+
+ // Not a loopback device
+ if device != "/dev/null" {
+ deviceaddrf, err := open(device + "/addr")
+ if err != nil {
+ return nil, err
+ }
+ defer deviceaddrf.close()
+
+ line, ok = deviceaddrf.readLine()
+ if !ok {
+ return nil, errors.New("invalid address file for interface: " + device + "/addr")
+ }
+
+ if len(line) > 0 && len(line)%2 == 0 {
+ ifc.HardwareAddr = make([]byte, len(line)/2)
+ var ok bool
+ for i := range ifc.HardwareAddr {
+ j := (i + 1) * 2
+ ifc.HardwareAddr[i], ok = xtoi2(line[i*2:j], 0)
+ if !ok {
+ ifc.HardwareAddr = ifc.HardwareAddr[:i]
+ break
+ }
+ }
+ }
+
+ ifc.Flags = FlagUp | FlagBroadcast | FlagMulticast
+ } else {
+ ifc.Flags = FlagUp | FlagMulticast | FlagLoopback
+ }
+
+ return ifc, nil
+}
+
+func interfaceCount() (int, error) {
+ d, err := os.Open(netdir + "/ipifc")
+ if err != nil {
+ return -1, err
+ }
+ defer d.Close()
+
+ names, err := d.Readdirnames(0)
+ if err != nil {
+ return -1, err
+ }
+
+ // Assumes that numbered files in ipifc are strictly
+ // the incrementing numbered directories for the
+ // interfaces
+ c := 0
+ for _, name := range names {
+ if _, _, ok := dtoi(name); !ok {
+ continue
+ }
+ c++
+ }
+
+ return c, nil
+}
+
+// If the ifi is nil, interfaceAddrTable returns addresses for all
+// network interfaces. Otherwise it returns addresses for a specific
+// interface.
+func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
+ var ifcs []Interface
+ if ifi == nil {
+ var err error
+ ifcs, err = interfaceTable(0)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ ifcs = []Interface{*ifi}
+ }
+
+ addrs := make([]Addr, len(ifcs))
+ for i, ifc := range ifcs {
+ status := ifc.Name + "/status"
+ statusf, err := open(status)
+ if err != nil {
+ return nil, err
+ }
+ defer statusf.close()
+
+ line, ok := statusf.readLine()
+ line, ok = statusf.readLine()
+ if !ok {
+ return nil, errors.New("cannot parse IP address for interface: " + status)
+ }
+
+ // This assumes only a single address for the interface.
+ fields := getFields(line)
+ if len(fields) < 1 {
+ return nil, errors.New("cannot parse IP address for interface: " + status)
+ }
+ addr := fields[0]
+ ip := ParseIP(addr)
+ if ip == nil {
+ return nil, errors.New("cannot parse IP address for interface: " + status)
+ }
+
+ // The mask is represented as CIDR relative to the IPv6 address.
+ // Plan 9 internal representation is always IPv6.
+ maskfld := fields[1]
+ maskfld = maskfld[1:]
+ pfxlen, _, ok := dtoi(maskfld)
+ if !ok {
+ return nil, errors.New("cannot parse network mask for interface: " + status)
+ }
+ var mask IPMask
+ if ip.To4() != nil { // IPv4 or IPv6 IPv4-mapped address
+ mask = CIDRMask(pfxlen-8*len(v4InV6Prefix), 8*IPv4len)
+ }
+ if ip.To16() != nil && ip.To4() == nil { // IPv6 address
+ mask = CIDRMask(pfxlen, 8*IPv6len)
+ }
+
+ addrs[i] = &IPNet{IP: ip, Mask: mask}
+ }
+
+ return addrs, nil
+}
+
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+ return nil, nil
+}
diff --git a/libgo/go/net/interface_solaris.go b/libgo/go/net/interface_solaris.go
new file mode 100644
index 00000000000..dc8ffbfcb8a
--- /dev/null
+++ b/libgo/go/net/interface_solaris.go
@@ -0,0 +1,107 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "syscall"
+
+ "golang_org/x/net/lif"
+)
+
+// If the ifindex is zero, interfaceTable returns mappings of all
+// network interfaces. Otherwise it returns a mapping of a specific
+// interface.
+func interfaceTable(ifindex int) ([]Interface, error) {
+ lls, err := lif.Links(syscall.AF_UNSPEC, "")
+ if err != nil {
+ return nil, err
+ }
+ var ift []Interface
+ for _, ll := range lls {
+ if ifindex != 0 && ifindex != ll.Index {
+ continue
+ }
+ ifi := Interface{Index: ll.Index, MTU: ll.MTU, Name: ll.Name, Flags: linkFlags(ll.Flags)}
+ if len(ll.Addr) > 0 {
+ ifi.HardwareAddr = HardwareAddr(ll.Addr)
+ }
+ ift = append(ift, ifi)
+ }
+ return ift, nil
+}
+
+const (
+ sysIFF_UP = 0x1
+ sysIFF_BROADCAST = 0x2
+ sysIFF_DEBUG = 0x4
+ sysIFF_LOOPBACK = 0x8
+ sysIFF_POINTOPOINT = 0x10
+ sysIFF_NOTRAILERS = 0x20
+ sysIFF_RUNNING = 0x40
+ sysIFF_NOARP = 0x80
+ sysIFF_PROMISC = 0x100
+ sysIFF_ALLMULTI = 0x200
+ sysIFF_INTELLIGENT = 0x400
+ sysIFF_MULTICAST = 0x800
+ sysIFF_MULTI_BCAST = 0x1000
+ sysIFF_UNNUMBERED = 0x2000
+ sysIFF_PRIVATE = 0x8000
+)
+
+func linkFlags(rawFlags int) Flags {
+ var f Flags
+ if rawFlags&sysIFF_UP != 0 {
+ f |= FlagUp
+ }
+ if rawFlags&sysIFF_BROADCAST != 0 {
+ f |= FlagBroadcast
+ }
+ if rawFlags&sysIFF_LOOPBACK != 0 {
+ f |= FlagLoopback
+ }
+ if rawFlags&sysIFF_POINTOPOINT != 0 {
+ f |= FlagPointToPoint
+ }
+ if rawFlags&sysIFF_MULTICAST != 0 {
+ f |= FlagMulticast
+ }
+ return f
+}
+
+// If the ifi is nil, interfaceAddrTable returns addresses for all
+// network interfaces. Otherwise it returns addresses for a specific
+// interface.
+func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
+ var name string
+ if ifi != nil {
+ name = ifi.Name
+ }
+ as, err := lif.Addrs(syscall.AF_UNSPEC, name)
+ if err != nil {
+ return nil, err
+ }
+ var ifat []Addr
+ for _, a := range as {
+ var ip IP
+ var mask IPMask
+ switch a := a.(type) {
+ case *lif.Inet4Addr:
+ ip = IPv4(a.IP[0], a.IP[1], a.IP[2], a.IP[3])
+ mask = CIDRMask(a.PrefixLen, 8*IPv4len)
+ case *lif.Inet6Addr:
+ ip = make(IP, IPv6len)
+ copy(ip, a.IP[:])
+ mask = CIDRMask(a.PrefixLen, 8*IPv6len)
+ }
+ ifat = append(ifat, &IPNet{IP: ip, Mask: mask})
+ }
+ return ifat, nil
+}
+
+// interfaceMulticastAddrTable returns addresses for a specific
+// interface.
+func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
+ return nil, nil
+}
diff --git a/libgo/go/net/interface_stub.go b/libgo/go/net/interface_stub.go
index f64174c62ee..3b0a1aeacf2 100644
--- a/libgo/go/net/interface_stub.go
+++ b/libgo/go/net/interface_stub.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build nacl plan9 solaris
+// +build nacl
package net
diff --git a/libgo/go/net/interface_test.go b/libgo/go/net/interface_test.go
index 4c695b902a2..38a2ca46565 100644
--- a/libgo/go/net/interface_test.go
+++ b/libgo/go/net/interface_test.go
@@ -58,8 +58,15 @@ func TestInterfaces(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- if !reflect.DeepEqual(ifxi, &ifi) {
- t.Errorf("got %v; want %v", ifxi, ifi)
+ switch runtime.GOOS {
+ case "solaris":
+ if ifxi.Index != ifi.Index {
+ t.Errorf("got %v; want %v", ifxi, ifi)
+ }
+ default:
+ if !reflect.DeepEqual(ifxi, &ifi) {
+ t.Errorf("got %v; want %v", ifxi, ifi)
+ }
}
ifxn, err := InterfaceByName(ifi.Name)
if err != nil {
diff --git a/libgo/go/net/ip.go b/libgo/go/net/ip.go
index d0c82630b57..db3364c1b31 100644
--- a/libgo/go/net/ip.go
+++ b/libgo/go/net/ip.go
@@ -90,7 +90,7 @@ func CIDRMask(ones, bits int) IPMask {
// Well-known IPv4 addresses
var (
- IPv4bcast = IPv4(255, 255, 255, 255) // broadcast
+ IPv4bcast = IPv4(255, 255, 255, 255) // limited broadcast
IPv4allsys = IPv4(224, 0, 0, 1) // all systems
IPv4allrouter = IPv4(224, 0, 0, 2) // all routers
IPv4zero = IPv4(0, 0, 0, 0) // all zeros
@@ -153,6 +153,12 @@ func (ip IP) IsLinkLocalUnicast() bool {
// IsGlobalUnicast reports whether ip is a global unicast
// address.
+//
+// The identification of global unicast addresses uses address type
+// identification as defined in RFC 1122, RFC 4632 and RFC 4291 with
+// the exception of IPv4 directed broadcast addresses.
+// It returns true even if ip is in IPv4 private address space or
+// local IPv6 unicast address space.
func (ip IP) IsGlobalUnicast() bool {
return (len(ip) == IPv4len || len(ip) == IPv6len) &&
!ip.Equal(IPv4bcast) &&
@@ -504,29 +510,25 @@ func (n *IPNet) String() string {
// Parse IPv4 address (d.d.d.d).
func parseIPv4(s string) IP {
var p [IPv4len]byte
- i := 0
- for j := 0; j < IPv4len; j++ {
- if i >= len(s) {
+ for i := 0; i < IPv4len; i++ {
+ if len(s) == 0 {
// Missing octets.
return nil
}
- if j > 0 {
- if s[i] != '.' {
+ if i > 0 {
+ if s[0] != '.' {
return nil
}
- i++
+ s = s[1:]
}
- var (
- n int
- ok bool
- )
- n, i, ok = dtoi(s, i)
+ n, c, ok := dtoi(s)
if !ok || n > 0xFF {
return nil
}
- p[j] = byte(n)
+ s = s[c:]
+ p[i] = byte(n)
}
- if i != len(s) {
+ if len(s) != 0 {
return nil
}
return IPv4(p[0], p[1], p[2], p[3])
@@ -538,8 +540,7 @@ func parseIPv4(s string) IP {
// true.
func parseIPv6(s string, zoneAllowed bool) (ip IP, zone string) {
ip = make(IP, IPv6len)
- ellipsis := -1 // position of ellipsis in p
- i := 0 // index in string s
+ ellipsis := -1 // position of ellipsis in ip
if zoneAllowed {
s, zone = splitHostZone(s)
@@ -548,90 +549,91 @@ func parseIPv6(s string, zoneAllowed bool) (ip IP, zone string) {
// Might have leading ellipsis
if len(s) >= 2 && s[0] == ':' && s[1] == ':' {
ellipsis = 0
- i = 2
+ s = s[2:]
// Might be only ellipsis
- if i == len(s) {
+ if len(s) == 0 {
return ip, zone
}
}
// Loop, parsing hex numbers followed by colon.
- j := 0
- for j < IPv6len {
+ i := 0
+ for i < IPv6len {
// Hex number.
- n, i1, ok := xtoi(s, i)
+ n, c, ok := xtoi(s)
if !ok || n > 0xFFFF {
return nil, zone
}
// If followed by dot, might be in trailing IPv4.
- if i1 < len(s) && s[i1] == '.' {
- if ellipsis < 0 && j != IPv6len-IPv4len {
+ if c < len(s) && s[c] == '.' {
+ if ellipsis < 0 && i != IPv6len-IPv4len {
// Not the right place.
return nil, zone
}
- if j+IPv4len > IPv6len {
+ if i+IPv4len > IPv6len {
// Not enough room.
return nil, zone
}
- ip4 := parseIPv4(s[i:])
+ ip4 := parseIPv4(s)
if ip4 == nil {
return nil, zone
}
- ip[j] = ip4[12]
- ip[j+1] = ip4[13]
- ip[j+2] = ip4[14]
- ip[j+3] = ip4[15]
- i = len(s)
- j += IPv4len
+ ip[i] = ip4[12]
+ ip[i+1] = ip4[13]
+ ip[i+2] = ip4[14]
+ ip[i+3] = ip4[15]
+ s = ""
+ i += IPv4len
break
}
// Save this 16-bit chunk.
- ip[j] = byte(n >> 8)
- ip[j+1] = byte(n)
- j += 2
+ ip[i] = byte(n >> 8)
+ ip[i+1] = byte(n)
+ i += 2
// Stop at end of string.
- i = i1
- if i == len(s) {
+ s = s[c:]
+ if len(s) == 0 {
break
}
// Otherwise must be followed by colon and more.
- if s[i] != ':' || i+1 == len(s) {
+ if s[0] != ':' || len(s) == 1 {
return nil, zone
}
- i++
+ s = s[1:]
// Look for ellipsis.
- if s[i] == ':' {
+ if s[0] == ':' {
if ellipsis >= 0 { // already have one
return nil, zone
}
- ellipsis = j
- if i++; i == len(s) { // can be at end
+ ellipsis = i
+ s = s[1:]
+ if len(s) == 0 { // can be at end
break
}
}
}
// Must have used entire string.
- if i != len(s) {
+ if len(s) != 0 {
return nil, zone
}
// If didn't parse enough, expand ellipsis.
- if j < IPv6len {
+ if i < IPv6len {
if ellipsis < 0 {
return nil, zone
}
- n := IPv6len - j
- for k := j - 1; k >= ellipsis; k-- {
- ip[k+n] = ip[k]
+ n := IPv6len - i
+ for j := i - 1; j >= ellipsis; j-- {
+ ip[j+n] = ip[j]
}
- for k := ellipsis + n - 1; k >= ellipsis; k-- {
- ip[k] = 0
+ for j := ellipsis + n - 1; j >= ellipsis; j-- {
+ ip[j] = 0
}
} else if ellipsis >= 0 {
// Ellipsis must represent at least one 0 group.
@@ -658,13 +660,14 @@ func ParseIP(s string) IP {
return nil
}
-// ParseCIDR parses s as a CIDR notation IP address and mask,
+// ParseCIDR parses s as a CIDR notation IP address and prefix length,
// like "192.0.2.0/24" or "2001:db8::/32", as defined in
// RFC 4632 and RFC 4291.
//
-// It returns the IP address and the network implied by the IP
-// and mask. For example, ParseCIDR("198.51.100.1/24") returns
-// the IP address 198.51.100.1 and the network 198.51.100.0/24.
+// It returns the IP address and the network implied by the IP and
+// prefix length.
+// For example, ParseCIDR("192.0.2.1/24") returns the IP address
+// 198.0.2.1 and the network 198.0.2.0/24.
func ParseCIDR(s string) (IP, *IPNet, error) {
i := byteIndex(s, '/')
if i < 0 {
@@ -677,7 +680,7 @@ func ParseCIDR(s string) (IP, *IPNet, error) {
iplen = IPv6len
ip, _ = parseIPv6(addr, false)
}
- n, i, ok := dtoi(mask, 0)
+ n, i, ok := dtoi(mask)
if ip == nil || !ok || i != len(mask) || n < 0 || n > 8*iplen {
return nil, nil, &ParseError{Type: "CIDR address", Text: s}
}
diff --git a/libgo/go/net/ip_test.go b/libgo/go/net/ip_test.go
index b6ac26da05b..46551633ce2 100644
--- a/libgo/go/net/ip_test.go
+++ b/libgo/go/net/ip_test.go
@@ -28,6 +28,10 @@ var parseIPTests = []struct {
{"2001:4860:0:2001::68", IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}},
{"2001:4860:0000:2001:0000:0000:0000:0068", IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}},
+ {"-0.0.0.0", nil},
+ {"0.-1.0.0", nil},
+ {"0.0.-2.0", nil},
+ {"0.0.0.-3", nil},
{"127.0.0.256", nil},
{"abc", nil},
{"123:", nil},
@@ -242,13 +246,15 @@ func TestIPString(t *testing.T) {
}
}
+var sink string
+
func BenchmarkIPString(b *testing.B) {
testHookUninstaller.Do(uninstallTestHooks)
for i := 0; i < b.N; i++ {
for _, tt := range ipStringTests {
if tt.in != nil {
- tt.in.String()
+ sink = tt.in.String()
}
}
}
@@ -299,7 +305,7 @@ func BenchmarkIPMaskString(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tt := range ipMaskStringTests {
- tt.in.String()
+ sink = tt.in.String()
}
}
}
@@ -330,6 +336,12 @@ var parseCIDRTests = []struct {
{"192.168.1.1/255.255.255.0", nil, nil, &ParseError{Type: "CIDR address", Text: "192.168.1.1/255.255.255.0"}},
{"192.168.1.1/35", nil, nil, &ParseError{Type: "CIDR address", Text: "192.168.1.1/35"}},
{"2001:db8::1/-1", nil, nil, &ParseError{Type: "CIDR address", Text: "2001:db8::1/-1"}},
+ {"2001:db8::1/-0", nil, nil, &ParseError{Type: "CIDR address", Text: "2001:db8::1/-0"}},
+ {"-0.0.0.0/32", nil, nil, &ParseError{Type: "CIDR address", Text: "-0.0.0.0/32"}},
+ {"0.-1.0.0/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.-1.0.0/32"}},
+ {"0.0.-2.0/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.-2.0/32"}},
+ {"0.0.0.-3/32", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.0.-3/32"}},
+ {"0.0.0.0/-0", nil, nil, &ParseError{Type: "CIDR address", Text: "0.0.0.0/-0"}},
{"", nil, nil, &ParseError{Type: "CIDR address", Text: ""}},
}
diff --git a/libgo/go/net/iprawsock.go b/libgo/go/net/iprawsock.go
index 173b3cb4114..d994fc67c65 100644
--- a/libgo/go/net/iprawsock.go
+++ b/libgo/go/net/iprawsock.go
@@ -9,6 +9,24 @@ import (
"syscall"
)
+// BUG(mikio): On every POSIX platform, reads from the "ip4" network
+// using the ReadFrom or ReadFromIP method might not return a complete
+// IPv4 packet, including its header, even if there is space
+// available. This can occur even in cases where Read or ReadMsgIP
+// could return a complete packet. For this reason, it is recommended
+// that you do not use these methods if it is important to receive a
+// full packet.
+//
+// The Go 1 compatibility guidelines make it impossible for us to
+// change the behavior of these methods; use Read or ReadMsgIP
+// instead.
+
+// BUG(mikio): On NaCl, Plan 9 and Windows, the ReadMsgIP and
+// WriteMsgIP methods of IPConn are not implemented.
+
+// BUG(mikio): On Windows, the File method of IPConn is not
+// implemented.
+
// IPAddr represents the address of an IP end point.
type IPAddr struct {
IP IP
@@ -46,6 +64,9 @@ func (a *IPAddr) opAddr() Addr {
// ResolveIPAddr parses addr as an IP address of the form "host" or
// "ipv6-host%zone" and resolves the domain name on the network net,
// which must be "ip", "ip4" or "ip6".
+//
+// Resolving a hostname is not recommended because this returns at most
+// one of its IP addresses.
func ResolveIPAddr(net, addr string) (*IPAddr, error) {
if net == "" { // a hint wildcard for Go 1.0 undocumented behavior
net = "ip"
@@ -59,7 +80,7 @@ func ResolveIPAddr(net, addr string) (*IPAddr, error) {
default:
return nil, UnknownNetworkError(net)
}
- addrs, err := internetAddrList(context.Background(), afnet, addr)
+ addrs, err := DefaultResolver.internetAddrList(context.Background(), afnet, addr)
if err != nil {
return nil, err
}
diff --git a/libgo/go/net/iprawsock_posix.go b/libgo/go/net/iprawsock_posix.go
index 3e0b060a8a4..8f4b702e480 100644
--- a/libgo/go/net/iprawsock_posix.go
+++ b/libgo/go/net/iprawsock_posix.go
@@ -11,18 +11,6 @@ import (
"syscall"
)
-// BUG(mikio): On every POSIX platform, reads from the "ip4" network
-// using the ReadFrom or ReadFromIP method might not return a complete
-// IPv4 packet, including its header, even if there is space
-// available. This can occur even in cases where Read or ReadMsgIP
-// could return a complete packet. For this reason, it is recommended
-// that you do not uses these methods if it is important to receive a
-// full packet.
-//
-// The Go 1 compatibility guidelines make it impossible for us to
-// change the behavior of these methods; use Read or ReadMsgIP
-// instead.
-
func sockaddrToIP(sa syscall.Sockaddr) Addr {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
@@ -50,6 +38,10 @@ func (a *IPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
return ipToSockaddr(family, a.IP, 0, a.Zone)
}
+func (a *IPAddr) toLocal(net string) sockaddr {
+ return &IPAddr{loopbackIP(net), a.Zone}
+}
+
func (c *IPConn) readFrom(b []byte) (int, *IPAddr, error) {
// TODO(cw,rsc): consider using readv if we know the family
// type to avoid the header trim/copy
diff --git a/libgo/go/net/iprawsock_test.go b/libgo/go/net/iprawsock_test.go
index 29cd4b6fd0d..5d33b26a91e 100644
--- a/libgo/go/net/iprawsock_test.go
+++ b/libgo/go/net/iprawsock_test.go
@@ -43,6 +43,13 @@ var resolveIPAddrTests = []resolveIPAddrTest{
{"l2tp", "127.0.0.1", nil, UnknownNetworkError("l2tp")},
{"l2tp:gre", "127.0.0.1", nil, UnknownNetworkError("l2tp:gre")},
{"tcp", "1.2.3.4:123", nil, UnknownNetworkError("tcp")},
+
+ {"ip4", "2001:db8::1", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}},
+ {"ip4:icmp", "2001:db8::1", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}},
+ {"ip6", "127.0.0.1", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}},
+ {"ip6", "::ffff:127.0.0.1", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}},
+ {"ip6:ipv6-icmp", "127.0.0.1", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}},
+ {"ip6:ipv6-icmp", "::ffff:127.0.0.1", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}},
}
func TestResolveIPAddr(t *testing.T) {
@@ -54,21 +61,17 @@ func TestResolveIPAddr(t *testing.T) {
defer func() { testHookLookupIP = origTestHookLookupIP }()
testHookLookupIP = lookupLocalhost
- for i, tt := range resolveIPAddrTests {
+ for _, tt := range resolveIPAddrTests {
addr, err := ResolveIPAddr(tt.network, tt.litAddrOrName)
- if err != tt.err {
- t.Errorf("#%d: %v", i, err)
- } else if !reflect.DeepEqual(addr, tt.addr) {
- t.Errorf("#%d: got %#v; want %#v", i, addr, tt.addr)
- }
- if err != nil {
+ if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) {
+ t.Errorf("ResolveIPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err)
continue
}
- rtaddr, err := ResolveIPAddr(addr.Network(), addr.String())
- if err != nil {
- t.Errorf("#%d: %v", i, err)
- } else if !reflect.DeepEqual(rtaddr, addr) {
- t.Errorf("#%d: got %#v; want %#v", i, rtaddr, addr)
+ if err == nil {
+ addr2, err := ResolveIPAddr(addr.Network(), addr.String())
+ if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err {
+ t.Errorf("(%q, %q): ResolveIPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr.Network(), addr.String(), addr2, err, tt.addr, tt.err)
+ }
}
}
}
diff --git a/libgo/go/net/ipsock.go b/libgo/go/net/ipsock.go
index 24daf173ace..f1394a7ed87 100644
--- a/libgo/go/net/ipsock.go
+++ b/libgo/go/net/ipsock.go
@@ -10,6 +10,13 @@ import (
"context"
)
+// BUG(rsc,mikio): On DragonFly BSD and OpenBSD, listening on the
+// "tcp" and "udp" networks does not listen for both IPv4 and IPv6
+// connections. This is due to the fact that IPv4 traffic will not be
+// routed to an IPv6 socket - two separate sockets are required if
+// both address families are to be supported.
+// See inet6(4) for details.
+
var (
// supportsIPv4 reports whether the platform supports IPv4
// networking functionality.
@@ -76,7 +83,7 @@ func (addrs addrList) partition(strategy func(Addr) bool) (primaries, fallbacks
// yielding a list of Addr objects. Known filters are nil, ipv4only,
// and ipv6only. It returns every address when the filter is nil.
// The result contains at least one address when error is nil.
-func filterAddrList(filter func(IPAddr) bool, ips []IPAddr, inetaddr func(IPAddr) Addr) (addrList, error) {
+func filterAddrList(filter func(IPAddr) bool, ips []IPAddr, inetaddr func(IPAddr) Addr, originalAddr string) (addrList, error) {
var addrs addrList
for _, ip := range ips {
if filter == nil || filter(ip) {
@@ -84,21 +91,19 @@ func filterAddrList(filter func(IPAddr) bool, ips []IPAddr, inetaddr func(IPAddr
}
}
if len(addrs) == 0 {
- return nil, errNoSuitableAddress
+ return nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: originalAddr}
}
return addrs, nil
}
-// ipv4only reports whether the kernel supports IPv4 addressing mode
-// and addr is an IPv4 address.
+// ipv4only reports whether addr is an IPv4 address.
func ipv4only(addr IPAddr) bool {
- return supportsIPv4 && addr.IP.To4() != nil
+ return addr.IP.To4() != nil
}
-// ipv6only reports whether the kernel supports IPv6 addressing mode
-// and addr is an IPv6 address except IPv4-mapped IPv6 address.
+// ipv6only reports whether addr is an IPv6 address except IPv4-mapped IPv6 address.
func ipv6only(addr IPAddr) bool {
- return supportsIPv6 && len(addr.IP) == IPv6len && addr.IP.To4() == nil
+ return len(addr.IP) == IPv6len && addr.IP.To4() == nil
}
// SplitHostPort splits a network address of the form "host:port",
@@ -190,7 +195,7 @@ func JoinHostPort(host, port string) string {
// address or a DNS name, and returns a list of internet protocol
// family addresses. The result contains at least one address when
// error is nil.
-func internetAddrList(ctx context.Context, net, addr string) (addrList, error) {
+func (r *Resolver) internetAddrList(ctx context.Context, net, addr string) (addrList, error) {
var (
err error
host, port string
@@ -202,7 +207,7 @@ func internetAddrList(ctx context.Context, net, addr string) (addrList, error) {
if host, port, err = SplitHostPort(addr); err != nil {
return nil, err
}
- if portnum, err = LookupPort(net, port); err != nil {
+ if portnum, err = r.LookupPort(ctx, net, port); err != nil {
return nil, err
}
}
@@ -228,20 +233,21 @@ func internetAddrList(ctx context.Context, net, addr string) (addrList, error) {
if host == "" {
return addrList{inetaddr(IPAddr{})}, nil
}
- // Try as a literal IP address.
- var ip IP
- if ip = parseIPv4(host); ip != nil {
- return addrList{inetaddr(IPAddr{IP: ip})}, nil
- }
- var zone string
- if ip, zone = parseIPv6(host, true); ip != nil {
- return addrList{inetaddr(IPAddr{IP: ip, Zone: zone})}, nil
- }
- // Try as a DNS name.
- ips, err := lookupIPContext(ctx, host)
- if err != nil {
- return nil, err
+
+ // Try as a literal IP address, then as a DNS name.
+ var ips []IPAddr
+ if ip := parseIPv4(host); ip != nil {
+ ips = []IPAddr{{IP: ip}}
+ } else if ip, zone := parseIPv6(host, true); ip != nil {
+ ips = []IPAddr{{IP: ip, Zone: zone}}
+ } else {
+ // Try as a DNS name.
+ ips, err = r.LookupIPAddr(ctx, host)
+ if err != nil {
+ return nil, err
+ }
}
+
var filter func(IPAddr) bool
if net != "" && net[len(net)-1] == '4' {
filter = ipv4only
@@ -249,5 +255,12 @@ func internetAddrList(ctx context.Context, net, addr string) (addrList, error) {
if net != "" && net[len(net)-1] == '6' {
filter = ipv6only
}
- return filterAddrList(filter, ips, inetaddr)
+ return filterAddrList(filter, ips, inetaddr, host)
+}
+
+func loopbackIP(net string) IP {
+ if net != "" && net[len(net)-1] == '6' {
+ return IPv6loopback
+ }
+ return IP{127, 0, 0, 1}
}
diff --git a/libgo/go/net/ipsock_plan9.go b/libgo/go/net/ipsock_plan9.go
index 2b84683eeb5..b7fd344c8ad 100644
--- a/libgo/go/net/ipsock_plan9.go
+++ b/libgo/go/net/ipsock_plan9.go
@@ -63,7 +63,7 @@ func parsePlan9Addr(s string) (ip IP, iport int, err error) {
return nil, 0, &ParseError{Type: "IP address", Text: s}
}
}
- p, _, ok := dtoi(s[i+1:], 0)
+ p, _, ok := dtoi(s[i+1:])
if !ok {
return nil, 0, &ParseError{Type: "port", Text: s}
}
@@ -119,6 +119,11 @@ func startPlan9(ctx context.Context, net string, addr Addr) (ctl *os.File, dest,
return
}
+ if port > 65535 {
+ err = InvalidAddrError("port should be < 65536")
+ return
+ }
+
clone, dest, err := queryCS1(ctx, proto, ip, port)
if err != nil {
return
@@ -193,6 +198,9 @@ func dialPlan9(ctx context.Context, net string, laddr, raddr Addr) (fd *netFD, e
}
func dialPlan9Blocking(ctx context.Context, net string, laddr, raddr Addr) (fd *netFD, err error) {
+ if isWildcard(raddr) {
+ raddr = toLocal(raddr, net)
+ }
f, dest, proto, name, err := startPlan9(ctx, net, raddr)
if err != nil {
return nil, err
@@ -213,7 +221,7 @@ func dialPlan9Blocking(ctx context.Context, net string, laddr, raddr Addr) (fd *
f.Close()
return nil, err
}
- return newFD(proto, name, f, data, laddr, raddr)
+ return newFD(proto, name, nil, f, data, laddr, raddr)
}
func listenPlan9(ctx context.Context, net string, laddr Addr) (fd *netFD, err error) {
@@ -232,11 +240,11 @@ func listenPlan9(ctx context.Context, net string, laddr Addr) (fd *netFD, err er
f.Close()
return nil, err
}
- return newFD(proto, name, f, nil, laddr, nil)
+ return newFD(proto, name, nil, f, nil, laddr, nil)
}
func (fd *netFD) netFD() (*netFD, error) {
- return newFD(fd.net, fd.n, fd.ctl, fd.data, fd.laddr, fd.raddr)
+ return newFD(fd.net, fd.n, fd.listen, fd.ctl, fd.data, fd.laddr, fd.raddr)
}
func (fd *netFD) acceptPlan9() (nfd *netFD, err error) {
@@ -245,27 +253,59 @@ func (fd *netFD) acceptPlan9() (nfd *netFD, err error) {
return nil, err
}
defer fd.readUnlock()
- f, err := os.Open(fd.dir + "/listen")
+ listen, err := os.Open(fd.dir + "/listen")
if err != nil {
return nil, err
}
var buf [16]byte
- n, err := f.Read(buf[:])
+ n, err := listen.Read(buf[:])
if err != nil {
- f.Close()
+ listen.Close()
return nil, err
}
name := string(buf[:n])
+ ctl, err := os.OpenFile(netdir+"/"+fd.net+"/"+name+"/ctl", os.O_RDWR, 0)
+ if err != nil {
+ listen.Close()
+ return nil, err
+ }
data, err := os.OpenFile(netdir+"/"+fd.net+"/"+name+"/data", os.O_RDWR, 0)
if err != nil {
- f.Close()
+ listen.Close()
+ ctl.Close()
return nil, err
}
raddr, err := readPlan9Addr(fd.net, netdir+"/"+fd.net+"/"+name+"/remote")
if err != nil {
+ listen.Close()
+ ctl.Close()
data.Close()
- f.Close()
return nil, err
}
- return newFD(fd.net, name, f, data, fd.laddr, raddr)
+ return newFD(fd.net, name, listen, ctl, data, fd.laddr, raddr)
+}
+
+func isWildcard(a Addr) bool {
+ var wildcard bool
+ switch a := a.(type) {
+ case *TCPAddr:
+ wildcard = a.isWildcard()
+ case *UDPAddr:
+ wildcard = a.isWildcard()
+ case *IPAddr:
+ wildcard = a.isWildcard()
+ }
+ return wildcard
+}
+
+func toLocal(a Addr, net string) Addr {
+ switch a := a.(type) {
+ case *TCPAddr:
+ a.IP = loopbackIP(net)
+ case *UDPAddr:
+ a.IP = loopbackIP(net)
+ case *IPAddr:
+ a.IP = loopbackIP(net)
+ }
+ return a
}
diff --git a/libgo/go/net/ipsock_posix.go b/libgo/go/net/ipsock_posix.go
index abe90ac0e61..ff280c3e4e8 100644
--- a/libgo/go/net/ipsock_posix.go
+++ b/libgo/go/net/ipsock_posix.go
@@ -12,13 +12,6 @@ import (
"syscall"
)
-// BUG(rsc,mikio): On DragonFly BSD and OpenBSD, listening on the
-// "tcp" and "udp" networks does not listen for both IPv4 and IPv6
-// connections. This is due to the fact that IPv4 traffic will not be
-// routed to an IPv6 socket - two separate sockets are required if
-// both address families are to be supported.
-// See inet6(4) for details.
-
func probeIPv4Stack() bool {
s, err := socketFunc(syscall.AF_INET, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
switch err {
@@ -154,6 +147,9 @@ func favoriteAddrFamily(net string, laddr, raddr sockaddr, mode string) (family
// Internet sockets (TCP, UDP, IP)
func internetSocket(ctx context.Context, net string, laddr, raddr sockaddr, sotype, proto int, mode string) (fd *netFD, err error) {
+ if (runtime.GOOS == "windows" || runtime.GOOS == "openbsd" || runtime.GOOS == "nacl") && mode == "dial" && raddr.isWildcard() {
+ raddr = raddr.toLocal(net)
+ }
family, ipv6only := favoriteAddrFamily(net, laddr, raddr, mode)
return socket(ctx, net, family, sotype, proto, ipv6only, laddr, raddr)
}
diff --git a/libgo/go/net/ipsock_test.go b/libgo/go/net/ipsock_test.go
index b36557a1575..1d0f00ff5ee 100644
--- a/libgo/go/net/ipsock_test.go
+++ b/libgo/go/net/ipsock_test.go
@@ -205,13 +205,13 @@ var addrListTests = []struct {
nil,
},
- {nil, nil, testInetaddr, nil, nil, nil, errNoSuitableAddress},
+ {nil, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
- {ipv4only, nil, testInetaddr, nil, nil, nil, errNoSuitableAddress},
- {ipv4only, []IPAddr{{IP: IPv6loopback}}, testInetaddr, nil, nil, nil, errNoSuitableAddress},
+ {ipv4only, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
+ {ipv4only, []IPAddr{{IP: IPv6loopback}}, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
- {ipv6only, nil, testInetaddr, nil, nil, nil, errNoSuitableAddress},
- {ipv6only, []IPAddr{{IP: IPv4(127, 0, 0, 1)}}, testInetaddr, nil, nil, nil, errNoSuitableAddress},
+ {ipv6only, nil, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
+ {ipv6only, []IPAddr{{IP: IPv4(127, 0, 0, 1)}}, testInetaddr, nil, nil, nil, &AddrError{errNoSuitableAddress.Error(), "ADDR"}},
}
func TestAddrList(t *testing.T) {
@@ -220,8 +220,8 @@ func TestAddrList(t *testing.T) {
}
for i, tt := range addrListTests {
- addrs, err := filterAddrList(tt.filter, tt.ips, tt.inetaddr)
- if err != tt.err {
+ addrs, err := filterAddrList(tt.filter, tt.ips, tt.inetaddr, "ADDR")
+ if !reflect.DeepEqual(err, tt.err) {
t.Errorf("#%v: got %v; want %v", i, err, tt.err)
}
if tt.err != nil {
diff --git a/libgo/go/net/lookup.go b/libgo/go/net/lookup.go
index c169e9e902c..cc2013e4325 100644
--- a/libgo/go/net/lookup.go
+++ b/libgo/go/net/lookup.go
@@ -15,94 +15,137 @@ import (
// protocol numbers.
//
// See http://www.iana.org/assignments/protocol-numbers
+//
+// On Unix, this map is augmented by readProtocols via lookupProtocol.
var protocols = map[string]int{
- "icmp": 1, "ICMP": 1,
- "igmp": 2, "IGMP": 2,
- "tcp": 6, "TCP": 6,
- "udp": 17, "UDP": 17,
- "ipv6-icmp": 58, "IPV6-ICMP": 58, "IPv6-ICMP": 58,
+ "icmp": 1,
+ "igmp": 2,
+ "tcp": 6,
+ "udp": 17,
+ "ipv6-icmp": 58,
}
-// LookupHost looks up the given host using the local resolver.
-// It returns an array of that host's addresses.
-func LookupHost(host string) (addrs []string, err error) {
- // Make sure that no matter what we do later, host=="" is rejected.
- // ParseIP, for example, does accept empty strings.
- if host == "" {
- return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host}
+// services contains minimal mappings between services names and port
+// numbers for platforms that don't have a complete list of port numbers
+// (some Solaris distros, nacl, etc).
+// On Unix, this map is augmented by readServices via goLookupPort.
+var services = map[string]map[string]int{
+ "udp": {
+ "domain": 53,
+ },
+ "tcp": {
+ "ftp": 21,
+ "ftps": 990,
+ "gopher": 70, // ʕ◔ϖ◔ʔ
+ "http": 80,
+ "https": 443,
+ "imap2": 143,
+ "imap3": 220,
+ "imaps": 993,
+ "pop3": 110,
+ "pop3s": 995,
+ "smtp": 25,
+ "ssh": 22,
+ "telnet": 23,
+ },
+}
+
+const maxProtoLength = len("RSVP-E2E-IGNORE") + 10 // with room to grow
+
+func lookupProtocolMap(name string) (int, error) {
+ var lowerProtocol [maxProtoLength]byte
+ n := copy(lowerProtocol[:], name)
+ lowerASCIIBytes(lowerProtocol[:n])
+ proto, found := protocols[string(lowerProtocol[:n])]
+ if !found || n != len(name) {
+ return 0, &AddrError{Err: "unknown IP protocol specified", Addr: name}
}
- if ip := ParseIP(host); ip != nil {
- return []string{host}, nil
+ return proto, nil
+}
+
+const maxServiceLength = len("mobility-header") + 10 // with room to grow
+
+func lookupPortMap(network, service string) (port int, error error) {
+ switch network {
+ case "tcp4", "tcp6":
+ network = "tcp"
+ case "udp4", "udp6":
+ network = "udp"
}
- return lookupHost(context.Background(), host)
+
+ if m, ok := services[network]; ok {
+ var lowerService [maxServiceLength]byte
+ n := copy(lowerService[:], service)
+ lowerASCIIBytes(lowerService[:n])
+ if port, ok := m[string(lowerService[:n])]; ok && n == len(service) {
+ return port, nil
+ }
+ }
+ return 0, &AddrError{Err: "unknown port", Addr: network + "/" + service}
}
-// LookupIP looks up host using the local resolver.
-// It returns an array of that host's IPv4 and IPv6 addresses.
-func LookupIP(host string) (ips []IP, err error) {
+// DefaultResolver is the resolver used by the package-level Lookup
+// functions and by Dialers without a specified Resolver.
+var DefaultResolver = &Resolver{}
+
+// A Resolver looks up names and numbers.
+//
+// A nil *Resolver is equivalent to a zero Resolver.
+type Resolver struct {
+ // PreferGo controls whether Go's built-in DNS resolver is preferred
+ // on platforms where it's available. It is equivalent to setting
+ // GODEBUG=netdns=go, but scoped to just this resolver.
+ PreferGo bool
+
+ // TODO(bradfitz): optional interface impl override hook
+ // TODO(bradfitz): Timeout time.Duration?
+}
+
+// LookupHost looks up the given host using the local resolver.
+// It returns a slice of that host's addresses.
+func LookupHost(host string) (addrs []string, err error) {
+ return DefaultResolver.LookupHost(context.Background(), host)
+}
+
+// LookupHost looks up the given host using the local resolver.
+// It returns a slice of that host's addresses.
+func (r *Resolver) LookupHost(ctx context.Context, host string) (addrs []string, err error) {
// Make sure that no matter what we do later, host=="" is rejected.
// ParseIP, for example, does accept empty strings.
if host == "" {
return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host}
}
if ip := ParseIP(host); ip != nil {
- return []IP{ip}, nil
- }
- addrs, err := lookupIPMerge(context.Background(), host)
- if err != nil {
- return
- }
- ips = make([]IP, len(addrs))
- for i, addr := range addrs {
- ips[i] = addr.IP
+ return []string{host}, nil
}
- return
-}
-
-var lookupGroup singleflight.Group
-
-// lookupIPMerge wraps lookupIP, but makes sure that for any given
-// host, only one lookup is in-flight at a time. The returned memory
-// is always owned by the caller.
-func lookupIPMerge(ctx context.Context, host string) (addrs []IPAddr, err error) {
- addrsi, err, shared := lookupGroup.Do(host, func() (interface{}, error) {
- return testHookLookupIP(ctx, lookupIP, host)
- })
- return lookupIPReturn(addrsi, err, shared)
+ return r.lookupHost(ctx, host)
}
-// lookupIPReturn turns the return values from singleflight.Do into
-// the return values from LookupIP.
-func lookupIPReturn(addrsi interface{}, err error, shared bool) ([]IPAddr, error) {
+// LookupIP looks up host using the local resolver.
+// It returns a slice of that host's IPv4 and IPv6 addresses.
+func LookupIP(host string) ([]IP, error) {
+ addrs, err := DefaultResolver.LookupIPAddr(context.Background(), host)
if err != nil {
return nil, err
}
- addrs := addrsi.([]IPAddr)
- if shared {
- clone := make([]IPAddr, len(addrs))
- copy(clone, addrs)
- addrs = clone
+ ips := make([]IP, len(addrs))
+ for i, ia := range addrs {
+ ips[i] = ia.IP
}
- return addrs, nil
+ return ips, nil
}
-// ipAddrsEface returns an empty interface slice of addrs.
-func ipAddrsEface(addrs []IPAddr) []interface{} {
- s := make([]interface{}, len(addrs))
- for i, v := range addrs {
- s[i] = v
+// LookupIPAddr looks up host using the local resolver.
+// It returns a slice of that host's IPv4 and IPv6 addresses.
+func (r *Resolver) LookupIPAddr(ctx context.Context, host string) ([]IPAddr, error) {
+ // Make sure that no matter what we do later, host=="" is rejected.
+ // ParseIP, for example, does accept empty strings.
+ if host == "" {
+ return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host}
+ }
+ if ip := ParseIP(host); ip != nil {
+ return []IPAddr{{IP: ip}}, nil
}
- return s
-}
-
-// lookupIPContext looks up a hostname with a context.
-//
-// TODO(bradfitz): rename this function. All the other
-// build-tag-specific lookupIP funcs also take a context now, so this
-// name is no longer great. Maybe make this lookupIPMerge and ditch
-// the other one, making its callers call this instead with a
-// context.Background().
-func lookupIPContext(ctx context.Context, host string) (addrs []IPAddr, err error) {
trace, _ := ctx.Value(nettrace.TraceKey{}).(*nettrace.Trace)
if trace != nil && trace.DNSStart != nil {
trace.DNSStart(host)
@@ -110,7 +153,7 @@ func lookupIPContext(ctx context.Context, host string) (addrs []IPAddr, err erro
// The underlying resolver func is lookupIP by default but it
// can be overridden by tests. This is needed by net/http, so it
// uses a context key instead of unexported variables.
- resolverFunc := lookupIP
+ resolverFunc := r.lookupIP
if alt, _ := ctx.Value(nettrace.LookupIPAltResolverKey{}).(func(context.Context, string) ([]IPAddr, error)); alt != nil {
resolverFunc = alt
}
@@ -140,11 +183,46 @@ func lookupIPContext(ctx context.Context, host string) (addrs []IPAddr, err erro
}
}
+// lookupGroup merges LookupIPAddr calls together for lookups
+// for the same host. The lookupGroup key is is the LookupIPAddr.host
+// argument.
+// The return values are ([]IPAddr, error).
+var lookupGroup singleflight.Group
+
+// lookupIPReturn turns the return values from singleflight.Do into
+// the return values from LookupIP.
+func lookupIPReturn(addrsi interface{}, err error, shared bool) ([]IPAddr, error) {
+ if err != nil {
+ return nil, err
+ }
+ addrs := addrsi.([]IPAddr)
+ if shared {
+ clone := make([]IPAddr, len(addrs))
+ copy(clone, addrs)
+ addrs = clone
+ }
+ return addrs, nil
+}
+
+// ipAddrsEface returns an empty interface slice of addrs.
+func ipAddrsEface(addrs []IPAddr) []interface{} {
+ s := make([]interface{}, len(addrs))
+ for i, v := range addrs {
+ s[i] = v
+ }
+ return s
+}
+
// LookupPort looks up the port for the given network and service.
func LookupPort(network, service string) (port int, err error) {
+ return DefaultResolver.LookupPort(context.Background(), network, service)
+}
+
+// LookupPort looks up the port for the given network and service.
+func (r *Resolver) LookupPort(ctx context.Context, network, service string) (port int, err error) {
port, needsLookup := parsePort(service)
if needsLookup {
- port, err = lookupPort(context.Background(), network, service)
+ port, err = r.lookupPort(ctx, network, service)
if err != nil {
return 0, err
}
@@ -155,12 +233,32 @@ func LookupPort(network, service string) (port int, err error) {
return port, nil
}
-// LookupCNAME returns the canonical DNS host for the given name.
+// LookupCNAME returns the canonical name for the given host.
+// Callers that do not care about the canonical name can call
+// LookupHost or LookupIP directly; both take care of resolving
+// the canonical name as part of the lookup.
+//
+// A canonical name is the final name after following zero
+// or more CNAME records.
+// LookupCNAME does not return an error if host does not
+// contain DNS "CNAME" records, as long as host resolves to
+// address records.
+func LookupCNAME(host string) (cname string, err error) {
+ return DefaultResolver.lookupCNAME(context.Background(), host)
+}
+
+// LookupCNAME returns the canonical name for the given host.
// Callers that do not care about the canonical name can call
// LookupHost or LookupIP directly; both take care of resolving
// the canonical name as part of the lookup.
-func LookupCNAME(name string) (cname string, err error) {
- return lookupCNAME(context.Background(), name)
+//
+// A canonical name is the final name after following zero
+// or more CNAME records.
+// LookupCNAME does not return an error if host does not
+// contain DNS "CNAME" records, as long as host resolves to
+// address records.
+func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string, err error) {
+ return r.lookupCNAME(ctx, host)
}
// LookupSRV tries to resolve an SRV query of the given service,
@@ -173,26 +271,63 @@ func LookupCNAME(name string) (cname string, err error) {
// publishing SRV records under non-standard names, if both service
// and proto are empty strings, LookupSRV looks up name directly.
func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
- return lookupSRV(context.Background(), service, proto, name)
+ return DefaultResolver.lookupSRV(context.Background(), service, proto, name)
+}
+
+// LookupSRV tries to resolve an SRV query of the given service,
+// protocol, and domain name. The proto is "tcp" or "udp".
+// The returned records are sorted by priority and randomized
+// by weight within a priority.
+//
+// LookupSRV constructs the DNS name to look up following RFC 2782.
+// That is, it looks up _service._proto.name. To accommodate services
+// publishing SRV records under non-standard names, if both service
+// and proto are empty strings, LookupSRV looks up name directly.
+func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*SRV, err error) {
+ return r.lookupSRV(ctx, service, proto, name)
+}
+
+// LookupMX returns the DNS MX records for the given domain name sorted by preference.
+func LookupMX(name string) ([]*MX, error) {
+ return DefaultResolver.lookupMX(context.Background(), name)
}
// LookupMX returns the DNS MX records for the given domain name sorted by preference.
-func LookupMX(name string) (mxs []*MX, err error) {
- return lookupMX(context.Background(), name)
+func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
+ return r.lookupMX(ctx, name)
}
// LookupNS returns the DNS NS records for the given domain name.
-func LookupNS(name string) (nss []*NS, err error) {
- return lookupNS(context.Background(), name)
+func LookupNS(name string) ([]*NS, error) {
+ return DefaultResolver.lookupNS(context.Background(), name)
+}
+
+// LookupNS returns the DNS NS records for the given domain name.
+func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) {
+ return r.lookupNS(ctx, name)
}
// LookupTXT returns the DNS TXT records for the given domain name.
-func LookupTXT(name string) (txts []string, err error) {
- return lookupTXT(context.Background(), name)
+func LookupTXT(name string) ([]string, error) {
+ return DefaultResolver.lookupTXT(context.Background(), name)
+}
+
+// LookupTXT returns the DNS TXT records for the given domain name.
+func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error) {
+ return r.lookupTXT(ctx, name)
}
// LookupAddr performs a reverse lookup for the given address, returning a list
// of names mapping to that address.
+//
+// When using the host C library resolver, at most one result will be
+// returned. To bypass the host resolver, use a custom Resolver.
func LookupAddr(addr string) (names []string, err error) {
- return lookupAddr(context.Background(), addr)
+ return DefaultResolver.lookupAddr(context.Background(), addr)
+}
+
+// LookupAddr performs a reverse lookup for the given address, returning a list
+// of names mapping to that address.
+func (r *Resolver) LookupAddr(ctx context.Context, addr string) (names []string, err error) {
+ return r.lookupAddr(ctx, addr)
}
diff --git a/libgo/go/net/lookup_nacl.go b/libgo/go/net/lookup_nacl.go
new file mode 100644
index 00000000000..43cebad7602
--- /dev/null
+++ b/libgo/go/net/lookup_nacl.go
@@ -0,0 +1,52 @@
+// 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 nacl
+
+package net
+
+import (
+ "context"
+ "syscall"
+)
+
+func lookupProtocol(ctx context.Context, name string) (proto int, err error) {
+ return lookupProtocolMap(name)
+}
+
+func (*Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
+
+func (*Resolver) lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
+
+func (*Resolver) lookupPort(ctx context.Context, network, service string) (port int, err error) {
+ return goLookupPort(network, service)
+}
+
+func (*Resolver) lookupCNAME(ctx context.Context, name string) (cname string, err error) {
+ return "", syscall.ENOPROTOOPT
+}
+
+func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (cname string, srvs []*SRV, err error) {
+ return "", nil, syscall.ENOPROTOOPT
+}
+
+func (*Resolver) lookupMX(ctx context.Context, name string) (mxs []*MX, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
+
+func (*Resolver) lookupNS(ctx context.Context, name string) (nss []*NS, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
+
+func (*Resolver) lookupTXT(ctx context.Context, name string) (txts []string, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
+
+func (*Resolver) lookupAddr(ctx context.Context, addr string) (ptrs []string, err error) {
+ return nil, syscall.ENOPROTOOPT
+}
diff --git a/libgo/go/net/lookup_plan9.go b/libgo/go/net/lookup_plan9.go
index 3f7af2a1747..f81e220fc8c 100644
--- a/libgo/go/net/lookup_plan9.go
+++ b/libgo/go/net/lookup_plan9.go
@@ -111,17 +111,20 @@ func lookupProtocol(ctx context.Context, name string) (proto int, err error) {
return 0, UnknownNetworkError(name)
}
s := f[1]
- if n, _, ok := dtoi(s, byteIndex(s, '=')+1); ok {
+ if n, _, ok := dtoi(s[byteIndex(s, '=')+1:]); ok {
return n, nil
}
return 0, UnknownNetworkError(name)
}
-func lookupHost(ctx context.Context, host string) (addrs []string, err error) {
+func (*Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) {
// Use netdir/cs instead of netdir/dns because cs knows about
// host names in local network (e.g. from /lib/ndb/local)
lines, err := queryCS(ctx, "net", host, "1")
if err != nil {
+ if stringsHasSuffix(err.Error(), "dns failure") {
+ err = errNoSuchHost
+ }
return
}
loop:
@@ -148,8 +151,8 @@ loop:
return
}
-func lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
- lits, err := lookupHost(ctx, host)
+func (r *Resolver) lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
+ lits, err := r.lookupHost(ctx, host)
if err != nil {
return
}
@@ -163,14 +166,14 @@ func lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
return
}
-func lookupPort(ctx context.Context, network, service string) (port int, err error) {
+func (*Resolver) lookupPort(ctx context.Context, network, service string) (port int, err error) {
switch network {
case "tcp4", "tcp6":
network = "tcp"
case "udp4", "udp6":
network = "udp"
}
- lines, err := queryCS(ctx, network, "127.0.0.1", service)
+ lines, err := queryCS(ctx, network, "127.0.0.1", toLower(service))
if err != nil {
return
}
@@ -186,15 +189,19 @@ func lookupPort(ctx context.Context, network, service string) (port int, err err
if i := byteIndex(s, '!'); i >= 0 {
s = s[i+1:] // remove address
}
- if n, _, ok := dtoi(s, 0); ok {
+ if n, _, ok := dtoi(s); ok {
return n, nil
}
return 0, unknownPortError
}
-func lookupCNAME(ctx context.Context, name string) (cname string, err error) {
+func (*Resolver) lookupCNAME(ctx context.Context, name string) (cname string, err error) {
lines, err := queryDNS(ctx, name, "cname")
if err != nil {
+ if stringsHasSuffix(err.Error(), "dns failure") {
+ cname = name + "."
+ err = nil
+ }
return
}
if len(lines) > 0 {
@@ -205,7 +212,7 @@ func lookupCNAME(ctx context.Context, name string) (cname string, err error) {
return "", errors.New("bad response from ndb/dns")
}
-func lookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*SRV, err error) {
+func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*SRV, err error) {
var target string
if service == "" && proto == "" {
target = name
@@ -221,9 +228,9 @@ func lookupSRV(ctx context.Context, service, proto, name string) (cname string,
if len(f) < 6 {
continue
}
- port, _, portOk := dtoi(f[4], 0)
- priority, _, priorityOk := dtoi(f[3], 0)
- weight, _, weightOk := dtoi(f[2], 0)
+ port, _, portOk := dtoi(f[4])
+ priority, _, priorityOk := dtoi(f[3])
+ weight, _, weightOk := dtoi(f[2])
if !(portOk && priorityOk && weightOk) {
continue
}
@@ -234,7 +241,7 @@ func lookupSRV(ctx context.Context, service, proto, name string) (cname string,
return
}
-func lookupMX(ctx context.Context, name string) (mx []*MX, err error) {
+func (*Resolver) lookupMX(ctx context.Context, name string) (mx []*MX, err error) {
lines, err := queryDNS(ctx, name, "mx")
if err != nil {
return
@@ -244,7 +251,7 @@ func lookupMX(ctx context.Context, name string) (mx []*MX, err error) {
if len(f) < 4 {
continue
}
- if pref, _, ok := dtoi(f[2], 0); ok {
+ if pref, _, ok := dtoi(f[2]); ok {
mx = append(mx, &MX{absDomainName([]byte(f[3])), uint16(pref)})
}
}
@@ -252,7 +259,7 @@ func lookupMX(ctx context.Context, name string) (mx []*MX, err error) {
return
}
-func lookupNS(ctx context.Context, name string) (ns []*NS, err error) {
+func (*Resolver) lookupNS(ctx context.Context, name string) (ns []*NS, err error) {
lines, err := queryDNS(ctx, name, "ns")
if err != nil {
return
@@ -267,7 +274,7 @@ func lookupNS(ctx context.Context, name string) (ns []*NS, err error) {
return
}
-func lookupTXT(ctx context.Context, name string) (txt []string, err error) {
+func (*Resolver) lookupTXT(ctx context.Context, name string) (txt []string, err error) {
lines, err := queryDNS(ctx, name, "txt")
if err != nil {
return
@@ -280,7 +287,7 @@ func lookupTXT(ctx context.Context, name string) (txt []string, err error) {
return
}
-func lookupAddr(ctx context.Context, addr string) (name []string, err error) {
+func (*Resolver) lookupAddr(ctx context.Context, addr string) (name []string, err error) {
arpa, err := reverseaddr(addr)
if err != nil {
return
diff --git a/libgo/go/net/lookup_stub.go b/libgo/go/net/lookup_stub.go
deleted file mode 100644
index bd096b39652..00000000000
--- a/libgo/go/net/lookup_stub.go
+++ /dev/null
@@ -1,52 +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 nacl
-
-package net
-
-import (
- "context"
- "syscall"
-)
-
-func lookupProtocol(ctx context.Context, name string) (proto int, err error) {
- return 0, syscall.ENOPROTOOPT
-}
-
-func lookupHost(ctx context.Context, host string) (addrs []string, err error) {
- return nil, syscall.ENOPROTOOPT
-}
-
-func lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
- return nil, syscall.ENOPROTOOPT
-}
-
-func lookupPort(ctx context.Context, network, service string) (port int, err error) {
- return 0, syscall.ENOPROTOOPT
-}
-
-func lookupCNAME(ctx context.Context, name string) (cname string, err error) {
- return "", syscall.ENOPROTOOPT
-}
-
-func lookupSRV(ctx context.Context, service, proto, name string) (cname string, srvs []*SRV, err error) {
- return "", nil, syscall.ENOPROTOOPT
-}
-
-func lookupMX(ctx context.Context, name string) (mxs []*MX, err error) {
- return nil, syscall.ENOPROTOOPT
-}
-
-func lookupNS(ctx context.Context, name string) (nss []*NS, err error) {
- return nil, syscall.ENOPROTOOPT
-}
-
-func lookupTXT(ctx context.Context, name string) (txts []string, err error) {
- return nil, syscall.ENOPROTOOPT
-}
-
-func lookupAddr(ctx context.Context, addr string) (ptrs []string, err error) {
- return nil, syscall.ENOPROTOOPT
-}
diff --git a/libgo/go/net/lookup_test.go b/libgo/go/net/lookup_test.go
index b3aeb85afbc..36db56acd03 100644
--- a/libgo/go/net/lookup_test.go
+++ b/libgo/go/net/lookup_test.go
@@ -243,14 +243,15 @@ func TestLookupIPv6LinkLocalAddr(t *testing.T) {
}
}
-var lookupIANACNAMETests = []struct {
+var lookupCNAMETests = []struct {
name, cname string
}{
{"www.iana.org", "icann.org."},
{"www.iana.org.", "icann.org."},
+ {"www.google.com", "google.com."},
}
-func TestLookupIANACNAME(t *testing.T) {
+func TestLookupCNAME(t *testing.T) {
if testenv.Builder() == "" {
testenv.MustHaveExternalNetwork(t)
}
@@ -259,7 +260,7 @@ func TestLookupIANACNAME(t *testing.T) {
t.Skip("IPv4 is required")
}
- for _, tt := range lookupIANACNAMETests {
+ for _, tt := range lookupCNAMETests {
cname, err := LookupCNAME(tt.name)
if err != nil {
t.Fatal(err)
@@ -398,11 +399,11 @@ func TestDNSFlood(t *testing.T) {
for i := 0; i < N; i++ {
name := fmt.Sprintf("%d.net-test.golang.org", i)
go func() {
- _, err := lookupIPContext(ctxHalfTimeout, name)
+ _, err := DefaultResolver.LookupIPAddr(ctxHalfTimeout, name)
c <- err
}()
go func() {
- _, err := lookupIPContext(ctxTimeout, name)
+ _, err := DefaultResolver.LookupIPAddr(ctxTimeout, name)
c <- err
}()
}
@@ -616,7 +617,7 @@ func srvString(srvs []*SRV) string {
func TestLookupPort(t *testing.T) {
// See http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
//
- // Please be careful about adding new mappings for testings.
+ // Please be careful about adding new test cases.
// There are platforms having incomplete mappings for
// restricted resource access and security reasons.
type test struct {
@@ -648,8 +649,6 @@ func TestLookupPort(t *testing.T) {
}
switch runtime.GOOS {
- case "nacl":
- t.Skipf("not supported on %s", runtime.GOOS)
case "android":
if netGo {
t.Skipf("not supported on %s without cgo; see golang.org/issues/14576", runtime.GOOS)
@@ -670,3 +669,73 @@ func TestLookupPort(t *testing.T) {
}
}
}
+
+// Like TestLookupPort but with minimal tests that should always pass
+// because the answers are baked-in to the net package.
+func TestLookupPort_Minimal(t *testing.T) {
+ type test struct {
+ network string
+ name string
+ port int
+ }
+ var tests = []test{
+ {"tcp", "http", 80},
+ {"tcp", "HTTP", 80}, // case shouldn't matter
+ {"tcp", "https", 443},
+ {"tcp", "ssh", 22},
+ {"tcp", "gopher", 70},
+ {"tcp4", "http", 80},
+ {"tcp6", "http", 80},
+ }
+
+ for _, tt := range tests {
+ port, err := LookupPort(tt.network, tt.name)
+ if port != tt.port || err != nil {
+ t.Errorf("LookupPort(%q, %q) = %d, %v; want %d, error=nil", tt.network, tt.name, port, err, tt.port)
+ }
+ }
+}
+
+func TestLookupProtocol_Minimal(t *testing.T) {
+ type test struct {
+ name string
+ want int
+ }
+ var tests = []test{
+ {"tcp", 6},
+ {"TcP", 6}, // case shouldn't matter
+ {"icmp", 1},
+ {"igmp", 2},
+ {"udp", 17},
+ {"ipv6-icmp", 58},
+ }
+
+ for _, tt := range tests {
+ got, err := lookupProtocol(context.Background(), tt.name)
+ if got != tt.want || err != nil {
+ t.Errorf("LookupProtocol(%q) = %d, %v; want %d, error=nil", tt.name, got, err, tt.want)
+ }
+ }
+
+}
+
+func TestLookupNonLDH(t *testing.T) {
+ if runtime.GOOS == "nacl" {
+ t.Skip("skip on nacl")
+ }
+ if fixup := forceGoDNS(); fixup != nil {
+ defer fixup()
+ }
+
+ // "LDH" stands for letters, digits, and hyphens and is the usual
+ // description of standard DNS names.
+ // This test is checking that other kinds of names are reported
+ // as not found, not reported as invalid names.
+ addrs, err := LookupHost("!!!.###.bogus..domain.")
+ if err == nil {
+ t.Fatalf("lookup succeeded: %v", addrs)
+ }
+ if !strings.HasSuffix(err.Error(), errNoSuchHost.Error()) {
+ t.Fatalf("lookup error = %v, want %v", err, errNoSuchHost)
+ }
+}
diff --git a/libgo/go/net/lookup_unix.go b/libgo/go/net/lookup_unix.go
index 15397e8105a..be2ced9c393 100644
--- a/libgo/go/net/lookup_unix.go
+++ b/libgo/go/net/lookup_unix.go
@@ -26,7 +26,7 @@ func readProtocols() {
if len(f) < 2 {
continue
}
- if proto, _, ok := dtoi(f[1], 0); ok {
+ if proto, _, ok := dtoi(f[1]); ok {
if _, ok := protocols[f[0]]; !ok {
protocols[f[0]] = proto
}
@@ -45,16 +45,12 @@ func readProtocols() {
// returns correspondent protocol number.
func lookupProtocol(_ context.Context, name string) (int, error) {
onceReadProtocols.Do(readProtocols)
- proto, found := protocols[name]
- if !found {
- return 0, &AddrError{Err: "unknown IP protocol specified", Addr: name}
- }
- return proto, nil
+ return lookupProtocolMap(name)
}
-func lookupHost(ctx context.Context, host string) (addrs []string, err error) {
+func (r *Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) {
order := systemConf().hostLookupOrder(host)
- if order == hostLookupCgo {
+ if !r.PreferGo && order == hostLookupCgo {
if addrs, err, ok := cgoLookupHost(ctx, host); ok {
return addrs, err
}
@@ -64,7 +60,10 @@ func lookupHost(ctx context.Context, host string) (addrs []string, err error) {
return goLookupHostOrder(ctx, host, order)
}
-func lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
+func (r *Resolver) lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
+ if r.PreferGo {
+ return goLookupIP(ctx, host)
+ }
order := systemConf().hostLookupOrder(host)
if order == hostLookupCgo {
if addrs, err, ok := cgoLookupIP(ctx, host); ok {
@@ -73,25 +72,28 @@ func lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
// cgo not available (or netgo); fall back to Go's DNS resolver
order = hostLookupFilesDNS
}
- return goLookupIPOrder(ctx, host, order)
+ addrs, _, err = goLookupIPCNAMEOrder(ctx, host, order)
+ return
}
-func lookupPort(ctx context.Context, network, service string) (int, error) {
- // TODO: use the context if there ever becomes a need. Related
- // is issue 15321. But port lookup generally just involves
- // local files, and the os package has no context support. The
- // files might be on a remote filesystem, though. This should
- // probably race goroutines if ctx != context.Background().
- if systemConf().canUseCgo() {
+func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) {
+ if !r.PreferGo && systemConf().canUseCgo() {
if port, err, ok := cgoLookupPort(ctx, network, service); ok {
+ if err != nil {
+ // Issue 18213: if cgo fails, first check to see whether we
+ // have the answer baked-in to the net package.
+ if port, err := goLookupPort(network, service); err == nil {
+ return port, nil
+ }
+ }
return port, err
}
}
return goLookupPort(network, service)
}
-func lookupCNAME(ctx context.Context, name string) (string, error) {
- if systemConf().canUseCgo() {
+func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) {
+ if !r.PreferGo && systemConf().canUseCgo() {
if cname, err, ok := cgoLookupCNAME(ctx, name); ok {
return cname, err
}
@@ -99,7 +101,7 @@ func lookupCNAME(ctx context.Context, name string) (string, error) {
return goLookupCNAME(ctx, name)
}
-func lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
+func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
var target string
if service == "" && proto == "" {
target = name
@@ -119,7 +121,7 @@ func lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV
return cname, srvs, nil
}
-func lookupMX(ctx context.Context, name string) ([]*MX, error) {
+func (*Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) {
_, rrs, err := lookup(ctx, name, dnsTypeMX)
if err != nil {
return nil, err
@@ -133,7 +135,7 @@ func lookupMX(ctx context.Context, name string) ([]*MX, error) {
return mxs, nil
}
-func lookupNS(ctx context.Context, name string) ([]*NS, error) {
+func (*Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) {
_, rrs, err := lookup(ctx, name, dnsTypeNS)
if err != nil {
return nil, err
@@ -145,7 +147,7 @@ func lookupNS(ctx context.Context, name string) ([]*NS, error) {
return nss, nil
}
-func lookupTXT(ctx context.Context, name string) ([]string, error) {
+func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) {
_, rrs, err := lookup(ctx, name, dnsTypeTXT)
if err != nil {
return nil, err
@@ -157,8 +159,8 @@ func lookupTXT(ctx context.Context, name string) ([]string, error) {
return txts, nil
}
-func lookupAddr(ctx context.Context, addr string) ([]string, error) {
- if systemConf().canUseCgo() {
+func (r *Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) {
+ if !r.PreferGo && systemConf().canUseCgo() {
if ptrs, err, ok := cgoLookupPTR(ctx, addr); ok {
return ptrs, err
}
diff --git a/libgo/go/net/lookup_windows.go b/libgo/go/net/lookup_windows.go
index 5f65c2d00d4..5808293058a 100644
--- a/libgo/go/net/lookup_windows.go
+++ b/libgo/go/net/lookup_windows.go
@@ -12,10 +12,20 @@ import (
"unsafe"
)
+const _WSAHOST_NOT_FOUND = syscall.Errno(11001)
+
+func winError(call string, err error) error {
+ switch err {
+ case _WSAHOST_NOT_FOUND:
+ return errNoSuchHost
+ }
+ return os.NewSyscallError(call, err)
+}
+
func getprotobyname(name string) (proto int, err error) {
p, err := syscall.GetProtoByName(name)
if err != nil {
- return 0, os.NewSyscallError("getprotobyname", err)
+ return 0, winError("getprotobyname", err)
}
return int(p.Proto), nil
}
@@ -43,7 +53,7 @@ func lookupProtocol(ctx context.Context, name string) (int, error) {
select {
case r := <-ch:
if r.err != nil {
- if proto, ok := protocols[name]; ok {
+ if proto, err := lookupProtocolMap(name); err == nil {
return proto, nil
}
r.err = &DNSError{Err: r.err.Error(), Name: name}
@@ -54,8 +64,8 @@ func lookupProtocol(ctx context.Context, name string) (int, error) {
}
}
-func lookupHost(ctx context.Context, name string) ([]string, error) {
- ips, err := lookupIP(ctx, name)
+func (r *Resolver) lookupHost(ctx context.Context, name string) ([]string, error) {
+ ips, err := r.lookupIP(ctx, name)
if err != nil {
return nil, err
}
@@ -66,8 +76,8 @@ func lookupHost(ctx context.Context, name string) ([]string, error) {
return addrs, nil
}
-func lookupIP(ctx context.Context, name string) ([]IPAddr, error) {
- // TODO(bradfitz,brainman): use ctx?
+func (r *Resolver) lookupIP(ctx context.Context, name string) ([]IPAddr, error) {
+ // TODO(bradfitz,brainman): use ctx more. See TODO below.
type ret struct {
addrs []IPAddr
@@ -85,7 +95,7 @@ func lookupIP(ctx context.Context, name string) ([]IPAddr, error) {
var result *syscall.AddrinfoW
e := syscall.GetAddrInfoW(syscall.StringToUTF16Ptr(name), nil, &hints, &result)
if e != nil {
- ch <- ret{err: &DNSError{Err: os.NewSyscallError("getaddrinfow", e).Error(), Name: name}}
+ ch <- ret{err: &DNSError{Err: winError("getaddrinfow", e).Error(), Name: name}}
}
defer syscall.FreeAddrInfoW(result)
addrs := make([]IPAddr, 0, 5)
@@ -125,7 +135,11 @@ func lookupIP(ctx context.Context, name string) ([]IPAddr, error) {
}
}
-func lookupPort(ctx context.Context, network, service string) (int, error) {
+func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int, error) {
+ if r.PreferGo {
+ return lookupPortMap(network, service)
+ }
+
// TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this.
acquireThread()
defer releaseThread()
@@ -144,7 +158,10 @@ func lookupPort(ctx context.Context, network, service string) (int, error) {
var result *syscall.AddrinfoW
e := syscall.GetAddrInfoW(nil, syscall.StringToUTF16Ptr(service), &hints, &result)
if e != nil {
- return 0, &DNSError{Err: os.NewSyscallError("getaddrinfow", e).Error(), Name: network + "/" + service}
+ if port, err := lookupPortMap(network, service); err == nil {
+ return port, nil
+ }
+ return 0, &DNSError{Err: winError("getaddrinfow", e).Error(), Name: network + "/" + service}
}
defer syscall.FreeAddrInfoW(result)
if result == nil {
@@ -162,7 +179,7 @@ func lookupPort(ctx context.Context, network, service string) (int, error) {
return 0, &DNSError{Err: syscall.EINVAL.Error(), Name: network + "/" + service}
}
-func lookupCNAME(ctx context.Context, name string) (string, error) {
+func (*Resolver) lookupCNAME(ctx context.Context, name string) (string, error) {
// TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this.
acquireThread()
defer releaseThread()
@@ -174,7 +191,7 @@ func lookupCNAME(ctx context.Context, name string) (string, error) {
return absDomainName([]byte(name)), nil
}
if e != nil {
- return "", &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: name}
+ return "", &DNSError{Err: winError("dnsquery", e).Error(), Name: name}
}
defer syscall.DnsRecordListFree(r, 1)
@@ -183,7 +200,7 @@ func lookupCNAME(ctx context.Context, name string) (string, error) {
return absDomainName([]byte(cname)), nil
}
-func lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
+func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
// TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this.
acquireThread()
defer releaseThread()
@@ -196,7 +213,7 @@ func lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV
var r *syscall.DNSRecord
e := syscall.DnsQuery(target, syscall.DNS_TYPE_SRV, 0, nil, &r, nil)
if e != nil {
- return "", nil, &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: target}
+ return "", nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: target}
}
defer syscall.DnsRecordListFree(r, 1)
@@ -209,14 +226,14 @@ func lookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV
return absDomainName([]byte(target)), srvs, nil
}
-func lookupMX(ctx context.Context, name string) ([]*MX, error) {
+func (*Resolver) lookupMX(ctx context.Context, name string) ([]*MX, error) {
// TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this.
acquireThread()
defer releaseThread()
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_MX, 0, nil, &r, nil)
if e != nil {
- return nil, &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: name}
+ return nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: name}
}
defer syscall.DnsRecordListFree(r, 1)
@@ -229,14 +246,14 @@ func lookupMX(ctx context.Context, name string) ([]*MX, error) {
return mxs, nil
}
-func lookupNS(ctx context.Context, name string) ([]*NS, error) {
+func (*Resolver) lookupNS(ctx context.Context, name string) ([]*NS, error) {
// TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this.
acquireThread()
defer releaseThread()
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_NS, 0, nil, &r, nil)
if e != nil {
- return nil, &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: name}
+ return nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: name}
}
defer syscall.DnsRecordListFree(r, 1)
@@ -248,14 +265,14 @@ func lookupNS(ctx context.Context, name string) ([]*NS, error) {
return nss, nil
}
-func lookupTXT(ctx context.Context, name string) ([]string, error) {
+func (*Resolver) lookupTXT(ctx context.Context, name string) ([]string, error) {
// TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this.
acquireThread()
defer releaseThread()
var r *syscall.DNSRecord
e := syscall.DnsQuery(name, syscall.DNS_TYPE_TEXT, 0, nil, &r, nil)
if e != nil {
- return nil, &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: name}
+ return nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: name}
}
defer syscall.DnsRecordListFree(r, 1)
@@ -270,7 +287,7 @@ func lookupTXT(ctx context.Context, name string) ([]string, error) {
return txts, nil
}
-func lookupAddr(ctx context.Context, addr string) ([]string, error) {
+func (*Resolver) lookupAddr(ctx context.Context, addr string) ([]string, error) {
// TODO(bradfitz): finish ctx plumbing. Nothing currently depends on this.
acquireThread()
defer releaseThread()
@@ -281,7 +298,7 @@ func lookupAddr(ctx context.Context, addr string) ([]string, error) {
var r *syscall.DNSRecord
e := syscall.DnsQuery(arpa, syscall.DNS_TYPE_PTR, 0, nil, &r, nil)
if e != nil {
- return nil, &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: addr}
+ return nil, &DNSError{Err: winError("dnsquery", e).Error(), Name: addr}
}
defer syscall.DnsRecordListFree(r, 1)
diff --git a/libgo/go/net/mail/message.go b/libgo/go/net/mail/message.go
index 0c000697f7b..702b765c349 100644
--- a/libgo/go/net/mail/message.go
+++ b/libgo/go/net/mail/message.go
@@ -92,7 +92,8 @@ func init() {
}
}
-func parseDate(date string) (time.Time, error) {
+// ParseDate parses an RFC 5322 date string.
+func ParseDate(date string) (time.Time, error) {
for _, layout := range dateLayouts {
t, err := time.Parse(layout, date)
if err == nil {
@@ -106,7 +107,11 @@ func parseDate(date string) (time.Time, error) {
type Header map[string][]string
// Get gets the first value associated with the given key.
+// It is case insensitive; CanonicalMIMEHeaderKey is used
+// to canonicalize the provided key.
// If there are no values associated with the key, Get returns "".
+// To access multiple values of a key, or to use non-canonical keys,
+// access the map directly.
func (h Header) Get(key string) string {
return textproto.MIMEHeader(h).Get(key)
}
@@ -119,7 +124,7 @@ func (h Header) Date() (time.Time, error) {
if hdr == "" {
return time.Time{}, ErrHeaderNotPresent
}
- return parseDate(hdr)
+ return ParseDate(hdr)
}
// AddressList parses the named header field as a list of addresses.
@@ -345,6 +350,9 @@ func (p *addrParser) consumeAddrSpec() (spec string, err error) {
// quoted-string
debug.Printf("consumeAddrSpec: parsing quoted-string")
localPart, err = p.consumeQuotedString()
+ if localPart == "" {
+ err = errors.New("mail: empty quoted string in addr-spec")
+ }
} else {
// dot-atom
debug.Printf("consumeAddrSpec: parsing dot-atom")
@@ -462,9 +470,6 @@ Loop:
i += size
}
p.s = p.s[i+1:]
- if len(qsb) == 0 {
- return "", errors.New("mail: empty quoted-string")
- }
return string(qsb), nil
}
diff --git a/libgo/go/net/mail/message_test.go b/libgo/go/net/mail/message_test.go
index bbbba6b584a..f0761ab09fb 100644
--- a/libgo/go/net/mail/message_test.go
+++ b/libgo/go/net/mail/message_test.go
@@ -110,11 +110,16 @@ func TestDateParsing(t *testing.T) {
}
date, err := hdr.Date()
if err != nil {
- t.Errorf("Failed parsing %q: %v", test.dateStr, err)
- continue
+ t.Errorf("Header(Date: %s).Date(): %v", test.dateStr, err)
+ } else if !date.Equal(test.exp) {
+ t.Errorf("Header(Date: %s).Date() = %+v, want %+v", test.dateStr, date, test.exp)
}
- if !date.Equal(test.exp) {
- t.Errorf("Parse of %q: got %+v, want %+v", test.dateStr, date, test.exp)
+
+ date, err = ParseDate(test.dateStr)
+ if err != nil {
+ t.Errorf("ParseDate(%s): %v", test.dateStr, err)
+ } else if !date.Equal(test.exp) {
+ t.Errorf("ParseDate(%s) = %+v, want %+v", test.dateStr, date, test.exp)
}
}
}
@@ -310,6 +315,16 @@ func TestAddressParsing(t *testing.T) {
},
},
},
+ // Issue 14866
+ {
+ `"" <emptystring@example.com>`,
+ []*Address{
+ {
+ Name: "",
+ Address: "emptystring@example.com",
+ },
+ },
+ },
}
for _, test := range tests {
if len(test.exp) == 1 {
diff --git a/libgo/go/net/main_test.go b/libgo/go/net/main_test.go
index 7573ded93bd..28a8ff66d65 100644
--- a/libgo/go/net/main_test.go
+++ b/libgo/go/net/main_test.go
@@ -24,6 +24,8 @@ var (
)
var (
+ testTCPBig = flag.Bool("tcpbig", false, "whether to test massive size of data per read or write call on TCP connection")
+
testDNSFlood = flag.Bool("dnsflood", false, "whether to test DNS query flooding")
// If external IPv4 connectivity exists, we can try dialing
diff --git a/libgo/go/net/net.go b/libgo/go/net/net.go
index d6812d1ef05..81206ea1cb6 100644
--- a/libgo/go/net/net.go
+++ b/libgo/go/net/net.go
@@ -102,9 +102,13 @@ func init() {
}
// Addr represents a network end point address.
+//
+// The two methods Network and String conventionally return strings
+// that can be passed as the arguments to Dial, but the exact form
+// and meaning of the strings is up to the implementation.
type Addr interface {
- Network() string // name of the network
- String() string // string form of address
+ Network() string // name of the network (for example, "tcp", "udp")
+ String() string // string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80")
}
// Conn is a generic stream-oriented network connection.
@@ -112,12 +116,12 @@ type Addr interface {
// Multiple goroutines may invoke methods on a Conn simultaneously.
type Conn interface {
// Read reads data from the connection.
- // Read can be made to time out and return a Error with Timeout() == true
+ // Read can be made to time out and return an Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetReadDeadline.
Read(b []byte) (n int, err error)
// Write writes data to the connection.
- // Write can be made to time out and return a Error with Timeout() == true
+ // Write can be made to time out and return an Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
Write(b []byte) (n int, err error)
@@ -137,8 +141,10 @@ type Conn interface {
//
// A deadline is an absolute time after which I/O operations
// fail with a timeout (see type Error) instead of
- // blocking. The deadline applies to all future I/O, not just
- // the immediately following call to Read or Write.
+ // blocking. The deadline applies to all future and pending
+ // I/O, not just the immediately following call to Read or
+ // Write. After a deadline has been exceeded, the connection
+ // can be refreshed by setting a deadline in the future.
//
// An idle timeout can be implemented by repeatedly extending
// the deadline after successful Read or Write calls.
@@ -146,11 +152,13 @@ type Conn interface {
// A zero value for t means I/O operations will not time out.
SetDeadline(t time.Time) error
- // SetReadDeadline sets the deadline for future Read calls.
+ // SetReadDeadline sets the deadline for future Read calls
+ // and any currently-blocked Read call.
// A zero value for t means Read will not time out.
SetReadDeadline(t time.Time) error
- // SetWriteDeadline sets the deadline for future Write calls.
+ // SetWriteDeadline sets the deadline for future Write calls
+ // and any currently-blocked Write call.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
// A zero value for t means Write will not time out.
@@ -302,13 +310,13 @@ type PacketConn interface {
// bytes copied into b and the return address that
// was on the packet.
// ReadFrom can be made to time out and return
- // an error with Timeout() == true after a fixed time limit;
+ // an Error with Timeout() == true after a fixed time limit;
// see SetDeadline and SetReadDeadline.
ReadFrom(b []byte) (n int, addr Addr, err error)
// WriteTo writes a packet with payload b to addr.
// WriteTo can be made to time out and return
- // an error with Timeout() == true after a fixed time limit;
+ // an Error with Timeout() == true after a fixed time limit;
// see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
WriteTo(b []byte, addr Addr) (n int, err error)
@@ -321,21 +329,32 @@ type PacketConn interface {
LocalAddr() Addr
// SetDeadline sets the read and write deadlines associated
- // with the connection.
+ // with the connection. It is equivalent to calling both
+ // SetReadDeadline and SetWriteDeadline.
+ //
+ // A deadline is an absolute time after which I/O operations
+ // fail with a timeout (see type Error) instead of
+ // blocking. The deadline applies to all future and pending
+ // I/O, not just the immediately following call to ReadFrom or
+ // WriteTo. After a deadline has been exceeded, the connection
+ // can be refreshed by setting a deadline in the future.
+ //
+ // An idle timeout can be implemented by repeatedly extending
+ // the deadline after successful ReadFrom or WriteTo calls.
+ //
+ // A zero value for t means I/O operations will not time out.
SetDeadline(t time.Time) error
- // SetReadDeadline sets the deadline for future Read calls.
- // If the deadline is reached, Read will fail with a timeout
- // (see type Error) instead of blocking.
- // A zero value for t means Read will not time out.
+ // SetReadDeadline sets the deadline for future ReadFrom calls
+ // and any currently-blocked ReadFrom call.
+ // A zero value for t means ReadFrom will not time out.
SetReadDeadline(t time.Time) error
- // SetWriteDeadline sets the deadline for future Write calls.
- // If the deadline is reached, Write will fail with a timeout
- // (see type Error) instead of blocking.
- // A zero value for t means Write will not time out.
+ // SetWriteDeadline sets the deadline for future WriteTo calls
+ // and any currently-blocked WriteTo call.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
+ // A zero value for t means WriteTo will not time out.
SetWriteDeadline(t time.Time) error
}
@@ -512,7 +531,7 @@ func (e *AddrError) Error() string {
}
s := e.Err
if e.Addr != "" {
- s += " " + e.Addr
+ s = "address " + e.Addr + ": " + s
}
return s
}
@@ -604,3 +623,66 @@ func acquireThread() {
func releaseThread() {
<-threadLimit
}
+
+// buffersWriter is the interface implemented by Conns that support a
+// "writev"-like batch write optimization.
+// writeBuffers should fully consume and write all chunks from the
+// provided Buffers, else it should report a non-nil error.
+type buffersWriter interface {
+ writeBuffers(*Buffers) (int64, error)
+}
+
+var testHookDidWritev = func(wrote int) {}
+
+// Buffers contains zero or more runs of bytes to write.
+//
+// On certain machines, for certain types of connections, this is
+// optimized into an OS-specific batch write operation (such as
+// "writev").
+type Buffers [][]byte
+
+var (
+ _ io.WriterTo = (*Buffers)(nil)
+ _ io.Reader = (*Buffers)(nil)
+)
+
+func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) {
+ if wv, ok := w.(buffersWriter); ok {
+ return wv.writeBuffers(v)
+ }
+ for _, b := range *v {
+ nb, err := w.Write(b)
+ n += int64(nb)
+ if err != nil {
+ v.consume(n)
+ return n, err
+ }
+ }
+ v.consume(n)
+ return n, nil
+}
+
+func (v *Buffers) Read(p []byte) (n int, err error) {
+ for len(p) > 0 && len(*v) > 0 {
+ n0 := copy(p, (*v)[0])
+ v.consume(int64(n0))
+ p = p[n0:]
+ n += n0
+ }
+ if len(*v) == 0 {
+ err = io.EOF
+ }
+ return
+}
+
+func (v *Buffers) consume(n int64) {
+ for len(*v) > 0 {
+ ln0 := int64(len((*v)[0]))
+ if ln0 > n {
+ (*v)[0] = (*v)[0][n:]
+ return
+ }
+ n -= ln0
+ *v = (*v)[1:]
+ }
+}
diff --git a/libgo/go/net/net_test.go b/libgo/go/net/net_test.go
index b2f825daffc..9a9a7e552c4 100644
--- a/libgo/go/net/net_test.go
+++ b/libgo/go/net/net_test.go
@@ -5,6 +5,8 @@
package net
import (
+ "errors"
+ "fmt"
"io"
"net/internal/socktest"
"os"
@@ -15,7 +17,7 @@ import (
func TestCloseRead(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "plan9":
t.Skipf("not supported on %s", runtime.GOOS)
}
@@ -414,3 +416,103 @@ func TestZeroByteRead(t *testing.T) {
}
}
}
+
+// withTCPConnPair sets up a TCP connection between two peers, then
+// runs peer1 and peer2 concurrently. withTCPConnPair returns when
+// both have completed.
+func withTCPConnPair(t *testing.T, peer1, peer2 func(c *TCPConn) error) {
+ ln, err := newLocalListener("tcp")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln.Close()
+ errc := make(chan error, 2)
+ go func() {
+ c1, err := ln.Accept()
+ if err != nil {
+ errc <- err
+ return
+ }
+ defer c1.Close()
+ errc <- peer1(c1.(*TCPConn))
+ }()
+ go func() {
+ c2, err := Dial("tcp", ln.Addr().String())
+ if err != nil {
+ errc <- err
+ return
+ }
+ defer c2.Close()
+ errc <- peer2(c2.(*TCPConn))
+ }()
+ for i := 0; i < 2; i++ {
+ if err := <-errc; err != nil {
+ t.Fatal(err)
+ }
+ }
+}
+
+// Tests that a blocked Read is interrupted by a concurrent SetReadDeadline
+// modifying that Conn's read deadline to the past.
+// See golang.org/cl/30164 which documented this. The net/http package
+// depends on this.
+func TestReadTimeoutUnblocksRead(t *testing.T) {
+ serverDone := make(chan struct{})
+ server := func(cs *TCPConn) error {
+ defer close(serverDone)
+ errc := make(chan error, 1)
+ go func() {
+ defer close(errc)
+ go func() {
+ // TODO: find a better way to wait
+ // until we're blocked in the cs.Read
+ // call below. Sleep is lame.
+ time.Sleep(100 * time.Millisecond)
+
+ // Interrupt the upcoming Read, unblocking it:
+ cs.SetReadDeadline(time.Unix(123, 0)) // time in the past
+ }()
+ var buf [1]byte
+ n, err := cs.Read(buf[:1])
+ if n != 0 || err == nil {
+ errc <- fmt.Errorf("Read = %v, %v; want 0, non-nil", n, err)
+ }
+ }()
+ select {
+ case err := <-errc:
+ return err
+ case <-time.After(5 * time.Second):
+ buf := make([]byte, 2<<20)
+ buf = buf[:runtime.Stack(buf, true)]
+ println("Stacks at timeout:\n", string(buf))
+ return errors.New("timeout waiting for Read to finish")
+ }
+
+ }
+ // Do nothing in the client. Never write. Just wait for the
+ // server's half to be done.
+ client := func(*TCPConn) error {
+ <-serverDone
+ return nil
+ }
+ withTCPConnPair(t, client, server)
+}
+
+// Issue 17695: verify that a blocked Read is woken up by a Close.
+func TestCloseUnblocksRead(t *testing.T) {
+ t.Parallel()
+ server := func(cs *TCPConn) error {
+ // Give the client time to get stuck in a Read:
+ time.Sleep(20 * time.Millisecond)
+ cs.Close()
+ return nil
+ }
+ client := func(ss *TCPConn) error {
+ n, err := ss.Read([]byte{0})
+ if n != 0 || err != io.EOF {
+ return fmt.Errorf("Read = %v, %v; want 0, EOF", n, err)
+ }
+ return nil
+ }
+ withTCPConnPair(t, client, server)
+}
diff --git a/libgo/go/net/parse.go b/libgo/go/net/parse.go
index 2c6b98ad9bc..b270159cd88 100644
--- a/libgo/go/net/parse.go
+++ b/libgo/go/net/parse.go
@@ -124,39 +124,27 @@ func getFields(s string) []string { return splitAtBytes(s, " \r\t\n") }
// Bigger than we need, not too big to worry about overflow
const big = 0xFFFFFF
-// Decimal to integer starting at &s[i0].
-// Returns number, new offset, success.
-func dtoi(s string, i0 int) (n int, i int, ok bool) {
+// Decimal to integer.
+// Returns number, characters consumed, success.
+func dtoi(s string) (n int, i int, ok bool) {
n = 0
- neg := false
- if len(s) > 0 && s[0] == '-' {
- neg = true
- s = s[1:]
- }
- for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
+ for i = 0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
n = n*10 + int(s[i]-'0')
if n >= big {
- if neg {
- return -big, i + 1, false
- }
return big, i, false
}
}
- if i == i0 {
- return 0, i, false
- }
- if neg {
- n = -n
- i++
+ if i == 0 {
+ return 0, 0, false
}
return n, i, true
}
-// Hexadecimal to integer starting at &s[i0].
-// Returns number, new offset, success.
-func xtoi(s string, i0 int) (n int, i int, ok bool) {
+// Hexadecimal to integer.
+// Returns number, characters consumed, success.
+func xtoi(s string) (n int, i int, ok bool) {
n = 0
- for i = i0; i < len(s); i++ {
+ for i = 0; i < len(s); i++ {
if '0' <= s[i] && s[i] <= '9' {
n *= 16
n += int(s[i] - '0')
@@ -173,7 +161,7 @@ func xtoi(s string, i0 int) (n int, i int, ok bool) {
return 0, i, false
}
}
- if i == i0 {
+ if i == 0 {
return 0, i, false
}
return n, i, true
@@ -187,7 +175,7 @@ func xtoi2(s string, e byte) (byte, bool) {
if len(s) > 2 && s[2] != e {
return 0, false
}
- n, ei, ok := xtoi(s[:2], 0)
+ n, ei, ok := xtoi(s[:2])
return byte(n), ok && ei == 2
}
@@ -348,22 +336,28 @@ func stringsHasSuffix(s, suffix string) bool {
// stringsHasSuffixFold reports whether s ends in suffix,
// ASCII-case-insensitively.
func stringsHasSuffixFold(s, suffix string) bool {
- if len(suffix) > len(s) {
+ return len(s) >= len(suffix) && stringsEqualFold(s[len(s)-len(suffix):], suffix)
+}
+
+// stringsHasPrefix is strings.HasPrefix. It reports whether s begins with prefix.
+func stringsHasPrefix(s, prefix string) bool {
+ return len(s) >= len(prefix) && s[:len(prefix)] == prefix
+}
+
+// stringsEqualFold is strings.EqualFold, ASCII only. It reports whether s and t
+// are equal, ASCII-case-insensitively.
+func stringsEqualFold(s, t string) bool {
+ if len(s) != len(t) {
return false
}
- for i := 0; i < len(suffix); i++ {
- if lowerASCII(suffix[i]) != lowerASCII(s[len(s)-len(suffix)+i]) {
+ for i := 0; i < len(s); i++ {
+ if lowerASCII(s[i]) != lowerASCII(t[i]) {
return false
}
}
return true
}
-// stringsHasPrefix is strings.HasPrefix. It reports whether s begins with prefix.
-func stringsHasPrefix(s, prefix string) bool {
- return len(s) >= len(prefix) && s[:len(prefix)] == prefix
-}
-
func readFull(r io.Reader) (all []byte, err error) {
buf := make([]byte, 1024)
for {
diff --git a/libgo/go/net/parse_test.go b/libgo/go/net/parse_test.go
index fec92009465..c5f8bfd198c 100644
--- a/libgo/go/net/parse_test.go
+++ b/libgo/go/net/parse_test.go
@@ -86,14 +86,13 @@ func TestDtoi(t *testing.T) {
ok bool
}{
{"", 0, 0, false},
-
- {"-123456789", -big, 9, false},
- {"-1", -1, 2, true},
{"0", 0, 1, true},
{"65536", 65536, 5, true},
{"123456789", big, 8, false},
+ {"-0", 0, 0, false},
+ {"-1234", 0, 0, false},
} {
- n, i, ok := dtoi(tt.in, 0)
+ n, i, ok := dtoi(tt.in)
if n != tt.out || i != tt.off || ok != tt.ok {
t.Errorf("got %d, %d, %v; want %d, %d, %v", n, i, ok, tt.out, tt.off, tt.ok)
}
diff --git a/libgo/go/net/port_unix.go b/libgo/go/net/port_unix.go
index badf8abc79b..868d1e4784f 100644
--- a/libgo/go/net/port_unix.go
+++ b/libgo/go/net/port_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 solaris
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris nacl
// Read system port mappings from /etc/services
@@ -10,31 +10,24 @@ package net
import "sync"
-// services contains minimal mappings between services names and port
-// numbers for platforms that don't have a complete list of port numbers
-// (some Solaris distros).
-var services = map[string]map[string]int{
- "tcp": {"http": 80},
-}
-var servicesError error
var onceReadServices sync.Once
func readServices() {
- var file *file
- if file, servicesError = open("/etc/services"); servicesError != nil {
+ file, err := open("/etc/services")
+ if err != nil {
return
}
for line, ok := file.readLine(); ok; line, ok = file.readLine() {
// "http 80/tcp www www-http # World Wide Web HTTP"
if i := byteIndex(line, '#'); i >= 0 {
- line = line[0:i]
+ line = line[:i]
}
f := getFields(line)
if len(f) < 2 {
continue
}
portnet := f[1] // "80/tcp"
- port, j, ok := dtoi(portnet, 0)
+ port, j, ok := dtoi(portnet)
if !ok || port <= 0 || j >= len(portnet) || portnet[j] != '/' {
continue
}
@@ -56,18 +49,5 @@ func readServices() {
// goLookupPort is the native Go implementation of LookupPort.
func goLookupPort(network, service string) (port int, err error) {
onceReadServices.Do(readServices)
-
- switch network {
- case "tcp4", "tcp6":
- network = "tcp"
- case "udp4", "udp6":
- network = "udp"
- }
-
- if m, ok := services[network]; ok {
- if port, ok = m[service]; ok {
- return
- }
- }
- return 0, &AddrError{Err: "unknown port", Addr: network + "/" + service}
+ return lookupPortMap(network, service)
}
diff --git a/libgo/go/net/rpc/client.go b/libgo/go/net/rpc/client.go
index 862fb1ae0c1..fce6a4866c9 100644
--- a/libgo/go/net/rpc/client.go
+++ b/libgo/go/net/rpc/client.go
@@ -274,6 +274,8 @@ func Dial(network, address string) (*Client, error) {
return NewClient(conn), nil
}
+// Close calls the underlying codec's Close method. If the connection is already
+// shutting down, ErrShutdown is returned.
func (client *Client) Close() error {
client.mutex.Lock()
if client.closing {
diff --git a/libgo/go/net/rpc/client_test.go b/libgo/go/net/rpc/client_test.go
index ba11ff85869..d116d2acc9a 100644
--- a/libgo/go/net/rpc/client_test.go
+++ b/libgo/go/net/rpc/client_test.go
@@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"net"
- "runtime"
"strings"
"testing"
)
@@ -53,9 +52,6 @@ func (s *S) Recv(nul *struct{}, reply *R) error {
}
func TestGobError(t *testing.T) {
- if runtime.GOOS == "plan9" {
- t.Skip("skipping test; see https://golang.org/issue/8908")
- }
defer func() {
err := recover()
if err == nil {
diff --git a/libgo/go/net/rpc/server.go b/libgo/go/net/rpc/server.go
index cff32413a34..18ea629b0d6 100644
--- a/libgo/go/net/rpc/server.go
+++ b/libgo/go/net/rpc/server.go
@@ -23,7 +23,7 @@
func (t *T) MethodName(argType T1, replyType *T2) error
- where T, T1 and T2 can be marshaled by encoding/gob.
+ where T1 and T2 can be marshaled by encoding/gob.
These requirements apply even if a different codec is used.
(In the future, these requirements may soften for custom codecs.)
@@ -55,6 +55,8 @@
package server
+ import "errors"
+
type Args struct {
A, B int
}
@@ -119,6 +121,8 @@
A server implementation will often provide a simple, type-safe wrapper for the
client.
+
+ The net/rpc package is frozen and is not accepting new features.
*/
package rpc
diff --git a/libgo/go/net/rpc/server_test.go b/libgo/go/net/rpc/server_test.go
index d04271d99c2..8369c9dec7b 100644
--- a/libgo/go/net/rpc/server_test.go
+++ b/libgo/go/net/rpc/server_test.go
@@ -693,7 +693,8 @@ func benchmarkEndToEndAsync(dial func() (*Client, error), b *testing.B) {
B := call.Args.(*Args).B
C := call.Reply.(*Reply).C
if A+B != C {
- b.Fatalf("incorrect reply: Add: expected %d got %d", A+B, C)
+ b.Errorf("incorrect reply: Add: expected %d got %d", A+B, C)
+ return
}
<-gate
if atomic.AddInt32(&recv, -1) == 0 {
diff --git a/libgo/go/net/smtp/smtp.go b/libgo/go/net/smtp/smtp.go
index 9e04dd7c82b..a408fa53363 100644
--- a/libgo/go/net/smtp/smtp.go
+++ b/libgo/go/net/smtp/smtp.go
@@ -9,7 +9,7 @@
// STARTTLS RFC 3207
// Additional extensions may be handled by clients.
//
-// The smtp package is frozen and not accepting new features.
+// The smtp package is frozen and is not accepting new features.
// Some external packages provide more functionality. See:
//
// https://godoc.org/?q=smtp
@@ -19,6 +19,7 @@ import (
"crypto/tls"
"encoding/base64"
"errors"
+ "fmt"
"io"
"net"
"net/textproto"
@@ -200,7 +201,7 @@ func (c *Client) Auth(a Auth) error {
}
resp64 := make([]byte, encoding.EncodedLen(len(resp)))
encoding.Encode(resp64, resp)
- code, msg64, err := c.cmd(0, "AUTH %s %s", mech, resp64)
+ code, msg64, err := c.cmd(0, strings.TrimSpace(fmt.Sprintf("AUTH %s %s", mech, resp64)))
for err == nil {
var msg []byte
switch code {
diff --git a/libgo/go/net/smtp/smtp_test.go b/libgo/go/net/smtp/smtp_test.go
index 3ae0d5bf1dd..c48fae6d5ac 100644
--- a/libgo/go/net/smtp/smtp_test.go
+++ b/libgo/go/net/smtp/smtp_test.go
@@ -94,6 +94,46 @@ func TestAuthPlain(t *testing.T) {
}
}
+// Issue 17794: don't send a trailing space on AUTH command when there's no password.
+func TestClientAuthTrimSpace(t *testing.T) {
+ server := "220 hello world\r\n" +
+ "200 some more"
+ var wrote bytes.Buffer
+ var fake faker
+ fake.ReadWriter = struct {
+ io.Reader
+ io.Writer
+ }{
+ strings.NewReader(server),
+ &wrote,
+ }
+ c, err := NewClient(fake, "fake.host")
+ if err != nil {
+ t.Fatalf("NewClient: %v", err)
+ }
+ c.tls = true
+ c.didHello = true
+ c.Auth(toServerEmptyAuth{})
+ c.Close()
+ if got, want := wrote.String(), "AUTH FOOAUTH\r\n*\r\nQUIT\r\n"; got != want {
+ t.Errorf("wrote %q; want %q", got, want)
+ }
+}
+
+// toServerEmptyAuth is an implementation of Auth that only implements
+// the Start method, and returns "FOOAUTH", nil, nil. Notably, it returns
+// zero bytes for "toServer" so we can test that we don't send spaces at
+// the end of the line. See TestClientAuthTrimSpace.
+type toServerEmptyAuth struct{}
+
+func (toServerEmptyAuth) Start(server *ServerInfo) (proto string, toServer []byte, err error) {
+ return "FOOAUTH", nil, nil
+}
+
+func (toServerEmptyAuth) Next(fromServer []byte, more bool) (toServer []byte, err error) {
+ panic("unexpected call")
+}
+
type faker struct {
io.ReadWriter
}
@@ -716,23 +756,24 @@ func sendMail(hostPort string) error {
// generated from src/crypto/tls:
// go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
-MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
-bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
-bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
-IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
-AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
-EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
-AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
-Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
+MIIBjjCCATigAwIBAgIQMon9v0s3pDFXvAMnPgelpzANBgkqhkiG9w0BAQsFADAS
+MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
+MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJB
+AM0u/mNXKkhAzNsFkwKZPSpC4lZZaePQ55IyaJv3ovMM2smvthnlqaUfVKVmz7FF
+wLP9csX6vGtvkZg1uWAtvfkCAwEAAaNoMGYwDgYDVR0PAQH/BAQDAgKkMBMGA1Ud
+JQQMMAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhh
+bXBsZS5jb22HBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZIhvcNAQELBQAD
+QQBOZsFVC7IwX+qibmSbt2IPHkUgXhfbq0a9MYhD6tHcj4gbDcTXh4kZCbgHCz22
+gfSj2/G2wxzopoISVDucuncj
-----END CERTIFICATE-----`)
// localhostKey is the private key for localhostCert.
var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
-MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
-0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
-NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
-AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
-MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
-EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
-1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
+MIIBOwIBAAJBAM0u/mNXKkhAzNsFkwKZPSpC4lZZaePQ55IyaJv3ovMM2smvthnl
+qaUfVKVmz7FFwLP9csX6vGtvkZg1uWAtvfkCAwEAAQJART2qkxODLUbQ2siSx7m2
+rmBLyR/7X+nLe8aPDrMOxj3heDNl4YlaAYLexbcY8d7VDfCRBKYoAOP0UCP1Vhuf
+UQIhAO6PEI55K3SpNIdc2k5f0xz+9rodJCYzu51EwWX7r8ufAiEA3C9EkLiU2NuK
+3L3DHCN5IlUSN1Nr/lw8NIt50Yorj2cCIQCDw1VbvCV6bDLtSSXzAA51B4ZzScE7
+sHtB5EYF9Dwm9QIhAJuCquuH4mDzVjUntXjXOQPdj7sRqVGCNWdrJwOukat7AiAy
+LXLEwb77DIPoI5ZuaXQC+MnyyJj1ExC9RFcGz+bexA==
-----END RSA PRIVATE KEY-----`)
diff --git a/libgo/go/net/sock_linux.go b/libgo/go/net/sock_linux.go
index e2732c59a57..7bca37605ec 100644
--- a/libgo/go/net/sock_linux.go
+++ b/libgo/go/net/sock_linux.go
@@ -17,7 +17,7 @@ func maxListenerBacklog() int {
return syscall.SOMAXCONN
}
f := getFields(l)
- n, _, ok := dtoi(f[0], 0)
+ n, _, ok := dtoi(f[0])
if n == 0 || !ok {
return syscall.SOMAXCONN
}
diff --git a/libgo/go/net/sock_posix.go b/libgo/go/net/sock_posix.go
index c3af27b596f..16351e1f14e 100644
--- a/libgo/go/net/sock_posix.go
+++ b/libgo/go/net/sock_posix.go
@@ -30,6 +30,9 @@ type sockaddr interface {
// interface. It returns a nil interface when the address is
// nil.
sockaddr(family int) (syscall.Sockaddr, error)
+
+ // toLocal maps the zero address to a local system address (127.0.0.1 or ::1)
+ toLocal(net string) sockaddr
}
// socket returns a network file descriptor that is ready for
diff --git a/libgo/go/net/tcpsock.go b/libgo/go/net/tcpsock.go
index 7cffcc58cbb..69731ebc914 100644
--- a/libgo/go/net/tcpsock.go
+++ b/libgo/go/net/tcpsock.go
@@ -12,6 +12,9 @@ import (
"time"
)
+// BUG(mikio): On Windows, the File method of TCPListener is not
+// implemented.
+
// TCPAddr represents the address of a TCP end point.
type TCPAddr struct {
IP IP
@@ -53,6 +56,9 @@ func (a *TCPAddr) opAddr() Addr {
// "tcp6". A literal address or host name for IPv6 must be enclosed
// in square brackets, as in "[::1]:80", "[ipv6-host]:http" or
// "[ipv6-host%zone]:80".
+//
+// Resolving a hostname is not recommended because this returns at most
+// one of its IP addresses.
func ResolveTCPAddr(net, addr string) (*TCPAddr, error) {
switch net {
case "tcp", "tcp4", "tcp6":
@@ -61,7 +67,7 @@ func ResolveTCPAddr(net, addr string) (*TCPAddr, error) {
default:
return nil, UnknownNetworkError(net)
}
- addrs, err := internetAddrList(context.Background(), net, addr)
+ addrs, err := DefaultResolver.internetAddrList(context.Background(), net, addr)
if err != nil {
return nil, err
}
@@ -81,7 +87,7 @@ func (c *TCPConn) ReadFrom(r io.Reader) (int64, error) {
}
n, err := c.readFrom(r)
if err != nil && err != io.EOF {
- err = &OpError{Op: "read", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
+ err = &OpError{Op: "readfrom", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
}
return n, err
}
diff --git a/libgo/go/net/tcpsock_posix.go b/libgo/go/net/tcpsock_posix.go
index c9a8b6808ea..9641e5c0283 100644
--- a/libgo/go/net/tcpsock_posix.go
+++ b/libgo/go/net/tcpsock_posix.go
@@ -40,6 +40,10 @@ func (a *TCPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
return ipToSockaddr(family, a.IP, a.Port, a.Zone)
}
+func (a *TCPAddr) toLocal(net string) sockaddr {
+ return &TCPAddr{loopbackIP(net), a.Port, a.Zone}
+}
+
func (c *TCPConn) readFrom(r io.Reader) (int64, error) {
if n, err, handled := sendFile(c.fd, r); handled {
return n, err
diff --git a/libgo/go/net/tcpsock_test.go b/libgo/go/net/tcpsock_test.go
index a8d93b02642..51154221d0a 100644
--- a/libgo/go/net/tcpsock_test.go
+++ b/libgo/go/net/tcpsock_test.go
@@ -5,6 +5,7 @@
package net
import (
+ "fmt"
"internal/testenv"
"io"
"reflect"
@@ -310,6 +311,17 @@ var resolveTCPAddrTests = []resolveTCPAddrTest{
{"tcp", ":12345", &TCPAddr{Port: 12345}, nil},
{"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
+
+ {"tcp", "127.0.0.1:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil},
+ {"tcp", "[::ffff:127.0.0.1]:http", &TCPAddr{IP: ParseIP("::ffff:127.0.0.1"), Port: 80}, nil},
+ {"tcp", "[2001:db8::1]:http", &TCPAddr{IP: ParseIP("2001:db8::1"), Port: 80}, nil},
+ {"tcp4", "127.0.0.1:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil},
+ {"tcp4", "[::ffff:127.0.0.1]:http", &TCPAddr{IP: ParseIP("127.0.0.1"), Port: 80}, nil},
+ {"tcp6", "[2001:db8::1]:http", &TCPAddr{IP: ParseIP("2001:db8::1"), Port: 80}, nil},
+
+ {"tcp4", "[2001:db8::1]:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}},
+ {"tcp6", "127.0.0.1:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}},
+ {"tcp6", "[::ffff:127.0.0.1]:http", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}},
}
func TestResolveTCPAddr(t *testing.T) {
@@ -317,21 +329,17 @@ func TestResolveTCPAddr(t *testing.T) {
defer func() { testHookLookupIP = origTestHookLookupIP }()
testHookLookupIP = lookupLocalhost
- for i, tt := range resolveTCPAddrTests {
+ for _, tt := range resolveTCPAddrTests {
addr, err := ResolveTCPAddr(tt.network, tt.litAddrOrName)
- if err != tt.err {
- t.Errorf("#%d: %v", i, err)
- } else if !reflect.DeepEqual(addr, tt.addr) {
- t.Errorf("#%d: got %#v; want %#v", i, addr, tt.addr)
- }
- if err != nil {
+ if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) {
+ t.Errorf("ResolveTCPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err)
continue
}
- rtaddr, err := ResolveTCPAddr(addr.Network(), addr.String())
- if err != nil {
- t.Errorf("#%d: %v", i, err)
- } else if !reflect.DeepEqual(rtaddr, addr) {
- t.Errorf("#%d: got %#v; want %#v", i, rtaddr, addr)
+ if err == nil {
+ addr2, err := ResolveTCPAddr(addr.Network(), addr.String())
+ if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err {
+ t.Errorf("(%q, %q): ResolveTCPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr.Network(), addr.String(), addr2, err, tt.addr, tt.err)
+ }
}
}
}
@@ -459,12 +467,19 @@ func TestTCPConcurrentAccept(t *testing.T) {
}
func TestTCPReadWriteAllocs(t *testing.T) {
+ if runtime.Compiler == "gccgo" {
+ t.Skip("skipping for gccgo until escape analysis is enabled")
+ }
+
switch runtime.GOOS {
- case "nacl", "windows":
+ case "plan9":
+ // The implementation of asynchronous cancelable
+ // I/O on Plan 9 allocates memory.
+ // See net/fd_io_plan9.go.
+ t.Skipf("not supported on %s", runtime.GOOS)
+ case "nacl":
// NaCl needs to allocate pseudo file descriptor
// stuff. See syscall/fd_nacl.go.
- // Windows uses closures and channels for IO
- // completion port-based netpoll. See fd_windows.go.
t.Skipf("not supported on %s", runtime.GOOS)
}
@@ -474,7 +489,7 @@ func TestTCPReadWriteAllocs(t *testing.T) {
}
defer ln.Close()
var server Conn
- errc := make(chan error)
+ errc := make(chan error, 1)
go func() {
var err error
server, err = ln.Accept()
@@ -489,6 +504,7 @@ func TestTCPReadWriteAllocs(t *testing.T) {
t.Fatal(err)
}
defer server.Close()
+
var buf [128]byte
allocs := testing.AllocsPerRun(1000, func() {
_, err := server.Write(buf[:])
@@ -504,6 +520,28 @@ func TestTCPReadWriteAllocs(t *testing.T) {
if allocs > 7 {
t.Fatalf("got %v; want 0", allocs)
}
+
+ var bufwrt [128]byte
+ ch := make(chan bool)
+ defer close(ch)
+ go func() {
+ for <-ch {
+ _, err := server.Write(bufwrt[:])
+ errc <- err
+ }
+ }()
+ allocs = testing.AllocsPerRun(1000, func() {
+ ch <- true
+ if _, err = io.ReadFull(client, buf[:]); err != nil {
+ t.Fatal(err)
+ }
+ if err := <-errc; err != nil {
+ t.Fatal(err)
+ }
+ })
+ if allocs > 0 {
+ t.Fatalf("got %v; want 0", allocs)
+ }
}
func TestTCPStress(t *testing.T) {
@@ -634,3 +672,58 @@ func TestTCPSelfConnect(t *testing.T) {
}
}
}
+
+// Test that >32-bit reads work on 64-bit systems.
+// On 32-bit systems this tests that maxint reads work.
+func TestTCPBig(t *testing.T) {
+ if !*testTCPBig {
+ t.Skip("test disabled; use -tcpbig to enable")
+ }
+
+ for _, writev := range []bool{false, true} {
+ t.Run(fmt.Sprintf("writev=%v", writev), func(t *testing.T) {
+ ln, err := newLocalListener("tcp")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln.Close()
+
+ x := int(1 << 30)
+ x = x*5 + 1<<20 // just over 5 GB on 64-bit, just over 1GB on 32-bit
+ done := make(chan int)
+ go func() {
+ defer close(done)
+ c, err := ln.Accept()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ buf := make([]byte, x)
+ var n int
+ if writev {
+ var n64 int64
+ n64, err = (&Buffers{buf}).WriteTo(c)
+ n = int(n64)
+ } else {
+ n, err = c.Write(buf)
+ }
+ if n != len(buf) || err != nil {
+ t.Errorf("Write(buf) = %d, %v, want %d, nil", n, err, x)
+ }
+ c.Close()
+ }()
+
+ c, err := Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ buf := make([]byte, x)
+ n, err := io.ReadFull(c, buf)
+ if n != len(buf) || err != nil {
+ t.Errorf("Read(buf) = %d, %v, want %d, nil", n, err, x)
+ }
+ c.Close()
+ <-done
+ })
+ }
+}
diff --git a/libgo/go/net/tcpsock_unix_test.go b/libgo/go/net/tcpsock_unix_test.go
index c07f7d7889b..2375fe24dc4 100644
--- a/libgo/go/net/tcpsock_unix_test.go
+++ b/libgo/go/net/tcpsock_unix_test.go
@@ -15,7 +15,7 @@ import (
)
// See golang.org/issue/14548.
-func TestTCPSupriousConnSetupCompletion(t *testing.T) {
+func TestTCPSpuriousConnSetupCompletion(t *testing.T) {
if testing.Short() {
t.Skip("skipping in short mode")
}
@@ -57,7 +57,7 @@ func TestTCPSupriousConnSetupCompletion(t *testing.T) {
c, err := d.Dial(ln.Addr().Network(), ln.Addr().String())
if err != nil {
if perr := parseDialError(err); perr != nil {
- t.Errorf("#%d: %v", i, err)
+ t.Errorf("#%d: %v (original error: %v)", i, perr, err)
}
return
}
diff --git a/libgo/go/net/testdata/invalid-ndots-resolv.conf b/libgo/go/net/testdata/invalid-ndots-resolv.conf
new file mode 100644
index 00000000000..084c1643dea
--- /dev/null
+++ b/libgo/go/net/testdata/invalid-ndots-resolv.conf
@@ -0,0 +1 @@
+options ndots:invalid \ No newline at end of file
diff --git a/libgo/go/net/testdata/large-ndots-resolv.conf b/libgo/go/net/testdata/large-ndots-resolv.conf
new file mode 100644
index 00000000000..72968eee916
--- /dev/null
+++ b/libgo/go/net/testdata/large-ndots-resolv.conf
@@ -0,0 +1 @@
+options ndots:16 \ No newline at end of file
diff --git a/libgo/go/net/testdata/negative-ndots-resolv.conf b/libgo/go/net/testdata/negative-ndots-resolv.conf
new file mode 100644
index 00000000000..c11e0cc4033
--- /dev/null
+++ b/libgo/go/net/testdata/negative-ndots-resolv.conf
@@ -0,0 +1 @@
+options ndots:-1 \ No newline at end of file
diff --git a/libgo/go/net/textproto/header.go b/libgo/go/net/textproto/header.go
index 2e2752a7558..ed096d9a3cb 100644
--- a/libgo/go/net/textproto/header.go
+++ b/libgo/go/net/textproto/header.go
@@ -23,8 +23,10 @@ func (h MIMEHeader) Set(key, value string) {
}
// Get gets the first value associated with the given key.
+// It is case insensitive; CanonicalMIMEHeaderKey is used
+// to canonicalize the provided key.
// If there are no values associated with the key, Get returns "".
-// Get is a convenience method. For more complex queries,
+// To access multiple values of a key, or to use non-canonical keys,
// access the map directly.
func (h MIMEHeader) Get(key string) string {
if h == nil {
diff --git a/libgo/go/net/timeout_test.go b/libgo/go/net/timeout_test.go
index ed26f2a4aff..55bbf4402d9 100644
--- a/libgo/go/net/timeout_test.go
+++ b/libgo/go/net/timeout_test.go
@@ -5,7 +5,6 @@
package net
import (
- "context"
"fmt"
"internal/testenv"
"io"
@@ -152,6 +151,7 @@ var acceptTimeoutTests = []struct {
}
func TestAcceptTimeout(t *testing.T) {
+ testenv.SkipFlaky(t, 17948)
t.Parallel()
switch runtime.GOOS {
@@ -165,19 +165,18 @@ func TestAcceptTimeout(t *testing.T) {
}
defer ln.Close()
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
+ var wg sync.WaitGroup
for i, tt := range acceptTimeoutTests {
if tt.timeout < 0 {
+ wg.Add(1)
go func() {
- var d Dialer
- c, err := d.DialContext(ctx, ln.Addr().Network(), ln.Addr().String())
+ defer wg.Done()
+ d := Dialer{Timeout: 100 * time.Millisecond}
+ c, err := d.Dial(ln.Addr().Network(), ln.Addr().String())
if err != nil {
t.Error(err)
return
}
- var b [1]byte
- c.Read(b[:])
c.Close()
}()
}
@@ -198,13 +197,14 @@ func TestAcceptTimeout(t *testing.T) {
}
if err == nil {
c.Close()
- time.Sleep(tt.timeout / 3)
+ time.Sleep(10 * time.Millisecond)
continue
}
break
}
}
}
+ wg.Wait()
}
func TestAcceptTimeoutMustReturn(t *testing.T) {
@@ -305,11 +305,6 @@ var readTimeoutTests = []struct {
}
func TestReadTimeout(t *testing.T) {
- switch runtime.GOOS {
- case "plan9":
- t.Skipf("not supported on %s", runtime.GOOS)
- }
-
handler := func(ls *localServer, ln Listener) {
c, err := ln.Accept()
if err != nil {
@@ -435,7 +430,7 @@ var readFromTimeoutTests = []struct {
func TestReadFromTimeout(t *testing.T) {
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "nacl":
t.Skipf("not supported on %s", runtime.GOOS) // see golang.org/issue/8916
}
@@ -509,11 +504,6 @@ var writeTimeoutTests = []struct {
func TestWriteTimeout(t *testing.T) {
t.Parallel()
- switch runtime.GOOS {
- case "plan9":
- t.Skipf("not supported on %s", runtime.GOOS)
- }
-
ln, err := newLocalListener("tcp")
if err != nil {
t.Fatal(err)
@@ -629,7 +619,7 @@ func TestWriteToTimeout(t *testing.T) {
t.Parallel()
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "nacl":
t.Skipf("not supported on %s", runtime.GOOS)
}
@@ -681,11 +671,6 @@ func TestWriteToTimeout(t *testing.T) {
func TestReadTimeoutFluctuation(t *testing.T) {
t.Parallel()
- switch runtime.GOOS {
- case "plan9":
- t.Skipf("not supported on %s", runtime.GOOS)
- }
-
ln, err := newLocalListener("tcp")
if err != nil {
t.Fatal(err)
@@ -719,11 +704,6 @@ func TestReadTimeoutFluctuation(t *testing.T) {
func TestReadFromTimeoutFluctuation(t *testing.T) {
t.Parallel()
- switch runtime.GOOS {
- case "plan9":
- t.Skipf("not supported on %s", runtime.GOOS)
- }
-
c1, err := newLocalPacketListener("udp")
if err != nil {
t.Fatal(err)
@@ -829,11 +809,6 @@ func (b neverEnding) Read(p []byte) (int, error) {
}
func testVariousDeadlines(t *testing.T) {
- switch runtime.GOOS {
- case "plan9":
- t.Skipf("not supported on %s", runtime.GOOS)
- }
-
type result struct {
n int64
err error
@@ -1030,7 +1005,7 @@ func TestReadWriteDeadlineRace(t *testing.T) {
t.Parallel()
switch runtime.GOOS {
- case "nacl", "plan9":
+ case "nacl":
t.Skipf("not supported on %s", runtime.GOOS)
}
diff --git a/libgo/go/net/udpsock.go b/libgo/go/net/udpsock.go
index 980f67c81f9..841ef533590 100644
--- a/libgo/go/net/udpsock.go
+++ b/libgo/go/net/udpsock.go
@@ -9,6 +9,15 @@ import (
"syscall"
)
+// BUG(mikio): On NaCl, Plan 9 and Windows, the ReadMsgUDP and
+// WriteMsgUDP methods of UDPConn are not implemented.
+
+// BUG(mikio): On Windows, the File method of UDPConn is not
+// implemented.
+
+// BUG(mikio): On NaCl, the ListenMulticastUDP function is not
+// implemented.
+
// UDPAddr represents the address of a UDP end point.
type UDPAddr struct {
IP IP
@@ -50,6 +59,9 @@ func (a *UDPAddr) opAddr() Addr {
// "udp6". A literal address or host name for IPv6 must be enclosed
// in square brackets, as in "[::1]:80", "[ipv6-host]:http" or
// "[ipv6-host%zone]:80".
+//
+// Resolving a hostname is not recommended because this returns at most
+// one of its IP addresses.
func ResolveUDPAddr(net, addr string) (*UDPAddr, error) {
switch net {
case "udp", "udp4", "udp6":
@@ -58,7 +70,7 @@ func ResolveUDPAddr(net, addr string) (*UDPAddr, error) {
default:
return nil, UnknownNetworkError(net)
}
- addrs, err := internetAddrList(context.Background(), net, addr)
+ addrs, err := DefaultResolver.internetAddrList(context.Background(), net, addr)
if err != nil {
return nil, err
}
diff --git a/libgo/go/net/udpsock_plan9.go b/libgo/go/net/udpsock_plan9.go
index 666f20622f6..1ce7f88c62c 100644
--- a/libgo/go/net/udpsock_plan9.go
+++ b/libgo/go/net/udpsock_plan9.go
@@ -109,5 +109,41 @@ func listenUDP(ctx context.Context, network string, laddr *UDPAddr) (*UDPConn, e
}
func listenMulticastUDP(ctx context.Context, network string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
- return nil, syscall.EPLAN9
+ l, err := listenPlan9(ctx, network, gaddr)
+ if err != nil {
+ return nil, err
+ }
+ _, err = l.ctl.WriteString("headers")
+ if err != nil {
+ return nil, err
+ }
+ var addrs []Addr
+ if ifi != nil {
+ addrs, err = ifi.Addrs()
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ addrs, err = InterfaceAddrs()
+ if err != nil {
+ return nil, err
+ }
+ }
+ for _, addr := range addrs {
+ if ipnet, ok := addr.(*IPNet); ok {
+ _, err = l.ctl.WriteString("addmulti " + ipnet.IP.String() + " " + gaddr.IP.String())
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ l.data, err = os.OpenFile(l.dir+"/data", os.O_RDWR, 0)
+ if err != nil {
+ return nil, err
+ }
+ fd, err := l.netFD()
+ if err != nil {
+ return nil, err
+ }
+ return newUDPConn(fd), nil
}
diff --git a/libgo/go/net/udpsock_plan9_test.go b/libgo/go/net/udpsock_plan9_test.go
new file mode 100644
index 00000000000..09f5a5dc654
--- /dev/null
+++ b/libgo/go/net/udpsock_plan9_test.go
@@ -0,0 +1,69 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "internal/testenv"
+ "runtime"
+ "testing"
+)
+
+func TestListenMulticastUDP(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ ifcs, err := Interfaces()
+ if err != nil {
+ t.Skip(err.Error())
+ }
+ if len(ifcs) == 0 {
+ t.Skip("no network interfaces found")
+ }
+
+ var mifc *Interface
+ for _, ifc := range ifcs {
+ if ifc.Flags&FlagUp|FlagMulticast != FlagUp|FlagMulticast {
+ continue
+ }
+ mifc = &ifc
+ break
+ }
+
+ if mifc == nil {
+ t.Skipf("no multicast interfaces found")
+ }
+
+ c1, err := ListenMulticastUDP("udp4", mifc, &UDPAddr{IP: ParseIP("224.0.0.254")})
+ if err != nil {
+ t.Fatalf("multicast not working on %s", runtime.GOOS)
+ }
+ c1addr := c1.LocalAddr().(*UDPAddr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c1.Close()
+
+ c2, err := ListenUDP("udp4", &UDPAddr{IP: IPv4zero, Port: 0})
+ c2addr := c2.LocalAddr().(*UDPAddr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c2.Close()
+
+ n, err := c2.WriteToUDP([]byte("data"), c1addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if n != 4 {
+ t.Fatalf("got %d; want 4", n)
+ }
+
+ n, err = c1.WriteToUDP([]byte("data"), c2addr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if n != 4 {
+ t.Fatalf("got %d; want 4", n)
+ }
+}
diff --git a/libgo/go/net/udpsock_posix.go b/libgo/go/net/udpsock_posix.go
index 4924801ebb2..72aadca5dc9 100644
--- a/libgo/go/net/udpsock_posix.go
+++ b/libgo/go/net/udpsock_posix.go
@@ -38,6 +38,10 @@ func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
return ipToSockaddr(family, a.IP, a.Port, a.Zone)
}
+func (a *UDPAddr) toLocal(net string) sockaddr {
+ return &UDPAddr{loopbackIP(net), a.Port, a.Zone}
+}
+
func (c *UDPConn) readFrom(b []byte) (int, *UDPAddr, error) {
var addr *UDPAddr
n, sa, err := c.fd.readFrom(b)
diff --git a/libgo/go/net/udpsock_test.go b/libgo/go/net/udpsock_test.go
index 29d769c5a58..708cc101209 100644
--- a/libgo/go/net/udpsock_test.go
+++ b/libgo/go/net/udpsock_test.go
@@ -72,6 +72,17 @@ var resolveUDPAddrTests = []resolveUDPAddrTest{
{"udp", ":12345", &UDPAddr{Port: 12345}, nil},
{"http", "127.0.0.1:0", nil, UnknownNetworkError("http")},
+
+ {"udp", "127.0.0.1:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil},
+ {"udp", "[::ffff:127.0.0.1]:domain", &UDPAddr{IP: ParseIP("::ffff:127.0.0.1"), Port: 53}, nil},
+ {"udp", "[2001:db8::1]:domain", &UDPAddr{IP: ParseIP("2001:db8::1"), Port: 53}, nil},
+ {"udp4", "127.0.0.1:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil},
+ {"udp4", "[::ffff:127.0.0.1]:domain", &UDPAddr{IP: ParseIP("127.0.0.1"), Port: 53}, nil},
+ {"udp6", "[2001:db8::1]:domain", &UDPAddr{IP: ParseIP("2001:db8::1"), Port: 53}, nil},
+
+ {"udp4", "[2001:db8::1]:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "2001:db8::1"}},
+ {"udp6", "127.0.0.1:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "127.0.0.1"}},
+ {"udp6", "[::ffff:127.0.0.1]:domain", nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: "::ffff:127.0.0.1"}},
}
func TestResolveUDPAddr(t *testing.T) {
@@ -79,21 +90,17 @@ func TestResolveUDPAddr(t *testing.T) {
defer func() { testHookLookupIP = origTestHookLookupIP }()
testHookLookupIP = lookupLocalhost
- for i, tt := range resolveUDPAddrTests {
+ for _, tt := range resolveUDPAddrTests {
addr, err := ResolveUDPAddr(tt.network, tt.litAddrOrName)
- if err != tt.err {
- t.Errorf("#%d: %v", i, err)
- } else if !reflect.DeepEqual(addr, tt.addr) {
- t.Errorf("#%d: got %#v; want %#v", i, addr, tt.addr)
- }
- if err != nil {
+ if !reflect.DeepEqual(addr, tt.addr) || !reflect.DeepEqual(err, tt.err) {
+ t.Errorf("ResolveUDPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr, err, tt.addr, tt.err)
continue
}
- rtaddr, err := ResolveUDPAddr(addr.Network(), addr.String())
- if err != nil {
- t.Errorf("#%d: %v", i, err)
- } else if !reflect.DeepEqual(rtaddr, addr) {
- t.Errorf("#%d: got %#v; want %#v", i, rtaddr, addr)
+ if err == nil {
+ addr2, err := ResolveUDPAddr(addr.Network(), addr.String())
+ if !reflect.DeepEqual(addr2, tt.addr) || err != tt.err {
+ t.Errorf("(%q, %q): ResolveUDPAddr(%q, %q) = %#v, %v, want %#v, %v", tt.network, tt.litAddrOrName, addr.Network(), addr.String(), addr2, err, tt.addr, tt.err)
+ }
}
}
}
diff --git a/libgo/go/net/unixsock.go b/libgo/go/net/unixsock.go
index bacdaa41d90..b25d492f591 100644
--- a/libgo/go/net/unixsock.go
+++ b/libgo/go/net/unixsock.go
@@ -7,6 +7,7 @@ package net
import (
"context"
"os"
+ "sync"
"syscall"
"time"
)
@@ -120,6 +121,9 @@ func (c *UnixConn) ReadFrom(b []byte) (int, Addr, error) {
// the associated out-of-band data into oob. It returns the number of
// bytes copied into b, the number of bytes copied into oob, the flags
// that were set on the packet, and the source address of the packet.
+//
+// Note that if len(b) == 0 and len(oob) > 0, this function will still
+// read (and discard) 1 byte from the connection.
func (c *UnixConn) ReadMsgUnix(b, oob []byte) (n, oobn, flags int, addr *UnixAddr, err error) {
if !c.ok() {
return 0, 0, 0, nil, syscall.EINVAL
@@ -167,6 +171,9 @@ func (c *UnixConn) WriteTo(b []byte, addr Addr) (int, error) {
// WriteMsgUnix writes a packet to addr via c, copying the payload
// from b and the associated out-of-band data from oob. It returns
// the number of payload and out-of-band bytes written.
+//
+// Note that if len(b) == 0 and len(oob) > 0, this function will still
+// write 1 byte to the connection.
func (c *UnixConn) WriteMsgUnix(b, oob []byte, addr *UnixAddr) (n, oobn int, err error) {
if !c.ok() {
return 0, 0, syscall.EINVAL
@@ -200,9 +207,10 @@ func DialUnix(net string, laddr, raddr *UnixAddr) (*UnixConn, error) {
// typically use variables of type Listener instead of assuming Unix
// domain sockets.
type UnixListener struct {
- fd *netFD
- path string
- unlink bool
+ fd *netFD
+ path string
+ unlink bool
+ unlinkOnce sync.Once
}
func (ln *UnixListener) ok() bool { return ln != nil && ln.fd != nil }
diff --git a/libgo/go/net/unixsock_posix.go b/libgo/go/net/unixsock_posix.go
index 5f0999c4c27..a8f892e6c46 100644
--- a/libgo/go/net/unixsock_posix.go
+++ b/libgo/go/net/unixsock_posix.go
@@ -94,6 +94,10 @@ func (a *UnixAddr) sockaddr(family int) (syscall.Sockaddr, error) {
return &syscall.SockaddrUnix{Name: a.Name}, nil
}
+func (a *UnixAddr) toLocal(net string) sockaddr {
+ return a
+}
+
func (c *UnixConn) readFrom(b []byte) (int, *UnixAddr, error) {
var addr *UnixAddr
n, sa, err := c.fd.readFrom(b)
@@ -173,9 +177,12 @@ func (ln *UnixListener) close() error {
// is at least compatible with the auto-remove
// sequence in ListenUnix. It's only non-Go
// programs that can mess us up.
- if ln.path[0] != '@' && ln.unlink {
- syscall.Unlink(ln.path)
- }
+ // Even if there are racy calls to Close, we want to unlink only for the first one.
+ ln.unlinkOnce.Do(func() {
+ if ln.path[0] != '@' && ln.unlink {
+ syscall.Unlink(ln.path)
+ }
+ })
return ln.fd.Close()
}
@@ -187,6 +194,18 @@ func (ln *UnixListener) file() (*os.File, error) {
return f, nil
}
+// SetUnlinkOnClose sets whether the underlying socket file should be removed
+// from the file system when the listener is closed.
+//
+// The default behavior is to unlink the socket file only when package net created it.
+// That is, when the listener and the underlying socket file were created by a call to
+// Listen or ListenUnix, then by default closing the listener will remove the socket file.
+// but if the listener was created by a call to FileListener to use an already existing
+// socket file, then by default closing the listener will not remove the socket file.
+func (l *UnixListener) SetUnlinkOnClose(unlink bool) {
+ l.unlink = unlink
+}
+
func listenUnix(ctx context.Context, network string, laddr *UnixAddr) (*UnixListener, error) {
fd, err := unixSocket(ctx, network, laddr, nil, "listen")
if err != nil {
diff --git a/libgo/go/net/unixsock_test.go b/libgo/go/net/unixsock_test.go
index f0f88ed37b2..489a29bc7d7 100644
--- a/libgo/go/net/unixsock_test.go
+++ b/libgo/go/net/unixsock_test.go
@@ -9,6 +9,7 @@ package net
import (
"bytes"
"internal/testenv"
+ "io/ioutil"
"os"
"reflect"
"runtime"
@@ -414,33 +415,104 @@ func TestUnixUnlink(t *testing.T) {
t.Skip("unix test")
}
name := testUnixAddr()
- l, err := Listen("unix", name)
- if err != nil {
- t.Fatal(err)
- }
- if _, err := os.Stat(name); err != nil {
- t.Fatalf("cannot stat unix socket after ListenUnix: %v", err)
- }
- f, _ := l.(*UnixListener).File()
- l1, err := FileListener(f)
- if err != nil {
- t.Fatal(err)
- }
- if _, err := os.Stat(name); err != nil {
- t.Fatalf("cannot stat unix socket after FileListener: %v", err)
- }
- if err := l1.Close(); err != nil {
- t.Fatalf("closing file listener: %v", err)
- }
- if _, err := os.Stat(name); err != nil {
- t.Fatalf("cannot stat unix socket after closing FileListener: %v", err)
+
+ listen := func(t *testing.T) *UnixListener {
+ l, err := Listen("unix", name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ return l.(*UnixListener)
}
- f.Close()
- if _, err := os.Stat(name); err != nil {
- t.Fatalf("cannot stat unix socket after closing FileListener and fd: %v", err)
+ checkExists := func(t *testing.T, desc string) {
+ if _, err := os.Stat(name); err != nil {
+ t.Fatalf("unix socket does not exist %s: %v", desc, err)
+ }
}
- l.Close()
- if _, err := os.Stat(name); err == nil {
- t.Fatal("closing unix listener did not remove unix socket")
+ checkNotExists := func(t *testing.T, desc string) {
+ if _, err := os.Stat(name); err == nil {
+ t.Fatalf("unix socket does exist %s: %v", desc, err)
+ }
}
+
+ // Listener should remove on close.
+ t.Run("Listen", func(t *testing.T) {
+ l := listen(t)
+ checkExists(t, "after Listen")
+ l.Close()
+ checkNotExists(t, "after Listener close")
+ })
+
+ // FileListener should not.
+ t.Run("FileListener", func(t *testing.T) {
+ l := listen(t)
+ f, _ := l.File()
+ l1, _ := FileListener(f)
+ checkExists(t, "after FileListener")
+ f.Close()
+ checkExists(t, "after File close")
+ l1.Close()
+ checkExists(t, "after FileListener close")
+ l.Close()
+ checkNotExists(t, "after Listener close")
+ })
+
+ // Only first call to l.Close should remove.
+ t.Run("SecondClose", func(t *testing.T) {
+ l := listen(t)
+ checkExists(t, "after Listen")
+ l.Close()
+ checkNotExists(t, "after Listener close")
+ if err := ioutil.WriteFile(name, []byte("hello world"), 0666); err != nil {
+ t.Fatalf("cannot recreate socket file: %v", err)
+ }
+ checkExists(t, "after writing temp file")
+ l.Close()
+ checkExists(t, "after second Listener close")
+ os.Remove(name)
+ })
+
+ // SetUnlinkOnClose should do what it says.
+
+ t.Run("Listen/SetUnlinkOnClose(true)", func(t *testing.T) {
+ l := listen(t)
+ checkExists(t, "after Listen")
+ l.SetUnlinkOnClose(true)
+ l.Close()
+ checkNotExists(t, "after Listener close")
+ })
+
+ t.Run("Listen/SetUnlinkOnClose(false)", func(t *testing.T) {
+ l := listen(t)
+ checkExists(t, "after Listen")
+ l.SetUnlinkOnClose(false)
+ l.Close()
+ checkExists(t, "after Listener close")
+ os.Remove(name)
+ })
+
+ t.Run("FileListener/SetUnlinkOnClose(true)", func(t *testing.T) {
+ l := listen(t)
+ f, _ := l.File()
+ l1, _ := FileListener(f)
+ checkExists(t, "after FileListener")
+ l1.(*UnixListener).SetUnlinkOnClose(true)
+ f.Close()
+ checkExists(t, "after File close")
+ l1.Close()
+ checkNotExists(t, "after FileListener close")
+ l.Close()
+ })
+
+ t.Run("FileListener/SetUnlinkOnClose(false)", func(t *testing.T) {
+ l := listen(t)
+ f, _ := l.File()
+ l1, _ := FileListener(f)
+ checkExists(t, "after FileListener")
+ l1.(*UnixListener).SetUnlinkOnClose(false)
+ f.Close()
+ checkExists(t, "after File close")
+ l1.Close()
+ checkExists(t, "after FileListener close")
+ l.Close()
+ })
}
diff --git a/libgo/go/net/url/url.go b/libgo/go/net/url/url.go
index 30e92779370..42a514bbc12 100644
--- a/libgo/go/net/url/url.go
+++ b/libgo/go/net/url/url.go
@@ -74,6 +74,7 @@ type encoding int
const (
encodePath encoding = 1 + iota
+ encodePathSegment
encodeHost
encodeZone
encodeUserPassword
@@ -132,9 +133,14 @@ func shouldEscape(c byte, mode encoding) bool {
// The RFC allows : @ & = + $ but saves / ; , for assigning
// meaning to individual path segments. This package
// only manipulates the path as a whole, so we allow those
- // last two as well. That leaves only ? to escape.
+ // last three as well. That leaves only ? to escape.
return c == '?'
+ case encodePathSegment: // §3.3
+ // The RFC allows : @ & = + $ but saves / ; , for assigning
+ // meaning to individual path segments.
+ return c == '/' || c == ';' || c == ',' || c == '?'
+
case encodeUserPassword: // §3.2.1
// The RFC allows ';', ':', '&', '=', '+', '$', and ',' in
// userinfo, so we must escape only '@', '/', and '?'.
@@ -164,6 +170,15 @@ func QueryUnescape(s string) (string, error) {
return unescape(s, encodeQueryComponent)
}
+// PathUnescape does the inverse transformation of PathEscape, converting
+// %AB into the byte 0xAB. It returns an error if any % is not followed by
+// two hexadecimal digits.
+//
+// PathUnescape is identical to QueryUnescape except that it does not unescape '+' to ' ' (space).
+func PathUnescape(s string) (string, error) {
+ return unescape(s, encodePathSegment)
+}
+
// unescape unescapes a string; the mode specifies
// which section of the URL string is being unescaped.
func unescape(s string, mode encoding) (string, error) {
@@ -250,6 +265,12 @@ func QueryEscape(s string) string {
return escape(s, encodeQueryComponent)
}
+// PathEscape escapes the string so it can be safely placed
+// inside a URL path segment.
+func PathEscape(s string) string {
+ return escape(s, encodePathSegment)
+}
+
func escape(s string, mode encoding) string {
spaceCount, hexCount := 0, 0
for i := 0; i < len(s); i++ {
@@ -356,10 +377,7 @@ func (u *Userinfo) Username() string {
// Password returns the password in case it is set, and whether it is set.
func (u *Userinfo) Password() (string, bool) {
- if u.passwordSet {
- return u.password, true
- }
- return "", false
+ return u.password, u.passwordSet
}
// String returns the encoded userinfo information in the standard form
@@ -420,7 +438,7 @@ func Parse(rawurl string) (*URL, error) {
u, frag := split(rawurl, "#", true)
url, err := parse(u, false)
if err != nil {
- return nil, err
+ return nil, &Error{"parse", u, err}
}
if frag == "" {
return url, nil
@@ -437,31 +455,35 @@ func Parse(rawurl string) (*URL, error) {
// The string rawurl is assumed not to have a #fragment suffix.
// (Web browsers strip #fragment before sending the URL to a web server.)
func ParseRequestURI(rawurl string) (*URL, error) {
- return parse(rawurl, true)
+ url, err := parse(rawurl, true)
+ if err != nil {
+ return nil, &Error{"parse", rawurl, err}
+ }
+ return url, nil
}
// parse parses a URL from a string in one of two contexts. If
// viaRequest is true, the URL is assumed to have arrived via an HTTP request,
// in which case only absolute URLs or path-absolute relative URLs are allowed.
// If viaRequest is false, all forms of relative URLs are allowed.
-func parse(rawurl string, viaRequest bool) (url *URL, err error) {
+func parse(rawurl string, viaRequest bool) (*URL, error) {
var rest string
+ var err error
if rawurl == "" && viaRequest {
- err = errors.New("empty url")
- goto Error
+ return nil, errors.New("empty url")
}
- url = new(URL)
+ url := new(URL)
if rawurl == "*" {
url.Path = "*"
- return
+ return url, nil
}
// Split off possible leading "http:", "mailto:", etc.
// Cannot contain escaped characters.
if url.Scheme, rest, err = getscheme(rawurl); err != nil {
- goto Error
+ return nil, err
}
url.Scheme = strings.ToLower(url.Scheme)
@@ -479,8 +501,20 @@ func parse(rawurl string, viaRequest bool) (url *URL, err error) {
return url, nil
}
if viaRequest {
- err = errors.New("invalid URI for request")
- goto Error
+ return nil, errors.New("invalid URI for request")
+ }
+
+ // Avoid confusion with malformed schemes, like cache_object:foo/bar.
+ // See golang.org/issue/16822.
+ //
+ // RFC 3986, §3.3:
+ // In addition, a URI reference (Section 4.1) may be a relative-path reference,
+ // in which case the first path segment cannot contain a colon (":") character.
+ colon := strings.Index(rest, ":")
+ slash := strings.Index(rest, "/")
+ if colon >= 0 && (slash < 0 || colon < slash) {
+ // First path segment has colon. Not allowed in relative URL.
+ return nil, errors.New("first path segment in URL cannot contain colon")
}
}
@@ -489,23 +523,17 @@ func parse(rawurl string, viaRequest bool) (url *URL, err error) {
authority, rest = split(rest[2:], "/", false)
url.User, url.Host, err = parseAuthority(authority)
if err != nil {
- goto Error
+ return nil, err
}
}
- if url.Path, err = unescape(rest, encodePath); err != nil {
- goto Error
- }
- // RawPath is a hint as to the encoding of Path to use
- // in url.EscapedPath. If that method already gets the
- // right answer without RawPath, leave it empty.
- // This will help make sure that people don't rely on it in general.
- if url.EscapedPath() != rest && validEncodedPath(rest) {
- url.RawPath = rest
+ // Set Path and, optionally, RawPath.
+ // RawPath is a hint of the encoding of Path. We don't want to set it if
+ // the default escaping of Path is equivalent, to help make sure that people
+ // don't rely on it in general.
+ if err := url.setPath(rest); err != nil {
+ return nil, err
}
return url, nil
-
-Error:
- return nil, &Error{"parse", rawurl, err}
}
func parseAuthority(authority string) (user *Userinfo, host string, err error) {
@@ -586,6 +614,29 @@ func parseHost(host string) (string, error) {
return host, nil
}
+// setPath sets the Path and RawPath fields of the URL based on the provided
+// escaped path p. It maintains the invariant that RawPath is only specified
+// when it differs from the default encoding of the path.
+// For example:
+// - setPath("/foo/bar") will set Path="/foo/bar" and RawPath=""
+// - setPath("/foo%2fbar") will set Path="/foo/bar" and RawPath="/foo%2fbar"
+// setPath will return an error only if the provided path contains an invalid
+// escaping.
+func (u *URL) setPath(p string) error {
+ path, err := unescape(p, encodePath)
+ if err != nil {
+ return err
+ }
+ u.Path = path
+ if escp := escape(path, encodePath); p == escp {
+ // Default encoding is fine.
+ u.RawPath = ""
+ } else {
+ u.RawPath = p
+ }
+ return nil
+}
+
// EscapedPath returns the escaped form of u.Path.
// In general there are multiple possible escaped forms of any path.
// EscapedPath returns u.RawPath when it is a valid escaping of u.Path.
@@ -693,6 +744,17 @@ func (u *URL) String() string {
if path != "" && path[0] != '/' && u.Host != "" {
buf.WriteByte('/')
}
+ if buf.Len() == 0 {
+ // RFC 3986 §4.2
+ // A path segment that contains a colon character (e.g., "this:that")
+ // cannot be used as the first segment of a relative-path reference, as
+ // it would be mistaken for a scheme name. Such a segment must be
+ // preceded by a dot-segment (e.g., "./this:that") to make a relative-
+ // path reference.
+ if i := strings.IndexByte(path, ':'); i > -1 && strings.IndexByte(path[:i], '/') == -1 {
+ buf.WriteString("./")
+ }
+ }
buf.WriteString(path)
}
if u.ForceQuery || u.RawQuery != "" {
@@ -749,6 +811,10 @@ func (v Values) Del(key string) {
// ParseQuery always returns a non-nil map containing all the
// valid query parameters found; err describes the first decoding error
// encountered, if any.
+//
+// Query is expected to be a list of key=value settings separated by
+// ampersands or semicolons. A setting without an equals sign is
+// interpreted as a key set to an empty value.
func ParseQuery(query string) (Values, error) {
m := make(Values)
err := parseQuery(m, query)
@@ -852,6 +918,7 @@ func resolvePath(base, ref string) string {
}
// IsAbs reports whether the URL is absolute.
+// Absolute means that it has a non-empty scheme.
func (u *URL) IsAbs() bool {
return u.Scheme != ""
}
@@ -880,7 +947,9 @@ func (u *URL) ResolveReference(ref *URL) *URL {
}
if ref.Scheme != "" || ref.Host != "" || ref.User != nil {
// The "absoluteURI" or "net_path" cases.
- url.Path = resolvePath(ref.Path, "")
+ // We can ignore the error from setPath since we know we provided a
+ // validly-escaped path.
+ url.setPath(resolvePath(ref.EscapedPath(), ""))
return &url
}
if ref.Opaque != "" {
@@ -900,7 +969,7 @@ func (u *URL) ResolveReference(ref *URL) *URL {
// The "abs_path" or "rel_path" cases.
url.Host = u.Host
url.User = u.User
- url.Path = resolvePath(u.Path, ref.Path)
+ url.setPath(resolvePath(u.EscapedPath(), ref.EscapedPath()))
return &url
}
@@ -929,3 +998,59 @@ func (u *URL) RequestURI() string {
}
return result
}
+
+// Hostname returns u.Host, without any port number.
+//
+// If Host is an IPv6 literal with a port number, Hostname returns the
+// IPv6 literal without the square brackets. IPv6 literals may include
+// a zone identifier.
+func (u *URL) Hostname() string {
+ return stripPort(u.Host)
+}
+
+// Port returns the port part of u.Host, without the leading colon.
+// If u.Host doesn't contain a port, Port returns an empty string.
+func (u *URL) Port() string {
+ return portOnly(u.Host)
+}
+
+func stripPort(hostport string) string {
+ colon := strings.IndexByte(hostport, ':')
+ if colon == -1 {
+ return hostport
+ }
+ if i := strings.IndexByte(hostport, ']'); i != -1 {
+ return strings.TrimPrefix(hostport[:i], "[")
+ }
+ return hostport[:colon]
+}
+
+func portOnly(hostport string) string {
+ colon := strings.IndexByte(hostport, ':')
+ if colon == -1 {
+ return ""
+ }
+ if i := strings.Index(hostport, "]:"); i != -1 {
+ return hostport[i+len("]:"):]
+ }
+ if strings.Contains(hostport, "]") {
+ return ""
+ }
+ return hostport[colon+len(":"):]
+}
+
+// Marshaling interface implementations.
+// Would like to implement MarshalText/UnmarshalText but that will change the JSON representation of URLs.
+
+func (u *URL) MarshalBinary() (text []byte, err error) {
+ return []byte(u.String()), nil
+}
+
+func (u *URL) UnmarshalBinary(text []byte) error {
+ u1, err := Parse(string(text))
+ if err != nil {
+ return err
+ }
+ *u = *u1
+ return nil
+}
diff --git a/libgo/go/net/url/url_test.go b/libgo/go/net/url/url_test.go
index 7560f22c4a1..6c3bb21d20c 100644
--- a/libgo/go/net/url/url_test.go
+++ b/libgo/go/net/url/url_test.go
@@ -5,6 +5,10 @@
package url
import (
+ "bytes"
+ encodingPkg "encoding"
+ "encoding/gob"
+ "encoding/json"
"fmt"
"io"
"net"
@@ -579,20 +583,6 @@ func ufmt(u *URL) string {
u.Opaque, u.Scheme, user, pass, u.Host, u.Path, u.RawPath, u.RawQuery, u.Fragment, u.ForceQuery)
}
-func DoTest(t *testing.T, parse func(string) (*URL, error), name string, tests []URLTest) {
- for _, tt := range tests {
- u, err := parse(tt.in)
- if err != nil {
- t.Errorf("%s(%q) returned error %s", name, tt.in, err)
- continue
- }
- if !reflect.DeepEqual(u, tt.out) {
- t.Errorf("%s(%q):\n\thave %v\n\twant %v\n",
- name, tt.in, ufmt(u), ufmt(tt.out))
- }
- }
-}
-
func BenchmarkString(b *testing.B) {
b.StopTimer()
b.ReportAllocs()
@@ -618,7 +608,16 @@ func BenchmarkString(b *testing.B) {
}
func TestParse(t *testing.T) {
- DoTest(t, Parse, "Parse", urltests)
+ for _, tt := range urltests {
+ u, err := Parse(tt.in)
+ if err != nil {
+ t.Errorf("Parse(%q) returned error %v", tt.in, err)
+ continue
+ }
+ if !reflect.DeepEqual(u, tt.out) {
+ t.Errorf("Parse(%q):\n\tgot %v\n\twant %v\n", tt.in, ufmt(u), ufmt(tt.out))
+ }
+ }
}
const pathThatLooksSchemeRelative = "//not.a.user@not.a.host/just/a/path"
@@ -665,9 +664,10 @@ var parseRequestURLTests = []struct {
func TestParseRequestURI(t *testing.T) {
for _, test := range parseRequestURLTests {
_, err := ParseRequestURI(test.url)
- valid := err == nil
- if valid != test.expectedValid {
- t.Errorf("Expected valid=%v for %q; got %v", test.expectedValid, test.url, valid)
+ if test.expectedValid && err != nil {
+ t.Errorf("ParseRequestURI(%q) gave err %v; want no error", test.url, err)
+ } else if !test.expectedValid && err == nil {
+ t.Errorf("ParseRequestURI(%q) gave nil error; want some error", test.url)
}
}
@@ -676,45 +676,69 @@ func TestParseRequestURI(t *testing.T) {
t.Fatalf("Unexpected error %v", err)
}
if url.Path != pathThatLooksSchemeRelative {
- t.Errorf("Expected path %q; got %q", pathThatLooksSchemeRelative, url.Path)
+ t.Errorf("ParseRequestURI path:\ngot %q\nwant %q", url.Path, pathThatLooksSchemeRelative)
}
}
-func DoTestString(t *testing.T, parse func(string) (*URL, error), name string, tests []URLTest) {
- for _, tt := range tests {
- u, err := parse(tt.in)
+var stringURLTests = []struct {
+ url URL
+ want string
+}{
+ // No leading slash on path should prepend slash on String() call
+ {
+ url: URL{
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "search",
+ },
+ want: "http://www.google.com/search",
+ },
+ // Relative path with first element containing ":" should be prepended with "./", golang.org/issue/17184
+ {
+ url: URL{
+ Path: "this:that",
+ },
+ want: "./this:that",
+ },
+ // Relative path with second element containing ":" should not be prepended with "./"
+ {
+ url: URL{
+ Path: "here/this:that",
+ },
+ want: "here/this:that",
+ },
+ // Non-relative path with first element containing ":" should not be prepended with "./"
+ {
+ url: URL{
+ Scheme: "http",
+ Host: "www.google.com",
+ Path: "this:that",
+ },
+ want: "http://www.google.com/this:that",
+ },
+}
+
+func TestURLString(t *testing.T) {
+ for _, tt := range urltests {
+ u, err := Parse(tt.in)
if err != nil {
- t.Errorf("%s(%q) returned error %s", name, tt.in, err)
+ t.Errorf("Parse(%q) returned error %s", tt.in, err)
continue
}
expected := tt.in
- if len(tt.roundtrip) > 0 {
+ if tt.roundtrip != "" {
expected = tt.roundtrip
}
s := u.String()
if s != expected {
- t.Errorf("%s(%q).String() == %q (expected %q)", name, tt.in, s, expected)
+ t.Errorf("Parse(%q).String() == %q (expected %q)", tt.in, s, expected)
}
}
-}
-func TestURLString(t *testing.T) {
- DoTestString(t, Parse, "Parse", urltests)
-
- // no leading slash on path should prepend
- // slash on String() call
- noslash := URLTest{
- "http://www.google.com/search",
- &URL{
- Scheme: "http",
- Host: "www.google.com",
- Path: "search",
- },
- "",
- }
- s := noslash.out.String()
- if s != noslash.in {
- t.Errorf("Expected %s; go %s", noslash.in, s)
+ for _, tt := range stringURLTests {
+ if got := tt.url.String(); got != tt.want {
+ t.Errorf("%+v.String() = %q; want %q", tt.url, got, tt.want)
+ }
}
}
@@ -780,6 +804,16 @@ var unescapeTests = []EscapeTest{
"",
EscapeError("%zz"),
},
+ {
+ "a+b",
+ "a b",
+ nil,
+ },
+ {
+ "a%20b",
+ "a b",
+ nil,
+ },
}
func TestUnescape(t *testing.T) {
@@ -788,10 +822,33 @@ func TestUnescape(t *testing.T) {
if actual != tt.out || (err != nil) != (tt.err != nil) {
t.Errorf("QueryUnescape(%q) = %q, %s; want %q, %s", tt.in, actual, err, tt.out, tt.err)
}
+
+ in := tt.in
+ out := tt.out
+ if strings.Contains(tt.in, "+") {
+ in = strings.Replace(tt.in, "+", "%20", -1)
+ actual, err := PathUnescape(in)
+ if actual != tt.out || (err != nil) != (tt.err != nil) {
+ t.Errorf("PathUnescape(%q) = %q, %s; want %q, %s", in, actual, err, tt.out, tt.err)
+ }
+ if tt.err == nil {
+ s, err := QueryUnescape(strings.Replace(tt.in, "+", "XXX", -1))
+ if err != nil {
+ continue
+ }
+ in = tt.in
+ out = strings.Replace(s, "XXX", "+", -1)
+ }
+ }
+
+ actual, err = PathUnescape(in)
+ if actual != out || (err != nil) != (tt.err != nil) {
+ t.Errorf("PathUnescape(%q) = %q, %s; want %q, %s", in, actual, err, out, tt.err)
+ }
}
}
-var escapeTests = []EscapeTest{
+var queryEscapeTests = []EscapeTest{
{
"",
"",
@@ -819,8 +876,8 @@ var escapeTests = []EscapeTest{
},
}
-func TestEscape(t *testing.T) {
- for _, tt := range escapeTests {
+func TestQueryEscape(t *testing.T) {
+ for _, tt := range queryEscapeTests {
actual := QueryEscape(tt.in)
if tt.out != actual {
t.Errorf("QueryEscape(%q) = %q, want %q", tt.in, actual, tt.out)
@@ -834,6 +891,54 @@ func TestEscape(t *testing.T) {
}
}
+var pathEscapeTests = []EscapeTest{
+ {
+ "",
+ "",
+ nil,
+ },
+ {
+ "abc",
+ "abc",
+ nil,
+ },
+ {
+ "abc+def",
+ "abc+def",
+ nil,
+ },
+ {
+ "one two",
+ "one%20two",
+ nil,
+ },
+ {
+ "10%",
+ "10%25",
+ nil,
+ },
+ {
+ " ?&=#+%!<>#\"{}|\\^[]`☺\t:/@$'()*,;",
+ "%20%3F&=%23+%25%21%3C%3E%23%22%7B%7D%7C%5C%5E%5B%5D%60%E2%98%BA%09:%2F@$%27%28%29%2A%2C%3B",
+ nil,
+ },
+}
+
+func TestPathEscape(t *testing.T) {
+ for _, tt := range pathEscapeTests {
+ actual := PathEscape(tt.in)
+ if tt.out != actual {
+ t.Errorf("PathEscape(%q) = %q, want %q", tt.in, actual, tt.out)
+ }
+
+ // for bonus points, verify that escape:unescape is an identity.
+ roundtrip, err := PathUnescape(actual)
+ if roundtrip != tt.in || err != nil {
+ t.Errorf("PathUnescape(%q) = %q, %s; want %q, %s", actual, roundtrip, err, tt.in, "[no error]")
+ }
+ }
+}
+
//var userinfoTests = []UserinfoTest{
// {"user", "password", "user:password"},
// {"foo:bar", "~!@#$%^&*()_+{}|[]\\-=`:;'\"<>?,./",
@@ -945,6 +1050,15 @@ var resolveReferenceTests = []struct {
// Fragment
{"http://foo.com/bar", ".#frag", "http://foo.com/#frag"},
+ // Paths with escaping (issue 16947).
+ {"http://foo.com/foo%2fbar/", "../baz", "http://foo.com/baz"},
+ {"http://foo.com/1/2%2f/3%2f4/5", "../../a/b/c", "http://foo.com/1/a/b/c"},
+ {"http://foo.com/1/2/3", "./a%2f../../b/..%2fc", "http://foo.com/1/2/b/..%2fc"},
+ {"http://foo.com/1/2%2f/3%2f4/5", "./a%2f../b/../c", "http://foo.com/1/2%2f/3%2f4/a%2f../c"},
+ {"http://foo.com/foo%20bar/", "../baz", "http://foo.com/baz"},
+ {"http://foo.com/foo", "../bar%2fbaz", "http://foo.com/bar%2fbaz"},
+ {"http://foo.com/foo%2dbar/", "./baz-quux", "http://foo.com/foo%2dbar/baz-quux"},
+
// RFC 3986: Normal Examples
// http://tools.ietf.org/html/rfc3986#section-5.4.1
{"http://a/b/c/d;p?q", "g:h", "g:h"},
@@ -1004,7 +1118,7 @@ func TestResolveReference(t *testing.T) {
mustParse := func(url string) *URL {
u, err := Parse(url)
if err != nil {
- t.Fatalf("Expected URL to parse: %q, got error: %v", url, err)
+ t.Fatalf("Parse(%q) got err %v", url, err)
}
return u
}
@@ -1013,8 +1127,8 @@ func TestResolveReference(t *testing.T) {
base := mustParse(test.base)
rel := mustParse(test.rel)
url := base.ResolveReference(rel)
- if url.String() != test.expected {
- t.Errorf("URL(%q).ResolveReference(%q) == %q, got %q", test.base, test.rel, test.expected, url.String())
+ if got := url.String(); got != test.expected {
+ t.Errorf("URL(%q).ResolveReference(%q)\ngot %q\nwant %q", test.base, test.rel, got, test.expected)
}
// Ensure that new instances are returned.
if base == url {
@@ -1024,8 +1138,8 @@ func TestResolveReference(t *testing.T) {
url, err := base.Parse(test.rel)
if err != nil {
t.Errorf("URL(%q).Parse(%q) failed: %v", test.base, test.rel, err)
- } else if url.String() != test.expected {
- t.Errorf("URL(%q).Parse(%q) == %q, got %q", test.base, test.rel, test.expected, url.String())
+ } else if got := url.String(); got != test.expected {
+ t.Errorf("URL(%q).Parse(%q)\ngot %q\nwant %q", test.base, test.rel, got, test.expected)
} else if base == url {
// Ensure that new instances are returned for the wrapper too.
t.Errorf("Expected URL.Parse to return new URL instance.")
@@ -1033,14 +1147,14 @@ func TestResolveReference(t *testing.T) {
// Ensure Opaque resets the URL.
url = base.ResolveReference(opaque)
if *url != *opaque {
- t.Errorf("ResolveReference failed to resolve opaque URL: want %#v, got %#v", url, opaque)
+ t.Errorf("ResolveReference failed to resolve opaque URL:\ngot %#v\nwant %#v", url, opaque)
}
// Test the convenience wrapper with an opaque URL too.
url, err = base.Parse("scheme:opaque")
if err != nil {
t.Errorf(`URL(%q).Parse("scheme:opaque") failed: %v`, test.base, err)
} else if *url != *opaque {
- t.Errorf("Parse failed to resolve opaque URL: want %#v, got %#v", url, opaque)
+ t.Errorf("Parse failed to resolve opaque URL:\ngot %#v\nwant %#v", opaque, url)
} else if base == url {
// Ensure that new instances are returned, again.
t.Errorf("Expected URL.Parse to return new URL instance.")
@@ -1271,7 +1385,7 @@ func TestParseFailure(t *testing.T) {
}
}
-func TestParseAuthority(t *testing.T) {
+func TestParseErrors(t *testing.T) {
tests := []struct {
in string
wantErr bool
@@ -1291,9 +1405,13 @@ func TestParseAuthority(t *testing.T) {
{"http://%41:8080/", true}, // not allowed: % encoding only for non-ASCII
{"mysql://x@y(z:123)/foo", false}, // golang.org/issue/12023
{"mysql://x@y(1.2.3.4:123)/foo", false},
- {"mysql://x@y([2001:db8::1]:123)/foo", false},
+
{"http://[]%20%48%54%54%50%2f%31%2e%31%0a%4d%79%48%65%61%64%65%72%3a%20%31%32%33%0a%0a/", true}, // golang.org/issue/11208
{"http://a b.com/", true}, // no space in host name please
+ {"cache_object://foo", true}, // scheme cannot have _, relative path cannot have : in first segment
+ {"cache_object:foo", true},
+ {"cache_object:foo/bar", true},
+ {"cache_object/:foo/bar", false},
}
for _, tt := range tests {
u, err := Parse(tt.in)
@@ -1462,11 +1580,106 @@ func TestURLErrorImplementsNetError(t *testing.T) {
continue
}
if err.Timeout() != tt.timeout {
- t.Errorf("%d: err.Timeout(): want %v, have %v", i+1, tt.timeout, err.Timeout())
+ t.Errorf("%d: err.Timeout(): got %v, want %v", i+1, err.Timeout(), tt.timeout)
continue
}
if err.Temporary() != tt.temporary {
- t.Errorf("%d: err.Temporary(): want %v, have %v", i+1, tt.temporary, err.Temporary())
+ t.Errorf("%d: err.Temporary(): got %v, want %v", i+1, err.Temporary(), tt.temporary)
+ }
+ }
+}
+
+func TestURLHostname(t *testing.T) {
+ tests := []struct {
+ host string // URL.Host field
+ want string
+ }{
+ {"foo.com:80", "foo.com"},
+ {"foo.com", "foo.com"},
+ {"FOO.COM", "FOO.COM"}, // no canonicalization (yet?)
+ {"1.2.3.4", "1.2.3.4"},
+ {"1.2.3.4:80", "1.2.3.4"},
+ {"[1:2:3:4]", "1:2:3:4"},
+ {"[1:2:3:4]:80", "1:2:3:4"},
+ {"[::1]:80", "::1"},
+ }
+ for _, tt := range tests {
+ u := &URL{Host: tt.host}
+ got := u.Hostname()
+ if got != tt.want {
+ t.Errorf("Hostname for Host %q = %q; want %q", tt.host, got, tt.want)
+ }
+ }
+}
+
+func TestURLPort(t *testing.T) {
+ tests := []struct {
+ host string // URL.Host field
+ want string
+ }{
+ {"foo.com", ""},
+ {"foo.com:80", "80"},
+ {"1.2.3.4", ""},
+ {"1.2.3.4:80", "80"},
+ {"[1:2:3:4]", ""},
+ {"[1:2:3:4]:80", "80"},
+ }
+ for _, tt := range tests {
+ u := &URL{Host: tt.host}
+ got := u.Port()
+ if got != tt.want {
+ t.Errorf("Port for Host %q = %q; want %q", tt.host, got, tt.want)
}
}
}
+
+var _ encodingPkg.BinaryMarshaler = (*URL)(nil)
+var _ encodingPkg.BinaryUnmarshaler = (*URL)(nil)
+
+func TestJSON(t *testing.T) {
+ u, err := Parse("https://www.google.com/x?y=z")
+ if err != nil {
+ t.Fatal(err)
+ }
+ js, err := json.Marshal(u)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // If only we could implement TextMarshaler/TextUnmarshaler,
+ // this would work:
+ //
+ // if string(js) != strconv.Quote(u.String()) {
+ // t.Errorf("json encoding: %s\nwant: %s\n", js, strconv.Quote(u.String()))
+ // }
+
+ u1 := new(URL)
+ err = json.Unmarshal(js, u1)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if u1.String() != u.String() {
+ t.Errorf("json decoded to: %s\nwant: %s\n", u1, u)
+ }
+}
+
+func TestGob(t *testing.T) {
+ u, err := Parse("https://www.google.com/x?y=z")
+ if err != nil {
+ t.Fatal(err)
+ }
+ var w bytes.Buffer
+ err = gob.NewEncoder(&w).Encode(u)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ u1 := new(URL)
+ err = gob.NewDecoder(&w).Decode(u1)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if u1.String() != u.String() {
+ t.Errorf("json decoded to: %s\nwant: %s\n", u1, u)
+ }
+}
diff --git a/libgo/go/net/writev_test.go b/libgo/go/net/writev_test.go
new file mode 100644
index 00000000000..7160d28c3a0
--- /dev/null
+++ b/libgo/go/net/writev_test.go
@@ -0,0 +1,225 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "reflect"
+ "runtime"
+ "sync"
+ "testing"
+)
+
+func TestBuffers_read(t *testing.T) {
+ const story = "once upon a time in Gopherland ... "
+ buffers := Buffers{
+ []byte("once "),
+ []byte("upon "),
+ []byte("a "),
+ []byte("time "),
+ []byte("in "),
+ []byte("Gopherland ... "),
+ }
+ got, err := ioutil.ReadAll(&buffers)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(got) != story {
+ t.Errorf("read %q; want %q", got, story)
+ }
+ if len(buffers) != 0 {
+ t.Errorf("len(buffers) = %d; want 0", len(buffers))
+ }
+}
+
+func TestBuffers_consume(t *testing.T) {
+ tests := []struct {
+ in Buffers
+ consume int64
+ want Buffers
+ }{
+ {
+ in: Buffers{[]byte("foo"), []byte("bar")},
+ consume: 0,
+ want: Buffers{[]byte("foo"), []byte("bar")},
+ },
+ {
+ in: Buffers{[]byte("foo"), []byte("bar")},
+ consume: 2,
+ want: Buffers{[]byte("o"), []byte("bar")},
+ },
+ {
+ in: Buffers{[]byte("foo"), []byte("bar")},
+ consume: 3,
+ want: Buffers{[]byte("bar")},
+ },
+ {
+ in: Buffers{[]byte("foo"), []byte("bar")},
+ consume: 4,
+ want: Buffers{[]byte("ar")},
+ },
+ {
+ in: Buffers{nil, nil, nil, []byte("bar")},
+ consume: 1,
+ want: Buffers{[]byte("ar")},
+ },
+ {
+ in: Buffers{nil, nil, nil, []byte("foo")},
+ consume: 0,
+ want: Buffers{[]byte("foo")},
+ },
+ {
+ in: Buffers{nil, nil, nil},
+ consume: 0,
+ want: Buffers{},
+ },
+ }
+ for i, tt := range tests {
+ in := tt.in
+ in.consume(tt.consume)
+ if !reflect.DeepEqual(in, tt.want) {
+ t.Errorf("%d. after consume(%d) = %+v, want %+v", i, tt.consume, in, tt.want)
+ }
+ }
+}
+
+func TestBuffers_WriteTo(t *testing.T) {
+ for _, name := range []string{"WriteTo", "Copy"} {
+ for _, size := range []int{0, 10, 1023, 1024, 1025} {
+ t.Run(fmt.Sprintf("%s/%d", name, size), func(t *testing.T) {
+ testBuffer_writeTo(t, size, name == "Copy")
+ })
+ }
+ }
+}
+
+func testBuffer_writeTo(t *testing.T, chunks int, useCopy bool) {
+ oldHook := testHookDidWritev
+ defer func() { testHookDidWritev = oldHook }()
+ var writeLog struct {
+ sync.Mutex
+ log []int
+ }
+ testHookDidWritev = func(size int) {
+ writeLog.Lock()
+ writeLog.log = append(writeLog.log, size)
+ writeLog.Unlock()
+ }
+ var want bytes.Buffer
+ for i := 0; i < chunks; i++ {
+ want.WriteByte(byte(i))
+ }
+
+ withTCPConnPair(t, func(c *TCPConn) error {
+ buffers := make(Buffers, chunks)
+ for i := range buffers {
+ buffers[i] = want.Bytes()[i : i+1]
+ }
+ var n int64
+ var err error
+ if useCopy {
+ n, err = io.Copy(c, &buffers)
+ } else {
+ n, err = buffers.WriteTo(c)
+ }
+ if err != nil {
+ return err
+ }
+ if len(buffers) != 0 {
+ return fmt.Errorf("len(buffers) = %d; want 0", len(buffers))
+ }
+ if n != int64(want.Len()) {
+ return fmt.Errorf("Buffers.WriteTo returned %d; want %d", n, want.Len())
+ }
+ return nil
+ }, func(c *TCPConn) error {
+ all, err := ioutil.ReadAll(c)
+ if !bytes.Equal(all, want.Bytes()) || err != nil {
+ return fmt.Errorf("client read %q, %v; want %q, nil", all, err, want.Bytes())
+ }
+
+ writeLog.Lock() // no need to unlock
+ var gotSum int
+ for _, v := range writeLog.log {
+ gotSum += v
+ }
+
+ var wantSum int
+ switch runtime.GOOS {
+ case "android", "darwin", "dragonfly", "freebsd", "linux", "netbsd", "openbsd":
+ var wantMinCalls int
+ wantSum = want.Len()
+ v := chunks
+ for v > 0 {
+ wantMinCalls++
+ v -= 1024
+ }
+ if len(writeLog.log) < wantMinCalls {
+ t.Errorf("write calls = %v < wanted min %v", len(writeLog.log), wantMinCalls)
+ }
+ case "windows":
+ var wantCalls int
+ wantSum = want.Len()
+ if wantSum > 0 {
+ wantCalls = 1 // windows will always do 1 syscall, unless sending empty buffer
+ }
+ if len(writeLog.log) != wantCalls {
+ t.Errorf("write calls = %v; want %v", len(writeLog.log), wantCalls)
+ }
+ }
+ if gotSum != wantSum {
+ t.Errorf("writev call sum = %v; want %v", gotSum, wantSum)
+ }
+ return nil
+ })
+}
+
+func TestWritevError(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Skipf("skipping the test: windows does not have problem sending large chunks of data")
+ }
+
+ ln, err := newLocalListener("tcp")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer ln.Close()
+
+ ch := make(chan Conn, 1)
+ go func() {
+ defer close(ch)
+ c, err := ln.Accept()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ ch <- c
+ }()
+ c1, err := Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c1.Close()
+ c2 := <-ch
+ if c2 == nil {
+ t.Fatal("no server side connection")
+ }
+ c2.Close()
+
+ // 1 GB of data should be enough to notice the connection is gone.
+ // Just a few bytes is not enough.
+ // Arrange to reuse the same 1 MB buffer so that we don't allocate much.
+ buf := make([]byte, 1<<20)
+ buffers := make(Buffers, 1<<10)
+ for i := range buffers {
+ buffers[i] = buf
+ }
+ if _, err := buffers.WriteTo(c1); err == nil {
+ t.Fatal("Buffers.WriteTo(closed conn) succeeded, want error")
+ }
+}
diff --git a/libgo/go/net/writev_unix.go b/libgo/go/net/writev_unix.go
new file mode 100644
index 00000000000..174e6bc51e3
--- /dev/null
+++ b/libgo/go/net/writev_unix.go
@@ -0,0 +1,95 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package net
+
+import (
+ "io"
+ "os"
+ "syscall"
+ "unsafe"
+)
+
+func (c *conn) writeBuffers(v *Buffers) (int64, error) {
+ if !c.ok() {
+ return 0, syscall.EINVAL
+ }
+ n, err := c.fd.writeBuffers(v)
+ if err != nil {
+ return n, &OpError{Op: "writev", Net: c.fd.net, Source: c.fd.laddr, Addr: c.fd.raddr, Err: err}
+ }
+ return n, nil
+}
+
+func (fd *netFD) writeBuffers(v *Buffers) (n int64, err error) {
+ if err := fd.writeLock(); err != nil {
+ return 0, err
+ }
+ defer fd.writeUnlock()
+ if err := fd.pd.prepareWrite(); err != nil {
+ return 0, err
+ }
+
+ var iovecs []syscall.Iovec
+ if fd.iovecs != nil {
+ iovecs = *fd.iovecs
+ }
+ // TODO: read from sysconf(_SC_IOV_MAX)? The Linux default is
+ // 1024 and this seems conservative enough for now. Darwin's
+ // UIO_MAXIOV also seems to be 1024.
+ maxVec := 1024
+
+ for len(*v) > 0 {
+ iovecs = iovecs[:0]
+ for _, chunk := range *v {
+ if len(chunk) == 0 {
+ continue
+ }
+ iovecs = append(iovecs, syscall.Iovec{Base: &chunk[0]})
+ if fd.isStream && len(chunk) > 1<<30 {
+ iovecs[len(iovecs)-1].SetLen(1 << 30)
+ break // continue chunk on next writev
+ }
+ iovecs[len(iovecs)-1].SetLen(len(chunk))
+ if len(iovecs) == maxVec {
+ break
+ }
+ }
+ if len(iovecs) == 0 {
+ break
+ }
+ fd.iovecs = &iovecs // cache
+
+ wrote, _, e0 := syscall.Syscall(syscall.SYS_WRITEV,
+ uintptr(fd.sysfd),
+ uintptr(unsafe.Pointer(&iovecs[0])),
+ uintptr(len(iovecs)))
+ if wrote == ^uintptr(0) {
+ wrote = 0
+ }
+ testHookDidWritev(int(wrote))
+ n += int64(wrote)
+ v.consume(int64(wrote))
+ if e0 == syscall.EAGAIN {
+ if err = fd.pd.waitWrite(); err == nil {
+ continue
+ }
+ } else if e0 != 0 {
+ err = syscall.Errno(e0)
+ }
+ if err != nil {
+ break
+ }
+ if n == 0 {
+ err = io.ErrUnexpectedEOF
+ break
+ }
+ }
+ if _, ok := err.(syscall.Errno); ok {
+ err = os.NewSyscallError("writev", err)
+ }
+ return n, err
+}
diff --git a/libgo/go/os/dir.go b/libgo/go/os/dir.go
index d811c9fdd86..6c54456a215 100644
--- a/libgo/go/os/dir.go
+++ b/libgo/go/os/dir.go
@@ -1,102 +1,46 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package os
-import (
- "io"
- "sync/atomic"
- "syscall"
- "unsafe"
-)
-
-//extern opendir
-func libc_opendir(*byte) *syscall.DIR
-
-//extern closedir
-func libc_closedir(*syscall.DIR) int
-
-// FIXME: pathconf returns long, not int.
-//extern pathconf
-func libc_pathconf(*byte, int) int
-
-func clen(n []byte) int {
- for i := 0; i < len(n); i++ {
- if n[i] == 0 {
- return i
- }
+// Readdir reads the contents of the directory associated with file and
+// returns a slice of up to n FileInfo values, as would be returned
+// by Lstat, in directory order. Subsequent calls on the same file will yield
+// further FileInfos.
+//
+// If n > 0, Readdir returns at most n FileInfo structures. In this case, if
+// Readdir returns an empty slice, it will return a non-nil error
+// explaining why. At the end of a directory, the error is io.EOF.
+//
+// If n <= 0, Readdir returns all the FileInfo from the directory in
+// a single slice. In this case, if Readdir succeeds (reads all
+// the way to the end of the directory), it returns the slice and a
+// nil error. If it encounters an error before the end of the
+// directory, Readdir returns the FileInfo read until that point
+// and a non-nil error.
+func (f *File) Readdir(n int) ([]FileInfo, error) {
+ if f == nil {
+ return nil, ErrInvalid
}
- return len(n)
+ return f.readdir(n)
}
-var nameMax int32
-
-func (file *File) readdirnames(n int) (names []string, err error) {
- if file.dirinfo == nil {
- p, err := syscall.BytePtrFromString(file.name)
- if err != nil {
- return nil, err
- }
-
- elen := int(atomic.LoadInt32(&nameMax))
- if elen == 0 {
- syscall.Entersyscall()
- plen := libc_pathconf(p, syscall.PC_NAME_MAX)
- syscall.Exitsyscall()
- if plen < 1024 {
- plen = 1024
- }
- var dummy syscall.Dirent
- elen = int(unsafe.Offsetof(dummy.Name)) + plen + 1
- atomic.StoreInt32(&nameMax, int32(elen))
- }
-
- syscall.Entersyscall()
- r := libc_opendir(p)
- errno := syscall.GetErrno()
- syscall.Exitsyscall()
- if r == nil {
- return nil, &PathError{"opendir", file.name, errno}
- }
-
- file.dirinfo = new(dirInfo)
- file.dirinfo.buf = make([]byte, elen)
- file.dirinfo.dir = r
- }
-
- entryDirent := (*syscall.Dirent)(unsafe.Pointer(&file.dirinfo.buf[0]))
-
- size := n
- if size <= 0 {
- size = 100
- n = -1
- }
-
- names = make([]string, 0, size) // Empty with room to grow.
-
- for n != 0 {
- var dirent *syscall.Dirent
- pr := &dirent
- syscall.Entersyscall()
- i := libc_readdir_r(file.dirinfo.dir, entryDirent, pr)
- syscall.Exitsyscall()
- if i != 0 {
- return names, NewSyscallError("readdir_r", i)
- }
- if dirent == nil {
- break // EOF
- }
- bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
- var name = string(bytes[0:clen(bytes[:])])
- if name == "." || name == ".." { // Useless names
- continue
- }
- names = append(names, name)
- n--
- }
- if n >= 0 && len(names) == 0 {
- return names, io.EOF
+// Readdirnames reads and returns a slice of names from the directory f.
+//
+// If n > 0, Readdirnames returns at most n names. In this case, if
+// Readdirnames returns an empty slice, it will return a non-nil error
+// explaining why. At the end of a directory, the error is io.EOF.
+//
+// If n <= 0, Readdirnames returns all the names from the directory in
+// a single slice. In this case, if Readdirnames succeeds (reads all
+// the way to the end of the directory), it returns the slice and a
+// nil error. If it encounters an error before the end of the
+// directory, Readdirnames returns the names read until that point and
+// a non-nil error.
+func (f *File) Readdirnames(n int) (names []string, err error) {
+ if f == nil {
+ return nil, ErrInvalid
}
- return names, nil
+ return f.readdirnames(n)
}
diff --git a/libgo/go/os/dir_gccgo.go b/libgo/go/os/dir_gccgo.go
new file mode 100644
index 00000000000..d811c9fdd86
--- /dev/null
+++ b/libgo/go/os/dir_gccgo.go
@@ -0,0 +1,102 @@
+// 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 os
+
+import (
+ "io"
+ "sync/atomic"
+ "syscall"
+ "unsafe"
+)
+
+//extern opendir
+func libc_opendir(*byte) *syscall.DIR
+
+//extern closedir
+func libc_closedir(*syscall.DIR) int
+
+// FIXME: pathconf returns long, not int.
+//extern pathconf
+func libc_pathconf(*byte, int) int
+
+func clen(n []byte) int {
+ for i := 0; i < len(n); i++ {
+ if n[i] == 0 {
+ return i
+ }
+ }
+ return len(n)
+}
+
+var nameMax int32
+
+func (file *File) readdirnames(n int) (names []string, err error) {
+ if file.dirinfo == nil {
+ p, err := syscall.BytePtrFromString(file.name)
+ if err != nil {
+ return nil, err
+ }
+
+ elen := int(atomic.LoadInt32(&nameMax))
+ if elen == 0 {
+ syscall.Entersyscall()
+ plen := libc_pathconf(p, syscall.PC_NAME_MAX)
+ syscall.Exitsyscall()
+ if plen < 1024 {
+ plen = 1024
+ }
+ var dummy syscall.Dirent
+ elen = int(unsafe.Offsetof(dummy.Name)) + plen + 1
+ atomic.StoreInt32(&nameMax, int32(elen))
+ }
+
+ syscall.Entersyscall()
+ r := libc_opendir(p)
+ errno := syscall.GetErrno()
+ syscall.Exitsyscall()
+ if r == nil {
+ return nil, &PathError{"opendir", file.name, errno}
+ }
+
+ file.dirinfo = new(dirInfo)
+ file.dirinfo.buf = make([]byte, elen)
+ file.dirinfo.dir = r
+ }
+
+ entryDirent := (*syscall.Dirent)(unsafe.Pointer(&file.dirinfo.buf[0]))
+
+ size := n
+ if size <= 0 {
+ size = 100
+ n = -1
+ }
+
+ names = make([]string, 0, size) // Empty with room to grow.
+
+ for n != 0 {
+ var dirent *syscall.Dirent
+ pr := &dirent
+ syscall.Entersyscall()
+ i := libc_readdir_r(file.dirinfo.dir, entryDirent, pr)
+ syscall.Exitsyscall()
+ if i != 0 {
+ return names, NewSyscallError("readdir_r", i)
+ }
+ if dirent == nil {
+ break // EOF
+ }
+ bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
+ var name = string(bytes[0:clen(bytes[:])])
+ if name == "." || name == ".." { // Useless names
+ continue
+ }
+ names = append(names, name)
+ n--
+ }
+ if n >= 0 && len(names) == 0 {
+ return names, io.EOF
+ }
+ return names, nil
+}
diff --git a/libgo/go/os/dir_unix.go b/libgo/go/os/dir_unix.go
new file mode 100644
index 00000000000..cd42f59e01f
--- /dev/null
+++ b/libgo/go/os/dir_unix.go
@@ -0,0 +1,38 @@
+// 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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package os
+
+import (
+ "io"
+)
+
+func (f *File) readdir(n int) (fi []FileInfo, err error) {
+ dirname := f.name
+ if dirname == "" {
+ dirname = "."
+ }
+ names, err := f.Readdirnames(n)
+ fi = make([]FileInfo, 0, len(names))
+ for _, filename := range names {
+ fip, lerr := lstat(dirname + "/" + filename)
+ if IsNotExist(lerr) {
+ // File disappeared between readdir + stat.
+ // Just treat it as if it didn't exist.
+ continue
+ }
+ if lerr != nil {
+ return fi, lerr
+ }
+ fi = append(fi, fip)
+ }
+ if len(fi) == 0 && err == nil && n > 0 {
+ // Per File.Readdir, the slice must be non-empty or err
+ // must be non-nil if n > 0.
+ err = io.EOF
+ }
+ return fi, err
+}
diff --git a/libgo/go/os/doc.go b/libgo/go/os/doc.go
deleted file mode 100644
index 0313eac234d..00000000000
--- a/libgo/go/os/doc.go
+++ /dev/null
@@ -1,139 +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.
-
-package os
-
-import "time"
-
-// FindProcess looks for a running process by its pid.
-//
-// The Process it returns can be used to obtain information
-// about the underlying operating system process.
-//
-// On Unix systems, FindProcess always succeeds and returns a Process
-// for the given pid, regardless of whether the process exists.
-func FindProcess(pid int) (*Process, error) {
- return findProcess(pid)
-}
-
-// StartProcess starts a new process with the program, arguments and attributes
-// specified by name, argv and attr.
-//
-// StartProcess is a low-level interface. The os/exec package provides
-// higher-level interfaces.
-//
-// If there is an error, it will be of type *PathError.
-func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) {
- return startProcess(name, argv, attr)
-}
-
-// Release releases any resources associated with the Process p,
-// rendering it unusable in the future.
-// Release only needs to be called if Wait is not.
-func (p *Process) Release() error {
- return p.release()
-}
-
-// Kill causes the Process to exit immediately.
-func (p *Process) Kill() error {
- return p.kill()
-}
-
-// Wait waits for the Process to exit, and then returns a
-// ProcessState describing its status and an error, if any.
-// Wait releases any resources associated with the Process.
-// On most operating systems, the Process must be a child
-// of the current process or an error will be returned.
-func (p *Process) Wait() (*ProcessState, error) {
- return p.wait()
-}
-
-// Signal sends a signal to the Process.
-// Sending Interrupt on Windows is not implemented.
-func (p *Process) Signal(sig Signal) error {
- return p.signal(sig)
-}
-
-// UserTime returns the user CPU time of the exited process and its children.
-func (p *ProcessState) UserTime() time.Duration {
- return p.userTime()
-}
-
-// SystemTime returns the system CPU time of the exited process and its children.
-func (p *ProcessState) SystemTime() time.Duration {
- return p.systemTime()
-}
-
-// Exited reports whether the program has exited.
-func (p *ProcessState) Exited() bool {
- return p.exited()
-}
-
-// Success reports whether the program exited successfully,
-// such as with exit status 0 on Unix.
-func (p *ProcessState) Success() bool {
- return p.success()
-}
-
-// Sys returns system-dependent exit information about
-// the process. Convert it to the appropriate underlying
-// type, such as syscall.WaitStatus on Unix, to access its contents.
-func (p *ProcessState) Sys() interface{} {
- return p.sys()
-}
-
-// SysUsage returns system-dependent resource usage information about
-// the exited process. Convert it to the appropriate underlying
-// type, such as *syscall.Rusage on Unix, to access its contents.
-// (On Unix, *syscall.Rusage matches struct rusage as defined in the
-// getrusage(2) manual page.)
-func (p *ProcessState) SysUsage() interface{} {
- return p.sysUsage()
-}
-
-// Hostname returns the host name reported by the kernel.
-func Hostname() (name string, err error) {
- return hostname()
-}
-
-// Readdir reads the contents of the directory associated with file and
-// returns a slice of up to n FileInfo values, as would be returned
-// by Lstat, in directory order. Subsequent calls on the same file will yield
-// further FileInfos.
-//
-// If n > 0, Readdir returns at most n FileInfo structures. In this case, if
-// Readdir returns an empty slice, it will return a non-nil error
-// explaining why. At the end of a directory, the error is io.EOF.
-//
-// If n <= 0, Readdir returns all the FileInfo from the directory in
-// a single slice. In this case, if Readdir succeeds (reads all
-// the way to the end of the directory), it returns the slice and a
-// nil error. If it encounters an error before the end of the
-// directory, Readdir returns the FileInfo read until that point
-// and a non-nil error.
-func (f *File) Readdir(n int) ([]FileInfo, error) {
- if f == nil {
- return nil, ErrInvalid
- }
- return f.readdir(n)
-}
-
-// Readdirnames reads and returns a slice of names from the directory f.
-//
-// If n > 0, Readdirnames returns at most n names. In this case, if
-// Readdirnames returns an empty slice, it will return a non-nil error
-// explaining why. At the end of a directory, the error is io.EOF.
-//
-// If n <= 0, Readdirnames returns all the names from the directory in
-// a single slice. In this case, if Readdirnames succeeds (reads all
-// the way to the end of the directory), it returns the slice and a
-// nil error. If it encounters an error before the end of the
-// directory, Readdirnames returns the names read until that point and
-// a non-nil error.
-func (f *File) Readdirnames(n int) (names []string, err error) {
- if f == nil {
- return nil, ErrInvalid
- }
- return f.readdirnames(n)
-}
diff --git a/libgo/go/os/env.go b/libgo/go/os/env.go
index 4a147144c3e..a03b8f68f50 100644
--- a/libgo/go/os/env.go
+++ b/libgo/go/os/env.go
@@ -37,7 +37,7 @@ func ExpandEnv(s string) string {
// shell variable such as $*.
func isShellSpecialVar(c uint8) bool {
switch c {
- case '*', '#', '$', '@', '!', '?', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ case '*', '#', '$', '@', '!', '?', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return true
}
return false
@@ -76,6 +76,7 @@ func getShellName(s string) (string, int) {
// Getenv retrieves the value of the environment variable named by the key.
// It returns the value, which will be empty if the variable is not present.
+// To distinguish between an empty value and an unset value, use LookupEnv.
func Getenv(key string) string {
v, _ := syscall.Getenv(key)
return v
diff --git a/libgo/go/os/env_test.go b/libgo/go/os/env_test.go
index d1074cdc60a..e5749f0e899 100644
--- a/libgo/go/os/env_test.go
+++ b/libgo/go/os/env_test.go
@@ -95,6 +95,34 @@ func TestUnsetenv(t *testing.T) {
}
}
+func TestClearenv(t *testing.T) {
+ const testKey = "GO_TEST_CLEARENV"
+ const testValue = "1"
+
+ // reset env
+ defer func(origEnv []string) {
+ for _, pair := range origEnv {
+ // Environment variables on Windows can begin with =
+ // http://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
+ i := strings.Index(pair[1:], "=") + 1
+ if err := Setenv(pair[:i], pair[i+1:]); err != nil {
+ t.Errorf("Setenv(%q, %q) failed during reset: %v", pair[:i], pair[i+1:], err)
+ }
+ }
+ }(Environ())
+
+ if err := Setenv(testKey, testValue); err != nil {
+ t.Fatalf("Setenv(%q, %q) failed: %v", testKey, testValue, err)
+ }
+ if _, ok := LookupEnv(testKey); !ok {
+ t.Errorf("Setenv(%q, %q) didn't set $%s", testKey, testValue, testKey)
+ }
+ Clearenv()
+ if val, ok := LookupEnv(testKey); ok {
+ t.Errorf("Clearenv() didn't clear $%s, remained with value %q", testKey, val)
+ }
+}
+
func TestLookupEnv(t *testing.T) {
const smallpox = "SMALLPOX" // No one has smallpox.
value, ok := LookupEnv(smallpox) // Should not exist.
diff --git a/libgo/go/os/env_unix_test.go b/libgo/go/os/env_unix_test.go
index 5ec07ee1b1b..f7b67ebbb80 100644
--- a/libgo/go/os/env_unix_test.go
+++ b/libgo/go/os/env_unix_test.go
@@ -7,6 +7,7 @@
package os_test
import (
+ "fmt"
. "os"
"testing"
)
@@ -28,3 +29,28 @@ func TestSetenvUnixEinval(t *testing.T) {
}
}
}
+
+var shellSpecialVarTests = []struct {
+ k, v string
+}{
+ {"*", "asterisk"},
+ {"#", "pound"},
+ {"$", "dollar"},
+ {"@", "at"},
+ {"!", "exclamation mark"},
+ {"?", "question mark"},
+ {"-", "dash"},
+}
+
+func TestExpandEnvShellSpecialVar(t *testing.T) {
+ for _, tt := range shellSpecialVarTests {
+ Setenv(tt.k, tt.v)
+ defer Unsetenv(tt.k)
+
+ argRaw := fmt.Sprintf("$%s", tt.k)
+ argWithBrace := fmt.Sprintf("${%s}", tt.k)
+ if gotRaw, gotBrace := ExpandEnv(argRaw), ExpandEnv(argWithBrace); gotRaw != gotBrace {
+ t.Errorf("ExpandEnv(%q) = %q, ExpandEnv(%q) = %q; expect them to be equal", argRaw, gotRaw, argWithBrace, gotBrace)
+ }
+ }
+}
diff --git a/libgo/go/os/error.go b/libgo/go/os/error.go
index e26ce279706..7235bfb6d61 100644
--- a/libgo/go/os/error.go
+++ b/libgo/go/os/error.go
@@ -14,6 +14,7 @@ var (
ErrPermission = errors.New("permission denied")
ErrExist = errors.New("file already exists")
ErrNotExist = errors.New("file does not exist")
+ ErrClosed = errors.New("file already closed")
)
// PathError records an error and the operation and file path that caused it.
@@ -63,3 +64,16 @@ func IsNotExist(err error) bool {
func IsPermission(err error) bool {
return isPermission(err)
}
+
+// underlyingError returns the underlying error for known os error types.
+func underlyingError(err error) error {
+ switch err := err.(type) {
+ case *PathError:
+ return err.Err
+ case *LinkError:
+ return err.Err
+ case *SyscallError:
+ return err.Err
+ }
+ return err
+}
diff --git a/libgo/go/os/error_plan9.go b/libgo/go/os/error_plan9.go
index 2dc6b39c395..a67343981e2 100644
--- a/libgo/go/os/error_plan9.go
+++ b/libgo/go/os/error_plan9.go
@@ -5,46 +5,30 @@
package os
func isExist(err error) bool {
- switch pe := err.(type) {
- case nil:
- return false
- case *PathError:
- err = pe.Err
- case *LinkError:
- err = pe.Err
- case *SyscallError:
- err = pe.Err
- }
- return contains(err.Error(), " exists")
+ return checkErrMessageContent(err, " exists")
}
func isNotExist(err error) bool {
- switch pe := err.(type) {
- case nil:
- return false
- case *PathError:
- err = pe.Err
- case *LinkError:
- err = pe.Err
- case *SyscallError:
- err = pe.Err
- }
- return contains(err.Error(), "does not exist") || contains(err.Error(), "not found") ||
- contains(err.Error(), "has been removed") || contains(err.Error(), "no parent")
+ return checkErrMessageContent(err, "does not exist", "not found",
+ "has been removed", "no parent")
}
func isPermission(err error) bool {
- switch pe := err.(type) {
- case nil:
+ return checkErrMessageContent(err, "permission denied")
+}
+
+// checkErrMessageContent checks if err message contains one of msgs.
+func checkErrMessageContent(err error, msgs ...string) bool {
+ if err == nil {
return false
- case *PathError:
- err = pe.Err
- case *LinkError:
- err = pe.Err
- case *SyscallError:
- err = pe.Err
}
- return contains(err.Error(), "permission denied")
+ err = underlyingError(err)
+ for _, msg := range msgs {
+ if contains(err.Error(), msg) {
+ return true
+ }
+ }
+ return false
}
// contains is a local version of strings.Contains. It knows len(sep) > 1.
diff --git a/libgo/go/os/error_test.go b/libgo/go/os/error_test.go
index a47c1732cb8..3499ceec959 100644
--- a/libgo/go/os/error_test.go
+++ b/libgo/go/os/error_test.go
@@ -91,10 +91,12 @@ var isExistTests = []isExistTest{
{&os.PathError{Err: os.ErrPermission}, false, false},
{&os.PathError{Err: os.ErrExist}, true, false},
{&os.PathError{Err: os.ErrNotExist}, false, true},
+ {&os.PathError{Err: os.ErrClosed}, false, false},
{&os.LinkError{Err: os.ErrInvalid}, false, false},
{&os.LinkError{Err: os.ErrPermission}, false, false},
{&os.LinkError{Err: os.ErrExist}, true, false},
{&os.LinkError{Err: os.ErrNotExist}, false, true},
+ {&os.LinkError{Err: os.ErrClosed}, false, false},
{&os.SyscallError{Err: os.ErrNotExist}, false, true},
{&os.SyscallError{Err: os.ErrExist}, true, false},
{nil, false, false},
diff --git a/libgo/go/os/error_unix.go b/libgo/go/os/error_unix.go
index 3c78eb4dd2f..be1440cacba 100644
--- a/libgo/go/os/error_unix.go
+++ b/libgo/go/os/error_unix.go
@@ -9,43 +9,16 @@ package os
import "syscall"
func isExist(err error) bool {
- switch pe := err.(type) {
- case nil:
- return false
- case *PathError:
- err = pe.Err
- case *LinkError:
- err = pe.Err
- case *SyscallError:
- err = pe.Err
- }
+ err = underlyingError(err)
return err == syscall.EEXIST || err == syscall.ENOTEMPTY || err == ErrExist
}
func isNotExist(err error) bool {
- switch pe := err.(type) {
- case nil:
- return false
- case *PathError:
- err = pe.Err
- case *LinkError:
- err = pe.Err
- case *SyscallError:
- err = pe.Err
- }
+ err = underlyingError(err)
return err == syscall.ENOENT || err == ErrNotExist
}
func isPermission(err error) bool {
- switch pe := err.(type) {
- case nil:
- return false
- case *PathError:
- err = pe.Err
- case *LinkError:
- err = pe.Err
- case *SyscallError:
- err = pe.Err
- }
+ err = underlyingError(err)
return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission
}
diff --git a/libgo/go/os/error_windows.go b/libgo/go/os/error_windows.go
index 2c1c39c414b..02593b53fe4 100644
--- a/libgo/go/os/error_windows.go
+++ b/libgo/go/os/error_windows.go
@@ -7,48 +7,22 @@ package os
import "syscall"
func isExist(err error) bool {
- switch pe := err.(type) {
- case nil:
- return false
- case *PathError:
- err = pe.Err
- case *LinkError:
- err = pe.Err
- case *SyscallError:
- err = pe.Err
- }
+ err = underlyingError(err)
return err == syscall.ERROR_ALREADY_EXISTS ||
+ err == syscall.ERROR_DIR_NOT_EMPTY ||
err == syscall.ERROR_FILE_EXISTS || err == ErrExist
}
const _ERROR_BAD_NETPATH = syscall.Errno(53)
func isNotExist(err error) bool {
- switch pe := err.(type) {
- case nil:
- return false
- case *PathError:
- err = pe.Err
- case *LinkError:
- err = pe.Err
- case *SyscallError:
- err = pe.Err
- }
+ err = underlyingError(err)
return err == syscall.ERROR_FILE_NOT_FOUND ||
err == _ERROR_BAD_NETPATH ||
err == syscall.ERROR_PATH_NOT_FOUND || err == ErrNotExist
}
func isPermission(err error) bool {
- switch pe := err.(type) {
- case nil:
- return false
- case *PathError:
- err = pe.Err
- case *LinkError:
- err = pe.Err
- case *SyscallError:
- err = pe.Err
- }
+ err = underlyingError(err)
return err == syscall.ERROR_ACCESS_DENIED || err == ErrPermission
}
diff --git a/libgo/go/os/error_windows_test.go b/libgo/go/os/error_windows_test.go
index 427dfdb962c..1635c1088e6 100644
--- a/libgo/go/os/error_windows_test.go
+++ b/libgo/go/os/error_windows_test.go
@@ -26,6 +26,10 @@ func init() {
isExistTest{err: &os.PathError{Err: syscall.ERROR_PATH_NOT_FOUND}, is: false, isnot: true},
isExistTest{err: &os.LinkError{Err: syscall.ERROR_PATH_NOT_FOUND}, is: false, isnot: true},
isExistTest{err: &os.SyscallError{Err: syscall.ERROR_PATH_NOT_FOUND}, is: false, isnot: true},
+
+ isExistTest{err: &os.PathError{Err: syscall.ERROR_DIR_NOT_EMPTY}, is: true, isnot: false},
+ isExistTest{err: &os.LinkError{Err: syscall.ERROR_DIR_NOT_EMPTY}, is: true, isnot: false},
+ isExistTest{err: &os.SyscallError{Err: syscall.ERROR_DIR_NOT_EMPTY}, is: true, isnot: false},
)
isPermissionTests = append(isPermissionTests,
isPermissionTest{err: &os.PathError{Err: syscall.ERROR_ACCESS_DENIED}, want: true},
diff --git a/libgo/go/os/example_test.go b/libgo/go/os/example_test.go
new file mode 100644
index 00000000000..07f9c769590
--- /dev/null
+++ b/libgo/go/os/example_test.go
@@ -0,0 +1,106 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os_test
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "time"
+)
+
+func ExampleOpenFile() {
+ f, err := os.OpenFile("notes.txt", os.O_RDWR|os.O_CREATE, 0755)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if err := f.Close(); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func ExampleChmod() {
+ if err := os.Chmod("some-filename", 0644); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func ExampleChtimes() {
+ mtime := time.Date(2006, time.February, 1, 3, 4, 5, 0, time.UTC)
+ atime := time.Date(2007, time.March, 2, 4, 5, 6, 0, time.UTC)
+ if err := os.Chtimes("some-filename", atime, mtime); err != nil {
+ log.Fatal(err)
+ }
+}
+
+func ExampleFileMode() {
+ fi, err := os.Stat("some-filename")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ switch mode := fi.Mode(); {
+ case mode.IsRegular():
+ fmt.Println("regular file")
+ case mode.IsDir():
+ fmt.Println("directory")
+ case mode&os.ModeSymlink != 0:
+ fmt.Println("symbolic link")
+ case mode&os.ModeNamedPipe != 0:
+ fmt.Println("named pipe")
+ }
+}
+
+func ExampleIsNotExist() {
+ filename := "a-nonexistent-file"
+ if _, err := os.Stat(filename); os.IsNotExist(err) {
+ fmt.Printf("file does not exist")
+ }
+ // Output:
+ // file does not exist
+}
+
+func init() {
+ os.Setenv("USER", "gopher")
+ os.Setenv("HOME", "/usr/gopher")
+ os.Unsetenv("GOPATH")
+}
+
+func ExampleExpandEnv() {
+ fmt.Println(os.ExpandEnv("$USER lives in ${HOME}."))
+
+ // Output:
+ // gopher lives in /usr/gopher.
+}
+
+func ExampleLookupEnv() {
+ show := func(key string) {
+ val, ok := os.LookupEnv(key)
+ if !ok {
+ fmt.Printf("%s not set\n", key)
+ } else {
+ fmt.Printf("%s=%s\n", key, val)
+ }
+ }
+
+ show("USER")
+ show("GOPATH")
+
+ // Output:
+ // USER=gopher
+ // GOPATH not set
+}
+
+func ExampleGetenv() {
+ fmt.Printf("%s lives in %s.\n", os.Getenv("USER"), os.Getenv("HOME"))
+
+ // Output:
+ // gopher lives in /usr/gopher.
+}
+
+func ExampleUnsetenv() {
+ os.Setenv("TMPDIR", "/my/tmp")
+ defer os.Unsetenv("TMPDIR")
+}
diff --git a/libgo/go/os/exec.go b/libgo/go/os/exec.go
index bf3249864d3..8a53e5dd1ee 100644
--- a/libgo/go/os/exec.go
+++ b/libgo/go/os/exec.go
@@ -9,6 +9,7 @@ import (
"sync"
"sync/atomic"
"syscall"
+ "time"
)
// Process stores the information about a process created by StartProcess.
@@ -70,3 +71,89 @@ func Getpid() int { return syscall.Getpid() }
// Getppid returns the process id of the caller's parent.
func Getppid() int { return syscall.Getppid() }
+
+// FindProcess looks for a running process by its pid.
+//
+// The Process it returns can be used to obtain information
+// about the underlying operating system process.
+//
+// On Unix systems, FindProcess always succeeds and returns a Process
+// for the given pid, regardless of whether the process exists.
+func FindProcess(pid int) (*Process, error) {
+ return findProcess(pid)
+}
+
+// StartProcess starts a new process with the program, arguments and attributes
+// specified by name, argv and attr.
+//
+// StartProcess is a low-level interface. The os/exec package provides
+// higher-level interfaces.
+//
+// If there is an error, it will be of type *PathError.
+func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) {
+ return startProcess(name, argv, attr)
+}
+
+// Release releases any resources associated with the Process p,
+// rendering it unusable in the future.
+// Release only needs to be called if Wait is not.
+func (p *Process) Release() error {
+ return p.release()
+}
+
+// Kill causes the Process to exit immediately.
+func (p *Process) Kill() error {
+ return p.kill()
+}
+
+// Wait waits for the Process to exit, and then returns a
+// ProcessState describing its status and an error, if any.
+// Wait releases any resources associated with the Process.
+// On most operating systems, the Process must be a child
+// of the current process or an error will be returned.
+func (p *Process) Wait() (*ProcessState, error) {
+ return p.wait()
+}
+
+// Signal sends a signal to the Process.
+// Sending Interrupt on Windows is not implemented.
+func (p *Process) Signal(sig Signal) error {
+ return p.signal(sig)
+}
+
+// UserTime returns the user CPU time of the exited process and its children.
+func (p *ProcessState) UserTime() time.Duration {
+ return p.userTime()
+}
+
+// SystemTime returns the system CPU time of the exited process and its children.
+func (p *ProcessState) SystemTime() time.Duration {
+ return p.systemTime()
+}
+
+// Exited reports whether the program has exited.
+func (p *ProcessState) Exited() bool {
+ return p.exited()
+}
+
+// Success reports whether the program exited successfully,
+// such as with exit status 0 on Unix.
+func (p *ProcessState) Success() bool {
+ return p.success()
+}
+
+// Sys returns system-dependent exit information about
+// the process. Convert it to the appropriate underlying
+// type, such as syscall.WaitStatus on Unix, to access its contents.
+func (p *ProcessState) Sys() interface{} {
+ return p.sys()
+}
+
+// SysUsage returns system-dependent resource usage information about
+// the exited process. Convert it to the appropriate underlying
+// type, such as *syscall.Rusage on Unix, to access its contents.
+// (On Unix, *syscall.Rusage matches struct rusage as defined in the
+// getrusage(2) manual page.)
+func (p *ProcessState) SysUsage() interface{} {
+ return p.sysUsage()
+}
diff --git a/libgo/go/os/exec/exec.go b/libgo/go/os/exec/exec.go
index d2c1b17e509..c4c5168b980 100644
--- a/libgo/go/os/exec/exec.go
+++ b/libgo/go/os/exec/exec.go
@@ -120,12 +120,13 @@ type Cmd struct {
// It sets only the Path and Args in the returned structure.
//
// If name contains no path separators, Command uses LookPath to
-// resolve the path to a complete name if possible. Otherwise it uses
-// name directly.
+// resolve name to a complete path if possible. Otherwise it uses name
+// directly as Path.
//
// The returned Cmd's Args field is constructed from the command name
// followed by the elements of arg, so arg should not include the
-// command name itself. For example, Command("echo", "hello")
+// command name itself. For example, Command("echo", "hello").
+// Args[0] is always name, not the possibly resolved Path.
func Command(name string, arg ...string) *Cmd {
cmd := &Cmd{
Path: name,
@@ -515,15 +516,16 @@ func (c *Cmd) StdinPipe() (io.WriteCloser, error) {
c.Stdin = pr
c.closeAfterStart = append(c.closeAfterStart, pr)
wc := &closeOnce{File: pw}
- c.closeAfterWait = append(c.closeAfterWait, wc)
+ c.closeAfterWait = append(c.closeAfterWait, closerFunc(wc.safeClose))
return wc, nil
}
type closeOnce struct {
*os.File
- once sync.Once
- err error
+ writers sync.RWMutex // coordinate safeClose and Write
+ once sync.Once
+ err error
}
func (c *closeOnce) Close() error {
@@ -535,6 +537,55 @@ func (c *closeOnce) close() {
c.err = c.File.Close()
}
+type closerFunc func() error
+
+func (f closerFunc) Close() error { return f() }
+
+// safeClose closes c being careful not to race with any calls to c.Write.
+// See golang.org/issue/9307 and TestEchoFileRace in exec_test.go.
+// In theory other calls could also be excluded (by writing appropriate
+// wrappers like c.Write's implementation below), but since c is most
+// commonly used as a WriteCloser, Write is the main one to worry about.
+// See also #7970, for which this is a partial fix for this specific instance.
+// The idea is that we return a WriteCloser, and so the caller can be
+// relied upon not to call Write and Close simultaneously, but it's less
+// obvious that cmd.Wait calls Close and that the caller must not call
+// Write and cmd.Wait simultaneously. In fact that seems too onerous.
+// So we change the use of Close in cmd.Wait to use safeClose, which will
+// synchronize with any Write.
+//
+// It's important that we know this won't block forever waiting for the
+// operations being excluded. At the point where this is called,
+// the invoked command has exited and the parent copy of the read side
+// of the pipe has also been closed, so there should really be no read side
+// of the pipe left. Any active writes should return very shortly with an EPIPE,
+// making it reasonable to wait for them.
+// Technically it is possible that the child forked a sub-process or otherwise
+// handed off the read side of the pipe before exiting and the current holder
+// is not reading from the pipe, and the pipe is full, in which case the close here
+// might block waiting for the write to complete. That's probably OK.
+// It's a small enough problem to be outweighed by eliminating the race here.
+func (c *closeOnce) safeClose() error {
+ c.writers.Lock()
+ err := c.Close()
+ c.writers.Unlock()
+ return err
+}
+
+func (c *closeOnce) Write(b []byte) (int, error) {
+ c.writers.RLock()
+ n, err := c.File.Write(b)
+ c.writers.RUnlock()
+ return n, err
+}
+
+func (c *closeOnce) WriteString(s string) (int, error) {
+ c.writers.RLock()
+ n, err := c.File.WriteString(s)
+ c.writers.RUnlock()
+ return n, err
+}
+
// StdoutPipe returns a pipe that will be connected to the command's
// standard output when the command starts.
//
diff --git a/libgo/go/os/exec/exec_test.go b/libgo/go/os/exec/exec_test.go
index 3a866a99550..a9cceecd2a8 100644
--- a/libgo/go/os/exec/exec_test.go
+++ b/libgo/go/os/exec/exec_test.go
@@ -105,6 +105,26 @@ func TestCatStdin(t *testing.T) {
}
}
+func TestEchoFileRace(t *testing.T) {
+ cmd := helperCommand(t, "echo")
+ stdin, err := cmd.StdinPipe()
+ if err != nil {
+ t.Fatalf("StdinPipe: %v", err)
+ }
+ if err := cmd.Start(); err != nil {
+ t.Fatalf("Start: %v", err)
+ }
+ wrote := make(chan bool)
+ go func() {
+ defer close(wrote)
+ fmt.Fprint(stdin, "echo\n")
+ }()
+ if err := cmd.Wait(); err != nil {
+ t.Fatalf("Wait: %v", err)
+ }
+ <-wrote
+}
+
func TestCatGoodAndBadFile(t *testing.T) {
// Testing combined output and error values.
bs, err := helperCommand(t, "cat", "/bogus/file.foo", "exec_test.go").CombinedOutput()
@@ -230,6 +250,42 @@ func TestStdinClose(t *testing.T) {
check("Wait", cmd.Wait())
}
+// Issue 17647.
+// It used to be the case that TestStdinClose, above, would fail when
+// run under the race detector. This test is a variant of TestStdinClose
+// that also used to fail when run under the race detector.
+// This test is run by cmd/dist under the race detector to verify that
+// the race detector no longer reports any problems.
+func TestStdinCloseRace(t *testing.T) {
+ cmd := helperCommand(t, "stdinClose")
+ stdin, err := cmd.StdinPipe()
+ if err != nil {
+ t.Fatalf("StdinPipe: %v", err)
+ }
+ if err := cmd.Start(); err != nil {
+ t.Fatalf("Start: %v", err)
+ }
+ go func() {
+ if err := cmd.Process.Kill(); err != nil {
+ t.Errorf("Kill: %v", err)
+ }
+ }()
+ go func() {
+ // Send the wrong string, so that the child fails even
+ // if the other goroutine doesn't manage to kill it first.
+ // This test is to check that the race detector does not
+ // falsely report an error, so it doesn't matter how the
+ // child process fails.
+ io.Copy(stdin, strings.NewReader("unexpected string"))
+ if err := stdin.Close(); err != nil {
+ t.Errorf("stdin.Close: %v", err)
+ }
+ }()
+ if err := cmd.Wait(); err == nil {
+ t.Fatalf("Wait: succeeded unexpectedly")
+ }
+}
+
// Issue 5071
func TestPipeLookPathLeak(t *testing.T) {
fd0, lsof0 := numOpenFDS(t)
@@ -416,7 +472,7 @@ func TestExtraFilesFDShuffle(t *testing.T) {
buf := make([]byte, 512)
n, err := stderr.Read(buf)
if err != nil {
- t.Fatalf("Read: %s", err)
+ t.Errorf("Read: %s", err)
ch <- err.Error()
} else {
ch <- string(buf[:n])
@@ -936,13 +992,13 @@ func TestContextCancel(t *testing.T) {
break
}
if time.Since(start) > time.Second {
- t.Fatal("cancelling context did not stop program")
+ t.Fatal("canceling context did not stop program")
}
time.Sleep(time.Millisecond)
}
if err := w.Close(); err != nil {
- t.Error("error closing write end of pipe: %v", err)
+ t.Errorf("error closing write end of pipe: %v", err)
}
<-readDone
diff --git a/libgo/go/os/exec_windows.go b/libgo/go/os/exec_windows.go
index 72b5a931999..d89db2022cc 100644
--- a/libgo/go/os/exec_windows.go
+++ b/libgo/go/os/exec_windows.go
@@ -63,7 +63,9 @@ func (p *Process) signal(sig Signal) error {
return errors.New("os: process already finished")
}
if sig == Kill {
- return terminateProcess(p.Pid, 1)
+ err := terminateProcess(p.Pid, 1)
+ runtime.KeepAlive(p)
+ return err
}
// TODO(rsc): Handle Interrupt too?
return syscall.Errno(syscall.EWINDOWS)
diff --git a/libgo/go/os/executable.go b/libgo/go/os/executable.go
new file mode 100644
index 00000000000..8c21246f5a8
--- /dev/null
+++ b/libgo/go/os/executable.go
@@ -0,0 +1,23 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+// Executable returns the path name for the executable that started
+// the current process. There is no guarantee that the path is still
+// pointing to the correct executable. If a symlink was used to start
+// the process, depending on the operating system, the result might
+// be the symlink or the path it pointed to. If a stable result is
+// needed, path/filepath.EvalSymlinks might help.
+//
+// Executable returns an absolute path unless an error occurred.
+//
+// The main use case is finding resources located relative to an
+// executable.
+//
+// Executable is not supported on nacl or OpenBSD (unless procfs is
+// mounted.)
+func Executable() (string, error) {
+ return executable()
+}
diff --git a/libgo/go/os/executable_darwin.go b/libgo/go/os/executable_darwin.go
new file mode 100644
index 00000000000..ce5b8140a4c
--- /dev/null
+++ b/libgo/go/os/executable_darwin.go
@@ -0,0 +1,24 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+var executablePath string // set by ../runtime/os_darwin.go
+
+var initCwd, initCwdErr = Getwd()
+
+func executable() (string, error) {
+ ep := executablePath
+ if ep[0] != '/' {
+ if initCwdErr != nil {
+ return ep, initCwdErr
+ }
+ if len(ep) > 2 && ep[0:2] == "./" {
+ // skip "./"
+ ep = ep[2:]
+ }
+ ep = initCwd + "/" + ep
+ }
+ return ep, nil
+}
diff --git a/libgo/go/os/executable_freebsd.go b/libgo/go/os/executable_freebsd.go
new file mode 100644
index 00000000000..ccaf8e6dd44
--- /dev/null
+++ b/libgo/go/os/executable_freebsd.go
@@ -0,0 +1,33 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+func executable() (string, error) {
+ mib := [4]int32{1 /* CTL_KERN */, 14 /* KERN_PROC */, 12 /* KERN_PROC_PATHNAME */, -1}
+
+ n := uintptr(0)
+ // get length
+ _, _, err := syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, 0, uintptr(unsafe.Pointer(&n)), 0, 0)
+ if err != 0 {
+ return "", err
+ }
+ if n == 0 { // shouldn't happen
+ return "", nil
+ }
+ buf := make([]byte, n)
+ _, _, err = syscall.Syscall6(syscall.SYS___SYSCTL, uintptr(unsafe.Pointer(&mib[0])), 4, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&n)), 0, 0)
+ if err != 0 {
+ return "", err
+ }
+ if n == 0 { // shouldn't happen
+ return "", nil
+ }
+ return string(buf[:n-1]), nil
+}
diff --git a/libgo/go/os/executable_plan9.go b/libgo/go/os/executable_plan9.go
new file mode 100644
index 00000000000..a5947eaae1e
--- /dev/null
+++ b/libgo/go/os/executable_plan9.go
@@ -0,0 +1,19 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build plan9
+
+package os
+
+import "syscall"
+
+func executable() (string, error) {
+ fn := "/proc/" + itoa(Getpid()) + "/text"
+ f, err := Open(fn)
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+ return syscall.Fd2path(int(f.Fd()))
+}
diff --git a/libgo/go/os/executable_procfs.go b/libgo/go/os/executable_procfs.go
new file mode 100644
index 00000000000..69a70e18df0
--- /dev/null
+++ b/libgo/go/os/executable_procfs.go
@@ -0,0 +1,36 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux netbsd openbsd dragonfly nacl
+
+package os
+
+import (
+ "errors"
+ "runtime"
+)
+
+// We query the executable path at init time to avoid the problem of
+// readlink returns a path appended with " (deleted)" when the original
+// binary gets deleted.
+var executablePath, executablePathErr = func() (string, error) {
+ var procfn string
+ switch runtime.GOOS {
+ default:
+ return "", errors.New("Executable not implemented for " + runtime.GOOS)
+ case "linux", "android":
+ procfn = "/proc/self/exe"
+ case "netbsd":
+ procfn = "/proc/curproc/exe"
+ case "openbsd":
+ procfn = "/proc/curproc/file"
+ case "dragonfly":
+ procfn = "/proc/curproc/file"
+ }
+ return Readlink(procfn)
+}()
+
+func executable() (string, error) {
+ return executablePath, executablePathErr
+}
diff --git a/libgo/go/os/executable_solaris.go b/libgo/go/os/executable_solaris.go
new file mode 100644
index 00000000000..80f937201ac
--- /dev/null
+++ b/libgo/go/os/executable_solaris.go
@@ -0,0 +1,27 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import "syscall"
+
+var initCwd, initCwdErr = Getwd()
+
+func executable() (string, error) {
+ path, err := syscall.Getexecname()
+ if err != nil {
+ return path, err
+ }
+ if len(path) > 0 && path[0] != '/' {
+ if initCwdErr != nil {
+ return path, initCwdErr
+ }
+ if len(path) > 2 && path[0:2] == "./" {
+ // skip "./"
+ path = path[2:]
+ }
+ return initCwd + "/" + path, nil
+ }
+ return path, nil
+}
diff --git a/libgo/go/os/executable_test.go b/libgo/go/os/executable_test.go
new file mode 100644
index 00000000000..a4d89092ac6
--- /dev/null
+++ b/libgo/go/os/executable_test.go
@@ -0,0 +1,87 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os_test
+
+import (
+ "fmt"
+ "internal/testenv"
+ "os"
+ osexec "os/exec"
+ "path/filepath"
+ "runtime"
+ "testing"
+)
+
+const executable_EnvVar = "OSTEST_OUTPUT_EXECPATH"
+
+func TestExecutable(t *testing.T) {
+ testenv.MustHaveExec(t) // will also execlude nacl, which doesn't support Executable anyway
+ ep, err := os.Executable()
+ if err != nil {
+ switch goos := runtime.GOOS; goos {
+ case "openbsd": // procfs is not mounted by default
+ t.Skipf("Executable failed on %s: %v, expected", goos, err)
+ }
+ t.Fatalf("Executable failed: %v", err)
+ }
+ // we want fn to be of the form "dir/prog"
+ dir := filepath.Dir(filepath.Dir(ep))
+ fn, err := filepath.Rel(dir, ep)
+ if err != nil {
+ t.Fatalf("filepath.Rel: %v", err)
+ }
+ cmd := &osexec.Cmd{}
+ // make child start with a relative program path
+ cmd.Dir = dir
+ cmd.Path = fn
+ // forge argv[0] for child, so that we can verify we could correctly
+ // get real path of the executable without influenced by argv[0].
+ cmd.Args = []string{"-", "-test.run=XXXX"}
+ cmd.Env = append(os.Environ(), fmt.Sprintf("%s=1", executable_EnvVar))
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("exec(self) failed: %v", err)
+ }
+ outs := string(out)
+ if !filepath.IsAbs(outs) {
+ t.Fatalf("Child returned %q, want an absolute path", out)
+ }
+ if !sameFile(outs, ep) {
+ t.Fatalf("Child returned %q, not the same file as %q", out, ep)
+ }
+}
+
+func sameFile(fn1, fn2 string) bool {
+ fi1, err := os.Stat(fn1)
+ if err != nil {
+ return false
+ }
+ fi2, err := os.Stat(fn2)
+ if err != nil {
+ return false
+ }
+ return os.SameFile(fi1, fi2)
+}
+
+func init() {
+ if e := os.Getenv(executable_EnvVar); e != "" {
+ // first chdir to another path
+ dir := "/"
+ if runtime.GOOS == "windows" {
+ cwd, err := os.Getwd()
+ if err != nil {
+ panic(err)
+ }
+ dir = filepath.VolumeName(cwd)
+ }
+ os.Chdir(dir)
+ if ep, err := os.Executable(); err != nil {
+ fmt.Fprint(os.Stderr, "ERROR: ", err)
+ } else {
+ fmt.Fprint(os.Stderr, ep)
+ }
+ os.Exit(0)
+ }
+}
diff --git a/libgo/go/os/executable_windows.go b/libgo/go/os/executable_windows.go
new file mode 100644
index 00000000000..fc5cf860053
--- /dev/null
+++ b/libgo/go/os/executable_windows.go
@@ -0,0 +1,32 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+import (
+ "internal/syscall/windows"
+ "syscall"
+)
+
+func getModuleFileName(handle syscall.Handle) (string, error) {
+ n := uint32(1024)
+ var buf []uint16
+ for {
+ buf = make([]uint16, n)
+ r, err := windows.GetModuleFileName(handle, &buf[0], n)
+ if err != nil {
+ return "", err
+ }
+ if r < n {
+ break
+ }
+ // r == n means n not big enough
+ n += 1024
+ }
+ return syscall.UTF16ToString(buf), nil
+}
+
+func executable() (string, error) {
+ return getModuleFileName(0)
+}
diff --git a/libgo/go/os/export_windows_test.go b/libgo/go/os/export_windows_test.go
new file mode 100644
index 00000000000..3bb2d2015f7
--- /dev/null
+++ b/libgo/go/os/export_windows_test.go
@@ -0,0 +1,13 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os
+
+// Export for testing.
+
+var (
+ FixLongPath = fixLongPath
+ NewConsoleFile = newConsoleFile
+ ReadConsoleFunc = &readConsole
+)
diff --git a/libgo/go/os/file.go b/libgo/go/os/file.go
index e546441497b..d45a00b1239 100644
--- a/libgo/go/os/file.go
+++ b/libgo/go/os/file.go
@@ -92,11 +92,11 @@ func (e *LinkError) Error() string {
}
// Read reads up to len(b) bytes from the File.
-// It returns the number of bytes read and an error, if any.
-// EOF is signaled by a zero count with err set to io.EOF.
+// It returns the number of bytes read and any error encountered.
+// At end of file, Read returns 0, io.EOF.
func (f *File) Read(b []byte) (n int, err error) {
- if f == nil {
- return 0, ErrInvalid
+ if err := f.checkValid("read"); err != nil {
+ return 0, err
}
n, e := f.read(b)
if n == 0 && len(b) > 0 && e == nil {
@@ -113,8 +113,8 @@ func (f *File) Read(b []byte) (n int, err error) {
// ReadAt always returns a non-nil error when n < len(b).
// At end of file, that error is io.EOF.
func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
- if f == nil {
- return 0, ErrInvalid
+ if err := f.checkValid("read"); err != nil {
+ return 0, err
}
for len(b) > 0 {
m, e := f.pread(b, off)
@@ -136,8 +136,8 @@ func (f *File) ReadAt(b []byte, off int64) (n int, err error) {
// It returns the number of bytes written and an error, if any.
// Write returns a non-nil error when n != len(b).
func (f *File) Write(b []byte) (n int, err error) {
- if f == nil {
- return 0, ErrInvalid
+ if err := f.checkValid("write"); err != nil {
+ return 0, err
}
n, e := f.write(b)
if n < 0 {
@@ -159,8 +159,8 @@ func (f *File) Write(b []byte) (n int, err error) {
// It returns the number of bytes written and an error, if any.
// WriteAt returns a non-nil error when n != len(b).
func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
- if f == nil {
- return 0, ErrInvalid
+ if err := f.checkValid("write"); err != nil {
+ return 0, err
}
for len(b) > 0 {
m, e := f.pwrite(b, off)
@@ -181,8 +181,8 @@ func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
// It returns the new offset and an error, if any.
// The behavior of Seek on a file opened with O_APPEND is not specified.
func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
- if f == nil {
- return 0, ErrInvalid
+ if err := f.checkValid("seek"); err != nil {
+ return 0, err
}
r, e := f.seek(offset, whence)
if e == nil && f.dirinfo != nil && r != 0 {
@@ -197,16 +197,13 @@ func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
// WriteString is like Write, but writes the contents of string s rather than
// a slice of bytes.
func (f *File) WriteString(s string) (n int, err error) {
- if f == nil {
- return 0, ErrInvalid
- }
return f.Write([]byte(s))
}
// Mkdir creates a new directory with the specified name and permission bits.
// If there is an error, it will be of type *PathError.
func Mkdir(name string, perm FileMode) error {
- e := syscall.Mkdir(name, syscallMode(perm))
+ e := syscall.Mkdir(fixLongPath(name), syscallMode(perm))
if e != nil {
return &PathError{"mkdir", name, e}
@@ -233,8 +230,8 @@ func Chdir(dir string) error {
// which must be a directory.
// If there is an error, it will be of type *PathError.
func (f *File) Chdir() error {
- if f == nil {
- return ErrInvalid
+ if err := f.checkValid("chdir"); err != nil {
+ return err
}
if e := syscall.Fchdir(f.fd); e != nil {
return &PathError{"chdir", f.name, e}
@@ -263,7 +260,7 @@ func Create(name string) (*File, error) {
var lstat = Lstat
// Rename renames (moves) oldpath to newpath.
-// If newpath already exists, Rename replaces it.
+// If newpath already exists and is not a directory, Rename replaces it.
// OS-specific restrictions may apply when oldpath and newpath are in different directories.
// If there is an error, it will be of type *LinkError.
func Rename(oldpath, newpath string) error {
@@ -278,3 +275,15 @@ func fixCount(n int, err error) (int, error) {
}
return n, err
}
+
+// checkValid checks whether f is valid for use.
+// If not, it returns an appropriate error, perhaps incorporating the operation name op.
+func (f *File) checkValid(op string) error {
+ if f == nil {
+ return ErrInvalid
+ }
+ if f.fd == badFd {
+ return &PathError{op, f.name, ErrClosed}
+ }
+ return nil
+}
diff --git a/libgo/go/os/file_plan9.go b/libgo/go/os/file_plan9.go
index 9edb6bc0747..5276a7ec541 100644
--- a/libgo/go/os/file_plan9.go
+++ b/libgo/go/os/file_plan9.go
@@ -11,9 +11,9 @@ import (
"time"
)
-// File represents an open file descriptor.
-type File struct {
- *file
+// fixLongPath is a noop on non-Windows platforms.
+func fixLongPath(path string) string {
+ return path
}
// file is the real representation of *File.
@@ -135,21 +135,21 @@ func OpenFile(name string, flag int, perm FileMode) (*File, error) {
// Close closes the File, rendering it unusable for I/O.
// It returns an error, if any.
func (f *File) Close() error {
- if f == nil {
- return ErrInvalid
+ if err := f.checkValid("close"); err != nil {
+ return err
}
return f.file.close()
}
func (file *file) close() error {
- if file == nil || file.fd < 0 {
+ if file == nil || file.fd == badFd {
return ErrInvalid
}
var err error
if e := syscall.Close(file.fd); e != nil {
err = &PathError{"close", file.name, e}
}
- file.fd = -1 // so it can't be closed again
+ file.fd = badFd // so it can't be closed again
// no need for a finalizer anymore
runtime.SetFinalizer(file, nil)
diff --git a/libgo/go/os/file_posix.go b/libgo/go/os/file_posix.go
index 6d8076fdf5c..d817f34b1d0 100644
--- a/libgo/go/os/file_posix.go
+++ b/libgo/go/os/file_posix.go
@@ -18,7 +18,7 @@ func sigpipe() // implemented in package runtime
func Readlink(name string) (string, error) {
for len := 128; ; len *= 2 {
b := make([]byte, len)
- n, e := fixCount(syscall.Readlink(name, b))
+ n, e := fixCount(syscall.Readlink(fixLongPath(name), b))
if e != nil {
return "", &PathError{"readlink", name, e}
}
@@ -57,8 +57,8 @@ func Chmod(name string, mode FileMode) error {
// Chmod changes the mode of the file to mode.
// If there is an error, it will be of type *PathError.
func (f *File) Chmod(mode FileMode) error {
- if f == nil {
- return ErrInvalid
+ if err := f.checkValid("chmod"); err != nil {
+ return err
}
if e := syscall.Fchmod(f.fd, syscallMode(mode)); e != nil {
return &PathError{"chmod", f.name, e}
@@ -89,8 +89,8 @@ func Lchown(name string, uid, gid int) error {
// Chown changes the numeric uid and gid of the named file.
// If there is an error, it will be of type *PathError.
func (f *File) Chown(uid, gid int) error {
- if f == nil {
- return ErrInvalid
+ if err := f.checkValid("chown"); err != nil {
+ return err
}
if e := syscall.Fchown(f.fd, uid, gid); e != nil {
return &PathError{"chown", f.name, e}
@@ -102,8 +102,8 @@ func (f *File) Chown(uid, gid int) error {
// It does not change the I/O offset.
// If there is an error, it will be of type *PathError.
func (f *File) Truncate(size int64) error {
- if f == nil {
- return ErrInvalid
+ if err := f.checkValid("truncate"); err != nil {
+ return err
}
if e := syscall.Ftruncate(f.fd, size); e != nil {
return &PathError{"truncate", f.name, e}
@@ -115,11 +115,11 @@ func (f *File) Truncate(size int64) error {
// Typically, this means flushing the file system's in-memory copy
// of recently written data to disk.
func (f *File) Sync() error {
- if f == nil {
- return ErrInvalid
+ if err := f.checkValid("sync"); err != nil {
+ return err
}
if e := syscall.Fsync(f.fd); e != nil {
- return NewSyscallError("fsync", e)
+ return &PathError{"sync", f.name, e}
}
return nil
}
@@ -134,7 +134,7 @@ func Chtimes(name string, atime time.Time, mtime time.Time) error {
var utimes [2]syscall.Timespec
utimes[0] = syscall.NsecToTimespec(atime.UnixNano())
utimes[1] = syscall.NsecToTimespec(mtime.UnixNano())
- if e := syscall.UtimesNano(name, utimes[0:]); e != nil {
+ if e := syscall.UtimesNano(fixLongPath(name), utimes[0:]); e != nil {
return &PathError{"chtimes", name, e}
}
return nil
diff --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go
index 5d6c8afe112..54b5dfd1285 100644
--- a/libgo/go/os/file_unix.go
+++ b/libgo/go/os/file_unix.go
@@ -11,11 +11,16 @@ import (
"syscall"
)
-func sameFile(fs1, fs2 *fileStat) bool {
- return fs1.sys.Dev == fs2.sys.Dev && fs1.sys.Ino == fs2.sys.Ino
+// fixLongPath is a noop on non-Windows platforms.
+func fixLongPath(path string) string {
+ return path
}
func rename(oldname, newname string) error {
+ fi, err := Lstat(newname)
+ if err == nil && fi.IsDir() {
+ return &LinkError{"rename", oldname, newname, syscall.EEXIST}
+ }
e := syscall.Rename(oldname, newname)
if e != nil {
return &LinkError{"rename", oldname, newname, e}
@@ -23,11 +28,6 @@ func rename(oldname, newname string) error {
return nil
}
-// File represents an open file descriptor.
-type File struct {
- *file
-}
-
// file is the real representation of *File.
// The extra level of indirection ensures that no clients of os
// can overwrite this data, which could cause the finalizer
@@ -132,7 +132,7 @@ func (f *File) Close() error {
}
func (file *file) close() error {
- if file == nil || file.fd < 0 {
+ if file == nil || file.fd == badFd {
return syscall.EINVAL
}
var err error
@@ -158,69 +158,6 @@ func (file *file) close() error {
return err
}
-// Stat returns the FileInfo structure describing file.
-// If there is an error, it will be of type *PathError.
-func (f *File) Stat() (FileInfo, error) {
- if f == nil {
- return nil, ErrInvalid
- }
- var fs fileStat
- err := syscall.Fstat(f.fd, &fs.sys)
- if err != nil {
- return nil, &PathError{"stat", f.name, err}
- }
- fillFileStatFromSys(&fs, f.name)
- return &fs, nil
-}
-
-// Stat returns a FileInfo describing the named file.
-// If there is an error, it will be of type *PathError.
-func Stat(name string) (FileInfo, error) {
- var fs fileStat
- err := syscall.Stat(name, &fs.sys)
- if err != nil {
- return nil, &PathError{"stat", name, err}
- }
- fillFileStatFromSys(&fs, name)
- return &fs, nil
-}
-
-// Lstat returns a FileInfo describing the named file.
-// If the file is a symbolic link, the returned FileInfo
-// describes the symbolic link. Lstat makes no attempt to follow the link.
-// If there is an error, it will be of type *PathError.
-func Lstat(name string) (FileInfo, error) {
- var fs fileStat
- err := syscall.Lstat(name, &fs.sys)
- if err != nil {
- return nil, &PathError{"lstat", name, err}
- }
- fillFileStatFromSys(&fs, name)
- return &fs, nil
-}
-
-func (f *File) readdir(n int) (fi []FileInfo, err error) {
- dirname := f.name
- if dirname == "" {
- dirname = "."
- }
- names, err := f.Readdirnames(n)
- fi = make([]FileInfo, 0, len(names))
- for _, filename := range names {
- fip, lerr := lstat(dirname + "/" + filename)
- if IsNotExist(lerr) {
- // File disappeared between readdir + stat.
- // Just treat it as if it didn't exist.
- continue
- }
- if lerr != nil {
- return fi, lerr
- }
- fi = append(fi, fip)
- }
- return fi, err
-}
-
// Darwin and FreeBSD can't read or write 2GB+ at a time,
// even on 64-bit systems. See golang.org/issue/7812.
// Use 1GB instead of, say, 2GB-1, to keep subsequent
@@ -335,24 +272,6 @@ func Remove(name string) error {
return &PathError{"remove", name, e}
}
-// basename removes trailing slashes and the leading directory name from path name
-func basename(name string) string {
- i := len(name) - 1
- // Remove trailing slashes
- for ; i > 0 && name[i] == '/'; i-- {
- name = name[:i]
- }
- // Remove leading directory name
- for i--; i >= 0; i-- {
- if name[i] == '/' {
- name = name[i+1:]
- break
- }
- }
-
- return name
-}
-
// TempDir returns the default directory to use for temporary files.
func TempDir() string {
dir := Getenv("TMPDIR")
diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go
index a3885a899c3..10a74c2062a 100644
--- a/libgo/go/os/os_test.go
+++ b/libgo/go/os/os_test.go
@@ -25,8 +25,6 @@ import (
"time"
)
-var supportsSymlinks = true
-
var dot = []string{
"dir.go",
"env.go",
@@ -229,6 +227,28 @@ func TestRead0(t *testing.T) {
}
}
+// Reading a closed file should should return ErrClosed error
+func TestReadClosed(t *testing.T) {
+ path := sfdir + "/" + sfname
+ file, err := Open(path)
+ if err != nil {
+ t.Fatal("open failed:", err)
+ }
+ file.Close() // close immediately
+
+ b := make([]byte, 100)
+ _, err = file.Read(b)
+
+ e, ok := err.(*PathError)
+ if !ok {
+ t.Fatalf("Read: %T(%v), want PathError", e, e)
+ }
+
+ if e.Err != ErrClosed {
+ t.Errorf("Read: %v, want PathError(ErrClosed)", e)
+ }
+}
+
func testReaddirnames(dir string, contents []string, t *testing.T) {
file, err := Open(dir)
if err != nil {
@@ -578,15 +598,8 @@ func TestReaddirOfFile(t *testing.T) {
}
func TestHardLink(t *testing.T) {
- if runtime.GOOS == "plan9" {
- t.Skip("skipping on plan9, hardlinks not supported")
- }
- // From Android release M (Marshmallow), hard linking files is blocked
- // and an attempt to call link() on a file will return EACCES.
- // - https://code.google.com/p/android-developer-preview/issues/detail?id=3150
- if runtime.GOOS == "android" {
- t.Skip("skipping on android, hardlinks not supported")
- }
+ testenv.MustHaveLink(t)
+
defer chtmpdir(t)()
from, to := "hardlinktestfrom", "hardlinktestto"
Remove(from) // Just in case.
@@ -650,14 +663,8 @@ func chtmpdir(t *testing.T) func() {
}
func TestSymlink(t *testing.T) {
- switch runtime.GOOS {
- case "android", "nacl", "plan9":
- t.Skipf("skipping on %s", runtime.GOOS)
- case "windows":
- if !supportsSymlinks {
- t.Skipf("skipping on %s", runtime.GOOS)
- }
- }
+ testenv.MustHaveSymlink(t)
+
defer chtmpdir(t)()
from, to := "symlinktestfrom", "symlinktestto"
Remove(from) // Just in case.
@@ -717,14 +724,8 @@ func TestSymlink(t *testing.T) {
}
func TestLongSymlink(t *testing.T) {
- switch runtime.GOOS {
- case "android", "plan9", "nacl":
- t.Skipf("skipping on %s", runtime.GOOS)
- case "windows":
- if !supportsSymlinks {
- t.Skipf("skipping on %s", runtime.GOOS)
- }
- }
+ testenv.MustHaveSymlink(t)
+
defer chtmpdir(t)()
s := "0123456789abcdef"
// Long, but not too long: a common limit is 255.
@@ -840,6 +841,39 @@ func TestRenameFailed(t *testing.T) {
}
}
+func TestRenameToDirFailed(t *testing.T) {
+ defer chtmpdir(t)()
+ from, to := "renamefrom", "renameto"
+
+ Remove(from)
+ Remove(to)
+ Mkdir(from, 0777)
+ Mkdir(to, 0777)
+ defer Remove(from)
+ defer Remove(to)
+
+ err := Rename(from, to)
+ switch err := err.(type) {
+ case *LinkError:
+ if err.Op != "rename" {
+ t.Errorf("rename %q, %q: err.Op: want %q, got %q", from, to, "rename", err.Op)
+ }
+ if err.Old != from {
+ t.Errorf("rename %q, %q: err.Old: want %q, got %q", from, to, from, err.Old)
+ }
+ if err.New != to {
+ t.Errorf("rename %q, %q: err.New: want %q, got %q", from, to, to, err.New)
+ }
+ case nil:
+ t.Errorf("rename %q, %q: expected error, got nil", from, to)
+
+ // cleanup whatever was placed in "renameto"
+ Remove(to)
+ default:
+ t.Errorf("rename %q, %q: expected %T, got %T %v", from, to, new(LinkError), err, err)
+ }
+}
+
func exec(t *testing.T, dir, cmd string, args []string, expect string) {
r, w, err := Pipe()
if err != nil {
@@ -1028,7 +1062,7 @@ func testChtimes(t *testing.T, name string) {
}
if !pmt.Before(mt) {
- t.Errorf("ModTime didn't go backwards; was=%d, after=%d", mt, pmt)
+ t.Errorf("ModTime didn't go backwards; was=%v, after=%v", mt, pmt)
}
}
@@ -1665,6 +1699,72 @@ func TestReadAtEOF(t *testing.T) {
}
}
+func TestLongPath(t *testing.T) {
+ tmpdir := newDir("TestLongPath", t)
+ defer func(d string) {
+ if err := RemoveAll(d); err != nil {
+ t.Fatalf("RemoveAll failed: %v", err)
+ }
+ }(tmpdir)
+
+ // Test the boundary of 247 and fewer bytes (normal) and 248 and more bytes (adjusted).
+ sizes := []int{247, 248, 249, 400}
+ for len(tmpdir) < 400 {
+ tmpdir += "/dir3456789"
+ }
+ for _, sz := range sizes {
+ t.Run(fmt.Sprintf("length=%d", sz), func(t *testing.T) {
+ sizedTempDir := tmpdir[:sz-1] + "x" // Ensure it does not end with a slash.
+
+ // The various sized runs are for this call to trigger the boundary
+ // condition.
+ if err := MkdirAll(sizedTempDir, 0755); err != nil {
+ t.Fatalf("MkdirAll failed: %v", err)
+ }
+ data := []byte("hello world\n")
+ if err := ioutil.WriteFile(sizedTempDir+"/foo.txt", data, 0644); err != nil {
+ t.Fatalf("ioutil.WriteFile() failed: %v", err)
+ }
+ if err := Rename(sizedTempDir+"/foo.txt", sizedTempDir+"/bar.txt"); err != nil {
+ t.Fatalf("Rename failed: %v", err)
+ }
+ mtime := time.Now().Truncate(time.Minute)
+ if err := Chtimes(sizedTempDir+"/bar.txt", mtime, mtime); err != nil {
+ t.Fatalf("Chtimes failed: %v", err)
+ }
+ names := []string{"bar.txt"}
+ if testenv.HasSymlink() {
+ if err := Symlink(sizedTempDir+"/bar.txt", sizedTempDir+"/symlink.txt"); err != nil {
+ t.Fatalf("Symlink failed: %v", err)
+ }
+ names = append(names, "symlink.txt")
+ }
+ if testenv.HasLink() {
+ if err := Link(sizedTempDir+"/bar.txt", sizedTempDir+"/link.txt"); err != nil {
+ t.Fatalf("Link failed: %v", err)
+ }
+ names = append(names, "link.txt")
+ }
+ for _, wantSize := range []int64{int64(len(data)), 0} {
+ for _, name := range names {
+ path := sizedTempDir + "/" + name
+ dir, err := Stat(path)
+ if err != nil {
+ t.Fatalf("Stat(%q) failed: %v", path, err)
+ }
+ filesize := size(path, t)
+ if dir.Size() != filesize || filesize != wantSize {
+ t.Errorf("Size(%q) is %d, len(ReadFile()) is %d, want %d", path, dir.Size(), filesize, wantSize)
+ }
+ }
+ if err := Truncate(sizedTempDir+"/bar.txt", 0); err != nil {
+ t.Fatalf("Truncate failed: %v", err)
+ }
+ }
+ })
+ }
+}
+
func testKillProcess(t *testing.T, processKiller func(p *Process)) {
testenv.MustHaveExec(t)
diff --git a/libgo/go/os/os_unix_test.go b/libgo/go/os/os_unix_test.go
index 5c10154760c..e239835c6ac 100644
--- a/libgo/go/os/os_unix_test.go
+++ b/libgo/go/os/os_unix_test.go
@@ -7,8 +7,12 @@
package os_test
import (
+ "io"
+ "io/ioutil"
. "os"
+ "path/filepath"
"runtime"
+ "strings"
"syscall"
"testing"
)
@@ -178,3 +182,38 @@ func TestLchown(t *testing.T) {
checkUidGid(t, f.Name(), int(sys.Uid), int(sys.Gid))
}
}
+
+// Issue 16919: Readdir must return a non-empty slice or an error.
+func TestReaddirRemoveRace(t *testing.T) {
+ oldStat := *LstatP
+ defer func() { *LstatP = oldStat }()
+ *LstatP = func(name string) (FileInfo, error) {
+ if strings.HasSuffix(name, "some-file") {
+ // Act like it's been deleted.
+ return nil, ErrNotExist
+ }
+ return oldStat(name)
+ }
+ dir := newDir("TestReaddirRemoveRace", t)
+ defer RemoveAll(dir)
+ if err := ioutil.WriteFile(filepath.Join(dir, "some-file"), []byte("hello"), 0644); err != nil {
+ t.Fatal(err)
+ }
+ d, err := Open(dir)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer d.Close()
+ fis, err := d.Readdir(2) // notably, greater than zero
+ if len(fis) == 0 && err == nil {
+ // This is what used to happen (Issue 16919)
+ t.Fatal("Readdir = empty slice & err == nil")
+ }
+ if len(fis) != 0 || err != io.EOF {
+ t.Errorf("Readdir = %d entries: %v; want 0, io.EOF", len(fis), err)
+ for i, fi := range fis {
+ t.Errorf(" entry[%d]: %q, %v", i, fi.Name(), fi.Mode())
+ }
+ t.FailNow()
+ }
+}
diff --git a/libgo/go/os/path_test.go b/libgo/go/os/path_test.go
index 51dc25bb230..6f5bfa54f8f 100644
--- a/libgo/go/os/path_test.go
+++ b/libgo/go/os/path_test.go
@@ -5,6 +5,7 @@
package os_test
import (
+ "internal/testenv"
"io/ioutil"
. "os"
"path/filepath"
@@ -169,14 +170,7 @@ func TestRemoveAll(t *testing.T) {
}
func TestMkdirAllWithSymlink(t *testing.T) {
- switch runtime.GOOS {
- case "android", "nacl", "plan9":
- t.Skipf("skipping on %s", runtime.GOOS)
- case "windows":
- if !supportsSymlinks {
- t.Skipf("skipping on %s", runtime.GOOS)
- }
- }
+ testenv.MustHaveSymlink(t)
tmpDir, err := ioutil.TempDir("", "TestMkdirAllWithSymlink-")
if err != nil {
diff --git a/libgo/go/os/path_unix.go b/libgo/go/os/path_unix.go
index 36f8e61bf92..ecf098c4612 100644
--- a/libgo/go/os/path_unix.go
+++ b/libgo/go/os/path_unix.go
@@ -15,3 +15,21 @@ const (
func IsPathSeparator(c uint8) bool {
return PathSeparator == c
}
+
+// basename removes trailing slashes and the leading directory name from path name
+func basename(name string) string {
+ i := len(name) - 1
+ // Remove trailing slashes
+ for ; i > 0 && name[i] == '/'; i-- {
+ name = name[:i]
+ }
+ // Remove leading directory name
+ for i--; i >= 0; i-- {
+ if name[i] == '/' {
+ name = name[i+1:]
+ break
+ }
+ }
+
+ return name
+}
diff --git a/libgo/go/os/path_windows.go b/libgo/go/os/path_windows.go
index c96f1376860..101b026dc9e 100644
--- a/libgo/go/os/path_windows.go
+++ b/libgo/go/os/path_windows.go
@@ -14,3 +14,196 @@ func IsPathSeparator(c uint8) bool {
// NOTE: Windows accept / as path separator.
return c == '\\' || c == '/'
}
+
+// basename removes trailing slashes and the leading
+// directory name and drive letter from path name.
+func basename(name string) string {
+ // Remove drive letter
+ if len(name) == 2 && name[1] == ':' {
+ name = "."
+ } else if len(name) > 2 && name[1] == ':' {
+ name = name[2:]
+ }
+ i := len(name) - 1
+ // Remove trailing slashes
+ for ; i > 0 && (name[i] == '/' || name[i] == '\\'); i-- {
+ name = name[:i]
+ }
+ // Remove leading directory name
+ for i--; i >= 0; i-- {
+ if name[i] == '/' || name[i] == '\\' {
+ name = name[i+1:]
+ break
+ }
+ }
+ return name
+}
+
+func isAbs(path string) (b bool) {
+ v := volumeName(path)
+ if v == "" {
+ return false
+ }
+ path = path[len(v):]
+ if path == "" {
+ return false
+ }
+ return IsPathSeparator(path[0])
+}
+
+func volumeName(path string) (v string) {
+ if len(path) < 2 {
+ return ""
+ }
+ // with drive letter
+ c := path[0]
+ if path[1] == ':' &&
+ ('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||
+ 'A' <= c && c <= 'Z') {
+ return path[:2]
+ }
+ // is it UNC
+ if l := len(path); l >= 5 && IsPathSeparator(path[0]) && IsPathSeparator(path[1]) &&
+ !IsPathSeparator(path[2]) && path[2] != '.' {
+ // first, leading `\\` and next shouldn't be `\`. its server name.
+ for n := 3; n < l-1; n++ {
+ // second, next '\' shouldn't be repeated.
+ if IsPathSeparator(path[n]) {
+ n++
+ // third, following something characters. its share name.
+ if !IsPathSeparator(path[n]) {
+ if path[n] == '.' {
+ break
+ }
+ for ; n < l; n++ {
+ if IsPathSeparator(path[n]) {
+ break
+ }
+ }
+ return path[:n]
+ }
+ break
+ }
+ }
+ }
+ return ""
+}
+
+func fromSlash(path string) string {
+ // Replace each '/' with '\\' if present
+ var pathbuf []byte
+ var lastSlash int
+ for i, b := range path {
+ if b == '/' {
+ if pathbuf == nil {
+ pathbuf = make([]byte, len(path))
+ }
+ copy(pathbuf[lastSlash:], path[lastSlash:i])
+ pathbuf[i] = '\\'
+ lastSlash = i + 1
+ }
+ }
+ if pathbuf == nil {
+ return path
+ }
+
+ copy(pathbuf[lastSlash:], path[lastSlash:])
+ return string(pathbuf)
+}
+
+func dirname(path string) string {
+ vol := volumeName(path)
+ i := len(path) - 1
+ for i >= len(vol) && !IsPathSeparator(path[i]) {
+ i--
+ }
+ dir := path[len(vol) : i+1]
+ last := len(dir) - 1
+ if last > 0 && IsPathSeparator(dir[last]) {
+ dir = dir[:last]
+ }
+ if dir == "" {
+ dir = "."
+ }
+ return vol + dir
+}
+
+// fixLongPath returns the extended-length (\\?\-prefixed) form of
+// path when needed, in order to avoid the default 260 character file
+// path limit imposed by Windows. If path is not easily converted to
+// the extended-length form (for example, if path is a relative path
+// or contains .. elements), or is short enough, fixLongPath returns
+// path unmodified.
+//
+// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
+func fixLongPath(path string) string {
+ // Do nothing (and don't allocate) if the path is "short".
+ // Empirically (at least on the Windows Server 2013 builder),
+ // the kernel is arbitrarily okay with < 248 bytes. That
+ // matches what the docs above say:
+ // "When using an API to create a directory, the specified
+ // path cannot be so long that you cannot append an 8.3 file
+ // name (that is, the directory name cannot exceed MAX_PATH
+ // minus 12)." Since MAX_PATH is 260, 260 - 12 = 248.
+ //
+ // The MSDN docs appear to say that a normal path that is 248 bytes long
+ // will work; empirically the path must be less then 248 bytes long.
+ if len(path) < 248 {
+ // Don't fix. (This is how Go 1.7 and earlier worked,
+ // not automatically generating the \\?\ form)
+ return path
+ }
+
+ // The extended form begins with \\?\, as in
+ // \\?\c:\windows\foo.txt or \\?\UNC\server\share\foo.txt.
+ // The extended form disables evaluation of . and .. path
+ // elements and disables the interpretation of / as equivalent
+ // to \. The conversion here rewrites / to \ and elides
+ // . elements as well as trailing or duplicate separators. For
+ // simplicity it avoids the conversion entirely for relative
+ // paths or paths containing .. elements. For now,
+ // \\server\share paths are not converted to
+ // \\?\UNC\server\share paths because the rules for doing so
+ // are less well-specified.
+ if len(path) >= 2 && path[:2] == `\\` {
+ // Don't canonicalize UNC paths.
+ return path
+ }
+ if !isAbs(path) {
+ // Relative path
+ return path
+ }
+
+ const prefix = `\\?`
+
+ pathbuf := make([]byte, len(prefix)+len(path)+len(`\`))
+ copy(pathbuf, prefix)
+ n := len(path)
+ r, w := 0, len(prefix)
+ for r < n {
+ switch {
+ case IsPathSeparator(path[r]):
+ // empty block
+ r++
+ case path[r] == '.' && (r+1 == n || IsPathSeparator(path[r+1])):
+ // /./
+ r++
+ case r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || IsPathSeparator(path[r+2])):
+ // /../ is currently unhandled
+ return path
+ default:
+ pathbuf[w] = '\\'
+ w++
+ for ; r < n && !IsPathSeparator(path[r]); r++ {
+ pathbuf[w] = path[r]
+ w++
+ }
+ }
+ }
+ // A drive's root directory needs a trailing \
+ if w == len(`\\?\c:`) {
+ pathbuf[w] = '\\'
+ w++
+ }
+ return string(pathbuf[:w])
+}
diff --git a/libgo/go/os/path_windows_test.go b/libgo/go/os/path_windows_test.go
new file mode 100644
index 00000000000..cce0bdd522d
--- /dev/null
+++ b/libgo/go/os/path_windows_test.go
@@ -0,0 +1,46 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package os_test
+
+import (
+ "os"
+ "strings"
+ "testing"
+)
+
+func TestFixLongPath(t *testing.T) {
+ // 248 is long enough to trigger the longer-than-248 checks in
+ // fixLongPath, but short enough not to make a path component
+ // longer than 255, which is illegal on Windows. (which
+ // doesn't really matter anyway, since this is purely a string
+ // function we're testing, and it's not actually being used to
+ // do a system call)
+ veryLong := "l" + strings.Repeat("o", 248) + "ng"
+ for _, test := range []struct{ in, want string }{
+ // Short; unchanged:
+ {`C:\short.txt`, `C:\short.txt`},
+ {`C:\`, `C:\`},
+ {`C:`, `C:`},
+ // The "long" substring is replaced by a looooooong
+ // string which triggers the rewriting. Except in the
+ // cases below where it doesn't.
+ {`C:\long\foo.txt`, `\\?\C:\long\foo.txt`},
+ {`C:/long/foo.txt`, `\\?\C:\long\foo.txt`},
+ {`C:\long\foo\\bar\.\baz\\`, `\\?\C:\long\foo\bar\baz`},
+ {`\\unc\path`, `\\unc\path`},
+ {`long.txt`, `long.txt`},
+ {`C:long.txt`, `C:long.txt`},
+ {`c:\long\..\bar\baz`, `c:\long\..\bar\baz`},
+ {`\\?\c:\long\foo.txt`, `\\?\c:\long\foo.txt`},
+ {`\\?\c:\long/foo.txt`, `\\?\c:\long/foo.txt`},
+ } {
+ in := strings.Replace(test.in, "long", veryLong, -1)
+ want := strings.Replace(test.want, "long", veryLong, -1)
+ if got := os.FixLongPath(in); got != want {
+ got = strings.Replace(got, veryLong, "long", -1)
+ t.Errorf("fixLongPath(%q) = %q; want %q", test.in, got, test.want)
+ }
+ }
+}
diff --git a/libgo/go/os/stat_plan9.go b/libgo/go/os/stat_plan9.go
index 96f056c1117..274d0d86f34 100644
--- a/libgo/go/os/stat_plan9.go
+++ b/libgo/go/os/stat_plan9.go
@@ -11,12 +11,6 @@ import (
const _BIT16SZ = 2
-func sameFile(fs1, fs2 *fileStat) bool {
- a := fs1.sys.(*syscall.Dir)
- b := fs2.sys.(*syscall.Dir)
- return a.Qid.Path == b.Qid.Path && a.Type == b.Type && a.Dev == b.Dev
-}
-
func fileInfoFromStat(d *syscall.Dir) FileInfo {
fs := &fileStat{
name: d.Name,
@@ -37,6 +31,10 @@ func fileInfoFromStat(d *syscall.Dir) FileInfo {
if d.Mode&syscall.DMTMP != 0 {
fs.mode |= ModeTemporary
}
+ // Consider all files not served by #M as device files.
+ if d.Type != 'M' {
+ fs.mode |= ModeDevice
+ }
return fs
}
diff --git a/libgo/go/os/stat_unix.go b/libgo/go/os/stat_unix.go
new file mode 100644
index 00000000000..1733d3f1327
--- /dev/null
+++ b/libgo/go/os/stat_unix.go
@@ -0,0 +1,52 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package os
+
+import (
+ "syscall"
+)
+
+// Stat returns the FileInfo structure describing file.
+// If there is an error, it will be of type *PathError.
+func (f *File) Stat() (FileInfo, error) {
+ if f == nil {
+ return nil, ErrInvalid
+ }
+ var fs fileStat
+ err := syscall.Fstat(f.fd, &fs.sys)
+ if err != nil {
+ return nil, &PathError{"stat", f.name, err}
+ }
+ fillFileStatFromSys(&fs, f.name)
+ return &fs, nil
+}
+
+// Stat returns a FileInfo describing the named file.
+// If there is an error, it will be of type *PathError.
+func Stat(name string) (FileInfo, error) {
+ var fs fileStat
+ err := syscall.Stat(name, &fs.sys)
+ if err != nil {
+ return nil, &PathError{"stat", name, err}
+ }
+ fillFileStatFromSys(&fs, name)
+ return &fs, nil
+}
+
+// Lstat returns a FileInfo describing the named file.
+// If the file is a symbolic link, the returned FileInfo
+// describes the symbolic link. Lstat makes no attempt to follow the link.
+// If there is an error, it will be of type *PathError.
+func Lstat(name string) (FileInfo, error) {
+ var fs fileStat
+ err := syscall.Lstat(name, &fs.sys)
+ if err != nil {
+ return nil, &PathError{"lstat", name, err}
+ }
+ fillFileStatFromSys(&fs, name)
+ return &fs, nil
+}
diff --git a/libgo/go/os/sys.go b/libgo/go/os/sys.go
new file mode 100644
index 00000000000..28b0f6bab02
--- /dev/null
+++ b/libgo/go/os/sys.go
@@ -0,0 +1,10 @@
+// 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 os
+
+// Hostname returns the host name reported by the kernel.
+func Hostname() (name string, err error) {
+ return hostname()
+}
diff --git a/libgo/go/os/types.go b/libgo/go/os/types.go
index 12b593fa1eb..c56548353f1 100644
--- a/libgo/go/os/types.go
+++ b/libgo/go/os/types.go
@@ -12,6 +12,11 @@ import (
// Getpagesize returns the underlying system's memory page size.
func Getpagesize() int { return syscall.Getpagesize() }
+// File represents an open file descriptor.
+type File struct {
+ *file // os specific
+}
+
// A FileInfo describes a file and is returned by Stat and Lstat.
type FileInfo interface {
Name() string // base name of the file
diff --git a/libgo/go/os/types_plan9.go b/libgo/go/os/types_plan9.go
index 6d46ca9dd3d..125da661b79 100644
--- a/libgo/go/os/types_plan9.go
+++ b/libgo/go/os/types_plan9.go
@@ -4,7 +4,10 @@
package os
-import "time"
+import (
+ "syscall"
+ "time"
+)
// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
type fileStat struct {
@@ -19,3 +22,11 @@ func (fs *fileStat) Size() int64 { return fs.size }
func (fs *fileStat) Mode() FileMode { return fs.mode }
func (fs *fileStat) ModTime() time.Time { return fs.modTime }
func (fs *fileStat) Sys() interface{} { return fs.sys }
+
+func sameFile(fs1, fs2 *fileStat) bool {
+ a := fs1.sys.(*syscall.Dir)
+ b := fs2.sys.(*syscall.Dir)
+ return a.Qid.Path == b.Qid.Path && a.Type == b.Type && a.Dev == b.Dev
+}
+
+const badFd = -1
diff --git a/libgo/go/os/types_unix.go b/libgo/go/os/types_unix.go
index 056220c09b6..1f614812fdd 100644
--- a/libgo/go/os/types_unix.go
+++ b/libgo/go/os/types_unix.go
@@ -25,3 +25,9 @@ func (fs *fileStat) Size() int64 { return fs.size }
func (fs *fileStat) Mode() FileMode { return fs.mode }
func (fs *fileStat) ModTime() time.Time { return fs.modTime }
func (fs *fileStat) Sys() interface{} { return &fs.sys }
+
+func sameFile(fs1, fs2 *fileStat) bool {
+ return fs1.sys.Dev == fs2.sys.Dev && fs1.sys.Ino == fs2.sys.Ino
+}
+
+const badFd = -1
diff --git a/libgo/go/os/user/user.go b/libgo/go/os/user/user.go
index 7b44397afb3..ad61992ad31 100644
--- a/libgo/go/os/user/user.go
+++ b/libgo/go/os/user/user.go
@@ -15,31 +15,39 @@ var (
)
// User represents a user account.
-//
-// On POSIX systems Uid and Gid contain a decimal number
-// representing uid and gid. On windows Uid and Gid
-// contain security identifier (SID) in a string format.
-// On Plan 9, Uid, Gid, Username, and Name will be the
-// contents of /dev/user.
type User struct {
- Uid string // user ID
- Gid string // primary group ID
+ // Uid is the user ID.
+ // On POSIX systems, this is a decimal number representing the uid.
+ // On Windows, this is a security identifier (SID) in a string format.
+ // On Plan 9, this is the contents of /dev/user.
+ Uid string
+ // Gid is the primary group ID.
+ // On POSIX systems, this is a decimal number representing the gid.
+ // On Windows, this is a SID in a string format.
+ // On Plan 9, this is the contents of /dev/user.
+ Gid string
+ // Username is the login name.
Username string
- Name string
- HomeDir string
+ // Name is the user's real or display name.
+ // It might be blank.
+ // On POSIX systems, this is the first (or only) entry in the GECOS field
+ // list.
+ // On Windows, this is the user's display name.
+ // On Plan 9, this is the contents of /dev/user.
+ Name string
+ // HomeDir is the path to the user's home directory (if they have one).
+ HomeDir string
}
// Group represents a grouping of users.
//
-// On POSIX systems Gid contains a decimal number
-// representing the group ID.
+// On POSIX systems Gid contains a decimal number representing the group ID.
type Group struct {
Gid string // group ID
Name string // group name
}
-// UnknownUserIdError is returned by LookupId when
-// a user cannot be found.
+// UnknownUserIdError is returned by LookupId when a user cannot be found.
type UnknownUserIdError int
func (e UnknownUserIdError) Error() string {
diff --git a/libgo/go/os/wait_wait6.go b/libgo/go/os/wait_wait6.go
index 7f4780ae2d0..b30981199e1 100644
--- a/libgo/go/os/wait_wait6.go
+++ b/libgo/go/os/wait_wait6.go
@@ -28,6 +28,7 @@ func (p *Process) blockUntilWaitable() (bool, error) {
} else {
_, _, errno = syscall.Syscall6(syscall.SYS_WAIT6, _P_PID, uintptr(p.Pid), 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0)
}
+ runtime.KeepAlive(p)
if errno != 0 {
// The wait6 system call is supported only on FreeBSD
// 9.3 and above, so it may return an ENOSYS error.
diff --git a/libgo/go/os/wait_waitid.go b/libgo/go/os/wait_waitid.go
index 74b7494c0de..653fce92532 100644
--- a/libgo/go/os/wait_waitid.go
+++ b/libgo/go/os/wait_waitid.go
@@ -26,7 +26,7 @@ func (p *Process) blockUntilWaitable() (bool, error) {
var siginfo [128]byte
psig := &siginfo[0]
_, _, e := syscall.Syscall6(syscall.SYS_WAITID, _P_PID, uintptr(p.Pid), uintptr(unsafe.Pointer(psig)), syscall.WEXITED|syscall.WNOWAIT, 0, 0)
- runtime.KeepAlive(psig)
+ runtime.KeepAlive(p)
if e != 0 {
// waitid has been available since Linux 2.6.9, but
// reportedly is not available in Ubuntu on Windows.
diff --git a/libgo/go/path/filepath/match.go b/libgo/go/path/filepath/match.go
index 9fa68f578d0..5168e037b53 100644
--- a/libgo/go/path/filepath/match.go
+++ b/libgo/go/path/filepath/match.go
@@ -240,13 +240,14 @@ func Glob(pattern string) (matches []string, err error) {
}
dir, file := Split(pattern)
+ volumeLen := 0
if runtime.GOOS == "windows" {
- dir = cleanGlobPathWindows(dir)
+ volumeLen, dir = cleanGlobPathWindows(dir)
} else {
dir = cleanGlobPath(dir)
}
- if !hasMeta(dir) {
+ if !hasMeta(dir[volumeLen:]) {
return glob(dir, file, nil)
}
@@ -283,18 +284,21 @@ func cleanGlobPath(path string) string {
}
// cleanGlobPathWindows is windows version of cleanGlobPath.
-func cleanGlobPathWindows(path string) string {
+func cleanGlobPathWindows(path string) (prefixLen int, cleaned string) {
vollen := volumeNameLen(path)
switch {
case path == "":
- return "."
+ return 0, "."
case vollen+1 == len(path) && os.IsPathSeparator(path[len(path)-1]): // /, \, C:\ and C:/
// do nothing to the path
- return path
+ return vollen + 1, path
case vollen == len(path) && len(path) == 2: // C:
- return path + "." // convert C: into C:.
+ return vollen, path + "." // convert C: into C:.
default:
- return path[0 : len(path)-1] // chop off trailing separator
+ if vollen >= len(path) {
+ vollen = len(path) - 1
+ }
+ return vollen, path[0 : len(path)-1] // chop off trailing separator
}
}
diff --git a/libgo/go/path/filepath/match_test.go b/libgo/go/path/filepath/match_test.go
index 102eb1ce092..ae7ca1c228f 100644
--- a/libgo/go/path/filepath/match_test.go
+++ b/libgo/go/path/filepath/match_test.go
@@ -6,6 +6,7 @@ package filepath_test
import (
"fmt"
+ "internal/testenv"
"io/ioutil"
"os"
. "path/filepath"
@@ -175,15 +176,7 @@ var globSymlinkTests = []struct {
}
func TestGlobSymlink(t *testing.T) {
- switch runtime.GOOS {
- case "android", "nacl", "plan9":
- t.Skipf("skipping on %s", runtime.GOOS)
- case "windows":
- if !supportsSymlinks {
- t.Skipf("skipping on %s", runtime.GOOS)
- }
-
- }
+ testenv.MustHaveSymlink(t)
tmpDir, err := ioutil.TempDir("", "globsymlink")
if err != nil {
diff --git a/libgo/go/path/filepath/path.go b/libgo/go/path/filepath/path.go
index 0dc559cdd67..1d8e35c969e 100644
--- a/libgo/go/path/filepath/path.go
+++ b/libgo/go/path/filepath/path.go
@@ -177,7 +177,7 @@ func FromSlash(path string) string {
// SplitList splits a list of paths joined by the OS-specific ListSeparator,
// usually found in PATH or GOPATH environment variables.
// Unlike strings.Split, SplitList returns an empty slice when passed an empty
-// string. SplitList does not replace slash characters in the returned paths.
+// string.
func SplitList(path string) []string {
return splitList(path)
}
@@ -393,9 +393,14 @@ func walk(path string, info os.FileInfo, walkFn WalkFunc) error {
func Walk(root string, walkFn WalkFunc) error {
info, err := os.Lstat(root)
if err != nil {
- return walkFn(root, nil, err)
+ err = walkFn(root, nil, err)
+ } else {
+ err = walk(root, info, walkFn)
}
- return walk(root, info, walkFn)
+ if err == SkipDir {
+ return nil
+ }
+ return err
}
// readDirNames reads the directory named by dirname and returns
diff --git a/libgo/go/path/filepath/path_plan9.go b/libgo/go/path/filepath/path_plan9.go
index 60d46d9d421..ec792fc831a 100644
--- a/libgo/go/path/filepath/path_plan9.go
+++ b/libgo/go/path/filepath/path_plan9.go
@@ -18,6 +18,9 @@ func volumeNameLen(path string) int {
}
// HasPrefix exists for historical compatibility and should not be used.
+//
+// Deprecated: HasPrefix does not respect path boundaries and
+// does not ignore case when required.
func HasPrefix(p, prefix string) bool {
return strings.HasPrefix(p, prefix)
}
diff --git a/libgo/go/path/filepath/path_test.go b/libgo/go/path/filepath/path_test.go
index 9c3f287ecbd..7389ea29a48 100644
--- a/libgo/go/path/filepath/path_test.go
+++ b/libgo/go/path/filepath/path_test.go
@@ -6,6 +6,7 @@ package filepath_test
import (
"errors"
+ "internal/testenv"
"io/ioutil"
"os"
"path/filepath"
@@ -15,8 +16,6 @@ import (
"testing"
)
-var supportsSymlinks = true
-
type PathTest struct {
path, result string
}
@@ -532,7 +531,7 @@ func TestWalkSkipDirOnFile(t *testing.T) {
touch(t, filepath.Join(td, "dir/foo2"))
sawFoo2 := false
- filepath.Walk(td, func(path string, info os.FileInfo, err error) error {
+ walker := func(path string, info os.FileInfo, err error) error {
if strings.HasSuffix(path, "foo2") {
sawFoo2 = true
}
@@ -540,8 +539,20 @@ func TestWalkSkipDirOnFile(t *testing.T) {
return filepath.SkipDir
}
return nil
- })
+ }
+
+ err = filepath.Walk(td, walker)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if sawFoo2 {
+ t.Errorf("SkipDir on file foo1 did not block processing of foo2")
+ }
+ err = filepath.Walk(filepath.Join(td, "dir"), walker)
+ if err != nil {
+ t.Fatal(err)
+ }
if sawFoo2 {
t.Errorf("SkipDir on file foo1 did not block processing of foo2")
}
@@ -779,13 +790,7 @@ func simpleJoin(dir, path string) string {
}
func TestEvalSymlinks(t *testing.T) {
- switch runtime.GOOS {
- case "android", "nacl", "plan9":
- t.Skipf("skipping on %s", runtime.GOOS)
- }
- if !supportsSymlinks {
- t.Skip("skipping because symlinks are not supported")
- }
+ testenv.MustHaveSymlink(t)
tmpDir, err := ioutil.TempDir("", "evalsymlink")
if err != nil {
@@ -875,6 +880,40 @@ func TestEvalSymlinks(t *testing.T) {
t.Errorf(`EvalSymlinks(".") in %q directory returns %q, want "." or %q`, d.path, p, want)
}()
+ // test EvalSymlinks("C:.") on Windows
+ if runtime.GOOS == "windows" {
+ func() {
+ defer func() {
+ err := os.Chdir(wd)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }()
+
+ err := os.Chdir(path)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ volDot := filepath.VolumeName(tmpDir) + "."
+
+ p, err := filepath.EvalSymlinks(volDot)
+ if err != nil {
+ t.Errorf(`EvalSymlinks("%s") in %q directory error: %v`, volDot, d.path, err)
+ return
+ }
+ if p == volDot {
+ return
+ }
+ want := filepath.Clean(findEvalSymlinksTestDirsDest(t, testdirs, d.path))
+ if p == want {
+ return
+ }
+ t.Errorf(`EvalSymlinks("%s") in %q directory returns %q, want %q or %q`, volDot, d.path, p, volDot, want)
+ }()
+ }
+
// test EvalSymlinks(".."+path)
func() {
defer func() {
@@ -926,14 +965,30 @@ func TestEvalSymlinks(t *testing.T) {
}
}
-func TestIssue13582(t *testing.T) {
- switch runtime.GOOS {
- case "android", "nacl", "plan9":
- t.Skipf("skipping on %s", runtime.GOOS)
+func TestEvalSymlinksIsNotExist(t *testing.T) {
+ testenv.MustHaveSymlink(t)
+
+ defer chtmpdir(t)()
+
+ _, err := filepath.EvalSymlinks("notexist")
+ if !os.IsNotExist(err) {
+ t.Errorf("expected the file is not found, got %v\n", err)
+ }
+
+ err = os.Symlink("notexist", "link")
+ if err != nil {
+ t.Fatal(err)
}
- if !supportsSymlinks {
- t.Skip("skipping because symlinks are not supported")
+ defer os.Remove("link")
+
+ _, err = filepath.EvalSymlinks("link")
+ if !os.IsNotExist(err) {
+ t.Errorf("expected the file is not found, got %v\n", err)
}
+}
+
+func TestIssue13582(t *testing.T) {
+ testenv.MustHaveSymlink(t)
tmpDir, err := ioutil.TempDir("", "issue13582")
if err != nil {
@@ -1009,13 +1064,16 @@ var absTestDirs = []string{
var absTests = []string{
".",
"b",
+ "b/",
"../a",
"../a/b",
"../a/b/./c/../../.././a",
+ "../a/b/./c/../../.././a/",
"$",
"$/.",
"$/a/../a/b",
"$/a/b/c/../../.././a",
+ "$/a/b/c/../../.././a/",
}
func TestAbs(t *testing.T) {
@@ -1080,7 +1138,7 @@ func TestAbs(t *testing.T) {
if !filepath.IsAbs(abspath) {
t.Errorf("Abs(%q)=%q, not an absolute path", path, abspath)
}
- if filepath.IsAbs(path) && abspath != filepath.Clean(path) {
+ if filepath.IsAbs(abspath) && abspath != filepath.Clean(abspath) {
t.Errorf("Abs(%q)=%q, isn't clean", path, abspath)
}
}
@@ -1244,11 +1302,11 @@ func TestBug3486(t *testing.T) { // https://golang.org/issue/3486
if err != nil {
t.Fatal(err)
}
- bugs := filepath.Join(root, "bugs")
+ bugs := filepath.Join(root, "fixedbugs")
ken := filepath.Join(root, "ken")
seenBugs := false
seenKen := false
- filepath.Walk(root, func(pth string, info os.FileInfo, err error) error {
+ err = filepath.Walk(root, func(pth string, info os.FileInfo, err error) error {
if err != nil {
t.Fatal(err)
}
@@ -1259,12 +1317,15 @@ func TestBug3486(t *testing.T) { // https://golang.org/issue/3486
return filepath.SkipDir
case ken:
if !seenBugs {
- t.Fatal("filepath.Walk out of order - ken before bugs")
+ t.Fatal("filepath.Walk out of order - ken before fixedbugs")
}
seenKen = true
}
return nil
})
+ if err != nil {
+ t.Fatal(err)
+ }
if !seenKen {
t.Fatalf("%q not seen", ken)
}
diff --git a/libgo/go/path/filepath/path_unix.go b/libgo/go/path/filepath/path_unix.go
index 2d242cc0b5d..d77ff24cdc3 100644
--- a/libgo/go/path/filepath/path_unix.go
+++ b/libgo/go/path/filepath/path_unix.go
@@ -20,6 +20,9 @@ func volumeNameLen(path string) int {
}
// HasPrefix exists for historical compatibility and should not be used.
+//
+// Deprecated: HasPrefix does not respect path boundaries and
+// does not ignore case when required.
func HasPrefix(p, prefix string) bool {
return strings.HasPrefix(p, prefix)
}
diff --git a/libgo/go/path/filepath/path_windows.go b/libgo/go/path/filepath/path_windows.go
index 41c57df7386..0d8b62015c5 100644
--- a/libgo/go/path/filepath/path_windows.go
+++ b/libgo/go/path/filepath/path_windows.go
@@ -37,7 +37,7 @@ func volumeNameLen(path string) int {
if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
return 2
}
- // is it UNC
+ // is it UNC? https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) &&
!isSlash(path[2]) && path[2] != '.' {
// first, leading `\\` and next shouldn't be `\`. its server name.
@@ -65,6 +65,9 @@ func volumeNameLen(path string) int {
}
// HasPrefix exists for historical compatibility and should not be used.
+//
+// Deprecated: HasPrefix does not respect path boundaries and
+// does not ignore case when required.
func HasPrefix(p, prefix string) bool {
if strings.HasPrefix(p, prefix) {
return true
@@ -106,7 +109,11 @@ func splitList(path string) []string {
}
func abs(path string) (string, error) {
- return syscall.FullPath(path)
+ fullPath, err := syscall.FullPath(path)
+ if err != nil {
+ return "", err
+ }
+ return Clean(fullPath), nil
}
func join(elem []string) string {
diff --git a/libgo/go/path/filepath/symlink.go b/libgo/go/path/filepath/symlink.go
index f627a94ddb9..824aee4e490 100644
--- a/libgo/go/path/filepath/symlink.go
+++ b/libgo/go/path/filepath/symlink.go
@@ -105,8 +105,9 @@ func walkSymlinks(path string) (string, error) {
// directory is a symlink. Stop the walk, if symlink
// target is not absolute path, and return "."
// to the caller (just like unix does).
- if path == "." && !IsAbs(newpath) {
- return ".", nil
+ // Same for "C:.".
+ if path[volumeNameLen(path):] == "." && !IsAbs(newpath) {
+ return path, nil
}
}
if i == linksWalked {
diff --git a/libgo/go/path/filepath/symlink_windows.go b/libgo/go/path/filepath/symlink_windows.go
index bb05aabc924..f771fe3a8a3 100644
--- a/libgo/go/path/filepath/symlink_windows.go
+++ b/libgo/go/path/filepath/symlink_windows.go
@@ -47,7 +47,7 @@ func baseIsDotDot(path string) bool {
return path[i+1:] == ".."
}
-// toNorm returns the normalized path that is guranteed to be unique.
+// toNorm returns the normalized path that is guaranteed to be unique.
// It should accept the following formats:
// * UNC paths (e.g \\server\share\foo\bar)
// * absolute paths (e.g C:\foo\bar)
diff --git a/libgo/go/path/path.go b/libgo/go/path/path.go
index c1d4d8aced3..76c7814c59d 100644
--- a/libgo/go/path/path.go
+++ b/libgo/go/path/path.go
@@ -4,6 +4,8 @@
// Package path implements utility routines for manipulating slash-separated
// paths.
+//
+// To manipulate operating system paths, use the path/filepath package.
package path
import (
diff --git a/libgo/go/plugin/plugin.go b/libgo/go/plugin/plugin.go
new file mode 100644
index 00000000000..b86099a4f6f
--- /dev/null
+++ b/libgo/go/plugin/plugin.go
@@ -0,0 +1,73 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package plugin implements loading and symbol resolution of Go plugins.
+//
+// Currently plugins only work on Linux.
+//
+// A plugin is a Go main package with exported functions and variables that
+// has been built with:
+//
+// go build -buildmode=plugin
+//
+// When a plugin is first opened, the init functions of all packages not
+// already part of the program are called. The main function is not run.
+// A plugin is only initialized once, and cannot be closed.
+package plugin
+
+// Plugin is a loaded Go plugin.
+type Plugin struct {
+ pluginpath string
+ loaded chan struct{} // closed when loaded
+ syms map[string]interface{}
+}
+
+// Open opens a Go plugin.
+// If a path has already been opened, then the existing *Plugin is returned.
+// It is safe for concurrent use by multiple goroutines.
+func Open(path string) (*Plugin, error) {
+ return open(path)
+}
+
+// Lookup searches for a symbol named symName in plugin p.
+// A symbol is any exported variable or function.
+// It reports an error if the symbol is not found.
+// It is safe for concurrent use by multiple goroutines.
+func (p *Plugin) Lookup(symName string) (Symbol, error) {
+ return lookup(p, symName)
+}
+
+// A Symbol is a pointer to a variable or function.
+//
+// For example, a plugin defined as
+//
+// package main
+//
+// // // No C code needed.
+// import "C"
+//
+// import "fmt"
+//
+// var V int
+//
+// func F() { fmt.Printf("Hello, number %d\n", V) }
+//
+// may be loaded with the Open function and then the exported package
+// symbols V and F can be accessed
+//
+// p, err := plugin.Open("plugin_name.so")
+// if err != nil {
+// panic(err)
+// }
+// v, err := p.Lookup("V")
+// if err != nil {
+// panic(err)
+// }
+// f, err := p.Lookup("F")
+// if err != nil {
+// panic(err)
+// }
+// *v.(*int) = 7
+// f.(func())() // prints "Hello, number 7"
+type Symbol interface{}
diff --git a/libgo/go/plugin/plugin_dlopen.go b/libgo/go/plugin/plugin_dlopen.go
new file mode 100644
index 00000000000..c5b0a4721c5
--- /dev/null
+++ b/libgo/go/plugin/plugin_dlopen.go
@@ -0,0 +1,138 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux,cgo darwin,cgo
+
+package plugin
+
+/*
+#cgo linux LDFLAGS: -ldl
+#include <dlfcn.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <stdio.h>
+
+static uintptr_t pluginOpen(const char* path, char** err) {
+ void* h = dlopen(path, RTLD_NOW|RTLD_GLOBAL);
+ if (h == NULL) {
+ *err = (char*)dlerror();
+ }
+ return (uintptr_t)h;
+}
+
+static void* pluginLookup(uintptr_t h, const char* name, char** err) {
+ void* r = dlsym((void*)h, name);
+ if (r == NULL) {
+ *err = (char*)dlerror();
+ }
+ return r;
+}
+*/
+import "C"
+
+import (
+ "errors"
+ "sync"
+ "unsafe"
+)
+
+func open(name string) (*Plugin, error) {
+ cPath := (*C.char)(C.malloc(C.PATH_MAX + 1))
+ defer C.free(unsafe.Pointer(cPath))
+
+ cRelName := C.CString(name)
+ defer C.free(unsafe.Pointer(cRelName))
+ if C.realpath(cRelName, cPath) == nil {
+ return nil, errors.New("plugin.Open(" + name + "): realpath failed")
+ }
+
+ filepath := C.GoString(cPath)
+
+ pluginsMu.Lock()
+ if p := plugins[filepath]; p != nil {
+ pluginsMu.Unlock()
+ <-p.loaded
+ return p, nil
+ }
+ var cErr *C.char
+ h := C.pluginOpen(cPath, &cErr)
+ if h == 0 {
+ pluginsMu.Unlock()
+ return nil, errors.New("plugin.Open: " + C.GoString(cErr))
+ }
+ // TODO(crawshaw): look for plugin note, confirm it is a Go plugin
+ // and it was built with the correct toolchain.
+ if len(name) > 3 && name[len(name)-3:] == ".so" {
+ name = name[:len(name)-3]
+ }
+
+ pluginpath, syms, mismatchpkg := lastmoduleinit()
+ if mismatchpkg != "" {
+ pluginsMu.Unlock()
+ return nil, errors.New("plugin.Open: plugin was built with a different version of package " + mismatchpkg)
+ }
+ if plugins == nil {
+ plugins = make(map[string]*Plugin)
+ }
+ // This function can be called from the init function of a plugin.
+ // Drop a placeholder in the map so subsequent opens can wait on it.
+ p := &Plugin{
+ pluginpath: pluginpath,
+ loaded: make(chan struct{}),
+ syms: syms,
+ }
+ plugins[filepath] = p
+ pluginsMu.Unlock()
+
+ initStr := C.CString(pluginpath + ".init")
+ initFuncPC := C.pluginLookup(h, initStr, &cErr)
+ C.free(unsafe.Pointer(initStr))
+ if initFuncPC != nil {
+ initFuncP := &initFuncPC
+ initFunc := *(*func())(unsafe.Pointer(&initFuncP))
+ initFunc()
+ }
+
+ // Fill out the value of each plugin symbol.
+ for symName, sym := range syms {
+ isFunc := symName[0] == '.'
+ if isFunc {
+ delete(syms, symName)
+ symName = symName[1:]
+ }
+
+ cname := C.CString(pluginpath + "." + symName)
+ p := C.pluginLookup(h, cname, &cErr)
+ C.free(unsafe.Pointer(cname))
+ if p == nil {
+ return nil, errors.New("plugin.Open: could not find symbol " + symName + ": " + C.GoString(cErr))
+ }
+ valp := (*[2]unsafe.Pointer)(unsafe.Pointer(&sym))
+ if isFunc {
+ (*valp)[1] = unsafe.Pointer(&p)
+ } else {
+ (*valp)[1] = p
+ }
+ syms[symName] = sym
+ }
+ close(p.loaded)
+ return p, nil
+}
+
+func lookup(p *Plugin, symName string) (Symbol, error) {
+ if s := p.syms[symName]; s != nil {
+ return s, nil
+ }
+ return nil, errors.New("plugin: symbol " + symName + " not found in plugin " + p.pluginpath)
+}
+
+var (
+ pluginsMu sync.Mutex
+ plugins map[string]*Plugin
+)
+
+// lastmoduleinit is defined in package runtime
+func lastmoduleinit() (pluginpath string, syms map[string]interface{}, mismatchpkg string)
diff --git a/libgo/go/plugin/plugin_stubs.go b/libgo/go/plugin/plugin_stubs.go
new file mode 100644
index 00000000000..f0bcb4a3bdf
--- /dev/null
+++ b/libgo/go/plugin/plugin_stubs.go
@@ -0,0 +1,17 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !linux,!darwin !cgo
+
+package plugin
+
+import "errors"
+
+func lookup(p *Plugin, symName string) (interface{}, error) {
+ return nil, errors.New("plugin: not implemented")
+}
+
+func open(name string) (*Plugin, error) {
+ return nil, errors.New("plugin: not implemented")
+}
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index e601c2cbde2..f51e95fd734 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -648,6 +648,20 @@ var (
type self struct{}
+type Loop *Loop
+type Loopy interface{}
+
+var loop1, loop2 Loop
+var loopy1, loopy2 Loopy
+
+func init() {
+ loop1 = &loop2
+ loop2 = &loop1
+
+ loopy1 = &loopy2
+ loopy2 = &loopy1
+}
+
var deepEqualTests = []DeepEqualTest{
// Equalities
{nil, nil, true},
@@ -706,6 +720,12 @@ var deepEqualTests = []DeepEqualTest{
{&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false},
{Basic{1, 0.5}, NotBasic{1, 0.5}, false},
{map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false},
+
+ // Possible loops.
+ {&loop1, &loop1, true},
+ {&loop1, &loop2, true},
+ {&loopy1, &loopy1, true},
+ {&loopy1, &loopy2, true},
}
func TestDeepEqual(t *testing.T) {
@@ -1535,6 +1555,34 @@ func BenchmarkCall(b *testing.B) {
})
}
+func BenchmarkCallArgCopy(b *testing.B) {
+ byteArray := func(n int) Value {
+ return Zero(ArrayOf(n, TypeOf(byte(0))))
+ }
+ sizes := [...]struct {
+ fv Value
+ arg Value
+ }{
+ {ValueOf(func(a [128]byte) {}), byteArray(128)},
+ {ValueOf(func(a [256]byte) {}), byteArray(256)},
+ {ValueOf(func(a [1024]byte) {}), byteArray(1024)},
+ {ValueOf(func(a [4096]byte) {}), byteArray(4096)},
+ {ValueOf(func(a [65536]byte) {}), byteArray(65536)},
+ }
+ for _, size := range sizes {
+ bench := func(b *testing.B) {
+ args := []Value{size.arg}
+ b.SetBytes(int64(size.arg.Len()))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ size.fv.Call(args)
+ }
+ }
+ name := fmt.Sprintf("size=%v", size.arg.Len())
+ b.Run(name, bench)
+ }
+}
+
func TestMakeFunc(t *testing.T) {
f := dummy
fv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in })
@@ -2277,25 +2325,39 @@ func TestFieldPkgPath(t *testing.T) {
unexported string
OtherPkgFields
}{})
- for _, test := range []struct {
+
+ type pkgpathTest struct {
index []int
pkgPath string
anonymous bool
- }{
+ }
+
+ checkPkgPath := func(name string, s []pkgpathTest) {
+ for _, test := range s {
+ f := typ.FieldByIndex(test.index)
+ if got, want := f.PkgPath, test.pkgPath; got != want {
+ t.Errorf("%s: Field(%d).PkgPath = %q, want %q", name, test.index, got, want)
+ }
+ if got, want := f.Anonymous, test.anonymous; got != want {
+ t.Errorf("%s: Field(%d).Anonymous = %v, want %v", name, test.index, got, want)
+ }
+ }
+ }
+
+ checkPkgPath("testStruct", []pkgpathTest{
{[]int{0}, "", false}, // Exported
{[]int{1}, "reflect_test", false}, // unexported
{[]int{2}, "", true}, // OtherPkgFields
{[]int{2, 0}, "", false}, // OtherExported
{[]int{2, 1}, "reflect", false}, // otherUnexported
- } {
- f := typ.FieldByIndex(test.index)
- if got, want := f.PkgPath, test.pkgPath; got != want {
- t.Errorf("Field(%d).PkgPath = %q, want %q", test.index, got, want)
- }
- if got, want := f.Anonymous, test.anonymous; got != want {
- t.Errorf("Field(%d).Anonymous = %v, want %v", test.index, got, want)
- }
- }
+ })
+
+ type localOtherPkgFields OtherPkgFields
+ typ = TypeOf(localOtherPkgFields{})
+ checkPkgPath("localOtherPkgFields", []pkgpathTest{
+ {[]int{0}, "", false}, // OtherExported
+ {[]int{1}, "reflect", false}, // otherUnexported
+ })
}
func TestVariadicType(t *testing.T) {
@@ -3077,6 +3139,9 @@ func ReadWriterV(x io.ReadWriter) Value {
}
type Empty struct{}
+type MyStruct struct {
+ x int `some:"tag"`
+}
type MyString string
type MyBytes []byte
type MyRunes []int32
@@ -3388,6 +3453,35 @@ var convertTests = []struct {
{V((func())(nil)), V(MyFunc(nil))},
{V((MyFunc)(nil)), V((func())(nil))},
+ // structs with different tags
+ {V(struct {
+ x int `some:"foo"`
+ }{}), V(struct {
+ x int `some:"bar"`
+ }{})},
+
+ {V(struct {
+ x int `some:"bar"`
+ }{}), V(struct {
+ x int `some:"foo"`
+ }{})},
+
+ {V(MyStruct{}), V(struct {
+ x int `some:"foo"`
+ }{})},
+
+ {V(struct {
+ x int `some:"foo"`
+ }{}), V(MyStruct{})},
+
+ {V(MyStruct{}), V(struct {
+ x int `some:"bar"`
+ }{})},
+
+ {V(struct {
+ x int `some:"bar"`
+ }{}), V(MyStruct{})},
+
// can convert *byte and *MyByte
{V((*byte)(nil)), V((*MyByte)(nil))},
{V((*MyByte)(nil)), V((*byte)(nil))},
@@ -3973,6 +4067,39 @@ func TestStructOf(t *testing.T) {
}
}
+ // Check size and alignment with a trailing zero-sized field.
+ st = StructOf([]StructField{
+ {
+ Name: "F1",
+ Type: TypeOf(byte(0)),
+ },
+ {
+ Name: "F2",
+ Type: TypeOf([0]*byte{}),
+ },
+ })
+ stt = TypeOf(struct {
+ G1 byte
+ G2 [0]*byte
+ }{})
+ // Broken with gccgo for now--gccgo does not pad structs yet.
+ // if st.Size() != stt.Size() {
+ // t.Errorf("constructed zero-padded struct size = %v, want %v", st.Size(), stt.Size())
+ // }
+ if st.Align() != stt.Align() {
+ t.Errorf("constructed zero-padded struct align = %v, want %v", st.Align(), stt.Align())
+ }
+ if st.FieldAlign() != stt.FieldAlign() {
+ t.Errorf("constructed zero-padded struct field align = %v, want %v", st.FieldAlign(), stt.FieldAlign())
+ }
+ for i := 0; i < st.NumField(); i++ {
+ o1 := st.Field(i).Offset
+ o2 := stt.Field(i).Offset
+ if o1 != o2 {
+ t.Errorf("constructed zero-padded struct field %v offset = %v, want %v", i, o1, o2)
+ }
+ }
+
// check duplicate names
shouldPanic(func() {
StructOf([]StructField{
@@ -5788,3 +5915,101 @@ func BenchmarkNew(b *testing.B) {
New(v)
}
}
+
+func TestSwapper(t *testing.T) {
+ type I int
+ var a, b, c I
+ type pair struct {
+ x, y int
+ }
+ type pairPtr struct {
+ x, y int
+ p *I
+ }
+ type S string
+
+ tests := []struct {
+ in interface{}
+ i, j int
+ want interface{}
+ }{
+ {
+ in: []int{1, 20, 300},
+ i: 0,
+ j: 2,
+ want: []int{300, 20, 1},
+ },
+ {
+ in: []uintptr{1, 20, 300},
+ i: 0,
+ j: 2,
+ want: []uintptr{300, 20, 1},
+ },
+ {
+ in: []int16{1, 20, 300},
+ i: 0,
+ j: 2,
+ want: []int16{300, 20, 1},
+ },
+ {
+ in: []int8{1, 20, 100},
+ i: 0,
+ j: 2,
+ want: []int8{100, 20, 1},
+ },
+ {
+ in: []*I{&a, &b, &c},
+ i: 0,
+ j: 2,
+ want: []*I{&c, &b, &a},
+ },
+ {
+ in: []string{"eric", "sergey", "larry"},
+ i: 0,
+ j: 2,
+ want: []string{"larry", "sergey", "eric"},
+ },
+ {
+ in: []S{"eric", "sergey", "larry"},
+ i: 0,
+ j: 2,
+ want: []S{"larry", "sergey", "eric"},
+ },
+ {
+ in: []pair{{1, 2}, {3, 4}, {5, 6}},
+ i: 0,
+ j: 2,
+ want: []pair{{5, 6}, {3, 4}, {1, 2}},
+ },
+ {
+ in: []pairPtr{{1, 2, &a}, {3, 4, &b}, {5, 6, &c}},
+ i: 0,
+ j: 2,
+ want: []pairPtr{{5, 6, &c}, {3, 4, &b}, {1, 2, &a}},
+ },
+ }
+ for i, tt := range tests {
+ inStr := fmt.Sprint(tt.in)
+ Swapper(tt.in)(tt.i, tt.j)
+ if !DeepEqual(tt.in, tt.want) {
+ t.Errorf("%d. swapping %v and %v of %v = %v; want %v", i, tt.i, tt.j, inStr, tt.in, tt.want)
+ }
+ }
+}
+
+// TestUnaddressableField tests that the reflect package will not allow
+// a type from another package to be used as a named type with an
+// unexported field.
+//
+// This ensures that unexported fields cannot be modified by other packages.
+func TestUnaddressableField(t *testing.T) {
+ var b Buffer // type defined in reflect, a different package
+ var localBuffer struct {
+ buf []byte
+ }
+ lv := ValueOf(&localBuffer).Elem()
+ rv := ValueOf(b)
+ shouldPanic(func() {
+ lv.Set(rv)
+ })
+}
diff --git a/libgo/go/reflect/deepequal.go b/libgo/go/reflect/deepequal.go
index 9770358ae77..f3fd7043e5a 100644
--- a/libgo/go/reflect/deepequal.go
+++ b/libgo/go/reflect/deepequal.go
@@ -30,9 +30,13 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
}
// if depth > 10 { panic("deepValueEqual") } // for debugging
+
+ // We want to avoid putting more in the visited map than we need to.
+ // For any possible reference cycle that might be encountered,
+ // hard(t) needs to return true for at least one of the types in the cycle.
hard := func(k Kind) bool {
switch k {
- case Array, Map, Slice, Struct:
+ case Map, Slice, Ptr, Interface:
return true
}
return false
@@ -142,8 +146,9 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
//
// Interface values are deeply equal if they hold deeply equal concrete values.
//
-// Map values are deeply equal if they are the same map object
-// or if they have the same length and their corresponding keys
+// Map values are deeply equal when all of the following are true:
+// they are both nil or both non-nil, they have the same length,
+// and either they are the same map object or their corresponding keys
// (matched using Go equality) map to deeply equal values.
//
// Pointer values are deeply equal if they are equal using Go's == operator
diff --git a/libgo/go/reflect/example_test.go b/libgo/go/reflect/example_test.go
index 9e2b9b3e972..f959b958463 100644
--- a/libgo/go/reflect/example_test.go
+++ b/libgo/go/reflect/example_test.go
@@ -5,6 +5,8 @@
package reflect_test
import (
+ "bytes"
+ "encoding/json"
"fmt"
"io"
"os"
@@ -107,3 +109,42 @@ func ExampleTypeOf() {
// Output:
// true
}
+
+func ExampleStructOf() {
+ typ := reflect.StructOf([]reflect.StructField{
+ {
+ Name: "Height",
+ Type: reflect.TypeOf(float64(0)),
+ Tag: `json:"height"`,
+ },
+ {
+ Name: "Age",
+ Type: reflect.TypeOf(int(0)),
+ Tag: `json:"age"`,
+ },
+ })
+
+ v := reflect.New(typ).Elem()
+ v.Field(0).SetFloat(0.4)
+ v.Field(1).SetInt(2)
+ s := v.Addr().Interface()
+
+ w := new(bytes.Buffer)
+ if err := json.NewEncoder(w).Encode(s); err != nil {
+ panic(err)
+ }
+
+ fmt.Printf("value: %+v\n", s)
+ fmt.Printf("json: %s", w.Bytes())
+
+ r := bytes.NewReader([]byte(`{"height":1.5,"age":10}`))
+ if err := json.NewDecoder(r).Decode(s); err != nil {
+ panic(err)
+ }
+ fmt.Printf("value: %+v\n", s)
+
+ // Output:
+ // value: &{Height:0.4 Age:2}
+ // json: {"height":0.4,"age":2}
+ // value: &{Height:1.5 Age:10}
+}
diff --git a/libgo/go/reflect/export_test.go b/libgo/go/reflect/export_test.go
index a06e8d0a944..92b13025380 100644
--- a/libgo/go/reflect/export_test.go
+++ b/libgo/go/reflect/export_test.go
@@ -83,3 +83,7 @@ func ResolveReflectName(s string) {
resolveReflectName(newName(s, "", "", false))
}
*/
+
+type Buffer struct {
+ buf []byte
+}
diff --git a/libgo/go/reflect/makefunc.go b/libgo/go/reflect/makefunc.go
index 3a9fd2897b7..91df32839cd 100644
--- a/libgo/go/reflect/makefunc.go
+++ b/libgo/go/reflect/makefunc.go
@@ -12,8 +12,8 @@ import (
// makeFuncImpl is the closure value implementing the function
// returned by MakeFunc.
+// The first three words are layed out like ffi_go_closure.
type makeFuncImpl struct {
- // These first three words are layed out like ffi_go_closure.
code uintptr
ffi_cif unsafe.Pointer
ffi_fun func(unsafe.Pointer, unsafe.Pointer)
diff --git a/libgo/go/reflect/swapper.go b/libgo/go/reflect/swapper.go
new file mode 100644
index 00000000000..5441cb03150
--- /dev/null
+++ b/libgo/go/reflect/swapper.go
@@ -0,0 +1,74 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package reflect
+
+import "unsafe"
+
+// Swapper returns a function that swaps the elements in the provided
+// slice.
+//
+// Swapper panics if the provided interface is not a slice.
+func Swapper(slice interface{}) func(i, j int) {
+ v := ValueOf(slice)
+ if v.Kind() != Slice {
+ panic(&ValueError{Method: "Swapper", Kind: v.Kind()})
+ }
+ // Fast path for slices of size 0 and 1. Nothing to swap.
+ switch v.Len() {
+ case 0:
+ return func(i, j int) { panic("reflect: slice index out of range") }
+ case 1:
+ return func(i, j int) {
+ if i != 0 || j != 0 {
+ panic("reflect: slice index out of range")
+ }
+ }
+ }
+
+ typ := v.Type().Elem().(*rtype)
+ size := typ.Size()
+ hasPtr := typ.kind&kindNoPointers == 0
+
+ // Some common & small cases, without using memmove:
+ if hasPtr {
+ if size == ptrSize {
+ ps := *(*[]unsafe.Pointer)(v.ptr)
+ return func(i, j int) { ps[i], ps[j] = ps[j], ps[i] }
+ }
+ if typ.Kind() == String {
+ ss := *(*[]string)(v.ptr)
+ return func(i, j int) { ss[i], ss[j] = ss[j], ss[i] }
+ }
+ } else {
+ switch size {
+ case 8:
+ is := *(*[]int64)(v.ptr)
+ return func(i, j int) { is[i], is[j] = is[j], is[i] }
+ case 4:
+ is := *(*[]int32)(v.ptr)
+ return func(i, j int) { is[i], is[j] = is[j], is[i] }
+ case 2:
+ is := *(*[]int16)(v.ptr)
+ return func(i, j int) { is[i], is[j] = is[j], is[i] }
+ case 1:
+ is := *(*[]int8)(v.ptr)
+ return func(i, j int) { is[i], is[j] = is[j], is[i] }
+ }
+ }
+
+ s := (*sliceHeader)(v.ptr)
+ tmp := unsafe_New(typ) // swap scratch space
+
+ return func(i, j int) {
+ if uint(i) >= uint(s.Len) || uint(j) >= uint(s.Len) {
+ panic("reflect: slice index out of range")
+ }
+ val1 := arrayAt(s.Data, i, size)
+ val2 := arrayAt(s.Data, j, size)
+ typedmemmove(typ, tmp, val1)
+ typedmemmove(typ, val1, val2)
+ typedmemmove(typ, val2, tmp)
+ }
+}
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index 4f13f144327..07a355d5e41 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -28,6 +28,9 @@ import (
// Use the Kind method to find out the kind of type before
// calling kind-specific methods. Calling a method
// inappropriate to the kind of type causes a run-time panic.
+//
+// Type values are comparable, such as with the == operator.
+// Two Type values are equal if they represent identical types.
type Type interface {
// Methods applicable to all types.
@@ -59,7 +62,7 @@ type Type interface {
// method signature, without a receiver, and the Func field is nil.
MethodByName(string) (Method, bool)
- // NumMethod returns the number of methods in the type's method set.
+ // NumMethod returns the number of exported methods in the type's method set.
NumMethod() int
// Name returns the type's name within its package.
@@ -79,7 +82,7 @@ type Type interface {
// String returns a string representation of the type.
// The string representation may use shortened package names
// (e.g., base64 instead of "encoding/base64") and is not
- // guaranteed to be unique among types. To test for equality,
+ // guaranteed to be unique among types. To test for type identity,
// compare the Types directly.
String() string
@@ -155,9 +158,18 @@ type Type interface {
// and a boolean indicating if the field was found.
FieldByName(name string) (StructField, bool)
- // FieldByNameFunc returns the first struct field with a name
+ // FieldByNameFunc returns the struct field with a name
// that satisfies the match function and a boolean indicating if
// the field was found.
+ //
+ // FieldByNameFunc considers the fields in the struct itself
+ // and then the fields in any anonymous structs, in breadth first order,
+ // stopping at the shallowest nesting depth containing one or more
+ // fields satisfying the match function. If multiple fields at that depth
+ // satisfy the match function, they cancel each other
+ // and FieldByNameFunc returns no match.
+ // This behavior mirrors Go's handling of name lookup in
+ // structs containing anonymous fields.
FieldByNameFunc(match func(string) bool) (StructField, bool)
// In returns the type of a function type's i'th input parameter.
@@ -826,7 +838,7 @@ func (tag StructTag) Get(key string) string {
// the value returned by Lookup is unspecified.
func (tag StructTag) Lookup(key string) (value string, ok bool) {
// When modifying this code, also update the validateStructTag code
- // in golang.org/x/tools/cmd/vet/structtag.go.
+ // in cmd/vet/structtag.go.
for tag != "" {
// Skip leading space.
@@ -1157,12 +1169,11 @@ func (t *rtype) ptrTo() *rtype {
// Create a new ptrType starting with the description
// of an *unsafe.Pointer.
- p = new(ptrType)
var iptr interface{} = (*unsafe.Pointer)(nil)
prototype := *(**ptrType)(unsafe.Pointer(&iptr))
- *p = *prototype
+ pp := *prototype
- p.string = &s
+ pp.string = &s
// For the type structures linked into the binary, the
// compiler provides a good hash of the string.
@@ -1171,17 +1182,17 @@ func (t *rtype) ptrTo() *rtype {
// old hash and the new "*".
// p.hash = fnv1(t.hash, '*')
// This is the gccgo version.
- p.hash = (t.hash << 4) + 9
+ pp.hash = (t.hash << 4) + 9
- p.uncommonType = nil
- p.ptrToThis = nil
- p.elem = t
+ pp.uncommonType = nil
+ pp.ptrToThis = nil
+ pp.elem = t
if t.kind&kindNoPointers != 0 {
- p.gc = unsafe.Pointer(&ptrDataGCProg)
+ pp.gc = unsafe.Pointer(&ptrDataGCProg)
} else {
- p.gc = unsafe.Pointer(&ptrGC{
- width: p.size,
+ pp.gc = unsafe.Pointer(&ptrGC{
+ width: pp.size,
op: _GC_PTR,
off: 0,
elemgc: t.gc,
@@ -1189,7 +1200,7 @@ func (t *rtype) ptrTo() *rtype {
})
}
- q := canonicalize(&p.rtype)
+ q := canonicalize(&pp.rtype)
p = (*ptrType)(unsafe.Pointer(q.(*rtype)))
ptrMap.m[t] = p
@@ -1331,10 +1342,22 @@ func directlyAssignable(T, V *rtype) bool {
}
// x's type T and V must have identical underlying types.
- return haveIdenticalUnderlyingType(T, V)
+ return haveIdenticalUnderlyingType(T, V, true)
+}
+
+func haveIdenticalType(T, V Type, cmpTags bool) bool {
+ if cmpTags {
+ return T == V
+ }
+
+ if T.Name() != V.Name() || T.Kind() != V.Kind() {
+ return false
+ }
+
+ return haveIdenticalUnderlyingType(T.common(), V.common(), false)
}
-func haveIdenticalUnderlyingType(T, V *rtype) bool {
+func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
if T == V {
return true
}
@@ -1353,18 +1376,18 @@ func haveIdenticalUnderlyingType(T, V *rtype) bool {
// Composite types.
switch kind {
case Array:
- return T.Elem() == V.Elem() && T.Len() == V.Len()
+ return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
case Chan:
// Special case:
// x is a bidirectional channel value, T is a channel type,
// and x's type V and T have identical element types.
- if V.ChanDir() == BothDir && T.Elem() == V.Elem() {
+ if V.ChanDir() == BothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
return true
}
// Otherwise continue test for identical underlying type.
- return V.ChanDir() == T.ChanDir() && T.Elem() == V.Elem()
+ return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
case Func:
t := (*funcType)(unsafe.Pointer(T))
@@ -1373,12 +1396,12 @@ func haveIdenticalUnderlyingType(T, V *rtype) bool {
return false
}
for i, typ := range t.in {
- if typ != v.in[i] {
+ if !haveIdenticalType(typ, v.in[i], cmpTags) {
return false
}
}
for i, typ := range t.out {
- if typ != v.out[i] {
+ if !haveIdenticalType(typ, v.out[i], cmpTags) {
return false
}
}
@@ -1395,10 +1418,10 @@ func haveIdenticalUnderlyingType(T, V *rtype) bool {
return false
case Map:
- return T.Key() == V.Key() && T.Elem() == V.Elem()
+ return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
case Ptr, Slice:
- return T.Elem() == V.Elem()
+ return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
case Struct:
t := (*structType)(unsafe.Pointer(T))
@@ -1415,10 +1438,10 @@ func haveIdenticalUnderlyingType(T, V *rtype) bool {
if tf.pkgPath != vf.pkgPath && (tf.pkgPath == nil || vf.pkgPath == nil || *tf.pkgPath != *vf.pkgPath) {
return false
}
- if tf.typ != vf.typ {
+ if !haveIdenticalType(tf.typ, vf.typ, cmpTags) {
return false
}
- if tf.tag != vf.tag && (tf.tag == nil || vf.tag == nil || *tf.tag != *vf.tag) {
+ if cmpTags && tf.tag != vf.tag && (tf.tag == nil || vf.tag == nil || *tf.tag != *vf.tag) {
return false
}
if tf.offset != vf.offset {
@@ -1539,8 +1562,7 @@ func ChanOf(dir ChanDir, t Type) Type {
// Make a channel type.
var ichan interface{} = (chan unsafe.Pointer)(nil)
prototype := *(**chanType)(unsafe.Pointer(&ichan))
- ch := new(chanType)
- *ch = *prototype
+ ch := *prototype
ch.dir = uintptr(dir)
ch.string = &s
@@ -1602,8 +1624,7 @@ func MapOf(key, elem Type) Type {
// Make a map type.
var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
- mt := new(mapType)
- *mt = **(**mapType)(unsafe.Pointer(&imap))
+ mt := **(**mapType)(unsafe.Pointer(&imap))
mt.string = &s
// gccgo uses a different hash
@@ -1684,7 +1705,7 @@ func FuncOf(in, out []Type, variadic bool) Type {
// Look in cache.
funcLookupCache.RLock()
for _, t := range funcLookupCache.m[hash] {
- if haveIdenticalUnderlyingType(&ft.rtype, t) {
+ if haveIdenticalUnderlyingType(&ft.rtype, t, true) {
funcLookupCache.RUnlock()
return t
}
@@ -1698,7 +1719,7 @@ func FuncOf(in, out []Type, variadic bool) Type {
funcLookupCache.m = make(map[uint32][]*rtype)
}
for _, t := range funcLookupCache.m[hash] {
- if haveIdenticalUnderlyingType(&ft.rtype, t) {
+ if haveIdenticalUnderlyingType(&ft.rtype, t, true) {
return t
}
}
@@ -1885,12 +1906,13 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
gcPtr = unsafe.Pointer(&gc[0])
}
- b := new(rtype)
- b.align = int8(maxAlign)
- b.fieldAlign = uint8(maxAlign)
- b.size = size
- b.kind = kind
- b.gc = gcPtr
+ b := &rtype{
+ align: int8(maxAlign),
+ fieldAlign: uint8(maxAlign),
+ size: size,
+ kind: kind,
+ gc: gcPtr,
+ }
s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
b.string = &s
return b
@@ -2002,8 +2024,7 @@ func SliceOf(t Type) Type {
// Make a slice type.
var islice interface{} = ([]unsafe.Pointer)(nil)
prototype := *(**sliceType)(unsafe.Pointer(&islice))
- slice := new(sliceType)
- *slice = *prototype
+ slice := *prototype
slice.string = &s
// gccgo uses a different hash.
@@ -2061,6 +2082,7 @@ func StructOf(fields []StructField) Type {
hasPtr = false // records whether at least one struct-field is a pointer
)
+ lastzero := uintptr(0)
repr = append(repr, "struct {"...)
for i, field := range fields {
if field.Type == nil {
@@ -2138,9 +2160,22 @@ func StructOf(fields []StructField) Type {
}
size = f.offset + ft.size
+ if ft.size == 0 {
+ lastzero = size
+ }
+
fs[i] = f
}
+ if size > 0 && lastzero == size {
+ // This is a non-zero sized struct that ends in a
+ // zero-sized field. We add an extra byte of padding,
+ // to ensure that taking the address of the final
+ // zero-sized field can't manufacture a pointer to the
+ // next object in the heap. See issue 9401.
+ size++
+ }
+
if len(fs) > 0 {
repr = append(repr, ' ')
}
@@ -2162,7 +2197,7 @@ func StructOf(fields []StructField) Type {
structLookupCache.RLock()
for _, st := range structLookupCache.m[hash] {
t := st.common()
- if haveIdenticalUnderlyingType(&typ.rtype, t) {
+ if haveIdenticalUnderlyingType(&typ.rtype, t, true) {
structLookupCache.RUnlock()
return t
}
@@ -2179,7 +2214,7 @@ func StructOf(fields []StructField) Type {
}
for _, st := range structLookupCache.m[hash] {
t := st.common()
- if haveIdenticalUnderlyingType(&typ.rtype, t) {
+ if haveIdenticalUnderlyingType(&typ.rtype, t, true) {
return t
}
}
@@ -2295,8 +2330,7 @@ func ArrayOf(count int, elem Type) Type {
// Make an array type.
var iarray interface{} = [1]unsafe.Pointer{}
prototype := *(**arrayType)(unsafe.Pointer(&iarray))
- array := new(arrayType)
- *array = *prototype
+ array := *prototype
array.string = &s
// gccgo uses a different hash.
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index 1d1887693d3..1b4c5407e57 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -2113,14 +2113,14 @@ func convertOp(dst, src *rtype) func(Value, Type) Value {
}
// dst and src have same underlying type.
- if haveIdenticalUnderlyingType(dst, src) {
+ if haveIdenticalUnderlyingType(dst, src, false) {
return cvtDirect
}
// dst and src are unnamed pointer types with same underlying base type.
if dst.Kind() == Ptr && dst.Name() == "" &&
src.Kind() == Ptr && src.Name() == "" &&
- haveIdenticalUnderlyingType(dst.Elem().common(), src.Elem().common()) {
+ haveIdenticalUnderlyingType(dst.Elem().common(), src.Elem().common(), false) {
return cvtDirect
}
diff --git a/libgo/go/regexp/all_test.go b/libgo/go/regexp/all_test.go
index 88391ff47de..beb46e70995 100644
--- a/libgo/go/regexp/all_test.go
+++ b/libgo/go/regexp/all_test.go
@@ -11,7 +11,7 @@ import (
"testing"
)
-var good_re = []string{
+var goodRe = []string{
``,
`.`,
`^.$`,
@@ -36,7 +36,7 @@ type stringError struct {
err string
}
-var bad_re = []stringError{
+var badRe = []stringError{
{`*`, "missing argument to repetition operator: `*`"},
{`+`, "missing argument to repetition operator: `+`"},
{`?`, "missing argument to repetition operator: `?`"},
@@ -64,14 +64,14 @@ func compileTest(t *testing.T, expr string, error string) *Regexp {
}
func TestGoodCompile(t *testing.T) {
- for i := 0; i < len(good_re); i++ {
- compileTest(t, good_re[i], "")
+ for i := 0; i < len(goodRe); i++ {
+ compileTest(t, goodRe[i], "")
}
}
func TestBadCompile(t *testing.T) {
- for i := 0; i < len(bad_re); i++ {
- compileTest(t, bad_re[i].re, bad_re[i].err)
+ for i := 0; i < len(badRe); i++ {
+ compileTest(t, badRe[i].re, badRe[i].err)
}
}
@@ -512,6 +512,32 @@ func TestSplit(t *testing.T) {
}
}
+// The following sequence of Match calls used to panic. See issue #12980.
+func TestParseAndCompile(t *testing.T) {
+ expr := "a$"
+ s := "a\nb"
+
+ for i, tc := range []struct {
+ reFlags syntax.Flags
+ expMatch bool
+ }{
+ {syntax.Perl | syntax.OneLine, false},
+ {syntax.Perl &^ syntax.OneLine, true},
+ } {
+ parsed, err := syntax.Parse(expr, tc.reFlags)
+ if err != nil {
+ t.Fatalf("%d: parse: %v", i, err)
+ }
+ re, err := Compile(parsed.String())
+ if err != nil {
+ t.Fatalf("%d: compile: %v", i, err)
+ }
+ if match := re.MatchString(s); match != tc.expMatch {
+ t.Errorf("%d: %q.MatchString(%q)=%t; expected=%t", i, re, s, match, tc.expMatch)
+ }
+ }
+}
+
// Check that one-pass cutoff does trigger.
func TestOnePassCutoff(t *testing.T) {
re, err := syntax.Parse(`^x{1,1000}y{1,1000}$`, syntax.Perl)
@@ -538,6 +564,72 @@ func TestSwitchBacktrack(t *testing.T) {
re.Match(long[:1]) // triggers backtracker
}
+func BenchmarkFind(b *testing.B) {
+ b.StopTimer()
+ re := MustCompile("a+b+")
+ wantSubs := "aaabb"
+ s := []byte("acbb" + wantSubs + "dd")
+ b.StartTimer()
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ subs := re.Find(s)
+ if string(subs) != wantSubs {
+ b.Fatalf("Find(%q) = %q; want %q", s, subs, wantSubs)
+ }
+ }
+}
+
+func BenchmarkFindString(b *testing.B) {
+ b.StopTimer()
+ re := MustCompile("a+b+")
+ wantSubs := "aaabb"
+ s := "acbb" + wantSubs + "dd"
+ b.StartTimer()
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ subs := re.FindString(s)
+ if subs != wantSubs {
+ b.Fatalf("FindString(%q) = %q; want %q", s, subs, wantSubs)
+ }
+ }
+}
+
+func BenchmarkFindSubmatch(b *testing.B) {
+ b.StopTimer()
+ re := MustCompile("a(a+b+)b")
+ wantSubs := "aaabb"
+ s := []byte("acbb" + wantSubs + "dd")
+ b.StartTimer()
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ subs := re.FindSubmatch(s)
+ if string(subs[0]) != wantSubs {
+ b.Fatalf("FindSubmatch(%q)[0] = %q; want %q", s, subs[0], wantSubs)
+ }
+ if string(subs[1]) != "aab" {
+ b.Fatalf("FindSubmatch(%q)[1] = %q; want %q", s, subs[1], "aab")
+ }
+ }
+}
+
+func BenchmarkFindStringSubmatch(b *testing.B) {
+ b.StopTimer()
+ re := MustCompile("a(a+b+)b")
+ wantSubs := "aaabb"
+ s := "acbb" + wantSubs + "dd"
+ b.StartTimer()
+ b.ReportAllocs()
+ for i := 0; i < b.N; i++ {
+ subs := re.FindStringSubmatch(s)
+ if subs[0] != wantSubs {
+ b.Fatalf("FindStringSubmatch(%q)[0] = %q; want %q", s, subs[0], wantSubs)
+ }
+ if subs[1] != "aab" {
+ b.Fatalf("FindStringSubmatch(%q)[1] = %q; want %q", s, subs[1], "aab")
+ }
+ }
+}
+
func BenchmarkLiteral(b *testing.B) {
x := strings.Repeat("x", 50) + "y"
b.StopTimer()
@@ -726,3 +818,23 @@ func BenchmarkMatchParallelCopied(b *testing.B) {
}
})
}
+
+var sink string
+
+func BenchmarkQuoteMetaAll(b *testing.B) {
+ s := string(specialBytes)
+ b.SetBytes(int64(len(s)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ sink = QuoteMeta(s)
+ }
+}
+
+func BenchmarkQuoteMetaNone(b *testing.B) {
+ s := "abcdefghijklmnopqrstuvwxyz"
+ b.SetBytes(int64(len(s)))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ sink = QuoteMeta(s)
+ }
+}
diff --git a/libgo/go/regexp/exec.go b/libgo/go/regexp/exec.go
index 4fd61b5d8d1..977619cb28a 100644
--- a/libgo/go/regexp/exec.go
+++ b/libgo/go/regexp/exec.go
@@ -405,14 +405,16 @@ func (m *machine) onepass(i input, pos int) bool {
return m.matched
}
-// empty is a non-nil 0-element slice,
-// so doExecute can avoid an allocation
-// when 0 captures are requested from a successful match.
-var empty = make([]int, 0)
+// doMatch reports whether either r, b or s match the regexp.
+func (re *Regexp) doMatch(r io.RuneReader, b []byte, s string) bool {
+ return re.doExecute(r, b, s, 0, 0, nil) != nil
+}
-// doExecute finds the leftmost match in the input and returns
-// the position of its subexpressions.
-func (re *Regexp) doExecute(r io.RuneReader, b []byte, s string, pos int, ncap int) []int {
+// doExecute finds the leftmost match in the input, appends the position
+// of its subexpressions to dstCap and returns dstCap.
+//
+// nil is returned if no matches are found and non-nil if matches are found.
+func (re *Regexp) doExecute(r io.RuneReader, b []byte, s string, pos int, ncap int, dstCap []int) []int {
m := re.get()
var i input
var size int
@@ -445,12 +447,15 @@ func (re *Regexp) doExecute(r io.RuneReader, b []byte, s string, pos int, ncap i
return nil
}
}
- if ncap == 0 {
- re.put(m)
- return empty // empty but not nil
+ dstCap = append(dstCap, m.matchcap...)
+ if dstCap == nil {
+ // Keep the promise of returning non-nil value on match.
+ dstCap = arrayNoInts[:0]
}
- cap := make([]int, len(m.matchcap))
- copy(cap, m.matchcap)
re.put(m)
- return cap
+ return dstCap
}
+
+// arrayNoInts is returned by doExecute match if nil dstCap is passed
+// to it with ncap=0.
+var arrayNoInts [0]int
diff --git a/libgo/go/regexp/exec_test.go b/libgo/go/regexp/exec_test.go
index 69f187e38a8..766394de6ee 100644
--- a/libgo/go/regexp/exec_test.go
+++ b/libgo/go/regexp/exec_test.go
@@ -8,6 +8,7 @@ import (
"bufio"
"compress/bzip2"
"fmt"
+ "internal/testenv"
"io"
"os"
"path/filepath"
@@ -659,9 +660,14 @@ func makeText(n int) []byte {
}
func BenchmarkMatch(b *testing.B) {
+ isRaceBuilder := strings.HasSuffix(testenv.Builder(), "-race")
+
for _, data := range benchData {
r := MustCompile(data.re)
for _, size := range benchSizes {
+ if isRaceBuilder && size.n > 1<<10 {
+ continue
+ }
t := makeText(size.n)
b.Run(data.name+"/"+size.name, func(b *testing.B) {
b.SetBytes(int64(size.n))
diff --git a/libgo/go/regexp/onepass.go b/libgo/go/regexp/onepass.go
index 49919548201..1b0564c3fd0 100644
--- a/libgo/go/regexp/onepass.go
+++ b/libgo/go/regexp/onepass.go
@@ -287,11 +287,6 @@ func (p runeSlice) Len() int { return len(p) }
func (p runeSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p runeSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
-// Sort is a convenience method.
-func (p runeSlice) Sort() {
- sort.Sort(p)
-}
-
var anyRuneNotNL = []rune{0, '\n' - 1, '\n' + 1, unicode.MaxRune}
var anyRune = []rune{0, unicode.MaxRune}
diff --git a/libgo/go/regexp/regexp.go b/libgo/go/regexp/regexp.go
index fe3db9f78b0..01093d4bd0d 100644
--- a/libgo/go/regexp/regexp.go
+++ b/libgo/go/regexp/regexp.go
@@ -408,17 +408,17 @@ func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
// MatchReader reports whether the Regexp matches the text read by the
// RuneReader.
func (re *Regexp) MatchReader(r io.RuneReader) bool {
- return re.doExecute(r, nil, "", 0, 0) != nil
+ return re.doMatch(r, nil, "")
}
// MatchString reports whether the Regexp matches the string s.
func (re *Regexp) MatchString(s string) bool {
- return re.doExecute(nil, nil, s, 0, 0) != nil
+ return re.doMatch(nil, nil, s)
}
// Match reports whether the Regexp matches the byte slice b.
func (re *Regexp) Match(b []byte) bool {
- return re.doExecute(nil, b, "", 0, 0) != nil
+ return re.doMatch(nil, b, "")
}
// MatchReader checks whether a textual regular expression matches the text
@@ -502,8 +502,9 @@ func (re *Regexp) replaceAll(bsrc []byte, src string, nmatch int, repl func(dst
nmatch = re.prog.NumCap
}
+ var dstCap [2]int
for searchPos <= endPos {
- a := re.doExecute(nil, bsrc, src, searchPos, nmatch)
+ a := re.doExecute(nil, bsrc, src, searchPos, nmatch, dstCap[:0])
if len(a) == 0 {
break // no more matches
}
@@ -599,11 +600,22 @@ func special(b byte) bool {
// inside the argument text; the returned string is a regular expression matching
// the literal text. For example, QuoteMeta(`[foo]`) returns `\[foo\]`.
func QuoteMeta(s string) string {
- b := make([]byte, 2*len(s))
-
// A byte loop is correct because all metacharacters are ASCII.
- j := 0
- for i := 0; i < len(s); i++ {
+ var i int
+ for i = 0; i < len(s); i++ {
+ if special(s[i]) {
+ break
+ }
+ }
+ // No meta characters found, so return original string.
+ if i >= len(s) {
+ return s
+ }
+
+ b := make([]byte, 2*len(s)-i)
+ copy(b, s[:i])
+ j := i
+ for ; i < len(s); i++ {
if special(s[i]) {
b[j] = '\\'
j++
@@ -611,7 +623,7 @@ func QuoteMeta(s string) string {
b[j] = s[i]
j++
}
- return string(b[0:j])
+ return string(b[:j])
}
// The number of capture values in the program may correspond
@@ -641,7 +653,7 @@ func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
}
for pos, i, prevMatchEnd := 0, 0, -1; i < n && pos <= end; {
- matches := re.doExecute(nil, b, s, pos, re.prog.NumCap)
+ matches := re.doExecute(nil, b, s, pos, re.prog.NumCap, nil)
if len(matches) == 0 {
break
}
@@ -681,7 +693,8 @@ func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
// Find returns a slice holding the text of the leftmost match in b of the regular expression.
// A return value of nil indicates no match.
func (re *Regexp) Find(b []byte) []byte {
- a := re.doExecute(nil, b, "", 0, 2)
+ var dstCap [2]int
+ a := re.doExecute(nil, b, "", 0, 2, dstCap[:0])
if a == nil {
return nil
}
@@ -693,7 +706,7 @@ func (re *Regexp) Find(b []byte) []byte {
// b[loc[0]:loc[1]].
// A return value of nil indicates no match.
func (re *Regexp) FindIndex(b []byte) (loc []int) {
- a := re.doExecute(nil, b, "", 0, 2)
+ a := re.doExecute(nil, b, "", 0, 2, nil)
if a == nil {
return nil
}
@@ -706,7 +719,8 @@ func (re *Regexp) FindIndex(b []byte) (loc []int) {
// an empty string. Use FindStringIndex or FindStringSubmatch if it is
// necessary to distinguish these cases.
func (re *Regexp) FindString(s string) string {
- a := re.doExecute(nil, nil, s, 0, 2)
+ var dstCap [2]int
+ a := re.doExecute(nil, nil, s, 0, 2, dstCap[:0])
if a == nil {
return ""
}
@@ -718,7 +732,7 @@ func (re *Regexp) FindString(s string) string {
// itself is at s[loc[0]:loc[1]].
// A return value of nil indicates no match.
func (re *Regexp) FindStringIndex(s string) (loc []int) {
- a := re.doExecute(nil, nil, s, 0, 2)
+ a := re.doExecute(nil, nil, s, 0, 2, nil)
if a == nil {
return nil
}
@@ -731,7 +745,7 @@ func (re *Regexp) FindStringIndex(s string) (loc []int) {
// byte offset loc[0] through loc[1]-1.
// A return value of nil indicates no match.
func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int) {
- a := re.doExecute(r, nil, "", 0, 2)
+ a := re.doExecute(r, nil, "", 0, 2, nil)
if a == nil {
return nil
}
@@ -744,7 +758,8 @@ func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int) {
// comment.
// A return value of nil indicates no match.
func (re *Regexp) FindSubmatch(b []byte) [][]byte {
- a := re.doExecute(nil, b, "", 0, re.prog.NumCap)
+ var dstCap [4]int
+ a := re.doExecute(nil, b, "", 0, re.prog.NumCap, dstCap[:0])
if a == nil {
return nil
}
@@ -891,7 +906,7 @@ func extract(str string) (name string, num int, rest string, ok bool) {
// in the package comment.
// A return value of nil indicates no match.
func (re *Regexp) FindSubmatchIndex(b []byte) []int {
- return re.pad(re.doExecute(nil, b, "", 0, re.prog.NumCap))
+ return re.pad(re.doExecute(nil, b, "", 0, re.prog.NumCap, nil))
}
// FindStringSubmatch returns a slice of strings holding the text of the
@@ -900,7 +915,8 @@ func (re *Regexp) FindSubmatchIndex(b []byte) []int {
// package comment.
// A return value of nil indicates no match.
func (re *Regexp) FindStringSubmatch(s string) []string {
- a := re.doExecute(nil, nil, s, 0, re.prog.NumCap)
+ var dstCap [4]int
+ a := re.doExecute(nil, nil, s, 0, re.prog.NumCap, dstCap[:0])
if a == nil {
return nil
}
@@ -919,7 +935,7 @@ func (re *Regexp) FindStringSubmatch(s string) []string {
// 'Index' descriptions in the package comment.
// A return value of nil indicates no match.
func (re *Regexp) FindStringSubmatchIndex(s string) []int {
- return re.pad(re.doExecute(nil, nil, s, 0, re.prog.NumCap))
+ return re.pad(re.doExecute(nil, nil, s, 0, re.prog.NumCap, nil))
}
// FindReaderSubmatchIndex returns a slice holding the index pairs
@@ -928,7 +944,7 @@ func (re *Regexp) FindStringSubmatchIndex(s string) []int {
// by the 'Submatch' and 'Index' descriptions in the package comment. A
// return value of nil indicates no match.
func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int {
- return re.pad(re.doExecute(r, nil, "", 0, re.prog.NumCap))
+ return re.pad(re.doExecute(r, nil, "", 0, re.prog.NumCap, nil))
}
const startSize = 10 // The size at which to start a slice in the 'All' routines.
diff --git a/libgo/go/runtime/alg.go b/libgo/go/runtime/alg.go
index 426b7f6bab3..49462692451 100644
--- a/libgo/go/runtime/alg.go
+++ b/libgo/go/runtime/alg.go
@@ -103,7 +103,7 @@ func f32hash(p unsafe.Pointer, h uintptr) uintptr {
case f == 0:
return c1 * (c0 ^ h) // +0, -0
case f != f:
- return c1 * (c0 ^ h ^ uintptr(fastrand1())) // any kind of NaN
+ return c1 * (c0 ^ h ^ uintptr(fastrand())) // any kind of NaN
default:
return memhash(p, h, 4)
}
@@ -115,7 +115,7 @@ func f64hash(p unsafe.Pointer, h uintptr) uintptr {
case f == 0:
return c1 * (c0 ^ h) // +0, -0
case f != f:
- return c1 * (c0 ^ h ^ uintptr(fastrand1())) // any kind of NaN
+ return c1 * (c0 ^ h ^ uintptr(fastrand())) // any kind of NaN
default:
return memhash(p, h, 8)
}
@@ -300,15 +300,6 @@ func efacevaleq(x eface, t *_type, p unsafe.Pointer) bool {
return eq(x.data, p)
}
-func eqstring(x, y string) bool {
- a := stringStructOf(&x)
- b := stringStructOf(&y)
- if a.len != b.len {
- return false
- }
- return memcmp(unsafe.Pointer(a.str), unsafe.Pointer(b.str), uintptr(a.len)) == 0
-}
-
func cmpstring(x, y string) int {
a := stringStructOf(&x)
b := stringStructOf(&y)
diff --git a/libgo/go/runtime/append_test.go b/libgo/go/runtime/append_test.go
index 6b8968e382d..6bd8f3bd951 100644
--- a/libgo/go/runtime/append_test.go
+++ b/libgo/go/runtime/append_test.go
@@ -100,6 +100,22 @@ func BenchmarkAppendSlice(b *testing.B) {
}
}
+var (
+ blackhole []byte
+)
+
+func BenchmarkAppendSliceLarge(b *testing.B) {
+ for _, length := range []int{1 << 10, 4 << 10, 16 << 10, 64 << 10, 256 << 10, 1024 << 10} {
+ y := make([]byte, length)
+ b.Run(fmt.Sprint(length, "Bytes"), func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ blackhole = nil
+ blackhole = append(blackhole, y...)
+ }
+ })
+ }
+}
+
func BenchmarkAppendStr(b *testing.B) {
for _, str := range []string{
"1",
diff --git a/libgo/go/runtime/cgocheck.go b/libgo/go/runtime/cgocheck.go
index 7e38d9c449a..fec36462dd3 100644
--- a/libgo/go/runtime/cgocheck.go
+++ b/libgo/go/runtime/cgocheck.go
@@ -110,7 +110,7 @@ func cgoCheckTypedBlock(typ *_type, src unsafe.Pointer, off, size uintptr) {
}
// The type has a GC program. Try to find GC bits somewhere else.
- for datap := &firstmoduledata; datap != nil; datap = datap.next {
+ for _, datap := range activeModules() {
if cgoInRange(src, datap.data, datap.edata) {
doff := uintptr(src) - datap.data
cgoCheckBits(add(src, -doff), datap.gcdatamask.bytedata, off+doff, size)
@@ -125,7 +125,7 @@ func cgoCheckTypedBlock(typ *_type, src unsafe.Pointer, off, size uintptr) {
aoff := uintptr(src) - mheap_.arena_start
idx := aoff >> _PageShift
- s := h_spans[idx]
+ s := mheap_.spans[idx]
if s.state == _MSpanStack {
// There are no heap bits for value stored on the stack.
// For a channel receive src might be on the stack of some
diff --git a/libgo/go/runtime/chan.go b/libgo/go/runtime/chan.go
index eb2cad6d1dc..a9574dd8ac7 100644
--- a/libgo/go/runtime/chan.go
+++ b/libgo/go/runtime/chan.go
@@ -7,10 +7,16 @@ package runtime
// This file contains the implementation of Go channels.
// Invariants:
-// At least one of c.sendq and c.recvq is empty.
+// At least one of c.sendq and c.recvq is empty,
+// except for the case of an unbuffered channel with a single goroutine
+// blocked on it for both sending and receiving using a select statement,
+// in which case the length of c.sendq and c.recvq is limited only by the
+// size of the select statement.
+//
// For buffered channels, also:
// c.qcount > 0 implies that c.recvq is empty.
// c.qcount < c.dataqsiz implies that c.sendq is empty.
+
import (
"runtime/internal/atomic"
"unsafe"
@@ -290,23 +296,34 @@ func send(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func()) {
goready(gp, 4)
}
+// Sends and receives on unbuffered or empty-buffered channels are the
+// only operations where one running goroutine writes to the stack of
+// another running goroutine. The GC assumes that stack writes only
+// happen when the goroutine is running and are only done by that
+// goroutine. Using a write barrier is sufficient to make up for
+// violating that assumption, but the write barrier has to work.
+// typedmemmove will call bulkBarrierPreWrite, but the target bytes
+// are not in the heap, so that will not help. We arrange to call
+// memmove and typeBitsBulkBarrier instead.
+
func sendDirect(t *_type, sg *sudog, src unsafe.Pointer) {
- // Send on an unbuffered or empty-buffered channel is the only operation
- // in the entire runtime where one goroutine
- // writes to the stack of another goroutine. The GC assumes that
- // stack writes only happen when the goroutine is running and are
- // only done by that goroutine. Using a write barrier is sufficient to
- // make up for violating that assumption, but the write barrier has to work.
- // typedmemmove will call heapBitsBulkBarrier, but the target bytes
- // are not in the heap, so that will not help. We arrange to call
- // memmove and typeBitsBulkBarrier instead.
+ // src is on our stack, dst is a slot on another stack.
// Once we read sg.elem out of sg, it will no longer
// be updated if the destination's stack gets copied (shrunk).
// So make sure that no preemption points can happen between read & use.
dst := sg.elem
+ typeBitsBulkBarrier(t, uintptr(dst), uintptr(src), t.size)
+ memmove(dst, src, t.size)
+}
+
+func recvDirect(t *_type, sg *sudog, dst unsafe.Pointer) {
+ // dst is on our stack or the heap, src is on another stack.
+ // The channel is locked, so src will not move during this
+ // operation.
+ src := sg.elem
+ typeBitsBulkBarrier(t, uintptr(dst), uintptr(src), t.size)
memmove(dst, src, t.size)
- typeBitsBulkBarrier(t, uintptr(dst), t.size)
}
func closechan(c *hchan) {
@@ -337,7 +354,7 @@ func closechan(c *hchan) {
break
}
if sg.elem != nil {
- memclr(sg.elem, uintptr(c.elemsize))
+ typedmemclr(c.elemtype, sg.elem)
sg.elem = nil
}
if sg.releasetime != 0 {
@@ -446,7 +463,7 @@ func chanrecv(t *chantype, c *hchan, ep unsafe.Pointer, block bool) (selected, r
}
unlock(&c.lock)
if ep != nil {
- memclr(ep, uintptr(c.elemsize))
+ typedmemclr(c.elemtype, ep)
}
return true, false
}
@@ -470,7 +487,7 @@ func chanrecv(t *chantype, c *hchan, ep unsafe.Pointer, block bool) (selected, r
if ep != nil {
typedmemmove(c.elemtype, ep, qp)
}
- memclr(qp, uintptr(c.elemsize))
+ typedmemclr(c.elemtype, qp)
c.recvx++
if c.recvx == c.dataqsiz {
c.recvx = 0
@@ -539,9 +556,7 @@ func recv(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func()) {
}
if ep != nil {
// copy data from sender
- // ep points to our own stack or heap, so nothing
- // special (ala sendDirect) needed here.
- typedmemmove(c.elemtype, ep, sg.elem)
+ recvDirect(c.elemtype, sg, ep)
}
} else {
// Queue is full. Take the item at the
diff --git a/libgo/go/runtime/chan_test.go b/libgo/go/runtime/chan_test.go
index 4bd061dbc7b..b96af8af5d7 100644
--- a/libgo/go/runtime/chan_test.go
+++ b/libgo/go/runtime/chan_test.go
@@ -215,11 +215,14 @@ func TestNonblockRecvRace(t *testing.T) {
select {
case <-c:
default:
- t.Fatal("chan is not ready")
+ t.Error("chan is not ready")
}
}()
close(c)
<-c
+ if t.Failed() {
+ return
+ }
}
}
@@ -316,14 +319,16 @@ func TestSelfSelect(t *testing.T) {
case c <- p:
case v := <-c:
if chanCap == 0 && v == p {
- t.Fatalf("self receive")
+ t.Errorf("self receive")
+ return
}
}
} else {
select {
case v := <-c:
if chanCap == 0 && v == p {
- t.Fatalf("self receive")
+ t.Errorf("self receive")
+ return
}
case c <- p:
}
diff --git a/libgo/go/runtime/cpuprof.go b/libgo/go/runtime/cpuprof.go
index 873276f3639..e1206f99f10 100644
--- a/libgo/go/runtime/cpuprof.go
+++ b/libgo/go/runtime/cpuprof.go
@@ -4,7 +4,7 @@
// CPU profiling.
// Based on algorithms and data structures used in
-// http://code.google.com/p/google-perftools/.
+// https://github.com/google/pprof.
//
// The main difference between this code and the google-perftools
// code is that this code is written to allow copying the profile data
@@ -68,6 +68,7 @@ type cpuprofEntry struct {
stack [maxCPUProfStack]uintptr
}
+//go:notinheap
type cpuProfile struct {
on bool // profiling is on
wait note // goroutine waits here
diff --git a/libgo/go/runtime/crash_cgo_test.go b/libgo/go/runtime/crash_cgo_test.go
index 2504bd0f415..347b820eb5a 100644
--- a/libgo/go/runtime/crash_cgo_test.go
+++ b/libgo/go/runtime/crash_cgo_test.go
@@ -19,10 +19,12 @@ import (
)
func TestCgoCrashHandler(t *testing.T) {
+ t.Parallel()
testCrashHandler(t, true)
}
func TestCgoSignalDeadlock(t *testing.T) {
+ t.Parallel()
if testing.Short() && runtime.GOOS == "windows" {
t.Skip("Skipping in short mode") // takes up to 64 seconds
}
@@ -34,6 +36,7 @@ func TestCgoSignalDeadlock(t *testing.T) {
}
func TestCgoTraceback(t *testing.T) {
+ t.Parallel()
got := runTestProg(t, "testprogcgo", "CgoTraceback")
want := "OK\n"
if got != want {
@@ -42,7 +45,9 @@ func TestCgoTraceback(t *testing.T) {
}
func TestCgoCallbackGC(t *testing.T) {
- if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
+ t.Parallel()
+ switch runtime.GOOS {
+ case "plan9", "windows":
t.Skipf("no pthreads on %s", runtime.GOOS)
}
if testing.Short() {
@@ -63,6 +68,7 @@ func TestCgoCallbackGC(t *testing.T) {
}
func TestCgoExternalThreadPanic(t *testing.T) {
+ t.Parallel()
if runtime.GOOS == "plan9" {
t.Skipf("no pthreads on %s", runtime.GOOS)
}
@@ -74,6 +80,7 @@ func TestCgoExternalThreadPanic(t *testing.T) {
}
func TestCgoExternalThreadSIGPROF(t *testing.T) {
+ t.Parallel()
// issue 9456.
switch runtime.GOOS {
case "plan9", "windows":
@@ -97,22 +104,42 @@ func TestCgoExternalThreadSIGPROF(t *testing.T) {
// ppc64 (issue #8912)
t.Skipf("no external linking on ppc64")
}
- got := runTestProg(t, "testprogcgo", "CgoExternalThreadSIGPROF")
- want := "OK\n"
- if got != want {
+
+ exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ got, err := testEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
+ if err != nil {
+ t.Fatalf("exit status: %v\n%s", err, got)
+ }
+
+ if want := "OK\n"; string(got) != want {
t.Fatalf("expected %q, but got:\n%s", want, got)
}
}
func TestCgoExternalThreadSignal(t *testing.T) {
+ t.Parallel()
// issue 10139
switch runtime.GOOS {
case "plan9", "windows":
t.Skipf("no pthreads on %s", runtime.GOOS)
}
- got := runTestProg(t, "testprogcgo", "CgoExternalThreadSignal")
- want := "OK\n"
- if got != want {
+
+ exe, err := buildTestProg(t, "testprogcgo", "-tags=threadprof")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ got, err := testEnv(exec.Command(exe, "CgoExternalThreadSIGPROF")).CombinedOutput()
+ if err != nil {
+ t.Fatalf("exit status: %v\n%s", err, got)
+ }
+
+ want := []byte("OK\n")
+ if !bytes.Equal(got, want) {
t.Fatalf("expected %q, but got:\n%s", want, got)
}
}
@@ -130,6 +157,7 @@ func TestCgoDLLImports(t *testing.T) {
}
func TestCgoExecSignalMask(t *testing.T) {
+ t.Parallel()
// Test issue 13164.
switch runtime.GOOS {
case "windows", "plan9":
@@ -143,6 +171,7 @@ func TestCgoExecSignalMask(t *testing.T) {
}
func TestEnsureDropM(t *testing.T) {
+ t.Parallel()
// Test for issue 13881.
switch runtime.GOOS {
case "windows", "plan9":
@@ -159,6 +188,7 @@ func TestEnsureDropM(t *testing.T) {
// Test that the program that doesn't need any cgo pointer checking
// takes about the same amount of time with it as without it.
func TestCgoCheckBytes(t *testing.T) {
+ t.Parallel()
// Make sure we don't count the build time as part of the run time.
testenv.MustHaveGoBuild(t)
exe, err := buildTestProg(t, "testprogcgo")
@@ -198,6 +228,7 @@ func TestCgoCheckBytes(t *testing.T) {
}
func TestCgoPanicDeadlock(t *testing.T) {
+ t.Parallel()
// test issue 14432
got := runTestProg(t, "testprogcgo", "CgoPanicDeadlock")
want := "panic: cgo error\n\n"
@@ -207,6 +238,7 @@ func TestCgoPanicDeadlock(t *testing.T) {
}
func TestCgoCCodeSIGPROF(t *testing.T) {
+ t.Parallel()
got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
want := "OK\n"
if got != want {
@@ -215,6 +247,7 @@ func TestCgoCCodeSIGPROF(t *testing.T) {
}
func TestCgoCrashTraceback(t *testing.T) {
+ t.Parallel()
if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
}
@@ -227,6 +260,7 @@ func TestCgoCrashTraceback(t *testing.T) {
}
func TestCgoTracebackContext(t *testing.T) {
+ t.Parallel()
got := runTestProg(t, "testprogcgo", "TracebackContext")
want := "OK\n"
if got != want {
@@ -235,6 +269,7 @@ func TestCgoTracebackContext(t *testing.T) {
}
func testCgoPprof(t *testing.T, buildArg, runArg string) {
+ t.Parallel()
if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
}
@@ -252,7 +287,7 @@ func testCgoPprof(t *testing.T, buildArg, runArg string) {
fn := strings.TrimSpace(string(got))
defer os.Remove(fn)
- cmd := testEnv(exec.Command("go", "tool", "pprof", "-top", "-nodecount=1", exe, fn))
+ cmd := testEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-top", "-nodecount=1", exe, fn))
found := false
for i, e := range cmd.Env {
@@ -288,3 +323,65 @@ func TestCgoPprofPIE(t *testing.T) {
func TestCgoPprofThread(t *testing.T) {
testCgoPprof(t, "", "CgoPprofThread")
}
+
+func TestCgoPprofThreadNoTraceback(t *testing.T) {
+ testCgoPprof(t, "", "CgoPprofThreadNoTraceback")
+}
+
+func TestRaceProf(t *testing.T) {
+ if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
+ t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
+ }
+
+ testenv.MustHaveGoRun(t)
+
+ // This test requires building various packages with -race, so
+ // it's somewhat slow.
+ if testing.Short() {
+ t.Skip("skipping test in -short mode")
+ }
+
+ exe, err := buildTestProg(t, "testprogcgo", "-race")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ got, err := testEnv(exec.Command(exe, "CgoRaceprof")).CombinedOutput()
+ if err != nil {
+ t.Fatal(err)
+ }
+ want := "OK\n"
+ if string(got) != want {
+ t.Errorf("expected %q got %s", want, got)
+ }
+}
+
+func TestRaceSignal(t *testing.T) {
+ t.Parallel()
+ if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
+ t.Skipf("not yet supported on %s/%s", runtime.GOOS, runtime.GOARCH)
+ }
+
+ testenv.MustHaveGoRun(t)
+
+ // This test requires building various packages with -race, so
+ // it's somewhat slow.
+ if testing.Short() {
+ t.Skip("skipping test in -short mode")
+ }
+
+ exe, err := buildTestProg(t, "testprogcgo", "-race")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ got, err := testEnv(exec.Command(exe, "CgoRaceSignal")).CombinedOutput()
+ if err != nil {
+ t.Logf("%s\n", got)
+ t.Fatal(err)
+ }
+ want := "OK\n"
+ if string(got) != want {
+ t.Errorf("expected %q got %s", want, got)
+ }
+}
diff --git a/libgo/go/runtime/crash_test.go b/libgo/go/runtime/crash_test.go
index a2f7ff7dec8..9ec0ae468b7 100644
--- a/libgo/go/runtime/crash_test.go
+++ b/libgo/go/runtime/crash_test.go
@@ -6,6 +6,7 @@ package runtime_test
import (
"bytes"
+ "flag"
"fmt"
"internal/testenv"
"io/ioutil"
@@ -136,11 +137,10 @@ func buildTestProg(t *testing.T, binary string, flags ...string) (string, error)
}
exe := filepath.Join(testprog.dir, name+".exe")
- cmd := exec.Command("go", append([]string{"build", "-o", exe}, flags...)...)
+ cmd := exec.Command(testenv.GoToolPath(t), append([]string{"build", "-o", exe}, flags...)...)
cmd.Dir = "testdata/" + binary
out, err := testEnv(cmd).CombinedOutput()
if err != nil {
- exe = ""
target.err = fmt.Errorf("building %s %v: %v\n%s", binary, flags, err, out)
testprog.target[name] = target
return "", target.err
@@ -158,7 +158,7 @@ var (
func checkStaleRuntime(t *testing.T) {
staleRuntimeOnce.Do(func() {
// 'go run' uses the installed copy of runtime.a, which may be out of date.
- out, err := testEnv(exec.Command("go", "list", "-f", "{{.Stale}}", "runtime")).CombinedOutput()
+ out, err := testEnv(exec.Command(testenv.GoToolPath(t), "list", "-f", "{{.Stale}}", "runtime")).CombinedOutput()
if err != nil {
staleRuntimeErr = fmt.Errorf("failed to execute 'go list': %v\n%v", err, string(out))
return
@@ -401,6 +401,7 @@ func TestRecoverBeforePanicAfterGoexit(t *testing.T) {
}
func TestNetpollDeadlock(t *testing.T) {
+ t.Parallel()
output := runTestProg(t, "testprognet", "NetpollDeadlock")
want := "done\n"
if !strings.HasSuffix(output, want) {
@@ -409,6 +410,7 @@ func TestNetpollDeadlock(t *testing.T) {
}
func TestPanicTraceback(t *testing.T) {
+ t.Parallel()
output := runTestProg(t, "testprog", "PanicTraceback")
want := "panic: hello"
if !strings.HasPrefix(output, want) {
@@ -416,7 +418,7 @@ func TestPanicTraceback(t *testing.T) {
}
// Check functions in the traceback.
- fns := []string{"panic", "main.pt1.func1", "panic", "main.pt2.func1", "panic", "main.pt2", "main.pt1"}
+ fns := []string{"main.pt1.func1", "panic", "main.pt2.func1", "panic", "main.pt2", "main.pt1"}
for _, fn := range fns {
re := regexp.MustCompile(`(?m)^` + regexp.QuoteMeta(fn) + `\(.*\n`)
idx := re.FindStringIndex(output)
@@ -443,6 +445,13 @@ func TestPanicDeadlockSyscall(t *testing.T) {
testPanicDeadlock(t, "SyscallInPanic", "1\n2\npanic: 3\n\n")
}
+func TestPanicLoop(t *testing.T) {
+ output := runTestProg(t, "testprog", "PanicLoop")
+ if want := "panic while printing panic value"; !strings.Contains(output, want) {
+ t.Errorf("output does not contain %q:\n%s", want, output)
+ }
+}
+
func TestMemPprof(t *testing.T) {
testenv.MustHaveGoRun(t)
@@ -458,7 +467,7 @@ func TestMemPprof(t *testing.T) {
fn := strings.TrimSpace(string(got))
defer os.Remove(fn)
- cmd := testEnv(exec.Command("go", "tool", "pprof", "-alloc_space", "-top", exe, fn))
+ cmd := testEnv(exec.Command(testenv.GoToolPath(t), "tool", "pprof", "-alloc_space", "-top", exe, fn))
found := false
for i, e := range cmd.Env {
@@ -482,3 +491,39 @@ func TestMemPprof(t *testing.T) {
t.Error("missing MemProf in pprof output")
}
}
+
+var concurrentMapTest = flag.Bool("run_concurrent_map_tests", false, "also run flaky concurrent map tests")
+
+func TestConcurrentMapWrites(t *testing.T) {
+ if !*concurrentMapTest {
+ t.Skip("skipping without -run_concurrent_map_tests")
+ }
+ testenv.MustHaveGoRun(t)
+ output := runTestProg(t, "testprog", "concurrentMapWrites")
+ want := "fatal error: concurrent map writes"
+ if !strings.HasPrefix(output, want) {
+ t.Fatalf("output does not start with %q:\n%s", want, output)
+ }
+}
+func TestConcurrentMapReadWrite(t *testing.T) {
+ if !*concurrentMapTest {
+ t.Skip("skipping without -run_concurrent_map_tests")
+ }
+ testenv.MustHaveGoRun(t)
+ output := runTestProg(t, "testprog", "concurrentMapReadWrite")
+ want := "fatal error: concurrent map read and map write"
+ if !strings.HasPrefix(output, want) {
+ t.Fatalf("output does not start with %q:\n%s", want, output)
+ }
+}
+func TestConcurrentMapIterateWrite(t *testing.T) {
+ if !*concurrentMapTest {
+ t.Skip("skipping without -run_concurrent_map_tests")
+ }
+ testenv.MustHaveGoRun(t)
+ output := runTestProg(t, "testprog", "concurrentMapIterateWrite")
+ want := "fatal error: concurrent map iteration and map write"
+ if !strings.HasPrefix(output, want) {
+ t.Fatalf("output does not start with %q:\n%s", want, output)
+ }
+}
diff --git a/libgo/go/runtime/crash_unix_test.go b/libgo/go/runtime/crash_unix_test.go
index 6e4d04bd200..97deed8b9d9 100644
--- a/libgo/go/runtime/crash_unix_test.go
+++ b/libgo/go/runtime/crash_unix_test.go
@@ -37,6 +37,8 @@ func TestCrashDumpsAllThreads(t *testing.T) {
checkStaleRuntime(t)
+ t.Parallel()
+
dir, err := ioutil.TempDir("", "go-build")
if err != nil {
t.Fatalf("failed to create temp directory: %v", err)
@@ -47,7 +49,7 @@ func TestCrashDumpsAllThreads(t *testing.T) {
t.Fatalf("failed to create Go file: %v", err)
}
- cmd := exec.Command("go", "build", "-o", "a.exe")
+ cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "a.exe")
cmd.Dir = dir
out, err := testEnv(cmd).CombinedOutput()
if err != nil {
diff --git a/libgo/go/runtime/debug/garbage.go b/libgo/go/runtime/debug/garbage.go
index 81444971774..c82c024235b 100644
--- a/libgo/go/runtime/debug/garbage.go
+++ b/libgo/go/runtime/debug/garbage.go
@@ -71,7 +71,7 @@ func ReadGCStats(stats *GCStats) {
// See the allocation at the top of the function.
sorted := stats.Pause[n : n+n]
copy(sorted, stats.Pause)
- sort.Sort(byDuration(sorted))
+ sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] })
nq := len(stats.PauseQuantiles) - 1
for i := 0; i < nq; i++ {
stats.PauseQuantiles[i] = sorted[len(sorted)*i/nq]
@@ -81,12 +81,6 @@ func ReadGCStats(stats *GCStats) {
}
}
-type byDuration []time.Duration
-
-func (x byDuration) Len() int { return len(x) }
-func (x byDuration) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
-func (x byDuration) Less(i, j int) bool { return x[i] < x[j] }
-
// SetGCPercent sets the garbage collection target percentage:
// a collection is triggered when the ratio of freshly allocated data
// to live data remaining after the previous collection reaches this percentage.
diff --git a/libgo/go/runtime/debug/garbage_test.go b/libgo/go/runtime/debug/garbage_test.go
index 6ec94aa3fb9..04e954b1b1e 100644
--- a/libgo/go/runtime/debug/garbage_test.go
+++ b/libgo/go/runtime/debug/garbage_test.go
@@ -80,7 +80,7 @@ func TestReadGCStats(t *testing.T) {
for i := 0; i < n; i++ {
dt := stats.PauseEnd[i]
if dt.UnixNano() != int64(mstats.PauseEnd[off]) {
- t.Errorf("stats.PauseEnd[%d] = %d, want %d", i, dt, mstats.PauseEnd[off])
+ t.Errorf("stats.PauseEnd[%d] = %d, want %d", i, dt.UnixNano(), mstats.PauseEnd[off])
}
off = (off + len(mstats.PauseEnd) - 1) % len(mstats.PauseEnd)
}
@@ -89,10 +89,6 @@ func TestReadGCStats(t *testing.T) {
var big = make([]byte, 1<<20)
func TestFreeOSMemory(t *testing.T) {
- if runtime.GOARCH == "arm64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" ||
- runtime.GOOS == "nacl" {
- t.Skip("issue 9993; scavenger temporarily disabled on systems with physical pages larger than logical pages")
- }
var ms1, ms2 runtime.MemStats
if big == nil {
@@ -118,3 +114,16 @@ func TestSetGCPercent(t *testing.T) {
t.Errorf("SetGCPercent(123); SetGCPercent(x) = %d, want 123", new)
}
}
+
+func TestSetMaxThreadsOvf(t *testing.T) {
+ // Verify that a big threads count will not overflow the int32
+ // maxmcount variable, causing a panic (see Issue 16076).
+ //
+ // This can only happen when ints are 64 bits, since on platforms
+ // with 32 bit ints SetMaxThreads (which takes an int parameter)
+ // cannot be given anything that will overflow an int32.
+ //
+ // Call SetMaxThreads with 1<<31, but only on 64 bit systems.
+ nt := SetMaxThreads(1 << (30 + ^uint(0)>>63))
+ SetMaxThreads(nt) // restore previous value
+}
diff --git a/libgo/go/runtime/export_mmap_test.go b/libgo/go/runtime/export_mmap_test.go
index 7bde44dc430..6e05bb9fbb7 100644
--- a/libgo/go/runtime/export_mmap_test.go
+++ b/libgo/go/runtime/export_mmap_test.go
@@ -2,14 +2,19 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build ignore
-
// Export guts for testing.
package runtime
var Mmap = mmap
+var Munmap = munmap
+var Errno = errno
const ENOMEM = _ENOMEM
const MAP_ANON = _MAP_ANON
const MAP_PRIVATE = _MAP_PRIVATE
+const MAP_FIXED = _MAP_FIXED
+
+func GetPhysPageSize() uintptr {
+ return physPageSize
+}
diff --git a/libgo/go/runtime/export_test.go b/libgo/go/runtime/export_test.go
index 77b59000f32..fcc1e6199a4 100644
--- a/libgo/go/runtime/export_test.go
+++ b/libgo/go/runtime/export_test.go
@@ -8,6 +8,7 @@ package runtime
import (
"runtime/internal/atomic"
+ "runtime/internal/sys"
"unsafe"
)
@@ -30,6 +31,9 @@ var LockedOSThread = lockedOSThread
// var FuncPC = funcPC
+var Atoi = atoi
+var Atoi32 = atoi32
+
type LFNode struct {
Next uint64
Pushcnt uintptr
@@ -150,7 +154,11 @@ func RunSchedLocalQueueEmptyTest(iters int) {
//var Int64Hash = int64Hash
//var EfaceHash = efaceHash
//var IfaceHash = ifaceHash
-//var MemclrBytes = memclrBytes
+
+func MemclrBytes(b []byte) {
+ s := (*slice)(unsafe.Pointer(&b))
+ memclrNoHeapPointers(s.array, uintptr(s.len))
+}
var HashLoad = &hashLoad
@@ -160,10 +168,7 @@ var HashLoad = &hashLoad
// return
//}
-//var Gostringnocopy = gostringnocopy
-//var Maxstring = &maxstring
-
-//type Uintreg uintreg
+type Uintreg sys.Uintreg
var Open = open
var Close = closefd
@@ -207,9 +212,6 @@ func BenchSetType(n int, x interface{}) {
const PtrSize = sys.PtrSize
-var TestingAssertE2I2GC = &testingAssertE2I2GC
-var TestingAssertE2T2GC = &testingAssertE2T2GC
-
var ForceGCPeriod = &forcegcperiod
*/
@@ -230,7 +232,7 @@ func CountPagesInUse() (pagesInUse, counted uintptr) {
pagesInUse = uintptr(mheap_.pagesInUse)
- for _, s := range h_allspans {
+ for _, s := range mheap_.allspans {
if s.state == mSpanInUse {
counted += s.npages
}
diff --git a/libgo/go/runtime/extern.go b/libgo/go/runtime/extern.go
index c221b1d8109..5aa76ac8e2c 100644
--- a/libgo/go/runtime/extern.go
+++ b/libgo/go/runtime/extern.go
@@ -57,6 +57,11 @@ It is a comma-separated list of name=val pairs setting these named variables:
gcstackbarrierall: setting gcstackbarrierall=1 installs stack barriers
in every stack frame, rather than in exponentially-spaced frames.
+ gcrescanstacks: setting gcrescanstacks=1 enables stack
+ re-scanning during the STW mark termination phase. This is
+ helpful for debugging if objects are being prematurely
+ garbage collected.
+
gcstoptheworld: setting gcstoptheworld=1 disables concurrent garbage collection,
making every garbage collection a stop-the-world event. Setting gcstoptheworld=2
also disables concurrent sweeping after the garbage collection finishes.
diff --git a/libgo/go/runtime/fastlog2.go b/libgo/go/runtime/fastlog2.go
index 1029de2dbae..6fbe572f4a6 100644
--- a/libgo/go/runtime/fastlog2.go
+++ b/libgo/go/runtime/fastlog2.go
@@ -10,7 +10,7 @@ import "unsafe"
// fastlog2 implements a fast approximation to the base 2 log of a
// float64. This is used to compute a geometric distribution for heap
-// sampling, without introducing dependences into package math. This
+// sampling, without introducing dependencies into package math. This
// uses a very rough approximation using the float64 exponent and the
// first 25 bits of the mantissa. The top 5 bits of the mantissa are
// used to load limits from a table of constants and the rest are used
@@ -31,5 +31,5 @@ func fastlog2(x float64) float64 {
}
// float64bits returns the IEEE 754 binary representation of f.
-// Taken from math.Float64bits to avoid dependences into package math.
+// Taken from math.Float64bits to avoid dependencies into package math.
func float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) }
diff --git a/libgo/go/runtime/gc_test.go b/libgo/go/runtime/gc_test.go
index 11035c321ab..2a6acf0836e 100644
--- a/libgo/go/runtime/gc_test.go
+++ b/libgo/go/runtime/gc_test.go
@@ -400,39 +400,6 @@ func TestPrintGC(t *testing.T) {
close(done)
}
-/*
-
-// The implicit y, ok := x.(error) for the case error
-// in testTypeSwitch used to not initialize the result y
-// before passing &y to assertE2I2GC.
-// Catch this by making assertE2I2 call runtime.GC,
-// which will force a stack scan and failure if there are
-// bad pointers, and then fill the stack with bad pointers
-// and run the type switch.
-func TestAssertE2I2Liveness(t *testing.T) {
- // Note that this flag is defined in export_test.go
- // and is not available to ordinary imports of runtime.
- *runtime.TestingAssertE2I2GC = true
- defer func() {
- *runtime.TestingAssertE2I2GC = false
- }()
-
- poisonStack()
- testTypeSwitch(io.EOF)
- poisonStack()
- testAssert(io.EOF)
- poisonStack()
- testAssertVar(io.EOF)
-}
-
-func poisonStack() uintptr {
- var x [1000]uintptr
- for i := range x {
- x[i] = 0xff
- }
- return x[123]
-}
-
func testTypeSwitch(x interface{}) error {
switch y := x.(type) {
case nil:
@@ -458,16 +425,6 @@ func testAssertVar(x interface{}) error {
return nil
}
-func TestAssertE2T2Liveness(t *testing.T) {
- *runtime.TestingAssertE2T2GC = true
- defer func() {
- *runtime.TestingAssertE2T2GC = false
- }()
-
- poisonStack()
- testIfaceEqual(io.EOF)
-}
-
var a bool
//go:noinline
@@ -477,6 +434,8 @@ func testIfaceEqual(x interface{}) {
}
}
+/*
+
func TestPageAccounting(t *testing.T) {
// Grow the heap in small increments. This used to drop the
// pages-in-use count below zero because of a rounding
diff --git a/libgo/go/runtime/gcinfo_test.go b/libgo/go/runtime/gcinfo_test.go
index 2253d93a0ac..4ac67dc4be2 100644
--- a/libgo/go/runtime/gcinfo_test.go
+++ b/libgo/go/runtime/gcinfo_test.go
@@ -125,7 +125,7 @@ type BigStruct struct {
func infoBigStruct() []byte {
switch runtime.GOARCH {
- case "386", "arm":
+ case "386", "arm", "mips", "mipsle":
return []byte{
typePointer, // q *int
typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte
diff --git a/libgo/go/runtime/hashmap.go b/libgo/go/runtime/hashmap.go
index 77b33f341f7..5b191d45752 100644
--- a/libgo/go/runtime/hashmap.go
+++ b/libgo/go/runtime/hashmap.go
@@ -67,7 +67,7 @@ import (
//go:linkname mapaccess2 runtime.mapaccess2
//go:linkname mapaccess1_fat runtime.mapaccess1_fat
//go:linkname mapaccess2_fat runtime.mapaccess2_fat
-//go:linkname mapassign1 runtime.mapassign1
+//go:linkname mapassign runtime.mapassign
//go:linkname mapdelete runtime.mapdelete
//go:linkname mapiterinit runtime.mapiterinit
//go:linkname mapiternext runtime.mapiternext
@@ -106,9 +106,10 @@ const (
minTopHash = 4 // minimum tophash for a normal filled cell.
// flags
- iterator = 1 // there may be an iterator using buckets
- oldIterator = 2 // there may be an iterator using oldbuckets
- hashWriting = 4 // a goroutine is writing to the map
+ iterator = 1 // there may be an iterator using buckets
+ oldIterator = 2 // there may be an iterator using oldbuckets
+ hashWriting = 4 // a goroutine is writing to the map
+ sameSizeGrow = 8 // the current map growth is to a new map of the same size
// sentinel bucket ID for iterator checks
noCheck = 1<<(8*sys.PtrSize) - 1
@@ -118,10 +119,11 @@ const (
type hmap struct {
// Note: the format of the Hmap is encoded in ../../cmd/internal/gc/reflect.go and
// ../reflect/type.go. Don't change this structure without also changing that code!
- count int // # live cells == size of map. Must be first (used by len() builtin)
- flags uint8
- B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
- hash0 uint32 // hash seed
+ count int // # live cells == size of map. Must be first (used by len() builtin)
+ flags uint8
+ B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
+ noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
+ hash0 uint32 // hash seed
buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
@@ -141,6 +143,9 @@ type hmap struct {
// A bucket for a Go map.
type bmap struct {
+ // tophash generally contains the top byte of the hash value
+ // for each key in this bucket. If tophash[0] < minTopHash,
+ // tophash[0] is a bucket evacuation state instead.
tophash [bucketCnt]uint8
// Followed by bucketCnt keys and then bucketCnt values.
// NOTE: packing all the keys together and then all the values together makes the
@@ -178,7 +183,34 @@ func (b *bmap) overflow(t *maptype) *bmap {
return *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-sys.PtrSize))
}
+// incrnoverflow increments h.noverflow.
+// noverflow counts the number of overflow buckets.
+// This is used to trigger same-size map growth.
+// See also tooManyOverflowBuckets.
+// To keep hmap small, noverflow is a uint16.
+// When there are few buckets, noverflow is an exact count.
+// When there are many buckets, noverflow is an approximate count.
+func (h *hmap) incrnoverflow() {
+ // We trigger same-size map growth if there are
+ // as many overflow buckets as buckets.
+ // We need to be able to count to 1<<h.B.
+ if h.B < 16 {
+ h.noverflow++
+ return
+ }
+ // Increment with probability 1/(1<<(h.B-15)).
+ // When we reach 1<<15 - 1, we will have approximately
+ // as many overflow buckets as buckets.
+ mask := uint32(1)<<(h.B-15) - 1
+ // Example: if h.B == 18, then mask == 7,
+ // and fastrand & 7 == 0 with probability 1/8.
+ if fastrand()&mask == 0 {
+ h.noverflow++
+ }
+}
+
func (h *hmap) setoverflow(t *maptype, b, ovf *bmap) {
+ h.incrnoverflow()
if t.bucket.kind&kindNoPointers != 0 {
h.createOverflow()
*h.overflow[0] = append(*h.overflow[0], ovf)
@@ -251,7 +283,7 @@ func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap {
// find size parameter which will hold the requested # of elements
B := uint8(0)
- for ; hint > bucketCnt && float32(hint) > loadFactor*float32(uintptr(1)<<B); B++ {
+ for ; overLoadFactor(hint, B); B++ {
}
// allocate initial hash table
@@ -269,10 +301,11 @@ func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap {
h.count = 0
h.B = B
h.flags = 0
- h.hash0 = fastrand1()
+ h.hash0 = fastrand()
h.buckets = buckets
h.oldbuckets = nil
h.nevacuate = 0
+ h.noverflow = 0
return h
}
@@ -304,7 +337,11 @@ func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
m := uintptr(1)<<h.B - 1
b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
if c := h.oldbuckets; c != nil {
- oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !h.sameSizeGrow() {
+ // There used to be half as many buckets; mask down one more power of two.
+ m >>= 1
+ }
+ oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize)))
if !evacuated(oldb) {
b = oldb
}
@@ -359,7 +396,11 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool)
m := uintptr(1)<<h.B - 1
b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + (hash&m)*uintptr(t.bucketsize)))
if c := h.oldbuckets; c != nil {
- oldb := (*bmap)(unsafe.Pointer(uintptr(c) + (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !h.sameSizeGrow() {
+ // There used to be half as many buckets; mask down one more power of two.
+ m >>= 1
+ }
+ oldb := (*bmap)(unsafe.Pointer(uintptr(c) + (hash&m)*uintptr(t.bucketsize)))
if !evacuated(oldb) {
b = oldb
}
@@ -397,16 +438,17 @@ func mapaccessK(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, unsafe
if h == nil || h.count == 0 {
return nil, nil
}
- if h.flags&hashWriting != 0 {
- throw("concurrent map read and map write")
- }
hashfn := t.key.hashfn
equalfn := t.key.equalfn
hash := hashfn(key, uintptr(h.hash0))
m := uintptr(1)<<h.B - 1
b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + (hash&m)*uintptr(t.bucketsize)))
if c := h.oldbuckets; c != nil {
- oldb := (*bmap)(unsafe.Pointer(uintptr(c) + (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !h.sameSizeGrow() {
+ // There used to be half as many buckets; mask down one more power of two.
+ m >>= 1
+ }
+ oldb := (*bmap)(unsafe.Pointer(uintptr(c) + (hash&m)*uintptr(t.bucketsize)))
if !evacuated(oldb) {
b = oldb
}
@@ -455,20 +497,19 @@ func mapaccess2_fat(t *maptype, h *hmap, key, zero unsafe.Pointer) (unsafe.Point
return v, true
}
-func mapassign1(t *maptype, h *hmap, key unsafe.Pointer, val unsafe.Pointer) {
+// Like mapaccess, but allocates a slot for the key if it is not present in the map.
+func mapassign(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
if h == nil {
panic(plainError("assignment to entry in nil map"))
}
if raceenabled {
callerpc := getcallerpc(unsafe.Pointer( /* &t */ nil))
- pc := funcPC(mapassign1)
+ pc := funcPC(mapassign)
racewritepc(unsafe.Pointer(h), callerpc, pc)
raceReadObjectPC(t.key, key, callerpc, pc)
- raceReadObjectPC(t.elem, val, callerpc, pc)
}
if msanenabled {
msanread(key, t.key.size)
- msanread(val, t.elem.size)
}
if h.flags&hashWriting != 0 {
throw("concurrent map writes")
@@ -485,7 +526,7 @@ func mapassign1(t *maptype, h *hmap, key unsafe.Pointer, val unsafe.Pointer) {
again:
bucket := hash & (uintptr(1)<<h.B - 1)
- if h.oldbuckets != nil {
+ if h.growing() {
growWork(t, h, bucket)
}
b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
@@ -496,35 +537,29 @@ again:
var inserti *uint8
var insertk unsafe.Pointer
- var insertv unsafe.Pointer
+ var val unsafe.Pointer
for {
for i := uintptr(0); i < bucketCnt; i++ {
if b.tophash[i] != top {
if b.tophash[i] == empty && inserti == nil {
inserti = &b.tophash[i]
insertk = add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
- insertv = add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
+ val = add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
}
continue
}
k := add(unsafe.Pointer(b), dataOffset+i*uintptr(t.keysize))
- k2 := k
if t.indirectkey {
- k2 = *((*unsafe.Pointer)(k2))
+ k = *((*unsafe.Pointer)(k))
}
- if !equalfn(key, k2) {
+ if !equalfn(key, k) {
continue
}
// already have a mapping for key. Update it.
if t.needkeyupdate {
- typedmemmove(t.key, k2, key)
+ typedmemmove(t.key, k, key)
}
- v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
- v2 := v
- if t.indirectvalue {
- v2 = *((*unsafe.Pointer)(v2))
- }
- typedmemmove(t.elem, v2, val)
+ val = add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
goto done
}
ovf := b.overflow(t)
@@ -534,8 +569,11 @@ again:
b = ovf
}
- // did not find mapping for key. Allocate new cell & add entry.
- if float32(h.count) >= loadFactor*float32((uintptr(1)<<h.B)) && h.count >= bucketCnt {
+ // Did not find mapping for key. Allocate new cell & add entry.
+
+ // If we hit the max load factor or we have too many overflow buckets,
+ // and we're not already in the middle of growing, start growing.
+ if !h.growing() && (overLoadFactor(int64(h.count), h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
hashGrow(t, h)
goto again // Growing the table invalidates everything, so try again
}
@@ -546,7 +584,7 @@ again:
h.setoverflow(t, b, newb)
inserti = &newb.tophash[0]
insertk = add(unsafe.Pointer(newb), dataOffset)
- insertv = add(insertk, bucketCnt*uintptr(t.keysize))
+ val = add(insertk, bucketCnt*uintptr(t.keysize))
}
// store new key/value at insert position
@@ -557,11 +595,9 @@ again:
}
if t.indirectvalue {
vmem := newobject(t.elem)
- *(*unsafe.Pointer)(insertv) = vmem
- insertv = vmem
+ *(*unsafe.Pointer)(val) = vmem
}
typedmemmove(t.key, insertk, key)
- typedmemmove(t.elem, insertv, val)
*inserti = top
h.count++
@@ -570,6 +606,10 @@ done:
throw("concurrent map writes")
}
h.flags &^= hashWriting
+ if t.indirectvalue {
+ val = *((*unsafe.Pointer)(val))
+ }
+ return val
}
func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
@@ -594,7 +634,7 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
equalfn := t.key.equalfn
hash := hashfn(key, uintptr(h.hash0))
bucket := hash & (uintptr(1)<<h.B - 1)
- if h.oldbuckets != nil {
+ if h.growing() {
growWork(t, h, bucket)
}
b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
@@ -615,9 +655,17 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
if !equalfn(key, k2) {
continue
}
- memclr(k, uintptr(t.keysize))
+ if t.indirectkey {
+ *(*unsafe.Pointer)(k) = nil
+ } else {
+ typedmemclr(t.key, k)
+ }
v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*uintptr(t.keysize) + i*uintptr(t.valuesize))
- memclr(v, uintptr(t.valuesize))
+ if t.indirectvalue {
+ *(*unsafe.Pointer)(v) = nil
+ } else {
+ typedmemclr(t.elem, v)
+ }
b.tophash[i] = empty
h.count--
goto done
@@ -676,9 +724,9 @@ func mapiterinit(t *maptype, h *hmap, it *hiter) {
}
// decide where to start
- r := uintptr(fastrand1())
+ r := uintptr(fastrand())
if h.B > 31-bucketCntBits {
- r += uintptr(fastrand1()) << 31
+ r += uintptr(fastrand()) << 31
}
it.startBucket = r & (uintptr(1)<<h.B - 1)
it.offset = uint8(r >> h.B & (bucketCnt - 1))
@@ -703,6 +751,9 @@ func mapiternext(it *hiter) {
callerpc := getcallerpc(unsafe.Pointer( /* &it */ nil))
racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapiternext))
}
+ if h.flags&hashWriting != 0 {
+ throw("concurrent map iteration and map write")
+ }
t := it.t
bucket := it.bucket
b := it.bptr
@@ -719,12 +770,12 @@ next:
it.value = nil
return
}
- if h.oldbuckets != nil && it.B == h.B {
+ if h.growing() && it.B == h.B {
// Iterator was started in the middle of a grow, and the grow isn't done yet.
// If the bucket we're looking at hasn't been filled in yet (i.e. the old
// bucket hasn't been evacuated) then we need to iterate through the old
// bucket and only return the ones that will be migrated to this bucket.
- oldbucket := bucket & (uintptr(1)<<(it.B-1) - 1)
+ oldbucket := bucket & it.h.oldbucketmask()
b = (*bmap)(add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)))
if !evacuated(b) {
checkBucket = bucket
@@ -748,9 +799,9 @@ next:
k := add(unsafe.Pointer(b), dataOffset+uintptr(offi)*uintptr(t.keysize))
v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+uintptr(offi)*uintptr(t.valuesize))
if b.tophash[offi] != empty && b.tophash[offi] != evacuatedEmpty {
- if checkBucket != noCheck {
- // Special case: iterator was started during a grow and the
- // grow is not done yet. We're working on a bucket whose
+ if checkBucket != noCheck && !h.sameSizeGrow() {
+ // Special case: iterator was started during a grow to a larger size
+ // and the grow is not done yet. We're working on a bucket whose
// oldbucket has not been evacuated yet. Or at least, it wasn't
// evacuated when we started the bucket. So we're iterating
// through the oldbucket, skipping any keys that will go
@@ -836,21 +887,27 @@ next:
}
func hashGrow(t *maptype, h *hmap) {
- if h.oldbuckets != nil {
- throw("evacuation not done in time")
+ // If we've hit the load factor, get bigger.
+ // Otherwise, there are too many overflow buckets,
+ // so keep the same number of buckets and "grow" laterally.
+ bigger := uint8(1)
+ if !overLoadFactor(int64(h.count), h.B) {
+ bigger = 0
+ h.flags |= sameSizeGrow
}
oldbuckets := h.buckets
- newbuckets := newarray(t.bucket, 1<<(h.B+1))
+ newbuckets := newarray(t.bucket, 1<<(h.B+bigger))
flags := h.flags &^ (iterator | oldIterator)
if h.flags&iterator != 0 {
flags |= oldIterator
}
// commit the grow (atomic wrt gc)
- h.B++
+ h.B += bigger
h.flags = flags
h.oldbuckets = oldbuckets
h.buckets = newbuckets
h.nevacuate = 0
+ h.noverflow = 0
if h.overflow != nil {
// Promote current overflow buckets to the old generation.
@@ -865,36 +922,88 @@ func hashGrow(t *maptype, h *hmap) {
// by growWork() and evacuate().
}
-func growWork(t *maptype, h *hmap, bucket uintptr) {
- noldbuckets := uintptr(1) << (h.B - 1)
+// overLoadFactor reports whether count items placed in 1<<B buckets is over loadFactor.
+func overLoadFactor(count int64, B uint8) bool {
+ // TODO: rewrite to use integer math and comparison?
+ return count >= bucketCnt && float32(count) >= loadFactor*float32((uintptr(1)<<B))
+}
+
+// tooManyOverflowBuckets reports whether noverflow buckets is too many for a map with 1<<B buckets.
+// Note that most of these overflow buckets must be in sparse use;
+// if use was dense, then we'd have already triggered regular map growth.
+func tooManyOverflowBuckets(noverflow uint16, B uint8) bool {
+ // If the threshold is too low, we do extraneous work.
+ // If the threshold is too high, maps that grow and shrink can hold on to lots of unused memory.
+ // "too many" means (approximately) as many overflow buckets as regular buckets.
+ // See incrnoverflow for more details.
+ if B < 16 {
+ return noverflow >= uint16(1)<<B
+ }
+ return noverflow >= 1<<15
+}
+
+// growing reports whether h is growing. The growth may be to the same size or bigger.
+func (h *hmap) growing() bool {
+ return h.oldbuckets != nil
+}
+
+// sameSizeGrow reports whether the current growth is to a map of the same size.
+func (h *hmap) sameSizeGrow() bool {
+ return h.flags&sameSizeGrow != 0
+}
+
+// noldbuckets calculates the number of buckets prior to the current map growth.
+func (h *hmap) noldbuckets() uintptr {
+ oldB := h.B
+ if !h.sameSizeGrow() {
+ oldB--
+ }
+ return uintptr(1) << oldB
+}
+
+// oldbucketmask provides a mask that can be applied to calculate n % noldbuckets().
+func (h *hmap) oldbucketmask() uintptr {
+ return h.noldbuckets() - 1
+}
+func growWork(t *maptype, h *hmap, bucket uintptr) {
// make sure we evacuate the oldbucket corresponding
// to the bucket we're about to use
- evacuate(t, h, bucket&(noldbuckets-1))
+ evacuate(t, h, bucket&h.oldbucketmask())
// evacuate one more oldbucket to make progress on growing
- if h.oldbuckets != nil {
+ if h.growing() {
evacuate(t, h, h.nevacuate)
}
}
func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
b := (*bmap)(add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)))
- newbit := uintptr(1) << (h.B - 1)
+ newbit := h.noldbuckets()
hashfn := t.key.hashfn
equalfn := t.key.equalfn
if !evacuated(b) {
// TODO: reuse overflow buckets instead of using new ones, if there
// is no iterator using the old buckets. (If !oldIterator.)
- x := (*bmap)(add(h.buckets, oldbucket*uintptr(t.bucketsize)))
- y := (*bmap)(add(h.buckets, (oldbucket+newbit)*uintptr(t.bucketsize)))
- xi := 0
- yi := 0
- xk := add(unsafe.Pointer(x), dataOffset)
- yk := add(unsafe.Pointer(y), dataOffset)
- xv := add(xk, bucketCnt*uintptr(t.keysize))
- yv := add(yk, bucketCnt*uintptr(t.keysize))
+ var (
+ x, y *bmap // current low/high buckets in new map
+ xi, yi int // key/val indices into x and y
+ xk, yk unsafe.Pointer // pointers to current x and y key storage
+ xv, yv unsafe.Pointer // pointers to current x and y value storage
+ )
+ x = (*bmap)(add(h.buckets, oldbucket*uintptr(t.bucketsize)))
+ xi = 0
+ xk = add(unsafe.Pointer(x), dataOffset)
+ xv = add(xk, bucketCnt*uintptr(t.keysize))
+ if !h.sameSizeGrow() {
+ // Only calculate y pointers if we're growing bigger.
+ // Otherwise GC can see bad pointers.
+ y = (*bmap)(add(h.buckets, (oldbucket+newbit)*uintptr(t.bucketsize)))
+ yi = 0
+ yk = add(unsafe.Pointer(y), dataOffset)
+ yv = add(yk, bucketCnt*uintptr(t.keysize))
+ }
for ; b != nil; b = b.overflow(t) {
k := add(unsafe.Pointer(b), dataOffset)
v := add(k, bucketCnt*uintptr(t.keysize))
@@ -911,34 +1020,38 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
if t.indirectkey {
k2 = *((*unsafe.Pointer)(k2))
}
- // Compute hash to make our evacuation decision (whether we need
- // to send this key/value to bucket x or bucket y).
- hash := hashfn(k2, uintptr(h.hash0))
- if h.flags&iterator != 0 {
- if !t.reflexivekey && !equalfn(k2, k2) {
- // If key != key (NaNs), then the hash could be (and probably
- // will be) entirely different from the old hash. Moreover,
- // it isn't reproducible. Reproducibility is required in the
- // presence of iterators, as our evacuation decision must
- // match whatever decision the iterator made.
- // Fortunately, we have the freedom to send these keys either
- // way. Also, tophash is meaningless for these kinds of keys.
- // We let the low bit of tophash drive the evacuation decision.
- // We recompute a new random tophash for the next level so
- // these keys will get evenly distributed across all buckets
- // after multiple grows.
- if (top & 1) != 0 {
- hash |= newbit
- } else {
- hash &^= newbit
- }
- top = uint8(hash >> (sys.PtrSize*8 - 8))
- if top < minTopHash {
- top += minTopHash
+ useX := true
+ if !h.sameSizeGrow() {
+ // Compute hash to make our evacuation decision (whether we need
+ // to send this key/value to bucket x or bucket y).
+ hash := hashfn(k2, uintptr(h.hash0))
+ if h.flags&iterator != 0 {
+ if !t.reflexivekey && !equalfn(k2, k2) {
+ // If key != key (NaNs), then the hash could be (and probably
+ // will be) entirely different from the old hash. Moreover,
+ // it isn't reproducible. Reproducibility is required in the
+ // presence of iterators, as our evacuation decision must
+ // match whatever decision the iterator made.
+ // Fortunately, we have the freedom to send these keys either
+ // way. Also, tophash is meaningless for these kinds of keys.
+ // We let the low bit of tophash drive the evacuation decision.
+ // We recompute a new random tophash for the next level so
+ // these keys will get evenly distributed across all buckets
+ // after multiple grows.
+ if top&1 != 0 {
+ hash |= newbit
+ } else {
+ hash &^= newbit
+ }
+ top = uint8(hash >> (sys.PtrSize*8 - 8))
+ if top < minTopHash {
+ top += minTopHash
+ }
}
}
+ useX = hash&newbit == 0
}
- if (hash & newbit) == 0 {
+ if useX {
b.tophash[i] = evacuatedX
if xi == bucketCnt {
newx := (*bmap)(newobject(t.bucket))
@@ -992,7 +1105,13 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
// Unlink the overflow buckets & clear key/value to help GC.
if h.flags&oldIterator == 0 {
b = (*bmap)(add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)))
- memclr(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset)
+ // Preserve b.tophash because the evacuation
+ // state is maintained there.
+ if t.bucket.kind&kindNoPointers == 0 {
+ memclrHasPointers(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset)
+ } else {
+ memclrNoHeapPointers(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset)
+ }
}
}
@@ -1008,6 +1127,7 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
if h.overflow != nil {
h.overflow[1] = nil
}
+ h.flags &^= sameSizeGrow
}
}
}
@@ -1035,7 +1155,8 @@ func reflect_mapaccess(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
//go:linkname reflect_mapassign reflect.mapassign
func reflect_mapassign(t *maptype, h *hmap, key unsafe.Pointer, val unsafe.Pointer) {
- mapassign1(t, h, key, val)
+ p := mapassign(t, h, key)
+ typedmemmove(t.elem, p, val)
}
//go:linkname reflect_mapdelete reflect.mapdelete
diff --git a/libgo/go/runtime/hashmap_fast.go b/libgo/go/runtime/hashmap_fast.go
index c6cad9dc8c9..853da70e966 100644
--- a/libgo/go/runtime/hashmap_fast.go
+++ b/libgo/go/runtime/hashmap_fast.go
@@ -29,7 +29,11 @@ func mapaccess1_fast32(t *maptype, h *hmap, key uint32) unsafe.Pointer {
m := uintptr(1)<<h.B - 1
b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
if c := h.oldbuckets; c != nil {
- oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !h.sameSizeGrow() {
+ // There used to be half as many buckets; mask down one more power of two.
+ m >>= 1
+ }
+ oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize)))
if !evacuated(oldb) {
b = oldb
}
@@ -74,7 +78,11 @@ func mapaccess2_fast32(t *maptype, h *hmap, key uint32) (unsafe.Pointer, bool) {
m := uintptr(1)<<h.B - 1
b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
if c := h.oldbuckets; c != nil {
- oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !h.sameSizeGrow() {
+ // There used to be half as many buckets; mask down one more power of two.
+ m >>= 1
+ }
+ oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize)))
if !evacuated(oldb) {
b = oldb
}
@@ -119,7 +127,11 @@ func mapaccess1_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
m := uintptr(1)<<h.B - 1
b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
if c := h.oldbuckets; c != nil {
- oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !h.sameSizeGrow() {
+ // There used to be half as many buckets; mask down one more power of two.
+ m >>= 1
+ }
+ oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize)))
if !evacuated(oldb) {
b = oldb
}
@@ -164,7 +176,11 @@ func mapaccess2_fast64(t *maptype, h *hmap, key uint64) (unsafe.Pointer, bool) {
m := uintptr(1)<<h.B - 1
b = (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
if c := h.oldbuckets; c != nil {
- oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !h.sameSizeGrow() {
+ // There used to be half as many buckets; mask down one more power of two.
+ m >>= 1
+ }
+ oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize)))
if !evacuated(oldb) {
b = oldb
}
@@ -264,7 +280,11 @@ dohash:
m := uintptr(1)<<h.B - 1
b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
if c := h.oldbuckets; c != nil {
- oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !h.sameSizeGrow() {
+ // There used to be half as many buckets; mask down one more power of two.
+ m >>= 1
+ }
+ oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize)))
if !evacuated(oldb) {
b = oldb
}
@@ -367,7 +387,11 @@ dohash:
m := uintptr(1)<<h.B - 1
b := (*bmap)(add(h.buckets, (hash&m)*uintptr(t.bucketsize)))
if c := h.oldbuckets; c != nil {
- oldb := (*bmap)(add(c, (hash&(m>>1))*uintptr(t.bucketsize)))
+ if !h.sameSizeGrow() {
+ // There used to be half as many buckets; mask down one more power of two.
+ m >>= 1
+ }
+ oldb := (*bmap)(add(c, (hash&m)*uintptr(t.bucketsize)))
if !evacuated(oldb) {
b = oldb
}
diff --git a/libgo/go/runtime/iface.go b/libgo/go/runtime/iface.go
index 5274734ba8f..62d47ce68a0 100644
--- a/libgo/go/runtime/iface.go
+++ b/libgo/go/runtime/iface.go
@@ -261,7 +261,7 @@ func ifaceI2T2P(t *_type, i iface) (unsafe.Pointer, bool) {
// Convert an empty interface to a non-pointer non-interface type.
func ifaceE2T2(t *_type, e eface, ret unsafe.Pointer) bool {
if !eqtype(t, e._type) {
- memclr(ret, t.size)
+ typedmemclr(t, ret)
return false
} else {
typedmemmove(t, ret, e.data)
@@ -272,7 +272,7 @@ func ifaceE2T2(t *_type, e eface, ret unsafe.Pointer) bool {
// Convert a non-empty interface to a non-pointer non-interface type.
func ifaceI2T2(t *_type, i iface, ret unsafe.Pointer) bool {
if i.tab == nil || !eqtype(t, *(**_type)(i.tab)) {
- memclr(ret, t.size)
+ typedmemclr(t, ret)
return false
} else {
typedmemmove(t, ret, i.data)
diff --git a/libgo/go/runtime/internal/atomic/atomic.c b/libgo/go/runtime/internal/atomic/atomic.c
index 3393fbef44e..b584656f817 100644
--- a/libgo/go/runtime/internal/atomic/atomic.c
+++ b/libgo/go/runtime/internal/atomic/atomic.c
@@ -33,6 +33,8 @@ uint64_t Load64 (uint64_t *ptr)
uint64_t
Load64 (uint64_t *ptr)
{
+ if (((uintptr_t) ptr & 7) != 0)
+ ptr = NULL;
return __atomic_load_n (ptr, __ATOMIC_ACQUIRE);
}
@@ -63,6 +65,8 @@ int64_t Loadint64 (int64_t *ptr)
int64_t
Loadint64 (int64_t *ptr)
{
+ if (((uintptr_t) ptr & 7) != 0)
+ ptr = NULL;
return __atomic_load_n (ptr, __ATOMIC_ACQUIRE);
}
@@ -83,6 +87,8 @@ uint64_t Xadd64 (uint64_t *ptr, int64_t delta)
uint64_t
Xadd64 (uint64_t *ptr, int64_t delta)
{
+ if (((uintptr_t) ptr & 7) != 0)
+ ptr = NULL;
return __atomic_add_fetch (ptr, (uint64_t) delta, __ATOMIC_SEQ_CST);
}
@@ -103,6 +109,8 @@ int64_t Xaddint64 (int64_t *ptr, int64_t delta)
int64_t
Xaddint64 (int64_t *ptr, int64_t delta)
{
+ if (((uintptr_t) ptr & 7) != 0)
+ ptr = NULL;
return __atomic_add_fetch (ptr, delta, __ATOMIC_SEQ_CST);
}
@@ -123,6 +131,8 @@ uint64_t Xchg64 (uint64_t *ptr, uint64_t new)
uint64_t
Xchg64 (uint64_t *ptr, uint64_t new)
{
+ if (((uintptr_t) ptr & 7) != 0)
+ ptr = NULL;
return __atomic_exchange_n (ptr, new, __ATOMIC_SEQ_CST);
}
@@ -173,6 +183,8 @@ _Bool Cas64 (uint64_t *ptr, uint64_t old, uint64_t new)
_Bool
Cas64 (uint64_t *ptr, uint64_t old, uint64_t new)
{
+ if (((uintptr_t) ptr & 7) != 0)
+ ptr = NULL;
return __atomic_compare_exchange_n (ptr, &old, new, false, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
}
@@ -213,6 +225,8 @@ void Store64 (uint64_t *ptr, uint64_t val)
void
Store64 (uint64_t *ptr, uint64_t val)
{
+ if (((uintptr_t) ptr & 7) != 0)
+ ptr = NULL;
__atomic_store_n (ptr, val, __ATOMIC_SEQ_CST);
}
diff --git a/libgo/go/runtime/internal/atomic/atomic_test.go b/libgo/go/runtime/internal/atomic/atomic_test.go
index d5dc552b952..879a82f9c82 100644
--- a/libgo/go/runtime/internal/atomic/atomic_test.go
+++ b/libgo/go/runtime/internal/atomic/atomic_test.go
@@ -7,6 +7,7 @@ package atomic_test
import (
"runtime"
"runtime/internal/atomic"
+ "runtime/internal/sys"
"testing"
"unsafe"
)
@@ -51,13 +52,13 @@ func TestXadduintptr(t *testing.T) {
// Tests that xadduintptr correctly updates 64-bit values. The place where
// we actually do so is mstats.go, functions mSysStat{Inc,Dec}.
func TestXadduintptrOnUint64(t *testing.T) {
- /* if runtime.BigEndian != 0 {
+ if sys.BigEndian != 0 {
// On big endian architectures, we never use xadduintptr to update
// 64-bit values and hence we skip the test. (Note that functions
// mSysStat{Inc,Dec} in mstats.go have explicit checks for
// big-endianness.)
- return
- }*/
+ t.Skip("skip xadduintptr on big endian architecture")
+ }
const inc = 100
val := uint64(0)
atomic.Xadduintptr((*uintptr)(unsafe.Pointer(&val)), inc)
@@ -65,3 +66,40 @@ func TestXadduintptrOnUint64(t *testing.T) {
t.Fatalf("xadduintptr should increase lower-order bits, want %d, got %d", inc, val)
}
}
+
+func shouldPanic(t *testing.T, name string, f func()) {
+ defer func() {
+ if recover() == nil {
+ t.Errorf("%s did not panic", name)
+ }
+ }()
+ f()
+}
+
+// Variant of sync/atomic's TestUnaligned64:
+func TestUnaligned64(t *testing.T) {
+ // Unaligned 64-bit atomics on 32-bit systems are
+ // a continual source of pain. Test that on 32-bit systems they crash
+ // instead of failing silently.
+
+ switch runtime.GOARCH {
+ default:
+ if unsafe.Sizeof(int(0)) != 4 {
+ t.Skip("test only runs on 32-bit systems")
+ }
+ case "amd64p32":
+ // amd64p32 can handle unaligned atomics.
+ t.Skipf("test not needed on %v", runtime.GOARCH)
+ }
+
+ x := make([]uint32, 4)
+ up64 := (*uint64)(unsafe.Pointer(&x[1])) // misaligned
+ p64 := (*int64)(unsafe.Pointer(&x[1])) // misaligned
+
+ shouldPanic(t, "Load64", func() { atomic.Load64(up64) })
+ shouldPanic(t, "Loadint64", func() { atomic.Loadint64(p64) })
+ shouldPanic(t, "Store64", func() { atomic.Store64(up64, 0) })
+ shouldPanic(t, "Xadd64", func() { atomic.Xadd64(up64, 1) })
+ shouldPanic(t, "Xchg64", func() { atomic.Xchg64(up64, 1) })
+ shouldPanic(t, "Cas64", func() { atomic.Cas64(up64, 1, 2) })
+}
diff --git a/libgo/go/runtime/internal/atomic/bench_test.go b/libgo/go/runtime/internal/atomic/bench_test.go
new file mode 100644
index 00000000000..47010e32d53
--- /dev/null
+++ b/libgo/go/runtime/internal/atomic/bench_test.go
@@ -0,0 +1,28 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package atomic_test
+
+import (
+ "runtime/internal/atomic"
+ "testing"
+)
+
+var sink interface{}
+
+func BenchmarkAtomicLoad64(b *testing.B) {
+ var x uint64
+ sink = &x
+ for i := 0; i < b.N; i++ {
+ _ = atomic.Load64(&x)
+ }
+}
+
+func BenchmarkAtomicStore64(b *testing.B) {
+ var x uint64
+ sink = &x
+ for i := 0; i < b.N; i++ {
+ atomic.Store64(&x, 0)
+ }
+}
diff --git a/libgo/go/runtime/internal/sys/intrinsics.go b/libgo/go/runtime/internal/sys/intrinsics.go
index f33209a8878..43acf34b801 100644
--- a/libgo/go/runtime/internal/sys/intrinsics.go
+++ b/libgo/go/runtime/internal/sys/intrinsics.go
@@ -32,28 +32,6 @@ func Ctz32(x uint32) uint32 {
return uint32(builtinCtz32(x))
}
-//go:nosplit
-
-// Ctz16 counts trailing (low-order) zeroes,
-// and if all are zero, then 16.
-func Ctz16(x uint16) uint16 {
- if x == 0 {
- return 16
- }
- return uint16(builtinCtz32(uint32(x)))
-}
-
-//go:nosplit
-
-// Ctz8 counts trailing (low-order) zeroes,
-// and if all are zero, then 8.
-func Ctz8(x uint8) uint8 {
- if x == 0 {
- return 8
- }
- return uint8(builtinCtz32(uint32(x)))
-}
-
//extern __builtin_bswap64
func bswap64(uint64) uint64
diff --git a/libgo/go/runtime/internal/sys/intrinsics_test.go b/libgo/go/runtime/internal/sys/intrinsics_test.go
index 097631bc1e5..1f2c8daa962 100644
--- a/libgo/go/runtime/internal/sys/intrinsics_test.go
+++ b/libgo/go/runtime/internal/sys/intrinsics_test.go
@@ -21,22 +21,6 @@ func TestCtz32(t *testing.T) {
}
}
}
-func TestCtz16(t *testing.T) {
- for i := uint(0); i <= 16; i++ {
- x := uint16(5) << i
- if got := sys.Ctz16(x); got != uint16(i) {
- t.Errorf("Ctz16(%d)=%d, want %d", x, got, i)
- }
- }
-}
-func TestCtz8(t *testing.T) {
- for i := uint(0); i <= 8; i++ {
- x := uint8(5) << i
- if got := sys.Ctz8(x); got != uint8(i) {
- t.Errorf("Ctz8(%d)=%d, want %d", x, got, i)
- }
- }
-}
func TestBswap64(t *testing.T) {
x := uint64(0x1122334455667788)
diff --git a/libgo/go/runtime/malloc_test.go b/libgo/go/runtime/malloc_test.go
index 4f9262760e1..bc5530c2f23 100644
--- a/libgo/go/runtime/malloc_test.go
+++ b/libgo/go/runtime/malloc_test.go
@@ -14,6 +14,10 @@ import (
func TestMemStats(t *testing.T) {
t.Skip("skipping test with gccgo")
+
+ // Make sure there's at least one forced GC.
+ GC()
+
// Test that MemStats has sane values.
st := new(MemStats)
ReadMemStats(st)
@@ -25,7 +29,7 @@ func TestMemStats(t *testing.T) {
st.HeapInuse == 0 || st.HeapObjects == 0 || st.StackInuse == 0 ||
st.StackSys == 0 || st.MSpanInuse == 0 || st.MSpanSys == 0 || st.MCacheInuse == 0 ||
st.MCacheSys == 0 || st.BuckHashSys == 0 || st.GCSys == 0 || st.OtherSys == 0 ||
- st.NextGC == 0 {
+ st.NextGC == 0 || st.NumForcedGC == 0 {
t.Fatalf("Zero value: %+v", *st)
}
@@ -34,7 +38,7 @@ func TestMemStats(t *testing.T) {
st.HeapIdle > 1e10 || st.HeapInuse > 1e10 || st.HeapObjects > 1e10 || st.StackInuse > 1e10 ||
st.StackSys > 1e10 || st.MSpanInuse > 1e10 || st.MSpanSys > 1e10 || st.MCacheInuse > 1e10 ||
st.MCacheSys > 1e10 || st.BuckHashSys > 1e10 || st.GCSys > 1e10 || st.OtherSys > 1e10 ||
- st.NextGC > 1e10 || st.NumGC > 1e9 || st.PauseTotalNs > 1e11 {
+ st.NextGC > 1e10 || st.NumGC > 1e9 || st.NumForcedGC > 1e9 || st.PauseTotalNs > 1e11 {
t.Fatalf("Insanely high value (overflow?): %+v", *st)
}
if st.Sys != st.HeapSys+st.StackSys+st.MSpanSys+st.MCacheSys+
@@ -72,6 +76,10 @@ func TestMemStats(t *testing.T) {
t.Fatalf("PauseTotalNs(%d) < sum PauseNs(%d)", st.PauseTotalNs, pauseTotal)
}
}
+
+ if st.NumForcedGC > st.NumGC {
+ t.Fatalf("NumForcedGC(%d) > NumGC(%d)", st.NumForcedGC, st.NumGC)
+ }
}
func TestStringConcatenationAllocs(t *testing.T) {
diff --git a/libgo/go/runtime/map_test.go b/libgo/go/runtime/map_test.go
index 77affdfda12..9b5b051250e 100644
--- a/libgo/go/runtime/map_test.go
+++ b/libgo/go/runtime/map_test.go
@@ -235,6 +235,7 @@ func TestIterGrowWithGC(t *testing.T) {
}
func testConcurrentReadsAfterGrowth(t *testing.T, useReflect bool) {
+ t.Parallel()
if runtime.GOMAXPROCS(-1) == 1 {
if runtime.GOARCH == "s390" {
// Test uses too much address space on 31-bit S390.
diff --git a/libgo/go/runtime/mcache.go b/libgo/go/runtime/mcache.go
index e383e0d57d0..b65dd37421d 100644
--- a/libgo/go/runtime/mcache.go
+++ b/libgo/go/runtime/mcache.go
@@ -9,15 +9,6 @@ package runtime
import "unsafe"
-const (
- // Computed constant. The definition of MaxSmallSize and the
- // algorithm in msize.go produces some number of different allocation
- // size classes. NumSizeClasses is that number. It's needed here
- // because there are static arrays of this length; when msize runs its
- // size choosing algorithm it double-checks that NumSizeClasses agrees.
- _NumSizeClasses = 67
-)
-
type mcachelist struct {
list *mlink
nlist uint32
@@ -28,6 +19,8 @@ type mcachelist struct {
//
// mcaches are allocated from non-GC'd memory, so any heap pointers
// must be specially handled.
+//
+//go:notinheap
type mcache struct {
// The following members are accessed on every malloc,
// so they are grouped here for better caching.
diff --git a/libgo/go/runtime/mksizeclasses.go b/libgo/go/runtime/mksizeclasses.go
new file mode 100644
index 00000000000..0f897ba8e69
--- /dev/null
+++ b/libgo/go/runtime/mksizeclasses.go
@@ -0,0 +1,325 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// Generate tables for small malloc size classes.
+//
+// See malloc.go for overview.
+//
+// The size classes are chosen so that rounding an allocation
+// request up to the next size class wastes at most 12.5% (1.125x).
+//
+// Each size class has its own page count that gets allocated
+// and chopped up when new objects of the size class are needed.
+// That page count is chosen so that chopping up the run of
+// pages into objects of the given size wastes at most 12.5% (1.125x)
+// of the memory. It is not necessary that the cutoff here be
+// the same as above.
+//
+// The two sources of waste multiply, so the worst possible case
+// for the above constraints would be that allocations of some
+// size might have a 26.6% (1.266x) overhead.
+// In practice, only one of the wastes comes into play for a
+// given size (sizes < 512 waste mainly on the round-up,
+// sizes > 512 waste mainly on the page chopping).
+//
+// TODO(rsc): Compute max waste for any given size.
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "go/format"
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+)
+
+// Generate msize.go
+
+var stdout = flag.Bool("stdout", false, "write to stdout instead of sizeclasses.go")
+
+func main() {
+ flag.Parse()
+
+ var b bytes.Buffer
+ fmt.Fprintln(&b, "// AUTO-GENERATED by mksizeclasses.go; DO NOT EDIT")
+ fmt.Fprintln(&b, "//go:generate go run mksizeclasses.go")
+ fmt.Fprintln(&b)
+ fmt.Fprintln(&b, "package runtime")
+ classes := makeClasses()
+
+ printComment(&b, classes)
+
+ printClasses(&b, classes)
+
+ out, err := format.Source(b.Bytes())
+ if err != nil {
+ log.Fatal(err)
+ }
+ if *stdout {
+ _, err = os.Stdout.Write(out)
+ } else {
+ err = ioutil.WriteFile("sizeclasses.go", out, 0666)
+ }
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+const (
+ // Constants that we use and will transfer to the runtime.
+ maxSmallSize = 32 << 10
+ smallSizeDiv = 8
+ smallSizeMax = 1024
+ largeSizeDiv = 128
+ pageShift = 13
+
+ // Derived constants.
+ pageSize = 1 << pageShift
+)
+
+type class struct {
+ size int // max size
+ npages int // number of pages
+
+ mul int
+ shift uint
+ shift2 uint
+ mask int
+}
+
+func powerOfTwo(x int) bool {
+ return x != 0 && x&(x-1) == 0
+}
+
+func makeClasses() []class {
+ var classes []class
+
+ classes = append(classes, class{}) // class #0 is a dummy entry
+
+ align := 8
+ for size := align; size <= maxSmallSize; size += align {
+ if powerOfTwo(size) { // bump alignment once in a while
+ if size >= 2048 {
+ align = 256
+ } else if size >= 128 {
+ align = size / 8
+ } else if size >= 16 {
+ align = 16 // required for x86 SSE instructions, if we want to use them
+ }
+ }
+ if !powerOfTwo(align) {
+ panic("incorrect alignment")
+ }
+
+ // Make the allocnpages big enough that
+ // the leftover is less than 1/8 of the total,
+ // so wasted space is at most 12.5%.
+ allocsize := pageSize
+ for allocsize%size > allocsize/8 {
+ allocsize += pageSize
+ }
+ npages := allocsize / pageSize
+
+ // If the previous sizeclass chose the same
+ // allocation size and fit the same number of
+ // objects into the page, we might as well
+ // use just this size instead of having two
+ // different sizes.
+ if len(classes) > 1 && npages == classes[len(classes)-1].npages && allocsize/size == allocsize/classes[len(classes)-1].size {
+ classes[len(classes)-1].size = size
+ continue
+ }
+ classes = append(classes, class{size: size, npages: npages})
+ }
+
+ // Increase object sizes if we can fit the same number of larger objects
+ // into the same number of pages. For example, we choose size 8448 above
+ // with 6 objects in 7 pages. But we can well use object size 9472,
+ // which is also 6 objects in 7 pages but +1024 bytes (+12.12%).
+ // We need to preserve at least largeSizeDiv alignment otherwise
+ // sizeToClass won't work.
+ for i := range classes {
+ if i == 0 {
+ continue
+ }
+ c := &classes[i]
+ psize := c.npages * pageSize
+ new_size := (psize / (psize / c.size)) &^ (largeSizeDiv - 1)
+ if new_size > c.size {
+ c.size = new_size
+ }
+ }
+
+ if len(classes) != 67 {
+ panic("number of size classes has changed")
+ }
+
+ for i := range classes {
+ computeDivMagic(&classes[i])
+ }
+
+ return classes
+}
+
+// computeDivMagic computes some magic constants to implement
+// the division required to compute object number from span offset.
+// n / c.size is implemented as n >> c.shift * c.mul >> c.shift2
+// for all 0 <= n < c.npages * pageSize
+func computeDivMagic(c *class) {
+ // divisor
+ d := c.size
+ if d == 0 {
+ return
+ }
+
+ // maximum input value for which the formula needs to work.
+ max := c.npages*pageSize - 1
+
+ if powerOfTwo(d) {
+ // If the size is a power of two, heapBitsForObject can divide even faster by masking.
+ // Compute this mask.
+ if max >= 1<<16 {
+ panic("max too big for power of two size")
+ }
+ c.mask = 1<<16 - d
+ }
+
+ // Compute pre-shift by factoring power of 2 out of d.
+ for d%2 == 0 {
+ c.shift++
+ d >>= 1
+ max >>= 1
+ }
+
+ // Find the smallest k that works.
+ // A small k allows us to fit the math required into 32 bits
+ // so we can use 32-bit multiplies and shifts on 32-bit platforms.
+nextk:
+ for k := uint(0); ; k++ {
+ mul := (int(1)<<k + d - 1) / d // ⌈2^k / d⌉
+
+ // Test to see if mul works.
+ for n := 0; n <= max; n++ {
+ if n*mul>>k != n/d {
+ continue nextk
+ }
+ }
+ if mul >= 1<<16 {
+ panic("mul too big")
+ }
+ if uint64(mul)*uint64(max) >= 1<<32 {
+ panic("mul*max too big")
+ }
+ c.mul = mul
+ c.shift2 = k
+ break
+ }
+
+ // double-check.
+ for n := 0; n <= max; n++ {
+ if n*c.mul>>c.shift2 != n/d {
+ fmt.Printf("d=%d max=%d mul=%d shift2=%d n=%d\n", d, max, c.mul, c.shift2, n)
+ panic("bad multiply magic")
+ }
+ // Also check the exact computations that will be done by the runtime,
+ // for both 32 and 64 bit operations.
+ if uint32(n)*uint32(c.mul)>>uint8(c.shift2) != uint32(n/d) {
+ fmt.Printf("d=%d max=%d mul=%d shift2=%d n=%d\n", d, max, c.mul, c.shift2, n)
+ panic("bad 32-bit multiply magic")
+ }
+ if uint64(n)*uint64(c.mul)>>uint8(c.shift2) != uint64(n/d) {
+ fmt.Printf("d=%d max=%d mul=%d shift2=%d n=%d\n", d, max, c.mul, c.shift2, n)
+ panic("bad 64-bit multiply magic")
+ }
+ }
+}
+
+func printComment(w io.Writer, classes []class) {
+ fmt.Fprintf(w, "// %-5s %-9s %-10s %-7s %-11s\n", "class", "bytes/obj", "bytes/span", "objects", "waste bytes")
+ for i, c := range classes {
+ if i == 0 {
+ continue
+ }
+ spanSize := c.npages * pageSize
+ objects := spanSize / c.size
+ waste := spanSize - c.size*(spanSize/c.size)
+ fmt.Fprintf(w, "// %5d %9d %10d %7d %11d\n", i, c.size, spanSize, objects, waste)
+ }
+ fmt.Fprintf(w, "\n")
+}
+
+func printClasses(w io.Writer, classes []class) {
+ fmt.Fprintln(w, "const (")
+ fmt.Fprintf(w, "_MaxSmallSize = %d\n", maxSmallSize)
+ fmt.Fprintf(w, "smallSizeDiv = %d\n", smallSizeDiv)
+ fmt.Fprintf(w, "smallSizeMax = %d\n", smallSizeMax)
+ fmt.Fprintf(w, "largeSizeDiv = %d\n", largeSizeDiv)
+ fmt.Fprintf(w, "_NumSizeClasses = %d\n", len(classes))
+ fmt.Fprintf(w, "_PageShift = %d\n", pageShift)
+ fmt.Fprintln(w, ")")
+
+ fmt.Fprint(w, "var class_to_size = [_NumSizeClasses]uint16 {")
+ for _, c := range classes {
+ fmt.Fprintf(w, "%d,", c.size)
+ }
+ fmt.Fprintln(w, "}")
+
+ fmt.Fprint(w, "var class_to_allocnpages = [_NumSizeClasses]uint8 {")
+ for _, c := range classes {
+ fmt.Fprintf(w, "%d,", c.npages)
+ }
+ fmt.Fprintln(w, "}")
+
+ fmt.Fprintln(w, "type divMagic struct {")
+ fmt.Fprintln(w, " shift uint8")
+ fmt.Fprintln(w, " shift2 uint8")
+ fmt.Fprintln(w, " mul uint16")
+ fmt.Fprintln(w, " baseMask uint16")
+ fmt.Fprintln(w, "}")
+ fmt.Fprint(w, "var class_to_divmagic = [_NumSizeClasses]divMagic {")
+ for _, c := range classes {
+ fmt.Fprintf(w, "{%d,%d,%d,%d},", c.shift, c.shift2, c.mul, c.mask)
+ }
+ fmt.Fprintln(w, "}")
+
+ // map from size to size class, for small sizes.
+ sc := make([]int, smallSizeMax/smallSizeDiv+1)
+ for i := range sc {
+ size := i * smallSizeDiv
+ for j, c := range classes {
+ if c.size >= size {
+ sc[i] = j
+ break
+ }
+ }
+ }
+ fmt.Fprint(w, "var size_to_class8 = [smallSizeMax/smallSizeDiv+1]uint8 {")
+ for _, v := range sc {
+ fmt.Fprintf(w, "%d,", v)
+ }
+ fmt.Fprintln(w, "}")
+
+ // map from size to size class, for large sizes.
+ sc = make([]int, (maxSmallSize-smallSizeMax)/largeSizeDiv+1)
+ for i := range sc {
+ size := smallSizeMax + i*largeSizeDiv
+ for j, c := range classes {
+ if c.size >= size {
+ sc[i] = j
+ break
+ }
+ }
+ }
+ fmt.Fprint(w, "var size_to_class128 = [(_MaxSmallSize-smallSizeMax)/largeSizeDiv+1]uint8 {")
+ for _, v := range sc {
+ fmt.Fprintf(w, "%d,", v)
+ }
+ fmt.Fprintln(w, "}")
+}
diff --git a/libgo/go/runtime/mmap.go b/libgo/go/runtime/mmap.go
deleted file mode 100644
index 02aafdd210e..00000000000
--- a/libgo/go/runtime/mmap.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-// +build !plan9
-// +build !solaris
-// +build !windows
-// +build !nacl
-// +build !linux !amd64
-
-package runtime
-
-import "unsafe"
-
-// mmap calls the mmap system call. It is implemented in assembly.
-// We only pass the lower 32 bits of file offset to the
-// assembly routine; the higher bits (if required), should be provided
-// by the assembly routine as 0.
-func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
diff --git a/libgo/go/runtime/mprof.go b/libgo/go/runtime/mprof.go
index e1900176637..1bfdc39b624 100644
--- a/libgo/go/runtime/mprof.go
+++ b/libgo/go/runtime/mprof.go
@@ -31,6 +31,7 @@ const (
// profile types
memProfile bucketType = 1 + iota
blockProfile
+ mutexProfile
// size of bucket hash table
buckHashSize = 179999
@@ -49,10 +50,14 @@ type bucketType int
//
// Per-call-stack profiling information.
// Lookup by hashing call stack into a linked-list hash table.
+//
+// No heap pointers.
+//
+//go:notinheap
type bucket struct {
next *bucket
allnext *bucket
- typ bucketType // memBucket or blockBucket
+ typ bucketType // memBucket or blockBucket (includes mutexProfile)
hash uintptr
size uintptr
nstk uintptr
@@ -92,7 +97,7 @@ type memRecord struct {
}
// A blockRecord is the bucket data for a bucket of type blockProfile,
-// part of the blocking profile.
+// which is used in blocking and mutex profiles.
type blockRecord struct {
count int64
cycles int64
@@ -101,6 +106,7 @@ type blockRecord struct {
var (
mbuckets *bucket // memory profile buckets
bbuckets *bucket // blocking profile buckets
+ xbuckets *bucket // mutex profile buckets
buckhash *[179999]*bucket
bucketmem uintptr
)
@@ -113,7 +119,7 @@ func newBucket(typ bucketType, nstk int) *bucket {
throw("invalid profile bucket type")
case memProfile:
size += unsafe.Sizeof(memRecord{})
- case blockProfile:
+ case blockProfile, mutexProfile:
size += unsafe.Sizeof(blockRecord{})
}
@@ -141,7 +147,7 @@ func (b *bucket) mp() *memRecord {
// bp returns the blockRecord associated with the blockProfile bucket b.
func (b *bucket) bp() *blockRecord {
- if b.typ != blockProfile {
+ if b.typ != blockProfile && b.typ != mutexProfile {
throw("bad use of bucket.bp")
}
data := add(unsafe.Pointer(b), unsafe.Sizeof(*b)+b.nstk*unsafe.Sizeof(location{}))
@@ -193,6 +199,9 @@ func stkbucket(typ bucketType, size uintptr, stk []location, alloc bool) *bucket
if typ == memProfile {
b.allnext = mbuckets
mbuckets = b
+ } else if typ == mutexProfile {
+ b.allnext = xbuckets
+ xbuckets = b
} else {
b.allnext = bbuckets
bbuckets = b
@@ -297,10 +306,20 @@ func blockevent(cycles int64, skip int) {
if cycles <= 0 {
cycles = 1
}
+ if blocksampled(cycles) {
+ saveblockevent(cycles, skip+1, blockProfile, &blockprofilerate)
+ }
+}
+
+func blocksampled(cycles int64) bool {
rate := int64(atomic.Load64(&blockprofilerate))
- if rate <= 0 || (rate > cycles && int64(fastrand1())%rate > cycles) {
- return
+ if rate <= 0 || (rate > cycles && int64(fastrand())%rate > cycles) {
+ return false
}
+ return true
+}
+
+func saveblockevent(cycles int64, skip int, which bucketType, ratep *uint64) {
gp := getg()
var nstk int
var stk [maxStack]location
@@ -312,12 +331,43 @@ func blockevent(cycles int64, skip int) {
nstk = callers(skip, stk[:])
}
lock(&proflock)
- b := stkbucket(blockProfile, 0, stk[:nstk], true)
+ b := stkbucket(which, 0, stk[:nstk], true)
b.bp().count++
b.bp().cycles += cycles
unlock(&proflock)
}
+var mutexprofilerate uint64 // fraction sampled
+
+// SetMutexProfileFraction controls the fraction of mutex contention events
+// that are reported in the mutex profile. On average 1/rate events are
+// reported. The previous rate is returned.
+//
+// To turn off profiling entirely, pass rate 0.
+// To just read the current rate, pass rate -1.
+// (For n>1 the details of sampling may change.)
+func SetMutexProfileFraction(rate int) int {
+ if rate < 0 {
+ return int(mutexprofilerate)
+ }
+ old := mutexprofilerate
+ atomic.Store64(&mutexprofilerate, uint64(rate))
+ return int(old)
+}
+
+//go:linkname mutexevent sync.event
+func mutexevent(cycles int64, skip int) {
+ if cycles < 0 {
+ cycles = 0
+ }
+ rate := int64(atomic.Load64(&mutexprofilerate))
+ // TODO(pjw): measure impact of always calling fastrand vs using something
+ // like malloc.go:nextSample()
+ if rate > 0 && int64(fastrand())%rate == 0 {
+ saveblockevent(cycles, skip+1, mutexProfile, &mutexprofilerate)
+ }
+}
+
// Go interface to profile data.
// A StackRecord describes a single execution stack.
@@ -514,6 +564,42 @@ func BlockProfile(p []BlockProfileRecord) (n int, ok bool) {
return
}
+// MutexProfile returns n, the number of records in the current mutex profile.
+// If len(p) >= n, MutexProfile copies the profile into p and returns n, true.
+// Otherwise, MutexProfile does not change p, and returns n, false.
+//
+// Most clients should use the runtime/pprof package
+// instead of calling MutexProfile directly.
+func MutexProfile(p []BlockProfileRecord) (n int, ok bool) {
+ lock(&proflock)
+ for b := xbuckets; b != nil; b = b.allnext {
+ n++
+ }
+ if n <= len(p) {
+ ok = true
+ for b := xbuckets; b != nil; b = b.allnext {
+ bp := b.bp()
+ r := &p[0]
+ r.Count = int64(bp.count)
+ r.Cycles = bp.cycles
+ i := 0
+ var loc location
+ for i, loc = range b.stk() {
+ if i >= len(r.Stack0) {
+ break
+ }
+ r.Stack0[i] = loc.pc
+ }
+ for ; i < len(r.Stack0); i++ {
+ r.Stack0[i] = 0
+ }
+ p = p[1:]
+ }
+ }
+ unlock(&proflock)
+ return
+}
+
// ThreadCreateProfile returns n, the number of records in the thread creation profile.
// If len(p) >= n, ThreadCreateProfile copies the profile into p and returns n, true.
// If len(p) < n, ThreadCreateProfile does not change p and returns n, false.
diff --git a/libgo/go/runtime/mstats.go b/libgo/go/runtime/mstats.go
index 6ec268d421c..178c32c0320 100644
--- a/libgo/go/runtime/mstats.go
+++ b/libgo/go/runtime/mstats.go
@@ -14,6 +14,13 @@ import (
// Statistics.
// If you edit this structure, also edit type MemStats below.
+// Their layouts must match exactly.
+//
+// For detailed descriptions see the documentation for MemStats.
+// Fields that differ from MemStats are further documented here.
+//
+// Many of these fields are updated on the fly, while others are only
+// updated when updatememstats is called.
type mstats struct {
// General statistics.
alloc uint64 // bytes allocated and not yet freed
@@ -24,18 +31,36 @@ type mstats struct {
nfree uint64 // number of frees
// Statistics about malloc heap.
- // protected by mheap.lock
+ // Protected by mheap.lock
+ //
+ // In mstats, heap_sys and heap_inuse includes stack memory,
+ // while in MemStats stack memory is separated out from the
+ // heap stats.
heap_alloc uint64 // bytes allocated and not yet freed (same as alloc above)
- heap_sys uint64 // bytes obtained from system
+ heap_sys uint64 // virtual address space obtained from system
heap_idle uint64 // bytes in idle spans
heap_inuse uint64 // bytes in non-idle spans
heap_released uint64 // bytes released to the os
heap_objects uint64 // total number of allocated objects
+ // TODO(austin): heap_released is both useless and inaccurate
+ // in its current form. It's useless because, from the user's
+ // and OS's perspectives, there's no difference between a page
+ // that has not yet been faulted in and a page that has been
+ // released back to the OS. We could fix this by considering
+ // newly mapped spans to be "released". It's inaccurate
+ // because when we split a large span for allocation, we
+ // "unrelease" all pages in the large span and not just the
+ // ones we split off for use. This is trickier to fix because
+ // we currently don't know which pages of a span we've
+ // released. We could fix it by separating "free" and
+ // "released" spans, but then we have to allocate from runs of
+ // free and released spans.
+
// Statistics about allocation of low-level fixed-size structures.
// Protected by FixAlloc locks.
- stacks_inuse uint64 // this number is included in heap_inuse above
- stacks_sys uint64 // always 0 in mstats
+ stacks_inuse uint64 // this number is included in heap_inuse above; differs from MemStats.StackInuse
+ stacks_sys uint64 // only counts newosproc0 stack in mstats; differs from MemStats.StackSys
mspan_inuse uint64 // mspan structures
mspan_sys uint64
mcache_inuse uint64 // mcache structures
@@ -46,12 +71,13 @@ type mstats struct {
// Statistics about garbage collector.
// Protected by mheap or stopping the world during GC.
- next_gc uint64 // next gc (in heap_live time)
+ next_gc uint64 // goal heap_live for when next GC ends; ^0 if disabled
last_gc uint64 // last gc (in absolute time)
pause_total_ns uint64
pause_ns [256]uint64 // circular buffer of recent gc pause lengths
pause_end [256]uint64 // circular buffer of recent gc end times (nanoseconds since 1970)
numgc uint32
+ numforcedgc uint32 // number of user-forced GCs
gc_cpu_fraction float64 // fraction of CPU time used by GC
enablegc bool
debuggc bool
@@ -64,10 +90,17 @@ type mstats struct {
nfree uint64
}
- // Statistics below here are not exported to Go directly.
+ // Statistics below here are not exported to MemStats directly.
tinyallocs uint64 // number of tiny allocations that didn't cause actual allocation; not exported to go directly
+ // gc_trigger is the heap size that triggers marking.
+ //
+ // When heap_live ≥ gc_trigger, the mark phase will start.
+ // This is also the heap size by which proportional sweeping
+ // must be complete.
+ gc_trigger uint64
+
// heap_live is the number of bytes considered live by the GC.
// That is: retained by the most recent GC plus allocated
// since then. heap_live <= heap_alloc, since heap_alloc
@@ -104,10 +137,6 @@ type mstats struct {
// unlike heap_live, heap_marked does not change until the
// next mark termination.
heap_marked uint64
-
- // heap_reachable is an estimate of the reachable heap bytes
- // at the end of the previous GC.
- heap_reachable uint64
}
var memstats mstats
@@ -115,58 +144,281 @@ var memstats mstats
// A MemStats records statistics about the memory allocator.
type MemStats struct {
// General statistics.
- Alloc uint64 // bytes allocated and not yet freed
- TotalAlloc uint64 // bytes allocated (even if freed)
- Sys uint64 // bytes obtained from system (sum of XxxSys below)
- Lookups uint64 // number of pointer lookups
- Mallocs uint64 // number of mallocs
- Frees uint64 // number of frees
-
- // Main allocation heap statistics.
- HeapAlloc uint64 // bytes allocated and not yet freed (same as Alloc above)
- HeapSys uint64 // bytes obtained from system
- HeapIdle uint64 // bytes in idle spans
- HeapInuse uint64 // bytes in non-idle span
- HeapReleased uint64 // bytes released to the OS
- HeapObjects uint64 // total number of allocated objects
-
- // Low-level fixed-size structure allocator statistics.
- // Inuse is bytes used now.
- // Sys is bytes obtained from system.
- StackInuse uint64 // bytes used by stack allocator
- StackSys uint64
- MSpanInuse uint64 // mspan structures
- MSpanSys uint64
- MCacheInuse uint64 // mcache structures
- MCacheSys uint64
- BuckHashSys uint64 // profiling bucket hash table
- GCSys uint64 // GC metadata
- OtherSys uint64 // other system allocations
+
+ // Alloc is bytes of allocated heap objects.
+ //
+ // This is the same as HeapAlloc (see below).
+ Alloc uint64
+
+ // TotalAlloc is cumulative bytes allocated for heap objects.
+ //
+ // TotalAlloc increases as heap objects are allocated, but
+ // unlike Alloc and HeapAlloc, it does not decrease when
+ // objects are freed.
+ TotalAlloc uint64
+
+ // Sys is the total bytes of memory obtained from the OS.
+ //
+ // Sys is the sum of the XSys fields below. Sys measures the
+ // virtual address space reserved by the Go runtime for the
+ // heap, stacks, and other internal data structures. It's
+ // likely that not all of the virtual address space is backed
+ // by physical memory at any given moment, though in general
+ // it all was at some point.
+ Sys uint64
+
+ // Lookups is the number of pointer lookups performed by the
+ // runtime.
+ //
+ // This is primarily useful for debugging runtime internals.
+ Lookups uint64
+
+ // Mallocs is the cumulative count of heap objects allocated.
+ // The number of live objects is Mallocs - Frees.
+ Mallocs uint64
+
+ // Frees is the cumulative count of heap objects freed.
+ Frees uint64
+
+ // Heap memory statistics.
+ //
+ // Interpreting the heap statistics requires some knowledge of
+ // how Go organizes memory. Go divides the virtual address
+ // space of the heap into "spans", which are contiguous
+ // regions of memory 8K or larger. A span may be in one of
+ // three states:
+ //
+ // An "idle" span contains no objects or other data. The
+ // physical memory backing an idle span can be released back
+ // to the OS (but the virtual address space never is), or it
+ // can be converted into an "in use" or "stack" span.
+ //
+ // An "in use" span contains at least one heap object and may
+ // have free space available to allocate more heap objects.
+ //
+ // A "stack" span is used for goroutine stacks. Stack spans
+ // are not considered part of the heap. A span can change
+ // between heap and stack memory; it is never used for both
+ // simultaneously.
+
+ // HeapAlloc is bytes of allocated heap objects.
+ //
+ // "Allocated" heap objects include all reachable objects, as
+ // well as unreachable objects that the garbage collector has
+ // not yet freed. Specifically, HeapAlloc increases as heap
+ // objects are allocated and decreases as the heap is swept
+ // and unreachable objects are freed. Sweeping occurs
+ // incrementally between GC cycles, so these two processes
+ // occur simultaneously, and as a result HeapAlloc tends to
+ // change smoothly (in contrast with the sawtooth that is
+ // typical of stop-the-world garbage collectors).
+ HeapAlloc uint64
+
+ // HeapSys is bytes of heap memory obtained from the OS.
+ //
+ // HeapSys measures the amount of virtual address space
+ // reserved for the heap. This includes virtual address space
+ // that has been reserved but not yet used, which consumes no
+ // physical memory, but tends to be small, as well as virtual
+ // address space for which the physical memory has been
+ // returned to the OS after it became unused (see HeapReleased
+ // for a measure of the latter).
+ //
+ // HeapSys estimates the largest size the heap has had.
+ HeapSys uint64
+
+ // HeapIdle is bytes in idle (unused) spans.
+ //
+ // Idle spans have no objects in them. These spans could be
+ // (and may already have been) returned to the OS, or they can
+ // be reused for heap allocations, or they can be reused as
+ // stack memory.
+ //
+ // HeapIdle minus HeapReleased estimates the amount of memory
+ // that could be returned to the OS, but is being retained by
+ // the runtime so it can grow the heap without requesting more
+ // memory from the OS. If this difference is significantly
+ // larger than the heap size, it indicates there was a recent
+ // transient spike in live heap size.
+ HeapIdle uint64
+
+ // HeapInuse is bytes in in-use spans.
+ //
+ // In-use spans have at least one object in them. These spans
+ // can only be used for other objects of roughly the same
+ // size.
+ //
+ // HeapInuse minus HeapAlloc esimates the amount of memory
+ // that has been dedicated to particular size classes, but is
+ // not currently being used. This is an upper bound on
+ // fragmentation, but in general this memory can be reused
+ // efficiently.
+ HeapInuse uint64
+
+ // HeapReleased is bytes of physical memory returned to the OS.
+ //
+ // This counts heap memory from idle spans that was returned
+ // to the OS and has not yet been reacquired for the heap.
+ HeapReleased uint64
+
+ // HeapObjects is the number of allocated heap objects.
+ //
+ // Like HeapAlloc, this increases as objects are allocated and
+ // decreases as the heap is swept and unreachable objects are
+ // freed.
+ HeapObjects uint64
+
+ // Stack memory statistics.
+ //
+ // Stacks are not considered part of the heap, but the runtime
+ // can reuse a span of heap memory for stack memory, and
+ // vice-versa.
+
+ // StackInuse is bytes in stack spans.
+ //
+ // In-use stack spans have at least one stack in them. These
+ // spans can only be used for other stacks of the same size.
+ //
+ // There is no StackIdle because unused stack spans are
+ // returned to the heap (and hence counted toward HeapIdle).
+ StackInuse uint64
+
+ // StackSys is bytes of stack memory obtained from the OS.
+ //
+ // StackSys is StackInuse, plus any memory obtained directly
+ // from the OS for OS thread stacks (which should be minimal).
+ StackSys uint64
+
+ // Off-heap memory statistics.
+ //
+ // The following statistics measure runtime-internal
+ // structures that are not allocated from heap memory (usually
+ // because they are part of implementing the heap). Unlike
+ // heap or stack memory, any memory allocated to these
+ // structures is dedicated to these structures.
+ //
+ // These are primarily useful for debugging runtime memory
+ // overheads.
+
+ // MSpanInuse is bytes of allocated mspan structures.
+ MSpanInuse uint64
+
+ // MSpanSys is bytes of memory obtained from the OS for mspan
+ // structures.
+ MSpanSys uint64
+
+ // MCacheInuse is bytes of allocated mcache structures.
+ MCacheInuse uint64
+
+ // MCacheSys is bytes of memory obtained from the OS for
+ // mcache structures.
+ MCacheSys uint64
+
+ // BuckHashSys is bytes of memory in profiling bucket hash tables.
+ BuckHashSys uint64
+
+ // GCSys is bytes of memory in garbage collection metadata.
+ GCSys uint64
+
+ // OtherSys is bytes of memory in miscellaneous off-heap
+ // runtime allocations.
+ OtherSys uint64
// Garbage collector statistics.
- NextGC uint64 // next collection will happen when HeapAlloc ≥ this amount
- LastGC uint64 // end time of last collection (nanoseconds since 1970)
- PauseTotalNs uint64
- PauseNs [256]uint64 // circular buffer of recent GC pause durations, most recent at [(NumGC+255)%256]
- PauseEnd [256]uint64 // circular buffer of recent GC pause end times
- NumGC uint32
- GCCPUFraction float64 // fraction of CPU time used by GC
- EnableGC bool
- DebugGC bool
-
- // Per-size allocation statistics.
- // 61 is NumSizeClasses in the C code.
+
+ // NextGC is the target heap size of the next GC cycle.
+ //
+ // The garbage collector's goal is to keep HeapAlloc ≤ NextGC.
+ // At the end of each GC cycle, the target for the next cycle
+ // is computed based on the amount of reachable data and the
+ // value of GOGC.
+ NextGC uint64
+
+ // LastGC is the time the last garbage collection finished, as
+ // nanoseconds since 1970 (the UNIX epoch).
+ LastGC uint64
+
+ // PauseTotalNs is the cumulative nanoseconds in GC
+ // stop-the-world pauses since the program started.
+ //
+ // During a stop-the-world pause, all goroutines are paused
+ // and only the garbage collector can run.
+ PauseTotalNs uint64
+
+ // PauseNs is a circular buffer of recent GC stop-the-world
+ // pause times in nanoseconds.
+ //
+ // The most recent pause is at PauseNs[(NumGC+255)%256]. In
+ // general, PauseNs[N%256] records the time paused in the most
+ // recent N%256th GC cycle. There may be multiple pauses per
+ // GC cycle; this is the sum of all pauses during a cycle.
+ PauseNs [256]uint64
+
+ // PauseEnd is a circular buffer of recent GC pause end times,
+ // as nanoseconds since 1970 (the UNIX epoch).
+ //
+ // This buffer is filled the same way as PauseNs. There may be
+ // multiple pauses per GC cycle; this records the end of the
+ // last pause in a cycle.
+ PauseEnd [256]uint64
+
+ // NumGC is the number of completed GC cycles.
+ NumGC uint32
+
+ // NumForcedGC is the number of GC cycles that were forced by
+ // the application calling the GC function.
+ NumForcedGC uint32
+
+ // GCCPUFraction is the fraction of this program's available
+ // CPU time used by the GC since the program started.
+ //
+ // GCCPUFraction is expressed as a number between 0 and 1,
+ // where 0 means GC has consumed none of this program's CPU. A
+ // program's available CPU time is defined as the integral of
+ // GOMAXPROCS since the program started. That is, if
+ // GOMAXPROCS is 2 and a program has been running for 10
+ // seconds, its "available CPU" is 20 seconds. GCCPUFraction
+ // does not include CPU time used for write barrier activity.
+ //
+ // This is the same as the fraction of CPU reported by
+ // GODEBUG=gctrace=1.
+ GCCPUFraction float64
+
+ // EnableGC indicates that GC is enabled. It is always true,
+ // even if GOGC=off.
+ EnableGC bool
+
+ // DebugGC is currently unused.
+ DebugGC bool
+
+ // BySize reports per-size class allocation statistics.
+ //
+ // BySize[N] gives statistics for allocations of size S where
+ // BySize[N-1].Size < S ≤ BySize[N].Size.
+ //
+ // This does not report allocations larger than BySize[60].Size.
BySize [61]struct {
- Size uint32
+ // Size is the maximum byte size of an object in this
+ // size class.
+ Size uint32
+
+ // Mallocs is the cumulative count of heap objects
+ // allocated in this size class. The cumulative bytes
+ // of allocation is Size*Mallocs. The number of live
+ // objects in this size class is Mallocs - Frees.
Mallocs uint64
- Frees uint64
+
+ // Frees is the cumulative count of heap objects freed
+ // in this size class.
+ Frees uint64
}
}
-// Size of the trailing by_size array differs between Go and C,
+// Size of the trailing by_size array differs between mstats and MemStats,
// and all data after by_size is local to runtime, not exported.
-// NumSizeClasses was changed, but we cannot change Go struct because of backward compatibility.
-// sizeof_C_MStats is what C thinks about size of Go struct.
+// NumSizeClasses was changed, but we cannot change MemStats because of backward compatibility.
+// sizeof_C_MStats is the size of the prefix of mstats that
+// corresponds to MemStats. It should match Sizeof(MemStats{}).
var sizeof_C_MStats = unsafe.Offsetof(memstats.by_size) + 61*unsafe.Sizeof(memstats.by_size[0])
func init() {
@@ -175,9 +427,19 @@ func init() {
println(sizeof_C_MStats, unsafe.Sizeof(memStats))
throw("MStats vs MemStatsType size mismatch")
}
+
+ if unsafe.Offsetof(memstats.heap_live)%8 != 0 {
+ println(unsafe.Offsetof(memstats.heap_live))
+ throw("memstats.heap_live not aligned to 8 bytes")
+ }
}
// ReadMemStats populates m with memory allocator statistics.
+//
+// The returned memory allocator statistics are up to date as of the
+// call to ReadMemStats. This is in contrast with a heap profile,
+// which is a snapshot as of the most recently completed garbage
+// collection cycle.
func ReadMemStats(m *MemStats) {
stopTheWorld("read mem stats")
@@ -191,8 +453,9 @@ func ReadMemStats(m *MemStats) {
func readmemstats_m(stats *MemStats) {
updatememstats(nil)
- // Size of the trailing by_size array differs between Go and C,
- // NumSizeClasses was changed, but we cannot change Go struct because of backward compatibility.
+ // The size of the trailing by_size array differs between
+ // mstats and MemStats. NumSizeClasses was changed, but we
+ // cannot change MemStats because of backward compatibility.
memmove(unsafe.Pointer(stats), unsafe.Pointer(&memstats), sizeof_C_MStats)
// Stack numbers are part of the heap numbers, separate those out for user consumption
@@ -292,8 +555,7 @@ func updatememstats(stats *gcstats) {
// Scan all spans and count number of alive objects.
lock(&mheap_.lock)
- for i := uint32(0); i < mheap_.nspan; i++ {
- s := h_allspans[i]
+ for _, s := range mheap_.allspans {
if s.state != mSpanInUse {
continue
}
@@ -341,19 +603,32 @@ func cachestats() {
}
}
+// flushmcache flushes the mcache of allp[i].
+//
+// The world must be stopped.
+//
+//go:nowritebarrier
+func flushmcache(i int) {
+ p := allp[i]
+ if p == nil {
+ return
+ }
+ c := p.mcache
+ if c == nil {
+ return
+ }
+ c.releaseAll()
+ stackcache_clear(c)
+}
+
+// flushallmcaches flushes the mcaches of all Ps.
+//
+// The world must be stopped.
+//
//go:nowritebarrier
func flushallmcaches() {
- for i := 0; ; i++ {
- p := allp[i]
- if p == nil {
- break
- }
- c := p.mcache
- if c == nil {
- continue
- }
- c.releaseAll()
- stackcache_clear(c)
+ for i := 0; i < int(gomaxprocs); i++ {
+ flushmcache(i)
}
}
diff --git a/libgo/go/runtime/mstkbar.go b/libgo/go/runtime/mstkbar.go
index 6d0b5ac211b..616c220132f 100644
--- a/libgo/go/runtime/mstkbar.go
+++ b/libgo/go/runtime/mstkbar.go
@@ -150,6 +150,10 @@ var firstStackBarrierOffset = 1024
// gcMaxStackBarriers returns the maximum number of stack barriers
// that can be installed in a stack of stackSize bytes.
func gcMaxStackBarriers(stackSize int) (n int) {
+ if debug.gcstackbarrieroff > 0 {
+ return 0
+ }
+
if firstStackBarrierOffset == 0 {
// Special debugging case for inserting stack barriers
// at every frame. Steal half of the stack for the
diff --git a/libgo/go/runtime/net_plan9.go b/libgo/go/runtime/net_plan9.go
new file mode 100644
index 00000000000..10fd089aea3
--- /dev/null
+++ b/libgo/go/runtime/net_plan9.go
@@ -0,0 +1,29 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+ _ "unsafe"
+)
+
+//go:linkname runtime_ignoreHangup net.runtime_ignoreHangup
+func runtime_ignoreHangup() {
+ getg().m.ignoreHangup = true
+}
+
+//go:linkname runtime_unignoreHangup net.runtime_unignoreHangup
+func runtime_unignoreHangup(sig string) {
+ getg().m.ignoreHangup = false
+}
+
+func ignoredNote(note *byte) bool {
+ if note == nil {
+ return false
+ }
+ if gostringnocopy(note) != "hangup" {
+ return false
+ }
+ return getg().m.ignoreHangup
+}
diff --git a/libgo/go/runtime/netpoll.go b/libgo/go/runtime/netpoll.go
index 729b5973675..876eaeac79d 100644
--- a/libgo/go/runtime/netpoll.go
+++ b/libgo/go/runtime/netpoll.go
@@ -42,6 +42,10 @@ const (
const pollBlockSize = 4 * 1024
// Network poller descriptor.
+//
+// No heap pointers.
+//
+//go:notinheap
type pollDesc struct {
link *pollDesc // in pollcache, protected by pollcache.lock
diff --git a/libgo/go/runtime/os_darwin.go b/libgo/go/runtime/os_darwin.go
index db403e2eb37..ec92370ad70 100644
--- a/libgo/go/runtime/os_darwin.go
+++ b/libgo/go/runtime/os_darwin.go
@@ -269,7 +269,10 @@ func semasleep1(ns int64) int32 {
if r == 0 {
break
}
- if r == _KERN_ABORTED { // interrupted
+ // Note: We don't know how this call (with no timeout) can get _KERN_OPERATION_TIMED_OUT,
+ // but it does reliably, though at a very low rate, on OS X 10.8, 10.9, 10.10, and 10.11.
+ // See golang.org/issue/17161.
+ if r == _KERN_ABORTED || r == _KERN_OPERATION_TIMED_OUT { // interrupted
continue
}
macherror(r, "semaphore_wait")
diff --git a/libgo/go/runtime/os_freebsd.go b/libgo/go/runtime/os_freebsd.go
index 4512e7699fe..a4d2886d6af 100644
--- a/libgo/go/runtime/os_freebsd.go
+++ b/libgo/go/runtime/os_freebsd.go
@@ -14,7 +14,7 @@ type mOS struct {
//go:noescape
//extern _umtx_op
-func sys_umtx_op(addr *uint32, mode int32, val uint32, ptr2, ts *timespec) int32
+func sys_umtx_op(addr *uint32, mode int32, val uint32, uaddr1 uinptr, ts *umtx_time) int32
// FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and
// thus the code is largely similar. See Linux implementation
@@ -28,14 +28,14 @@ func futexsleep(addr *uint32, val uint32, ns int64) {
}
func futexsleep1(addr *uint32, val uint32, ns int64) {
- var tsp *timespec
+ var utp *umtx_time
if ns >= 0 {
- var ts timespec
- ts.tv_nsec = 0
- ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
- tsp = &ts
+ var ut umtx_time
+ ut._clockid = _CLOCK_MONOTONIC
+ ut._timeout.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ut._timeout.tv_nsec)))))
+ utp = &ut
}
- ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, nil, tsp)
+ ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, unsafe.Sizeof(*utp), utp)
if ret >= 0 || ret == -_EINTR {
return
}
@@ -45,7 +45,7 @@ func futexsleep1(addr *uint32, val uint32, ns int64) {
//go:nosplit
func futexwakeup(addr *uint32, cnt uint32) {
- ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, nil, nil)
+ ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, 0, nil)
if ret >= 0 {
return
}
diff --git a/libgo/go/runtime/os_gccgo.go b/libgo/go/runtime/os_gccgo.go
index 1bdef7d43c2..a8f05a4b3d7 100644
--- a/libgo/go/runtime/os_gccgo.go
+++ b/libgo/go/runtime/os_gccgo.go
@@ -21,36 +21,15 @@ func mpreinit(mp *m) {
// minit is called to initialize a new m (including the bootstrap m).
// Called on the new thread, cannot allocate memory.
func minit() {
- // Initialize signal handling.
- _g_ := getg()
-
- var st _stack_t
- sigaltstack(nil, &st)
- if st.ss_flags&_SS_DISABLE != 0 {
- signalstack(_g_.m.gsignalstack, _g_.m.gsignalstacksize)
- _g_.m.newSigstack = true
- } else {
- _g_.m.newSigstack = false
- }
+ minitSignals()
// FIXME: We should set _g_.m.procid here.
-
- // restore signal mask from m.sigmask and unblock essential signals
- nmask := _g_.m.sigmask
- for i := range sigtable {
- if sigtable[i].flags&_SigUnblock != 0 {
- sigdelset(&nmask, int32(i))
- }
- }
- sigprocmask(_SIG_SETMASK, &nmask, nil)
}
// Called from dropm to undo the effect of an minit.
//go:nosplit
func unminit() {
- if getg().m.newSigstack {
- signalstack(nil, 0)
- }
+ unminitSignals()
}
var urandom_dev = []byte("/dev/urandom\x00")
diff --git a/libgo/go/runtime/os_linux.go b/libgo/go/runtime/os_linux.go
index 04c690bd42f..ad334869ed1 100644
--- a/libgo/go/runtime/os_linux.go
+++ b/libgo/go/runtime/os_linux.go
@@ -86,9 +86,13 @@ func futexwakeup(addr *uint32, cnt uint32) {
const (
_AT_NULL = 0 // End of vector
_AT_PAGESZ = 6 // System physical page size
+ _AT_HWCAP = 16 // hardware capability bit vector
_AT_RANDOM = 25 // introduced in 2.6.29
+ _AT_HWCAP2 = 26 // hardware capability bit vector 2
)
+var procAuxv = []byte("/proc/self/auxv\x00")
+
func sysargs(argc int32, argv **byte) {
n := argc + 1
@@ -102,7 +106,50 @@ func sysargs(argc int32, argv **byte) {
// now argv+n is auxv
auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
- for i := 0; auxv[i] != _AT_NULL; i += 2 {
+ if sysauxv(auxv[:]) == 0 {
+ // In some situations we don't get a loader-provided
+ // auxv, such as when loaded as a library on Android.
+ // Fall back to /proc/self/auxv.
+ fd := open(&procAuxv[0], 0 /* O_RDONLY */, 0)
+ if fd < 0 {
+ // On Android, /proc/self/auxv might be unreadable (issue 9229), so we fallback to
+ // try using mincore to detect the physical page size.
+ // mincore should return EINVAL when address is not a multiple of system page size.
+ const size = 256 << 10 // size of memory region to allocate
+ p := mmap(nil, size, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
+ if uintptr(p) < 4096 {
+ return
+ }
+ var n uintptr
+ for n = 4 << 10; n < size; n <<= 1 {
+ err := mincore(unsafe.Pointer(uintptr(p)+n), 1, &addrspace_vec[0])
+ if err == 0 {
+ physPageSize = n
+ break
+ }
+ }
+ if physPageSize == 0 {
+ physPageSize = size
+ }
+ munmap(p, size)
+ return
+ }
+ var buf [128]uintptr
+ n := read(fd, noescape(unsafe.Pointer(&buf[0])), int32(unsafe.Sizeof(buf)))
+ closefd(fd)
+ if n < 0 {
+ return
+ }
+ // Make sure buf is terminated, even if we didn't read
+ // the whole file.
+ buf[len(buf)-2] = _AT_NULL
+ sysauxv(buf[:])
+ }
+}
+
+func sysauxv(auxv []uintptr) int {
+ var i int
+ for ; auxv[i] != _AT_NULL; i += 2 {
tag, val := auxv[i], auxv[i+1]
switch tag {
case _AT_RANDOM:
@@ -111,20 +158,14 @@ func sysargs(argc int32, argv **byte) {
startupRandomData = (*[16]byte)(unsafe.Pointer(val))[:]
case _AT_PAGESZ:
- // Check that the true physical page size is
- // compatible with the runtime's assumed
- // physical page size.
- if sys.PhysPageSize < val {
- print("runtime: kernel page size (", val, ") is larger than runtime page size (", sys.PhysPageSize, ")\n")
- exit(1)
- }
- if sys.PhysPageSize%val != 0 {
- print("runtime: runtime page size (", sys.PhysPageSize, ") is not a multiple of kernel page size (", val, ")\n")
- exit(1)
- }
+ physPageSize = val
}
// Commented out for gccgo for now.
// archauxv(tag, val)
}
+ return i / 2
}
+
+// Temporary for gccgo until we port mem_GOOS.go.
+var addrspace_vec [1]byte
diff --git a/libgo/go/runtime/os_linux_ppc64x.go b/libgo/go/runtime/os_linux_ppc64x.go
new file mode 100644
index 00000000000..b324344493e
--- /dev/null
+++ b/libgo/go/runtime/os_linux_ppc64x.go
@@ -0,0 +1,61 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore_for_gccgo
+// +build ppc64 ppc64le
+
+package runtime
+
+import (
+ "runtime/internal/sys"
+)
+
+const (
+ // ISA level
+ // Go currently requires POWER5 as a minimum for ppc64, so we need
+ // to check for ISA 2.03 and beyond.
+ _PPC_FEATURE_POWER5_PLUS = 0x00020000 // ISA 2.03 (POWER5+)
+ _PPC_FEATURE_ARCH_2_05 = 0x00001000 // ISA 2.05 (POWER6)
+ _PPC_FEATURE_POWER6_EXT = 0x00000200 // mffgpr/mftgpr extension (POWER6x)
+ _PPC_FEATURE_ARCH_2_06 = 0x00000100 // ISA 2.06 (POWER7)
+ _PPC_FEATURE2_ARCH_2_07 = 0x80000000 // ISA 2.07 (POWER8)
+
+ // Standalone capabilities
+ _PPC_FEATURE_HAS_ALTIVEC = 0x10000000 // SIMD/Vector unit
+ _PPC_FEATURE_HAS_VSX = 0x00000080 // Vector scalar unit
+)
+
+type facilities struct {
+ _ [sys.CacheLineSize]byte
+ isPOWER5x bool // ISA 2.03
+ isPOWER6 bool // ISA 2.05
+ isPOWER6x bool // ISA 2.05 + mffgpr/mftgpr extension
+ isPOWER7 bool // ISA 2.06
+ isPOWER8 bool // ISA 2.07
+ hasVMX bool // Vector unit
+ hasVSX bool // Vector scalar unit
+ _ [sys.CacheLineSize]byte
+}
+
+// cpu can be tested at runtime in go assembler code to check for
+// a certain ISA level or hardware capability, for example:
+// ·cpu+facilities_hasVSX(SB) for checking the availability of VSX
+// or
+// ·cpu+facilities_isPOWER7(SB) for checking if the processor implements
+// ISA 2.06 instructions.
+var cpu facilities
+
+func archauxv(tag, val uintptr) {
+ switch tag {
+ case _AT_HWCAP:
+ cpu.isPOWER5x = val&_PPC_FEATURE_POWER5_PLUS != 0
+ cpu.isPOWER6 = val&_PPC_FEATURE_ARCH_2_05 != 0
+ cpu.isPOWER6x = val&_PPC_FEATURE_POWER6_EXT != 0
+ cpu.isPOWER7 = val&_PPC_FEATURE_ARCH_2_06 != 0
+ cpu.hasVMX = val&_PPC_FEATURE_HAS_ALTIVEC != 0
+ cpu.hasVSX = val&_PPC_FEATURE_HAS_VSX != 0
+ case _AT_HWCAP2:
+ cpu.isPOWER8 = val&_PPC_FEATURE2_ARCH_2_07 != 0
+ }
+}
diff --git a/libgo/go/runtime/panic.go b/libgo/go/runtime/panic.go
index f7e5efe363e..b76bb211914 100644
--- a/libgo/go/runtime/panic.go
+++ b/libgo/go/runtime/panic.go
@@ -78,10 +78,6 @@ func panicmem() {
panic(memoryError)
}
-func throwreturn() {
- throw("no return at end of a typed function - compiler is broken")
-}
-
func throwinit() {
throw("recursive call during initialization - linker skew")
}
@@ -108,17 +104,19 @@ func deferproc(frame *bool, pfn uintptr, arg unsafe.Pointer) {
// Each defer must be released with freedefer.
func newdefer() *_defer {
var d *_defer
- mp := acquirem()
- pp := mp.p.ptr()
+ gp := getg()
+ pp := gp.m.p.ptr()
if len(pp.deferpool) == 0 && sched.deferpool != nil {
- lock(&sched.deferlock)
- for len(pp.deferpool) < cap(pp.deferpool)/2 && sched.deferpool != nil {
- d := sched.deferpool
- sched.deferpool = d.link
- d.link = nil
- pp.deferpool = append(pp.deferpool, d)
- }
- unlock(&sched.deferlock)
+ systemstack(func() {
+ lock(&sched.deferlock)
+ for len(pp.deferpool) < cap(pp.deferpool)/2 && sched.deferpool != nil {
+ d := sched.deferpool
+ sched.deferpool = d.link
+ d.link = nil
+ pp.deferpool = append(pp.deferpool, d)
+ }
+ unlock(&sched.deferlock)
+ })
}
if n := len(pp.deferpool); n > 0 {
d = pp.deferpool[n-1]
@@ -126,17 +124,22 @@ func newdefer() *_defer {
pp.deferpool = pp.deferpool[:n-1]
}
if d == nil {
- d = new(_defer)
+ systemstack(func() {
+ d = new(_defer)
+ })
}
- gp := mp.curg
d.link = gp._defer
gp._defer = d
- releasem(mp)
return d
}
// Free the given defer.
// The defer cannot be used after this call.
+//
+// This must not grow the stack because there may be a frame without a
+// stack map when this is called.
+//
+//go:nosplit
func freedefer(d *_defer) {
if d.special {
return
@@ -150,31 +153,34 @@ func freedefer(d *_defer) {
return
}
- mp := acquirem()
- pp := mp.p.ptr()
+ pp := getg().m.p.ptr()
if len(pp.deferpool) == cap(pp.deferpool) {
// Transfer half of local cache to the central cache.
- var first, last *_defer
- for len(pp.deferpool) > cap(pp.deferpool)/2 {
- n := len(pp.deferpool)
- d := pp.deferpool[n-1]
- pp.deferpool[n-1] = nil
- pp.deferpool = pp.deferpool[:n-1]
- if first == nil {
- first = d
- } else {
- last.link = d
+ //
+ // Take this slow path on the system stack so
+ // we don't grow freedefer's stack.
+ systemstack(func() {
+ var first, last *_defer
+ for len(pp.deferpool) > cap(pp.deferpool)/2 {
+ n := len(pp.deferpool)
+ d := pp.deferpool[n-1]
+ pp.deferpool[n-1] = nil
+ pp.deferpool = pp.deferpool[:n-1]
+ if first == nil {
+ first = d
+ } else {
+ last.link = d
+ }
+ last = d
}
- last = d
- }
- lock(&sched.deferlock)
- last.link = sched.deferpool
- sched.deferpool = first
- unlock(&sched.deferlock)
+ lock(&sched.deferlock)
+ last.link = sched.deferpool
+ sched.deferpool = first
+ unlock(&sched.deferlock)
+ })
}
*d = _defer{}
pp.deferpool = append(pp.deferpool, d)
- releasem(mp)
}
// deferreturn is called to undefer the stack.
@@ -358,6 +364,11 @@ func Goexit() {
// Used when crashing with panicking.
// This must match types handled by printany.
func preprintpanics(p *_panic) {
+ defer func() {
+ if recover() != nil {
+ throw("panic while printing panic value")
+ }
+ }()
for p != nil {
switch v := p.arg.(type) {
case error:
@@ -731,6 +742,11 @@ func deferredrecover() interface{} {
return gorecover()
}
+//go:linkname sync_throw sync.throw
+func sync_throw(s string) {
+ throw(s)
+}
+
//go:nosplit
func throw(s string) {
print("fatal error: ", s, "\n")
@@ -769,7 +785,7 @@ func startpanic() {
freezetheworld()
return
case 1:
- // Something failed while panicing, probably the print of the
+ // Something failed while panicking, probably the print of the
// argument to panic(). Just print a stack trace and exit.
_g_.m.dying = 2
print("panic during panic\n")
diff --git a/libgo/go/runtime/pprof/internal/protopprof/protomemprofile.go b/libgo/go/runtime/pprof/internal/protopprof/protomemprofile.go
new file mode 100644
index 00000000000..c2ab5b57025
--- /dev/null
+++ b/libgo/go/runtime/pprof/internal/protopprof/protomemprofile.go
@@ -0,0 +1,83 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package protopprof
+
+import (
+ "internal/pprof/profile"
+ "math"
+ "runtime"
+ "time"
+)
+
+// EncodeMemProfile converts MemProfileRecords to a Profile.
+func EncodeMemProfile(mr []runtime.MemProfileRecord, rate int64, t time.Time) *profile.Profile {
+ p := &profile.Profile{
+ Period: rate,
+ PeriodType: &profile.ValueType{Type: "space", Unit: "bytes"},
+ SampleType: []*profile.ValueType{
+ {Type: "alloc_objects", Unit: "count"},
+ {Type: "alloc_space", Unit: "bytes"},
+ {Type: "inuse_objects", Unit: "count"},
+ {Type: "inuse_space", Unit: "bytes"},
+ },
+ TimeNanos: int64(t.UnixNano()),
+ }
+
+ locs := make(map[uintptr]*profile.Location)
+ for _, r := range mr {
+ stack := r.Stack()
+ sloc := make([]*profile.Location, len(stack))
+ for i, addr := range stack {
+ loc := locs[addr]
+ if loc == nil {
+ loc = &profile.Location{
+ ID: uint64(len(p.Location) + 1),
+ Address: uint64(addr),
+ }
+ locs[addr] = loc
+ p.Location = append(p.Location, loc)
+ }
+ sloc[i] = loc
+ }
+
+ ao, ab := scaleHeapSample(r.AllocObjects, r.AllocBytes, rate)
+ uo, ub := scaleHeapSample(r.InUseObjects(), r.InUseBytes(), rate)
+
+ p.Sample = append(p.Sample, &profile.Sample{
+ Value: []int64{ao, ab, uo, ub},
+ Location: sloc,
+ })
+ }
+ if runtime.GOOS == "linux" {
+ addMappings(p)
+ }
+ return p
+}
+
+// scaleHeapSample adjusts the data from a heap Sample to
+// account for its probability of appearing in the collected
+// data. heap profiles are a sampling of the memory allocations
+// requests in a program. We estimate the unsampled value by dividing
+// each collected sample by its probability of appearing in the
+// profile. heap profiles rely on a poisson process to determine
+// which samples to collect, based on the desired average collection
+// rate R. The probability of a sample of size S to appear in that
+// profile is 1-exp(-S/R).
+func scaleHeapSample(count, size, rate int64) (int64, int64) {
+ if count == 0 || size == 0 {
+ return 0, 0
+ }
+
+ if rate <= 1 {
+ // if rate==1 all samples were collected so no adjustment is needed.
+ // if rate<1 treat as unknown and skip scaling.
+ return count, size
+ }
+
+ avgSize := float64(size) / float64(count)
+ scale := 1 / (1 - math.Exp(-avgSize/float64(rate)))
+
+ return int64(float64(count) * scale), int64(float64(size) * scale)
+}
diff --git a/libgo/go/runtime/pprof/internal/protopprof/protomemprofile_test.go b/libgo/go/runtime/pprof/internal/protopprof/protomemprofile_test.go
new file mode 100644
index 00000000000..a10fe772ccf
--- /dev/null
+++ b/libgo/go/runtime/pprof/internal/protopprof/protomemprofile_test.go
@@ -0,0 +1,104 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package protopprof
+
+import (
+ "bytes"
+ "internal/pprof/profile"
+ "io/ioutil"
+ "reflect"
+ "runtime"
+ "testing"
+ "time"
+)
+
+// TestSampledHeapAllocProfile tests encoding of a memory profile from
+// runtime.MemProfileRecord data.
+func TestSampledHeapAllocProfile(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skip("Test requires a system with /proc/self/maps")
+ }
+
+ // Figure out two addresses from /proc/self/maps.
+ mmap, err := ioutil.ReadFile("/proc/self/maps")
+ if err != nil {
+ t.Fatal("Cannot read /proc/self/maps")
+ }
+ rd := bytes.NewReader(mmap)
+ mprof := &profile.Profile{}
+ if err = mprof.ParseMemoryMap(rd); err != nil {
+ t.Fatalf("Cannot parse /proc/self/maps")
+ }
+ if len(mprof.Mapping) < 2 {
+ // It is possible for a binary to only have 1 executable
+ // region of memory.
+ t.Skipf("need 2 or more mappings, got %v", len(mprof.Mapping))
+ }
+ address1 := mprof.Mapping[0].Start
+ address2 := mprof.Mapping[1].Start
+
+ var buf bytes.Buffer
+
+ rec, rate := testMemRecords(address1, address2)
+ p := EncodeMemProfile(rec, rate, time.Now())
+ if err := p.Write(&buf); err != nil {
+ t.Fatalf("Failed to write profile: %v", err)
+ }
+
+ p, err = profile.Parse(&buf)
+ if err != nil {
+ t.Fatalf("Could not parse Profile profile: %v", err)
+ }
+
+ // Expected PeriodType, SampleType and Sample.
+ expectedPeriodType := &profile.ValueType{Type: "space", Unit: "bytes"}
+ expectedSampleType := []*profile.ValueType{
+ {Type: "alloc_objects", Unit: "count"},
+ {Type: "alloc_space", Unit: "bytes"},
+ {Type: "inuse_objects", Unit: "count"},
+ {Type: "inuse_space", Unit: "bytes"},
+ }
+ // Expected samples, with values unsampled according to the profiling rate.
+ expectedSample := []*profile.Sample{
+ {Value: []int64{2050, 2099200, 1537, 1574400}, Location: []*profile.Location{
+ {ID: 1, Mapping: mprof.Mapping[0], Address: address1},
+ {ID: 2, Mapping: mprof.Mapping[1], Address: address2},
+ }},
+ {Value: []int64{1, 829411, 1, 829411}, Location: []*profile.Location{
+ {ID: 3, Mapping: mprof.Mapping[1], Address: address2 + 1},
+ {ID: 4, Mapping: mprof.Mapping[1], Address: address2 + 2},
+ }},
+ {Value: []int64{1, 829411, 0, 0}, Location: []*profile.Location{
+ {ID: 5, Mapping: mprof.Mapping[0], Address: address1 + 1},
+ {ID: 6, Mapping: mprof.Mapping[0], Address: address1 + 2},
+ {ID: 7, Mapping: mprof.Mapping[1], Address: address2 + 3},
+ }},
+ }
+
+ if p.Period != 512*1024 {
+ t.Fatalf("Sampling periods do not match")
+ }
+ if !reflect.DeepEqual(p.PeriodType, expectedPeriodType) {
+ t.Fatalf("Period types do not match")
+ }
+ if !reflect.DeepEqual(p.SampleType, expectedSampleType) {
+ t.Fatalf("Sample types do not match")
+ }
+ if !reflect.DeepEqual(p.Sample, expectedSample) {
+ t.Fatalf("Samples do not match: Expected: %v, Got:%v", getSampleAsString(expectedSample),
+ getSampleAsString(p.Sample))
+ }
+}
+
+func testMemRecords(a1, a2 uint64) ([]runtime.MemProfileRecord, int64) {
+ addr1, addr2 := uintptr(a1), uintptr(a2)
+ rate := int64(512 * 1024)
+ rec := []runtime.MemProfileRecord{
+ {4096, 1024, 4, 1, [32]uintptr{addr1, addr2}},
+ {512 * 1024, 0, 1, 0, [32]uintptr{addr2 + 1, addr2 + 2}},
+ {512 * 1024, 512 * 1024, 1, 1, [32]uintptr{addr1 + 1, addr1 + 2, addr2 + 3}},
+ }
+ return rec, rate
+}
diff --git a/libgo/go/runtime/pprof/internal/protopprof/protopprof.go b/libgo/go/runtime/pprof/internal/protopprof/protopprof.go
new file mode 100644
index 00000000000..5d269c4f652
--- /dev/null
+++ b/libgo/go/runtime/pprof/internal/protopprof/protopprof.go
@@ -0,0 +1,105 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package protopprof converts the runtime's raw profile logs
+// to Profile structs containing a representation of the pprof
+// protocol buffer profile format.
+package protopprof
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+ "time"
+ "unsafe"
+
+ "internal/pprof/profile"
+)
+
+// TranslateCPUProfile parses binary CPU profiling stack trace data
+// generated by runtime.CPUProfile() into a profile struct.
+func TranslateCPUProfile(b []byte, startTime time.Time) (*profile.Profile, error) {
+ const wordSize = unsafe.Sizeof(uintptr(0))
+ const minRawProfile = 5 * wordSize // Need a minimum of 5 words.
+ if uintptr(len(b)) < minRawProfile {
+ return nil, fmt.Errorf("truncated profile")
+ }
+ n := int(uintptr(len(b)) / wordSize)
+ data := ((*[1 << 28]uintptr)(unsafe.Pointer(&b[0])))[:n:n]
+ period := data[3]
+ data = data[5:] // skip header
+
+ // profile initialization taken from pprof tool
+ p := &profile.Profile{
+ Period: int64(period) * 1000,
+ PeriodType: &profile.ValueType{Type: "cpu", Unit: "nanoseconds"},
+ SampleType: []*profile.ValueType{
+ {Type: "samples", Unit: "count"},
+ {Type: "cpu", Unit: "nanoseconds"},
+ },
+ TimeNanos: int64(startTime.UnixNano()),
+ DurationNanos: time.Since(startTime).Nanoseconds(),
+ }
+ // Parse CPU samples from the profile.
+ locs := make(map[uint64]*profile.Location)
+ for len(b) > 0 {
+ if len(data) < 2 || uintptr(len(data)) < 2+data[1] {
+ return nil, fmt.Errorf("truncated profile")
+ }
+ count := data[0]
+ nstk := data[1]
+ if uintptr(len(data)) < 2+nstk {
+ return nil, fmt.Errorf("truncated profile")
+ }
+ stk := data[2 : 2+nstk]
+ data = data[2+nstk:]
+
+ if count == 0 && nstk == 1 && stk[0] == 0 {
+ // end of data marker
+ break
+ }
+
+ sloc := make([]*profile.Location, len(stk))
+ for i, addr := range stk {
+ addr := uint64(addr)
+ // Addresses from stack traces point to the next instruction after
+ // each call. Adjust by -1 to land somewhere on the actual call
+ // (except for the leaf, which is not a call).
+ if i > 0 {
+ addr--
+ }
+ loc := locs[addr]
+ if loc == nil {
+ loc = &profile.Location{
+ ID: uint64(len(p.Location) + 1),
+ Address: addr,
+ }
+ locs[addr] = loc
+ p.Location = append(p.Location, loc)
+ }
+ sloc[i] = loc
+ }
+ p.Sample = append(p.Sample, &profile.Sample{
+ Value: []int64{int64(count), int64(count) * int64(p.Period)},
+ Location: sloc,
+ })
+ }
+
+ if runtime.GOOS == "linux" {
+ if err := addMappings(p); err != nil {
+ return nil, err
+ }
+ }
+ return p, nil
+}
+
+func addMappings(p *profile.Profile) error {
+ // Parse memory map from /proc/self/maps
+ f, err := os.Open("/proc/self/maps")
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ return p.ParseMemoryMap(f)
+}
diff --git a/libgo/go/runtime/pprof/internal/protopprof/protopprof_test.go b/libgo/go/runtime/pprof/internal/protopprof/protopprof_test.go
new file mode 100644
index 00000000000..f1937b5bd06
--- /dev/null
+++ b/libgo/go/runtime/pprof/internal/protopprof/protopprof_test.go
@@ -0,0 +1,171 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package protopprof
+
+import (
+ "bytes"
+ "fmt"
+ "internal/pprof/profile"
+ "io/ioutil"
+ "reflect"
+ "runtime"
+ "testing"
+ "time"
+ "unsafe"
+)
+
+// Helper function to initialize empty cpu profile with sampling period provided.
+func createEmptyProfileWithPeriod(t *testing.T, periodMs uint64) bytes.Buffer {
+ // Mock the sample header produced by cpu profiler. Write a sample
+ // period of 2000 microseconds, followed by no samples.
+ buf := new(bytes.Buffer)
+ // Profile header is as follows:
+ // The first, third and fifth words are 0. The second word is 3.
+ // The fourth word is the period.
+ // EOD marker:
+ // The sixth word -- count is initialized to 0 above.
+ // The code below sets the seventh word -- nstk to 1
+ // The eighth word -- addr is initialized to 0 above.
+ words := []int{0, 3, 0, int(periodMs), 0, 0, 1, 0}
+ n := int(unsafe.Sizeof(0)) * len(words)
+ data := ((*[1 << 29]byte)(unsafe.Pointer(&words[0])))[:n:n]
+ if _, err := buf.Write(data); err != nil {
+ t.Fatalf("createEmptyProfileWithPeriod failed: %v", err)
+ }
+ return *buf
+}
+
+// Helper function to initialize cpu profile with two sample values.
+func createProfileWithTwoSamples(t *testing.T, periodMs uintptr, count1 uintptr, count2 uintptr,
+ address1 uintptr, address2 uintptr) bytes.Buffer {
+ // Mock the sample header produced by cpu profiler. Write a sample
+ // period of 2000 microseconds, followed by no samples.
+ buf := new(bytes.Buffer)
+ words := []uintptr{0, 3, 0, uintptr(periodMs), 0, uintptr(count1), 2,
+ uintptr(address1), uintptr(address1 + 2),
+ uintptr(count2), 2, uintptr(address2), uintptr(address2 + 2),
+ 0, 1, 0}
+ for _, n := range words {
+ var err error
+ switch unsafe.Sizeof(int(0)) {
+ case 8:
+ _, err = buf.Write((*[8]byte)(unsafe.Pointer(&n))[:8:8])
+ case 4:
+ _, err = buf.Write((*[4]byte)(unsafe.Pointer(&n))[:4:4])
+ }
+ if err != nil {
+ t.Fatalf("createProfileWithTwoSamples failed: %v", err)
+ }
+ }
+ return *buf
+}
+
+// Tests TranslateCPUProfile parses correct sampling period in an otherwise empty cpu profile.
+func TestTranlateCPUProfileSamplingPeriod(t *testing.T) {
+ // A test server with mock cpu profile data.
+ var buf bytes.Buffer
+
+ startTime := time.Now()
+ b := createEmptyProfileWithPeriod(t, 2000)
+ p, err := TranslateCPUProfile(b.Bytes(), startTime)
+ if err != nil {
+ t.Fatalf("translate failed: %v", err)
+ }
+ if err := p.Write(&buf); err != nil {
+ t.Fatalf("write failed: %v", err)
+ }
+
+ p, err = profile.Parse(&buf)
+ if err != nil {
+ t.Fatalf("Could not parse Profile profile: %v", err)
+ }
+
+ // Expected PeriodType and SampleType.
+ expectedPeriodType := &profile.ValueType{Type: "cpu", Unit: "nanoseconds"}
+ expectedSampleType := []*profile.ValueType{
+ {Type: "samples", Unit: "count"},
+ {Type: "cpu", Unit: "nanoseconds"},
+ }
+ if p.Period != 2000*1000 || !reflect.DeepEqual(p.PeriodType, expectedPeriodType) ||
+ !reflect.DeepEqual(p.SampleType, expectedSampleType) || p.Sample != nil {
+ t.Fatalf("Unexpected Profile fields")
+ }
+}
+
+func getSampleAsString(sample []*profile.Sample) string {
+ var str string
+ for _, x := range sample {
+ for _, y := range x.Location {
+ if y.Mapping != nil {
+ str += fmt.Sprintf("Mapping:%v\n", *y.Mapping)
+ }
+ str += fmt.Sprintf("Location:%v\n", y)
+ }
+ str += fmt.Sprintf("Sample:%v\n", *x)
+ }
+ return str
+}
+
+// Tests TranslateCPUProfile parses a cpu profile with sample values present.
+func TestTranslateCPUProfileWithSamples(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skip("test requires a system with /proc/self/maps")
+ }
+ // Figure out two addresses from /proc/self/maps.
+ mmap, err := ioutil.ReadFile("/proc/self/maps")
+ if err != nil {
+ t.Fatal("Cannot read /proc/self/maps")
+ }
+ rd := bytes.NewReader(mmap)
+ mprof := &profile.Profile{}
+ if err = mprof.ParseMemoryMap(rd); err != nil {
+ t.Fatalf("Cannot parse /proc/self/maps")
+ }
+ if len(mprof.Mapping) < 2 {
+ // It is possible for a binary to only have 1 executable
+ // region of memory.
+ t.Skipf("need 2 or more mappings, got %v", len(mprof.Mapping))
+ }
+ address1 := mprof.Mapping[0].Start
+ address2 := mprof.Mapping[1].Start
+ // A test server with mock cpu profile data.
+
+ startTime := time.Now()
+ b := createProfileWithTwoSamples(t, 2000, 20, 40, uintptr(address1), uintptr(address2))
+ p, err := TranslateCPUProfile(b.Bytes(), startTime)
+
+ if err != nil {
+ t.Fatalf("Could not parse Profile profile: %v", err)
+ }
+ // Expected PeriodType, SampleType and Sample.
+ expectedPeriodType := &profile.ValueType{Type: "cpu", Unit: "nanoseconds"}
+ expectedSampleType := []*profile.ValueType{
+ {Type: "samples", Unit: "count"},
+ {Type: "cpu", Unit: "nanoseconds"},
+ }
+ expectedSample := []*profile.Sample{
+ {Value: []int64{20, 20 * 2000 * 1000}, Location: []*profile.Location{
+ {ID: 1, Mapping: mprof.Mapping[0], Address: address1},
+ {ID: 2, Mapping: mprof.Mapping[0], Address: address1 + 1},
+ }},
+ {Value: []int64{40, 40 * 2000 * 1000}, Location: []*profile.Location{
+ {ID: 3, Mapping: mprof.Mapping[1], Address: address2},
+ {ID: 4, Mapping: mprof.Mapping[1], Address: address2 + 1},
+ }},
+ }
+ if p.Period != 2000*1000 {
+ t.Fatalf("Sampling periods do not match")
+ }
+ if !reflect.DeepEqual(p.PeriodType, expectedPeriodType) {
+ t.Fatalf("Period types do not match")
+ }
+ if !reflect.DeepEqual(p.SampleType, expectedSampleType) {
+ t.Fatalf("Sample types do not match")
+ }
+ if !reflect.DeepEqual(p.Sample, expectedSample) {
+ t.Fatalf("Samples do not match: Expected: %v, Got:%v", getSampleAsString(expectedSample),
+ getSampleAsString(p.Sample))
+ }
+}
diff --git a/libgo/go/runtime/pprof/mprof_test.go b/libgo/go/runtime/pprof/mprof_test.go
index 54daefa23d7..079af15588d 100644
--- a/libgo/go/runtime/pprof/mprof_test.go
+++ b/libgo/go/runtime/pprof/mprof_test.go
@@ -7,6 +7,7 @@ package pprof_test
import (
"bytes"
"fmt"
+ "reflect"
"regexp"
"runtime"
. "runtime/pprof"
@@ -42,6 +43,17 @@ func allocatePersistent1K() {
}
}
+// Allocate transient memory using reflect.Call.
+
+func allocateReflectTransient() {
+ memSink = make([]byte, 2<<20)
+}
+
+func allocateReflect() {
+ rv := reflect.ValueOf(allocateReflectTransient)
+ rv.Call(nil)
+}
+
var memoryProfilerRun = 0
func TestMemoryProfiler(t *testing.T) {
@@ -61,6 +73,7 @@ func TestMemoryProfiler(t *testing.T) {
allocateTransient1M()
allocateTransient2M()
allocatePersistent1K()
+ allocateReflect()
memSink = nil
runtime.GC() // materialize stats
@@ -74,21 +87,25 @@ func TestMemoryProfiler(t *testing.T) {
tests := []string{
fmt.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f x]+
-# 0x[0-9,a-f]+ pprof_test\.allocatePersistent1K\+0x[0-9,a-f]+ .*/mprof_test\.go:40
-# 0x[0-9,a-f]+ runtime_pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test\.go:63
+# 0x[0-9,a-f]+ pprof_test\.allocatePersistent1K\+0x[0-9,a-f]+ .*/mprof_test\.go:41
+# 0x[0-9,a-f]+ runtime_pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test\.go:75
`, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun),
fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f x]+
-# 0x[0-9,a-f]+ pprof_test\.allocateTransient1M\+0x[0-9,a-f]+ .*/mprof_test.go:21
-# 0x[0-9,a-f]+ runtime_pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:61
+# 0x[0-9,a-f]+ pprof_test\.allocateTransient1M\+0x[0-9,a-f]+ .*/mprof_test.go:22
+# 0x[0-9,a-f]+ runtime_pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:73
`, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun),
// This should start with "0: 0" but gccgo's imprecise
// GC means that sometimes the value is not collected.
fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+
-# 0x[0-9,a-f]+ pprof_test\.allocateTransient2M\+0x[0-9,a-f]+ .*/mprof_test.go:27
-# 0x[0-9,a-f]+ runtime_pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:62
+# 0x[0-9,a-f]+ pprof_test\.allocateTransient2M\+0x[0-9,a-f]+ .*/mprof_test.go:28
+# 0x[0-9,a-f]+ runtime_pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:74
`, memoryProfilerRun, (2<<20)*memoryProfilerRun, memoryProfilerRun, (2<<20)*memoryProfilerRun),
+
+ fmt.Sprintf(`0: 0 \[%v: %v\] @( 0x[0-9,a-f]+)+
+# 0x[0-9,a-f]+ pprof_test\.allocateReflectTransient\+0x[0-9,a-f]+ .*/mprof_test.go:49
+`, memoryProfilerRun, (2<<20)*memoryProfilerRun),
}
for _, test := range tests {
diff --git a/libgo/go/runtime/pprof/pprof.go b/libgo/go/runtime/pprof/pprof.go
index 0a58bafd85f..0db1dedd7ac 100644
--- a/libgo/go/runtime/pprof/pprof.go
+++ b/libgo/go/runtime/pprof/pprof.go
@@ -73,13 +73,15 @@ import (
"bufio"
"bytes"
"fmt"
+ "internal/pprof/profile"
"io"
- "os"
"runtime"
+ "runtime/pprof/internal/protopprof"
"sort"
"strings"
"sync"
"text/tabwriter"
+ "time"
)
// BUG(rsc): Profiles are only as good as the kernel support used to generate them.
@@ -99,6 +101,7 @@ import (
// heap - a sampling of all heap allocations
// threadcreate - stack traces that led to the creation of new OS threads
// block - stack traces that led to blocking on synchronization primitives
+// mutex - stack traces of holders of contended mutexes
//
// These predefined profiles maintain themselves and panic on an explicit
// Add or Remove method call.
@@ -152,6 +155,12 @@ var blockProfile = &Profile{
write: writeBlock,
}
+var mutexProfile = &Profile{
+ name: "mutex",
+ count: countMutex,
+ write: writeMutex,
+}
+
func lockProfiles() {
profiles.mu.Lock()
if profiles.m == nil {
@@ -161,6 +170,7 @@ func lockProfiles() {
"threadcreate": threadcreateProfile,
"heap": heapProfile,
"block": blockProfile,
+ "mutex": mutexProfile,
}
}
}
@@ -202,21 +212,15 @@ func Profiles() []*Profile {
lockProfiles()
defer unlockProfiles()
- var all []*Profile
+ all := make([]*Profile, 0, len(profiles.m))
for _, p := range profiles.m {
all = append(all, p)
}
- sort.Sort(byName(all))
+ sort.Slice(all, func(i, j int) bool { return all[i].name < all[j].name })
return all
}
-type byName []*Profile
-
-func (x byName) Len() int { return len(x) }
-func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
-func (x byName) Less(i, j int) bool { return x[i].name < x[j].name }
-
// Name returns this profile's name, which can be passed to Lookup to reobtain the profile.
func (p *Profile) Name() string {
return p.name
@@ -299,7 +303,7 @@ func (p *Profile) WriteTo(w io.Writer, debug int) error {
}
// Obtain consistent snapshot under lock; then process without lock.
- var all [][]uintptr
+ all := make([][]uintptr, 0, len(p.m))
p.mu.Lock()
for _, stk := range p.m {
all = append(all, stk)
@@ -337,17 +341,8 @@ type countProfile interface {
}
// printCountProfile prints a countProfile at the specified debug level.
+// The profile will be in compressed proto format unless debug is nonzero.
func printCountProfile(w io.Writer, debug int, name string, p countProfile) error {
- b := bufio.NewWriter(w)
- var tw *tabwriter.Writer
- w = b
- if debug > 0 {
- tw = tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
- w = tw
- }
-
- fmt.Fprintf(w, "%s profile: total %d\n", name, p.Len())
-
// Build count of each stack.
var buf bytes.Buffer
key := func(stk []uintptr) string {
@@ -373,17 +368,47 @@ func printCountProfile(w io.Writer, debug int, name string, p countProfile) erro
sort.Sort(&keysByCount{keys, count})
- for _, k := range keys {
- fmt.Fprintf(w, "%d %s\n", count[k], k)
- if debug > 0 {
- printStackRecord(w, p.Stack(index[k]), false)
+ if debug > 0 {
+ // Print debug profile in legacy format
+ tw := tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
+ fmt.Fprintf(tw, "%s profile: total %d\n", name, p.Len())
+ for _, k := range keys {
+ fmt.Fprintf(tw, "%d %s\n", count[k], k)
+ printStackRecord(tw, p.Stack(index[k]), false)
}
+ return tw.Flush()
}
- if tw != nil {
- tw.Flush()
+ // Output profile in protobuf form.
+ prof := &profile.Profile{
+ PeriodType: &profile.ValueType{Type: name, Unit: "count"},
+ Period: 1,
+ Sample: make([]*profile.Sample, 0, len(keys)),
+ SampleType: []*profile.ValueType{{Type: name, Unit: "count"}},
}
- return b.Flush()
+ locMap := make(map[uintptr]*profile.Location)
+ for _, k := range keys {
+ stk := p.Stack(index[k])
+ c := count[k]
+ locs := make([]*profile.Location, len(stk))
+ for i, addr := range stk {
+ loc := locMap[addr]
+ if loc == nil {
+ loc = &profile.Location{
+ ID: uint64(len(locMap) + 1),
+ Address: uint64(addr - 1),
+ }
+ prof.Location = append(prof.Location, loc)
+ locMap[addr] = loc
+ }
+ locs[i] = loc
+ }
+ prof.Sample = append(prof.Sample, &profile.Sample{
+ Location: locs,
+ Value: []int64{int64(c)},
+ })
+ }
+ return prof.Write(w)
}
// keysByCount sorts keys with higher counts first, breaking ties by key string order.
@@ -449,12 +474,6 @@ func printStackRecord(w io.Writer, stk []uintptr, allFrames bool) {
// Interface to system profiles.
-type byInUseBytes []runtime.MemProfileRecord
-
-func (x byInUseBytes) Len() int { return len(x) }
-func (x byInUseBytes) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
-func (x byInUseBytes) Less(i, j int) bool { return x[i].InUseBytes() > x[j].InUseBytes() }
-
// WriteHeapProfile is shorthand for Lookup("heap").WriteTo(w, 0).
// It is preserved for backwards compatibility.
func WriteHeapProfile(w io.Writer) error {
@@ -490,15 +509,16 @@ func writeHeap(w io.Writer, debug int) error {
// Profile grew; try again.
}
- sort.Sort(byInUseBytes(p))
+ if debug == 0 {
+ pp := protopprof.EncodeMemProfile(p, int64(runtime.MemProfileRate), time.Now())
+ return pp.Write(w)
+ }
+
+ sort.Slice(p, func(i, j int) bool { return p[i].InUseBytes() > p[j].InUseBytes() })
b := bufio.NewWriter(w)
- var tw *tabwriter.Writer
- w = b
- if debug > 0 {
- tw = tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
- w = tw
- }
+ tw := tabwriter.NewWriter(b, 1, 8, 1, '\t', 0)
+ w = tw
var total runtime.MemProfileRecord
for i := range p {
@@ -526,9 +546,7 @@ func writeHeap(w io.Writer, debug int) error {
fmt.Fprintf(w, " %#x", pc)
}
fmt.Fprintf(w, "\n")
- if debug > 0 {
- printStackRecord(w, r.Stack(), false)
- }
+ printStackRecord(w, r.Stack(), false)
}
// Print memstats information too.
@@ -554,15 +572,15 @@ func writeHeap(w io.Writer, debug int) error {
fmt.Fprintf(w, "# MSpan = %d / %d\n", s.MSpanInuse, s.MSpanSys)
fmt.Fprintf(w, "# MCache = %d / %d\n", s.MCacheInuse, s.MCacheSys)
fmt.Fprintf(w, "# BuckHashSys = %d\n", s.BuckHashSys)
+ fmt.Fprintf(w, "# GCSys = %d\n", s.GCSys)
+ fmt.Fprintf(w, "# OtherSys = %d\n", s.OtherSys)
fmt.Fprintf(w, "# NextGC = %d\n", s.NextGC)
fmt.Fprintf(w, "# PauseNs = %d\n", s.PauseNs)
fmt.Fprintf(w, "# NumGC = %d\n", s.NumGC)
fmt.Fprintf(w, "# DebugGC = %v\n", s.DebugGC)
- if tw != nil {
- tw.Flush()
- }
+ tw.Flush()
return b.Flush()
}
@@ -686,49 +704,29 @@ func StartCPUProfile(w io.Writer) error {
}
func profileWriter(w io.Writer) {
+ startTime := time.Now()
+ // This will buffer the entire profile into buf and then
+ // translate it into a profile.Profile structure. This will
+ // create two copies of all the data in the profile in memory.
+ // TODO(matloob): Convert each chunk of the proto output and
+ // stream it out instead of converting the entire profile.
+ var buf bytes.Buffer
for {
data := runtime.CPUProfile()
if data == nil {
break
}
- w.Write(data)
- }
-
- // We are emitting the legacy profiling format, which permits
- // a memory map following the CPU samples. The memory map is
- // simply a copy of the GNU/Linux /proc/self/maps file. The
- // profiler uses the memory map to map PC values in shared
- // libraries to a shared library in the filesystem, in order
- // to report the correct function and, if the shared library
- // has debug info, file/line. This is particularly useful for
- // PIE (position independent executables) as on ELF systems a
- // PIE is simply an executable shared library.
- //
- // Because the profiling format expects the memory map in
- // GNU/Linux format, we only do this on GNU/Linux for now. To
- // add support for profiling PIE on other ELF-based systems,
- // it may be necessary to map the system-specific mapping
- // information to the GNU/Linux format. For a reasonably
- // portable C++ version, see the FillProcSelfMaps function in
- // https://github.com/gperftools/gperftools/blob/master/src/base/sysinfo.cc
- //
- // The code that parses this mapping for the pprof tool is
- // ParseMemoryMap in cmd/internal/pprof/legacy_profile.go, but
- // don't change that code, as similar code exists in other
- // (non-Go) pprof readers. Change this code so that that code works.
- //
- // We ignore errors reading or copying the memory map; the
- // profile is likely usable without it, and we have no good way
- // to report errors.
- if runtime.GOOS == "linux" {
- f, err := os.Open("/proc/self/maps")
- if err == nil {
- io.WriteString(w, "\nMAPPED_LIBRARIES:\n")
- io.Copy(w, f)
- f.Close()
- }
+ buf.Write(data)
+ }
+
+ profile, err := protopprof.TranslateCPUProfile(buf.Bytes(), startTime)
+ if err != nil {
+ // The runtime should never produce an invalid or truncated profile.
+ // It drops records that can't fit into its log buffers.
+ panic(fmt.Errorf("could not translate binary profile to proto format: %v", err))
}
+ profile.Write(w)
cpu.done <- true
}
@@ -747,18 +745,18 @@ func StopCPUProfile() {
<-cpu.done
}
-type byCycles []runtime.BlockProfileRecord
-
-func (x byCycles) Len() int { return len(x) }
-func (x byCycles) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
-func (x byCycles) Less(i, j int) bool { return x[i].Cycles > x[j].Cycles }
-
// countBlock returns the number of records in the blocking profile.
func countBlock() int {
n, _ := runtime.BlockProfile(nil)
return n
}
+// countMutex returns the number of records in the mutex profile.
+func countMutex() int {
+ n, _ := runtime.MutexProfile(nil)
+ return n
+}
+
// writeBlock writes the current blocking profile to w.
func writeBlock(w io.Writer, debug int) error {
var p []runtime.BlockProfileRecord
@@ -772,7 +770,7 @@ func writeBlock(w io.Writer, debug int) error {
}
}
- sort.Sort(byCycles(p))
+ sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles })
b := bufio.NewWriter(w)
var tw *tabwriter.Writer
@@ -802,4 +800,49 @@ func writeBlock(w io.Writer, debug int) error {
return b.Flush()
}
+// writeMutex writes the current mutex profile to w.
+func writeMutex(w io.Writer, debug int) error {
+ // TODO(pjw): too much common code with writeBlock. FIX!
+ var p []runtime.BlockProfileRecord
+ n, ok := runtime.MutexProfile(nil)
+ for {
+ p = make([]runtime.BlockProfileRecord, n+50)
+ n, ok = runtime.MutexProfile(p)
+ if ok {
+ p = p[:n]
+ break
+ }
+ }
+
+ sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles })
+
+ b := bufio.NewWriter(w)
+ var tw *tabwriter.Writer
+ w = b
+ if debug > 0 {
+ tw = tabwriter.NewWriter(w, 1, 8, 1, '\t', 0)
+ w = tw
+ }
+
+ fmt.Fprintf(w, "--- mutex:\n")
+ fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond())
+ fmt.Fprintf(w, "sampling period=%d\n", runtime.SetMutexProfileFraction(-1))
+ for i := range p {
+ r := &p[i]
+ fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count)
+ for _, pc := range r.Stack() {
+ fmt.Fprintf(w, " %#x", pc)
+ }
+ fmt.Fprint(w, "\n")
+ if debug > 0 {
+ printStackRecord(w, r.Stack(), true)
+ }
+ }
+
+ if tw != nil {
+ tw.Flush()
+ }
+ return b.Flush()
+}
+
func runtime_cyclesPerSecond() int64
diff --git a/libgo/go/runtime/pprof/pprof_test.go b/libgo/go/runtime/pprof/pprof_test.go
index 1692d4210b7..60340582d5f 100644
--- a/libgo/go/runtime/pprof/pprof_test.go
+++ b/libgo/go/runtime/pprof/pprof_test.go
@@ -8,8 +8,12 @@ package pprof_test
import (
"bytes"
+ "compress/gzip"
"fmt"
+ "internal/pprof/profile"
"internal/testenv"
+ "io"
+ "io/ioutil"
"math/big"
"os"
"os/exec"
@@ -20,7 +24,6 @@ import (
"sync"
"testing"
"time"
- "unsafe"
)
func cpuHogger(f func(), dur time.Duration) {
@@ -87,40 +90,17 @@ func TestCPUProfileMultithreaded(t *testing.T) {
}
func parseProfile(t *testing.T, valBytes []byte, f func(uintptr, []uintptr)) {
- // Convert []byte to []uintptr.
- l := len(valBytes)
- if i := bytes.Index(valBytes, []byte("\nMAPPED_LIBRARIES:\n")); i >= 0 {
- l = i
- }
- l /= int(unsafe.Sizeof(uintptr(0)))
- val := *(*[]uintptr)(unsafe.Pointer(&valBytes))
- val = val[:l]
-
- // 5 for the header, 3 for the trailer.
- if l < 5+3 {
- t.Logf("profile too short: %#x", val)
- if badOS[runtime.GOOS] {
- t.Skipf("ignoring failure on %s; see golang.org/issue/13841", runtime.GOOS)
- return
- }
- t.FailNow()
- }
-
- hd, val, tl := val[:5], val[5:l-3], val[l-3:]
- if hd[0] != 0 || hd[1] != 3 || hd[2] != 0 || hd[3] != 1e6/100 || hd[4] != 0 {
- t.Fatalf("unexpected header %#x", hd)
- }
-
- if tl[0] != 0 || tl[1] != 1 || tl[2] != 0 {
- t.Fatalf("malformed end-of-data marker %#x", tl)
+ p, err := profile.Parse(bytes.NewReader(valBytes))
+ if err != nil {
+ t.Fatal(err)
}
-
- for len(val) > 0 {
- if len(val) < 2 || val[0] < 1 || val[1] < 1 || uintptr(len(val)) < 2+val[1] {
- t.Fatalf("malformed profile. leftover: %#x", val)
+ for _, sample := range p.Sample {
+ count := uintptr(sample.Value[0])
+ stk := make([]uintptr, len(sample.Location))
+ for i := range sample.Location {
+ stk[i] = uintptr(sample.Location[i].Address)
}
- f(val[0], val[2:2+val[1]])
- val = val[2+val[1]:]
+ f(count, stk)
}
}
@@ -225,7 +205,11 @@ func profileOk(t *testing.T, need []string, prof bytes.Buffer, duration time.Dur
}
// Check that we got a reasonable number of samples.
- if ideal := uintptr(duration * 100 / time.Second); samples == 0 || samples < ideal/4 {
+ // We used to always require at least ideal/4 samples,
+ // but that is too hard to guarantee on a loaded system.
+ // Now we accept 10 or more samples, which we take to be
+ // enough to show that at least some profiling is occurring.
+ if ideal := uintptr(duration * 100 / time.Second); samples == 0 || (samples < ideal/4 && samples < 10) {
t.Logf("too few samples; got %d, want at least %d, ideally %d", samples, ideal/4, ideal)
ok = false
}
@@ -367,8 +351,49 @@ func TestMathBigDivide(t *testing.T) {
})
}
+func slurpString(r io.Reader) string {
+ slurp, _ := ioutil.ReadAll(r)
+ return string(slurp)
+}
+
+func getLinuxKernelConfig() string {
+ if f, err := os.Open("/proc/config"); err == nil {
+ defer f.Close()
+ return slurpString(f)
+ }
+ if f, err := os.Open("/proc/config.gz"); err == nil {
+ defer f.Close()
+ r, err := gzip.NewReader(f)
+ if err != nil {
+ return ""
+ }
+ return slurpString(r)
+ }
+ if f, err := os.Open("/boot/config"); err == nil {
+ defer f.Close()
+ return slurpString(f)
+ }
+ uname, _ := exec.Command("uname", "-r").Output()
+ if len(uname) > 0 {
+ if f, err := os.Open("/boot/config-" + strings.TrimSpace(string(uname))); err == nil {
+ defer f.Close()
+ return slurpString(f)
+ }
+ }
+ return ""
+}
+
+func haveLinuxHiresTimers() bool {
+ config := getLinuxKernelConfig()
+ return strings.Contains(config, "CONFIG_HIGH_RES_TIMERS=y")
+}
+
func TestStackBarrierProfiling(t *testing.T) {
- if (runtime.GOOS == "linux" && runtime.GOARCH == "arm") || runtime.GOOS == "openbsd" || runtime.GOOS == "solaris" || runtime.GOOS == "dragonfly" || runtime.GOOS == "freebsd" {
+ if (runtime.GOOS == "linux" && runtime.GOARCH == "arm") ||
+ runtime.GOOS == "openbsd" ||
+ runtime.GOOS == "solaris" ||
+ runtime.GOOS == "dragonfly" ||
+ runtime.GOOS == "freebsd" {
// This test currently triggers a large number of
// usleep(100)s. These kernels/arches have poor
// resolution timers, so this gives up a whole
@@ -381,6 +406,12 @@ func TestStackBarrierProfiling(t *testing.T) {
return
}
+ if runtime.GOOS == "linux" && strings.HasPrefix(runtime.GOARCH, "mips") {
+ if !haveLinuxHiresTimers() {
+ t.Skipf("low resolution timers inhibit profiling signals (golang.org/issue/13405, golang.org/issue/17936)")
+ }
+ }
+
if !strings.Contains(os.Getenv("GODEBUG"), "gcstackbarrierall=1") {
// Re-execute this test with constant GC and stack
// barriers at every frame.
@@ -594,6 +625,50 @@ func blockCond() {
mu.Unlock()
}
+func TestMutexProfile(t *testing.T) {
+ old := runtime.SetMutexProfileFraction(1)
+ defer runtime.SetMutexProfileFraction(old)
+ if old != 0 {
+ t.Fatalf("need MutexProfileRate 0, got %d", old)
+ }
+
+ blockMutex()
+
+ var w bytes.Buffer
+ Lookup("mutex").WriteTo(&w, 1)
+ prof := w.String()
+
+ if !strings.HasPrefix(prof, "--- mutex:\ncycles/second=") {
+ t.Errorf("Bad profile header:\n%v", prof)
+ }
+ prof = strings.Trim(prof, "\n")
+ lines := strings.Split(prof, "\n")
+ // gccgo adds an extra line in the stack trace, not sure why.
+ if len(lines) < 6 {
+ t.Errorf("expected 6 lines, got %d %q\n%s", len(lines), prof, prof)
+ }
+ if len(lines) < 6 {
+ return
+ }
+ // checking that the line is like "35258904 1 @ 0x48288d 0x47cd28 0x458931"
+ r2 := `^\d+ 1 @(?: 0x[[:xdigit:]]+)+`
+ //r2 := "^[0-9]+ 1 @ 0x[0-9a-f x]+$"
+ if ok, err := regexp.MatchString(r2, lines[3]); err != nil || !ok {
+ t.Errorf("%q didn't match %q", lines[3], r2)
+ }
+ r3 := "^#.*pprof_test.\\$nested.*$"
+ match := false
+ for _, i := range []int{5, 6} {
+ if ok, _ := regexp.MatchString(r3, lines[i]); ok {
+ match = true
+ break
+ }
+ }
+ if !match {
+ t.Errorf("neither %q nor %q matched %q", lines[5], lines[6], r3)
+ }
+}
+
func func1(c chan int) { <-c }
func func2(c chan int) { <-c }
func func3(c chan int) { <-c }
@@ -621,13 +696,31 @@ func TestGoroutineCounts(t *testing.T) {
time.Sleep(10 * time.Millisecond) // let goroutines block on channel
var w bytes.Buffer
- Lookup("goroutine").WriteTo(&w, 1)
+ goroutineProf := Lookup("goroutine")
+
+ // Check debug profile
+ goroutineProf.WriteTo(&w, 1)
prof := w.String()
if !containsInOrder(prof, "\n50 @ ", "\n40 @", "\n10 @", "\n1 @") {
t.Errorf("expected sorted goroutine counts:\n%s", prof)
}
+ // Check proto profile
+ w.Reset()
+ goroutineProf.WriteTo(&w, 0)
+ p, err := profile.Parse(&w)
+ if err != nil {
+ t.Errorf("error parsing protobuf profile: %v", err)
+ }
+ if err := p.CheckValid(); err != nil {
+ t.Errorf("protobuf profile is invalid: %v", err)
+ }
+ if !containsCounts(p, []int64{50, 40, 10, 1}) {
+ t.Errorf("expected count profile to contain goroutines with counts %v, got %v",
+ []int64{50, 40, 10, 1}, p)
+ }
+
close(c)
time.Sleep(10 * time.Millisecond) // let goroutines exit
@@ -643,3 +736,23 @@ func containsInOrder(s string, all ...string) bool {
}
return true
}
+
+func containsCounts(prof *profile.Profile, counts []int64) bool {
+ m := make(map[int64]int)
+ for _, c := range counts {
+ m[c]++
+ }
+ for _, s := range prof.Sample {
+ // The count is the single value in the sample
+ if len(s.Value) != 1 {
+ return false
+ }
+ m[s.Value[0]]--
+ }
+ for _, n := range m {
+ if n > 0 {
+ return false
+ }
+ }
+ return true
+}
diff --git a/libgo/go/runtime/print.go b/libgo/go/runtime/print.go
index 371cec50587..4db726a7552 100644
--- a/libgo/go/runtime/print.go
+++ b/libgo/go/runtime/print.go
@@ -4,7 +4,10 @@
package runtime
-import "unsafe"
+import (
+ "runtime/internal/atomic"
+ "unsafe"
+)
// For gccgo, use go:linkname to rename compiler-called functions to
// themselves, so that the compiler will export them.
@@ -41,6 +44,36 @@ func bytes(s string) (ret []byte) {
return
}
+var (
+ // printBacklog is a circular buffer of messages written with the builtin
+ // print* functions, for use in postmortem analysis of core dumps.
+ printBacklog [512]byte
+ printBacklogIndex int
+)
+
+// recordForPanic maintains a circular buffer of messages written by the
+// runtime leading up to a process crash, allowing the messages to be
+// extracted from a core dump.
+//
+// The text written during a process crash (following "panic" or "fatal
+// error") is not saved, since the goroutine stacks will generally be readable
+// from the runtime datastructures in the core file.
+func recordForPanic(b []byte) {
+ printlock()
+
+ if atomic.Load(&panicking) == 0 {
+ // Not actively crashing: maintain circular buffer of print output.
+ for i := 0; i < len(b); {
+ n := copy(printBacklog[printBacklogIndex:], b[i:])
+ i += n
+ printBacklogIndex += n
+ printBacklogIndex %= len(printBacklog)
+ }
+ }
+
+ printunlock()
+}
+
var debuglock mutex
// The compiler emits calls to printlock and printunlock around
@@ -75,6 +108,7 @@ func gwrite(b []byte) {
if len(b) == 0 {
return
}
+ recordForPanic(b)
gp := getg()
if gp == nil || gp.writebuf == nil {
writeErr(b)
diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go
index ef863c8ec55..958b56e0ecd 100644
--- a/libgo/go/runtime/proc.go
+++ b/libgo/go/runtime/proc.go
@@ -266,7 +266,7 @@ func ready(gp *g, traceskip int, next bool) {
// status is Gwaiting or Gscanwaiting, make Grunnable and put on runq
casgstatus(gp, _Gwaiting, _Grunnable)
runqput(_g_.m.p.ptr(), gp, next)
- if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 { // TODO: fast atomic
+ if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 {
wakep()
}
_g_.m.locks--
@@ -329,10 +329,15 @@ func helpgc(nproc int32) {
// sched.stopwait to in order to request that all Gs permanently stop.
const freezeStopWait = 0x7fffffff
+// freezing is set to non-zero if the runtime is trying to freeze the
+// world.
+var freezing uint32
+
// Similar to stopTheWorld but best-effort and can be called several times.
// There is no reverse operation, used during crashing.
// This function must not lock any mutexes.
func freezetheworld() {
+ atomic.Store(&freezing, 1)
// stopwait and preemption requests can be lost
// due to races with concurrently executing threads,
// so try several times
@@ -498,7 +503,7 @@ func casgstatus(gp *g, oldval, newval uint32) {
// in panic or being exited, this may not reliably stop all
// goroutines.
func stopTheWorld(reason string) {
- semacquire(&worldsema, false)
+ semacquire(&worldsema, 0)
getg().m.preemptoff = reason
systemstack(stopTheWorldWithSema)
}
@@ -521,7 +526,7 @@ var worldsema uint32 = 1
// preemption first and then should stopTheWorldWithSema on the system
// stack:
//
-// semacquire(&worldsema, false)
+// semacquire(&worldsema, 0)
// m.preemptoff = "reason"
// systemstack(stopTheWorldWithSema)
//
@@ -590,15 +595,30 @@ func stopTheWorldWithSema() {
preemptall()
}
}
+
+ // sanity checks
+ bad := ""
if sched.stopwait != 0 {
- throw("stopTheWorld: not stopped")
- }
- for i := 0; i < int(gomaxprocs); i++ {
- p := allp[i]
- if p.status != _Pgcstop {
- throw("stopTheWorld: not stopped")
+ bad = "stopTheWorld: not stopped (stopwait != 0)"
+ } else {
+ for i := 0; i < int(gomaxprocs); i++ {
+ p := allp[i]
+ if p.status != _Pgcstop {
+ bad = "stopTheWorld: not stopped (status != _Pgcstop)"
+ }
}
}
+ if atomic.Load(&freezing) != 0 {
+ // Some other thread is panicking. This can cause the
+ // sanity checks above to fail if the panic happens in
+ // the signal handler on a stopped thread. Either way,
+ // we should halt this thread.
+ lock(&deadlock)
+ lock(&deadlock)
+ }
+ if bad != "" {
+ throw(bad)
+ }
}
func mhelpgc() {
@@ -897,6 +917,7 @@ func oneNewExtraM() {
mp := allocm(nil, true, &g0SP, &g0SPSize)
gp := malg(true, false, nil, nil)
gp.gcscanvalid = true // fresh G, so no dequeueRescan necessary
+ gp.gcscandone = true
gp.gcRescan = -1
// malg returns status as Gidle, change to Gdead before adding to allg
@@ -1061,7 +1082,7 @@ retry:
// Hands off P from syscall or locked M.
// Always runs without a P, so write barriers are not allowed.
-//go:nowritebarrier
+//go:nowritebarrierrec
func handoffp(_p_ *p) {
// handoffp must start an M in any situation where
// findrunnable would return a G to run on _p_.
@@ -1154,7 +1175,7 @@ func stoplockedm() {
// Schedules the locked m to run the locked gp.
// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//go:nowritebarrierrec
func startlockedm(gp *g) {
_g_ := getg()
@@ -1204,6 +1225,11 @@ func gcstopm() {
// If inheritTime is true, gp inherits the remaining time in the
// current time slice. Otherwise, it starts a new time slice.
// Never returns.
+//
+// Write barriers are allowed because this is called immediately after
+// acquiring a P in several places.
+//
+//go:yeswritebarrierrec
func execute(gp *g, inheritTime bool) {
_g_ := getg()
@@ -1302,7 +1328,7 @@ top:
// If number of spinning M's >= number of busy P's, block.
// This is necessary to prevent excessive CPU consumption
// when GOMAXPROCS>>1 but the program parallelism is low.
- if !_g_.m.spinning && 2*atomic.Load(&sched.nmspinning) >= procs-atomic.Load(&sched.npidle) { // TODO: fast atomic
+ if !_g_.m.spinning && 2*atomic.Load(&sched.nmspinning) >= procs-atomic.Load(&sched.npidle) {
goto stop
}
if !_g_.m.spinning {
@@ -1310,7 +1336,7 @@ top:
atomic.Xadd(&sched.nmspinning, 1)
}
for i := 0; i < 4; i++ {
- for enum := stealOrder.start(fastrand1()); !enum.done(); enum.next() {
+ for enum := stealOrder.start(fastrand()); !enum.done(); enum.next() {
if sched.gcwaiting != 0 {
goto top
}
@@ -1393,6 +1419,26 @@ stop:
}
}
+ // Check for idle-priority GC work again.
+ if gcBlackenEnabled != 0 && gcMarkWorkAvailable(nil) {
+ lock(&sched.lock)
+ _p_ = pidleget()
+ if _p_ != nil && _p_.gcBgMarkWorker == 0 {
+ pidleput(_p_)
+ _p_ = nil
+ }
+ unlock(&sched.lock)
+ if _p_ != nil {
+ acquirep(_p_)
+ if wasSpinning {
+ _g_.m.spinning = true
+ atomic.Xadd(&sched.nmspinning, 1)
+ }
+ // Go back to idle GC check.
+ goto stop
+ }
+ }
+
// poll network
if netpollinited() && atomic.Xchg64(&sched.lastpoll, 0) != 0 {
if _g_.m.p != 0 {
@@ -1423,6 +1469,27 @@ stop:
goto top
}
+// pollWork returns true if there is non-background work this P could
+// be doing. This is a fairly lightweight check to be used for
+// background work loops, like idle GC. It checks a subset of the
+// conditions checked by the actual scheduler.
+func pollWork() bool {
+ if sched.runqsize != 0 {
+ return true
+ }
+ p := getg().m.p.ptr()
+ if !runqempty(p) {
+ return true
+ }
+ if netpollinited() && sched.lastpoll != 0 {
+ if gp := netpoll(false); gp != nil {
+ injectglist(gp)
+ return true
+ }
+ }
+ return false
+}
+
func resetspinning() {
_g_ := getg()
if !_g_.m.spinning {
@@ -1562,8 +1629,8 @@ top:
func dropg() {
_g_ := getg()
- _g_.m.curg.m = nil
- _g_.m.curg = nil
+ setMNoWB(&_g_.m.curg.m, nil)
+ setGNoWB(&_g_.m.curg, nil)
}
func beforefork() {
@@ -1887,7 +1954,13 @@ func procresize(nprocs int32) *p {
}
// Associate p and the current m.
+//
+// This function is allowed to have write barriers even if the caller
+// isn't because it immediately acquires _p_.
+//
+//go:yeswritebarrierrec
func acquirep(_p_ *p) {
+ // Do the part that isn't allowed to have write barriers.
acquirep1(_p_)
// have p; write barriers now allowed
@@ -1899,8 +1972,11 @@ func acquirep(_p_ *p) {
}
}
-// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+// acquirep1 is the first step of acquirep, which actually acquires
+// _p_. This is broken out so we can disallow write barriers for this
+// part, since we don't yet have a P.
+//
+//go:nowritebarrierrec
func acquirep1(_p_ *p) {
_g_ := getg()
@@ -2064,7 +2140,7 @@ func sysmon() {
delay = 10 * 1000
}
usleep(delay)
- if debug.schedtrace <= 0 && (sched.gcwaiting != 0 || atomic.Load(&sched.npidle) == uint32(gomaxprocs)) { // TODO: fast atomic
+ if debug.schedtrace <= 0 && (sched.gcwaiting != 0 || atomic.Load(&sched.npidle) == uint32(gomaxprocs)) {
lock(&sched.lock)
if atomic.Load(&sched.gcwaiting) != 0 || atomic.Load(&sched.npidle) == uint32(gomaxprocs) {
atomic.Store(&sched.sysmonwait, 1)
@@ -2347,7 +2423,7 @@ func schedtrace(detailed bool) {
// Put mp on midle list.
// Sched must be locked.
// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//go:nowritebarrierrec
func mput(mp *m) {
mp.schedlink = sched.midle
sched.midle.set(mp)
@@ -2358,7 +2434,7 @@ func mput(mp *m) {
// Try to get an m from midle list.
// Sched must be locked.
// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//go:nowritebarrierrec
func mget() *m {
mp := sched.midle.ptr()
if mp != nil {
@@ -2371,7 +2447,7 @@ func mget() *m {
// Put gp on the global runnable queue.
// Sched must be locked.
// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//go:nowritebarrierrec
func globrunqput(gp *g) {
gp.schedlink = 0
if sched.runqtail != 0 {
@@ -2386,7 +2462,7 @@ func globrunqput(gp *g) {
// Put gp at the head of the global runnable queue.
// Sched must be locked.
// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//go:nowritebarrierrec
func globrunqputhead(gp *g) {
gp.schedlink = sched.runqhead
sched.runqhead.set(gp)
@@ -2446,7 +2522,7 @@ func globrunqget(_p_ *p, max int32) *g {
// Put p to on _Pidle list.
// Sched must be locked.
// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//go:nowritebarrierrec
func pidleput(_p_ *p) {
if !runqempty(_p_) {
throw("pidleput: P has non-empty run queue")
@@ -2459,7 +2535,7 @@ func pidleput(_p_ *p) {
// Try get a p from _Pidle list.
// Sched must be locked.
// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//go:nowritebarrierrec
func pidleget() *p {
_p_ := sched.pidle.ptr()
if _p_ != nil {
@@ -2503,7 +2579,7 @@ const randomizeScheduler = raceenabled
// If the run queue is full, runnext puts g on the global queue.
// Executed only by the owner P.
func runqput(_p_ *p, gp *g, next bool) {
- if randomizeScheduler && next && fastrand1()%2 == 0 {
+ if randomizeScheduler && next && fastrand()%2 == 0 {
next = false
}
@@ -2556,7 +2632,7 @@ func runqputslow(_p_ *p, gp *g, h, t uint32) bool {
if randomizeScheduler {
for i := uint32(1); i <= n; i++ {
- j := fastrand1() % (i + 1)
+ j := fastrand() % (i + 1)
batch[i], batch[j] = batch[j], batch[i]
}
}
@@ -2681,7 +2757,11 @@ func runqsteal(_p_, p2 *p, stealRunNextG bool) *g {
func setMaxThreads(in int) (out int) {
lock(&sched.lock)
out = int(sched.maxmcount)
- sched.maxmcount = int32(in)
+ if in > 0x7fffffff { // MaxInt32
+ sched.maxmcount = 0x7fffffff
+ } else {
+ sched.maxmcount = int32(in)
+ }
checkmcount()
unlock(&sched.lock)
return
diff --git a/libgo/go/runtime/race/race_linux_test.go b/libgo/go/runtime/race/race_linux_test.go
deleted file mode 100644
index c00ce4d3dfc..00000000000
--- a/libgo/go/runtime/race/race_linux_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build linux,race
-
-package race_test
-
-import (
- "sync/atomic"
- "syscall"
- "testing"
- "unsafe"
-)
-
-func TestAtomicMmap(t *testing.T) {
- // Test that atomic operations work on "external" memory. Previously they crashed (#16206).
- // Also do a sanity correctness check: under race detector atomic operations
- // are implemented inside of race runtime.
- mem, err := syscall.Mmap(-1, 0, 1<<20, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
- if err != nil {
- t.Fatalf("mmap failed: %v", err)
- }
- defer syscall.Munmap(mem)
- a := (*uint64)(unsafe.Pointer(&mem[0]))
- if *a != 0 {
- t.Fatalf("bad atomic value: %v, want 0", *a)
- }
- atomic.AddUint64(a, 1)
- if *a != 1 {
- t.Fatalf("bad atomic value: %v, want 1", *a)
- }
- atomic.AddUint64(a, 1)
- if *a != 2 {
- t.Fatalf("bad atomic value: %v, want 2", *a)
- }
-}
diff --git a/libgo/go/runtime/race/race_windows_test.go b/libgo/go/runtime/race/race_windows_test.go
deleted file mode 100644
index 307a1ea6c0d..00000000000
--- a/libgo/go/runtime/race/race_windows_test.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build windows,race
-
-package race_test
-
-import (
- "sync/atomic"
- "syscall"
- "testing"
- "unsafe"
-)
-
-func TestAtomicMmap(t *testing.T) {
- // Test that atomic operations work on "external" memory. Previously they crashed (#16206).
- // Also do a sanity correctness check: under race detector atomic operations
- // are implemented inside of race runtime.
- kernel32 := syscall.NewLazyDLL("kernel32.dll")
- VirtualAlloc := kernel32.NewProc("VirtualAlloc")
- VirtualFree := kernel32.NewProc("VirtualFree")
- const (
- MEM_COMMIT = 0x00001000
- MEM_RESERVE = 0x00002000
- MEM_RELEASE = 0x8000
- PAGE_READWRITE = 0x04
- )
- mem, _, err := syscall.Syscall6(VirtualAlloc.Addr(), 4, 0, 1<<20, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE, 0, 0)
- if err != 0 {
- t.Fatalf("VirtualAlloc failed: %v", err)
- }
- defer syscall.Syscall(VirtualFree.Addr(), 3, mem, 1<<20, MEM_RELEASE)
- a := (*uint64)(unsafe.Pointer(mem))
- if *a != 0 {
- t.Fatalf("bad atomic value: %v, want 0", *a)
- }
- atomic.AddUint64(a, 1)
- if *a != 1 {
- t.Fatalf("bad atomic value: %v, want 1", *a)
- }
- atomic.AddUint64(a, 1)
- if *a != 2 {
- t.Fatalf("bad atomic value: %v, want 2", *a)
- }
-}
diff --git a/libgo/go/runtime/race/testdata/issue12225_test.go b/libgo/go/runtime/race/testdata/issue12225_test.go
deleted file mode 100644
index 0494493b2e9..00000000000
--- a/libgo/go/runtime/race/testdata/issue12225_test.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package race_test
-
-import "unsafe"
-
-// golang.org/issue/12225
-// The test is that this compiles at all.
-
-//go:noinline
-func convert(s string) []byte {
- return []byte(s)
-}
-
-func issue12225() {
- println(*(*int)(unsafe.Pointer(&convert("")[0])))
- println(*(*int)(unsafe.Pointer(&[]byte("")[0])))
-}
diff --git a/libgo/go/runtime/race/testdata/issue12664_test.go b/libgo/go/runtime/race/testdata/issue12664_test.go
deleted file mode 100644
index c9f790edc85..00000000000
--- a/libgo/go/runtime/race/testdata/issue12664_test.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package race_test
-
-import (
- "fmt"
- "testing"
-)
-
-var issue12664 = "hi"
-
-func TestRaceIssue12664(t *testing.T) {
- c := make(chan struct{})
- go func() {
- issue12664 = "bye"
- close(c)
- }()
- fmt.Println(issue12664)
- <-c
-}
-
-type MyI interface {
- foo()
-}
-
-type MyT int
-
-func (MyT) foo() {
-}
-
-var issue12664_2 MyT = 0
-
-func TestRaceIssue12664_2(t *testing.T) {
- c := make(chan struct{})
- go func() {
- issue12664_2 = 1
- close(c)
- }()
- func(x MyI) {
- // Never true, but prevents inlining.
- if x.(MyT) == -1 {
- close(c)
- }
- }(issue12664_2)
- <-c
-}
-
-var issue12664_3 MyT = 0
-
-func TestRaceIssue12664_3(t *testing.T) {
- c := make(chan struct{})
- go func() {
- issue12664_3 = 1
- close(c)
- }()
- var r MyT
- var i interface{} = r
- issue12664_3 = i.(MyT)
- <-c
-}
-
-var issue12664_4 MyT = 0
-
-func TestRaceIssue12664_4(t *testing.T) {
- c := make(chan struct{})
- go func() {
- issue12664_4 = 1
- close(c)
- }()
- var r MyT
- var i MyI = r
- issue12664_4 = i.(MyT)
- <-c
-}
diff --git a/libgo/go/runtime/race/testdata/issue13264_test.go b/libgo/go/runtime/race/testdata/issue13264_test.go
deleted file mode 100644
index d42290de504..00000000000
--- a/libgo/go/runtime/race/testdata/issue13264_test.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package race_test
-
-// golang.org/issue/13264
-// The test is that this compiles at all.
-
-func issue13264() {
- for ; ; []map[int]int{}[0][0] = 0 {
- }
-}
diff --git a/libgo/go/runtime/rune.go b/libgo/go/runtime/rune.go
deleted file mode 100644
index 99c38e0bd91..00000000000
--- a/libgo/go/runtime/rune.go
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * The authors of this software are Rob Pike and Ken Thompson.
- * Copyright (c) 2002 by Lucent Technologies.
- * Portions Copyright 2009 The Go Authors. All rights reserved.
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- */
-
-/*
- * This code is copied, with slight editing due to type differences,
- * from a subset of ../lib9/utf/rune.c [which no longer exists]
- */
-
-package runtime
-
-const (
- bit1 = 7
- bitx = 6
- bit2 = 5
- bit3 = 4
- bit4 = 3
- bit5 = 2
-
- t1 = ((1 << (bit1 + 1)) - 1) ^ 0xFF /* 0000 0000 */
- tx = ((1 << (bitx + 1)) - 1) ^ 0xFF /* 1000 0000 */
- t2 = ((1 << (bit2 + 1)) - 1) ^ 0xFF /* 1100 0000 */
- t3 = ((1 << (bit3 + 1)) - 1) ^ 0xFF /* 1110 0000 */
- t4 = ((1 << (bit4 + 1)) - 1) ^ 0xFF /* 1111 0000 */
- t5 = ((1 << (bit5 + 1)) - 1) ^ 0xFF /* 1111 1000 */
-
- rune1 = (1 << (bit1 + 0*bitx)) - 1 /* 0000 0000 0111 1111 */
- rune2 = (1 << (bit2 + 1*bitx)) - 1 /* 0000 0111 1111 1111 */
- rune3 = (1 << (bit3 + 2*bitx)) - 1 /* 1111 1111 1111 1111 */
- rune4 = (1 << (bit4 + 3*bitx)) - 1 /* 0001 1111 1111 1111 1111 1111 */
-
- maskx = (1 << bitx) - 1 /* 0011 1111 */
- testx = maskx ^ 0xFF /* 1100 0000 */
-
- runeerror = 0xFFFD
- runeself = 0x80
-
- surrogateMin = 0xD800
- surrogateMax = 0xDFFF
-
- bad = runeerror
-
- runemax = 0x10FFFF /* maximum rune value */
-)
-
-/*
- * Modified by Wei-Hwa Huang, Google Inc., on 2004-09-24
- * This is a slower but "safe" version of the old chartorune
- * that works on strings that are not necessarily null-terminated.
- *
- * If you know for sure that your string is null-terminated,
- * chartorune will be a bit faster.
- *
- * It is guaranteed not to attempt to access "length"
- * past the incoming pointer. This is to avoid
- * possible access violations. If the string appears to be
- * well-formed but incomplete (i.e., to get the whole Rune
- * we'd need to read past str+length) then we'll set the Rune
- * to Bad and return 0.
- *
- * Note that if we have decoding problems for other
- * reasons, we return 1 instead of 0.
- */
-func charntorune(s string) (rune, int) {
- /* When we're not allowed to read anything */
- if len(s) <= 0 {
- return bad, 1
- }
-
- /*
- * one character sequence (7-bit value)
- * 00000-0007F => T1
- */
- c := s[0]
- if c < tx {
- return rune(c), 1
- }
-
- // If we can't read more than one character we must stop
- if len(s) <= 1 {
- return bad, 1
- }
-
- /*
- * two character sequence (11-bit value)
- * 0080-07FF => t2 tx
- */
- c1 := s[1] ^ tx
- if (c1 & testx) != 0 {
- return bad, 1
- }
- if c < t3 {
- if c < t2 {
- return bad, 1
- }
- l := ((rune(c) << bitx) | rune(c1)) & rune2
- if l <= rune1 {
- return bad, 1
- }
- return l, 2
- }
-
- // If we can't read more than two characters we must stop
- if len(s) <= 2 {
- return bad, 1
- }
-
- /*
- * three character sequence (16-bit value)
- * 0800-FFFF => t3 tx tx
- */
- c2 := s[2] ^ tx
- if (c2 & testx) != 0 {
- return bad, 1
- }
- if c < t4 {
- l := ((((rune(c) << bitx) | rune(c1)) << bitx) | rune(c2)) & rune3
- if l <= rune2 {
- return bad, 1
- }
- if surrogateMin <= l && l <= surrogateMax {
- return bad, 1
- }
- return l, 3
- }
-
- if len(s) <= 3 {
- return bad, 1
- }
-
- /*
- * four character sequence (21-bit value)
- * 10000-1FFFFF => t4 tx tx tx
- */
- c3 := s[3] ^ tx
- if (c3 & testx) != 0 {
- return bad, 1
- }
- if c < t5 {
- l := ((((((rune(c) << bitx) | rune(c1)) << bitx) | rune(c2)) << bitx) | rune(c3)) & rune4
- if l <= rune3 || l > runemax {
- return bad, 1
- }
- return l, 4
- }
-
- // Support for 5-byte or longer UTF-8 would go here, but
- // since we don't have that, we'll just return bad.
- return bad, 1
-}
-
-// runetochar converts r to bytes and writes the result to str.
-// returns the number of bytes generated.
-func runetochar(str []byte, r rune) int {
- /* runes are signed, so convert to unsigned for range check. */
- c := uint32(r)
- /*
- * one character sequence
- * 00000-0007F => 00-7F
- */
- if c <= rune1 {
- str[0] = byte(c)
- return 1
- }
- /*
- * two character sequence
- * 0080-07FF => t2 tx
- */
- if c <= rune2 {
- str[0] = byte(t2 | (c >> (1 * bitx)))
- str[1] = byte(tx | (c & maskx))
- return 2
- }
-
- /*
- * If the rune is out of range or a surrogate half, convert it to the error rune.
- * Do this test here because the error rune encodes to three bytes.
- * Doing it earlier would duplicate work, since an out of range
- * rune wouldn't have fit in one or two bytes.
- */
- if c > runemax {
- c = runeerror
- }
- if surrogateMin <= c && c <= surrogateMax {
- c = runeerror
- }
-
- /*
- * three character sequence
- * 0800-FFFF => t3 tx tx
- */
- if c <= rune3 {
- str[0] = byte(t3 | (c >> (2 * bitx)))
- str[1] = byte(tx | ((c >> (1 * bitx)) & maskx))
- str[2] = byte(tx | (c & maskx))
- return 3
- }
-
- /*
- * four character sequence (21-bit value)
- * 10000-1FFFFF => t4 tx tx tx
- */
- str[0] = byte(t4 | (c >> (3 * bitx)))
- str[1] = byte(tx | ((c >> (2 * bitx)) & maskx))
- str[2] = byte(tx | ((c >> (1 * bitx)) & maskx))
- str[3] = byte(tx | (c & maskx))
- return 4
-}
diff --git a/libgo/go/runtime/runtime-lldb_test.go b/libgo/go/runtime/runtime-lldb_test.go
index 4c379b9cdc2..98bc9066662 100644
--- a/libgo/go/runtime/runtime-lldb_test.go
+++ b/libgo/go/runtime/runtime-lldb_test.go
@@ -158,7 +158,7 @@ func TestLldbPython(t *testing.T) {
t.Fatalf("failed to create file: %v", err)
}
- cmd := exec.Command("go", "build", "-gcflags", "-N -l", "-o", "a.exe")
+ cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags", "-N -l", "-o", "a.exe")
cmd.Dir = dir
out, err := cmd.CombinedOutput()
if err != nil {
@@ -198,7 +198,7 @@ func TestDwarfAranges(t *testing.T) {
t.Fatalf("failed to create file: %v", err)
}
- cmd := exec.Command("go", "build", "-o", "a.exe")
+ cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "a.exe")
cmd.Dir = dir
out, err := cmd.CombinedOutput()
if err != nil {
diff --git a/libgo/go/runtime/runtime.go b/libgo/go/runtime/runtime.go
index 23601e1fc66..e63130b1496 100644
--- a/libgo/go/runtime/runtime.go
+++ b/libgo/go/runtime/runtime.go
@@ -58,6 +58,9 @@ var argslice []string
//go:linkname syscall_runtime_envs syscall.runtime_envs
func syscall_runtime_envs() []string { return append([]string{}, envs...) }
+//go:linkname syscall_Getpagesize syscall.Getpagesize
+func syscall_Getpagesize() int { return int(physPageSize) }
+
//go:linkname os_runtime_args os.runtime_args
func os_runtime_args() []string { return append([]string{}, argslice...) }
diff --git a/libgo/go/runtime/runtime1.go b/libgo/go/runtime/runtime1.go
index dea19da997f..a41cfc81181 100644
--- a/libgo/go/runtime/runtime1.go
+++ b/libgo/go/runtime/runtime1.go
@@ -80,7 +80,6 @@ func goargs() {
if GOOS == "windows" {
return
}
-
argslice = make([]string, argc)
for i := int32(0); i < argc; i++ {
argslice[i] = gostringnocopy(argv_index(argv, i))
@@ -345,6 +344,7 @@ type debugVars struct {
gcshrinkstackoff int32
gcstackbarrieroff int32
gcstackbarrierall int32
+ gcrescanstacks int32
gcstoptheworld int32
gctrace int32
invalidptr int32
@@ -370,6 +370,7 @@ var dbgvars = []dbgVar{
{"gcshrinkstackoff", &debug.gcshrinkstackoff},
{"gcstackbarrieroff", &debug.gcstackbarrieroff},
{"gcstackbarrierall", &debug.gcstackbarrierall},
+ {"gcrescanstacks", &debug.gcrescanstacks},
{"gcstoptheworld", &debug.gcstoptheworld},
{"gctrace", &debug.gctrace},
{"invalidptr", &debug.invalidptr},
@@ -403,11 +404,15 @@ func parsedebugvars() {
// is int, not int32, and should only be updated
// if specified in GODEBUG.
if key == "memprofilerate" {
- MemProfileRate = atoi(value)
+ if n, ok := atoi(value); ok {
+ MemProfileRate = n
+ }
} else {
for _, v := range dbgvars {
if v.name == key {
- *v.value = int32(atoi(value))
+ if n, ok := atoi32(value); ok {
+ *v.value = n
+ }
}
}
}
@@ -416,6 +421,13 @@ func parsedebugvars() {
setTraceback(gogetenv("GOTRACEBACK"))
traceback_env = traceback_cache
+ if debug.gcrescanstacks == 0 {
+ // Without rescanning, there's no need for stack
+ // barriers.
+ debug.gcstackbarrieroff = 1
+ debug.gcstackbarrierall = 0
+ }
+
// if debug.gcstackbarrierall > 0 {
// firstStackBarrierOffset = 0
// }
@@ -446,7 +458,10 @@ func setTraceback(level string) {
case "crash":
t = 2<<tracebackShift | tracebackAll | tracebackCrash
default:
- t = uint32(atoi(level))<<tracebackShift | tracebackAll
+ t = tracebackAll
+ if n, ok := atoi(level); ok && n == int(uint32(n)) {
+ t |= uint32(n) << tracebackShift
+ }
}
// when C owns the process, simply exit'ing the process on fatal errors
// and panics is surprising. Be louder and abort instead.
diff --git a/libgo/go/runtime/runtime2.go b/libgo/go/runtime/runtime2.go
index 7dc27433bae..195d65bbd73 100644
--- a/libgo/go/runtime/runtime2.go
+++ b/libgo/go/runtime/runtime2.go
@@ -209,6 +209,14 @@ func (gp *guintptr) cas(old, new guintptr) bool {
return atomic.Casuintptr((*uintptr)(unsafe.Pointer(gp)), uintptr(old), uintptr(new))
}
+// setGNoWB performs *gp = new without a write barrier.
+// For times when it's impractical to use a guintptr.
+//go:nosplit
+//go:nowritebarrier
+func setGNoWB(gp **g, new *g) {
+ (*guintptr)(unsafe.Pointer(gp)).set(new)
+}
+
type puintptr uintptr
//go:nosplit
@@ -225,6 +233,14 @@ func (mp muintptr) ptr() *m { return (*m)(unsafe.Pointer(mp)) }
//go:nosplit
func (mp *muintptr) set(m *m) { *mp = muintptr(unsafe.Pointer(m)) }
+// setMNoWB performs *mp = new without a write barrier.
+// For times when it's impractical to use an muintptr.
+//go:nosplit
+//go:nowritebarrier
+func setMNoWB(mp **m, new *m) {
+ (*muintptr)(unsafe.Pointer(mp)).set(new)
+}
+
// sudog represents a g in a wait list, such as for sending/receiving
// on a channel.
//
@@ -249,6 +265,7 @@ type sudog struct {
// The following fields are never accessed concurrently.
// waitlink is only accessed by g.
+ acquiretime int64
releasetime int64
ticket uint32
waitlink *sudog // g.waiting list
@@ -538,7 +555,7 @@ type p struct {
runSafePointFn uint32 // if 1, run sched.safePointFn at next safe point
- pad [64]byte
+ pad [sys.CacheLineSize]byte
}
const (
@@ -626,29 +643,6 @@ const (
_SigUnblock // unblocked in minit
)
-/*
-gccgo does not use this.
-
-// Layout of in-memory per-function information prepared by linker
-// See https://golang.org/s/go12symtab.
-// Keep in sync with linker
-// and with package debug/gosym and with symtab.go in package runtime.
-type _func struct {
- entry uintptr // start pc
- nameoff int32 // function name
-
- args int32 // in/out args size
- _ int32 // previously legacy frame size; kept for layout compatibility
-
- pcsp int32
- pcfile int32
- pcln int32
- npcdata int32
- nfuncdata int32
-}
-
-*/
-
// Lock-free stack node.
// // Also known to export_test.go.
type lfnode struct {
@@ -766,15 +760,17 @@ var (
newprocs int32
// Information about what cpu features are available.
- // Set on startup.
+ // Set on startup in asm_{x86,amd64}.s.
cpuid_ecx uint32
support_aes bool
-// cpuid_edx uint32
-// cpuid_ebx7 uint32
-// lfenceBeforeRdtsc bool
-// support_avx bool
-// support_avx2 bool
+ // cpuid_edx uint32
+ // cpuid_ebx7 uint32
+ // lfenceBeforeRdtsc bool
+ // support_avx bool
+ // support_avx2 bool
+ // support_bmi1 bool
+ // support_bmi2 bool
// goarm uint8 // set by cmd/link on arm systems
// framepointer_enabled bool // set by cmd/link
diff --git a/libgo/go/runtime/runtime_mmap_test.go b/libgo/go/runtime/runtime_mmap_test.go
index 97b44e2660d..0141e81d4a0 100644
--- a/libgo/go/runtime/runtime_mmap_test.go
+++ b/libgo/go/runtime/runtime_mmap_test.go
@@ -2,21 +2,19 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build ignore
-
package runtime_test
import (
"runtime"
- "runtime/internal/sys"
"testing"
+ "unsafe"
)
// Test that the error value returned by mmap is positive, as that is
// what the code in mem_bsd.go, mem_darwin.go, and mem_linux.go expects.
// See the uses of ENOMEM in sysMap in those files.
func TestMmapErrorSign(t *testing.T) {
- p := runtime.Mmap(nil, ^uintptr(0)&^(sys.PhysPageSize-1), 0, runtime.MAP_ANON|runtime.MAP_PRIVATE, -1, 0)
+ p := runtime.Mmap(nil, ^uintptr(0)&^(runtime.GetPhysPageSize()-1), 0, runtime.MAP_ANON|runtime.MAP_PRIVATE, -1, 0)
// The runtime.mmap function is nosplit, but t.Errorf is not.
// Reset the pointer so that we don't get an "invalid stack
@@ -24,7 +22,32 @@ func TestMmapErrorSign(t *testing.T) {
v := uintptr(p)
p = nil
- if v != runtime.ENOMEM {
- t.Errorf("mmap = %v, want %v", v, runtime.ENOMEM)
+ err := runtime.Errno()
+ if v != ^uintptr(0) || err != runtime.ENOMEM {
+ t.Errorf("mmap = %v, %v, want %v", v, err, runtime.ENOMEM)
+ }
+}
+
+func TestPhysPageSize(t *testing.T) {
+ // Mmap fails if the address is not page aligned, so we can
+ // use this to test if the page size is the true page size.
+ ps := runtime.GetPhysPageSize()
+
+ // Get a region of memory to play with. This should be page-aligned.
+ b := uintptr(runtime.Mmap(nil, 2*ps, 0, runtime.MAP_ANON|runtime.MAP_PRIVATE, -1, 0))
+ if b == ^uintptr(0) {
+ t.Fatalf("Mmap: %v %v", b, runtime.Errno())
+ }
+
+ // Mmap should fail at a half page into the buffer.
+ err := uintptr(runtime.Mmap(unsafe.Pointer(uintptr(b)+ps/2), ps, 0, runtime.MAP_ANON|runtime.MAP_PRIVATE|runtime.MAP_FIXED, -1, 0))
+ if err != ^uintptr(0) {
+ t.Errorf("Mmap should have failed with half-page alignment %d, but succeeded: %v", ps/2, err)
+ }
+
+ // Mmap should succeed at a full page into the buffer.
+ err = uintptr(runtime.Mmap(unsafe.Pointer(uintptr(b)+ps), ps, 0, runtime.MAP_ANON|runtime.MAP_PRIVATE|runtime.MAP_FIXED, -1, 0))
+ if err == ^uintptr(0) {
+ t.Errorf("Mmap at full-page alignment %d failed: %v %v", ps, err, runtime.Errno())
}
}
diff --git a/libgo/go/runtime/runtime_test.go b/libgo/go/runtime/runtime_test.go
index 2ea2dc22b6f..1f403a17056 100644
--- a/libgo/go/runtime/runtime_test.go
+++ b/libgo/go/runtime/runtime_test.go
@@ -8,6 +8,7 @@ import (
"io"
. "runtime"
"runtime/debug"
+ "strings"
"testing"
"unsafe"
)
@@ -331,3 +332,11 @@ func TestGoroutineProfileTrivial(t *testing.T) {
}
}
}
+
+func TestVersion(t *testing.T) {
+ // Test that version does not contain \r or \n.
+ vers := Version()
+ if strings.Contains(vers, "\r") || strings.Contains(vers, "\n") {
+ t.Fatalf("cr/nl in version: %q", vers)
+ }
+}
diff --git a/libgo/go/runtime/select.go b/libgo/go/runtime/select.go
index 08446a1ffdd..62c404949f1 100644
--- a/libgo/go/runtime/select.go
+++ b/libgo/go/runtime/select.go
@@ -81,7 +81,7 @@ func newselect(sel *hselect, selsize int64, size int32) {
sel.pollorder = (*uint16)(add(unsafe.Pointer(sel.lockorder), uintptr(size)*unsafe.Sizeof(*hselect{}.lockorder)))
// For gccgo the temporary variable will not have been zeroed.
- memclr(unsafe.Pointer(&sel.scase), uintptr(size)*unsafe.Sizeof(hselect{}.scase[0])+uintptr(size)*unsafe.Sizeof(*hselect{}.lockorder)+uintptr(size)*unsafe.Sizeof(*hselect{}.pollorder))
+ memclrNoHeapPointers(unsafe.Pointer(&sel.scase), uintptr(size)*unsafe.Sizeof(hselect{}.scase[0])+uintptr(size)*unsafe.Sizeof(*hselect{}.lockorder)+uintptr(size)*unsafe.Sizeof(*hselect{}.pollorder))
if debugSelect {
print("newselect s=", sel, " size=", size, "\n")
@@ -279,7 +279,7 @@ func selectgoImpl(sel *hselect) (uintptr, uint16) {
pollslice := slice{unsafe.Pointer(sel.pollorder), int(sel.ncase), int(sel.ncase)}
pollorder := *(*[]uint16)(unsafe.Pointer(&pollslice))
for i := 1; i < int(sel.ncase); i++ {
- j := int(fastrand1()) % (i + 1)
+ j := int(fastrand()) % (i + 1)
pollorder[i] = pollorder[j]
pollorder[j] = uint16(i)
}
@@ -431,8 +431,62 @@ loop:
gp.param = nil
gopark(selparkcommit, nil, "select", traceEvGoBlockSelect, 2)
- // someone woke us up
- sellock(scases, lockorder)
+ // While we were asleep, some goroutine came along and completed
+ // one of the cases in the select and woke us up (called ready).
+ // As part of that process, the goroutine did a cas on done above
+ // (aka *sg.selectdone for all queued sg) to win the right to
+ // complete the select. Now done = 1.
+ //
+ // If we copy (grow) our own stack, we will update the
+ // selectdone pointers inside the gp.waiting sudog list to point
+ // at the new stack. Another goroutine attempting to
+ // complete one of our (still linked in) select cases might
+ // see the new selectdone pointer (pointing at the new stack)
+ // before the new stack has real data; if the new stack has done = 0
+ // (before the old values are copied over), the goroutine might
+ // do a cas via sg.selectdone and incorrectly believe that it has
+ // won the right to complete the select, executing a second
+ // communication and attempting to wake us (call ready) again.
+ //
+ // Then things break.
+ //
+ // The best break is that the goroutine doing ready sees the
+ // _Gcopystack status and throws, as in #17007.
+ // A worse break would be for us to continue on, start running real code,
+ // block in a semaphore acquisition (sema.go), and have the other
+ // goroutine wake us up without having really acquired the semaphore.
+ // That would result in the goroutine spuriously running and then
+ // queue up another spurious wakeup when the semaphore really is ready.
+ // In general the situation can cascade until something notices the
+ // problem and causes a crash.
+ //
+ // A stack shrink does not have this problem, because it locks
+ // all the channels that are involved first, blocking out the
+ // possibility of a cas on selectdone.
+ //
+ // A stack growth before gopark above does not have this
+ // problem, because we hold those channel locks (released by
+ // selparkcommit).
+ //
+ // A stack growth after sellock below does not have this
+ // problem, because again we hold those channel locks.
+ //
+ // The only problem is a stack growth during sellock.
+ // To keep that from happening, run sellock on the system stack.
+ //
+ // It might be that we could avoid this if copystack copied the
+ // stack before calling adjustsudogs. In that case,
+ // syncadjustsudogs would need to recopy the tiny part that
+ // it copies today, resulting in a little bit of extra copying.
+ //
+ // An even better fix, not for the week before a release candidate,
+ // would be to put space in every sudog and make selectdone
+ // point at (say) the space in the first sudog.
+
+ systemstack(func() {
+ sellock(scases, lockorder)
+ })
+
sg = (*sudog)(gp.param)
gp.param = nil
@@ -473,8 +527,15 @@ loop:
}
if cas == nil {
- // This can happen if we were woken up by a close().
- // TODO: figure that out explicitly so we don't need this loop.
+ // We can wake up with gp.param == nil (so cas == nil)
+ // when a channel involved in the select has been closed.
+ // It is easiest to loop and re-run the operation;
+ // we'll see that it's now closed.
+ // Maybe some day we can signal the close explicitly,
+ // but we'd have to distinguish close-on-reader from close-on-writer.
+ // It's easiest not to duplicate the code and just recheck above.
+ // We know that something closed, and things never un-close,
+ // so we won't block again.
goto loop
}
@@ -527,7 +588,7 @@ bufrecv:
if cas.elem != nil {
typedmemmove(c.elemtype, cas.elem, qp)
}
- memclr(qp, uintptr(c.elemsize))
+ typedmemclr(c.elemtype, qp)
c.recvx++
if c.recvx == c.dataqsiz {
c.recvx = 0
@@ -573,7 +634,7 @@ rclose:
*cas.receivedp = false
}
if cas.elem != nil {
- memclr(cas.elem, uintptr(c.elemsize))
+ typedmemclr(c.elemtype, cas.elem)
}
if raceenabled {
raceacquire(unsafe.Pointer(c))
diff --git a/libgo/go/runtime/sema.go b/libgo/go/runtime/sema.go
index 855d73ef4f4..576a1fb7a20 100644
--- a/libgo/go/runtime/sema.go
+++ b/libgo/go/runtime/sema.go
@@ -19,10 +19,6 @@
package runtime
-// Export temporarily for gccgo's C code to call:
-//go:linkname semacquire runtime.semacquire
-//go:linkname semrelease runtime.semrelease
-
import (
"runtime/internal/atomic"
"runtime/internal/sys"
@@ -48,12 +44,12 @@ var semtable [semTabSize]struct {
//go:linkname sync_runtime_Semacquire sync.runtime_Semacquire
func sync_runtime_Semacquire(addr *uint32) {
- semacquire(addr, true)
+ semacquire(addr, semaBlockProfile)
}
//go:linkname net_runtime_Semacquire net.runtime_Semacquire
func net_runtime_Semacquire(addr *uint32) {
- semacquire(addr, true)
+ semacquire(addr, semaBlockProfile)
}
//go:linkname sync_runtime_Semrelease sync.runtime_Semrelease
@@ -61,6 +57,11 @@ func sync_runtime_Semrelease(addr *uint32) {
semrelease(addr)
}
+//go:linkname sync_runtime_SemacquireMutex sync.runtime_SemacquireMutex
+func sync_runtime_SemacquireMutex(addr *uint32) {
+ semacquire(addr, semaBlockProfile|semaMutexProfile)
+}
+
//go:linkname net_runtime_Semrelease net.runtime_Semrelease
func net_runtime_Semrelease(addr *uint32) {
semrelease(addr)
@@ -73,8 +74,15 @@ func readyWithTime(s *sudog, traceskip int) {
goready(s.g, traceskip)
}
+type semaProfileFlags int
+
+const (
+ semaBlockProfile semaProfileFlags = 1 << iota
+ semaMutexProfile
+)
+
// Called from runtime.
-func semacquire(addr *uint32, profile bool) {
+func semacquire(addr *uint32, profile semaProfileFlags) {
gp := getg()
if gp != gp.m.curg {
throw("semacquire not on the G stack")
@@ -95,10 +103,17 @@ func semacquire(addr *uint32, profile bool) {
root := semroot(addr)
t0 := int64(0)
s.releasetime = 0
- if profile && blockprofilerate > 0 {
+ s.acquiretime = 0
+ if profile&semaBlockProfile != 0 && blockprofilerate > 0 {
t0 = cputicks()
s.releasetime = -1
}
+ if profile&semaMutexProfile != 0 && mutexprofilerate > 0 {
+ if t0 == 0 {
+ t0 = cputicks()
+ }
+ s.acquiretime = t0
+ }
for {
lock(&root.lock)
// Add ourselves to nwait to disable "easy case" in semrelease.
@@ -150,8 +165,19 @@ func semrelease(addr *uint32) {
break
}
}
- unlock(&root.lock)
if s != nil {
+ if s.acquiretime != 0 {
+ t0 := cputicks()
+ for x := root.head; x != nil; x = x.next {
+ if x.elem == unsafe.Pointer(addr) {
+ x.acquiretime = t0
+ }
+ }
+ mutexevent(t0-s.acquiretime, 3)
+ }
+ }
+ unlock(&root.lock)
+ if s != nil { // May be slow, so unlock first
readyWithTime(s, 5)
}
}
diff --git a/libgo/go/runtime/signal1_unix.go b/libgo/go/runtime/signal1_unix.go
deleted file mode 100644
index 181aebe64b3..00000000000
--- a/libgo/go/runtime/signal1_unix.go
+++ /dev/null
@@ -1,337 +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.
-
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
-
-package runtime
-
-import (
- _ "unsafe" // For go:linkname.
-)
-
-// Temporary for gccgo's C code to call:
-//go:linkname initsig runtime.initsig
-//go:linkname crash runtime.crash
-//go:linkname resetcpuprofiler runtime.resetcpuprofiler
-
-//extern setitimer
-func setitimer(which int32, new *_itimerval, old *_itimerval) int32
-
-type sigTabT struct {
- flags int32
- name string
-}
-
-const (
- _SIG_DFL uintptr = 0
- _SIG_IGN uintptr = 1
-)
-
-// Stores the signal handlers registered before Go installed its own.
-// These signal handlers will be invoked in cases where Go doesn't want to
-// handle a particular signal (e.g., signal occurred on a non-Go thread).
-// See sigfwdgo() for more information on when the signals are forwarded.
-//
-// Signal forwarding is currently available only on Darwin and Linux.
-var fwdSig [_NSIG]uintptr
-
-// sigmask represents a general signal mask compatible with the GOOS
-// specific sigset types: the signal numbered x is represented by bit x-1
-// to match the representation expected by sigprocmask.
-type sigmask [(_NSIG + 31) / 32]uint32
-
-// channels for synchronizing signal mask updates with the signal mask
-// thread
-var (
- disableSigChan chan uint32
- enableSigChan chan uint32
- maskUpdatedChan chan struct{}
-)
-
-func init() {
- // _NSIG is the number of signals on this operating system.
- // sigtable should describe what to do for all the possible signals.
- if len(sigtable) != _NSIG {
- print("runtime: len(sigtable)=", len(sigtable), " _NSIG=", _NSIG, "\n")
- throw("bad sigtable len")
- }
-}
-
-var signalsOK bool
-
-// Initialize signals.
-// Called by libpreinit so runtime may not be initialized.
-//go:nosplit
-//go:nowritebarrierrec
-func initsig(preinit bool) {
- if preinit {
- // preinit is only passed as true if isarchive should be true.
- isarchive = true
- }
-
- if !preinit {
- // It's now OK for signal handlers to run.
- signalsOK = true
- }
-
- // For c-archive/c-shared this is called by libpreinit with
- // preinit == true.
- if (isarchive || islibrary) && !preinit {
- return
- }
-
- for i := int32(0); i < _NSIG; i++ {
- t := &sigtable[i]
- if t.flags == 0 || t.flags&_SigDefault != 0 {
- continue
- }
- fwdSig[i] = getsig(i)
-
- if !sigInstallGoHandler(i) {
- // Even if we are not installing a signal handler,
- // set SA_ONSTACK if necessary.
- if fwdSig[i] != _SIG_DFL && fwdSig[i] != _SIG_IGN {
- setsigstack(i)
- }
- continue
- }
-
- t.flags |= _SigHandling
- setsig(i, getSigtramp(), true)
- }
-}
-
-//go:nosplit
-//go:nowritebarrierrec
-func sigInstallGoHandler(sig int32) bool {
- // For some signals, we respect an inherited SIG_IGN handler
- // rather than insist on installing our own default handler.
- // Even these signals can be fetched using the os/signal package.
- switch sig {
- case _SIGHUP, _SIGINT:
- if fwdSig[sig] == _SIG_IGN {
- return false
- }
- }
-
- t := &sigtable[sig]
- if t.flags&_SigSetStack != 0 {
- return false
- }
-
- // When built using c-archive or c-shared, only install signal
- // handlers for synchronous signals.
- if (isarchive || islibrary) && t.flags&_SigPanic == 0 {
- return false
- }
-
- return true
-}
-
-func sigenable(sig uint32) {
- if sig >= uint32(len(sigtable)) {
- return
- }
-
- t := &sigtable[sig]
- if t.flags&_SigNotify != 0 {
- ensureSigM()
- enableSigChan <- sig
- <-maskUpdatedChan
- if t.flags&_SigHandling == 0 {
- t.flags |= _SigHandling
- fwdSig[sig] = getsig(int32(sig))
- setsig(int32(sig), getSigtramp(), true)
- }
- }
-}
-
-func sigdisable(sig uint32) {
- if sig >= uint32(len(sigtable)) {
- return
- }
-
- t := &sigtable[sig]
- if t.flags&_SigNotify != 0 {
- ensureSigM()
- disableSigChan <- sig
- <-maskUpdatedChan
-
- // If initsig does not install a signal handler for a
- // signal, then to go back to the state before Notify
- // we should remove the one we installed.
- if !sigInstallGoHandler(int32(sig)) {
- t.flags &^= _SigHandling
- setsig(int32(sig), fwdSig[sig], true)
- }
- }
-}
-
-func sigignore(sig uint32) {
- if sig >= uint32(len(sigtable)) {
- return
- }
-
- t := &sigtable[sig]
- if t.flags&_SigNotify != 0 {
- t.flags &^= _SigHandling
- setsig(int32(sig), _SIG_IGN, true)
- }
-}
-
-func resetcpuprofiler(hz int32) {
- var it _itimerval
- if hz == 0 {
- setitimer(_ITIMER_PROF, &it, nil)
- } else {
- it.it_interval.tv_sec = 0
- it.it_interval.set_usec(1000000 / hz)
- it.it_value = it.it_interval
- setitimer(_ITIMER_PROF, &it, nil)
- }
- _g_ := getg()
- _g_.m.profilehz = hz
-}
-
-func sigpipe() {
- if sigsend(_SIGPIPE) {
- return
- }
- dieFromSignal(_SIGPIPE)
-}
-
-// dieFromSignal kills the program with a signal.
-// This provides the expected exit status for the shell.
-// This is only called with fatal signals expected to kill the process.
-//go:nosplit
-//go:nowritebarrierrec
-func dieFromSignal(sig int32) {
- setsig(sig, _SIG_DFL, false)
- updatesigmask(sigmask{})
- raise(sig)
-
- // That should have killed us. On some systems, though, raise
- // sends the signal to the whole process rather than to just
- // the current thread, which means that the signal may not yet
- // have been delivered. Give other threads a chance to run and
- // pick up the signal.
- osyield()
- osyield()
- osyield()
-
- // If we are still somehow running, just exit with the wrong status.
- exit(2)
-}
-
-// raisebadsignal is called when a signal is received on a non-Go
-// thread, and the Go program does not want to handle it (that is, the
-// program has not called os/signal.Notify for the signal).
-func raisebadsignal(sig int32, c *sigctxt) {
- if sig == _SIGPROF {
- // Ignore profiling signals that arrive on non-Go threads.
- return
- }
-
- var handler uintptr
- if sig >= _NSIG {
- handler = _SIG_DFL
- } else {
- handler = fwdSig[sig]
- }
-
- // Reset the signal handler and raise the signal.
- // We are currently running inside a signal handler, so the
- // signal is blocked. We need to unblock it before raising the
- // signal, or the signal we raise will be ignored until we return
- // from the signal handler. We know that the signal was unblocked
- // before entering the handler, or else we would not have received
- // it. That means that we don't have to worry about blocking it
- // again.
- unblocksig(sig)
- setsig(sig, handler, false)
-
- // If we're linked into a non-Go program we want to try to
- // avoid modifying the original context in which the signal
- // was raised. If the handler is the default, we know it
- // is non-recoverable, so we don't have to worry about
- // re-installing sighandler. At this point we can just
- // return and the signal will be re-raised and caught by
- // the default handler with the correct context.
- if (isarchive || islibrary) && handler == _SIG_DFL && c.sigcode() != _SI_USER {
- return
- }
-
- raise(sig)
-
- // If the signal didn't cause the program to exit, restore the
- // Go signal handler and carry on.
- //
- // We may receive another instance of the signal before we
- // restore the Go handler, but that is not so bad: we know
- // that the Go program has been ignoring the signal.
- setsig(sig, getSigtramp(), true)
-}
-
-func crash() {
- dieFromSignal(_SIGABRT)
-}
-
-// ensureSigM starts one global, sleeping thread to make sure at least one thread
-// is available to catch signals enabled for os/signal.
-func ensureSigM() {
- if maskUpdatedChan != nil {
- return
- }
- maskUpdatedChan = make(chan struct{})
- disableSigChan = make(chan uint32)
- enableSigChan = make(chan uint32)
- go func() {
- // Signal masks are per-thread, so make sure this goroutine stays on one
- // thread.
- LockOSThread()
- defer UnlockOSThread()
- // The sigBlocked mask contains the signals not active for os/signal,
- // initially all signals except the essential. When signal.Notify()/Stop is called,
- // sigenable/sigdisable in turn notify this thread to update its signal
- // mask accordingly.
- var sigBlocked sigmask
- for i := range sigBlocked {
- sigBlocked[i] = ^uint32(0)
- }
- for i := range sigtable {
- if sigtable[i].flags&_SigUnblock != 0 {
- sigBlocked[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
- }
- }
- updatesigmask(sigBlocked)
- for {
- select {
- case sig := <-enableSigChan:
- if b := sig - 1; sig > 0 {
- sigBlocked[b/32] &^= (1 << (b & 31))
- }
- case sig := <-disableSigChan:
- if b := sig - 1; sig > 0 {
- sigBlocked[b/32] |= (1 << (b & 31))
- }
- }
- updatesigmask(sigBlocked)
- maskUpdatedChan <- struct{}{}
- }
- }()
-}
-
-// This runs on a foreign stack, without an m or a g. No stack split.
-//go:nosplit
-//go:norace
-//go:nowritebarrierrec
-func badsignal(sig uintptr, c *sigctxt) {
- needm(0)
- if !sigsend(uint32(sig)) {
- // A foreign thread received the signal sig, and the
- // Go code does not want to handle it.
- raisebadsignal(int32(sig), c)
- }
- dropm()
-}
diff --git a/libgo/go/runtime/signal2_unix.go b/libgo/go/runtime/signal2_unix.go
deleted file mode 100644
index 2a39eac43fa..00000000000
--- a/libgo/go/runtime/signal2_unix.go
+++ /dev/null
@@ -1,66 +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.
-
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
-
-package runtime
-
-import "unsafe"
-
-// Determines if the signal should be handled by Go and if not, forwards the
-// signal to the handler that was installed before Go's. Returns whether the
-// signal was forwarded.
-// This is called by the signal handler, and the world may be stopped.
-//go:nosplit
-//go:nowritebarrierrec
-func sigfwdgo(sig uint32, info *_siginfo_t, ctx unsafe.Pointer) bool {
- if sig >= uint32(len(sigtable)) {
- return false
- }
- fwdFn := fwdSig[sig]
-
- if !signalsOK {
- // The only way we can get here is if we are in a
- // library or archive, we installed a signal handler
- // at program startup, but the Go runtime has not yet
- // been initialized.
- if fwdFn == _SIG_DFL {
- dieFromSignal(int32(sig))
- } else {
- sigfwd(fwdFn, sig, info, ctx)
- }
- return true
- }
-
- flags := sigtable[sig].flags
-
- // If there is no handler to forward to, no need to forward.
- if fwdFn == _SIG_DFL {
- return false
- }
-
- // If we aren't handling the signal, forward it.
- if flags&_SigHandling == 0 {
- sigfwd(fwdFn, sig, info, ctx)
- return true
- }
-
- // Only forward synchronous signals.
- c := sigctxt{info, ctx}
- if c.sigcode() == _SI_USER || flags&_SigPanic == 0 {
- return false
- }
- // Determine if the signal occurred inside Go code. We test that:
- // (1) we were in a goroutine (i.e., m.curg != nil), and
- // (2) we weren't in CGO (i.e., m.curg.syscallsp == 0).
- g := getg()
- if g != nil && g.m != nil && g.m.curg != nil && g.m.curg.syscallsp == 0 {
- return false
- }
- // Signal not handled by Go, forward it.
- if fwdFn != _SIG_IGN {
- sigfwd(fwdFn, sig, info, ctx)
- }
- return true
-}
diff --git a/libgo/go/runtime/signal_gccgo.go b/libgo/go/runtime/signal_gccgo.go
index 4e5044f26dd..62fe4588034 100644
--- a/libgo/go/runtime/signal_gccgo.go
+++ b/libgo/go/runtime/signal_gccgo.go
@@ -14,7 +14,7 @@ import (
// these are written in OS-specific files and in assembler.
//extern sigaction
-func sigaction(signum int32, act *_sigaction, oact *_sigaction) int32
+func sigaction(signum uint32, act *_sigaction, oact *_sigaction) int32
//extern sigprocmask
func sigprocmask(how int32, set *sigset, oldset *sigset) int32
@@ -26,25 +26,35 @@ func sigfillset(set *sigset) int32
func sigemptyset(set *sigset) int32
//extern sigaddset
-func sigaddset(set *sigset, signum int32) int32
+func c_sigaddset(set *sigset, signum uint32) int32
//extern sigdelset
-func sigdelset(set *sigset, signum int32) int32
+func c_sigdelset(set *sigset, signum uint32) int32
//extern sigaltstack
func sigaltstack(ss *_stack_t, oss *_stack_t) int32
//extern raise
-func raise(sig int32) int32
+func raise(sig uint32) int32
//extern getpid
func getpid() _pid_t
//extern kill
-func kill(pid _pid_t, sig int32) int32
+func kill(pid _pid_t, sig uint32) int32
+
+//extern setitimer
+func setitimer(which int32, new *_itimerval, old *_itimerval) int32
+
+type siginfo _siginfo_t
+
+type sigTabT struct {
+ flags int32
+ name string
+}
type sigctxt struct {
- info *_siginfo_t
+ info *siginfo
ctxt unsafe.Pointer
}
@@ -58,27 +68,10 @@ func (c *sigctxt) sigcode() uint64 {
}
//go:nosplit
-func msigsave(mp *m) {
- sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
-}
-
-//go:nosplit
-func msigrestore(sigmask sigset) {
- sigprocmask(_SIG_SETMASK, &sigmask, nil)
-}
-
-//go:nosplit
-func sigblock() {
- var set sigset
- sigfillset(&set)
- sigprocmask(_SIG_SETMASK, &set, nil)
-}
-
-//go:nosplit
//go:nowritebarrierrec
-func setsig(i int32, fn uintptr, restart bool) {
+func setsig(i uint32, fn uintptr) {
var sa _sigaction
- sa.sa_flags = _SA_SIGINFO
+ sa.sa_flags = _SA_SIGINFO | _SA_RESTART
// For gccgo we do not set SA_ONSTACK for a signal that can
// cause a panic. Instead, we trust that the split stack has
@@ -89,9 +82,6 @@ func setsig(i int32, fn uintptr, restart bool) {
sa.sa_flags |= _SA_ONSTACK
}
- if restart {
- sa.sa_flags |= _SA_RESTART
- }
sigfillset((*sigset)(unsafe.Pointer(&sa.sa_mask)))
setSigactionHandler(&sa, fn)
sigaction(i, &sa, nil)
@@ -99,7 +89,7 @@ func setsig(i int32, fn uintptr, restart bool) {
//go:nosplit
//go:nowritebarrierrec
-func setsigstack(i int32) {
+func setsigstack(i uint32) {
var sa _sigaction
sigaction(i, nil, &sa)
handler := getSigactionHandler(&sa)
@@ -115,7 +105,7 @@ func setsigstack(i int32) {
//go:nosplit
//go:nowritebarrierrec
-func getsig(i int32) uintptr {
+func getsig(i uint32) uintptr {
var sa _sigaction
if sigaction(i, nil, &sa) < 0 {
// On GNU/Linux glibc rejects attempts to call
@@ -132,34 +122,24 @@ func signalstack(p unsafe.Pointer, n uintptr)
//go:nosplit
//go:nowritebarrierrec
-func updatesigmask(m sigmask) {
- var mask sigset
- sigemptyset(&mask)
- for i := int32(0); i < _NSIG; i++ {
- if m[(i-1)/32]&(1<<((uint(i)-1)&31)) != 0 {
- sigaddset(&mask, i)
- }
- }
- sigprocmask(_SIG_SETMASK, &mask, nil)
-}
-
-func unblocksig(sig int32) {
- var mask sigset
- sigemptyset(&mask)
- sigaddset(&mask, sig)
- sigprocmask(_SIG_UNBLOCK, &mask, nil)
+func raiseproc(sig uint32) {
+ kill(getpid(), sig)
}
//go:nosplit
//go:nowritebarrierrec
-func raiseproc(sig int32) {
- kill(getpid(), sig)
+func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer) {
+ f1 := &[1]uintptr{fn}
+ f2 := *(*func(uint32, *siginfo, unsafe.Pointer))(unsafe.Pointer(&f1))
+ f2(sig, info, ctx)
}
//go:nosplit
//go:nowritebarrierrec
-func sigfwd(fn uintptr, sig uint32, info *_siginfo_t, ctx unsafe.Pointer) {
- f1 := &[1]uintptr{fn}
- f2 := *(*func(uint32, *_siginfo_t, unsafe.Pointer))(unsafe.Pointer(&f1))
- f2(sig, info, ctx)
+func sigaddset(mask *sigset, i int) {
+ c_sigaddset(mask, uint32(i))
+}
+
+func sigdelset(mask *sigset, i int) {
+ c_sigdelset(mask, uint32(i))
}
diff --git a/libgo/go/runtime/signal_sighandler.go b/libgo/go/runtime/signal_sighandler.go
index 766bb7dc0fb..a057df9018a 100644
--- a/libgo/go/runtime/signal_sighandler.go
+++ b/libgo/go/runtime/signal_sighandler.go
@@ -25,7 +25,7 @@ var crashing int32
// are not allowed.
//
//go:nowritebarrierrec
-func sighandler(sig uint32, info *_siginfo_t, ctxt unsafe.Pointer, gp *g) {
+func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
_g_ := getg()
c := sigctxt{info, ctxt}
@@ -71,7 +71,7 @@ func sighandler(sig uint32, info *_siginfo_t, ctxt unsafe.Pointer, gp *g) {
}
if flags&_SigKill != 0 {
- dieFromSignal(int32(sig))
+ dieFromSignal(sig)
}
if flags&_SigThrow == 0 {
@@ -91,10 +91,7 @@ func sighandler(sig uint32, info *_siginfo_t, ctxt unsafe.Pointer, gp *g) {
print("Signal ", sig, "\n")
}
- if sigpc != 0 {
- print("PC=", hex(sigpc), " ")
- }
- print("m=", _g_.m.id, " sigcode=", c.sigcode(), "\n")
+ print("PC=", hex(sigpc), " m=", _g_.m.id, " sigcode=", c.sigcode(), "\n")
if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
print("signal arrived during cgo execution\n")
gp = _g_.m.lockedg
@@ -114,7 +111,7 @@ func sighandler(sig uint32, info *_siginfo_t, ctxt unsafe.Pointer, gp *g) {
if docrash {
crashing++
- if crashing < mcount() {
+ if crashing < sched.mcount {
// There are other m's that need to dump their stacks.
// Relay SIGQUIT to the next m by sending it to the current process.
// All m's that have already received SIGQUIT have signal masks blocking
diff --git a/libgo/go/runtime/signal_sigtramp.go b/libgo/go/runtime/signal_sigtramp.go
deleted file mode 100644
index 667d5feed98..00000000000
--- a/libgo/go/runtime/signal_sigtramp.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
-
-package runtime
-
-import "unsafe"
-
-// For gccgo, use go:linkname so the C signal handler can call this one.
-//go:linkname sigtrampgo runtime.sigtrampgo
-
-// Continuation of the (assembly) sigtramp() logic.
-// This may be called with the world stopped.
-//go:nosplit
-//go:nowritebarrierrec
-func sigtrampgo(sig uint32, info *_siginfo_t, ctx unsafe.Pointer) {
- if sigfwdgo(sig, info, ctx) {
- return
- }
- g := getg()
- if g == nil {
- if sig == _SIGPROF {
- // Ignore profiling signals that arrive on
- // non-Go threads. On some systems they will
- // be handled directly by the signal handler,
- // by calling sigprofNonGo, in which case we won't
- // get here anyhow.
- return
- }
- c := sigctxt{info, ctx}
- badsignal(uintptr(sig), &c)
- return
- }
-
- setg(g.m.gsignal)
- sighandler(sig, info, ctx, g)
- setg(g)
-}
diff --git a/libgo/go/runtime/signal_unix.go b/libgo/go/runtime/signal_unix.go
index f59c9b95497..43247538b66 100644
--- a/libgo/go/runtime/signal_unix.go
+++ b/libgo/go/runtime/signal_unix.go
@@ -6,7 +6,16 @@
package runtime
-import _ "unsafe" // for go:linkname
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
+
+// For gccgo's C code to call:
+//go:linkname initsig runtime.initsig
+//go:linkname crash runtime.crash
+//go:linkname resetcpuprofiler runtime.resetcpuprofiler
+//go:linkname sigtrampgo runtime.sigtrampgo
//go:linkname os_sigpipe os.sigpipe
func os_sigpipe() {
@@ -19,3 +28,574 @@ func signame(sig uint32) string {
}
return sigtable[sig].name
}
+
+const (
+ _SIG_DFL uintptr = 0
+ _SIG_IGN uintptr = 1
+)
+
+// Stores the signal handlers registered before Go installed its own.
+// These signal handlers will be invoked in cases where Go doesn't want to
+// handle a particular signal (e.g., signal occurred on a non-Go thread).
+// See sigfwdgo() for more information on when the signals are forwarded.
+//
+// Signal forwarding is currently available only on Darwin and Linux.
+var fwdSig [_NSIG]uintptr
+
+// channels for synchronizing signal mask updates with the signal mask
+// thread
+var (
+ disableSigChan chan uint32
+ enableSigChan chan uint32
+ maskUpdatedChan chan struct{}
+)
+
+func init() {
+ // _NSIG is the number of signals on this operating system.
+ // sigtable should describe what to do for all the possible signals.
+ if len(sigtable) != _NSIG {
+ print("runtime: len(sigtable)=", len(sigtable), " _NSIG=", _NSIG, "\n")
+ throw("bad sigtable len")
+ }
+}
+
+var signalsOK bool
+
+// Initialize signals.
+// Called by libpreinit so runtime may not be initialized.
+//go:nosplit
+//go:nowritebarrierrec
+func initsig(preinit bool) {
+ if !preinit {
+ // It's now OK for signal handlers to run.
+ signalsOK = true
+ }
+
+ // For c-archive/c-shared this is called by libpreinit with
+ // preinit == true.
+ if (isarchive || islibrary) && !preinit {
+ return
+ }
+
+ for i := uint32(0); i < _NSIG; i++ {
+ t := &sigtable[i]
+ if t.flags == 0 || t.flags&_SigDefault != 0 {
+ continue
+ }
+ fwdSig[i] = getsig(i)
+
+ if !sigInstallGoHandler(i) {
+ // Even if we are not installing a signal handler,
+ // set SA_ONSTACK if necessary.
+ if fwdSig[i] != _SIG_DFL && fwdSig[i] != _SIG_IGN {
+ setsigstack(i)
+ }
+ continue
+ }
+
+ t.flags |= _SigHandling
+ setsig(i, getSigtramp())
+ }
+}
+
+//go:nosplit
+//go:nowritebarrierrec
+func sigInstallGoHandler(sig uint32) bool {
+ // For some signals, we respect an inherited SIG_IGN handler
+ // rather than insist on installing our own default handler.
+ // Even these signals can be fetched using the os/signal package.
+ switch sig {
+ case _SIGHUP, _SIGINT:
+ if fwdSig[sig] == _SIG_IGN {
+ return false
+ }
+ }
+
+ t := &sigtable[sig]
+ if t.flags&_SigSetStack != 0 {
+ return false
+ }
+
+ // When built using c-archive or c-shared, only install signal
+ // handlers for synchronous signals.
+ if (isarchive || islibrary) && t.flags&_SigPanic == 0 {
+ return false
+ }
+
+ return true
+}
+
+func sigenable(sig uint32) {
+ if sig >= uint32(len(sigtable)) {
+ return
+ }
+
+ t := &sigtable[sig]
+ if t.flags&_SigNotify != 0 {
+ ensureSigM()
+ enableSigChan <- sig
+ <-maskUpdatedChan
+ if t.flags&_SigHandling == 0 {
+ t.flags |= _SigHandling
+ fwdSig[sig] = getsig(sig)
+ setsig(sig, getSigtramp())
+ }
+ }
+}
+
+func sigdisable(sig uint32) {
+ if sig >= uint32(len(sigtable)) {
+ return
+ }
+
+ t := &sigtable[sig]
+ if t.flags&_SigNotify != 0 {
+ ensureSigM()
+ disableSigChan <- sig
+ <-maskUpdatedChan
+
+ // If initsig does not install a signal handler for a
+ // signal, then to go back to the state before Notify
+ // we should remove the one we installed.
+ if !sigInstallGoHandler(sig) {
+ t.flags &^= _SigHandling
+ setsig(sig, fwdSig[sig])
+ }
+ }
+}
+
+func sigignore(sig uint32) {
+ if sig >= uint32(len(sigtable)) {
+ return
+ }
+
+ t := &sigtable[sig]
+ if t.flags&_SigNotify != 0 {
+ t.flags &^= _SigHandling
+ setsig(sig, _SIG_IGN)
+ }
+}
+
+func resetcpuprofiler(hz int32) {
+ var it _itimerval
+ if hz == 0 {
+ setitimer(_ITIMER_PROF, &it, nil)
+ } else {
+ it.it_interval.tv_sec = 0
+ it.it_interval.set_usec(1000000 / hz)
+ it.it_value = it.it_interval
+ setitimer(_ITIMER_PROF, &it, nil)
+ }
+ _g_ := getg()
+ _g_.m.profilehz = hz
+}
+
+func sigpipe() {
+ if sigsend(_SIGPIPE) {
+ return
+ }
+ dieFromSignal(_SIGPIPE)
+}
+
+// sigtrampgo is called from the signal handler function, sigtramp,
+// written in assembly code.
+// This is called by the signal handler, and the world may be stopped.
+//go:nosplit
+//go:nowritebarrierrec
+func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
+ if sigfwdgo(sig, info, ctx) {
+ return
+ }
+ g := getg()
+ if g == nil {
+ c := sigctxt{info, ctx}
+ if sig == _SIGPROF {
+ _, pc := getSiginfo(info, ctx)
+ sigprofNonGoPC(pc)
+ return
+ }
+ badsignal(uintptr(sig), &c)
+ return
+ }
+
+ setg(g.m.gsignal)
+ sighandler(sig, info, ctx, g)
+ setg(g)
+}
+
+// sigpanic turns a synchronous signal into a run-time panic.
+// If the signal handler sees a synchronous panic, it arranges the
+// stack to look like the function where the signal occurred called
+// sigpanic, sets the signal's PC value to sigpanic, and returns from
+// the signal handler. The effect is that the program will act as
+// though the function that got the signal simply called sigpanic
+// instead.
+func sigpanic() {
+ g := getg()
+ if !canpanic(g) {
+ throw("unexpected signal during runtime execution")
+ }
+
+ switch g.sig {
+ case _SIGBUS:
+ if g.sigcode0 == _BUS_ADRERR && g.sigcode1 < 0x1000 {
+ panicmem()
+ }
+ // Support runtime/debug.SetPanicOnFault.
+ if g.paniconfault {
+ panicmem()
+ }
+ print("unexpected fault address ", hex(g.sigcode1), "\n")
+ throw("fault")
+ case _SIGSEGV:
+ if (g.sigcode0 == 0 || g.sigcode0 == _SEGV_MAPERR || g.sigcode0 == _SEGV_ACCERR) && g.sigcode1 < 0x1000 {
+ panicmem()
+ }
+ // Support runtime/debug.SetPanicOnFault.
+ if g.paniconfault {
+ panicmem()
+ }
+ print("unexpected fault address ", hex(g.sigcode1), "\n")
+ throw("fault")
+ case _SIGFPE:
+ switch g.sigcode0 {
+ case _FPE_INTDIV:
+ panicdivide()
+ case _FPE_INTOVF:
+ panicoverflow()
+ }
+ panicfloat()
+ }
+
+ if g.sig >= uint32(len(sigtable)) {
+ // can't happen: we looked up g.sig in sigtable to decide to call sigpanic
+ throw("unexpected signal value")
+ }
+ panic(errorString(sigtable[g.sig].name))
+}
+
+// dieFromSignal kills the program with a signal.
+// This provides the expected exit status for the shell.
+// This is only called with fatal signals expected to kill the process.
+//go:nosplit
+//go:nowritebarrierrec
+func dieFromSignal(sig uint32) {
+ setsig(sig, _SIG_DFL)
+ unblocksig(sig)
+ raise(sig)
+
+ // That should have killed us. On some systems, though, raise
+ // sends the signal to the whole process rather than to just
+ // the current thread, which means that the signal may not yet
+ // have been delivered. Give other threads a chance to run and
+ // pick up the signal.
+ osyield()
+ osyield()
+ osyield()
+
+ // If we are still somehow running, just exit with the wrong status.
+ exit(2)
+}
+
+// raisebadsignal is called when a signal is received on a non-Go
+// thread, and the Go program does not want to handle it (that is, the
+// program has not called os/signal.Notify for the signal).
+func raisebadsignal(sig uint32, c *sigctxt) {
+ if sig == _SIGPROF {
+ // Ignore profiling signals that arrive on non-Go threads.
+ return
+ }
+
+ var handler uintptr
+ if sig >= _NSIG {
+ handler = _SIG_DFL
+ } else {
+ handler = fwdSig[sig]
+ }
+
+ // Reset the signal handler and raise the signal.
+ // We are currently running inside a signal handler, so the
+ // signal is blocked. We need to unblock it before raising the
+ // signal, or the signal we raise will be ignored until we return
+ // from the signal handler. We know that the signal was unblocked
+ // before entering the handler, or else we would not have received
+ // it. That means that we don't have to worry about blocking it
+ // again.
+ unblocksig(sig)
+ setsig(sig, handler)
+
+ // If we're linked into a non-Go program we want to try to
+ // avoid modifying the original context in which the signal
+ // was raised. If the handler is the default, we know it
+ // is non-recoverable, so we don't have to worry about
+ // re-installing sighandler. At this point we can just
+ // return and the signal will be re-raised and caught by
+ // the default handler with the correct context.
+ if (isarchive || islibrary) && handler == _SIG_DFL && c.sigcode() != _SI_USER {
+ return
+ }
+
+ raise(sig)
+
+ // Give the signal a chance to be delivered.
+ // In almost all real cases the program is about to crash,
+ // so sleeping here is not a waste of time.
+ usleep(1000)
+
+ // If the signal didn't cause the program to exit, restore the
+ // Go signal handler and carry on.
+ //
+ // We may receive another instance of the signal before we
+ // restore the Go handler, but that is not so bad: we know
+ // that the Go program has been ignoring the signal.
+ setsig(sig, getSigtramp())
+}
+
+func crash() {
+ if GOOS == "darwin" {
+ // OS X core dumps are linear dumps of the mapped memory,
+ // from the first virtual byte to the last, with zeros in the gaps.
+ // Because of the way we arrange the address space on 64-bit systems,
+ // this means the OS X core file will be >128 GB and even on a zippy
+ // workstation can take OS X well over an hour to write (uninterruptible).
+ // Save users from making that mistake.
+ if sys.PtrSize == 8 {
+ return
+ }
+ }
+
+ dieFromSignal(_SIGABRT)
+}
+
+// ensureSigM starts one global, sleeping thread to make sure at least one thread
+// is available to catch signals enabled for os/signal.
+func ensureSigM() {
+ if maskUpdatedChan != nil {
+ return
+ }
+ maskUpdatedChan = make(chan struct{})
+ disableSigChan = make(chan uint32)
+ enableSigChan = make(chan uint32)
+ go func() {
+ // Signal masks are per-thread, so make sure this goroutine stays on one
+ // thread.
+ LockOSThread()
+ defer UnlockOSThread()
+ // The sigBlocked mask contains the signals not active for os/signal,
+ // initially all signals except the essential. When signal.Notify()/Stop is called,
+ // sigenable/sigdisable in turn notify this thread to update its signal
+ // mask accordingly.
+ var sigBlocked sigset
+ sigfillset(&sigBlocked)
+ for i := range sigtable {
+ if sigtable[i].flags&_SigUnblock != 0 {
+ sigdelset(&sigBlocked, i)
+ }
+ }
+ sigprocmask(_SIG_SETMASK, &sigBlocked, nil)
+ for {
+ select {
+ case sig := <-enableSigChan:
+ if sig > 0 {
+ sigdelset(&sigBlocked, int(sig))
+ }
+ case sig := <-disableSigChan:
+ if sig > 0 {
+ sigaddset(&sigBlocked, int(sig))
+ }
+ }
+ sigprocmask(_SIG_SETMASK, &sigBlocked, nil)
+ maskUpdatedChan <- struct{}{}
+ }
+ }()
+}
+
+// This is called when we receive a signal when there is no signal stack.
+// This can only happen if non-Go code calls sigaltstack to disable the
+// signal stack.
+func noSignalStack(sig uint32) {
+ println("signal", sig, "received on thread with no signal stack")
+ throw("non-Go code disabled sigaltstack")
+}
+
+// This is called if we receive a signal when there is a signal stack
+// but we are not on it. This can only happen if non-Go code called
+// sigaction without setting the SS_ONSTACK flag.
+func sigNotOnStack(sig uint32) {
+ println("signal", sig, "received but handler not on signal stack")
+ throw("non-Go code set up signal handler without SA_ONSTACK flag")
+}
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+//go:nosplit
+//go:norace
+//go:nowritebarrierrec
+func badsignal(sig uintptr, c *sigctxt) {
+ needm(0)
+ if !sigsend(uint32(sig)) {
+ // A foreign thread received the signal sig, and the
+ // Go code does not want to handle it.
+ raisebadsignal(uint32(sig), c)
+ }
+ dropm()
+}
+
+// Determines if the signal should be handled by Go and if not, forwards the
+// signal to the handler that was installed before Go's. Returns whether the
+// signal was forwarded.
+// This is called by the signal handler, and the world may be stopped.
+//go:nosplit
+//go:nowritebarrierrec
+func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool {
+ if sig >= uint32(len(sigtable)) {
+ return false
+ }
+ fwdFn := fwdSig[sig]
+
+ if !signalsOK {
+ // The only way we can get here is if we are in a
+ // library or archive, we installed a signal handler
+ // at program startup, but the Go runtime has not yet
+ // been initialized.
+ if fwdFn == _SIG_DFL {
+ dieFromSignal(sig)
+ } else {
+ sigfwd(fwdFn, sig, info, ctx)
+ }
+ return true
+ }
+
+ flags := sigtable[sig].flags
+
+ // If there is no handler to forward to, no need to forward.
+ if fwdFn == _SIG_DFL {
+ return false
+ }
+
+ // If we aren't handling the signal, forward it.
+ if flags&_SigHandling == 0 {
+ sigfwd(fwdFn, sig, info, ctx)
+ return true
+ }
+
+ // Only forward synchronous signals.
+ c := sigctxt{info, ctx}
+ if c.sigcode() == _SI_USER || flags&_SigPanic == 0 {
+ return false
+ }
+ // Determine if the signal occurred inside Go code. We test that:
+ // (1) we were in a goroutine (i.e., m.curg != nil), and
+ // (2) we weren't in CGO (i.e., m.curg.syscallsp == 0).
+ g := getg()
+ if g != nil && g.m != nil && g.m.curg != nil && g.m.curg.syscallsp == 0 {
+ return false
+ }
+ // Signal not handled by Go, forward it.
+ if fwdFn != _SIG_IGN {
+ sigfwd(fwdFn, sig, info, ctx)
+ }
+ return true
+}
+
+// msigsave saves the current thread's signal mask into mp.sigmask.
+// This is used to preserve the non-Go signal mask when a non-Go
+// thread calls a Go function.
+// This is nosplit and nowritebarrierrec because it is called by needm
+// which may be called on a non-Go thread with no g available.
+//go:nosplit
+//go:nowritebarrierrec
+func msigsave(mp *m) {
+ sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
+}
+
+// msigrestore sets the current thread's signal mask to sigmask.
+// This is used to restore the non-Go signal mask when a non-Go thread
+// calls a Go function.
+// This is nosplit and nowritebarrierrec because it is called by dropm
+// after g has been cleared.
+//go:nosplit
+//go:nowritebarrierrec
+func msigrestore(sigmask sigset) {
+ sigprocmask(_SIG_SETMASK, &sigmask, nil)
+}
+
+// sigblock blocks all signals in the current thread's signal mask.
+// This is used to block signals while setting up and tearing down g
+// when a non-Go thread calls a Go function.
+// The OS-specific code is expected to define sigset_all.
+// This is nosplit and nowritebarrierrec because it is called by needm
+// which may be called on a non-Go thread with no g available.
+//go:nosplit
+//go:nowritebarrierrec
+func sigblock() {
+ var set sigset
+ sigfillset(&set)
+ sigprocmask(_SIG_SETMASK, &set, nil)
+}
+
+// unblocksig removes sig from the current thread's signal mask.
+// This is nosplit and nowritebarrierrec because it is called from
+// dieFromSignal, which can be called by sigfwdgo while running in the
+// signal handler, on the signal stack, with no g available.
+//go:nosplit
+//go:nowritebarrierrec
+func unblocksig(sig uint32) {
+ var set sigset
+ sigemptyset(&set)
+ sigaddset(&set, int(sig))
+ sigprocmask(_SIG_UNBLOCK, &set, nil)
+}
+
+// minitSignals is called when initializing a new m to set the
+// thread's alternate signal stack and signal mask.
+func minitSignals() {
+ minitSignalStack()
+ minitSignalMask()
+}
+
+// minitSignalStack is called when initializing a new m to set the
+// alternate signal stack. If the alternate signal stack is not set
+// for the thread (the normal case) then set the alternate signal
+// stack to the gsignal stack. If the alternate signal stack is set
+// for the thread (the case when a non-Go thread sets the alternate
+// signal stack and then calls a Go function) then set the gsignal
+// stack to the alternate signal stack. Record which choice was made
+// in newSigstack, so that it can be undone in unminit.
+func minitSignalStack() {
+ _g_ := getg()
+ var st _stack_t
+ sigaltstack(nil, &st)
+ if st.ss_flags&_SS_DISABLE != 0 {
+ signalstack(_g_.m.gsignalstack, _g_.m.gsignalstacksize)
+ _g_.m.newSigstack = true
+ } else {
+ _g_.m.newSigstack = false
+ }
+}
+
+// minitSignalMask is called when initializing a new m to set the
+// thread's signal mask. When this is called all signals have been
+// blocked for the thread. This starts with m.sigmask, which was set
+// either from initSigmask for a newly created thread or by calling
+// msigsave if this is a non-Go thread calling a Go function. It
+// removes all essential signals from the mask, thus causing those
+// signals to not be blocked. Then it sets the thread's signal mask.
+// After this is called the thread can receive signals.
+func minitSignalMask() {
+ nmask := getg().m.sigmask
+ for i := range sigtable {
+ if sigtable[i].flags&_SigUnblock != 0 {
+ sigdelset(&nmask, i)
+ }
+ }
+ sigprocmask(_SIG_SETMASK, &nmask, nil)
+}
+
+// unminitSignals is called from dropm, via unminit, to undo the
+// effect of calling minit on a non-Go thread.
+//go:nosplit
+func unminitSignals() {
+ if getg().m.newSigstack {
+ signalstack(nil, 0)
+ }
+}
diff --git a/libgo/go/runtime/sigpanic_unix.go b/libgo/go/runtime/sigpanic_unix.go
deleted file mode 100644
index 00ad090f428..00000000000
--- a/libgo/go/runtime/sigpanic_unix.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin dragonfly freebsd linux netbsd openbsd solaris
-
-package runtime
-
-import _ "unsafe" // For go:linkname.
-
-// For gccgo, C code has to call sigpanic, so we have to export it.
-//go:linkname sigpanic runtime.sigpanic
-
-func sigpanic() {
- g := getg()
- if !canpanic(g) {
- throw("unexpected signal during runtime execution")
- }
-
- switch g.sig {
- case _SIGBUS:
- if g.sigcode0 == _BUS_ADRERR && g.sigcode1 < 0x1000 || g.paniconfault {
- panicmem()
- }
- print("unexpected fault address ", hex(g.sigcode1), "\n")
- throw("fault")
- case _SIGSEGV:
- if (g.sigcode0 == 0 || g.sigcode0 == _SEGV_MAPERR || g.sigcode0 == _SEGV_ACCERR) && g.sigcode1 < 0x1000 || g.paniconfault {
- panicmem()
- }
- print("unexpected fault address ", hex(g.sigcode1), "\n")
- throw("fault")
- case _SIGFPE:
- switch g.sigcode0 {
- case _FPE_INTDIV:
- panicdivide()
- case _FPE_INTOVF:
- panicoverflow()
- }
- panicfloat()
- }
-
- if g.sig >= uint32(len(sigtable)) {
- // can't happen: we looked up g.sig in sigtable to decide to call sigpanic
- throw("unexpected signal value")
- }
- panic(errorString(sigtable[g.sig].name))
-}
diff --git a/libgo/go/runtime/sizeclasses.go b/libgo/go/runtime/sizeclasses.go
new file mode 100644
index 00000000000..e616e95148c
--- /dev/null
+++ b/libgo/go/runtime/sizeclasses.go
@@ -0,0 +1,95 @@
+// AUTO-GENERATED by mksizeclasses.go; DO NOT EDIT
+//go:generate go run mksizeclasses.go
+
+package runtime
+
+// class bytes/obj bytes/span objects waste bytes
+// 1 8 8192 1024 0
+// 2 16 8192 512 0
+// 3 32 8192 256 0
+// 4 48 8192 170 32
+// 5 64 8192 128 0
+// 6 80 8192 102 32
+// 7 96 8192 85 32
+// 8 112 8192 73 16
+// 9 128 8192 64 0
+// 10 144 8192 56 128
+// 11 160 8192 51 32
+// 12 176 8192 46 96
+// 13 192 8192 42 128
+// 14 208 8192 39 80
+// 15 224 8192 36 128
+// 16 240 8192 34 32
+// 17 256 8192 32 0
+// 18 288 8192 28 128
+// 19 320 8192 25 192
+// 20 352 8192 23 96
+// 21 384 8192 21 128
+// 22 416 8192 19 288
+// 23 448 8192 18 128
+// 24 480 8192 17 32
+// 25 512 8192 16 0
+// 26 576 8192 14 128
+// 27 640 8192 12 512
+// 28 704 8192 11 448
+// 29 768 8192 10 512
+// 30 896 8192 9 128
+// 31 1024 8192 8 0
+// 32 1152 8192 7 128
+// 33 1280 8192 6 512
+// 34 1408 16384 11 896
+// 35 1536 8192 5 512
+// 36 1792 16384 9 256
+// 37 2048 8192 4 0
+// 38 2304 16384 7 256
+// 39 2688 8192 3 128
+// 40 3072 24576 8 0
+// 41 3200 16384 5 384
+// 42 3456 24576 7 384
+// 43 4096 8192 2 0
+// 44 4864 24576 5 256
+// 45 5376 16384 3 256
+// 46 6144 24576 4 0
+// 47 6528 32768 5 128
+// 48 6784 40960 6 256
+// 49 6912 49152 7 768
+// 50 8192 8192 1 0
+// 51 9472 57344 6 512
+// 52 9728 49152 5 512
+// 53 10240 40960 4 0
+// 54 10880 32768 3 128
+// 55 12288 24576 2 0
+// 56 13568 40960 3 256
+// 57 14336 57344 4 0
+// 58 16384 16384 1 0
+// 59 18432 73728 4 0
+// 60 19072 57344 3 128
+// 61 20480 40960 2 0
+// 62 21760 65536 3 256
+// 63 24576 24576 1 0
+// 64 27264 81920 3 128
+// 65 28672 57344 2 0
+// 66 32768 32768 1 0
+
+const (
+ _MaxSmallSize = 32768
+ smallSizeDiv = 8
+ smallSizeMax = 1024
+ largeSizeDiv = 128
+ _NumSizeClasses = 67
+ _PageShift = 13
+)
+
+var class_to_size = [_NumSizeClasses]uint16{0, 8, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384, 416, 448, 480, 512, 576, 640, 704, 768, 896, 1024, 1152, 1280, 1408, 1536, 1792, 2048, 2304, 2688, 3072, 3200, 3456, 4096, 4864, 5376, 6144, 6528, 6784, 6912, 8192, 9472, 9728, 10240, 10880, 12288, 13568, 14336, 16384, 18432, 19072, 20480, 21760, 24576, 27264, 28672, 32768}
+var class_to_allocnpages = [_NumSizeClasses]uint8{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 3, 2, 3, 1, 3, 2, 3, 4, 5, 6, 1, 7, 6, 5, 4, 3, 5, 7, 2, 9, 7, 5, 8, 3, 10, 7, 4}
+
+type divMagic struct {
+ shift uint8
+ shift2 uint8
+ mul uint16
+ baseMask uint16
+}
+
+var class_to_divmagic = [_NumSizeClasses]divMagic{{0, 0, 0, 0}, {3, 0, 1, 65528}, {4, 0, 1, 65520}, {5, 0, 1, 65504}, {4, 9, 171, 0}, {6, 0, 1, 65472}, {4, 10, 205, 0}, {5, 9, 171, 0}, {4, 11, 293, 0}, {7, 0, 1, 65408}, {4, 9, 57, 0}, {5, 10, 205, 0}, {4, 12, 373, 0}, {6, 7, 43, 0}, {4, 13, 631, 0}, {5, 11, 293, 0}, {4, 13, 547, 0}, {8, 0, 1, 65280}, {5, 9, 57, 0}, {6, 9, 103, 0}, {5, 12, 373, 0}, {7, 7, 43, 0}, {5, 10, 79, 0}, {6, 10, 147, 0}, {5, 11, 137, 0}, {9, 0, 1, 65024}, {6, 9, 57, 0}, {7, 6, 13, 0}, {6, 11, 187, 0}, {8, 5, 11, 0}, {7, 8, 37, 0}, {10, 0, 1, 64512}, {7, 9, 57, 0}, {8, 6, 13, 0}, {7, 11, 187, 0}, {9, 5, 11, 0}, {8, 8, 37, 0}, {11, 0, 1, 63488}, {8, 9, 57, 0}, {7, 10, 49, 0}, {10, 5, 11, 0}, {7, 10, 41, 0}, {7, 9, 19, 0}, {12, 0, 1, 61440}, {8, 9, 27, 0}, {8, 10, 49, 0}, {11, 5, 11, 0}, {7, 13, 161, 0}, {7, 13, 155, 0}, {8, 9, 19, 0}, {13, 0, 1, 57344}, {8, 12, 111, 0}, {9, 9, 27, 0}, {11, 6, 13, 0}, {7, 14, 193, 0}, {12, 3, 3, 0}, {8, 13, 155, 0}, {11, 8, 37, 0}, {14, 0, 1, 49152}, {11, 8, 29, 0}, {7, 13, 55, 0}, {12, 5, 7, 0}, {8, 14, 193, 0}, {13, 3, 3, 0}, {7, 14, 77, 0}, {12, 7, 19, 0}, {15, 0, 1, 32768}}
+var size_to_class8 = [smallSizeMax/smallSizeDiv + 1]uint8{0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31}
+var size_to_class128 = [(_MaxSmallSize-smallSizeMax)/largeSizeDiv + 1]uint8{31, 32, 33, 34, 35, 36, 36, 37, 37, 38, 38, 39, 39, 39, 40, 40, 40, 41, 42, 42, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 47, 47, 47, 48, 48, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66}
diff --git a/libgo/go/runtime/slice.go b/libgo/go/runtime/slice.go
index 4548a5b2321..55f4454027d 100644
--- a/libgo/go/runtime/slice.go
+++ b/libgo/go/runtime/slice.go
@@ -12,6 +12,7 @@ import (
// themselves, so that the compiler will export them.
//
//go:linkname makeslice runtime.makeslice
+//go:linkname makeslice64 runtime.makeslice64
//go:linkname growslice runtime.growslice
//go:linkname slicecopy runtime.slicecopy
//go:linkname slicestringcopy runtime.slicestringcopy
@@ -44,21 +45,18 @@ func maxSliceCap(elemsize uintptr) uintptr {
return _MaxMem / elemsize
}
-// TODO: take uintptrs instead of int64s?
-func makeslice(et *_type, len64, cap64 int64) slice {
+func makeslice(et *_type, len, cap int) slice {
// NOTE: The len > maxElements check here is not strictly necessary,
// but it produces a 'len out of range' error instead of a 'cap out of range' error
// when someone does make([]T, bignumber). 'cap out of range' is true too,
// but since the cap is only being supplied implicitly, saying len is clearer.
// See issue 4085.
maxElements := maxSliceCap(et.size)
- len := int(len64)
- if len64 < 0 || int64(len) != len64 || uintptr(len) > maxElements {
+ if len < 0 || uintptr(len) > maxElements {
panic(errorString("makeslice: len out of range"))
}
- cap := int(cap64)
- if cap < len || int64(cap) != cap64 || uintptr(cap) > maxElements {
+ if cap < len || uintptr(cap) > maxElements {
panic(errorString("makeslice: cap out of range"))
}
@@ -69,6 +67,20 @@ func makeslice(et *_type, len64, cap64 int64) slice {
return slice{p, len, cap}
}
+func makeslice64(et *_type, len64, cap64 int64) slice {
+ len := int(len64)
+ if int64(len) != len64 {
+ panic(errorString("makeslice: len out of range"))
+ }
+
+ cap := int(cap64)
+ if int64(cap) != cap64 {
+ panic(errorString("makeslice: cap out of range"))
+ }
+
+ return makeslice(et, len, cap)
+}
+
// growslice handles slice growth during append.
// It is passed the slice element type, the old slice, and the desired new minimum capacity,
// and it returns a new slice with at least that capacity, with the old data
@@ -106,19 +118,22 @@ func growslice(et *_type, old slice, cap int) slice {
}
}
- var lenmem, capmem uintptr
+ var lenmem, newlenmem, capmem uintptr
const ptrSize = unsafe.Sizeof((*byte)(nil))
switch et.size {
case 1:
lenmem = uintptr(old.len)
+ newlenmem = uintptr(cap)
capmem = roundupsize(uintptr(newcap))
newcap = int(capmem)
case ptrSize:
lenmem = uintptr(old.len) * ptrSize
+ newlenmem = uintptr(cap) * ptrSize
capmem = roundupsize(uintptr(newcap) * ptrSize)
newcap = int(capmem / ptrSize)
default:
lenmem = uintptr(old.len) * et.size
+ newlenmem = uintptr(cap) * et.size
capmem = roundupsize(uintptr(newcap) * et.size)
newcap = int(capmem / et.size)
}
@@ -136,7 +151,10 @@ func growslice(et *_type, old slice, cap int) slice {
// the newarray function will zero the memory.
// Calling memclr is also wrong since we allocated
// newcap*et.size bytes, which is not the same as capmem.
- // memclr(add(p, lenmem), capmem-lenmem)
+ // The append() that calls growslice is going to overwrite from old.len to cap (which will be the new length).
+ // Only clear the part that will not be overwritten.
+ // memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem)
+ _ = newlenmem
} else {
// Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory.
// gccgo's current GC requires newarray, not mallocgc.
diff --git a/libgo/go/runtime/stack.go b/libgo/go/runtime/stack.go
index 708a4c299cc..fd99e4d2f67 100644
--- a/libgo/go/runtime/stack.go
+++ b/libgo/go/runtime/stack.go
@@ -92,7 +92,7 @@ const (
// The stack guard is a pointer this many bytes above the
// bottom of the stack.
- _StackGuard = 720*sys.StackGuardMultiplier + _StackSystem
+ _StackGuard = 880*sys.StackGuardMultiplier + _StackSystem
// After a stack split check the SP is allowed to be this
// many bytes below the stack guard. This saves an instruction
@@ -125,6 +125,9 @@ const (
stackPoisonCopy = 0 // fill stack that should not be accessed with garbage, to detect bad dereferences during copy
stackCache = 1
+
+ // check the BP links during traceback.
+ debugCheckBP = false
)
const (
@@ -337,6 +340,7 @@ func stackalloc(n uint32) (stack, []stkbar) {
// Compute the size of stack barrier array.
maxstkbar := gcMaxStackBarriers(int(n))
nstkbar := unsafe.Sizeof(stkbar{}) * uintptr(maxstkbar)
+ var stkbarSlice slice
if debug.efence != 0 || stackFromSystem != 0 {
v := sysAlloc(round(uintptr(n), _PageSize), &memstats.stacks_sys)
@@ -344,7 +348,9 @@ func stackalloc(n uint32) (stack, []stkbar) {
throw("out of memory (stackalloc)")
}
top := uintptr(n) - nstkbar
- stkbarSlice := slice{add(v, top), 0, maxstkbar}
+ if maxstkbar != 0 {
+ stkbarSlice = slice{add(v, top), 0, maxstkbar}
+ }
return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice))
}
@@ -412,7 +418,9 @@ func stackalloc(n uint32) (stack, []stkbar) {
print(" allocated ", v, "\n")
}
top := uintptr(n) - nstkbar
- stkbarSlice := slice{add(v, top), 0, maxstkbar}
+ if maxstkbar != 0 {
+ stkbarSlice = slice{add(v, top), 0, maxstkbar}
+ }
return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice))
}
@@ -433,7 +441,7 @@ func stackfree(stk stack, n uintptr) {
}
if stackDebug >= 1 {
println("stackfree", v, n)
- memclr(v, n) // for testing, clobber stack data
+ memclrNoHeapPointers(v, n) // for testing, clobber stack data
}
if debug.efence != 0 || stackFromSystem != 0 {
if debug.efence != 0 || stackFaultOnFree != 0 {
@@ -595,16 +603,16 @@ func adjustpointers(scanp unsafe.Pointer, cbv *bitvector, adjinfo *adjustinfo, f
pp := (*uintptr)(add(scanp, i*sys.PtrSize))
retry:
p := *pp
- if f != nil && 0 < p && p < _PageSize && debug.invalidptr != 0 {
+ if f != nil && 0 < p && p < minLegalPointer && debug.invalidptr != 0 {
// Looks like a junk value in a pointer slot.
// Live analysis wrong?
getg().m.traceback = 2
print("runtime: bad pointer in frame ", funcname(f), " at ", pp, ": ", hex(p), "\n")
- throw("invalid stack pointer")
+ throw("invalid pointer found on stack")
}
if minp <= p && p < maxp {
if stackDebug >= 3 {
- print("adjust ptr ", p, " ", funcname(f), "\n")
+ print("adjust ptr ", hex(p), " ", funcname(f), "\n")
}
if useCAS {
ppu := (*unsafe.Pointer)(unsafe.Pointer(pp))
@@ -685,6 +693,16 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
if stackDebug >= 3 {
print(" saved bp\n")
}
+ if debugCheckBP {
+ // Frame pointers should always point to the next higher frame on
+ // the Go stack (or be nil, for the top frame on the stack).
+ bp := *(*uintptr)(unsafe.Pointer(frame.varp))
+ if bp != 0 && (bp < adjinfo.old.lo || bp >= adjinfo.old.hi) {
+ println("runtime: found invalid frame pointer")
+ print("bp=", hex(bp), " min=", hex(adjinfo.old.lo), " max=", hex(adjinfo.old.hi), "\n")
+ throw("bad frame pointer")
+ }
+ }
adjustpointer(adjinfo, unsafe.Pointer(frame.varp))
}
@@ -716,6 +734,18 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
func adjustctxt(gp *g, adjinfo *adjustinfo) {
adjustpointer(adjinfo, unsafe.Pointer(&gp.sched.ctxt))
+ if !framepointer_enabled {
+ return
+ }
+ if debugCheckBP {
+ bp := gp.sched.bp
+ if bp != 0 && (bp < adjinfo.old.lo || bp >= adjinfo.old.hi) {
+ println("runtime: found invalid top frame pointer")
+ print("bp=", hex(bp), " min=", hex(adjinfo.old.lo), " max=", hex(adjinfo.old.hi), "\n")
+ throw("bad top frame pointer")
+ }
+ }
+ adjustpointer(adjinfo, unsafe.Pointer(&gp.sched.bp))
}
func adjustdefers(gp *g, adjinfo *adjustinfo) {
@@ -927,7 +957,10 @@ func round2(x int32) int32 {
//
// g->atomicstatus will be Grunning or Gscanrunning upon entry.
// If the GC is trying to stop this g then it will set preemptscan to true.
-func newstack() {
+//
+// ctxt is the value of the context register on morestack. newstack
+// will write it to g.sched.ctxt.
+func newstack(ctxt unsafe.Pointer) {
thisg := getg()
// TODO: double check all gp. shouldn't be getg().
if thisg.m.morebuf.g.ptr().stackguard0 == stackFork {
@@ -939,8 +972,13 @@ func newstack() {
traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g.ptr())
throw("runtime: wrong goroutine in newstack")
}
+
+ gp := thisg.m.curg
+ // Write ctxt to gp.sched. We do this here instead of in
+ // morestack so it has the necessary write barrier.
+ gp.sched.ctxt = ctxt
+
if thisg.m.curg.throwsplit {
- gp := thisg.m.curg
// Update syscallsp, syscallpc in case traceback uses them.
morebuf := thisg.m.morebuf
gp.syscallsp = morebuf.sp
@@ -953,13 +991,11 @@ func newstack() {
throw("runtime: stack split at bad time")
}
- gp := thisg.m.curg
morebuf := thisg.m.morebuf
thisg.m.morebuf.pc = 0
thisg.m.morebuf.lr = 0
thisg.m.morebuf.sp = 0
thisg.m.morebuf.g = 0
- rewindmorestack(&gp.sched)
// NOTE: stackguard0 may change underfoot, if another thread
// is about to try to preempt gp. Read it just once and use that same
@@ -1006,14 +1042,6 @@ func newstack() {
throw("runtime: split stack overflow")
}
- if gp.sched.ctxt != nil {
- // morestack wrote sched.ctxt on its way in here,
- // without a write barrier. Run the write barrier now.
- // It is not possible to be preempted between then
- // and now, so it's okay.
- writebarrierptr_nostore((*uintptr)(unsafe.Pointer(&gp.sched.ctxt)), uintptr(gp.sched.ctxt))
- }
-
if preempt {
if gp == thisg.m.g0 {
throw("runtime: preempt g0")
@@ -1121,6 +1149,11 @@ func shrinkstack(gp *g) {
if debug.gcshrinkstackoff > 0 {
return
}
+ if gp.startpc == gcBgMarkWorkerPC {
+ // We're not allowed to shrink the gcBgMarkWorker
+ // stack (see gcBgMarkWorker for explanation).
+ return
+ }
oldsize := gp.stackAlloc
newsize := oldsize / 2
diff --git a/libgo/go/runtime/string.go b/libgo/go/runtime/string.go
index bf5791e06ff..9cc28737434 100644
--- a/libgo/go/runtime/string.go
+++ b/libgo/go/runtime/string.go
@@ -4,9 +4,7 @@
package runtime
-import (
- "unsafe"
-)
+import "unsafe"
// For gccgo, use go:linkname to rename compiler-called functions to
// themselves, so that the compiler will export them.
@@ -19,12 +17,9 @@ import (
//go:linkname slicebytetostring runtime.slicebytetostring
//go:linkname slicebytetostringtmp runtime.slicebytetostringtmp
//go:linkname stringtoslicebyte runtime.stringtoslicebyte
-//go:linkname stringtoslicebytetmp runtime.stringtoslicebytetmp
//go:linkname stringtoslicerune runtime.stringtoslicerune
//go:linkname slicerunetostring runtime.slicerunetostring
//go:linkname intstring runtime.intstring
-//go:linkname stringiter runtime.stringiter
-//go:linkname stringiter2 runtime.stringiter2
// Temporary for C code to call:
//go:linkname gostringnocopy runtime.gostringnocopy
//go:linkname findnull runtime.findnull
@@ -68,10 +63,9 @@ func concatstrings(buf *tmpBuf, a []string) string {
// return a[idx]
// }
s, b := rawstringtmp(buf, l)
- l = 0
for _, x := range a {
- copy(b[l:], x)
- l += len(x)
+ copy(b, x)
+ b = b[len(x):]
}
return s
}
@@ -126,17 +120,20 @@ func rawstringtmp(buf *tmpBuf, l int) (s string, b []byte) {
return
}
+// slicebytetostringtmp returns a "string" referring to the actual []byte bytes.
+//
+// Callers need to ensure that the returned string will not be used after
+// the calling goroutine modifies the original slice or synchronizes with
+// another goroutine.
+//
+// The function is only called when instrumenting
+// and otherwise intrinsified by the compiler.
+//
+// Some internal compiler optimizations use this function.
+// - Used for m[string(k)] lookup where m is a string-keyed map and k is a []byte.
+// - Used for "<"+string(b)+">" concatenation where b is []byte.
+// - Used for string(b)=="foo" comparison where b is []byte.
func slicebytetostringtmp(b []byte) string {
- // Return a "string" referring to the actual []byte bytes.
- // This is only for use by internal compiler optimizations
- // that know that the string form will be discarded before
- // the calling goroutine could possibly modify the original
- // slice or synchronize with another goroutine.
- // First such case is a m[string(k)] lookup where
- // m is a string-keyed map and k is a []byte.
- // Second such case is "<"+string(b)+">" concatenation where b is []byte.
- // Third such case is string(b)=="foo" comparison where b is []byte.
-
if raceenabled && len(b) > 0 {
racereadrangepc(unsafe.Pointer(&b[0]),
uintptr(len(b)),
@@ -161,28 +158,14 @@ func stringtoslicebyte(buf *tmpBuf, s string) []byte {
return b
}
-func stringtoslicebytetmp(s string) []byte {
- // Return a slice referring to the actual string bytes.
- // This is only for use by internal compiler optimizations
- // that know that the slice won't be mutated.
- // The only such case today is:
- // for i, c := range []byte(str)
-
- str := stringStructOf(&s)
- ret := slice{array: str.str, len: str.len, cap: str.len}
- return *(*[]byte)(unsafe.Pointer(&ret))
-}
-
func stringtoslicerune(buf *[tmpStringBufSize]rune, s string) []rune {
// two passes.
// unlike slicerunetostring, no race because strings are immutable.
n := 0
- t := s
- for len(s) > 0 {
- _, k := charntorune(s)
- s = s[k:]
+ for range s {
n++
}
+
var a []rune
if buf != nil && n <= len(buf) {
*buf = [tmpStringBufSize]rune{}
@@ -190,10 +173,9 @@ func stringtoslicerune(buf *[tmpStringBufSize]rune, s string) []rune {
} else {
a = rawruneslice(n)
}
+
n = 0
- for len(t) > 0 {
- r, k := charntorune(t)
- t = t[k:]
+ for _, r := range s {
a[n] = r
n++
}
@@ -213,7 +195,7 @@ func slicerunetostring(buf *tmpBuf, a []rune) string {
var dum [4]byte
size1 := 0
for _, r := range a {
- size1 += runetochar(dum[:], r)
+ size1 += encoderune(dum[:], r)
}
s, b := rawstringtmp(buf, size1+3)
size2 := 0
@@ -222,7 +204,7 @@ func slicerunetostring(buf *tmpBuf, a []rune) string {
if size2 >= size1 {
break
}
- size2 += runetochar(b[size2:], r)
+ size2 += encoderune(b[size2:], r)
}
return s[:size2]
}
@@ -252,48 +234,12 @@ func intstring(buf *[4]byte, v int64) string {
s, b = rawstring(4)
}
if int64(rune(v)) != v {
- v = runeerror
+ v = runeError
}
- n := runetochar(b, rune(v))
+ n := encoderune(b, rune(v))
return s[:n]
}
-// stringiter returns the index of the next
-// rune after the rune that starts at s[k].
-func stringiter(s string, k int) int {
- if k >= len(s) {
- // 0 is end of iteration
- return 0
- }
-
- c := s[k]
- if c < runeself {
- return k + 1
- }
-
- // multi-char rune
- _, n := charntorune(s[k:])
- return k + n
-}
-
-// stringiter2 returns the rune that starts at s[k]
-// and the index where the next rune starts.
-func stringiter2(s string, k int) (int, rune) {
- if k >= len(s) {
- // 0 is end of iteration
- return 0, 0
- }
-
- c := s[k]
- if c < runeself {
- return k + 1, rune(c)
- }
-
- // multi-char rune
- r, n := charntorune(s[k:])
- return k + n, r
-}
-
// rawstring allocates storage for a new string. The returned
// string and byte slice both refer to the same storage.
// The storage is not zeroed. Callers should use
@@ -305,6 +251,7 @@ func rawstring(size int) (s string, b []byte) {
stringStructOf(&s).len = size
*(*slice)(unsafe.Pointer(&b)) = slice{p, size, size}
+
return
}
@@ -313,7 +260,7 @@ func rawbyteslice(size int) (b []byte) {
cap := roundupsize(uintptr(size))
p := mallocgc(cap, nil, false)
if cap != uintptr(size) {
- memclr(add(p, uintptr(size)), cap-uintptr(size))
+ memclrNoHeapPointers(add(p, uintptr(size)), cap-uintptr(size))
}
*(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(cap)}
@@ -328,7 +275,7 @@ func rawruneslice(size int) (b []rune) {
mem := roundupsize(uintptr(size) * 4)
p := mallocgc(mem, nil, false)
if mem != uintptr(size)*4 {
- memclr(add(p, uintptr(size)*4), mem-uintptr(size)*4)
+ memclrNoHeapPointers(add(p, uintptr(size)*4), mem-uintptr(size)*4)
}
*(*slice)(unsafe.Pointer(&b)) = slice{p, size, int(mem / 4)}
@@ -384,13 +331,66 @@ func hasprefix(s, t string) bool {
return len(s) >= len(t) && s[:len(t)] == t
}
-func atoi(s string) int {
- n := 0
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- n = n*10 + int(s[0]) - '0'
+const (
+ maxUint = ^uint(0)
+ maxInt = int(maxUint >> 1)
+)
+
+// atoi parses an int from a string s.
+// The bool result reports whether s is a number
+// representable by a value of type int.
+func atoi(s string) (int, bool) {
+ if s == "" {
+ return 0, false
+ }
+
+ neg := false
+ if s[0] == '-' {
+ neg = true
s = s[1:]
}
- return n
+
+ un := uint(0)
+ for i := 0; i < len(s); i++ {
+ c := s[i]
+ if c < '0' || c > '9' {
+ return 0, false
+ }
+ if un > maxUint/10 {
+ // overflow
+ return 0, false
+ }
+ un *= 10
+ un1 := un + uint(c) - '0'
+ if un1 < un {
+ // overflow
+ return 0, false
+ }
+ un = un1
+ }
+
+ if !neg && un > uint(maxInt) {
+ return 0, false
+ }
+ if neg && un > uint(maxInt)+1 {
+ return 0, false
+ }
+
+ n := int(un)
+ if neg {
+ n = -n
+ }
+
+ return n, true
+}
+
+// atoi32 is like atoi but for integers
+// that fit into an int32.
+func atoi32(s string) (int32, bool) {
+ if n, ok := atoi(s); n == int(int32(n)) {
+ return int32(n), ok
+ }
+ return 0, false
}
//go:nosplit
@@ -430,7 +430,7 @@ func gostringw(strw *uint16) string {
str := (*[_MaxMem/2/2 - 1]uint16)(unsafe.Pointer(strw))
n1 := 0
for i := 0; str[i] != 0; i++ {
- n1 += runetochar(buf[:], rune(str[i]))
+ n1 += encoderune(buf[:], rune(str[i]))
}
s, b := rawstring(n1 + 4)
n2 := 0
@@ -439,7 +439,7 @@ func gostringw(strw *uint16) string {
if n2 >= n1 {
break
}
- n2 += runetochar(b[n2:], rune(str[i]))
+ n2 += encoderune(b[n2:], rune(str[i]))
}
b[n2] = 0 // for luck
return s[:n2]
diff --git a/libgo/go/runtime/string_test.go b/libgo/go/runtime/string_test.go
index 11fa454a5a8..ee306999e2e 100644
--- a/libgo/go/runtime/string_test.go
+++ b/libgo/go/runtime/string_test.go
@@ -5,6 +5,7 @@
package runtime_test
import (
+ "runtime"
"strings"
"testing"
)
@@ -81,28 +82,50 @@ func BenchmarkCompareStringBig(b *testing.B) {
b.SetBytes(int64(len(s1)))
}
-func BenchmarkRuneIterate(b *testing.B) {
- bytes := make([]byte, 100)
- for i := range bytes {
- bytes[i] = byte('A')
- }
- s := string(bytes)
+func BenchmarkConcatStringAndBytes(b *testing.B) {
+ s1 := []byte("Gophers!")
for i := 0; i < b.N; i++ {
- for range s {
- }
+ _ = "Hello " + string(s1)
}
}
-func BenchmarkRuneIterate2(b *testing.B) {
- bytes := make([]byte, 100)
- for i := range bytes {
- bytes[i] = byte('A')
- }
- s := string(bytes)
- for i := 0; i < b.N; i++ {
- for range s {
+var stringdata = []struct{ name, data string }{
+ {"ASCII", "01234567890"},
+ {"Japanese", "日本語日本語日本語"},
+ {"MixedLength", "$Ѐࠀက퀀𐀀\U00040000\U0010FFFF"},
+}
+
+func BenchmarkRuneIterate(b *testing.B) {
+ b.Run("range", func(b *testing.B) {
+ for _, sd := range stringdata {
+ b.Run(sd.name, func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for range sd.data {
+ }
+ }
+ })
}
- }
+ })
+ b.Run("range1", func(b *testing.B) {
+ for _, sd := range stringdata {
+ b.Run(sd.name, func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _ = range sd.data {
+ }
+ }
+ })
+ }
+ })
+ b.Run("range2", func(b *testing.B) {
+ for _, sd := range stringdata {
+ b.Run(sd.name, func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ for _, _ = range sd.data {
+ }
+ }
+ })
+ }
+ })
}
func BenchmarkArrayEqual(b *testing.B) {
@@ -149,21 +172,6 @@ func TestLargeStringConcat(t *testing.T) {
}
}
-/*
-func TestGostringnocopy(t *testing.T) {
- max := *runtime.Maxstring
- b := make([]byte, max+10)
- for i := uintptr(0); i < max+9; i++ {
- b[i] = 'a'
- }
- _ = runtime.Gostringnocopy(&b[0])
- newmax := *runtime.Maxstring
- if newmax != max+9 {
- t.Errorf("want %d, got %d", max+9, newmax)
- }
-}
-*/
-
func TestCompareTempString(t *testing.T) {
s := strings.Repeat("x", sizeNoStack)
b := []byte(s)
@@ -277,3 +285,97 @@ func TestString2Slice(t *testing.T) {
t.Errorf("extra runes not zeroed")
}
}
+
+const intSize = 32 << (^uint(0) >> 63)
+
+type atoi64Test struct {
+ in string
+ out int64
+ ok bool
+}
+
+var atoi64tests = []atoi64Test{
+ {"", 0, false},
+ {"0", 0, true},
+ {"-0", 0, true},
+ {"1", 1, true},
+ {"-1", -1, true},
+ {"12345", 12345, true},
+ {"-12345", -12345, true},
+ {"012345", 12345, true},
+ {"-012345", -12345, true},
+ {"12345x", 0, false},
+ {"-12345x", 0, false},
+ {"98765432100", 98765432100, true},
+ {"-98765432100", -98765432100, true},
+ {"20496382327982653440", 0, false},
+ {"-20496382327982653440", 0, false},
+ {"9223372036854775807", 1<<63 - 1, true},
+ {"-9223372036854775807", -(1<<63 - 1), true},
+ {"9223372036854775808", 0, false},
+ {"-9223372036854775808", -1 << 63, true},
+ {"9223372036854775809", 0, false},
+ {"-9223372036854775809", 0, false},
+}
+
+func TestAtoi(t *testing.T) {
+ switch intSize {
+ case 32:
+ for i := range atoi32tests {
+ test := &atoi32tests[i]
+ out, ok := runtime.Atoi(test.in)
+ if test.out != int32(out) || test.ok != ok {
+ t.Errorf("atoi(%q) = (%v, %v) want (%v, %v)",
+ test.in, out, ok, test.out, test.ok)
+ }
+ }
+ case 64:
+ for i := range atoi64tests {
+ test := &atoi64tests[i]
+ out, ok := runtime.Atoi(test.in)
+ if test.out != int64(out) || test.ok != ok {
+ t.Errorf("atoi(%q) = (%v, %v) want (%v, %v)",
+ test.in, out, ok, test.out, test.ok)
+ }
+ }
+ }
+}
+
+type atoi32Test struct {
+ in string
+ out int32
+ ok bool
+}
+
+var atoi32tests = []atoi32Test{
+ {"", 0, false},
+ {"0", 0, true},
+ {"-0", 0, true},
+ {"1", 1, true},
+ {"-1", -1, true},
+ {"12345", 12345, true},
+ {"-12345", -12345, true},
+ {"012345", 12345, true},
+ {"-012345", -12345, true},
+ {"12345x", 0, false},
+ {"-12345x", 0, false},
+ {"987654321", 987654321, true},
+ {"-987654321", -987654321, true},
+ {"2147483647", 1<<31 - 1, true},
+ {"-2147483647", -(1<<31 - 1), true},
+ {"2147483648", 0, false},
+ {"-2147483648", -1 << 31, true},
+ {"2147483649", 0, false},
+ {"-2147483649", 0, false},
+}
+
+func TestAtoi32(t *testing.T) {
+ for i := range atoi32tests {
+ test := &atoi32tests[i]
+ out, ok := runtime.Atoi32(test.in)
+ if test.out != out || test.ok != ok {
+ t.Errorf("atoi32(%q) = (%v, %v) want (%v, %v)",
+ test.in, out, ok, test.out, test.ok)
+ }
+ }
+}
diff --git a/libgo/go/runtime/stubs.go b/libgo/go/runtime/stubs.go
index a5f0470155e..c51ccc6d51f 100644
--- a/libgo/go/runtime/stubs.go
+++ b/libgo/go/runtime/stubs.go
@@ -62,14 +62,24 @@ func badsystemstack() {
throw("systemstack called from unexpected goroutine")
}
-// memclr clears n bytes starting at ptr.
+// memclrNoHeapPointers clears n bytes starting at ptr.
+//
+// Usually you should use typedmemclr. memclrNoHeapPointers should be
+// used only when the caller knows that *ptr contains no heap pointers
+// because either:
+//
+// 1. *ptr is initialized memory and its type is pointer-free.
+//
+// 2. *ptr is uninitialized memory (e.g., memory that's being reused
+// for a new allocation) and hence contains only "junk".
+//
// in memclr_*.s
//go:noescape
-func memclr(ptr unsafe.Pointer, n uintptr)
+func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
-//go:linkname reflect_memclr reflect.memclr
-func reflect_memclr(ptr unsafe.Pointer, n uintptr) {
- memclr(ptr, n)
+//go:linkname reflect_memclrNoHeapPointers reflect.memclrNoHeapPointers
+func reflect_memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr) {
+ memclrNoHeapPointers(ptr, n)
}
// memmove copies n bytes from "from" to "to".
@@ -89,7 +99,10 @@ func memcmp(a, b unsafe.Pointer, size uintptr) int32
var hashLoad = loadFactor
// in asm_*.s
-func fastrand1() uint32
+func fastrand() uint32
+
+//go:linkname sync_fastrand sync.fastrand
+func sync_fastrand() uint32 { return fastrand() }
// in asm_*.s
//go:noescape
@@ -98,7 +111,7 @@ func memequal(a, b unsafe.Pointer, size uintptr) bool
// noescape hides a pointer from escape analysis. noescape is
// the identity function but escape analysis doesn't think the
// output depends on the input. noescape is inlined and currently
-// compiles down to a single xor instruction.
+// compiles down to zero instructions.
// USE CAREFULLY!
//go:nosplit
func noescape(p unsafe.Pointer) unsafe.Pointer {
@@ -106,6 +119,7 @@ func noescape(p unsafe.Pointer) unsafe.Pointer {
return unsafe.Pointer(x ^ 0)
}
+//extern mincore
func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32
//go:noescape
@@ -219,6 +233,18 @@ func checkASM() bool {
return true
}
+func eqstring(x, y string) bool {
+ a := stringStructOf(&x)
+ b := stringStructOf(&y)
+ if a.len != b.len {
+ return false
+ }
+ if a.str == b.str {
+ return true
+ }
+ return memequal(a.str, b.str, uintptr(a.len))
+}
+
// For gccgo this is in the C code.
func osyield()
@@ -266,12 +292,31 @@ func setSupportAES(v bool) {
// typedmemmove copies a typed value.
// For gccgo for now.
+//go:linkname typedmemmove runtime.typedmemmove
//go:nosplit
func typedmemmove(typ *_type, dst, src unsafe.Pointer) {
memmove(dst, src, typ.size)
}
// Temporary for gccgo until we port mbarrier.go.
+//go:linkname reflect_typedmemmove reflect.typedmemmove
+func reflect_typedmemmove(typ *_type, dst, src unsafe.Pointer) {
+ typedmemmove(typ, dst, src)
+}
+
+// Temporary for gccgo until we port mbarrier.go.
+//go:nosplit
+func typedmemclr(typ *_type, ptr unsafe.Pointer) {
+ memclrNoHeapPointers(ptr, typ.size)
+}
+
+// Temporary for gccgo until we port mbarrier.go.
+//go:nosplit
+func memclrHasPointers(ptr unsafe.Pointer, n uintptr) {
+ memclrNoHeapPointers(ptr, n)
+}
+
+// Temporary for gccgo until we port mbarrier.go.
//go:linkname typedslicecopy runtime.typedslicecopy
func typedslicecopy(typ *_type, dst, src slice) int {
n := dst.len
@@ -285,6 +330,12 @@ func typedslicecopy(typ *_type, dst, src slice) int {
return n
}
+// Temporary for gccgo until we port mbarrier.go.
+//go:linkname reflect_typedslicecopy reflect.typedslicecopy
+func reflect_typedslicecopy(elemType *_type, dst, src slice) int {
+ return typedslicecopy(elemType, dst, src)
+}
+
// Here for gccgo until we port malloc.go.
const (
_64bit = 1 << (^uintptr(0) >> 63) / 2
@@ -339,7 +390,7 @@ func gopark(func(*g, unsafe.Pointer) bool, unsafe.Pointer, string, byte, int)
func goparkunlock(*mutex, string, byte, int)
// Temporary hack for gccgo until we port the garbage collector.
-func typeBitsBulkBarrier(typ *_type, p, size uintptr) {}
+func typeBitsBulkBarrier(typ *_type, dst, src, size uintptr) {}
// Here for gccgo until we port msize.go.
func roundupsize(uintptr) uintptr
@@ -350,7 +401,7 @@ func GC()
// For gccgo to call from C code.
//go:linkname acquireWorldsema runtime.acquireWorldsema
func acquireWorldsema() {
- semacquire(&worldsema, false)
+ semacquire(&worldsema, 0)
}
// For gccgo to call from C code.
@@ -434,10 +485,10 @@ func setSigactionHandler(*_sigaction, uintptr)
// Retrieve fields from the siginfo_t and ucontext_t pointers passed
// to a signal handler using C, as they are often hidden in a union.
// Returns and, if available, PC where signal occurred.
-func getSiginfo(*_siginfo_t, unsafe.Pointer) (sigaddr uintptr, sigpc uintptr)
+func getSiginfo(*siginfo, unsafe.Pointer) (sigaddr uintptr, sigpc uintptr)
// Implemented in C for gccgo.
-func dumpregs(*_siginfo_t, unsafe.Pointer)
+func dumpregs(*siginfo, unsafe.Pointer)
// Temporary for gccgo until we port proc.go.
//go:linkname getsched runtime.getsched
@@ -565,3 +616,27 @@ func (h *mheap) scavenge(k int32, now, limit uint64) {
func setncpu(n int32) {
ncpu = n
}
+
+// Temporary for gccgo until we port malloc.go.
+var physPageSize uintptr
+
+// Temporary for gccgo until we reliably initialize physPageSize in Go.
+//go:linkname setpagesize runtime.setpagesize
+func setpagesize(s uintptr) {
+ if physPageSize == 0 {
+ physPageSize = s
+ }
+}
+
+// Temporary for gccgo until we port more of proc.go.
+func sigprofNonGoPC(pc uintptr) {
+}
+
+// Temporary for gccgo until we port mgc.go.
+// gcMarkWorkerModeStrings are the strings labels of gcMarkWorkerModes
+// to use in execution traces.
+var gcMarkWorkerModeStrings = [...]string{
+ "GC (dedicated)",
+ "GC (fractional)",
+ "GC (idle)",
+}
diff --git a/libgo/go/runtime/stubs2.go b/libgo/go/runtime/stubs2.go
index d96022674b6..e891fe5ee7b 100644
--- a/libgo/go/runtime/stubs2.go
+++ b/libgo/go/runtime/stubs2.go
@@ -18,7 +18,11 @@ func exit(code int32)
func nanotime() int64
func usleep(usec uint32)
-func munmap(addr unsafe.Pointer, n uintptr)
+//extern mmap
+func mmap(addr unsafe.Pointer, length uintptr, prot, flags, fd int32, offset uintptr) unsafe.Pointer
+
+//extern munmap
+func munmap(addr unsafe.Pointer, n uintptr) int32
//go:noescape
func write(fd uintptr, p unsafe.Pointer, n int32) int32
diff --git a/libgo/go/runtime/testdata/testprog/deadlock.go b/libgo/go/runtime/testdata/testprog/deadlock.go
index c938fcfb569..ca2be579114 100644
--- a/libgo/go/runtime/testdata/testprog/deadlock.go
+++ b/libgo/go/runtime/testdata/testprog/deadlock.go
@@ -32,6 +32,7 @@ func init() {
register("PanicTraceback", PanicTraceback)
register("GoschedInPanic", GoschedInPanic)
register("SyscallInPanic", SyscallInPanic)
+ register("PanicLoop", PanicLoop)
}
func SimpleDeadlock() {
@@ -214,3 +215,13 @@ func pt2() {
}()
panic("hello")
}
+
+type panicError struct{}
+
+func (*panicError) Error() string {
+ panic("double error")
+}
+
+func PanicLoop() {
+ panic(&panicError{})
+}
diff --git a/libgo/go/runtime/testdata/testprog/gc.go b/libgo/go/runtime/testdata/testprog/gc.go
index a0c1f82b56b..744b6108e2b 100644
--- a/libgo/go/runtime/testdata/testprog/gc.go
+++ b/libgo/go/runtime/testdata/testprog/gc.go
@@ -98,11 +98,25 @@ func GCFairness2() {
// If the scheduling rules change, this may not be enough time
// to let all goroutines run, but for now we cycle through
// them rapidly.
+ //
+ // OpenBSD's scheduler makes every usleep() take at least
+ // 20ms, so we need a long time to ensure all goroutines have
+ // run. If they haven't run after 30ms, give it another 1000ms
+ // and check again.
time.Sleep(30 * time.Millisecond)
+ var fail bool
for i := range count {
if atomic.LoadInt64(&count[i]) == 0 {
- fmt.Printf("goroutine %d did not run\n", i)
- return
+ fail = true
+ }
+ }
+ if fail {
+ time.Sleep(1 * time.Second)
+ for i := range count {
+ if atomic.LoadInt64(&count[i]) == 0 {
+ fmt.Printf("goroutine %d did not run\n", i)
+ return
+ }
}
}
fmt.Println("OK")
diff --git a/libgo/go/runtime/testdata/testprog/map.go b/libgo/go/runtime/testdata/testprog/map.go
new file mode 100644
index 00000000000..552428957bc
--- /dev/null
+++ b/libgo/go/runtime/testdata/testprog/map.go
@@ -0,0 +1,77 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "runtime"
+
+func init() {
+ register("concurrentMapWrites", concurrentMapWrites)
+ register("concurrentMapReadWrite", concurrentMapReadWrite)
+ register("concurrentMapIterateWrite", concurrentMapIterateWrite)
+}
+
+func concurrentMapWrites() {
+ m := map[int]int{}
+ c := make(chan struct{})
+ go func() {
+ for i := 0; i < 10000; i++ {
+ m[5] = 0
+ runtime.Gosched()
+ }
+ c <- struct{}{}
+ }()
+ go func() {
+ for i := 0; i < 10000; i++ {
+ m[6] = 0
+ runtime.Gosched()
+ }
+ c <- struct{}{}
+ }()
+ <-c
+ <-c
+}
+
+func concurrentMapReadWrite() {
+ m := map[int]int{}
+ c := make(chan struct{})
+ go func() {
+ for i := 0; i < 10000; i++ {
+ m[5] = 0
+ runtime.Gosched()
+ }
+ c <- struct{}{}
+ }()
+ go func() {
+ for i := 0; i < 10000; i++ {
+ _ = m[6]
+ runtime.Gosched()
+ }
+ c <- struct{}{}
+ }()
+ <-c
+ <-c
+}
+
+func concurrentMapIterateWrite() {
+ m := map[int]int{}
+ c := make(chan struct{})
+ go func() {
+ for i := 0; i < 10000; i++ {
+ m[5] = 0
+ runtime.Gosched()
+ }
+ c <- struct{}{}
+ }()
+ go func() {
+ for i := 0; i < 10000; i++ {
+ for range m {
+ }
+ runtime.Gosched()
+ }
+ c <- struct{}{}
+ }()
+ <-c
+ <-c
+}
diff --git a/libgo/go/runtime/testdata/testprogcgo/pprof.go b/libgo/go/runtime/testdata/testprogcgo/pprof.go
index cb30ec5b250..4460b9304e5 100644
--- a/libgo/go/runtime/testdata/testprogcgo/pprof.go
+++ b/libgo/go/runtime/testdata/testprogcgo/pprof.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The Go Authors. All rights reserved.
+// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/libgo/go/runtime/testdata/testprogcgo/raceprof.go b/libgo/go/runtime/testdata/testprogcgo/raceprof.go
new file mode 100644
index 00000000000..fe624c541fd
--- /dev/null
+++ b/libgo/go/runtime/testdata/testprogcgo/raceprof.go
@@ -0,0 +1,78 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux,amd64
+
+package main
+
+// Test that we can collect a lot of colliding profiling signals from
+// an external C thread. This used to fail when built with the race
+// detector, because a call of the predeclared function copy was
+// turned into a call to runtime.slicecopy, which is not marked nosplit.
+
+/*
+#include <signal.h>
+#include <stdint.h>
+#include <pthread.h>
+#include <sched.h>
+
+struct cgoTracebackArg {
+ uintptr_t context;
+ uintptr_t sigContext;
+ uintptr_t* buf;
+ uintptr_t max;
+};
+
+static int raceprofCount;
+
+// We want a bunch of different profile stacks that collide in the
+// hash table maintained in runtime/cpuprof.go. This code knows the
+// size of the hash table (1 << 10) and knows that the hash function
+// is simply multiplicative.
+void raceprofTraceback(void* parg) {
+ struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg);
+ raceprofCount++;
+ arg->buf[0] = raceprofCount * (1 << 10);
+ arg->buf[1] = 0;
+}
+
+static void* raceprofThread(void* p) {
+ int i;
+
+ for (i = 0; i < 100; i++) {
+ pthread_kill(pthread_self(), SIGPROF);
+ sched_yield();
+ }
+ return 0;
+}
+
+void runRaceprofThread() {
+ pthread_t tid;
+ pthread_create(&tid, 0, raceprofThread, 0);
+ pthread_join(tid, 0);
+}
+*/
+import "C"
+
+import (
+ "bytes"
+ "fmt"
+ "runtime"
+ "runtime/pprof"
+ "unsafe"
+)
+
+func init() {
+ register("CgoRaceprof", CgoRaceprof)
+}
+
+func CgoRaceprof() {
+ runtime.SetCgoTraceback(0, unsafe.Pointer(C.raceprofTraceback), nil, nil)
+
+ var buf bytes.Buffer
+ pprof.StartCPUProfile(&buf)
+
+ C.runRaceprofThread()
+ fmt.Println("OK")
+}
diff --git a/libgo/go/runtime/testdata/testprogcgo/racesig.go b/libgo/go/runtime/testdata/testprogcgo/racesig.go
new file mode 100644
index 00000000000..d0c1c3ce540
--- /dev/null
+++ b/libgo/go/runtime/testdata/testprogcgo/racesig.go
@@ -0,0 +1,102 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux,amd64
+
+package main
+
+// Test that an external C thread that is calling malloc can be hit
+// with SIGCHLD signals. This used to fail when built with the race
+// detector, because in that case the signal handler would indirectly
+// call the C malloc function.
+
+/*
+#include <errno.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sched.h>
+#include <unistd.h>
+
+#define ALLOCERS 100
+#define SIGNALERS 10
+
+static void* signalThread(void* p) {
+ pthread_t* pt = (pthread_t*)(p);
+ int i, j;
+
+ for (i = 0; i < 100; i++) {
+ for (j = 0; j < ALLOCERS; j++) {
+ if (pthread_kill(pt[j], SIGCHLD) < 0) {
+ return NULL;
+ }
+ }
+ usleep(1);
+ }
+ return NULL;
+}
+
+#define CALLS 100
+
+static void* mallocThread(void* p) {
+ int i;
+ void *a[CALLS];
+
+ for (i = 0; i < ALLOCERS; i++) {
+ sched_yield();
+ }
+ for (i = 0; i < CALLS; i++) {
+ a[i] = malloc(i);
+ }
+ for (i = 0; i < CALLS; i++) {
+ free(a[i]);
+ }
+ return NULL;
+}
+
+void runRaceSignalThread() {
+ int i;
+ pthread_t m[ALLOCERS];
+ pthread_t s[SIGNALERS];
+
+ for (i = 0; i < ALLOCERS; i++) {
+ pthread_create(&m[i], NULL, mallocThread, NULL);
+ }
+ for (i = 0; i < SIGNALERS; i++) {
+ pthread_create(&s[i], NULL, signalThread, &m[0]);
+ }
+ for (i = 0; i < SIGNALERS; i++) {
+ pthread_join(s[i], NULL);
+ }
+ for (i = 0; i < ALLOCERS; i++) {
+ pthread_join(m[i], NULL);
+ }
+}
+*/
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "time"
+)
+
+func init() {
+ register("CgoRaceSignal", CgoRaceSignal)
+}
+
+func CgoRaceSignal() {
+ // The failure symptom is that the program hangs because of a
+ // deadlock in malloc, so set an alarm.
+ go func() {
+ time.Sleep(5 * time.Second)
+ fmt.Println("Hung for 5 seconds")
+ os.Exit(1)
+ }()
+
+ C.runRaceSignalThread()
+ fmt.Println("OK")
+}
diff --git a/libgo/go/runtime/testdata/testprogcgo/threadpprof.go b/libgo/go/runtime/testdata/testprogcgo/threadpprof.go
index fdeee6910dd..44afb91d96f 100644
--- a/libgo/go/runtime/testdata/testprogcgo/threadpprof.go
+++ b/libgo/go/runtime/testdata/testprogcgo/threadpprof.go
@@ -1,4 +1,4 @@
-// Copyright 2016 The Go Authors. All rights reserved.
+// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -39,17 +39,6 @@ struct cgoTracebackArg {
uintptr_t max;
};
-static void *pprofThread(void* p) {
- time_t start;
-
- (void)p;
- start = time(NULL);
- while (__sync_add_and_fetch(&cpuHogThreadCount, 0) < 2 && time(NULL) - start < 2) {
- cpuHogThread();
- }
-}
-
-
// pprofCgoThreadTraceback is passed to runtime.SetCgoTraceback.
// For testing purposes it pretends that all CPU hits in C code are in cpuHog.
void pprofCgoThreadTraceback(void* parg) {
@@ -64,6 +53,18 @@ void pprofCgoThreadTraceback(void* parg) {
int getCPUHogThreadCount() {
return __sync_add_and_fetch(&cpuHogThreadCount, 0);
}
+
+static void* cpuHogDriver(void* arg __attribute__ ((unused))) {
+ while (1) {
+ cpuHogThread();
+ }
+ return 0;
+}
+
+void runCPUHogThread() {
+ pthread_t tid;
+ pthread_create(&tid, 0, cpuHogDriver, 0);
+}
*/
import "C"
@@ -79,11 +80,19 @@ import (
func init() {
register("CgoPprofThread", CgoPprofThread)
+ register("CgoPprofThreadNoTraceback", CgoPprofThreadNoTraceback)
}
func CgoPprofThread() {
runtime.SetCgoTraceback(0, unsafe.Pointer(C.pprofCgoThreadTraceback), nil, nil)
+ pprofThread()
+}
+
+func CgoPprofThreadNoTraceback() {
+ pprofThread()
+}
+func pprofThread() {
f, err := ioutil.TempFile("", "prof")
if err != nil {
fmt.Fprintln(os.Stderr, err)
@@ -95,6 +104,8 @@ func CgoPprofThread() {
os.Exit(2)
}
+ C.runCPUHogThread()
+
t0 := time.Now()
for C.getCPUHogThreadCount() < 2 && time.Since(t0) < time.Second {
time.Sleep(100 * time.Millisecond)
diff --git a/libgo/go/runtime/testdata/testprogcgo/threadprof.go b/libgo/go/runtime/testdata/testprogcgo/threadprof.go
index a77479dfad1..2d4c1039fb7 100644
--- a/libgo/go/runtime/testdata/testprogcgo/threadprof.go
+++ b/libgo/go/runtime/testdata/testprogcgo/threadprof.go
@@ -2,7 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// We only build this file with the tag "threadprof", since it starts
+// a thread running a busy loop at constructor time.
+
// +build !plan9,!windows
+// +build threadprof
package main
@@ -21,6 +25,7 @@ static void *thread1(void *p) {
spinlock = 0;
return NULL;
}
+
__attribute__((constructor)) void issue9456() {
pthread_t tid;
pthread_create(&tid, 0, thread1, NULL);
@@ -84,8 +89,8 @@ func CgoExternalThreadSignal() {
out, err := exec.Command(os.Args[0], "CgoExternalThreadSignal", "crash").CombinedOutput()
if err == nil {
- fmt.Println("C signal did not crash as expected\n")
- fmt.Printf("%s\n", out)
+ fmt.Println("C signal did not crash as expected")
+ fmt.Printf("\n%s\n", out)
os.Exit(1)
}
diff --git a/libgo/go/runtime/time.go b/libgo/go/runtime/time.go
index 8df185dc8fd..604ccded895 100644
--- a/libgo/go/runtime/time.go
+++ b/libgo/go/runtime/time.go
@@ -88,12 +88,12 @@ func addtimer(t *timer) {
unlock(&timers.lock)
}
-// Add a timer to the heap and start or kick the timer proc.
-// If the new timer is earlier than any of the others.
+// Add a timer to the heap and start or kick timerproc if the new timer is
+// earlier than any of the others.
// Timers are locked.
func addtimerLocked(t *timer) {
// when must never be negative; otherwise timerproc will overflow
- // during its delta calculation and never expire other runtime·timers.
+ // during its delta calculation and never expire other runtime timers.
if t.when < 0 {
t.when = 1<<63 - 1
}
@@ -150,7 +150,7 @@ func deltimer(t *timer) bool {
// Timerproc runs the time-driven events.
// It sleeps until the next event in the timers heap.
-// If addtimer inserts a new earlier event, addtimer1 wakes timerproc early.
+// If addtimer inserts a new earlier event, it wakes timerproc early.
func timerproc() {
timers.gp = getg()
for {
diff --git a/libgo/go/runtime/trace.go b/libgo/go/runtime/trace.go
index 09a150f6e63..61cfa8e751c 100644
--- a/libgo/go/runtime/trace.go
+++ b/libgo/go/runtime/trace.go
@@ -28,8 +28,8 @@ const (
traceEvProcStop = 6 // stop of P [timestamp]
traceEvGCStart = 7 // GC start [timestamp, seq, stack id]
traceEvGCDone = 8 // GC done [timestamp]
- traceEvGCScanStart = 9 // GC scan start [timestamp]
- traceEvGCScanDone = 10 // GC scan done [timestamp]
+ traceEvGCScanStart = 9 // GC mark termination start [timestamp]
+ traceEvGCScanDone = 10 // GC mark termination done [timestamp]
traceEvGCSweepStart = 11 // GC sweep start [timestamp, stack id]
traceEvGCSweepDone = 12 // GC sweep done [timestamp]
traceEvGoCreate = 13 // goroutine creation [timestamp, new goroutine id, new stack id, stack id]
@@ -60,7 +60,9 @@ const (
traceEvGoStartLocal = 38 // goroutine starts running on the same P as the last event [timestamp, goroutine id]
traceEvGoUnblockLocal = 39 // goroutine is unblocked on the same P as the last event [timestamp, goroutine id, stack]
traceEvGoSysExitLocal = 40 // syscall exit on the same P as the last event [timestamp, goroutine id, real timestamp]
- traceEvCount = 41
+ traceEvGoStartLabel = 41 // goroutine starts running with label [timestamp, goroutine id, seq, label string id]
+ traceEvGoBlockGC = 42 // goroutine blocks on GC assist [timestamp, stack]
+ traceEvCount = 43
)
const (
@@ -112,15 +114,20 @@ var trace struct {
empty traceBufPtr // stack of empty buffers
fullHead traceBufPtr // queue of full buffers
fullTail traceBufPtr
- reader *g // goroutine that called ReadTrace, or nil
+ reader guintptr // goroutine that called ReadTrace, or nil
stackTab traceStackTable // maps stack traces to unique ids
// Dictionary for traceEvString.
- // Currently this is used only for func/file:line info after tracing session,
- // so we assume single-threaded access.
+ //
+ // Currently this is used only at trace setup and for
+ // func/file:line info after tracing session, so we assume
+ // single-threaded access.
strings map[string]uint64
stringSeq uint64
+ // markWorkerLabels maps gcMarkWorkerMode to string ID.
+ markWorkerLabels [len(gcMarkWorkerModeStrings)]uint64
+
bufLock mutex // protects buf
buf traceBufPtr // global trace buffer, used when running without a p
}
@@ -134,6 +141,8 @@ type traceBufHeader struct {
}
// traceBuf is per-P tracing buffer.
+//
+//go:notinheap
type traceBuf struct {
traceBufHeader
arr [64<<10 - unsafe.Sizeof(traceBufHeader{})]byte // underlying buffer for traceBufHeader.buf
@@ -144,6 +153,8 @@ type traceBuf struct {
// allocated from the GC'd heap, so this is safe, and are often
// manipulated in contexts where write barriers are not allowed, so
// this is necessary.
+//
+// TODO: Since traceBuf is now go:notinheap, this isn't necessary.
type traceBufPtr uintptr
func (tp traceBufPtr) ptr() *traceBuf { return (*traceBuf)(unsafe.Pointer(tp)) }
@@ -184,10 +195,21 @@ func StartTrace() error {
// trace.enabled is set afterwards once we have emitted all preliminary events.
_g_ := getg()
_g_.m.startingtrace = true
+
+ // Obtain current stack ID to use in all traceEvGoCreate events below.
+ mp := acquirem()
+ stkBuf := make([]location, traceStackSize)
+ stackID := traceStackID(mp, stkBuf, 2)
+ releasem(mp)
+
for _, gp := range allgs {
status := readgstatus(gp)
if status != _Gdead {
- traceGoCreate(gp, gp.startpc) // also resets gp.traceseq/tracelastp
+ gp.traceseq = 0
+ gp.tracelastp = getg().m.p
+ // +PCQuantum because traceFrameForPC expects return PCs and subtracts PCQuantum.
+ id := trace.stackTab.put([]location{location{pc: gp.startpc + sys.PCQuantum}})
+ traceEvent(traceEvGoCreate, -1, uint64(gp.goid), uint64(id), stackID)
}
if status == _Gwaiting {
// traceEvGoWaiting is implied to have seq=1.
@@ -217,6 +239,18 @@ func StartTrace() error {
_g_.m.startingtrace = false
trace.enabled = true
+ // Register runtime goroutine labels.
+ _, pid, bufp := traceAcquireBuffer()
+ buf := (*bufp).ptr()
+ if buf == nil {
+ buf = traceFlush(0).ptr()
+ (*bufp).set(buf)
+ }
+ for i, label := range gcMarkWorkerModeStrings[:] {
+ trace.markWorkerLabels[i], buf = traceString(buf, label)
+ }
+ traceReleaseBuffer(pid)
+
unlock(&trace.bufLock)
startTheWorld()
@@ -251,10 +285,12 @@ func StopTrace() {
p.tracebuf = 0
}
}
- if trace.buf != 0 && trace.buf.ptr().pos != 0 {
+ if trace.buf != 0 {
buf := trace.buf
trace.buf = 0
- traceFullQueue(buf)
+ if buf.ptr().pos != 0 {
+ traceFullQueue(buf)
+ }
}
for {
@@ -275,7 +311,7 @@ func StopTrace() {
// The world is started but we've set trace.shutdown, so new tracing can't start.
// Wait for the trace reader to flush pending buffers and stop.
- semacquire(&trace.shutdownSema, false)
+ semacquire(&trace.shutdownSema, 0)
if raceenabled {
raceacquire(unsafe.Pointer(&trace.shutdownSema))
}
@@ -296,7 +332,7 @@ func StopTrace() {
if trace.fullHead != 0 || trace.fullTail != 0 {
throw("trace: non-empty full trace buffer")
}
- if trace.reading != 0 || trace.reader != nil {
+ if trace.reading != 0 || trace.reader != 0 {
throw("trace: reading after shutdown")
}
for trace.empty != 0 {
@@ -324,7 +360,7 @@ func ReadTrace() []byte {
lock(&trace.lock)
trace.lockOwner = getg()
- if trace.reader != nil {
+ if trace.reader != 0 {
// More than one goroutine reads trace. This is bad.
// But we rather do not crash the program because of tracing,
// because tracing can be enabled at runtime on prod servers.
@@ -344,11 +380,11 @@ func ReadTrace() []byte {
trace.headerWritten = true
trace.lockOwner = nil
unlock(&trace.lock)
- return []byte("go 1.7 trace\x00\x00\x00\x00")
+ return []byte("go 1.8 trace\x00\x00\x00\x00")
}
// Wait for new data.
if trace.fullHead == 0 && !trace.shutdown {
- trace.reader = getg()
+ trace.reader.set(getg())
goparkunlock(&trace.lock, "trace reader (blocked)", traceEvGoBlock, 2)
lock(&trace.lock)
}
@@ -402,16 +438,16 @@ func ReadTrace() []byte {
// traceReader returns the trace reader that should be woken up, if any.
func traceReader() *g {
- if trace.reader == nil || (trace.fullHead == 0 && !trace.shutdown) {
+ if trace.reader == 0 || (trace.fullHead == 0 && !trace.shutdown) {
return nil
}
lock(&trace.lock)
- if trace.reader == nil || (trace.fullHead == 0 && !trace.shutdown) {
+ if trace.reader == 0 || (trace.fullHead == 0 && !trace.shutdown) {
unlock(&trace.lock)
return nil
}
- gp := trace.reader
- trace.reader = nil
+ gp := trace.reader.ptr()
+ trace.reader.set(nil)
unlock(&trace.lock)
return gp
}
@@ -513,22 +549,7 @@ func traceEvent(ev byte, skip int, args ...uint64) {
if skip == 0 {
buf.varint(0)
} else if skip > 0 {
- _g_ := getg()
- gp := mp.curg
- var nstk int
- if gp == _g_ {
- nstk = callers(skip, buf.stk[:])
- } else if gp != nil {
- // FIXME: get stack trace of different goroutine.
- }
- if nstk > 0 {
- nstk-- // skip runtime.goexit
- }
- if nstk > 0 && gp.goid == 1 {
- nstk-- // skip runtime.main
- }
- id := trace.stackTab.put(buf.stk[:nstk])
- buf.varint(uint64(id))
+ buf.varint(traceStackID(mp, buf.stk[:], skip))
}
evSize := buf.pos - startPos
if evSize > maxSize {
@@ -541,6 +562,25 @@ func traceEvent(ev byte, skip int, args ...uint64) {
traceReleaseBuffer(pid)
}
+func traceStackID(mp *m, buf []location, skip int) uint64 {
+ _g_ := getg()
+ gp := mp.curg
+ var nstk int
+ if gp == _g_ {
+ nstk = callers(skip+1, buf[:])
+ } else if gp != nil {
+ // FIXME: get stack trace of different goroutine.
+ }
+ if nstk > 0 {
+ nstk-- // skip runtime.goexit
+ }
+ if nstk > 0 && gp.goid == 1 {
+ nstk-- // skip runtime.main
+ }
+ id := trace.stackTab.put(buf[:nstk])
+ return uint64(id)
+}
+
// traceAcquireBuffer returns trace buffer to use and, if necessary, locks it.
func traceAcquireBuffer() (mp *m, pid int32, bufp *traceBufPtr) {
mp = acquirem()
@@ -799,11 +839,14 @@ type traceAlloc struct {
// traceAllocBlock is allocated from non-GC'd memory, so it must not
// contain heap pointers. Writes to pointers to traceAllocBlocks do
// not need write barriers.
+//
+//go:notinheap
type traceAllocBlock struct {
next traceAllocBlockPtr
data [64<<10 - sys.PtrSize]byte
}
+// TODO: Since traceAllocBlock is now go:notinheap, this isn't necessary.
type traceAllocBlockPtr uintptr
func (p traceAllocBlockPtr) ptr() *traceAllocBlock { return (*traceAllocBlock)(unsafe.Pointer(p)) }
@@ -898,7 +941,9 @@ func traceGoStart() {
_g_ := getg().m.curg
_p_ := _g_.m.p
_g_.traceseq++
- if _g_.tracelastp == _p_ {
+ if _g_ == _p_.ptr().gcBgMarkWorker.ptr() {
+ traceEvent(traceEvGoStartLabel, -1, uint64(_g_.goid), _g_.traceseq, trace.markWorkerLabels[_p_.ptr().gcMarkWorkerMode])
+ } else if _g_.tracelastp == _p_ {
traceEvent(traceEvGoStartLocal, -1, uint64(_g_.goid))
} else {
_g_.tracelastp = _p_
@@ -979,5 +1024,10 @@ func traceHeapAlloc() {
}
func traceNextGC() {
- traceEvent(traceEvNextGC, -1, memstats.next_gc)
+ if memstats.next_gc == ^uint64(0) {
+ // Heap-based triggering is disabled.
+ traceEvent(traceEvNextGC, -1, 0)
+ } else {
+ traceEvent(traceEvNextGC, -1, memstats.next_gc)
+ }
}
diff --git a/libgo/go/runtime/trace/trace.go b/libgo/go/runtime/trace/trace.go
new file mode 100644
index 00000000000..7cbb8a6e82c
--- /dev/null
+++ b/libgo/go/runtime/trace/trace.go
@@ -0,0 +1,42 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Go execution tracer.
+// The tracer captures a wide range of execution events like goroutine
+// creation/blocking/unblocking, syscall enter/exit/block, GC-related events,
+// changes of heap size, processor start/stop, etc and writes them to an io.Writer
+// in a compact form. A precise nanosecond-precision timestamp and a stack
+// trace is captured for most events. A trace can be analyzed later with
+// 'go tool trace' command.
+package trace
+
+import (
+ "io"
+ "runtime"
+)
+
+// Start enables tracing for the current program.
+// While tracing, the trace will be buffered and written to w.
+// Start returns an error if tracing is already enabled.
+func Start(w io.Writer) error {
+ if err := runtime.StartTrace(); err != nil {
+ return err
+ }
+ go func() {
+ for {
+ data := runtime.ReadTrace()
+ if data == nil {
+ break
+ }
+ w.Write(data)
+ }
+ }()
+ return nil
+}
+
+// Stop stops the current tracing, if any.
+// Stop only returns after all the writes for the trace have completed.
+func Stop() {
+ runtime.StopTrace()
+}
diff --git a/libgo/go/runtime/trace/trace_stack_test.go b/libgo/go/runtime/trace/trace_stack_test.go
new file mode 100644
index 00000000000..c37b33de862
--- /dev/null
+++ b/libgo/go/runtime/trace/trace_stack_test.go
@@ -0,0 +1,282 @@
+// 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 trace_test
+
+import (
+ "bytes"
+ "internal/testenv"
+ "internal/trace"
+ "net"
+ "os"
+ "runtime"
+ . "runtime/trace"
+ "sync"
+ "testing"
+ "time"
+)
+
+// TestTraceSymbolize tests symbolization and that events has proper stacks.
+// In particular that we strip bottom uninteresting frames like goexit,
+// top uninteresting frames (runtime guts).
+func TestTraceSymbolize(t *testing.T) {
+ testenv.MustHaveGoBuild(t)
+
+ buf := new(bytes.Buffer)
+ if err := Start(buf); err != nil {
+ t.Fatalf("failed to start tracing: %v", err)
+ }
+ defer Stop() // in case of early return
+
+ // Now we will do a bunch of things for which we verify stacks later.
+ // It is impossible to ensure that a goroutine has actually blocked
+ // on a channel, in a select or otherwise. So we kick off goroutines
+ // that need to block first in the hope that while we are executing
+ // the rest of the test, they will block.
+ go func() {
+ select {}
+ }()
+ go func() {
+ var c chan int
+ c <- 0
+ }()
+ go func() {
+ var c chan int
+ <-c
+ }()
+ done1 := make(chan bool)
+ go func() {
+ <-done1
+ }()
+ done2 := make(chan bool)
+ go func() {
+ done2 <- true
+ }()
+ c1 := make(chan int)
+ c2 := make(chan int)
+ go func() {
+ select {
+ case <-c1:
+ case <-c2:
+ }
+ }()
+ var mu sync.Mutex
+ mu.Lock()
+ go func() {
+ mu.Lock()
+ mu.Unlock()
+ }()
+ var wg sync.WaitGroup
+ wg.Add(1)
+ go func() {
+ wg.Wait()
+ }()
+ cv := sync.NewCond(&sync.Mutex{})
+ go func() {
+ cv.L.Lock()
+ cv.Wait()
+ cv.L.Unlock()
+ }()
+ ln, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("failed to listen: %v", err)
+ }
+ go func() {
+ c, err := ln.Accept()
+ if err != nil {
+ t.Errorf("failed to accept: %v", err)
+ return
+ }
+ c.Close()
+ }()
+ rp, wp, err := os.Pipe()
+ if err != nil {
+ t.Fatalf("failed to create a pipe: %v", err)
+ }
+ defer rp.Close()
+ defer wp.Close()
+ pipeReadDone := make(chan bool)
+ go func() {
+ var data [1]byte
+ rp.Read(data[:])
+ pipeReadDone <- true
+ }()
+
+ time.Sleep(100 * time.Millisecond)
+ runtime.GC()
+ runtime.Gosched()
+ time.Sleep(100 * time.Millisecond) // the last chance for the goroutines above to block
+ done1 <- true
+ <-done2
+ select {
+ case c1 <- 0:
+ case c2 <- 0:
+ }
+ mu.Unlock()
+ wg.Done()
+ cv.Signal()
+ c, err := net.Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Fatalf("failed to dial: %v", err)
+ }
+ c.Close()
+ var data [1]byte
+ wp.Write(data[:])
+ <-pipeReadDone
+
+ Stop()
+ events, _ := parseTrace(t, buf)
+
+ // Now check that the stacks are correct.
+ type frame struct {
+ Fn string
+ Line int
+ }
+ type eventDesc struct {
+ Type byte
+ Stk []frame
+ }
+ want := []eventDesc{
+ {trace.EvGCStart, []frame{
+ {"runtime.GC", 0},
+ {"runtime/trace_test.TestTraceSymbolize", 107},
+ {"testing.tRunner", 0},
+ }},
+ {trace.EvGoStart, []frame{
+ {"runtime/trace_test.TestTraceSymbolize.func1", 37},
+ }},
+ {trace.EvGoSched, []frame{
+ {"runtime/trace_test.TestTraceSymbolize", 108},
+ {"testing.tRunner", 0},
+ }},
+ {trace.EvGoCreate, []frame{
+ {"runtime/trace_test.TestTraceSymbolize", 39},
+ {"testing.tRunner", 0},
+ }},
+ {trace.EvGoStop, []frame{
+ {"runtime.block", 0},
+ {"runtime/trace_test.TestTraceSymbolize.func1", 38},
+ }},
+ {trace.EvGoStop, []frame{
+ {"runtime.chansend1", 0},
+ {"runtime/trace_test.TestTraceSymbolize.func2", 42},
+ }},
+ {trace.EvGoStop, []frame{
+ {"runtime.chanrecv1", 0},
+ {"runtime/trace_test.TestTraceSymbolize.func3", 46},
+ }},
+ {trace.EvGoBlockRecv, []frame{
+ {"runtime.chanrecv1", 0},
+ {"runtime/trace_test.TestTraceSymbolize.func4", 50},
+ }},
+ {trace.EvGoUnblock, []frame{
+ {"runtime.chansend1", 0},
+ {"runtime/trace_test.TestTraceSymbolize", 110},
+ {"testing.tRunner", 0},
+ }},
+ {trace.EvGoBlockSend, []frame{
+ {"runtime.chansend1", 0},
+ {"runtime/trace_test.TestTraceSymbolize.func5", 54},
+ }},
+ {trace.EvGoUnblock, []frame{
+ {"runtime.chanrecv1", 0},
+ {"runtime/trace_test.TestTraceSymbolize", 111},
+ {"testing.tRunner", 0},
+ }},
+ {trace.EvGoBlockSelect, []frame{
+ {"runtime.selectgo", 0},
+ {"runtime/trace_test.TestTraceSymbolize.func6", 59},
+ }},
+ {trace.EvGoUnblock, []frame{
+ {"runtime.selectgo", 0},
+ {"runtime/trace_test.TestTraceSymbolize", 112},
+ {"testing.tRunner", 0},
+ }},
+ {trace.EvGoBlockSync, []frame{
+ {"sync.(*Mutex).Lock", 0},
+ {"runtime/trace_test.TestTraceSymbolize.func7", 67},
+ }},
+ {trace.EvGoUnblock, []frame{
+ {"sync.(*Mutex).Unlock", 0},
+ {"runtime/trace_test.TestTraceSymbolize", 116},
+ {"testing.tRunner", 0},
+ }},
+ {trace.EvGoBlockSync, []frame{
+ {"sync.(*WaitGroup).Wait", 0},
+ {"runtime/trace_test.TestTraceSymbolize.func8", 73},
+ }},
+ {trace.EvGoUnblock, []frame{
+ {"sync.(*WaitGroup).Add", 0},
+ {"sync.(*WaitGroup).Done", 0},
+ {"runtime/trace_test.TestTraceSymbolize", 117},
+ {"testing.tRunner", 0},
+ }},
+ {trace.EvGoBlockCond, []frame{
+ {"sync.(*Cond).Wait", 0},
+ {"runtime/trace_test.TestTraceSymbolize.func9", 78},
+ }},
+ {trace.EvGoUnblock, []frame{
+ {"sync.(*Cond).Signal", 0},
+ {"runtime/trace_test.TestTraceSymbolize", 118},
+ {"testing.tRunner", 0},
+ }},
+ {trace.EvGoSleep, []frame{
+ {"time.Sleep", 0},
+ {"runtime/trace_test.TestTraceSymbolize", 109},
+ {"testing.tRunner", 0},
+ }},
+ }
+ // Stacks for the following events are OS-dependent due to OS-specific code in net package.
+ if runtime.GOOS != "windows" && runtime.GOOS != "plan9" {
+ want = append(want, []eventDesc{
+ {trace.EvGoBlockNet, []frame{
+ {"net.(*netFD).accept", 0},
+ {"net.(*TCPListener).accept", 0},
+ {"net.(*TCPListener).Accept", 0},
+ {"runtime/trace_test.TestTraceSymbolize.func10", 86},
+ }},
+ {trace.EvGoSysCall, []frame{
+ {"syscall.read", 0},
+ {"syscall.Read", 0},
+ {"os.(*File).read", 0},
+ {"os.(*File).Read", 0},
+ {"runtime/trace_test.TestTraceSymbolize.func11", 102},
+ }},
+ }...)
+ }
+ matched := make([]bool, len(want))
+ for _, ev := range events {
+ wantLoop:
+ for i, w := range want {
+ if matched[i] || w.Type != ev.Type || len(w.Stk) != len(ev.Stk) {
+ continue
+ }
+
+ for fi, f := range ev.Stk {
+ wf := w.Stk[fi]
+ if wf.Fn != f.Fn || wf.Line != 0 && wf.Line != f.Line {
+ continue wantLoop
+ }
+ }
+ matched[i] = true
+ }
+ }
+ for i, m := range matched {
+ if m {
+ continue
+ }
+ w := want[i]
+ t.Errorf("did not match event %v at %v:%v", trace.EventDescriptions[w.Type].Name, w.Stk[0].Fn, w.Stk[0].Line)
+ t.Errorf("seen the following events of this type:")
+ for _, ev := range events {
+ if ev.Type != w.Type {
+ continue
+ }
+ for _, f := range ev.Stk {
+ t.Logf(" %v:%v", f.Fn, f.Line)
+ }
+ t.Logf("---")
+ }
+ }
+}
diff --git a/libgo/go/runtime/trace/trace_test.go b/libgo/go/runtime/trace/trace_test.go
new file mode 100644
index 00000000000..c5f64fcf4cf
--- /dev/null
+++ b/libgo/go/runtime/trace/trace_test.go
@@ -0,0 +1,489 @@
+// 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 trace_test
+
+import (
+ "bytes"
+ "flag"
+ "internal/trace"
+ "io"
+ "io/ioutil"
+ "net"
+ "os"
+ "runtime"
+ . "runtime/trace"
+ "sync"
+ "testing"
+ "time"
+)
+
+var (
+ saveTraces = flag.Bool("savetraces", false, "save traces collected by tests")
+)
+
+func TestTraceStartStop(t *testing.T) {
+ buf := new(bytes.Buffer)
+ if err := Start(buf); err != nil {
+ t.Fatalf("failed to start tracing: %v", err)
+ }
+ Stop()
+ size := buf.Len()
+ if size == 0 {
+ t.Fatalf("trace is empty")
+ }
+ time.Sleep(100 * time.Millisecond)
+ if size != buf.Len() {
+ t.Fatalf("trace writes after stop: %v -> %v", size, buf.Len())
+ }
+ saveTrace(t, buf, "TestTraceStartStop")
+}
+
+func TestTraceDoubleStart(t *testing.T) {
+ Stop()
+ buf := new(bytes.Buffer)
+ if err := Start(buf); err != nil {
+ t.Fatalf("failed to start tracing: %v", err)
+ }
+ if err := Start(buf); err == nil {
+ t.Fatalf("succeed to start tracing second time")
+ }
+ Stop()
+ Stop()
+}
+
+func TestTrace(t *testing.T) {
+ buf := new(bytes.Buffer)
+ if err := Start(buf); err != nil {
+ t.Fatalf("failed to start tracing: %v", err)
+ }
+ Stop()
+ saveTrace(t, buf, "TestTrace")
+ _, err := trace.Parse(buf, "")
+ if err == trace.ErrTimeOrder {
+ t.Skipf("skipping trace: %v", err)
+ }
+ if err != nil {
+ t.Fatalf("failed to parse trace: %v", err)
+ }
+}
+
+func parseTrace(t *testing.T, r io.Reader) ([]*trace.Event, map[uint64]*trace.GDesc) {
+ events, err := trace.Parse(r, "")
+ if err == trace.ErrTimeOrder {
+ t.Skipf("skipping trace: %v", err)
+ }
+ if err != nil {
+ t.Fatalf("failed to parse trace: %v", err)
+ }
+ gs := trace.GoroutineStats(events)
+ for goid := range gs {
+ // We don't do any particular checks on the result at the moment.
+ // But still check that RelatedGoroutines does not crash, hang, etc.
+ _ = trace.RelatedGoroutines(events, goid)
+ }
+ return events, gs
+}
+
+func testBrokenTimestamps(t *testing.T, data []byte) {
+ // On some processors cputicks (used to generate trace timestamps)
+ // produce non-monotonic timestamps. It is important that the parser
+ // distinguishes logically inconsistent traces (e.g. missing, excessive
+ // or misordered events) from broken timestamps. The former is a bug
+ // in tracer, the latter is a machine issue.
+ // So now that we have a consistent trace, test that (1) parser does
+ // not return a logical error in case of broken timestamps
+ // and (2) broken timestamps are eventually detected and reported.
+ trace.BreakTimestampsForTesting = true
+ defer func() {
+ trace.BreakTimestampsForTesting = false
+ }()
+ for i := 0; i < 1e4; i++ {
+ _, err := trace.Parse(bytes.NewReader(data), "")
+ if err == trace.ErrTimeOrder {
+ return
+ }
+ if err != nil {
+ t.Fatalf("failed to parse trace: %v", err)
+ }
+ }
+}
+
+func TestTraceStress(t *testing.T) {
+ var wg sync.WaitGroup
+ done := make(chan bool)
+
+ // Create a goroutine blocked before tracing.
+ wg.Add(1)
+ go func() {
+ <-done
+ wg.Done()
+ }()
+
+ // Create a goroutine blocked in syscall before tracing.
+ rp, wp, err := os.Pipe()
+ if err != nil {
+ t.Fatalf("failed to create pipe: %v", err)
+ }
+ defer func() {
+ rp.Close()
+ wp.Close()
+ }()
+ wg.Add(1)
+ go func() {
+ var tmp [1]byte
+ rp.Read(tmp[:])
+ <-done
+ wg.Done()
+ }()
+ time.Sleep(time.Millisecond) // give the goroutine above time to block
+
+ buf := new(bytes.Buffer)
+ if err := Start(buf); err != nil {
+ t.Fatalf("failed to start tracing: %v", err)
+ }
+
+ procs := runtime.GOMAXPROCS(10)
+ time.Sleep(50 * time.Millisecond) // test proc stop/start events
+
+ go func() {
+ runtime.LockOSThread()
+ for {
+ select {
+ case <-done:
+ return
+ default:
+ runtime.Gosched()
+ }
+ }
+ }()
+
+ runtime.GC()
+ // Trigger GC from malloc.
+ n := int(1e3)
+ if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" {
+ // Reduce allocation to avoid running out of
+ // memory on the builder - see issue/12032.
+ n = 512
+ }
+ for i := 0; i < n; i++ {
+ _ = make([]byte, 1<<20)
+ }
+
+ // Create a bunch of busy goroutines to load all Ps.
+ for p := 0; p < 10; p++ {
+ wg.Add(1)
+ go func() {
+ // Do something useful.
+ tmp := make([]byte, 1<<16)
+ for i := range tmp {
+ tmp[i]++
+ }
+ _ = tmp
+ <-done
+ wg.Done()
+ }()
+ }
+
+ // Block in syscall.
+ wg.Add(1)
+ go func() {
+ var tmp [1]byte
+ rp.Read(tmp[:])
+ <-done
+ wg.Done()
+ }()
+
+ // Test timers.
+ timerDone := make(chan bool)
+ go func() {
+ time.Sleep(time.Millisecond)
+ timerDone <- true
+ }()
+ <-timerDone
+
+ // A bit of network.
+ ln, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Fatalf("listen failed: %v", err)
+ }
+ defer ln.Close()
+ go func() {
+ c, err := ln.Accept()
+ if err != nil {
+ return
+ }
+ time.Sleep(time.Millisecond)
+ var buf [1]byte
+ c.Write(buf[:])
+ c.Close()
+ }()
+ c, err := net.Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Fatalf("dial failed: %v", err)
+ }
+ var tmp [1]byte
+ c.Read(tmp[:])
+ c.Close()
+
+ go func() {
+ runtime.Gosched()
+ select {}
+ }()
+
+ // Unblock helper goroutines and wait them to finish.
+ wp.Write(tmp[:])
+ wp.Write(tmp[:])
+ close(done)
+ wg.Wait()
+
+ runtime.GOMAXPROCS(procs)
+
+ Stop()
+ saveTrace(t, buf, "TestTraceStress")
+ trace := buf.Bytes()
+ parseTrace(t, buf)
+ testBrokenTimestamps(t, trace)
+}
+
+// Do a bunch of various stuff (timers, GC, network, etc) in a separate goroutine.
+// And concurrently with all that start/stop trace 3 times.
+func TestTraceStressStartStop(t *testing.T) {
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8))
+ outerDone := make(chan bool)
+
+ go func() {
+ defer func() {
+ outerDone <- true
+ }()
+
+ var wg sync.WaitGroup
+ done := make(chan bool)
+
+ wg.Add(1)
+ go func() {
+ <-done
+ wg.Done()
+ }()
+
+ rp, wp, err := os.Pipe()
+ if err != nil {
+ t.Errorf("failed to create pipe: %v", err)
+ return
+ }
+ defer func() {
+ rp.Close()
+ wp.Close()
+ }()
+ wg.Add(1)
+ go func() {
+ var tmp [1]byte
+ rp.Read(tmp[:])
+ <-done
+ wg.Done()
+ }()
+ time.Sleep(time.Millisecond)
+
+ go func() {
+ runtime.LockOSThread()
+ for {
+ select {
+ case <-done:
+ return
+ default:
+ runtime.Gosched()
+ }
+ }
+ }()
+
+ runtime.GC()
+ // Trigger GC from malloc.
+ n := int(1e3)
+ if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" {
+ // Reduce allocation to avoid running out of
+ // memory on the builder - see issue/12032.
+ n = 512
+ }
+ for i := 0; i < n; i++ {
+ _ = make([]byte, 1<<20)
+ }
+
+ // Create a bunch of busy goroutines to load all Ps.
+ for p := 0; p < 10; p++ {
+ wg.Add(1)
+ go func() {
+ // Do something useful.
+ tmp := make([]byte, 1<<16)
+ for i := range tmp {
+ tmp[i]++
+ }
+ _ = tmp
+ <-done
+ wg.Done()
+ }()
+ }
+
+ // Block in syscall.
+ wg.Add(1)
+ go func() {
+ var tmp [1]byte
+ rp.Read(tmp[:])
+ <-done
+ wg.Done()
+ }()
+
+ runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
+
+ // Test timers.
+ timerDone := make(chan bool)
+ go func() {
+ time.Sleep(time.Millisecond)
+ timerDone <- true
+ }()
+ <-timerDone
+
+ // A bit of network.
+ ln, err := net.Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ t.Errorf("listen failed: %v", err)
+ return
+ }
+ defer ln.Close()
+ go func() {
+ c, err := ln.Accept()
+ if err != nil {
+ return
+ }
+ time.Sleep(time.Millisecond)
+ var buf [1]byte
+ c.Write(buf[:])
+ c.Close()
+ }()
+ c, err := net.Dial("tcp", ln.Addr().String())
+ if err != nil {
+ t.Errorf("dial failed: %v", err)
+ return
+ }
+ var tmp [1]byte
+ c.Read(tmp[:])
+ c.Close()
+
+ go func() {
+ runtime.Gosched()
+ select {}
+ }()
+
+ // Unblock helper goroutines and wait them to finish.
+ wp.Write(tmp[:])
+ wp.Write(tmp[:])
+ close(done)
+ wg.Wait()
+ }()
+
+ for i := 0; i < 3; i++ {
+ buf := new(bytes.Buffer)
+ if err := Start(buf); err != nil {
+ t.Fatalf("failed to start tracing: %v", err)
+ }
+ time.Sleep(time.Millisecond)
+ Stop()
+ saveTrace(t, buf, "TestTraceStressStartStop")
+ trace := buf.Bytes()
+ parseTrace(t, buf)
+ testBrokenTimestamps(t, trace)
+ }
+ <-outerDone
+}
+
+func TestTraceFutileWakeup(t *testing.T) {
+ buf := new(bytes.Buffer)
+ if err := Start(buf); err != nil {
+ t.Fatalf("failed to start tracing: %v", err)
+ }
+
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8))
+ c0 := make(chan int, 1)
+ c1 := make(chan int, 1)
+ c2 := make(chan int, 1)
+ const procs = 2
+ var done sync.WaitGroup
+ done.Add(4 * procs)
+ for p := 0; p < procs; p++ {
+ const iters = 1e3
+ go func() {
+ for i := 0; i < iters; i++ {
+ runtime.Gosched()
+ c0 <- 0
+ }
+ done.Done()
+ }()
+ go func() {
+ for i := 0; i < iters; i++ {
+ runtime.Gosched()
+ <-c0
+ }
+ done.Done()
+ }()
+ go func() {
+ for i := 0; i < iters; i++ {
+ runtime.Gosched()
+ select {
+ case c1 <- 0:
+ case c2 <- 0:
+ }
+ }
+ done.Done()
+ }()
+ go func() {
+ for i := 0; i < iters; i++ {
+ runtime.Gosched()
+ select {
+ case <-c1:
+ case <-c2:
+ }
+ }
+ done.Done()
+ }()
+ }
+ done.Wait()
+
+ Stop()
+ saveTrace(t, buf, "TestTraceFutileWakeup")
+ events, _ := parseTrace(t, buf)
+ // Check that (1) trace does not contain EvFutileWakeup events and
+ // (2) there are no consecutive EvGoBlock/EvGCStart/EvGoBlock events
+ // (we call runtime.Gosched between all operations, so these would be futile wakeups).
+ gs := make(map[uint64]int)
+ for _, ev := range events {
+ switch ev.Type {
+ case trace.EvFutileWakeup:
+ t.Fatalf("found EvFutileWakeup event")
+ case trace.EvGoBlockSend, trace.EvGoBlockRecv, trace.EvGoBlockSelect:
+ if gs[ev.G] == 2 {
+ t.Fatalf("goroutine %v blocked on %v at %v right after start",
+ ev.G, trace.EventDescriptions[ev.Type].Name, ev.Ts)
+ }
+ if gs[ev.G] == 1 {
+ t.Fatalf("goroutine %v blocked on %v at %v while blocked",
+ ev.G, trace.EventDescriptions[ev.Type].Name, ev.Ts)
+ }
+ gs[ev.G] = 1
+ case trace.EvGoStart:
+ if gs[ev.G] == 1 {
+ gs[ev.G] = 2
+ }
+ default:
+ delete(gs, ev.G)
+ }
+ }
+}
+
+func saveTrace(t *testing.T, buf *bytes.Buffer, name string) {
+ if !*saveTraces {
+ return
+ }
+ if err := ioutil.WriteFile(name+".trace", buf.Bytes(), 0600); err != nil {
+ t.Errorf("failed to write trace file: %s", err)
+ }
+}
diff --git a/libgo/go/runtime/unaligned2.go b/libgo/go/runtime/unaligned2.go
index e52d6ce4c00..b8aefb95223 100644
--- a/libgo/go/runtime/unaligned2.go
+++ b/libgo/go/runtime/unaligned2.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 arm mips64 mips64le armbe m68k mipso32 mipsn32 mips mipsle sparc alpha ia64 mipso64 mipsn64 mips64p32 mips64p32le sparc64
+// +build arm mips mipsle mips64 mips64le armbe m68k mipso32 mipsn32 sparc alpha ia64 mipso64 mipsn64 mips64p32 mips64p32le sparc64
package runtime
diff --git a/libgo/go/runtime/utf8.go b/libgo/go/runtime/utf8.go
new file mode 100644
index 00000000000..e8454516723
--- /dev/null
+++ b/libgo/go/runtime/utf8.go
@@ -0,0 +1,130 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import _ "unsafe" // For go:linkname.
+
+// For gccgo, use go:linkname to rename compiler-called functions to
+// themselves, so that the compiler will export them.
+//
+//go:linkname decoderune runtime.decoderune
+
+// Numbers fundamental to the encoding.
+const (
+ runeError = '\uFFFD' // the "error" Rune or "Unicode replacement character"
+ runeSelf = 0x80 // characters below Runeself are represented as themselves in a single byte.
+ maxRune = '\U0010FFFF' // Maximum valid Unicode code point.
+)
+
+// Code points in the surrogate range are not valid for UTF-8.
+const (
+ surrogateMin = 0xD800
+ surrogateMax = 0xDFFF
+)
+
+const (
+ t1 = 0x00 // 0000 0000
+ tx = 0x80 // 1000 0000
+ t2 = 0xC0 // 1100 0000
+ t3 = 0xE0 // 1110 0000
+ t4 = 0xF0 // 1111 0000
+ t5 = 0xF8 // 1111 1000
+
+ maskx = 0x3F // 0011 1111
+ mask2 = 0x1F // 0001 1111
+ mask3 = 0x0F // 0000 1111
+ mask4 = 0x07 // 0000 0111
+
+ rune1Max = 1<<7 - 1
+ rune2Max = 1<<11 - 1
+ rune3Max = 1<<16 - 1
+
+ // The default lowest and highest continuation byte.
+ locb = 0x80 // 1000 0000
+ hicb = 0xBF // 1011 1111
+)
+
+// decoderune returns the non-ASCII rune at the start of
+// s[k:] and the index after the rune in s.
+//
+// decoderune assumes that caller has checked that
+// the to be decoded rune is a non-ASCII rune.
+//
+// If the string appears to be incomplete or decoding problems
+// are encountered (runeerror, k + 1) is returned to ensure
+// progress when decoderune is used to iterate over a string.
+func decoderune(s string, k int) (r rune, pos int) {
+ pos = k
+
+ if k >= len(s) {
+ return runeError, k + 1
+ }
+
+ s = s[k:]
+
+ switch {
+ case t2 <= s[0] && s[0] < t3:
+ // 0080-07FF two byte sequence
+ if len(s) > 1 && (locb <= s[1] && s[1] <= hicb) {
+ r = rune(s[0]&mask2)<<6 | rune(s[1]&maskx)
+ pos += 2
+ if rune1Max < r {
+ return
+ }
+ }
+ case t3 <= s[0] && s[0] < t4:
+ // 0800-FFFF three byte sequence
+ if len(s) > 2 && (locb <= s[1] && s[1] <= hicb) && (locb <= s[2] && s[2] <= hicb) {
+ r = rune(s[0]&mask3)<<12 | rune(s[1]&maskx)<<6 | rune(s[2]&maskx)
+ pos += 3
+ if rune2Max < r && !(surrogateMin <= r && r <= surrogateMax) {
+ return
+ }
+ }
+ case t4 <= s[0] && s[0] < t5:
+ // 10000-1FFFFF four byte sequence
+ if len(s) > 3 && (locb <= s[1] && s[1] <= hicb) && (locb <= s[2] && s[2] <= hicb) && (locb <= s[3] && s[3] <= hicb) {
+ r = rune(s[0]&mask4)<<18 | rune(s[1]&maskx)<<12 | rune(s[2]&maskx)<<6 | rune(s[3]&maskx)
+ pos += 4
+ if rune3Max < r && r <= maxRune {
+ return
+ }
+ }
+ }
+
+ return runeError, k + 1
+}
+
+// encoderune writes into p (which must be large enough) the UTF-8 encoding of the rune.
+// It returns the number of bytes written.
+func encoderune(p []byte, r rune) int {
+ // Negative values are erroneous. Making it unsigned addresses the problem.
+ switch i := uint32(r); {
+ case i <= rune1Max:
+ p[0] = byte(r)
+ return 1
+ case i <= rune2Max:
+ _ = p[1] // eliminate bounds checks
+ p[0] = t2 | byte(r>>6)
+ p[1] = tx | byte(r)&maskx
+ return 2
+ case i > maxRune, surrogateMin <= i && i <= surrogateMax:
+ r = runeError
+ fallthrough
+ case i <= rune3Max:
+ _ = p[2] // eliminate bounds checks
+ p[0] = t3 | byte(r>>12)
+ p[1] = tx | byte(r>>6)&maskx
+ p[2] = tx | byte(r)&maskx
+ return 3
+ default:
+ _ = p[3] // eliminate bounds checks
+ p[0] = t4 | byte(r>>18)
+ p[1] = tx | byte(r>>12)&maskx
+ p[2] = tx | byte(r>>6)&maskx
+ p[3] = tx | byte(r)&maskx
+ return 4
+ }
+}
diff --git a/libgo/go/runtime/vdso_none.go b/libgo/go/runtime/vdso_none.go
index efae23f6eeb..fc2124040fd 100644
--- a/libgo/go/runtime/vdso_none.go
+++ b/libgo/go/runtime/vdso_none.go
@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.
// +build !linux
+// +build !darwin
package runtime
diff --git a/libgo/go/runtime/write_err_android.go b/libgo/go/runtime/write_err_android.go
index 4411a147554..748dec644c6 100644
--- a/libgo/go/runtime/write_err_android.go
+++ b/libgo/go/runtime/write_err_android.go
@@ -75,7 +75,9 @@ func writeErr(b []byte) {
if v == '\n' || writePos == len(dst)-1 {
dst[writePos] = 0
write(writeFD, unsafe.Pointer(&writeBuf[0]), int32(hlen+writePos))
- memclrBytes(dst)
+ for i := range dst {
+ dst[i] = 0
+ }
writePos = 0
}
}
diff --git a/libgo/go/sort/example_search_test.go b/libgo/go/sort/example_search_test.go
new file mode 100644
index 00000000000..6928f0f092d
--- /dev/null
+++ b/libgo/go/sort/example_search_test.go
@@ -0,0 +1,42 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sort_test
+
+import (
+ "fmt"
+ "sort"
+)
+
+// This example demonstrates searching a list sorted in ascending order.
+func ExampleSearch() {
+ a := []int{1, 3, 6, 10, 15, 21, 28, 36, 45, 55}
+ x := 6
+
+ i := sort.Search(len(a), func(i int) bool { return a[i] >= x })
+ if i < len(a) && a[i] == x {
+ fmt.Printf("found %d at index %d in %v\n", x, i, a)
+ } else {
+ fmt.Printf("%d not found in %v\n", x, a)
+ }
+ // Output:
+ // found 6 at index 2 in [1 3 6 10 15 21 28 36 45 55]
+}
+
+// This example demonstrates searching a list sorted in descending order.
+// The approach is the same as searching a list in ascending order,
+// but with the condition inverted.
+func ExampleSearch_descendingOrder() {
+ a := []int{55, 45, 36, 28, 21, 15, 10, 6, 3, 1}
+ x := 6
+
+ i := sort.Search(len(a), func(i int) bool { return a[i] <= x })
+ if i < len(a) && a[i] == x {
+ fmt.Printf("found %d at index %d in %v\n", x, i, a)
+ } else {
+ fmt.Printf("%d not found in %v\n", x, a)
+ }
+ // Output:
+ // found 6 at index 7 in [55 45 36 28 21 15 10 6 3 1]
+}
diff --git a/libgo/go/sort/example_test.go b/libgo/go/sort/example_test.go
index f7372bec375..980c0d03680 100644
--- a/libgo/go/sort/example_test.go
+++ b/libgo/go/sort/example_test.go
@@ -22,3 +22,22 @@ func ExampleReverse() {
fmt.Println(s)
// Output: [6 5 4 3 2 1]
}
+
+func ExampleSlice() {
+ people := []struct {
+ Name string
+ Age int
+ }{
+ {"Gopher", 7},
+ {"Alice", 55},
+ {"Vera", 24},
+ {"Bob", 75},
+ }
+ sort.Slice(people, func(i, j int) bool { return people[i].Name < people[j].Name })
+ fmt.Println("By name:", people)
+
+ sort.Slice(people, func(i, j int) bool { return people[i].Age < people[j].Age })
+ fmt.Println("By age:", people)
+ // Output: By name: [{Alice 55} {Bob 75} {Gopher 7} {Vera 24}]
+ // By age: [{Gopher 7} {Vera 24} {Alice 55} {Bob 75}]
+}
diff --git a/libgo/go/sort/genzfunc.go b/libgo/go/sort/genzfunc.go
new file mode 100644
index 00000000000..6d2b471b62e
--- /dev/null
+++ b/libgo/go/sort/genzfunc.go
@@ -0,0 +1,122 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+// This program is run via "go generate" (via a directive in sort.go)
+// to generate zfuncversion.go.
+//
+// It copies sort.go to zfuncversion.go, only retaining funcs which
+// take a "data Interface" parameter, and renaming each to have a
+// "_func" suffix and taking a "data lessSwap" instead. It then rewrites
+// each internal function call to the appropriate _func variants.
+
+package main
+
+import (
+ "bytes"
+ "go/ast"
+ "go/format"
+ "go/parser"
+ "go/token"
+ "io/ioutil"
+ "log"
+ "regexp"
+)
+
+var fset = token.NewFileSet()
+
+func main() {
+ af, err := parser.ParseFile(fset, "sort.go", nil, 0)
+ if err != nil {
+ log.Fatal(err)
+ }
+ af.Doc = nil
+ af.Imports = nil
+ af.Comments = nil
+
+ var newDecl []ast.Decl
+ for _, d := range af.Decls {
+ fd, ok := d.(*ast.FuncDecl)
+ if !ok {
+ continue
+ }
+ if fd.Recv != nil || fd.Name.IsExported() {
+ continue
+ }
+ typ := fd.Type
+ if len(typ.Params.List) < 1 {
+ continue
+ }
+ arg0 := typ.Params.List[0]
+ arg0Name := arg0.Names[0].Name
+ arg0Type := arg0.Type.(*ast.Ident)
+ if arg0Name != "data" || arg0Type.Name != "Interface" {
+ continue
+ }
+ arg0Type.Name = "lessSwap"
+
+ newDecl = append(newDecl, fd)
+ }
+ af.Decls = newDecl
+ ast.Walk(visitFunc(rewriteCalls), af)
+
+ var out bytes.Buffer
+ if err := format.Node(&out, fset, af); err != nil {
+ log.Fatalf("format.Node: %v", err)
+ }
+
+ // Get rid of blank lines after removal of comments.
+ src := regexp.MustCompile(`\n{2,}`).ReplaceAll(out.Bytes(), []byte("\n"))
+
+ // Add comments to each func, for the lost reader.
+ // This is so much easier than adding comments via the AST
+ // and trying to get position info correct.
+ src = regexp.MustCompile(`(?m)^func (\w+)`).ReplaceAll(src, []byte("\n// Auto-generated variant of sort.go:$1\nfunc ${1}_func"))
+
+ // Final gofmt.
+ src, err = format.Source(src)
+ if err != nil {
+ log.Fatalf("format.Source: %v on\n%s", err, src)
+ }
+
+ out.Reset()
+ out.WriteString(`// DO NOT EDIT; AUTO-GENERATED from sort.go using genzfunc.go
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+`)
+ out.Write(src)
+
+ const target = "zfuncversion.go"
+ if err := ioutil.WriteFile(target, out.Bytes(), 0644); err != nil {
+ log.Fatal(err)
+ }
+}
+
+type visitFunc func(ast.Node) ast.Visitor
+
+func (f visitFunc) Visit(n ast.Node) ast.Visitor { return f(n) }
+
+func rewriteCalls(n ast.Node) ast.Visitor {
+ ce, ok := n.(*ast.CallExpr)
+ if ok {
+ rewriteCall(ce)
+ }
+ return visitFunc(rewriteCalls)
+}
+
+func rewriteCall(ce *ast.CallExpr) {
+ ident, ok := ce.Fun.(*ast.Ident)
+ if !ok {
+ // e.g. skip SelectorExpr (data.Less(..) calls)
+ return
+ }
+ if len(ce.Args) < 1 {
+ return
+ }
+ ident.Name += "_func"
+}
diff --git a/libgo/go/sort/sort.go b/libgo/go/sort/sort.go
index d07a0c27b84..72d24efceab 100644
--- a/libgo/go/sort/sort.go
+++ b/libgo/go/sort/sort.go
@@ -2,10 +2,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:generate go run genzfunc.go
+
// Package sort provides primitives for sorting slices and user-defined
// collections.
package sort
+import "reflect"
+
// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package. The methods require that the
// elements of the collection be enumerated by an integer index.
@@ -212,14 +216,63 @@ func quickSort(data Interface, a, b, maxDepth int) {
// It makes one call to data.Len to determine n, and O(n*log(n)) calls to
// data.Less and data.Swap. The sort is not guaranteed to be stable.
func Sort(data Interface) {
- // Switch to heapsort if depth of 2*ceil(lg(n+1)) is reached.
n := data.Len()
- maxDepth := 0
+ quickSort(data, 0, n, maxDepth(n))
+}
+
+// maxDepth returns a threshold at which quicksort should switch
+// to heapsort. It returns 2*ceil(lg(n+1)).
+func maxDepth(n int) int {
+ var depth int
for i := n; i > 0; i >>= 1 {
- maxDepth++
+ depth++
+ }
+ return depth * 2
+}
+
+// lessSwap is a pair of Less and Swap function for use with the
+// auto-generated func-optimized variant of sort.go in
+// zfuncversion.go.
+type lessSwap struct {
+ Less func(i, j int) bool
+ Swap func(i, j int)
+}
+
+// Slice sorts the provided slice given the provided less function.
+//
+// The sort is not guaranteed to be stable. For a stable sort, use
+// SliceStable.
+//
+// The function panics if the provided interface is not a slice.
+func Slice(slice interface{}, less func(i, j int) bool) {
+ rv := reflect.ValueOf(slice)
+ swap := reflect.Swapper(slice)
+ length := rv.Len()
+ quickSort_func(lessSwap{less, swap}, 0, length, maxDepth(length))
+}
+
+// SliceStable sorts the provided slice given the provided less
+// function while keeping the original order of equal elements.
+//
+// The function panics if the provided interface is not a slice.
+func SliceStable(slice interface{}, less func(i, j int) bool) {
+ rv := reflect.ValueOf(slice)
+ swap := reflect.Swapper(slice)
+ stable_func(lessSwap{less, swap}, rv.Len())
+}
+
+// SliceIsSorted tests whether a slice is sorted.
+//
+// The function panics if the provided interface is not a slice.
+func SliceIsSorted(slice interface{}, less func(i, j int) bool) bool {
+ rv := reflect.ValueOf(slice)
+ n := rv.Len()
+ for i := n - 1; i > 0; i-- {
+ if less(i, i-1) {
+ return false
+ }
}
- maxDepth *= 2
- quickSort(data, 0, n, maxDepth)
+ return true
}
type reverse struct {
@@ -337,7 +390,10 @@ func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
// It makes one call to data.Len to determine n, O(n*log(n)) calls to
// data.Less and O(n*log(n)*log(n)) calls to data.Swap.
func Stable(data Interface) {
- n := data.Len()
+ stable(data, data.Len())
+}
+
+func stable(data Interface, n int) {
blockSize := 20 // must be > 0
a, b := 0, blockSize
for b <= n {
diff --git a/libgo/go/sort/sort_test.go b/libgo/go/sort/sort_test.go
index 60fac2d6951..45713a28cc4 100644
--- a/libgo/go/sort/sort_test.go
+++ b/libgo/go/sort/sort_test.go
@@ -6,10 +6,12 @@ package sort_test
import (
"fmt"
+ "internal/testenv"
"math"
"math/rand"
. "sort"
"strconv"
+ stringspkg "strings"
"testing"
)
@@ -74,6 +76,17 @@ func TestStrings(t *testing.T) {
}
}
+func TestSlice(t *testing.T) {
+ data := strings
+ Slice(data[:], func(i, j int) bool {
+ return data[i] < data[j]
+ })
+ if !SliceIsSorted(data[:], func(i, j int) bool { return data[i] < data[j] }) {
+ t.Errorf("sorted %v", strings)
+ t.Errorf(" got %v", data)
+ }
+}
+
func TestSortLarge_Random(t *testing.T) {
n := 1000000
if testing.Short() {
@@ -148,24 +161,46 @@ func TestNonDeterministicComparison(t *testing.T) {
func BenchmarkSortString1K(b *testing.B) {
b.StopTimer()
+ unsorted := make([]string, 1<<10)
+ for i := range unsorted {
+ unsorted[i] = strconv.Itoa(i ^ 0x2cc)
+ }
+ data := make([]string, len(unsorted))
+
for i := 0; i < b.N; i++ {
- data := make([]string, 1<<10)
- for i := 0; i < len(data); i++ {
- data[i] = strconv.Itoa(i ^ 0x2cc)
- }
+ copy(data, unsorted)
b.StartTimer()
Strings(data)
b.StopTimer()
}
}
+func BenchmarkSortString1K_Slice(b *testing.B) {
+ b.StopTimer()
+ unsorted := make([]string, 1<<10)
+ for i := range unsorted {
+ unsorted[i] = strconv.Itoa(i ^ 0x2cc)
+ }
+ data := make([]string, len(unsorted))
+
+ for i := 0; i < b.N; i++ {
+ copy(data, unsorted)
+ b.StartTimer()
+ Slice(data, func(i, j int) bool { return data[i] < data[j] })
+ b.StopTimer()
+ }
+}
+
func BenchmarkStableString1K(b *testing.B) {
b.StopTimer()
+ unsorted := make([]string, 1<<10)
+ for i := 0; i < len(data); i++ {
+ unsorted[i] = strconv.Itoa(i ^ 0x2cc)
+ }
+ data := make([]string, len(unsorted))
+
for i := 0; i < b.N; i++ {
- data := make([]string, 1<<10)
- for i := 0; i < len(data); i++ {
- data[i] = strconv.Itoa(i ^ 0x2cc)
- }
+ copy(data, unsorted)
b.StartTimer()
Stable(StringSlice(data))
b.StopTimer()
@@ -187,17 +222,34 @@ func BenchmarkSortInt1K(b *testing.B) {
func BenchmarkStableInt1K(b *testing.B) {
b.StopTimer()
+ unsorted := make([]int, 1<<10)
+ for i := range unsorted {
+ unsorted[i] = i ^ 0x2cc
+ }
+ data := make([]int, len(unsorted))
for i := 0; i < b.N; i++ {
- data := make([]int, 1<<10)
- for i := 0; i < len(data); i++ {
- data[i] = i ^ 0x2cc
- }
+ copy(data, unsorted)
b.StartTimer()
Stable(IntSlice(data))
b.StopTimer()
}
}
+func BenchmarkStableInt1K_Slice(b *testing.B) {
+ b.StopTimer()
+ unsorted := make([]int, 1<<10)
+ for i := range unsorted {
+ unsorted[i] = i ^ 0x2cc
+ }
+ data := make([]int, len(unsorted))
+ for i := 0; i < b.N; i++ {
+ copy(data, unsorted)
+ b.StartTimer()
+ SliceStable(data, func(i, j int) bool { return data[i] < data[j] })
+ b.StopTimer()
+ }
+}
+
func BenchmarkSortInt64K(b *testing.B) {
b.StopTimer()
for i := 0; i < b.N; i++ {
@@ -211,6 +263,19 @@ func BenchmarkSortInt64K(b *testing.B) {
}
}
+func BenchmarkSortInt64K_Slice(b *testing.B) {
+ b.StopTimer()
+ for i := 0; i < b.N; i++ {
+ data := make([]int, 1<<16)
+ for i := 0; i < len(data); i++ {
+ data[i] = i ^ 0xcccc
+ }
+ b.StartTimer()
+ Slice(data, func(i, j int) bool { return data[i] < data[j] })
+ b.StopTimer()
+ }
+}
+
func BenchmarkStableInt64K(b *testing.B) {
b.StopTimer()
for i := 0; i < b.N; i++ {
@@ -555,6 +620,9 @@ func TestCountStableOps(t *testing.T) { countOps(t, Stable, "Stable") }
func TestCountSortOps(t *testing.T) { countOps(t, Sort, "Sort ") }
func bench(b *testing.B, size int, algo func(Interface), name string) {
+ if stringspkg.HasSuffix(testenv.Builder(), "-race") && size > 1e4 {
+ b.Skip("skipping slow benchmark on race builder")
+ }
b.StopTimer()
data := make(intPairs, size)
x := ^uint32(0)
diff --git a/libgo/go/sort/zfuncversion.go b/libgo/go/sort/zfuncversion.go
new file mode 100644
index 00000000000..7abb18a24d5
--- /dev/null
+++ b/libgo/go/sort/zfuncversion.go
@@ -0,0 +1,265 @@
+// DO NOT EDIT; AUTO-GENERATED from sort.go using genzfunc.go
+
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sort
+
+// Auto-generated variant of sort.go:insertionSort
+func insertionSort_func(data lessSwap, a, b int) {
+ for i := a + 1; i < b; i++ {
+ for j := i; j > a && data.Less(j, j-1); j-- {
+ data.Swap(j, j-1)
+ }
+ }
+}
+
+// Auto-generated variant of sort.go:siftDown
+func siftDown_func(data lessSwap, lo, hi, first int) {
+ root := lo
+ for {
+ child := 2*root + 1
+ if child >= hi {
+ break
+ }
+ if child+1 < hi && data.Less(first+child, first+child+1) {
+ child++
+ }
+ if !data.Less(first+root, first+child) {
+ return
+ }
+ data.Swap(first+root, first+child)
+ root = child
+ }
+}
+
+// Auto-generated variant of sort.go:heapSort
+func heapSort_func(data lessSwap, a, b int) {
+ first := a
+ lo := 0
+ hi := b - a
+ for i := (hi - 1) / 2; i >= 0; i-- {
+ siftDown_func(data, i, hi, first)
+ }
+ for i := hi - 1; i >= 0; i-- {
+ data.Swap(first, first+i)
+ siftDown_func(data, lo, i, first)
+ }
+}
+
+// Auto-generated variant of sort.go:medianOfThree
+func medianOfThree_func(data lessSwap, m1, m0, m2 int) {
+ if data.Less(m1, m0) {
+ data.Swap(m1, m0)
+ }
+ if data.Less(m2, m1) {
+ data.Swap(m2, m1)
+ if data.Less(m1, m0) {
+ data.Swap(m1, m0)
+ }
+ }
+}
+
+// Auto-generated variant of sort.go:swapRange
+func swapRange_func(data lessSwap, a, b, n int) {
+ for i := 0; i < n; i++ {
+ data.Swap(a+i, b+i)
+ }
+}
+
+// Auto-generated variant of sort.go:doPivot
+func doPivot_func(data lessSwap, lo, hi int) (midlo, midhi int) {
+ m := lo + (hi-lo)/2
+ if hi-lo > 40 {
+ s := (hi - lo) / 8
+ medianOfThree_func(data, lo, lo+s, lo+2*s)
+ medianOfThree_func(data, m, m-s, m+s)
+ medianOfThree_func(data, hi-1, hi-1-s, hi-1-2*s)
+ }
+ medianOfThree_func(data, lo, m, hi-1)
+ pivot := lo
+ a, c := lo+1, hi-1
+ for ; a < c && data.Less(a, pivot); a++ {
+ }
+ b := a
+ for {
+ for ; b < c && !data.Less(pivot, b); b++ {
+ }
+ for ; b < c && data.Less(pivot, c-1); c-- {
+ }
+ if b >= c {
+ break
+ }
+ data.Swap(b, c-1)
+ b++
+ c--
+ }
+ protect := hi-c < 5
+ if !protect && hi-c < (hi-lo)/4 {
+ dups := 0
+ if !data.Less(pivot, hi-1) {
+ data.Swap(c, hi-1)
+ c++
+ dups++
+ }
+ if !data.Less(b-1, pivot) {
+ b--
+ dups++
+ }
+ if !data.Less(m, pivot) {
+ data.Swap(m, b-1)
+ b--
+ dups++
+ }
+ protect = dups > 1
+ }
+ if protect {
+ for {
+ for ; a < b && !data.Less(b-1, pivot); b-- {
+ }
+ for ; a < b && data.Less(a, pivot); a++ {
+ }
+ if a >= b {
+ break
+ }
+ data.Swap(a, b-1)
+ a++
+ b--
+ }
+ }
+ data.Swap(pivot, b-1)
+ return b - 1, c
+}
+
+// Auto-generated variant of sort.go:quickSort
+func quickSort_func(data lessSwap, a, b, maxDepth int) {
+ for b-a > 12 {
+ if maxDepth == 0 {
+ heapSort_func(data, a, b)
+ return
+ }
+ maxDepth--
+ mlo, mhi := doPivot_func(data, a, b)
+ if mlo-a < b-mhi {
+ quickSort_func(data, a, mlo, maxDepth)
+ a = mhi
+ } else {
+ quickSort_func(data, mhi, b, maxDepth)
+ b = mlo
+ }
+ }
+ if b-a > 1 {
+ for i := a + 6; i < b; i++ {
+ if data.Less(i, i-6) {
+ data.Swap(i, i-6)
+ }
+ }
+ insertionSort_func(data, a, b)
+ }
+}
+
+// Auto-generated variant of sort.go:stable
+func stable_func(data lessSwap, n int) {
+ blockSize := 20
+ a, b := 0, blockSize
+ for b <= n {
+ insertionSort_func(data, a, b)
+ a = b
+ b += blockSize
+ }
+ insertionSort_func(data, a, n)
+ for blockSize < n {
+ a, b = 0, 2*blockSize
+ for b <= n {
+ symMerge_func(data, a, a+blockSize, b)
+ a = b
+ b += 2 * blockSize
+ }
+ if m := a + blockSize; m < n {
+ symMerge_func(data, a, m, n)
+ }
+ blockSize *= 2
+ }
+}
+
+// Auto-generated variant of sort.go:symMerge
+func symMerge_func(data lessSwap, a, m, b int) {
+ if m-a == 1 {
+ i := m
+ j := b
+ for i < j {
+ h := i + (j-i)/2
+ if data.Less(h, a) {
+ i = h + 1
+ } else {
+ j = h
+ }
+ }
+ for k := a; k < i-1; k++ {
+ data.Swap(k, k+1)
+ }
+ return
+ }
+ if b-m == 1 {
+ i := a
+ j := m
+ for i < j {
+ h := i + (j-i)/2
+ if !data.Less(m, h) {
+ i = h + 1
+ } else {
+ j = h
+ }
+ }
+ for k := m; k > i; k-- {
+ data.Swap(k, k-1)
+ }
+ return
+ }
+ mid := a + (b-a)/2
+ n := mid + m
+ var start, r int
+ if m > mid {
+ start = n - b
+ r = mid
+ } else {
+ start = a
+ r = m
+ }
+ p := n - 1
+ for start < r {
+ c := start + (r-start)/2
+ if !data.Less(p-c, c) {
+ start = c + 1
+ } else {
+ r = c
+ }
+ }
+ end := n - start
+ if start < m && m < end {
+ rotate_func(data, start, m, end)
+ }
+ if a < start && start < mid {
+ symMerge_func(data, a, start, mid)
+ }
+ if mid < end && end < b {
+ symMerge_func(data, mid, end, b)
+ }
+}
+
+// Auto-generated variant of sort.go:rotate
+func rotate_func(data lessSwap, a, m, b int) {
+ i := m - a
+ j := b - m
+ for i != j {
+ if i > j {
+ swapRange_func(data, m-i, m, j)
+ i -= j
+ } else {
+ swapRange_func(data, m-i, m+j-i, i)
+ j -= i
+ }
+ }
+ swapRange_func(data, m-i, m, i)
+}
diff --git a/libgo/go/strconv/atoi.go b/libgo/go/strconv/atoi.go
index a236de421c6..66df149172d 100644
--- a/libgo/go/strconv/atoi.go
+++ b/libgo/go/strconv/atoi.go
@@ -199,6 +199,10 @@ func ParseInt(s string, base int, bitSize int) (i int64, err error) {
// Atoi returns the result of ParseInt(s, 10, 0) converted to type int.
func Atoi(s string) (int, error) {
+ const fnAtoi = "Atoi"
i64, err := ParseInt(s, 10, 0)
+ if nerr, ok := err.(*NumError); ok {
+ nerr.Func = fnAtoi
+ }
return int(i64), err
}
diff --git a/libgo/go/strconv/decimal.go b/libgo/go/strconv/decimal.go
index 5252d6e86eb..957acd98918 100644
--- a/libgo/go/strconv/decimal.go
+++ b/libgo/go/strconv/decimal.go
@@ -131,11 +131,13 @@ func rightShift(a *decimal, k uint) {
}
a.dp -= r - 1
+ var mask uint = (1 << k) - 1
+
// Pick up a digit, put down a digit.
for ; r < a.nd; r++ {
c := uint(a.d[r])
dig := n >> k
- n -= dig << k
+ n &= mask
a.d[w] = byte(dig + '0')
w++
n = n*10 + c - '0'
@@ -144,7 +146,7 @@ func rightShift(a *decimal, k uint) {
// Put down extra digits.
for n > 0 {
dig := n >> k
- n -= dig << k
+ n &= mask
if w < len(a.d) {
a.d[w] = byte(dig + '0')
w++
diff --git a/libgo/go/strconv/ftoa_test.go b/libgo/go/strconv/ftoa_test.go
index 1d25242ff3f..976bd2c9b8b 100644
--- a/libgo/go/strconv/ftoa_test.go
+++ b/libgo/go/strconv/ftoa_test.go
@@ -208,6 +208,9 @@ var ftoaBenches = []struct {
{"64Fixed2", 123.456, 'e', 3, 64},
{"64Fixed3", 1.23456e+78, 'e', 3, 64},
{"64Fixed4", 1.23456e-78, 'e', 3, 64},
+
+ // Trigger slow path (see issue #15672).
+ {"Slowpath64", 622666234635.3213e-320, 'e', -1, 64},
}
func BenchmarkFormatFloat(b *testing.B) {
diff --git a/libgo/go/strconv/quote.go b/libgo/go/strconv/quote.go
index becfe1df075..76c5c2a1cbb 100644
--- a/libgo/go/strconv/quote.go
+++ b/libgo/go/strconv/quote.go
@@ -362,6 +362,16 @@ func Unquote(s string) (string, error) {
if contains(s, '`') {
return "", ErrSyntax
}
+ if contains(s, '\r') {
+ // -1 because we know there is at least one \r to remove.
+ buf := make([]byte, 0, len(s)-1)
+ for i := 0; i < len(s); i++ {
+ if s[i] != '\r' {
+ buf = append(buf, s[i])
+ }
+ }
+ return string(buf), nil
+ }
return s, nil
}
if quote != '"' && quote != '\'' {
diff --git a/libgo/go/strconv/quote_test.go b/libgo/go/strconv/quote_test.go
index 10735e316c7..a4b5804fc89 100644
--- a/libgo/go/strconv/quote_test.go
+++ b/libgo/go/strconv/quote_test.go
@@ -274,6 +274,7 @@ var unquotetests = []unQuoteTest{
{"`\n`", "\n"},
{"` `", ` `},
{"` `", ` `},
+ {"`a\rb`", "ab"},
}
var misquoted = []string{
@@ -306,7 +307,7 @@ var misquoted = []string{
func TestUnquote(t *testing.T) {
for _, tt := range unquotetests {
- if out, err := Unquote(tt.in); err != nil && out != tt.out {
+ if out, err := Unquote(tt.in); err != nil || out != tt.out {
t.Errorf("Unquote(%#q) = %q, %v want %q, nil", tt.in, out, err, tt.out)
}
}
diff --git a/libgo/go/strconv/strconv_test.go b/libgo/go/strconv/strconv_test.go
index 207e00e75dc..ebec0cc9e84 100644
--- a/libgo/go/strconv/strconv_test.go
+++ b/libgo/go/strconv/strconv_test.go
@@ -4,10 +4,6 @@
package strconv_test
-/*
-
-gccgo does not pass this.
-
import (
"runtime"
. "strconv"
@@ -46,6 +42,9 @@ var (
)
func TestCountMallocs(t *testing.T) {
+ if runtime.Compiler == "gccgo" {
+ t.Skip("skipping on gccgo until escape analysis is turned on")
+ }
if testing.Short() {
t.Skip("skipping malloc count in short mode")
}
@@ -60,4 +59,33 @@ func TestCountMallocs(t *testing.T) {
}
}
-*/
+func TestErrorPrefixes(t *testing.T) {
+ _, errInt := Atoi("INVALID")
+ _, errBool := ParseBool("INVALID")
+ _, errFloat := ParseFloat("INVALID", 64)
+ _, errInt64 := ParseInt("INVALID", 10, 64)
+ _, errUint64 := ParseUint("INVALID", 10, 64)
+
+ vectors := []struct {
+ err error // Input error
+ want string // Function name wanted
+ }{
+ {errInt, "Atoi"},
+ {errBool, "ParseBool"},
+ {errFloat, "ParseFloat"},
+ {errInt64, "ParseInt"},
+ {errUint64, "ParseUint"},
+ }
+
+ for _, v := range vectors {
+ nerr, ok := v.err.(*NumError)
+ if !ok {
+ t.Errorf("test %s, error was not a *NumError", v.want)
+ continue
+ }
+ if got := nerr.Func; got != v.want {
+ t.Errorf("mismatching Func: got %s, want %s", got, v.want)
+ }
+ }
+
+}
diff --git a/libgo/go/strings/strings.go b/libgo/go/strings/strings.go
index 919e8c8354e..60a281a6ac5 100644
--- a/libgo/go/strings/strings.go
+++ b/libgo/go/strings/strings.go
@@ -77,48 +77,18 @@ func hashStrRev(sep string) (uint32, uint32) {
func Count(s, sep string) int {
n := 0
// special cases
- switch {
- case len(sep) == 0:
+ if len(sep) == 0 {
return utf8.RuneCountInString(s) + 1
- case len(sep) == 1:
- // special case worth making fast
- c := sep[0]
- for i := 0; i < len(s); i++ {
- if s[i] == c {
- n++
- }
- }
- return n
- case len(sep) > len(s):
- return 0
- case len(sep) == len(s):
- if sep == s {
- return 1
- }
- return 0
}
- // Rabin-Karp search
- hashsep, pow := hashStr(sep)
- h := uint32(0)
- for i := 0; i < len(sep); i++ {
- h = h*primeRK + uint32(s[i])
- }
- lastmatch := 0
- if h == hashsep && s[:len(sep)] == sep {
- n++
- lastmatch = len(sep)
- }
- for i := len(sep); i < len(s); {
- h *= primeRK
- h += uint32(s[i])
- h -= pow * uint32(s[i-len(sep)])
- i++
- if h == hashsep && lastmatch <= i-len(sep) && s[i-len(sep):i] == sep {
- n++
- lastmatch = i
+ offset := 0
+ for {
+ i := Index(s[offset:], sep)
+ if i == -1 {
+ return n
}
+ n++
+ offset += i + len(sep)
}
- return n
}
// Contains reports whether substr is within s.
@@ -175,24 +145,40 @@ func LastIndex(s, sep string) int {
// IndexRune returns the index of the first instance of the Unicode code point
// r, or -1 if rune is not present in s.
+// If r is utf8.RuneError, it returns the first instance of any
+// invalid UTF-8 byte sequence.
func IndexRune(s string, r rune) int {
switch {
- case r < utf8.RuneSelf:
+ case 0 <= r && r < utf8.RuneSelf:
return IndexByte(s, byte(r))
- default:
- for i, c := range s {
- if c == r {
+ case r == utf8.RuneError:
+ for i, r := range s {
+ if r == utf8.RuneError {
return i
}
}
+ return -1
+ case !utf8.ValidRune(r):
+ return -1
+ default:
+ return Index(s, string(r))
}
- return -1
}
// IndexAny returns the index of the first instance of any Unicode code point
// from chars in s, or -1 if no Unicode code point from chars is present in s.
func IndexAny(s, chars string) int {
if len(chars) > 0 {
+ if len(s) > 8 {
+ if as, isASCII := makeASCIISet(chars); isASCII {
+ for i := 0; i < len(s); i++ {
+ if as.contains(s[i]) {
+ return i
+ }
+ }
+ return -1
+ }
+ }
for i, c := range s {
for _, m := range chars {
if c == m {
@@ -209,11 +195,21 @@ func IndexAny(s, chars string) int {
// present in s.
func LastIndexAny(s, chars string) int {
if len(chars) > 0 {
+ if len(s) > 8 {
+ if as, isASCII := makeASCIISet(chars); isASCII {
+ for i := len(s) - 1; i >= 0; i-- {
+ if as.contains(s[i]) {
+ return i
+ }
+ }
+ return -1
+ }
+ }
for i := len(s); i > 0; {
- rune, size := utf8.DecodeLastRuneInString(s[0:i])
+ r, size := utf8.DecodeLastRuneInString(s[:i])
i -= size
- for _, m := range chars {
- if rune == m {
+ for _, c := range chars {
+ if r == c {
return i
}
}
@@ -342,11 +338,19 @@ func FieldsFunc(s string, f func(rune) bool) []string {
// Join concatenates the elements of a to create a single string. The separator string
// sep is placed between elements in the resulting string.
func Join(a []string, sep string) string {
- if len(a) == 0 {
+ switch len(a) {
+ case 0:
return ""
- }
- if len(a) == 1 {
+ case 1:
return a[0]
+ case 2:
+ // Special case for common small values.
+ // Remove if golang.org/issue/6714 is fixed
+ return a[0] + sep + a[1]
+ case 3:
+ // Special case for common small values.
+ // Remove if golang.org/issue/6714 is fixed
+ return a[0] + sep + a[1] + sep + a[2]
}
n := len(sep) * (len(a) - 1)
for i := 0; i < len(a); i++ {
@@ -416,7 +420,20 @@ func Map(mapping func(rune) rune, s string) string {
}
// Repeat returns a new string consisting of count copies of the string s.
+//
+// It panics if count is negative or if
+// the result of (len(s) * count) overflows.
func Repeat(s string, count int) string {
+ // Since we cannot return an error on overflow,
+ // we should panic if the repeat will generate
+ // an overflow.
+ // See Issue golang.org/issue/16237
+ if count < 0 {
+ panic("strings: negative Repeat count")
+ } else if count > 0 && len(s)*count/count != len(s) {
+ panic("strings: Repeat count causes overflow")
+ }
+
b := make([]byte, len(s)*count)
bp := copy(b, s)
for bp < len(b) {
@@ -437,20 +454,20 @@ func ToTitle(s string) string { return Map(unicode.ToTitle, s) }
// ToUpperSpecial returns a copy of the string s with all Unicode letters mapped to their
// upper case, giving priority to the special casing rules.
-func ToUpperSpecial(_case unicode.SpecialCase, s string) string {
- return Map(func(r rune) rune { return _case.ToUpper(r) }, s)
+func ToUpperSpecial(c unicode.SpecialCase, s string) string {
+ return Map(func(r rune) rune { return c.ToUpper(r) }, s)
}
// ToLowerSpecial returns a copy of the string s with all Unicode letters mapped to their
// lower case, giving priority to the special casing rules.
-func ToLowerSpecial(_case unicode.SpecialCase, s string) string {
- return Map(func(r rune) rune { return _case.ToLower(r) }, s)
+func ToLowerSpecial(c unicode.SpecialCase, s string) string {
+ return Map(func(r rune) rune { return c.ToLower(r) }, s)
}
// ToTitleSpecial returns a copy of the string s with all Unicode letters mapped to their
// title case, giving priority to the special casing rules.
-func ToTitleSpecial(_case unicode.SpecialCase, s string) string {
- return Map(func(r rune) rune { return _case.ToTitle(r) }, s)
+func ToTitleSpecial(c unicode.SpecialCase, s string) string {
+ return Map(func(r rune) rune { return c.ToTitle(r) }, s)
}
// isSeparator reports whether the rune could mark a word boundary.
@@ -573,7 +590,43 @@ func lastIndexFunc(s string, f func(rune) bool, truth bool) int {
return -1
}
+// asciiSet is a 32-byte value, where each bit represents the presence of a
+// given ASCII character in the set. The 128-bits of the lower 16 bytes,
+// starting with the least-significant bit of the lowest word to the
+// most-significant bit of the highest word, map to the full range of all
+// 128 ASCII characters. The 128-bits of the upper 16 bytes will be zeroed,
+// ensuring that any non-ASCII character will be reported as not in the set.
+type asciiSet [8]uint32
+
+// makeASCIISet creates a set of ASCII characters and reports whether all
+// characters in chars are ASCII.
+func makeASCIISet(chars string) (as asciiSet, ok bool) {
+ for i := 0; i < len(chars); i++ {
+ c := chars[i]
+ if c >= utf8.RuneSelf {
+ return as, false
+ }
+ as[c>>5] |= 1 << uint(c&31)
+ }
+ return as, true
+}
+
+// contains reports whether c is inside the set.
+func (as *asciiSet) contains(c byte) bool {
+ return (as[c>>5] & (1 << uint(c&31))) != 0
+}
+
func makeCutsetFunc(cutset string) func(rune) bool {
+ if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
+ return func(r rune) bool {
+ return r == rune(cutset[0])
+ }
+ }
+ if as, isASCII := makeASCIISet(cutset); isASCII {
+ return func(r rune) bool {
+ return r < utf8.RuneSelf && as.contains(byte(r))
+ }
+ }
return func(r rune) bool { return IndexRune(cutset, r) >= 0 }
}
diff --git a/libgo/go/strings/strings_amd64.go b/libgo/go/strings/strings_amd64.go
index 4b06f8a0c18..e55afd53d01 100644
--- a/libgo/go/strings/strings_amd64.go
+++ b/libgo/go/strings/strings_amd64.go
@@ -6,10 +6,22 @@
package strings
+//go:noescape
+
// indexShortStr returns the index of the first instance of c in s, or -1 if c is not present in s.
// indexShortStr requires 2 <= len(c) <= shortStringLen
func indexShortStr(s, c string) int // ../runtime/asm_$GOARCH.s
-const shortStringLen = 31
+func supportAVX2() bool // ../runtime/asm_$GOARCH.s
+
+var shortStringLen int
+
+func init() {
+ if supportAVX2() {
+ shortStringLen = 63
+ } else {
+ shortStringLen = 31
+ }
+}
// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
func Index(s, sep string) int {
@@ -19,8 +31,6 @@ func Index(s, sep string) int {
return 0
case n == 1:
return IndexByte(s, sep[0])
- case n <= shortStringLen:
- return indexShortStr(s, sep)
case n == len(s):
if sep == s {
return 0
@@ -28,6 +38,42 @@ func Index(s, sep string) int {
return -1
case n > len(s):
return -1
+ case n <= shortStringLen:
+ // Use brute force when s and sep both are small
+ if len(s) <= 64 {
+ return indexShortStr(s, sep)
+ }
+ c := sep[0]
+ i := 0
+ t := s[:len(s)-n+1]
+ fails := 0
+ for i < len(t) {
+ if t[i] != c {
+ // IndexByte skips 16/32 bytes per iteration,
+ // so it's faster than indexShortStr.
+ o := IndexByte(t[i:], c)
+ if o < 0 {
+ return -1
+ }
+ i += o
+ }
+ if s[i:i+n] == sep {
+ return i
+ }
+ fails++
+ i++
+ // Switch to indexShortStr when IndexByte produces too many false positives.
+ // Too many means more that 1 error per 8 characters.
+ // Allow some errors in the beginning.
+ if fails > (i+16)/8 {
+ r := indexShortStr(s[i:], sep)
+ if r >= 0 {
+ return r + i
+ }
+ return -1
+ }
+ }
+ return -1
}
// Rabin-Karp search
hashsep, pow := hashStr(sep)
diff --git a/libgo/go/strings/strings_generic.go b/libgo/go/strings/strings_generic.go
index aef2c1e355b..a3ad515444b 100644
--- a/libgo/go/strings/strings_generic.go
+++ b/libgo/go/strings/strings_generic.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,!s390x
+
package strings
// TODO: implements short string optimization on non amd64 platforms
diff --git a/libgo/go/strings/strings_s390x.go b/libgo/go/strings/strings_s390x.go
new file mode 100644
index 00000000000..b47702fd51a
--- /dev/null
+++ b/libgo/go/strings/strings_s390x.go
@@ -0,0 +1,100 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build ignore
+
+package strings
+
+//go:noescape
+
+// indexShortStr returns the index of the first instance of sep in s,
+// or -1 if sep is not present in s.
+// indexShortStr requires 2 <= len(sep) <= shortStringLen
+func indexShortStr(s, sep string) int // ../runtime/asm_$GOARCH.s
+
+// supportsVX reports whether the vector facility is available.
+// indexShortStr must not be called if the vector facility is not
+// available.
+func supportsVX() bool // ../runtime/asm_s390x.s
+
+var shortStringLen = -1
+
+func init() {
+ if supportsVX() {
+ shortStringLen = 64
+ }
+}
+
+// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
+func Index(s, sep string) int {
+ n := len(sep)
+ switch {
+ case n == 0:
+ return 0
+ case n == 1:
+ return IndexByte(s, sep[0])
+ case n == len(s):
+ if sep == s {
+ return 0
+ }
+ return -1
+ case n > len(s):
+ return -1
+ case n <= shortStringLen:
+ // Use brute force when s and sep both are small
+ if len(s) <= 64 {
+ return indexShortStr(s, sep)
+ }
+ c := sep[0]
+ i := 0
+ t := s[:len(s)-n+1]
+ fails := 0
+ for i < len(t) {
+ if t[i] != c {
+ // IndexByte skips 16/32 bytes per iteration,
+ // so it's faster than indexShortStr.
+ o := IndexByte(t[i:], c)
+ if o < 0 {
+ return -1
+ }
+ i += o
+ }
+ if s[i:i+n] == sep {
+ return i
+ }
+ fails++
+ i++
+ // Switch to indexShortStr when IndexByte produces too many false positives.
+ // Too many means more that 1 error per 8 characters.
+ // Allow some errors in the beginning.
+ if fails > (i+16)/8 {
+ r := indexShortStr(s[i:], sep)
+ if r >= 0 {
+ return r + i
+ }
+ return -1
+ }
+ }
+ return -1
+ }
+ // Rabin-Karp search
+ hashsep, pow := hashStr(sep)
+ var h uint32
+ for i := 0; i < n; i++ {
+ h = h*primeRK + uint32(s[i])
+ }
+ if h == hashsep && s[:n] == sep {
+ return 0
+ }
+ for i := n; i < len(s); {
+ h *= primeRK
+ h += uint32(s[i])
+ h -= pow * uint32(s[i-n])
+ i++
+ if h == hashsep && s[i-n:i] == sep {
+ return i - n
+ }
+ }
+ return -1
+}
diff --git a/libgo/go/strings/strings_test.go b/libgo/go/strings/strings_test.go
index fcef761da79..449fb502d64 100644
--- a/libgo/go/strings/strings_test.go
+++ b/libgo/go/strings/strings_test.go
@@ -6,9 +6,11 @@ package strings_test
import (
"bytes"
+ "fmt"
"io"
"math/rand"
"reflect"
+ "runtime"
. "strings"
"testing"
"unicode"
@@ -86,32 +88,44 @@ var indexTests = []IndexTest{
{"32145678", "01234567", -1},
{"01234567", "01234567", 0},
{"x01234567", "01234567", 1},
+ {"x0123456x01234567", "01234567", 9},
{"xx01234567"[:9], "01234567", -1},
{"", "0123456789", -1},
{"3214567844", "0123456789", -1},
{"0123456789", "0123456789", 0},
{"x0123456789", "0123456789", 1},
+ {"x012345678x0123456789", "0123456789", 11},
{"xyz0123456789"[:12], "0123456789", -1},
{"x01234567x89", "0123456789", -1},
{"", "0123456789012345", -1},
{"3214567889012345", "0123456789012345", -1},
{"0123456789012345", "0123456789012345", 0},
{"x0123456789012345", "0123456789012345", 1},
+ {"x012345678901234x0123456789012345", "0123456789012345", 17},
{"", "01234567890123456789", -1},
{"32145678890123456789", "01234567890123456789", -1},
{"01234567890123456789", "01234567890123456789", 0},
{"x01234567890123456789", "01234567890123456789", 1},
+ {"x0123456789012345678x01234567890123456789", "01234567890123456789", 21},
{"xyz01234567890123456789"[:22], "01234567890123456789", -1},
{"", "0123456789012345678901234567890", -1},
{"321456788901234567890123456789012345678911", "0123456789012345678901234567890", -1},
{"0123456789012345678901234567890", "0123456789012345678901234567890", 0},
{"x0123456789012345678901234567890", "0123456789012345678901234567890", 1},
+ {"x012345678901234567890123456789x0123456789012345678901234567890", "0123456789012345678901234567890", 32},
{"xyz0123456789012345678901234567890"[:33], "0123456789012345678901234567890", -1},
{"", "01234567890123456789012345678901", -1},
{"32145678890123456789012345678901234567890211", "01234567890123456789012345678901", -1},
{"01234567890123456789012345678901", "01234567890123456789012345678901", 0},
{"x01234567890123456789012345678901", "01234567890123456789012345678901", 1},
+ {"x0123456789012345678901234567890x01234567890123456789012345678901", "01234567890123456789012345678901", 33},
{"xyz01234567890123456789012345678901"[:34], "01234567890123456789012345678901", -1},
+ {"xxxxxx012345678901234567890123456789012345678901234567890123456789012", "012345678901234567890123456789012345678901234567890123456789012", 6},
+ {"", "0123456789012345678901234567890123456789", -1},
+ {"xx012345678901234567890123456789012345678901234567890123456789012", "0123456789012345678901234567890123456789", 2},
+ {"xx012345678901234567890123456789012345678901234567890123456789012"[:41], "0123456789012345678901234567890123456789", -1},
+ {"xx012345678901234567890123456789012345678901234567890123456789012", "0123456789012345678901234567890123456xxx", -1},
+ {"xx0123456789012345678901234567890123456789012345678901234567890120123456789012345678901234567890123456xxx", "0123456789012345678901234567890123456xxx", 65},
}
var lastIndexTests = []IndexTest{
@@ -139,10 +153,15 @@ var indexAnyTests = []IndexTest{
{"aaa", "a", 0},
{"abc", "xyz", -1},
{"abc", "xcz", 2},
- {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
+ {"ab☺c", "x☺yz", 2},
+ {"a☺b☻c☹d", "cx", len("a☺b☻")},
+ {"a☺b☻c☹d", "uvw☻xyz", len("a☺b")},
{"aRegExp*", ".(|)*+?^$[]", 7},
{dots + dots + dots, " ", -1},
+ {"012abcba210", "\xffb", 4},
+ {"012\x80bcb\x80210", "\xffb", 3},
}
+
var lastIndexAnyTests = []IndexTest{
{"", "", -1},
{"", "a", -1},
@@ -152,9 +171,13 @@ var lastIndexAnyTests = []IndexTest{
{"aaa", "a", 2},
{"abc", "xyz", -1},
{"abc", "ab", 1},
- {"a☺b☻c☹d", "uvw☻xyz", 2 + len("☺")},
+ {"ab☺c", "x☺yz", 2},
+ {"a☺b☻c☹d", "cx", len("a☺b☻")},
+ {"a☺b☻c☹d", "uvw☻xyz", len("a☺b")},
{"a.RegExp*", ".(|)*+?^$[]", 8},
{dots + dots + dots, " ", -1},
+ {"012abcba210", "\xffb", 6},
+ {"012\x80bcb\x80210", "\xffb", 7},
}
// Execute f on each test case. funcName should be the name of f; it's used
@@ -227,22 +250,56 @@ func TestIndexRandom(t *testing.T) {
}
}
-var indexRuneTests = []struct {
- s string
- rune rune
- out int
-}{
- {"a A x", 'A', 2},
- {"some_text=some_value", '=', 9},
- {"☺a", 'a', 3},
- {"a☻☺b", '☺', 4},
-}
-
func TestIndexRune(t *testing.T) {
- for _, test := range indexRuneTests {
- if actual := IndexRune(test.s, test.rune); actual != test.out {
- t.Errorf("IndexRune(%q,%d)= %v; want %v", test.s, test.rune, actual, test.out)
+ tests := []struct {
+ in string
+ rune rune
+ want int
+ }{
+ {"", 'a', -1},
+ {"", '☺', -1},
+ {"foo", '☹', -1},
+ {"foo", 'o', 1},
+ {"foo☺bar", '☺', 3},
+ {"foo☺☻☹bar", '☹', 9},
+ {"a A x", 'A', 2},
+ {"some_text=some_value", '=', 9},
+ {"☺a", 'a', 3},
+ {"a☻☺b", '☺', 4},
+
+ // RuneError should match any invalid UTF-8 byte sequence.
+ {"�", '�', 0},
+ {"\xff", '�', 0},
+ {"☻x�", '�', len("☻x")},
+ {"☻x\xe2\x98", '�', len("☻x")},
+ {"☻x\xe2\x98�", '�', len("☻x")},
+ {"☻x\xe2\x98x", '�', len("☻x")},
+
+ // Invalid rune values should never match.
+ {"a☺b☻c☹d\xe2\x98�\xff�\xed\xa0\x80", -1, -1},
+ {"a☺b☻c☹d\xe2\x98�\xff�\xed\xa0\x80", 0xD800, -1}, // Surrogate pair
+ {"a☺b☻c☹d\xe2\x98�\xff�\xed\xa0\x80", utf8.MaxRune + 1, -1},
+ }
+ for _, tt := range tests {
+ if got := IndexRune(tt.in, tt.rune); got != tt.want {
+ t.Errorf("IndexRune(%q, %d) = %v; want %v", tt.in, tt.rune, got, tt.want)
+ }
+ }
+
+ haystack := "test世界"
+ allocs := testing.AllocsPerRun(1000, func() {
+ if i := IndexRune(haystack, 's'); i != 2 {
+ t.Fatalf("'s' at %d; want 2", i)
+ }
+ if i := IndexRune(haystack, '世'); i != 4 {
+ t.Fatalf("'世' at %d; want 4", i)
}
+ })
+ if runtime.Compiler == "gccgo" {
+ t.Skip("skipping allocations test for gccgo until escape analysis is enabled")
+ }
+ if allocs != 0 && testing.CoverMode() == "" {
+ t.Errorf("expected no allocations, got %f", allocs)
}
}
@@ -257,6 +314,17 @@ func BenchmarkIndexRune(b *testing.B) {
}
}
+var benchmarkLongString = Repeat(" ", 100) + benchmarkString
+
+func BenchmarkIndexRuneLongString(b *testing.B) {
+ if got := IndexRune(benchmarkLongString, '☺'); got != 114 {
+ b.Fatalf("wrong index: expected 114, got=%d", got)
+ }
+ for i := 0; i < b.N; i++ {
+ IndexRune(benchmarkLongString, '☺')
+ }
+}
+
func BenchmarkIndexRuneFastPath(b *testing.B) {
if got := IndexRune(benchmarkString, 'v'); got != 17 {
b.Fatalf("wrong index: expected 17, got=%d", got)
@@ -613,6 +681,9 @@ var trimTests = []struct {
{"Trim", "* listitem", " *", "listitem"},
{"Trim", `"quote"`, `"`, "quote"},
{"Trim", "\u2C6F\u2C6F\u0250\u0250\u2C6F\u2C6F", "\u2C6F", "\u0250\u0250"},
+ {"Trim", "\x80test\xff", "\xff", "test"},
+ {"Trim", " Ġ ", " ", "Ġ"},
+ {"Trim", " Ġİ0", "0 ", "Ġİ"},
//empty string tests
{"Trim", "abba", "", "abba"},
{"Trim", "", "123", ""},
@@ -855,6 +926,54 @@ func TestRepeat(t *testing.T) {
}
}
+func repeat(s string, count int) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ switch v := r.(type) {
+ case error:
+ err = v
+ default:
+ err = fmt.Errorf("%s", v)
+ }
+ }
+ }()
+
+ Repeat(s, count)
+
+ return
+}
+
+// See Issue golang.org/issue/16237
+func TestRepeatCatchesOverflow(t *testing.T) {
+ tests := [...]struct {
+ s string
+ count int
+ errStr string
+ }{
+ 0: {"--", -2147483647, "negative"},
+ 1: {"", int(^uint(0) >> 1), ""},
+ 2: {"-", 10, ""},
+ 3: {"gopher", 0, ""},
+ 4: {"-", -1, "negative"},
+ 5: {"--", -102, "negative"},
+ 6: {string(make([]byte, 255)), int((^uint(0))/255 + 1), "overflow"},
+ }
+
+ for i, tt := range tests {
+ err := repeat(tt.s, tt.count)
+ if tt.errStr == "" {
+ if err != nil {
+ t.Errorf("#%d panicked %v", i, err)
+ }
+ continue
+ }
+
+ if err == nil || !Contains(err.Error(), tt.errStr) {
+ t.Errorf("#%d expected %q got %q", i, tt.errStr, err)
+ }
+ }
+}
+
func runesEqual(a, b []rune) bool {
if len(a) != len(b) {
return false
@@ -1290,6 +1409,9 @@ func benchmarkCountHard(b *testing.B, sep string) {
func BenchmarkIndexHard1(b *testing.B) { benchmarkIndexHard(b, "<>") }
func BenchmarkIndexHard2(b *testing.B) { benchmarkIndexHard(b, "</pre>") }
func BenchmarkIndexHard3(b *testing.B) { benchmarkIndexHard(b, "<b>hello world</b>") }
+func BenchmarkIndexHard4(b *testing.B) {
+ benchmarkIndexHard(b, "<pre><b>hello</b><strong>world</strong></pre>")
+}
func BenchmarkLastIndexHard1(b *testing.B) { benchmarkLastIndexHard(b, "<>") }
func BenchmarkLastIndexHard2(b *testing.B) { benchmarkLastIndexHard(b, "</pre>") }
@@ -1381,3 +1503,31 @@ func BenchmarkRepeat(b *testing.B) {
Repeat("-", 80)
}
}
+
+func BenchmarkIndexAnyASCII(b *testing.B) {
+ x := Repeat("#", 4096) // Never matches set
+ cs := "0123456789abcdef"
+ for k := 1; k <= 4096; k <<= 4 {
+ for j := 1; j <= 16; j <<= 1 {
+ b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ IndexAny(x[:k], cs[:j])
+ }
+ })
+ }
+ }
+}
+
+func BenchmarkTrimASCII(b *testing.B) {
+ cs := "0123456789abcdef"
+ for k := 1; k <= 4096; k <<= 4 {
+ for j := 1; j <= 16; j <<= 1 {
+ b.Run(fmt.Sprintf("%d:%d", k, j), func(b *testing.B) {
+ x := Repeat(cs[:j], k) // Always matches set
+ for i := 0; i < b.N; i++ {
+ Trim(x[:k], cs[:j])
+ }
+ })
+ }
+ }
+}
diff --git a/libgo/go/sync/atomic/atomic.c b/libgo/go/sync/atomic/atomic.c
index f0ba57b3cca..7e04027c3f1 100644
--- a/libgo/go/sync/atomic/atomic.c
+++ b/libgo/go/sync/atomic/atomic.c
@@ -25,6 +25,8 @@ int64_t SwapInt64 (int64_t *, int64_t)
int64_t
SwapInt64 (int64_t *addr, int64_t new)
{
+ if (((uintptr_t) addr & 7) != 0)
+ addr = NULL;
return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
}
@@ -45,6 +47,8 @@ uint64_t SwapUint64 (uint64_t *, uint64_t)
uint64_t
SwapUint64 (uint64_t *addr, uint64_t new)
{
+ if (((uintptr_t) addr & 7) != 0)
+ addr = NULL;
return __atomic_exchange_n (addr, new, __ATOMIC_SEQ_CST);
}
@@ -85,6 +89,8 @@ _Bool CompareAndSwapInt64 (int64_t *, int64_t, int64_t)
_Bool
CompareAndSwapInt64 (int64_t *val, int64_t old, int64_t new)
{
+ if (((uintptr_t) val & 7) != 0)
+ val = NULL;
return __sync_bool_compare_and_swap (val, old, new);
}
@@ -105,6 +111,8 @@ _Bool CompareAndSwapUint64 (uint64_t *, uint64_t, uint64_t)
_Bool
CompareAndSwapUint64 (uint64_t *val, uint64_t old, uint64_t new)
{
+ if (((uintptr_t) val & 7) != 0)
+ val = NULL;
return __sync_bool_compare_and_swap (val, old, new);
}
@@ -155,6 +163,8 @@ int64_t AddInt64 (int64_t *, int64_t)
int64_t
AddInt64 (int64_t *val, int64_t delta)
{
+ if (((uintptr_t) val & 7) != 0)
+ val = NULL;
return __sync_add_and_fetch (val, delta);
}
@@ -165,6 +175,8 @@ uint64_t AddUint64 (uint64_t *, uint64_t)
uint64_t
AddUint64 (uint64_t *val, uint64_t delta)
{
+ if (((uintptr_t) val & 7) != 0)
+ val = NULL;
return __sync_add_and_fetch (val, delta);
}
@@ -202,6 +214,8 @@ LoadInt64 (int64_t *addr)
{
int64_t v;
+ if (((uintptr_t) addr & 7) != 0)
+ addr = NULL;
v = *addr;
while (! __sync_bool_compare_and_swap (addr, v, v))
v = *addr;
@@ -232,6 +246,8 @@ LoadUint64 (uint64_t *addr)
{
uint64_t v;
+ if (((uintptr_t) addr & 7) != 0)
+ addr = NULL;
v = *addr;
while (! __sync_bool_compare_and_swap (addr, v, v))
v = *addr;
@@ -291,6 +307,8 @@ StoreInt64 (int64_t *addr, int64_t val)
{
int64_t v;
+ if (((uintptr_t) addr & 7) != 0)
+ addr = NULL;
v = *addr;
while (! __sync_bool_compare_and_swap (addr, v, val))
v = *addr;
@@ -319,6 +337,8 @@ StoreUint64 (uint64_t *addr, uint64_t val)
{
uint64_t v;
+ if (((uintptr_t) addr & 7) != 0)
+ addr = NULL;
v = *addr;
while (! __sync_bool_compare_and_swap (addr, v, val))
v = *addr;
diff --git a/libgo/go/sync/atomic/atomic_test.go b/libgo/go/sync/atomic/atomic_test.go
index 5a33d7fac0d..6d0831c3f9d 100644
--- a/libgo/go/sync/atomic/atomic_test.go
+++ b/libgo/go/sync/atomic/atomic_test.go
@@ -1226,10 +1226,12 @@ func TestStoreLoadSeqCst32(t *testing.T) {
}
his := LoadInt32(&ack[he][i%3])
if (my != i && my != i-1) || (his != i && his != i-1) {
- t.Fatalf("invalid values: %d/%d (%d)", my, his, i)
+ t.Errorf("invalid values: %d/%d (%d)", my, his, i)
+ break
}
if my != i && his != i {
- t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
+ t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
+ break
}
StoreInt32(&ack[me][(i-1)%3], -1)
}
@@ -1269,10 +1271,12 @@ func TestStoreLoadSeqCst64(t *testing.T) {
}
his := LoadInt64(&ack[he][i%3])
if (my != i && my != i-1) || (his != i && his != i-1) {
- t.Fatalf("invalid values: %d/%d (%d)", my, his, i)
+ t.Errorf("invalid values: %d/%d (%d)", my, his, i)
+ break
}
if my != i && his != i {
- t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
+ t.Errorf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
+ break
}
StoreInt64(&ack[me][(i-1)%3], -1)
}
@@ -1317,7 +1321,8 @@ func TestStoreLoadRelAcq32(t *testing.T) {
d1 := X.data1
d2 := X.data2
if d1 != i || d2 != float32(i) {
- t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i)
+ t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i)
+ break
}
}
}
@@ -1365,7 +1370,8 @@ func TestStoreLoadRelAcq64(t *testing.T) {
d1 := X.data1
d2 := X.data2
if d1 != i || d2 != float64(i) {
- t.Fatalf("incorrect data: %d/%g (%d)", d1, d2, i)
+ t.Errorf("incorrect data: %d/%g (%d)", d1, d2, i)
+ break
}
}
}
@@ -1389,11 +1395,16 @@ func TestUnaligned64(t *testing.T) {
// Unaligned 64-bit atomics on 32-bit systems are
// a continual source of pain. Test that on 32-bit systems they crash
// instead of failing silently.
- if unsafe.Sizeof(int(0)) != 4 {
- t.Skip("test only runs on 32-bit systems")
- }
- t.Skip("skipping test for gccgo")
+ switch runtime.GOARCH {
+ default:
+ if unsafe.Sizeof(int(0)) != 4 {
+ t.Skip("test only runs on 32-bit systems")
+ }
+ case "amd64p32":
+ // amd64p32 can handle unaligned atomics.
+ t.Skipf("test not needed on %v", runtime.GOARCH)
+ }
x := make([]uint32, 4)
p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned
diff --git a/libgo/go/sync/cond_test.go b/libgo/go/sync/cond_test.go
index 7b0729571ce..9019f8f1028 100644
--- a/libgo/go/sync/cond_test.go
+++ b/libgo/go/sync/cond_test.go
@@ -137,7 +137,7 @@ func TestRace(t *testing.T) {
x = 1
c.Wait()
if x != 2 {
- t.Fatal("want 2")
+ t.Error("want 2")
}
x = 3
c.Signal()
@@ -165,7 +165,7 @@ func TestRace(t *testing.T) {
if x == 2 {
c.Wait()
if x != 3 {
- t.Fatal("want 3")
+ t.Error("want 3")
}
break
}
diff --git a/libgo/go/sync/example_pool_test.go b/libgo/go/sync/example_pool_test.go
new file mode 100644
index 00000000000..8288d41e8c0
--- /dev/null
+++ b/libgo/go/sync/example_pool_test.go
@@ -0,0 +1,45 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sync_test
+
+import (
+ "bytes"
+ "io"
+ "os"
+ "sync"
+ "time"
+)
+
+var bufPool = sync.Pool{
+ New: func() interface{} {
+ // The Pool's New function should generally only return pointer
+ // types, since a pointer can be put into the return interface
+ // value without an allocation:
+ return new(bytes.Buffer)
+ },
+}
+
+// timeNow is a fake version of time.Now for tests.
+func timeNow() time.Time {
+ return time.Unix(1136214245, 0)
+}
+
+func Log(w io.Writer, key, val string) {
+ b := bufPool.Get().(*bytes.Buffer)
+ b.Reset()
+ // Replace this with time.Now() in a real logger.
+ b.WriteString(timeNow().UTC().Format(time.RFC3339))
+ b.WriteByte(' ')
+ b.WriteString(key)
+ b.WriteByte('=')
+ b.WriteString(val)
+ w.Write(b.Bytes())
+ bufPool.Put(b)
+}
+
+func ExamplePool() {
+ Log(os.Stdout, "path", "/search?q=flowers")
+ // Output: 2006-01-02T15:04:05Z path=/search?q=flowers
+}
diff --git a/libgo/go/sync/mutex.go b/libgo/go/sync/mutex.go
index 90892793f0a..8c9366f4fe1 100644
--- a/libgo/go/sync/mutex.go
+++ b/libgo/go/sync/mutex.go
@@ -16,6 +16,8 @@ import (
"unsafe"
)
+func throw(string) // provided by runtime
+
// A Mutex is a mutual exclusion lock.
// Mutexes can be created as part of other structures;
// the zero value for a Mutex is an unlocked mutex.
@@ -74,7 +76,7 @@ func (m *Mutex) Lock() {
// The goroutine has been woken from sleep,
// so we need to reset the flag in either case.
if new&mutexWoken == 0 {
- panic("sync: inconsistent mutex state")
+ throw("sync: inconsistent mutex state")
}
new &^= mutexWoken
}
@@ -82,7 +84,7 @@ func (m *Mutex) Lock() {
if old&mutexLocked == 0 {
break
}
- runtime_Semacquire(&m.sema)
+ runtime_SemacquireMutex(&m.sema)
awoke = true
iter = 0
}
@@ -108,7 +110,7 @@ func (m *Mutex) Unlock() {
// Fast path: drop lock bit.
new := atomic.AddInt32(&m.state, -mutexLocked)
if (new+mutexLocked)&mutexLocked == 0 {
- panic("sync: unlock of unlocked mutex")
+ throw("sync: unlock of unlocked mutex")
}
old := new
diff --git a/libgo/go/sync/mutex_test.go b/libgo/go/sync/mutex_test.go
index 91a4855cb1f..88dbccf3add 100644
--- a/libgo/go/sync/mutex_test.go
+++ b/libgo/go/sync/mutex_test.go
@@ -7,7 +7,12 @@
package sync_test
import (
+ "fmt"
+ "internal/testenv"
+ "os"
+ "os/exec"
"runtime"
+ "strings"
. "sync"
"testing"
)
@@ -61,6 +66,10 @@ func HammerMutex(m *Mutex, loops int, cdone chan bool) {
}
func TestMutex(t *testing.T) {
+ if n := runtime.SetMutexProfileFraction(1); n != 0 {
+ t.Logf("got mutexrate %d expected 0", n)
+ }
+ defer runtime.SetMutexProfileFraction(0)
m := new(Mutex)
c := make(chan bool)
for i := 0; i < 10; i++ {
@@ -71,17 +80,98 @@ func TestMutex(t *testing.T) {
}
}
-func TestMutexPanic(t *testing.T) {
- defer func() {
- if recover() == nil {
- t.Fatalf("unlock of unlocked mutex did not panic")
+var misuseTests = []struct {
+ name string
+ f func()
+}{
+ {
+ "Mutex.Unlock",
+ func() {
+ var mu Mutex
+ mu.Unlock()
+ },
+ },
+ {
+ "Mutex.Unlock2",
+ func() {
+ var mu Mutex
+ mu.Lock()
+ mu.Unlock()
+ mu.Unlock()
+ },
+ },
+ {
+ "RWMutex.Unlock",
+ func() {
+ var mu RWMutex
+ mu.Unlock()
+ },
+ },
+ {
+ "RWMutex.Unlock2",
+ func() {
+ var mu RWMutex
+ mu.RLock()
+ mu.Unlock()
+ },
+ },
+ {
+ "RWMutex.Unlock3",
+ func() {
+ var mu RWMutex
+ mu.Lock()
+ mu.Unlock()
+ mu.Unlock()
+ },
+ },
+ {
+ "RWMutex.RUnlock",
+ func() {
+ var mu RWMutex
+ mu.RUnlock()
+ },
+ },
+ {
+ "RWMutex.RUnlock2",
+ func() {
+ var mu RWMutex
+ mu.Lock()
+ mu.RUnlock()
+ },
+ },
+ {
+ "RWMutex.RUnlock3",
+ func() {
+ var mu RWMutex
+ mu.RLock()
+ mu.RUnlock()
+ mu.RUnlock()
+ },
+ },
+}
+
+func init() {
+ if len(os.Args) == 3 && os.Args[1] == "TESTMISUSE" {
+ for _, test := range misuseTests {
+ if test.name == os.Args[2] {
+ test.f()
+ fmt.Printf("test completed\n")
+ os.Exit(0)
+ }
}
- }()
+ fmt.Printf("unknown test\n")
+ os.Exit(0)
+ }
+}
- var mu Mutex
- mu.Lock()
- mu.Unlock()
- mu.Unlock()
+func TestMutexMisuse(t *testing.T) {
+ testenv.MustHaveExec(t)
+ for _, test := range misuseTests {
+ out, err := exec.Command(os.Args[0], "TESTMISUSE", test.name).CombinedOutput()
+ if err == nil || !strings.Contains(string(out), "unlocked") {
+ t.Errorf("%s: did not find failure with message about unlocked lock: %s\n%s\n", test.name, err, out)
+ }
+ }
}
func BenchmarkMutexUncontended(b *testing.B) {
diff --git a/libgo/go/sync/pool.go b/libgo/go/sync/pool.go
index bf29d88c5cb..0acdbde096f 100644
--- a/libgo/go/sync/pool.go
+++ b/libgo/go/sync/pool.go
@@ -61,29 +61,49 @@ type poolLocal struct {
pad [128]byte // Prevents false sharing.
}
+// from runtime
+func fastrand() uint32
+
+var poolRaceHash [128]uint64
+
+// poolRaceAddr returns an address to use as the synchronization point
+// for race detector logic. We don't use the actual pointer stored in x
+// directly, for fear of conflicting with other synchronization on that address.
+// Instead, we hash the pointer to get an index into poolRaceHash.
+// See discussion on golang.org/cl/31589.
+func poolRaceAddr(x interface{}) unsafe.Pointer {
+ ptr := uintptr((*[2]unsafe.Pointer)(unsafe.Pointer(&x))[1])
+ h := uint32((uint64(uint32(ptr)) * 0x85ebca6b) >> 16)
+ return unsafe.Pointer(&poolRaceHash[h%uint32(len(poolRaceHash))])
+}
+
// Put adds x to the pool.
func (p *Pool) Put(x interface{}) {
- if race.Enabled {
- // Under race detector the Pool degenerates into no-op.
- // It's conforming, simple and does not introduce excessive
- // happens-before edges between unrelated goroutines.
- return
- }
if x == nil {
return
}
+ if race.Enabled {
+ if fastrand()%4 == 0 {
+ // Randomly drop x on floor.
+ return
+ }
+ race.ReleaseMerge(poolRaceAddr(x))
+ race.Disable()
+ }
l := p.pin()
if l.private == nil {
l.private = x
x = nil
}
runtime_procUnpin()
- if x == nil {
- return
+ if x != nil {
+ l.Lock()
+ l.shared = append(l.shared, x)
+ l.Unlock()
+ }
+ if race.Enabled {
+ race.Enable()
}
- l.Lock()
- l.shared = append(l.shared, x)
- l.Unlock()
}
// Get selects an arbitrary item from the Pool, removes it from the
@@ -96,29 +116,34 @@ func (p *Pool) Put(x interface{}) {
// the result of calling p.New.
func (p *Pool) Get() interface{} {
if race.Enabled {
- if p.New != nil {
- return p.New()
- }
- return nil
+ race.Disable()
}
l := p.pin()
x := l.private
l.private = nil
runtime_procUnpin()
- if x != nil {
- return x
+ if x == nil {
+ l.Lock()
+ last := len(l.shared) - 1
+ if last >= 0 {
+ x = l.shared[last]
+ l.shared = l.shared[:last]
+ }
+ l.Unlock()
+ if x == nil {
+ x = p.getSlow()
+ }
}
- l.Lock()
- last := len(l.shared) - 1
- if last >= 0 {
- x = l.shared[last]
- l.shared = l.shared[:last]
+ if race.Enabled {
+ race.Enable()
+ if x != nil {
+ race.Acquire(poolRaceAddr(x))
+ }
}
- l.Unlock()
- if x != nil {
- return x
+ if x == nil && p.New != nil {
+ x = p.New()
}
- return p.getSlow()
+ return x
}
func (p *Pool) getSlow() (x interface{}) {
@@ -140,10 +165,6 @@ func (p *Pool) getSlow() (x interface{}) {
}
l.Unlock()
}
-
- if x == nil && p.New != nil {
- x = p.New()
- }
return x
}
diff --git a/libgo/go/sync/pool_test.go b/libgo/go/sync/pool_test.go
index 051bb175338..f92e181a6b1 100644
--- a/libgo/go/sync/pool_test.go
+++ b/libgo/go/sync/pool_test.go
@@ -128,7 +128,8 @@ func TestPoolStress(t *testing.T) {
p.Put(v)
v = p.Get()
if v != nil && v.(int) != 0 {
- t.Fatalf("expect 0, got %v", v)
+ t.Errorf("expect 0, got %v", v)
+ break
}
}
done <- true
diff --git a/libgo/go/sync/runtime.go b/libgo/go/sync/runtime.go
index 96c56c85224..4d22ce6b0da 100644
--- a/libgo/go/sync/runtime.go
+++ b/libgo/go/sync/runtime.go
@@ -13,6 +13,9 @@ import "unsafe"
// library and should not be used directly.
func runtime_Semacquire(s *uint32)
+// SemacquireMutex is like Semacquire, but for profiling contended Mutexes.
+func runtime_SemacquireMutex(*uint32)
+
// Semrelease atomically increments *s and notifies a waiting goroutine
// if one is blocked in Semacquire.
// It is intended as a simple wakeup primitive for use by the synchronization
diff --git a/libgo/go/sync/rwmutex.go b/libgo/go/sync/rwmutex.go
index 6734360e37a..71064eeeba3 100644
--- a/libgo/go/sync/rwmutex.go
+++ b/libgo/go/sync/rwmutex.go
@@ -61,7 +61,7 @@ func (rw *RWMutex) RUnlock() {
if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 {
if r+1 == 0 || r+1 == -rwmutexMaxReaders {
race.Enable()
- panic("sync: RUnlock of unlocked RWMutex")
+ throw("sync: RUnlock of unlocked RWMutex")
}
// A writer is pending.
if atomic.AddInt32(&rw.readerWait, -1) == 0 {
@@ -115,7 +115,7 @@ func (rw *RWMutex) Unlock() {
r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
if r >= rwmutexMaxReaders {
race.Enable()
- panic("sync: Unlock of unlocked RWMutex")
+ throw("sync: Unlock of unlocked RWMutex")
}
// Unblock blocked readers, if any.
for i := 0; i < int(r); i++ {
diff --git a/libgo/go/sync/rwmutex_test.go b/libgo/go/sync/rwmutex_test.go
index f625bc3a585..0436f97239c 100644
--- a/libgo/go/sync/rwmutex_test.go
+++ b/libgo/go/sync/rwmutex_test.go
@@ -155,48 +155,6 @@ func TestRLocker(t *testing.T) {
}
}
-func TestUnlockPanic(t *testing.T) {
- defer func() {
- if recover() == nil {
- t.Fatalf("unlock of unlocked RWMutex did not panic")
- }
- }()
- var mu RWMutex
- mu.Unlock()
-}
-
-func TestUnlockPanic2(t *testing.T) {
- defer func() {
- if recover() == nil {
- t.Fatalf("unlock of unlocked RWMutex did not panic")
- }
- }()
- var mu RWMutex
- mu.RLock()
- mu.Unlock()
-}
-
-func TestRUnlockPanic(t *testing.T) {
- defer func() {
- if recover() == nil {
- t.Fatalf("read unlock of unlocked RWMutex did not panic")
- }
- }()
- var mu RWMutex
- mu.RUnlock()
-}
-
-func TestRUnlockPanic2(t *testing.T) {
- defer func() {
- if recover() == nil {
- t.Fatalf("read unlock of unlocked RWMutex did not panic")
- }
- }()
- var mu RWMutex
- mu.Lock()
- mu.RUnlock()
-}
-
func BenchmarkRWMutexUncontended(b *testing.B) {
type PaddedRWMutex struct {
RWMutex
diff --git a/libgo/go/syscall/const_plan9.go b/libgo/go/syscall/const_plan9.go
index ba26f123dea..063d5dfd7c2 100644
--- a/libgo/go/syscall/const_plan9.go
+++ b/libgo/go/syscall/const_plan9.go
@@ -12,6 +12,17 @@ const (
O_EXCL = 0x1000
)
+// Bind flags
+const (
+ MORDER = 0x0003 // mask for bits defining order of mounting
+ MREPL = 0x0000 // mount replaces object
+ MBEFORE = 0x0001 // mount goes before others in union directory
+ MAFTER = 0x0002 // mount goes after others in union directory
+ MCREATE = 0x0004 // permit creation in mounted directory
+ MCACHE = 0x0010 // cache some data
+ MMASK = 0x0017 // all bits on
+)
+
// Rfork flags
const (
RFNAMEG = 1 << 0
diff --git a/libgo/go/syscall/dir_plan9.go b/libgo/go/syscall/dir_plan9.go
index 15b267411cb..4ed052de761 100644
--- a/libgo/go/syscall/dir_plan9.go
+++ b/libgo/go/syscall/dir_plan9.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.
-// Plan 9 directory marshalling. See intro(5).
+// Plan 9 directory marshaling. See intro(5).
package syscall
diff --git a/libgo/go/syscall/dirent.go b/libgo/go/syscall/dirent.go
new file mode 100644
index 00000000000..4db2d4355b5
--- /dev/null
+++ b/libgo/go/syscall/dirent.go
@@ -0,0 +1,102 @@
+// 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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package syscall
+
+import "unsafe"
+
+// readInt returns the size-bytes unsigned integer in native byte order at offset off.
+func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
+ if len(b) < int(off+size) {
+ return 0, false
+ }
+ if isBigEndian {
+ return readIntBE(b[off:], size), true
+ }
+ return readIntLE(b[off:], size), true
+}
+
+func readIntBE(b []byte, size uintptr) uint64 {
+ switch size {
+ case 1:
+ return uint64(b[0])
+ case 2:
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[1]) | uint64(b[0])<<8
+ case 4:
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24
+ case 8:
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
+ uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
+ default:
+ panic("syscall: readInt with unsupported size")
+ }
+}
+
+func readIntLE(b []byte, size uintptr) uint64 {
+ switch size {
+ case 1:
+ return uint64(b[0])
+ case 2:
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8
+ case 4:
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24
+ case 8:
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
+ uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+ default:
+ panic("syscall: readInt with unsupported size")
+ }
+}
+
+// ParseDirent parses up to max directory entries in buf,
+// appending the names to names. It returns the number of
+// bytes consumed from buf, the number of entries added
+// to names, and the new names slice.
+func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
+ origlen := len(buf)
+ count = 0
+ for max != 0 && len(buf) > 0 {
+ reclen, ok := direntReclen(buf)
+ if !ok || reclen > uint64(len(buf)) {
+ return origlen, count, names
+ }
+ rec := buf[:reclen]
+ buf = buf[reclen:]
+ ino, ok := direntIno(rec)
+ if !ok {
+ break
+ }
+ if ino == 0 { // File absent in directory.
+ continue
+ }
+ const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
+ namlen, ok := direntNamlen(rec)
+ if !ok || namoff+namlen > uint64(len(rec)) {
+ break
+ }
+ name := rec[namoff : namoff+namlen]
+ for i, c := range name {
+ if c == 0 {
+ name = name[:i]
+ break
+ }
+ }
+ // Check for useless names before allocating a string.
+ if string(name) == "." || string(name) == ".." {
+ continue
+ }
+ max--
+ count++
+ names = append(names, string(name))
+ }
+ return origlen - len(buf), count, names
+}
diff --git a/libgo/go/syscall/endian_big.go b/libgo/go/syscall/endian_big.go
new file mode 100644
index 00000000000..b96594ec280
--- /dev/null
+++ b/libgo/go/syscall/endian_big.go
@@ -0,0 +1,9 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// +build ppc64 s390x mips mips64 armbe arm64be m68k ppc mipso32 mipsn32 mipso64 mipsn64 mips64p32 s390 sparc sparc64
+
+package syscall
+
+const isBigEndian = true
diff --git a/libgo/go/syscall/endian_little.go b/libgo/go/syscall/endian_little.go
new file mode 100644
index 00000000000..b6c9ed0f9f7
--- /dev/null
+++ b/libgo/go/syscall/endian_little.go
@@ -0,0 +1,9 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
+// +build 386 amd64 amd64p32 arm arm64 ppc64le mips64le mipsle alpha ia64 mips64p32le
+
+package syscall
+
+const isBigEndian = false
diff --git a/libgo/go/syscall/env_windows.go b/libgo/go/syscall/env_windows.go
index 3f751678ccb..1606b424ca0 100644
--- a/libgo/go/syscall/env_windows.go
+++ b/libgo/go/syscall/env_windows.go
@@ -60,7 +60,7 @@ func Clearenv() {
// http://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
for j := 1; j < len(s); j++ {
if s[j] == '=' {
- Setenv(s[0:j], "")
+ Unsetenv(s[0:j])
break
}
}
diff --git a/libgo/go/syscall/exec_linux.go b/libgo/go/syscall/exec_linux.go
index 83d9c1ca2db..8d6467a8720 100644
--- a/libgo/go/syscall/exec_linux.go
+++ b/libgo/go/syscall/exec_linux.go
@@ -216,11 +216,11 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
goto childerror
}
}
- _, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0)
+ _, _, err1 = RawSyscall(sys_SETGID, uintptr(cred.Gid), 0, 0)
if err1 != 0 {
goto childerror
}
- _, _, err1 = RawSyscall(SYS_SETUID, uintptr(cred.Uid), 0, 0)
+ _, _, err1 = RawSyscall(sys_SETUID, uintptr(cred.Uid), 0, 0)
if err1 != 0 {
goto childerror
}
diff --git a/libgo/go/syscall/exec_linux_test.go b/libgo/go/syscall/exec_linux_test.go
index aaffa067bcf..7a4b5717600 100644
--- a/libgo/go/syscall/exec_linux_test.go
+++ b/libgo/go/syscall/exec_linux_test.go
@@ -162,6 +162,12 @@ func TestUnshare(t *testing.T) {
t.Fatal(err)
}
+ orig, err := ioutil.ReadFile(path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ origLines := strings.Split(strings.TrimSpace(string(orig)), "\n")
+
cmd := exec.Command("cat", path)
cmd.SysProcAttr = &syscall.SysProcAttr{
Unshareflags: syscall.CLONE_NEWNET,
@@ -178,8 +184,8 @@ func TestUnshare(t *testing.T) {
}
lines := strings.Split(sout, "\n")
- if len(lines) != 3 {
- t.Fatalf("Expected 3 lines of output, got %d", len(lines))
+ if len(lines) >= len(origLines) {
+ t.Fatalf("Got %d lines of output, want <%d", len(lines), len(origLines))
}
}
diff --git a/libgo/go/syscall/exec_unix.go b/libgo/go/syscall/exec_unix.go
index 3018b43d72e..c04005cdd6e 100644
--- a/libgo/go/syscall/exec_unix.go
+++ b/libgo/go/syscall/exec_unix.go
@@ -292,7 +292,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
return pid, 0, err
}
-// Ordinary exec.
+// Exec invokes the execve(2) system call.
func Exec(argv0 string, argv []string, envv []string) (err error) {
argv0p, err := BytePtrFromString(argv0)
if err != nil {
diff --git a/libgo/go/syscall/exec_windows.go b/libgo/go/syscall/exec_windows.go
index 5a01843d2be..cafce1eff69 100644
--- a/libgo/go/syscall/exec_windows.go
+++ b/libgo/go/syscall/exec_windows.go
@@ -209,8 +209,6 @@ func joinExeDirAndFName(dir, p string) (name string, err error) {
return FullPath(d + "\\" + p)
}
}
- // we shouldn't be here
- return "", EINVAL
}
type ProcAttr struct {
diff --git a/libgo/go/syscall/libcall_linux.go b/libgo/go/syscall/libcall_linux.go
index ff81f547102..b58b2ddd6ea 100644
--- a/libgo/go/syscall/libcall_linux.go
+++ b/libgo/go/syscall/libcall_linux.go
@@ -251,27 +251,6 @@ func ReadDirent(fd int, buf []byte) (n int, err error) {
return Getdents(fd, buf)
}
-func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, newnames []string) {
- origlen := len(buf)
- count = 0
- for max != 0 && len(buf) > 0 {
- dirent := (*Dirent)(unsafe.Pointer(&buf[0]))
- buf = buf[dirent.Reclen:]
- if dirent.Ino == 0 { // File absent in directory.
- continue
- }
- bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0]))
- var name = string(bytes[0:clen(bytes[:])])
- if name == "." || name == ".." { // Useless names
- continue
- }
- max--
- count++
- names = append(names, name)
- }
- return origlen - len(buf), count, names
-}
-
//sys Getxattr(path string, attr string, dest []byte) (sz int, err error)
//getxattr(path *byte, attr *byte, buf *byte, count Size_t) Ssize_t
diff --git a/libgo/go/syscall/libcall_posix.go b/libgo/go/syscall/libcall_posix.go
index 84bbeda4127..76941c89b6f 100644
--- a/libgo/go/syscall/libcall_posix.go
+++ b/libgo/go/syscall/libcall_posix.go
@@ -226,9 +226,6 @@ func FDZero(set *FdSet) {
//sysnb Getgid() (gid int)
//getgid() Gid_t
-//sysnb Getpagesize() (pagesize int)
-//getpagesize() _C_int
-
//sysnb Getpgid(pid int) (pgid int, err error)
//getpgid(pid Pid_t) Pid_t
@@ -377,21 +374,12 @@ func Settimeofday(tv *Timeval) (err error) {
//sys Munlockall() (err error)
//munlockall() _C_int
-func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
-
-func NsecToTimespec(nsec int64) (ts Timespec) {
- ts.Sec = Timespec_sec_t(nsec / 1e9)
- ts.Nsec = Timespec_nsec_t(nsec % 1e9)
- return
+func setTimespec(sec, nsec int64) Timespec {
+ return Timespec{Sec: Timespec_sec_t(sec), Nsec: Timespec_nsec_t(nsec)}
}
-func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
-
-func NsecToTimeval(nsec int64) (tv Timeval) {
- nsec += 999 // round up to microsecond
- tv.Sec = Timeval_sec_t(nsec / 1e9)
- tv.Usec = Timeval_usec_t(nsec % 1e9 / 1e3)
- return
+func setTimeval(sec, usec int64) Timeval {
+ return Timeval{Sec: Timeval_sec_t(sec), Usec: Timeval_usec_t(usec)}
}
//sysnb Tcgetattr(fd int, p *Termios) (err error)
diff --git a/libgo/go/syscall/netlink_linux.go b/libgo/go/syscall/netlink_linux.go
index 26b30403a1a..1cda8c7704e 100644
--- a/libgo/go/syscall/netlink_linux.go
+++ b/libgo/go/syscall/netlink_linux.go
@@ -129,10 +129,11 @@ func ParseNetlinkMessage(b []byte) ([]NetlinkMessage, error) {
func netlinkMessageHeaderAndData(b []byte) (*NlMsghdr, []byte, int, error) {
h := (*NlMsghdr)(unsafe.Pointer(&b[0]))
- if int(h.Len) < NLMSG_HDRLEN || int(h.Len) > len(b) {
+ l := nlmAlignOf(int(h.Len))
+ if int(h.Len) < NLMSG_HDRLEN || l > len(b) {
return nil, nil, 0, EINVAL
}
- return h, b[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), nil
+ return h, b[NLMSG_HDRLEN:], l, nil
}
// NetlinkRouteAttr represents a netlink route attribute.
diff --git a/libgo/go/syscall/setuidgid_32_linux.go b/libgo/go/syscall/setuidgid_32_linux.go
new file mode 100644
index 00000000000..182f5d26a90
--- /dev/null
+++ b/libgo/go/syscall/setuidgid_32_linux.go
@@ -0,0 +1,13 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build 386 arm
+
+package syscall
+
+const (
+ sys_SETGID = SYS_SETGID32
+ sys_SETUID = SYS_SETUID32
+)
diff --git a/libgo/go/syscall/setuidgid_linux.go b/libgo/go/syscall/setuidgid_linux.go
new file mode 100644
index 00000000000..bf40d2d8829
--- /dev/null
+++ b/libgo/go/syscall/setuidgid_linux.go
@@ -0,0 +1,13 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build !386,!arm
+
+package syscall
+
+const (
+ sys_SETGID = SYS_SETGID
+ sys_SETUID = SYS_SETUID
+)
diff --git a/libgo/go/syscall/sockcmsg_linux.go b/libgo/go/syscall/sockcmsg_linux.go
index 5a56b25bebb..4cb9075ba8c 100644
--- a/libgo/go/syscall/sockcmsg_linux.go
+++ b/libgo/go/syscall/sockcmsg_linux.go
@@ -31,6 +31,9 @@ func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) {
if m.Header.Type != SCM_CREDENTIALS {
return nil, EINVAL
}
+ if uintptr(len(m.Data)) < unsafe.Sizeof(Ucred{}) {
+ return nil, EINVAL
+ }
ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
return &ucred, nil
}
diff --git a/libgo/go/syscall/sockcmsg_unix.go b/libgo/go/syscall/sockcmsg_unix.go
index b25f8476394..016169929b7 100644
--- a/libgo/go/syscall/sockcmsg_unix.go
+++ b/libgo/go/syscall/sockcmsg_unix.go
@@ -16,9 +16,10 @@ import (
// Round the length of a raw sockaddr up to align it properly.
func cmsgAlignOf(salen int) int {
salign := int(sizeofPtr)
- // NOTE: It seems like 64-bit Darwin and DragonFly BSD kernels
- // still require 32-bit aligned access to network subsystem.
- if darwin64Bit || dragonfly64Bit {
+ // NOTE: It seems like 64-bit Darwin, DragonFly BSD and
+ // Solaris kernels still require 32-bit aligned access to
+ // network subsystem.
+ if darwin64Bit || dragonfly64Bit || solaris64Bit {
salign = 4
}
// NOTE: Solaris always uses 32-bit alignment,
diff --git a/libgo/go/syscall/syscall.go b/libgo/go/syscall/syscall.go
index bb63e227cf9..91dfa9a0493 100644
--- a/libgo/go/syscall/syscall.go
+++ b/libgo/go/syscall/syscall.go
@@ -28,6 +28,8 @@ package syscall
import "unsafe"
+//go:generate go run mksyscall_windows.go -systemdll -output zsyscall_windows.go syscall_windows.go security_windows.go
+
// StringByteSlice converts a string to a NUL-terminated []byte,
// If s contains a NUL byte this function panics instead of
// returning an error.
@@ -97,6 +99,10 @@ func (tv *Timeval) Nano() int64 {
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
}
+// Getpagesize is provided by the runtime.
+
+func Getpagesize() int
+
// use is a no-op, but the compiler cannot see that it is.
// Calling use(p) ensures that p is kept live until that point.
// This was needed until Go 1.6 to call syscall.Syscall correctly.
diff --git a/libgo/go/syscall/syscall_darwin.go b/libgo/go/syscall/syscall_darwin.go
new file mode 100644
index 00000000000..2847d2b8e3e
--- /dev/null
+++ b/libgo/go/syscall/syscall_darwin.go
@@ -0,0 +1,19 @@
+// Copyright 2009,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 syscall
+
+import "unsafe"
+
+func direntIno(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
+}
+
+func direntReclen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
+}
+
+func direntNamlen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
+}
diff --git a/libgo/go/syscall/syscall_darwin_test.go b/libgo/go/syscall/syscall_darwin_test.go
deleted file mode 100644
index cea5636d07d..00000000000
--- a/libgo/go/syscall/syscall_darwin_test.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2016 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin
-// +build amd64 386 arm arm64
-
-package syscall_test
-
-import (
- "syscall"
- "testing"
-)
-
-func TestDarwinGettimeofday(t *testing.T) {
- tv := &syscall.Timeval{}
- if err := syscall.Gettimeofday(tv); err != nil {
- t.Fatal(err)
- }
- if tv.Sec == 0 && tv.Usec == 0 {
- t.Fatal("Sec and Usec both zero")
- }
-}
diff --git a/libgo/go/syscall/syscall_dragonfly.go b/libgo/go/syscall/syscall_dragonfly.go
new file mode 100644
index 00000000000..c2fc67f44a7
--- /dev/null
+++ b/libgo/go/syscall/syscall_dragonfly.go
@@ -0,0 +1,23 @@
+// Copyright 2009,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 syscall
+
+import "unsafe"
+
+func direntIno(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
+}
+
+func direntReclen(buf []byte) (uint64, bool) {
+ namlen, ok := direntNamlen(buf)
+ if !ok {
+ return 0, false
+ }
+ return (16 + namlen + 1 + 7) & ^uint64(7), true
+}
+
+func direntNamlen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
+}
diff --git a/libgo/go/syscall/syscall_freebsd.go b/libgo/go/syscall/syscall_freebsd.go
new file mode 100644
index 00000000000..c67550a011d
--- /dev/null
+++ b/libgo/go/syscall/syscall_freebsd.go
@@ -0,0 +1,19 @@
+// Copyright 2009,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 syscall
+
+import "unsafe"
+
+func direntIno(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
+}
+
+func direntReclen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
+}
+
+func direntNamlen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
+}
diff --git a/libgo/go/syscall/syscall_linux.go b/libgo/go/syscall/syscall_linux.go
new file mode 100644
index 00000000000..338a9717f01
--- /dev/null
+++ b/libgo/go/syscall/syscall_linux.go
@@ -0,0 +1,23 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+import "unsafe"
+
+func direntIno(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
+}
+
+func direntReclen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
+}
+
+func direntNamlen(buf []byte) (uint64, bool) {
+ reclen, ok := direntReclen(buf)
+ if !ok {
+ return 0, false
+ }
+ return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
+}
diff --git a/libgo/go/syscall/syscall_linux_mipsx.go b/libgo/go/syscall/syscall_linux_mipsx.go
new file mode 100644
index 00000000000..af319ac345f
--- /dev/null
+++ b/libgo/go/syscall/syscall_linux_mipsx.go
@@ -0,0 +1,12 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build linux
+// +build mips mipsle
+
+package syscall
+
+func (r *PtraceRegs) PC() uint64 { return uint64(r.Regs[64]) }
+
+func (r *PtraceRegs) SetPC(pc uint64) { r.Regs[64] = uint32(pc) }
diff --git a/libgo/go/syscall/syscall_linux_test.go b/libgo/go/syscall/syscall_linux_test.go
index 4cabf6c9c90..2c4d953561a 100644
--- a/libgo/go/syscall/syscall_linux_test.go
+++ b/libgo/go/syscall/syscall_linux_test.go
@@ -138,3 +138,31 @@ func deathSignalChild() {
fmt.Println("not ok")
os.Exit(1)
}
+
+func TestParseNetlinkMessage(t *testing.T) {
+ for i, b := range [][]byte{
+ {103, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 11, 0, 1, 0, 0, 0, 0, 5, 8, 0, 3,
+ 0, 8, 0, 6, 0, 0, 0, 0, 1, 63, 0, 10, 0, 69, 16, 0, 59, 39, 82, 64, 0, 64, 6, 21, 89, 127, 0, 0,
+ 1, 127, 0, 0, 1, 230, 228, 31, 144, 32, 186, 155, 211, 185, 151, 209, 179, 128, 24, 1, 86,
+ 53, 119, 0, 0, 1, 1, 8, 10, 0, 17, 234, 12, 0, 17, 189, 126, 107, 106, 108, 107, 106, 13, 10,
+ },
+ {106, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 11, 0, 1, 0, 0, 0, 0, 3, 8, 0, 3,
+ 0, 8, 0, 6, 0, 0, 0, 0, 1, 66, 0, 10, 0, 69, 0, 0, 62, 230, 255, 64, 0, 64, 6, 85, 184, 127, 0, 0,
+ 1, 127, 0, 0, 1, 237, 206, 31, 144, 73, 197, 128, 65, 250, 60, 192, 97, 128, 24, 1, 86, 253, 21, 0,
+ 0, 1, 1, 8, 10, 0, 51, 106, 89, 0, 51, 102, 198, 108, 104, 106, 108, 107, 104, 108, 107, 104, 10,
+ },
+ {102, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 11, 0, 1, 0, 0, 0, 0, 1, 8, 0, 3, 0,
+ 8, 0, 6, 0, 0, 0, 0, 1, 62, 0, 10, 0, 69, 0, 0, 58, 231, 2, 64, 0, 64, 6, 85, 185, 127, 0, 0, 1, 127,
+ 0, 0, 1, 237, 206, 31, 144, 73, 197, 128, 86, 250, 60, 192, 97, 128, 24, 1, 86, 104, 64, 0, 0, 1, 1, 8,
+ 10, 0, 52, 198, 200, 0, 51, 135, 232, 101, 115, 97, 103, 103, 10,
+ },
+ } {
+ m, err := syscall.ParseNetlinkMessage(b)
+ if err != syscall.EINVAL {
+ t.Errorf("#%d: got %v; want EINVAL", i, err)
+ }
+ if m != nil {
+ t.Errorf("#%d: got %v; want nil", i, m)
+ }
+ }
+}
diff --git a/libgo/go/syscall/syscall_netbsd.go b/libgo/go/syscall/syscall_netbsd.go
new file mode 100644
index 00000000000..c67550a011d
--- /dev/null
+++ b/libgo/go/syscall/syscall_netbsd.go
@@ -0,0 +1,19 @@
+// Copyright 2009,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 syscall
+
+import "unsafe"
+
+func direntIno(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
+}
+
+func direntReclen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
+}
+
+func direntNamlen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
+}
diff --git a/libgo/go/syscall/syscall_openbsd.go b/libgo/go/syscall/syscall_openbsd.go
new file mode 100644
index 00000000000..c67550a011d
--- /dev/null
+++ b/libgo/go/syscall/syscall_openbsd.go
@@ -0,0 +1,19 @@
+// Copyright 2009,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 syscall
+
+import "unsafe"
+
+func direntIno(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Fileno), unsafe.Sizeof(Dirent{}.Fileno))
+}
+
+func direntReclen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
+}
+
+func direntNamlen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
+}
diff --git a/libgo/go/syscall/syscall_solaris.go b/libgo/go/syscall/syscall_solaris.go
index c1919171b7d..0b2d7483e42 100644
--- a/libgo/go/syscall/syscall_solaris.go
+++ b/libgo/go/syscall/syscall_solaris.go
@@ -4,6 +4,8 @@
package syscall
+import "unsafe"
+
func (ts *Timestruc) Unix() (sec int64, nsec int64) {
return int64(ts.Sec), int64(ts.Nsec)
}
@@ -11,3 +13,19 @@ func (ts *Timestruc) Unix() (sec int64, nsec int64) {
func (ts *Timestruc) Nano() int64 {
return int64(ts.Sec)*1e9 + int64(ts.Nsec)
}
+
+func direntIno(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
+}
+
+func direntReclen(buf []byte) (uint64, bool) {
+ return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
+}
+
+func direntNamlen(buf []byte) (uint64, bool) {
+ reclen, ok := direntReclen(buf)
+ if !ok {
+ return 0, false
+ }
+ return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
+}
diff --git a/libgo/go/syscall/syscall_test.go b/libgo/go/syscall/syscall_test.go
index 0a0b8b7a26d..c3fffda2df5 100644
--- a/libgo/go/syscall/syscall_test.go
+++ b/libgo/go/syscall/syscall_test.go
@@ -8,6 +8,7 @@ import (
"fmt"
"internal/testenv"
"os"
+ "runtime"
"syscall"
"testing"
)
@@ -59,3 +60,16 @@ func TestExecErrPermutedFds(t *testing.T) {
t.Fatalf("StartProcess of invalid program returned err = nil")
}
}
+
+func TestGettimeofday(t *testing.T) {
+ if runtime.GOOS == "nacl" {
+ t.Skip("not implemented on nacl")
+ }
+ tv := &syscall.Timeval{}
+ if err := syscall.Gettimeofday(tv); err != nil {
+ t.Fatal(err)
+ }
+ if tv.Sec == 0 && tv.Usec == 0 {
+ t.Fatal("Sec and Usec both zero")
+ }
+}
diff --git a/libgo/go/syscall/syscall_unix.go b/libgo/go/syscall/syscall_unix.go
index c47050d2ad7..ddf7303df14 100644
--- a/libgo/go/syscall/syscall_unix.go
+++ b/libgo/go/syscall/syscall_unix.go
@@ -29,6 +29,7 @@ const (
darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8
dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8
netbsd32Bit = runtime.GOOS == "netbsd" && sizeofPtr == 4
+ solaris64Bit = runtime.GOOS == "solaris" && sizeofPtr == 8
)
// Do a system call. We look at the size of uintptr to see how to pass
diff --git a/libgo/go/syscall/syscall_unix_test.go b/libgo/go/syscall/syscall_unix_test.go
index 80544f33192..2f25d18bca9 100644
--- a/libgo/go/syscall/syscall_unix_test.go
+++ b/libgo/go/syscall/syscall_unix_test.go
@@ -125,15 +125,6 @@ func TestFcntlFlock(t *testing.T) {
// "-test.run=^TestPassFD$" and an environment variable used to signal
// that the test should become the child process instead.
func TestPassFD(t *testing.T) {
- switch runtime.GOOS {
- case "dragonfly":
- // TODO(jsing): Figure out why sendmsg is returning EINVAL.
- t.Skip("skipping test on dragonfly")
- case "solaris":
- // TODO(aram): Figure out why ReadMsgUnix is returning empty message.
- t.Skip("skipping test on solaris, see issue 7402")
- }
-
testenv.MustHaveExec(t)
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
diff --git a/libgo/go/syscall/timestruct.go b/libgo/go/syscall/timestruct.go
new file mode 100644
index 00000000000..49c3383b4f7
--- /dev/null
+++ b/libgo/go/syscall/timestruct.go
@@ -0,0 +1,40 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package syscall
+
+// TimespecToNsec converts a Timespec value into a number of
+// nanoseconds since the Unix epoch.
+func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
+
+// NsecToTimespec takes a number of nanoseconds since the Unix epoch
+// and returns the corresponding Timespec value.
+func NsecToTimespec(nsec int64) Timespec {
+ sec := nsec / 1e9
+ nsec = nsec % 1e9
+ if nsec < 0 {
+ nsec += 1e9
+ sec--
+ }
+ return setTimespec(sec, nsec)
+}
+
+// TimevalToNsec converts a Timeval value into a number of nanoseconds
+// since the Unix epoch.
+func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
+
+// NsecToTimeval takes a number of nanoseconds since the Unix epoch
+// and returns the corresponding Timeval value.
+func NsecToTimeval(nsec int64) Timeval {
+ nsec += 999 // round up to microsecond
+ usec := nsec % 1e9 / 1e3
+ sec := nsec / 1e9
+ if usec < 0 {
+ usec += 1e6
+ sec--
+ }
+ return setTimeval(sec, usec)
+}
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go
index 5d58b85e78a..c033ce5fecb 100644
--- a/libgo/go/testing/benchmark.go
+++ b/libgo/go/testing/benchmark.go
@@ -7,6 +7,7 @@ package testing
import (
"flag"
"fmt"
+ "internal/race"
"os"
"runtime"
"sync"
@@ -14,8 +15,8 @@ import (
"time"
)
-var matchBenchmarks = flag.String("test.bench", "", "regular expression per path component to select benchmarks to run")
-var benchTime = flag.Duration("test.benchtime", 1*time.Second, "approximate run time for each benchmark")
+var matchBenchmarks = flag.String("test.bench", "", "run only benchmarks matching `regexp`")
+var benchTime = flag.Duration("test.benchtime", 1*time.Second, "run each benchmark for duration `d`")
var benchmarkMemory = flag.Bool("test.benchmem", false, "print memory allocations for benchmarks")
// Global lock to ensure only one benchmark runs at a time.
@@ -56,7 +57,6 @@ type B struct {
missingBytes bool // one of the subbenchmarks does not have bytes set.
timerOn bool
showAllocResult bool
- hasSub bool
result BenchmarkResult
parallelism int // RunParallel creates parallelism*GOMAXPROCS goroutines
// The initial states of memStats.Mallocs and memStats.TotalAlloc.
@@ -132,6 +132,7 @@ func (b *B) runN(n int) {
// Try to get a comparable environment for each run
// by clearing garbage from previous runs.
runtime.GC()
+ b.raceErrors = -race.Errors()
b.N = n
b.parallelism = 1
b.ResetTimer()
@@ -140,6 +141,10 @@ func (b *B) runN(n int) {
b.StopTimer()
b.previousN = n
b.previousDuration = b.duration
+ b.raceErrors += race.Errors()
+ if b.raceErrors > 0 {
+ b.Errorf("race detected during execution of benchmark")
+ }
}
func min(x, y int) int {
@@ -263,10 +268,9 @@ func (b *B) launch() {
for n := 1; !b.failed && b.duration < d && n < 1e9; {
last := n
// Predict required iterations.
- if b.nsPerOp() == 0 {
- n = 1e9
- } else {
- n = int(d.Nanoseconds() / b.nsPerOp())
+ n = int(d.Nanoseconds())
+ if nsop := b.nsPerOp(); nsop != 0 {
+ n /= int(nsop)
}
// Run more iterations than we think we'll need (1.2x).
// Don't grow too fast in case we had timing errors previously.
@@ -359,10 +363,10 @@ type benchContext struct {
// An internal function but exported because it is cross-package; part of the implementation
// of the "go test" command.
func RunBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) {
- runBenchmarksInternal(matchString, benchmarks)
+ runBenchmarks(matchString, benchmarks)
}
-func runBenchmarksInternal(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) bool {
+func runBenchmarks(matchString func(pat, str string) (bool, error), benchmarks []InternalBenchmark) bool {
// If no flag was specified, don't run benchmarks.
if len(*matchBenchmarks) == 0 {
return true
diff --git a/libgo/go/testing/example.go b/libgo/go/testing/example.go
index fd8343f3bfc..e5bce7af4e7 100644
--- a/libgo/go/testing/example.go
+++ b/libgo/go/testing/example.go
@@ -21,7 +21,14 @@ type InternalExample struct {
Unordered bool
}
+// An internal function but exported because it is cross-package; part of the implementation
+// of the "go test" command.
func RunExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ok bool) {
+ _, ok = runExamples(matchString, examples)
+ return ok
+}
+
+func runExamples(matchString func(pat, str string) (bool, error), examples []InternalExample) (ran, ok bool) {
ok = true
var eg InternalExample
@@ -35,12 +42,13 @@ func RunExamples(matchString func(pat, str string) (bool, error), examples []Int
if !matched {
continue
}
+ ran = true
if !runExample(eg) {
ok = false
}
}
- return
+ return ran, ok
}
func sortLines(output string) string {
diff --git a/libgo/go/testing/internal/testdeps/deps.go b/libgo/go/testing/internal/testdeps/deps.go
new file mode 100644
index 00000000000..b08300b5d60
--- /dev/null
+++ b/libgo/go/testing/internal/testdeps/deps.go
@@ -0,0 +1,51 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package testdeps provides access to dependencies needed by test execution.
+//
+// This package is imported by the generated main package, which passes
+// TestDeps into testing.Main. This allows tests to use packages at run time
+// without making those packages direct dependencies of package testing.
+// Direct dependencies of package testing are harder to write tests for.
+package testdeps
+
+import (
+ "io"
+ "regexp"
+ "runtime/pprof"
+)
+
+// TestDeps is an implementation of the testing.testDeps interface,
+// suitable for passing to testing.MainStart.
+type TestDeps struct{}
+
+var matchPat string
+var matchRe *regexp.Regexp
+
+func (TestDeps) 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
+}
+
+func (TestDeps) StartCPUProfile(w io.Writer) error {
+ return pprof.StartCPUProfile(w)
+}
+
+func (TestDeps) StopCPUProfile() {
+ pprof.StopCPUProfile()
+}
+
+func (TestDeps) WriteHeapProfile(w io.Writer) error {
+ return pprof.WriteHeapProfile(w)
+}
+
+func (TestDeps) WriteProfileTo(name string, w io.Writer, debug int) error {
+ return pprof.Lookup(name).WriteTo(w, debug)
+}
diff --git a/libgo/go/testing/quick/quick.go b/libgo/go/testing/quick/quick.go
index 798d41aa7d1..95860fda0fb 100644
--- a/libgo/go/testing/quick/quick.go
+++ b/libgo/go/testing/quick/quick.go
@@ -3,6 +3,8 @@
// license that can be found in the LICENSE file.
// Package quick implements utility functions to help with black box testing.
+//
+// The testing/quick package is frozen and is not accepting new features.
package quick
import (
diff --git a/libgo/go/testing/sub_test.go b/libgo/go/testing/sub_test.go
index 2a24aaacfd7..8d5d9206f03 100644
--- a/libgo/go/testing/sub_test.go
+++ b/libgo/go/testing/sub_test.go
@@ -357,7 +357,7 @@ func TestTRun(t *T) {
want := strings.TrimSpace(tc.output)
re := makeRegexp(want)
if ok, err := regexp.MatchString(re, got); !ok || err != nil {
- t.Errorf("%s:ouput:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
+ t.Errorf("%s:output:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
}
}
}
@@ -498,7 +498,7 @@ func TestBRun(t *T) {
want := strings.TrimSpace(tc.output)
re := makeRegexp(want)
if ok, err := regexp.MatchString(re, got); !ok || err != nil {
- t.Errorf("%s:ouput:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
+ t.Errorf("%s:output:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
}
}
}
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index 5a3a9aba218..8364c8e4144 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -137,13 +137,17 @@
// of the top-level test and the sequence of names passed to Run, separated by
// slashes, with an optional trailing sequence number for disambiguation.
//
-// The argument to the -run and -bench command-line flags is a slash-separated
-// list of regular expressions that match each name element in turn.
-// For example:
+// The argument to the -run and -bench command-line flags is an unanchored regular
+// expression that matches the test's name. For tests with multiple slash-separated
+// elements, such as subtests, the argument is itself slash-separated, with
+// expressions matching each name element in turn. Because it is unanchored, an
+// empty expression matches any string.
+// For example, using "matching" to mean "whose name contains":
//
-// go test -run Foo # Run top-level tests matching "Foo".
-// go test -run Foo/A= # Run subtests of Foo matching "A=".
-// go test -run /A=1 # Run all subtests of a top-level test matching "A=1".
+// go test -run '' # Run all tests.
+// go test -run Foo # Run top-level tests matching "Foo", such as "TestFooBar".
+// go test -run Foo/A= # For top-level tests matching "Foo", run subtests matching "A=".
+// go test -run /A=1 # For all top-level tests, run subtests matching "A=1".
//
// Subtests can also be used to control parallelism. A parent test will only
// complete once all of its subtests complete. In this example, all tests are
@@ -192,7 +196,7 @@
// A simple implementation of TestMain is:
//
// func TestMain(m *testing.M) {
-// flag.Parse()
+// // call flag.Parse() here if TestMain uses flags
// os.Exit(m.Run())
// }
//
@@ -200,13 +204,15 @@ package testing
import (
"bytes"
+ "errors"
"flag"
"fmt"
+ "internal/race"
"io"
"os"
"runtime"
"runtime/debug"
- "runtime/pprof"
+ "runtime/trace"
"strconv"
"strings"
"sync"
@@ -225,22 +231,24 @@ var (
// "go test", the binary always runs in the source directory for the package;
// this flag lets "go test" tell the binary to write the files in the directory where
// the "go test" command is run.
- outputDir = flag.String("test.outputdir", "", "directory in which to write profiles")
+ outputDir = flag.String("test.outputdir", "", "write profiles to `dir`")
// Report as tests are run; default is silent for success.
- chatty = flag.Bool("test.v", false, "verbose: print additional output")
- count = flag.Uint("test.count", 1, "run tests and benchmarks `n` times")
- coverProfile = flag.String("test.coverprofile", "", "write a coverage profile to the named file after execution")
- match = flag.String("test.run", "", "regular expression to select tests and examples to run")
- memProfile = flag.String("test.memprofile", "", "write a memory profile to the named file after execution")
- memProfileRate = flag.Int("test.memprofilerate", 0, "if >=0, sets runtime.MemProfileRate")
- cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
- blockProfile = flag.String("test.blockprofile", "", "write a goroutine blocking profile to the named file after execution")
- blockProfileRate = flag.Int("test.blockprofilerate", 1, "if >= 0, calls runtime.SetBlockProfileRate()")
- traceFile = flag.String("test.trace", "", "write an execution trace to the named file after execution")
- timeout = flag.Duration("test.timeout", 0, "if positive, sets an aggregate time limit for all tests")
- cpuListStr = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
- parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
+ chatty = flag.Bool("test.v", false, "verbose: print additional output")
+ count = flag.Uint("test.count", 1, "run tests and benchmarks `n` times")
+ coverProfile = flag.String("test.coverprofile", "", "write a coverage profile to `file`")
+ match = flag.String("test.run", "", "run only tests and examples matching `regexp`")
+ memProfile = flag.String("test.memprofile", "", "write a memory profile to `file`")
+ memProfileRate = flag.Int("test.memprofilerate", 0, "set memory profiling `rate` (see runtime.MemProfileRate)")
+ cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to `file`")
+ blockProfile = flag.String("test.blockprofile", "", "write a goroutine blocking profile to `file`")
+ blockProfileRate = flag.Int("test.blockprofilerate", 1, "set blocking profile `rate` (see runtime.SetBlockProfileRate)")
+ mutexProfile = flag.String("test.mutexprofile", "", "write a mutex contention profile to the named file after execution")
+ mutexProfileFraction = flag.Int("test.mutexprofilefraction", 1, "if >= 0, calls runtime.SetMutexProfileFraction()")
+ traceFile = flag.String("test.trace", "", "write an execution trace to `file`")
+ timeout = flag.Duration("test.timeout", 0, "fail test binary execution after duration `d` (0 means unlimited)")
+ cpuListStr = flag.String("test.cpu", "", "comma-separated `list` of cpu counts to run each test with")
+ parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "run at most `n` tests in parallel")
haveExamples bool // are there examples?
@@ -250,14 +258,17 @@ var (
// common holds the elements common between T and B and
// captures common methods such as Errorf.
type common struct {
- mu sync.RWMutex // guards output, failed, and done.
- output []byte // Output generated by test or benchmark.
- w io.Writer // For flushToParent.
- chatty bool // A copy of the chatty flag.
- failed bool // Test or benchmark has failed.
- skipped bool // Test of benchmark has been skipped.
- finished bool // Test function has completed.
- done bool // Test is finished and all subtests have completed.
+ mu sync.RWMutex // guards output, failed, and done.
+ output []byte // Output generated by test or benchmark.
+ w io.Writer // For flushToParent.
+ chatty bool // A copy of the chatty flag.
+ ran bool // Test or benchmark (or one of its subtests) was executed.
+ failed bool // Test or benchmark has failed.
+ skipped bool // Test of benchmark has been skipped.
+ finished bool // Test function has completed.
+ done bool // Test is finished and all subtests have completed.
+ hasSub bool
+ raceErrors int // number of races detected during test
parent *common
level int // Nesting depth of test or benchmark.
@@ -274,6 +285,13 @@ func Short() bool {
return *short
}
+// CoverMode reports what the test coverage mode is set to. The
+// values are "set", "count", or "atomic". The return value will be
+// empty if test coverage is not enabled.
+func CoverMode() string {
+ return cover.Mode
+}
+
// Verbose reports whether the -test.v flag is set.
func Verbose() bool {
return *chatty
@@ -367,6 +385,7 @@ type TB interface {
Fatalf(format string, args ...interface{})
Log(args ...interface{})
Logf(format string, args ...interface{})
+ Name() string
Skip(args ...interface{})
SkipNow()
Skipf(format string, args ...interface{})
@@ -399,6 +418,20 @@ type T struct {
func (c *common) private() {}
+// Name returns the name of the running test or benchmark.
+func (c *common) Name() string {
+ return c.name
+}
+
+func (c *common) setRan() {
+ if c.parent != nil {
+ c.parent.setRan()
+ }
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ c.ran = true
+}
+
// Fail marks the function as having failed but continues execution.
func (c *common) Fail() {
if c.parent != nil {
@@ -465,10 +498,11 @@ func (c *common) log(s string) {
// printed to avoid having performance depend on the value of the -test.v flag.
func (c *common) Log(args ...interface{}) { c.log(fmt.Sprintln(args...)) }
-// Logf formats its arguments according to the format, analogous to Printf,
-// and records the text in the error log. For tests, the text will be printed only if
-// the test fails or the -test.v flag is set. For benchmarks, the text is always
-// printed to avoid having performance depend on the value of the -test.v flag.
+// Logf formats its arguments according to the format, analogous to Printf, and
+// records the text in the error log. A final newline is added if not provided. For
+// tests, the text will be printed only if the test fails or the -test.v flag is
+// set. For benchmarks, the text is always printed to avoid having performance
+// depend on the value of the -test.v flag.
func (c *common) Logf(format string, args ...interface{}) { c.log(fmt.Sprintf(format, args...)) }
// Error is equivalent to Log followed by Fail.
@@ -508,6 +542,8 @@ func (c *common) Skipf(format string, args ...interface{}) {
}
// SkipNow marks the test as having been skipped and stops its execution.
+// If a test fails (see Error, Errorf, Fail) and is then skipped,
+// it is still considered to have failed.
// Execution will continue at the next test or benchmark. See also FailNow.
// SkipNow must be called from the goroutine running the test, not from
// other goroutines created during the test. Calling SkipNow does not stop
@@ -546,11 +582,13 @@ func (t *T) Parallel() {
// Add to the list of tests to be released by the parent.
t.parent.sub = append(t.parent.sub, t)
+ t.raceErrors += race.Errors()
t.signal <- true // Release calling test.
<-t.parent.barrier // Wait for the parent test to complete.
t.context.waitParallel()
t.start = time.Now()
+ t.raceErrors += -race.Errors()
}
// An internal type but exported because it is cross-package; part of the implementation
@@ -566,6 +604,11 @@ func tRunner(t *T, fn func(t *T)) {
// a call to runtime.Goexit, record the duration and send
// a signal saying that the test is done.
defer func() {
+ t.raceErrors += race.Errors()
+ if t.raceErrors > 0 {
+ t.Errorf("race detected during execution of test")
+ }
+
t.duration += time.Now().Sub(t.start)
// If the test panicked, print any test output before dying.
err := recover()
@@ -602,10 +645,14 @@ func tRunner(t *T, fn func(t *T)) {
// Do not lock t.done to allow race detector to detect race in case
// the user does not appropriately synchronizes a goroutine.
t.done = true
+ if t.parent != nil && !t.hasSub {
+ t.setRan()
+ }
t.signal <- true
}()
t.start = time.Now()
+ t.raceErrors = -race.Errors()
fn(t)
t.finished = true
}
@@ -613,6 +660,7 @@ func tRunner(t *T, fn func(t *T)) {
// Run runs f as a subtest of t called name. It reports whether f succeeded.
// Run will block until all its parallel subtests have completed.
func (t *T) Run(name string, f func(t *T)) bool {
+ t.hasSub = true
testName, ok := t.context.match.fullName(&t.common, name)
if !ok {
return true
@@ -701,29 +749,57 @@ func (c *testContext) release() {
c.startParallel <- true // Pick a waiting test to be run.
}
-// An internal function but exported because it is cross-package; part of the implementation
-// of the "go test" command.
+// No one should be using func Main anymore.
+// See the doc comment on func Main and use MainStart instead.
+var errMain = errors.New("testing: unexpected use of func Main")
+
+type matchStringOnly func(pat, str string) (bool, error)
+
+func (f matchStringOnly) MatchString(pat, str string) (bool, error) { return f(pat, str) }
+func (f matchStringOnly) StartCPUProfile(w io.Writer) error { return errMain }
+func (f matchStringOnly) StopCPUProfile() {}
+func (f matchStringOnly) WriteHeapProfile(w io.Writer) error { return errMain }
+func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return errMain }
+
+// Main is an internal function, part of the implementation of the "go test" command.
+// It was exported because it is cross-package and predates "internal" packages.
+// It is no longer used by "go test" but preserved, as much as possible, for other
+// systems that simulate "go test" using Main, but Main sometimes cannot be updated as
+// new functionality is added to the testing package.
+// Systems simulating "go test" should be updated to use MainStart.
func Main(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
- os.Exit(MainStart(matchString, tests, benchmarks, examples).Run())
+ os.Exit(MainStart(matchStringOnly(matchString), tests, benchmarks, examples).Run())
}
// M is a type passed to a TestMain function to run the actual tests.
type M struct {
- matchString func(pat, str string) (bool, error)
- tests []InternalTest
- benchmarks []InternalBenchmark
- examples []InternalExample
+ deps testDeps
+ tests []InternalTest
+ benchmarks []InternalBenchmark
+ examples []InternalExample
+}
+
+// testDeps is an internal interface of functionality that is
+// passed into this package by a test's generated main package.
+// The canonical implementation of this interface is
+// testing/internal/testdeps's TestDeps.
+type testDeps interface {
+ MatchString(pat, str string) (bool, error)
+ StartCPUProfile(io.Writer) error
+ StopCPUProfile()
+ WriteHeapProfile(io.Writer) error
+ WriteProfileTo(string, io.Writer, int) error
}
// MainStart is meant for use by tests generated by 'go test'.
// It is not meant to be called directly and is not subject to the Go 1 compatibility document.
// It may change signature from release to release.
-func MainStart(matchString func(pat, str string) (bool, error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
+func MainStart(deps testDeps, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M {
return &M{
- matchString: matchString,
- tests: tests,
- benchmarks: benchmarks,
- examples: examples,
+ deps: deps,
+ tests: tests,
+ benchmarks: benchmarks,
+ examples: examples,
}
}
@@ -736,19 +812,22 @@ func (m *M) Run() int {
parseCpuList()
- before()
+ m.before()
startAlarm()
haveExamples = len(m.examples) > 0
- testOk := RunTests(m.matchString, m.tests)
- exampleOk := RunExamples(m.matchString, m.examples)
- stopAlarm()
- if !testOk || !exampleOk || !runBenchmarksInternal(m.matchString, m.benchmarks) {
+ testRan, testOk := runTests(m.deps.MatchString, m.tests)
+ exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples)
+ if !testRan && !exampleRan && *matchBenchmarks == "" {
+ fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
+ }
+ if !testOk || !exampleOk || !runBenchmarks(m.deps.MatchString, m.benchmarks) || race.Errors() > 0 {
fmt.Println("FAIL")
- after()
+ m.after()
return 1
}
+
fmt.Println("PASS")
- after()
+ m.after()
return 0
}
@@ -769,12 +848,18 @@ func (t *T) report() {
}
}
+// An internal function but exported because it is cross-package; part of the implementation
+// of the "go test" command.
func RunTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ok bool) {
- ok = true
- if len(tests) == 0 && !haveExamples {
+ ran, ok := runTests(matchString, tests)
+ if !ran && !haveExamples {
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
- return
}
+ return ok
+}
+
+func runTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ran, ok bool) {
+ ok = true
for _, procs := range cpuList {
runtime.GOMAXPROCS(procs)
ctx := newTestContext(*parallel, newMatcher(matchString, *match, "-test.run"))
@@ -797,23 +882,24 @@ func RunTests(matchString func(pat, str string) (bool, error), tests []InternalT
go func() { <-t.signal }()
})
ok = ok && !t.Failed()
+ ran = ran || t.ran
}
- return
+ return ran, ok
}
// before runs before all testing.
-func before() {
+func (m *M) before() {
if *memProfileRate > 0 {
runtime.MemProfileRate = *memProfileRate
}
if *cpuProfile != "" {
f, err := os.Create(toOutputDir(*cpuProfile))
if err != nil {
- fmt.Fprintf(os.Stderr, "testing: %s", err)
+ fmt.Fprintf(os.Stderr, "testing: %s\n", err)
return
}
- if err := pprof.StartCPUProfile(f); err != nil {
- fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s", err)
+ if err := m.deps.StartCPUProfile(f); err != nil {
+ fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s\n", err)
f.Close()
return
}
@@ -822,22 +908,22 @@ func before() {
if *traceFile != "" {
f, err := os.Create(toOutputDir(*traceFile))
if err != nil {
- fmt.Fprintf(os.Stderr, "testing: %s", err)
+ fmt.Fprintf(os.Stderr, "testing: %s\n", err)
+ return
+ }
+ if err := trace.Start(f); err != nil {
+ fmt.Fprintf(os.Stderr, "testing: can't start tracing: %s\n", err)
+ f.Close()
return
}
- /*
- if err := trace.Start(f); err != nil {
- fmt.Fprintf(os.Stderr, "testing: can't start tracing: %s", err)
- f.Close()
- return
- }
- */
- _ = f
// Could save f so after can call f.Close; not worth the effort.
}
if *blockProfile != "" && *blockProfileRate >= 0 {
runtime.SetBlockProfileRate(*blockProfileRate)
}
+ if *mutexProfile != "" && *mutexProfileFraction >= 0 {
+ runtime.SetMutexProfileFraction(*mutexProfileFraction)
+ }
if *coverProfile != "" && cover.Mode == "" {
fmt.Fprintf(os.Stderr, "testing: cannot use -test.coverprofile because test binary was not built with coverage enabled\n")
os.Exit(2)
@@ -845,14 +931,12 @@ func before() {
}
// after runs after all testing.
-func after() {
+func (m *M) after() {
if *cpuProfile != "" {
- pprof.StopCPUProfile() // flushes profile to disk
+ m.deps.StopCPUProfile() // flushes profile to disk
}
if *traceFile != "" {
- /*
- trace.Stop() // flushes trace to disk
- */
+ // trace.Stop() // flushes trace to disk
}
if *memProfile != "" {
f, err := os.Create(toOutputDir(*memProfile))
@@ -861,7 +945,7 @@ func after() {
os.Exit(2)
}
runtime.GC() // materialize all statistics
- if err = pprof.WriteHeapProfile(f); err != nil {
+ if err = m.deps.WriteHeapProfile(f); err != nil {
fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *memProfile, err)
os.Exit(2)
}
@@ -873,7 +957,19 @@ func after() {
fmt.Fprintf(os.Stderr, "testing: %s\n", err)
os.Exit(2)
}
- if err = pprof.Lookup("block").WriteTo(f, 0); err != nil {
+ if err = m.deps.WriteProfileTo("block", f, 0); err != nil {
+ fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *blockProfile, err)
+ os.Exit(2)
+ }
+ f.Close()
+ }
+ if *mutexProfile != "" && *mutexProfileFraction >= 0 {
+ f, err := os.Create(toOutputDir(*mutexProfile))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "testing: %s\n", err)
+ os.Exit(2)
+ }
+ if err = m.deps.WriteProfileTo("mutex", f, 0); err != nil {
fmt.Fprintf(os.Stderr, "testing: can't write %s: %s\n", *blockProfile, err)
os.Exit(2)
}
diff --git a/libgo/go/text/tabwriter/tabwriter.go b/libgo/go/text/tabwriter/tabwriter.go
index 796e1e86995..752c9b8e9fb 100644
--- a/libgo/go/text/tabwriter/tabwriter.go
+++ b/libgo/go/text/tabwriter/tabwriter.go
@@ -8,6 +8,7 @@
// The package is using the Elastic Tabstops algorithm described at
// http://nickgravgaard.com/elastictabstops/index.html.
//
+// The text/tabwriter package is frozen and is not accepting new features.
package tabwriter
import (
diff --git a/libgo/go/text/template/exec.go b/libgo/go/text/template/exec.go
index c7c6d504900..89d3e379b4b 100644
--- a/libgo/go/text/template/exec.go
+++ b/libgo/go/text/template/exec.go
@@ -173,20 +173,26 @@ func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{})
// execution stops, but partial results may already have been written to
// the output writer.
// A template may be executed safely in parallel.
+//
+// If data is a reflect.Value, the template applies to the concrete
+// value that the reflect.Value holds, as in fmt.Print.
func (t *Template) Execute(wr io.Writer, data interface{}) error {
return t.execute(wr, data)
}
func (t *Template) execute(wr io.Writer, data interface{}) (err error) {
defer errRecover(&err)
- value := reflect.ValueOf(data)
+ value, ok := data.(reflect.Value)
+ if !ok {
+ value = reflect.ValueOf(data)
+ }
state := &state{
tmpl: t,
wr: wr,
vars: []variable{{"$", value}},
}
if t.Tree == nil || t.Root == nil {
- state.errorf("%q is an incomplete or empty template%s", t.Name(), t.DefinedTemplates())
+ state.errorf("%q is an incomplete or empty template", t.Name())
}
state.walk(value, t.Root)
return
@@ -537,6 +543,9 @@ func (s *state) evalFunction(dot reflect.Value, node *parse.IdentifierNode, cmd
// value of the pipeline, if any.
func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value {
if !receiver.IsValid() {
+ if s.tmpl.option.missingKey == mapError { // Treat invalid value as missing map key.
+ s.errorf("nil data; no entry for key %q", fieldName)
+ }
return zero
}
typ := receiver.Type()
@@ -598,8 +607,9 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
}
var (
- errorType = reflect.TypeOf((*error)(nil)).Elem()
- fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
+ errorType = reflect.TypeOf((*error)(nil)).Elem()
+ fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
+ reflectValueType = reflect.TypeOf((*reflect.Value)(nil)).Elem()
)
// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
@@ -663,7 +673,11 @@ func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, a
s.at(node)
s.errorf("error calling %s: %s", name, result[1].Interface().(error))
}
- return result[0]
+ v := result[0]
+ if v.Type() == reflectValueType {
+ v = v.Interface().(reflect.Value)
+ }
+ return v
}
// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
@@ -671,6 +685,8 @@ func canBeNil(typ reflect.Type) bool {
switch typ.Kind() {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
return true
+ case reflect.Struct:
+ return typ == reflectValueType
}
return false
}
@@ -684,6 +700,9 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu
}
s.errorf("invalid value; expected %s", typ)
}
+ if typ == reflectValueType && value.Type() != typ {
+ return reflect.ValueOf(value)
+ }
if typ != nil && !value.Type().AssignableTo(typ) {
if value.Kind() == reflect.Interface && !value.IsNil() {
value = value.Elem()
@@ -745,6 +764,10 @@ func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) refle
if typ.NumMethod() == 0 {
return s.evalEmptyInterface(dot, n)
}
+ case reflect.Struct:
+ if typ == reflectValueType {
+ return reflect.ValueOf(s.evalEmptyInterface(dot, n))
+ }
case reflect.String:
return s.evalString(typ, n)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
@@ -856,6 +879,20 @@ func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
return v, false
}
+// indirectInterface returns the concrete value in an interface value,
+// or else the zero reflect.Value.
+// That is, if v represents the interface value x, the result is the same as reflect.ValueOf(x):
+// the fact that x was an interface value is forgotten.
+func indirectInterface(v reflect.Value) reflect.Value {
+ if v.Kind() != reflect.Interface {
+ return v
+ }
+ if v.IsNil() {
+ return reflect.Value{}
+ }
+ return v.Elem()
+}
+
// printValue writes the textual representation of the value to the output of
// the template.
func (s *state) printValue(n parse.Node, v reflect.Value) {
diff --git a/libgo/go/text/template/exec_test.go b/libgo/go/text/template/exec_test.go
index 3ef065edcfd..5892b27391b 100644
--- a/libgo/go/text/template/exec_test.go
+++ b/libgo/go/text/template/exec_test.go
@@ -932,7 +932,7 @@ func TestMessageForExecuteEmpty(t *testing.T) {
t.Fatal("expected second error")
}
got = err.Error()
- want = `template: empty: "empty" is an incomplete or empty template; defined templates are: "secondary"`
+ want = `template: empty: "empty" is an incomplete or empty template`
if got != want {
t.Errorf("expected error %s got %s", want, got)
}
@@ -1142,6 +1142,12 @@ func TestMissingMapKey(t *testing.T) {
if err == nil {
t.Errorf("expected error; got none")
}
+ // same Option, but now a nil interface: ask for an error
+ err = tmpl.Execute(&b, nil)
+ t.Log(err)
+ if err == nil {
+ t.Errorf("expected error for nil-interface; got none")
+ }
}
// Test that the error message for multiline unterminated string
@@ -1152,7 +1158,7 @@ func TestUnterminatedStringError(t *testing.T) {
t.Fatal("expected error")
}
str := err.Error()
- if !strings.Contains(str, "X:3: unexpected unterminated raw quoted strin") {
+ if !strings.Contains(str, "X:3: unexpected unterminated raw quoted string") {
t.Fatalf("unexpected error: %s", str)
}
}
@@ -1310,3 +1316,99 @@ func TestMaxExecDepth(t *testing.T) {
t.Errorf("got error %q; want %q", got, want)
}
}
+
+func TestAddrOfIndex(t *testing.T) {
+ // golang.org/issue/14916.
+ // Before index worked on reflect.Values, the .String could not be
+ // found on the (incorrectly unaddressable) V value,
+ // in contrast to range, which worked fine.
+ // Also testing that passing a reflect.Value to tmpl.Execute works.
+ texts := []string{
+ `{{range .}}{{.String}}{{end}}`,
+ `{{with index . 0}}{{.String}}{{end}}`,
+ }
+ for _, text := range texts {
+ tmpl := Must(New("tmpl").Parse(text))
+ var buf bytes.Buffer
+ err := tmpl.Execute(&buf, reflect.ValueOf([]V{{1}}))
+ if err != nil {
+ t.Fatalf("%s: Execute: %v", text, err)
+ }
+ if buf.String() != "<1>" {
+ t.Fatalf("%s: template output = %q, want %q", text, &buf, "<1>")
+ }
+ }
+}
+
+func TestInterfaceValues(t *testing.T) {
+ // golang.org/issue/17714.
+ // Before index worked on reflect.Values, interface values
+ // were always implicitly promoted to the underlying value,
+ // except that nil interfaces were promoted to the zero reflect.Value.
+ // Eliminating a round trip to interface{} and back to reflect.Value
+ // eliminated this promotion, breaking these cases.
+ tests := []struct {
+ text string
+ out string
+ }{
+ {`{{index .Nil 1}}`, "ERROR: index of untyped nil"},
+ {`{{index .Slice 2}}`, "2"},
+ {`{{index .Slice .Two}}`, "2"},
+ {`{{call .Nil 1}}`, "ERROR: call of nil"},
+ {`{{call .PlusOne 1}}`, "2"},
+ {`{{call .PlusOne .One}}`, "2"},
+ {`{{and (index .Slice 0) true}}`, "0"},
+ {`{{and .Zero true}}`, "0"},
+ {`{{and (index .Slice 1) false}}`, "false"},
+ {`{{and .One false}}`, "false"},
+ {`{{or (index .Slice 0) false}}`, "false"},
+ {`{{or .Zero false}}`, "false"},
+ {`{{or (index .Slice 1) true}}`, "1"},
+ {`{{or .One true}}`, "1"},
+ {`{{not (index .Slice 0)}}`, "true"},
+ {`{{not .Zero}}`, "true"},
+ {`{{not (index .Slice 1)}}`, "false"},
+ {`{{not .One}}`, "false"},
+ {`{{eq (index .Slice 0) .Zero}}`, "true"},
+ {`{{eq (index .Slice 1) .One}}`, "true"},
+ {`{{ne (index .Slice 0) .Zero}}`, "false"},
+ {`{{ne (index .Slice 1) .One}}`, "false"},
+ {`{{ge (index .Slice 0) .One}}`, "false"},
+ {`{{ge (index .Slice 1) .Zero}}`, "true"},
+ {`{{gt (index .Slice 0) .One}}`, "false"},
+ {`{{gt (index .Slice 1) .Zero}}`, "true"},
+ {`{{le (index .Slice 0) .One}}`, "true"},
+ {`{{le (index .Slice 1) .Zero}}`, "false"},
+ {`{{lt (index .Slice 0) .One}}`, "true"},
+ {`{{lt (index .Slice 1) .Zero}}`, "false"},
+ }
+
+ for _, tt := range tests {
+ tmpl := Must(New("tmpl").Parse(tt.text))
+ var buf bytes.Buffer
+ err := tmpl.Execute(&buf, map[string]interface{}{
+ "PlusOne": func(n int) int {
+ return n + 1
+ },
+ "Slice": []int{0, 1, 2, 3},
+ "One": 1,
+ "Two": 2,
+ "Nil": nil,
+ "Zero": 0,
+ })
+ if strings.HasPrefix(tt.out, "ERROR:") {
+ e := strings.TrimSpace(strings.TrimPrefix(tt.out, "ERROR:"))
+ if err == nil || !strings.Contains(err.Error(), e) {
+ t.Errorf("%s: Execute: %v, want error %q", tt.text, err, e)
+ }
+ continue
+ }
+ if err != nil {
+ t.Errorf("%s: Execute: %v", tt.text, err)
+ continue
+ }
+ if buf.String() != tt.out {
+ t.Errorf("%s: template output = %q, want %q", tt.text, &buf, tt.out)
+ }
+ }
+}
diff --git a/libgo/go/text/template/funcs.go b/libgo/go/text/template/funcs.go
index cd0b82b243d..3047b272e57 100644
--- a/libgo/go/text/template/funcs.go
+++ b/libgo/go/text/template/funcs.go
@@ -21,6 +21,12 @@ import (
// which the second has type error. In that case, if the second (error)
// return value evaluates to non-nil during execution, execution terminates and
// Execute returns that error.
+//
+// When template execution invokes a function with an argument list, that list
+// must be assignable to the function's parameter types. Functions meant to
+// apply to arguments of arbitrary type can use parameters of type interface{} or
+// of type reflect.Value. Similarly, functions meant to return a result of arbitrary
+// type can return interface{} or reflect.Value.
type FuncMap map[string]interface{}
var builtins = FuncMap{
@@ -144,16 +150,16 @@ func prepareArg(value reflect.Value, argType reflect.Type) (reflect.Value, error
// index returns the result of indexing its first argument by the following
// arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
// indexed item must be a map, slice, or array.
-func index(item interface{}, indices ...interface{}) (interface{}, error) {
- v := reflect.ValueOf(item)
+func index(item reflect.Value, indices ...reflect.Value) (reflect.Value, error) {
+ v := indirectInterface(item)
if !v.IsValid() {
- return nil, fmt.Errorf("index of untyped nil")
+ return reflect.Value{}, fmt.Errorf("index of untyped nil")
}
for _, i := range indices {
- index := reflect.ValueOf(i)
+ index := indirectInterface(i)
var isNil bool
if v, isNil = indirect(v); isNil {
- return nil, fmt.Errorf("index of nil pointer")
+ return reflect.Value{}, fmt.Errorf("index of nil pointer")
}
switch v.Kind() {
case reflect.Array, reflect.Slice, reflect.String:
@@ -164,18 +170,18 @@ func index(item interface{}, indices ...interface{}) (interface{}, error) {
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
x = int64(index.Uint())
case reflect.Invalid:
- return nil, fmt.Errorf("cannot index slice/array with nil")
+ return reflect.Value{}, fmt.Errorf("cannot index slice/array with nil")
default:
- return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type())
+ return reflect.Value{}, fmt.Errorf("cannot index slice/array with type %s", index.Type())
}
if x < 0 || x >= int64(v.Len()) {
- return nil, fmt.Errorf("index out of range: %d", x)
+ return reflect.Value{}, fmt.Errorf("index out of range: %d", x)
}
v = v.Index(int(x))
case reflect.Map:
index, err := prepareArg(index, v.Type().Key())
if err != nil {
- return nil, err
+ return reflect.Value{}, err
}
if x := v.MapIndex(index); x.IsValid() {
v = x
@@ -186,10 +192,10 @@ func index(item interface{}, indices ...interface{}) (interface{}, error) {
// the loop holds invariant: v.IsValid()
panic("unreachable")
default:
- return nil, fmt.Errorf("can't index item of type %s", v.Type())
+ return reflect.Value{}, fmt.Errorf("can't index item of type %s", v.Type())
}
}
- return v.Interface(), nil
+ return v, nil
}
// Length
@@ -215,33 +221,33 @@ func length(item interface{}) (int, error) {
// call returns the result of evaluating the first argument as a function.
// The function must return 1 result, or 2 results, the second of which is an error.
-func call(fn interface{}, args ...interface{}) (interface{}, error) {
- v := reflect.ValueOf(fn)
+func call(fn reflect.Value, args ...reflect.Value) (reflect.Value, error) {
+ v := indirectInterface(fn)
if !v.IsValid() {
- return nil, fmt.Errorf("call of nil")
+ return reflect.Value{}, fmt.Errorf("call of nil")
}
typ := v.Type()
if typ.Kind() != reflect.Func {
- return nil, fmt.Errorf("non-function of type %s", typ)
+ return reflect.Value{}, fmt.Errorf("non-function of type %s", typ)
}
if !goodFunc(typ) {
- return nil, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut())
+ return reflect.Value{}, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut())
}
numIn := typ.NumIn()
var dddType reflect.Type
if typ.IsVariadic() {
if len(args) < numIn-1 {
- return nil, fmt.Errorf("wrong number of args: got %d want at least %d", len(args), numIn-1)
+ return reflect.Value{}, fmt.Errorf("wrong number of args: got %d want at least %d", len(args), numIn-1)
}
dddType = typ.In(numIn - 1).Elem()
} else {
if len(args) != numIn {
- return nil, fmt.Errorf("wrong number of args: got %d want %d", len(args), numIn)
+ return reflect.Value{}, fmt.Errorf("wrong number of args: got %d want %d", len(args), numIn)
}
}
argv := make([]reflect.Value, len(args))
for i, arg := range args {
- value := reflect.ValueOf(arg)
+ value := indirectInterface(arg)
// Compute the expected type. Clumsy because of variadics.
var argType reflect.Type
if !typ.IsVariadic() || i < numIn-1 {
@@ -252,26 +258,26 @@ func call(fn interface{}, args ...interface{}) (interface{}, error) {
var err error
if argv[i], err = prepareArg(value, argType); err != nil {
- return nil, fmt.Errorf("arg %d: %s", i, err)
+ return reflect.Value{}, fmt.Errorf("arg %d: %s", i, err)
}
}
result := v.Call(argv)
if len(result) == 2 && !result[1].IsNil() {
- return result[0].Interface(), result[1].Interface().(error)
+ return result[0], result[1].Interface().(error)
}
- return result[0].Interface(), nil
+ return result[0], nil
}
// Boolean logic.
-func truth(a interface{}) bool {
- t, _ := IsTrue(a)
+func truth(arg reflect.Value) bool {
+ t, _ := isTrue(indirectInterface(arg))
return t
}
// and computes the Boolean AND of its arguments, returning
// the first false argument it encounters, or the last argument.
-func and(arg0 interface{}, args ...interface{}) interface{} {
+func and(arg0 reflect.Value, args ...reflect.Value) reflect.Value {
if !truth(arg0) {
return arg0
}
@@ -286,7 +292,7 @@ func and(arg0 interface{}, args ...interface{}) interface{} {
// or computes the Boolean OR of its arguments, returning
// the first true argument it encounters, or the last argument.
-func or(arg0 interface{}, args ...interface{}) interface{} {
+func or(arg0 reflect.Value, args ...reflect.Value) reflect.Value {
if truth(arg0) {
return arg0
}
@@ -300,7 +306,7 @@ func or(arg0 interface{}, args ...interface{}) interface{} {
}
// not returns the Boolean negation of its argument.
-func not(arg interface{}) bool {
+func not(arg reflect.Value) bool {
return !truth(arg)
}
@@ -345,8 +351,8 @@ func basicKind(v reflect.Value) (kind, error) {
}
// eq evaluates the comparison a == b || a == c || ...
-func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
- v1 := reflect.ValueOf(arg1)
+func eq(arg1 reflect.Value, arg2 ...reflect.Value) (bool, error) {
+ v1 := indirectInterface(arg1)
k1, err := basicKind(v1)
if err != nil {
return false, err
@@ -355,7 +361,7 @@ func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
return false, errNoComparison
}
for _, arg := range arg2 {
- v2 := reflect.ValueOf(arg)
+ v2 := indirectInterface(arg)
k2, err := basicKind(v2)
if err != nil {
return false, err
@@ -397,20 +403,20 @@ func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
}
// ne evaluates the comparison a != b.
-func ne(arg1, arg2 interface{}) (bool, error) {
+func ne(arg1, arg2 reflect.Value) (bool, error) {
// != is the inverse of ==.
equal, err := eq(arg1, arg2)
return !equal, err
}
// lt evaluates the comparison a < b.
-func lt(arg1, arg2 interface{}) (bool, error) {
- v1 := reflect.ValueOf(arg1)
+func lt(arg1, arg2 reflect.Value) (bool, error) {
+ v1 := indirectInterface(arg1)
k1, err := basicKind(v1)
if err != nil {
return false, err
}
- v2 := reflect.ValueOf(arg2)
+ v2 := indirectInterface(arg2)
k2, err := basicKind(v2)
if err != nil {
return false, err
@@ -446,7 +452,7 @@ func lt(arg1, arg2 interface{}) (bool, error) {
}
// le evaluates the comparison <= b.
-func le(arg1, arg2 interface{}) (bool, error) {
+func le(arg1, arg2 reflect.Value) (bool, error) {
// <= is < or ==.
lessThan, err := lt(arg1, arg2)
if lessThan || err != nil {
@@ -456,7 +462,7 @@ func le(arg1, arg2 interface{}) (bool, error) {
}
// gt evaluates the comparison a > b.
-func gt(arg1, arg2 interface{}) (bool, error) {
+func gt(arg1, arg2 reflect.Value) (bool, error) {
// > is the inverse of <=.
lessOrEqual, err := le(arg1, arg2)
if err != nil {
@@ -466,7 +472,7 @@ func gt(arg1, arg2 interface{}) (bool, error) {
}
// ge evaluates the comparison a >= b.
-func ge(arg1, arg2 interface{}) (bool, error) {
+func ge(arg1, arg2 reflect.Value) (bool, error) {
// >= is the inverse of <.
lessThan, err := lt(arg1, arg2)
if err != nil {
diff --git a/libgo/go/text/template/multi_test.go b/libgo/go/text/template/multi_test.go
index c8723cb7a8b..8142f008fdf 100644
--- a/libgo/go/text/template/multi_test.go
+++ b/libgo/go/text/template/multi_test.go
@@ -349,3 +349,39 @@ func TestParse(t *testing.T) {
t.Fatalf("parsing test: %s", err)
}
}
+
+func TestEmptyTemplate(t *testing.T) {
+ cases := []struct {
+ defn []string
+ in string
+ want string
+ }{
+ {[]string{""}, "once", ""},
+ {[]string{"", ""}, "twice", ""},
+ {[]string{"{{.}}", "{{.}}"}, "twice", "twice"},
+ {[]string{"{{/* a comment */}}", "{{/* a comment */}}"}, "comment", ""},
+ {[]string{"{{.}}", ""}, "twice", ""},
+ }
+
+ for _, c := range cases {
+ root := New("root")
+
+ var (
+ m *Template
+ err error
+ )
+ for _, d := range c.defn {
+ m, err = root.New(c.in).Parse(d)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ buf := &bytes.Buffer{}
+ if err := m.Execute(buf, c.in); err != nil {
+ t.Fatal(err)
+ }
+ if buf.String() != c.want {
+ t.Errorf("expected string %q: got %q", c.want, buf.String())
+ }
+ }
+}
diff --git a/libgo/go/text/template/parse/lex.go b/libgo/go/text/template/parse/lex.go
index 079c0ea6f71..6fbf36d7a4a 100644
--- a/libgo/go/text/template/parse/lex.go
+++ b/libgo/go/text/template/parse/lex.go
@@ -13,9 +13,10 @@ import (
// item represents a token or text string returned from the scanner.
type item struct {
- typ itemType // The type of this item.
- pos Pos // The starting position, in bytes, of this item in the input string.
- val string // The value of this item.
+ typ itemType // The type of this item.
+ pos Pos // The starting position, in bytes, of this item in the input string.
+ val string // The value of this item.
+ line int // The line number at the start of this item.
}
func (i item) String() string {
@@ -116,6 +117,7 @@ type lexer struct {
lastPos Pos // position of most recent item returned by nextItem
items chan item // channel of scanned items
parenDepth int // nesting depth of ( ) exprs
+ line int // 1+number of newlines seen
}
// next returns the next rune in the input.
@@ -127,6 +129,9 @@ func (l *lexer) next() rune {
r, w := utf8.DecodeRuneInString(l.input[l.pos:])
l.width = Pos(w)
l.pos += l.width
+ if r == '\n' {
+ l.line++
+ }
return r
}
@@ -140,11 +145,20 @@ func (l *lexer) peek() rune {
// backup steps back one rune. Can only be called once per call of next.
func (l *lexer) backup() {
l.pos -= l.width
+ // Correct newline count.
+ if l.width == 1 && l.input[l.pos] == '\n' {
+ l.line--
+ }
}
// emit passes an item back to the client.
func (l *lexer) emit(t itemType) {
- l.items <- item{t, l.start, l.input[l.start:l.pos]}
+ l.items <- item{t, l.start, l.input[l.start:l.pos], l.line}
+ // Some items contain text internally. If so, count their newlines.
+ switch t {
+ case itemText, itemRawString, itemLeftDelim, itemRightDelim:
+ l.line += strings.Count(l.input[l.start:l.pos], "\n")
+ }
l.start = l.pos
}
@@ -169,17 +183,10 @@ func (l *lexer) acceptRun(valid string) {
l.backup()
}
-// lineNumber reports which line we're on, based on the position of
-// the previous item returned by nextItem. Doing it this way
-// means we don't have to worry about peek double counting.
-func (l *lexer) lineNumber() int {
- return 1 + strings.Count(l.input[:l.lastPos], "\n")
-}
-
// errorf returns an error token and terminates the scan by passing
// back a nil pointer that will be the next state, terminating l.nextItem.
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
- l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)}
+ l.items <- item{itemError, l.start, fmt.Sprintf(format, args...), l.line}
return nil
}
@@ -212,6 +219,7 @@ func lex(name, input, left, right string) *lexer {
leftDelim: left,
rightDelim: right,
items: make(chan item),
+ line: 1,
}
go l.run()
return l
@@ -236,24 +244,23 @@ const (
// lexText scans until an opening action delimiter, "{{".
func lexText(l *lexer) stateFn {
- for {
- delim, trimSpace := l.atLeftDelim()
- if delim {
- trimLength := Pos(0)
- if trimSpace {
- trimLength = rightTrimLength(l.input[l.start:l.pos])
- }
- l.pos -= trimLength
- if l.pos > l.start {
- l.emit(itemText)
- }
- l.pos += trimLength
- l.ignore()
- return lexLeftDelim
+ l.width = 0
+ if x := strings.Index(l.input[l.pos:], l.leftDelim); x >= 0 {
+ ldn := Pos(len(l.leftDelim))
+ l.pos += Pos(x)
+ trimLength := Pos(0)
+ if strings.HasPrefix(l.input[l.pos+ldn:], leftTrimMarker) {
+ trimLength = rightTrimLength(l.input[l.start:l.pos])
}
- if l.next() == eof {
- break
+ l.pos -= trimLength
+ if l.pos > l.start {
+ l.emit(itemText)
}
+ l.pos += trimLength
+ l.ignore()
+ return lexLeftDelim
+ } else {
+ l.pos = Pos(len(l.input))
}
// Correctly reached EOF.
if l.pos > l.start {
@@ -263,16 +270,6 @@ func lexText(l *lexer) stateFn {
return nil
}
-// atLeftDelim reports whether the lexer is at a left delimiter, possibly followed by a trim marker.
-func (l *lexer) atLeftDelim() (delim, trimSpaces bool) {
- if !strings.HasPrefix(l.input[l.pos:], l.leftDelim) {
- return false, false
- }
- // The left delim might have the marker afterwards.
- trimSpaces = strings.HasPrefix(l.input[l.pos+Pos(len(l.leftDelim)):], leftTrimMarker)
- return true, trimSpaces
-}
-
// rightTrimLength returns the length of the spaces at the end of the string.
func rightTrimLength(s string) Pos {
return Pos(len(s) - len(strings.TrimRight(s, spaceChars)))
@@ -613,10 +610,14 @@ Loop:
// lexRawQuote scans a raw quoted string.
func lexRawQuote(l *lexer) stateFn {
+ startLine := l.line
Loop:
for {
switch l.next() {
case eof:
+ // Restore line number to location of opening quote.
+ // We will error out so it's ok just to overwrite the field.
+ l.line = startLine
return l.errorf("unterminated raw quoted string")
case '`':
break Loop
diff --git a/libgo/go/text/template/parse/lex_test.go b/libgo/go/text/template/parse/lex_test.go
index e35ebf1a854..d655d788b3b 100644
--- a/libgo/go/text/template/parse/lex_test.go
+++ b/libgo/go/text/template/parse/lex_test.go
@@ -58,39 +58,46 @@ type lexTest struct {
items []item
}
+func mkItem(typ itemType, text string) item {
+ return item{
+ typ: typ,
+ val: text,
+ }
+}
+
var (
- tDot = item{itemDot, 0, "."}
- tBlock = item{itemBlock, 0, "block"}
- tEOF = item{itemEOF, 0, ""}
- tFor = item{itemIdentifier, 0, "for"}
- tLeft = item{itemLeftDelim, 0, "{{"}
- tLpar = item{itemLeftParen, 0, "("}
- tPipe = item{itemPipe, 0, "|"}
- tQuote = item{itemString, 0, `"abc \n\t\" "`}
- tRange = item{itemRange, 0, "range"}
- tRight = item{itemRightDelim, 0, "}}"}
- tRpar = item{itemRightParen, 0, ")"}
- tSpace = item{itemSpace, 0, " "}
+ tDot = mkItem(itemDot, ".")
+ tBlock = mkItem(itemBlock, "block")
+ tEOF = mkItem(itemEOF, "")
+ tFor = mkItem(itemIdentifier, "for")
+ tLeft = mkItem(itemLeftDelim, "{{")
+ tLpar = mkItem(itemLeftParen, "(")
+ tPipe = mkItem(itemPipe, "|")
+ tQuote = mkItem(itemString, `"abc \n\t\" "`)
+ tRange = mkItem(itemRange, "range")
+ tRight = mkItem(itemRightDelim, "}}")
+ tRpar = mkItem(itemRightParen, ")")
+ tSpace = mkItem(itemSpace, " ")
raw = "`" + `abc\n\t\" ` + "`"
rawNL = "`now is{{\n}}the time`" // Contains newline inside raw quote.
- tRawQuote = item{itemRawString, 0, raw}
- tRawQuoteNL = item{itemRawString, 0, rawNL}
+ tRawQuote = mkItem(itemRawString, raw)
+ tRawQuoteNL = mkItem(itemRawString, rawNL)
)
var lexTests = []lexTest{
{"empty", "", []item{tEOF}},
- {"spaces", " \t\n", []item{{itemText, 0, " \t\n"}, tEOF}},
- {"text", `now is the time`, []item{{itemText, 0, "now is the time"}, tEOF}},
+ {"spaces", " \t\n", []item{mkItem(itemText, " \t\n"), tEOF}},
+ {"text", `now is the time`, []item{mkItem(itemText, "now is the time"), tEOF}},
{"text with comment", "hello-{{/* this is a comment */}}-world", []item{
- {itemText, 0, "hello-"},
- {itemText, 0, "-world"},
+ mkItem(itemText, "hello-"),
+ mkItem(itemText, "-world"),
tEOF,
}},
{"punctuation", "{{,@% }}", []item{
tLeft,
- {itemChar, 0, ","},
- {itemChar, 0, "@"},
- {itemChar, 0, "%"},
+ mkItem(itemChar, ","),
+ mkItem(itemChar, "@"),
+ mkItem(itemChar, "%"),
tSpace,
tRight,
tEOF,
@@ -99,7 +106,7 @@ var lexTests = []lexTest{
tLeft,
tLpar,
tLpar,
- {itemNumber, 0, "3"},
+ mkItem(itemNumber, "3"),
tRpar,
tRpar,
tRight,
@@ -108,54 +115,54 @@ var lexTests = []lexTest{
{"empty action", `{{}}`, []item{tLeft, tRight, tEOF}},
{"for", `{{for}}`, []item{tLeft, tFor, tRight, tEOF}},
{"block", `{{block "foo" .}}`, []item{
- tLeft, tBlock, tSpace, {itemString, 0, `"foo"`}, tSpace, tDot, tRight, tEOF,
+ tLeft, tBlock, tSpace, mkItem(itemString, `"foo"`), tSpace, tDot, tRight, tEOF,
}},
{"quote", `{{"abc \n\t\" "}}`, []item{tLeft, tQuote, tRight, tEOF}},
{"raw quote", "{{" + raw + "}}", []item{tLeft, tRawQuote, tRight, tEOF}},
{"raw quote with newline", "{{" + rawNL + "}}", []item{tLeft, tRawQuoteNL, tRight, tEOF}},
{"numbers", "{{1 02 0x14 -7.2i 1e3 +1.2e-4 4.2i 1+2i}}", []item{
tLeft,
- {itemNumber, 0, "1"},
+ mkItem(itemNumber, "1"),
tSpace,
- {itemNumber, 0, "02"},
+ mkItem(itemNumber, "02"),
tSpace,
- {itemNumber, 0, "0x14"},
+ mkItem(itemNumber, "0x14"),
tSpace,
- {itemNumber, 0, "-7.2i"},
+ mkItem(itemNumber, "-7.2i"),
tSpace,
- {itemNumber, 0, "1e3"},
+ mkItem(itemNumber, "1e3"),
tSpace,
- {itemNumber, 0, "+1.2e-4"},
+ mkItem(itemNumber, "+1.2e-4"),
tSpace,
- {itemNumber, 0, "4.2i"},
+ mkItem(itemNumber, "4.2i"),
tSpace,
- {itemComplex, 0, "1+2i"},
+ mkItem(itemComplex, "1+2i"),
tRight,
tEOF,
}},
{"characters", `{{'a' '\n' '\'' '\\' '\u00FF' '\xFF' '本'}}`, []item{
tLeft,
- {itemCharConstant, 0, `'a'`},
+ mkItem(itemCharConstant, `'a'`),
tSpace,
- {itemCharConstant, 0, `'\n'`},
+ mkItem(itemCharConstant, `'\n'`),
tSpace,
- {itemCharConstant, 0, `'\''`},
+ mkItem(itemCharConstant, `'\''`),
tSpace,
- {itemCharConstant, 0, `'\\'`},
+ mkItem(itemCharConstant, `'\\'`),
tSpace,
- {itemCharConstant, 0, `'\u00FF'`},
+ mkItem(itemCharConstant, `'\u00FF'`),
tSpace,
- {itemCharConstant, 0, `'\xFF'`},
+ mkItem(itemCharConstant, `'\xFF'`),
tSpace,
- {itemCharConstant, 0, `'本'`},
+ mkItem(itemCharConstant, `'本'`),
tRight,
tEOF,
}},
{"bools", "{{true false}}", []item{
tLeft,
- {itemBool, 0, "true"},
+ mkItem(itemBool, "true"),
tSpace,
- {itemBool, 0, "false"},
+ mkItem(itemBool, "false"),
tRight,
tEOF,
}},
@@ -167,178 +174,178 @@ var lexTests = []lexTest{
}},
{"nil", "{{nil}}", []item{
tLeft,
- {itemNil, 0, "nil"},
+ mkItem(itemNil, "nil"),
tRight,
tEOF,
}},
{"dots", "{{.x . .2 .x.y.z}}", []item{
tLeft,
- {itemField, 0, ".x"},
+ mkItem(itemField, ".x"),
tSpace,
tDot,
tSpace,
- {itemNumber, 0, ".2"},
+ mkItem(itemNumber, ".2"),
tSpace,
- {itemField, 0, ".x"},
- {itemField, 0, ".y"},
- {itemField, 0, ".z"},
+ mkItem(itemField, ".x"),
+ mkItem(itemField, ".y"),
+ mkItem(itemField, ".z"),
tRight,
tEOF,
}},
{"keywords", "{{range if else end with}}", []item{
tLeft,
- {itemRange, 0, "range"},
+ mkItem(itemRange, "range"),
tSpace,
- {itemIf, 0, "if"},
+ mkItem(itemIf, "if"),
tSpace,
- {itemElse, 0, "else"},
+ mkItem(itemElse, "else"),
tSpace,
- {itemEnd, 0, "end"},
+ mkItem(itemEnd, "end"),
tSpace,
- {itemWith, 0, "with"},
+ mkItem(itemWith, "with"),
tRight,
tEOF,
}},
{"variables", "{{$c := printf $ $hello $23 $ $var.Field .Method}}", []item{
tLeft,
- {itemVariable, 0, "$c"},
+ mkItem(itemVariable, "$c"),
tSpace,
- {itemColonEquals, 0, ":="},
+ mkItem(itemColonEquals, ":="),
tSpace,
- {itemIdentifier, 0, "printf"},
+ mkItem(itemIdentifier, "printf"),
tSpace,
- {itemVariable, 0, "$"},
+ mkItem(itemVariable, "$"),
tSpace,
- {itemVariable, 0, "$hello"},
+ mkItem(itemVariable, "$hello"),
tSpace,
- {itemVariable, 0, "$23"},
+ mkItem(itemVariable, "$23"),
tSpace,
- {itemVariable, 0, "$"},
+ mkItem(itemVariable, "$"),
tSpace,
- {itemVariable, 0, "$var"},
- {itemField, 0, ".Field"},
+ mkItem(itemVariable, "$var"),
+ mkItem(itemField, ".Field"),
tSpace,
- {itemField, 0, ".Method"},
+ mkItem(itemField, ".Method"),
tRight,
tEOF,
}},
{"variable invocation", "{{$x 23}}", []item{
tLeft,
- {itemVariable, 0, "$x"},
+ mkItem(itemVariable, "$x"),
tSpace,
- {itemNumber, 0, "23"},
+ mkItem(itemNumber, "23"),
tRight,
tEOF,
}},
{"pipeline", `intro {{echo hi 1.2 |noargs|args 1 "hi"}} outro`, []item{
- {itemText, 0, "intro "},
+ mkItem(itemText, "intro "),
tLeft,
- {itemIdentifier, 0, "echo"},
+ mkItem(itemIdentifier, "echo"),
tSpace,
- {itemIdentifier, 0, "hi"},
+ mkItem(itemIdentifier, "hi"),
tSpace,
- {itemNumber, 0, "1.2"},
+ mkItem(itemNumber, "1.2"),
tSpace,
tPipe,
- {itemIdentifier, 0, "noargs"},
+ mkItem(itemIdentifier, "noargs"),
tPipe,
- {itemIdentifier, 0, "args"},
+ mkItem(itemIdentifier, "args"),
tSpace,
- {itemNumber, 0, "1"},
+ mkItem(itemNumber, "1"),
tSpace,
- {itemString, 0, `"hi"`},
+ mkItem(itemString, `"hi"`),
tRight,
- {itemText, 0, " outro"},
+ mkItem(itemText, " outro"),
tEOF,
}},
{"declaration", "{{$v := 3}}", []item{
tLeft,
- {itemVariable, 0, "$v"},
+ mkItem(itemVariable, "$v"),
tSpace,
- {itemColonEquals, 0, ":="},
+ mkItem(itemColonEquals, ":="),
tSpace,
- {itemNumber, 0, "3"},
+ mkItem(itemNumber, "3"),
tRight,
tEOF,
}},
{"2 declarations", "{{$v , $w := 3}}", []item{
tLeft,
- {itemVariable, 0, "$v"},
+ mkItem(itemVariable, "$v"),
tSpace,
- {itemChar, 0, ","},
+ mkItem(itemChar, ","),
tSpace,
- {itemVariable, 0, "$w"},
+ mkItem(itemVariable, "$w"),
tSpace,
- {itemColonEquals, 0, ":="},
+ mkItem(itemColonEquals, ":="),
tSpace,
- {itemNumber, 0, "3"},
+ mkItem(itemNumber, "3"),
tRight,
tEOF,
}},
{"field of parenthesized expression", "{{(.X).Y}}", []item{
tLeft,
tLpar,
- {itemField, 0, ".X"},
+ mkItem(itemField, ".X"),
tRpar,
- {itemField, 0, ".Y"},
+ mkItem(itemField, ".Y"),
tRight,
tEOF,
}},
{"trimming spaces before and after", "hello- {{- 3 -}} -world", []item{
- {itemText, 0, "hello-"},
+ mkItem(itemText, "hello-"),
tLeft,
- {itemNumber, 0, "3"},
+ mkItem(itemNumber, "3"),
tRight,
- {itemText, 0, "-world"},
+ mkItem(itemText, "-world"),
tEOF,
}},
{"trimming spaces before and after comment", "hello- {{- /* hello */ -}} -world", []item{
- {itemText, 0, "hello-"},
- {itemText, 0, "-world"},
+ mkItem(itemText, "hello-"),
+ mkItem(itemText, "-world"),
tEOF,
}},
// errors
{"badchar", "#{{\x01}}", []item{
- {itemText, 0, "#"},
+ mkItem(itemText, "#"),
tLeft,
- {itemError, 0, "unrecognized character in action: U+0001"},
+ mkItem(itemError, "unrecognized character in action: U+0001"),
}},
{"unclosed action", "{{\n}}", []item{
tLeft,
- {itemError, 0, "unclosed action"},
+ mkItem(itemError, "unclosed action"),
}},
{"EOF in action", "{{range", []item{
tLeft,
tRange,
- {itemError, 0, "unclosed action"},
+ mkItem(itemError, "unclosed action"),
}},
{"unclosed quote", "{{\"\n\"}}", []item{
tLeft,
- {itemError, 0, "unterminated quoted string"},
+ mkItem(itemError, "unterminated quoted string"),
}},
{"unclosed raw quote", "{{`xx}}", []item{
tLeft,
- {itemError, 0, "unterminated raw quoted string"},
+ mkItem(itemError, "unterminated raw quoted string"),
}},
{"unclosed char constant", "{{'\n}}", []item{
tLeft,
- {itemError, 0, "unterminated character constant"},
+ mkItem(itemError, "unterminated character constant"),
}},
{"bad number", "{{3k}}", []item{
tLeft,
- {itemError, 0, `bad number syntax: "3k"`},
+ mkItem(itemError, `bad number syntax: "3k"`),
}},
{"unclosed paren", "{{(3}}", []item{
tLeft,
tLpar,
- {itemNumber, 0, "3"},
- {itemError, 0, `unclosed left paren`},
+ mkItem(itemNumber, "3"),
+ mkItem(itemError, `unclosed left paren`),
}},
{"extra right paren", "{{3)}}", []item{
tLeft,
- {itemNumber, 0, "3"},
+ mkItem(itemNumber, "3"),
tRpar,
- {itemError, 0, `unexpected right paren U+0029 ')'`},
+ mkItem(itemError, `unexpected right paren U+0029 ')'`),
}},
// Fixed bugs
@@ -355,17 +362,17 @@ var lexTests = []lexTest{
tEOF,
}},
{"text with bad comment", "hello-{{/*/}}-world", []item{
- {itemText, 0, "hello-"},
- {itemError, 0, `unclosed comment`},
+ mkItem(itemText, "hello-"),
+ mkItem(itemError, `unclosed comment`),
}},
{"text with comment close separated from delim", "hello-{{/* */ }}-world", []item{
- {itemText, 0, "hello-"},
- {itemError, 0, `comment ends before closing delimiter`},
+ mkItem(itemText, "hello-"),
+ mkItem(itemError, `comment ends before closing delimiter`),
}},
// This one is an error that we can't catch because it breaks templates with
// minimized JavaScript. Should have fixed it before Go 1.1.
{"unmatched right delimiter", "hello-{.}}-world", []item{
- {itemText, 0, "hello-{.}}-world"},
+ mkItem(itemText, "hello-{.}}-world"),
tEOF,
}},
}
@@ -414,13 +421,13 @@ func TestLex(t *testing.T) {
var lexDelimTests = []lexTest{
{"punctuation", "$$,@%{{}}@@", []item{
tLeftDelim,
- {itemChar, 0, ","},
- {itemChar, 0, "@"},
- {itemChar, 0, "%"},
- {itemChar, 0, "{"},
- {itemChar, 0, "{"},
- {itemChar, 0, "}"},
- {itemChar, 0, "}"},
+ mkItem(itemChar, ","),
+ mkItem(itemChar, "@"),
+ mkItem(itemChar, "%"),
+ mkItem(itemChar, "{"),
+ mkItem(itemChar, "{"),
+ mkItem(itemChar, "}"),
+ mkItem(itemChar, "}"),
tRightDelim,
tEOF,
}},
@@ -431,8 +438,8 @@ var lexDelimTests = []lexTest{
}
var (
- tLeftDelim = item{itemLeftDelim, 0, "$$"}
- tRightDelim = item{itemRightDelim, 0, "@@"}
+ tLeftDelim = mkItem(itemLeftDelim, "$$")
+ tRightDelim = mkItem(itemRightDelim, "@@")
)
func TestDelims(t *testing.T) {
@@ -447,21 +454,21 @@ func TestDelims(t *testing.T) {
var lexPosTests = []lexTest{
{"empty", "", []item{tEOF}},
{"punctuation", "{{,@%#}}", []item{
- {itemLeftDelim, 0, "{{"},
- {itemChar, 2, ","},
- {itemChar, 3, "@"},
- {itemChar, 4, "%"},
- {itemChar, 5, "#"},
- {itemRightDelim, 6, "}}"},
- {itemEOF, 8, ""},
+ {itemLeftDelim, 0, "{{", 1},
+ {itemChar, 2, ",", 1},
+ {itemChar, 3, "@", 1},
+ {itemChar, 4, "%", 1},
+ {itemChar, 5, "#", 1},
+ {itemRightDelim, 6, "}}", 1},
+ {itemEOF, 8, "", 1},
}},
{"sample", "0123{{hello}}xyz", []item{
- {itemText, 0, "0123"},
- {itemLeftDelim, 4, "{{"},
- {itemIdentifier, 6, "hello"},
- {itemRightDelim, 11, "}}"},
- {itemText, 13, "xyz"},
- {itemEOF, 16, ""},
+ {itemText, 0, "0123", 1},
+ {itemLeftDelim, 4, "{{", 1},
+ {itemIdentifier, 6, "hello", 1},
+ {itemRightDelim, 11, "}}", 1},
+ {itemText, 13, "xyz", 1},
+ {itemEOF, 16, "", 1},
}},
}
diff --git a/libgo/go/text/template/parse/parse.go b/libgo/go/text/template/parse/parse.go
index 86705e5a379..6060c6d74b7 100644
--- a/libgo/go/text/template/parse/parse.go
+++ b/libgo/go/text/template/parse/parse.go
@@ -157,7 +157,7 @@ func (t *Tree) ErrorContext(n Node) (location, context string) {
// errorf formats the error and terminates processing.
func (t *Tree) errorf(format string, args ...interface{}) {
t.Root = nil
- format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.lex.lineNumber(), format)
+ format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.token[0].line, format)
panic(fmt.Errorf(format, args...))
}
@@ -277,7 +277,7 @@ func IsEmptyTree(n Node) bool {
// parse is the top-level parser for a template, essentially the same
// as itemList except it also parses {{define}} actions.
// It runs to EOF.
-func (t *Tree) parse() (next Node) {
+func (t *Tree) parse() {
t.Root = t.newList(t.peek().pos)
for t.peek().typ != itemEOF {
if t.peek().typ == itemLeftDelim {
@@ -299,7 +299,6 @@ func (t *Tree) parse() (next Node) {
t.Root.append(n)
}
}
- return nil
}
// parseDefinition parses a {{define}} ... {{end}} template definition and
@@ -377,15 +376,17 @@ func (t *Tree) action() (n Node) {
return t.withControl()
}
t.backup()
+ token := t.peek()
// Do not pop variables; they persist until "end".
- return t.newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command"))
+ return t.newAction(token.pos, token.line, t.pipeline("command"))
}
// Pipeline:
// declarations? command ('|' command)*
func (t *Tree) pipeline(context string) (pipe *PipeNode) {
var decl []*VariableNode
- pos := t.peekNonSpace().pos
+ token := t.peekNonSpace()
+ pos := token.pos
// Are there declarations?
for {
if v := t.peekNonSpace(); v.typ == itemVariable {
@@ -414,7 +415,7 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
}
break
}
- pipe = t.newPipeline(pos, t.lex.lineNumber(), decl)
+ pipe = t.newPipeline(pos, token.line, decl)
for {
switch token := t.nextNonSpace(); token.typ {
case itemRightDelim, itemRightParen:
@@ -451,7 +452,6 @@ func (t *Tree) checkPipeline(pipe *PipeNode, context string) {
func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
defer t.popVars(len(t.vars))
- line = t.lex.lineNumber()
pipe = t.pipeline(context)
var next Node
list, next = t.itemList()
@@ -480,7 +480,7 @@ func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int
t.errorf("expected end; found %s", next)
}
}
- return pipe.Position(), line, pipe, list, elseList
+ return pipe.Position(), pipe.Line, pipe, list, elseList
}
// If:
@@ -522,9 +522,10 @@ func (t *Tree) elseControl() Node {
peek := t.peekNonSpace()
if peek.typ == itemIf {
// We see "{{else if ... " but in effect rewrite it to {{else}}{{if ... ".
- return t.newElse(peek.pos, t.lex.lineNumber())
+ return t.newElse(peek.pos, peek.line)
}
- return t.newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber())
+ token := t.expect(itemRightDelim, "else")
+ return t.newElse(token.pos, token.line)
}
// Block:
@@ -551,7 +552,7 @@ func (t *Tree) blockControl() Node {
block.add()
block.stopParse()
- return t.newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
+ return t.newTemplate(token.pos, token.line, name, pipe)
}
// Template:
@@ -568,7 +569,7 @@ func (t *Tree) templateControl() Node {
// Do not pop variables; they persist until "end".
pipe = t.pipeline(context)
}
- return t.newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
+ return t.newTemplate(token.pos, token.line, name, pipe)
}
func (t *Tree) parseTemplateName(token item, context string) (name string) {
diff --git a/libgo/go/text/template/parse/parse_test.go b/libgo/go/text/template/parse/parse_test.go
index 9d856bcb3df..81f14aca986 100644
--- a/libgo/go/text/template/parse/parse_test.go
+++ b/libgo/go/text/template/parse/parse_test.go
@@ -484,3 +484,37 @@ func TestBlock(t *testing.T) {
t.Errorf("inner template = %q, want %q", g, w)
}
}
+
+func TestLineNum(t *testing.T) {
+ const count = 100
+ text := strings.Repeat("{{printf 1234}}\n", count)
+ tree, err := New("bench").Parse(text, "", "", make(map[string]*Tree), builtins)
+ if err != nil {
+ t.Fatal(err)
+ }
+ // Check the line numbers. Each line is an action containing a template, followed by text.
+ // That's two nodes per line.
+ nodes := tree.Root.Nodes
+ for i := 0; i < len(nodes); i += 2 {
+ line := 1 + i/2
+ // Action first.
+ action := nodes[i].(*ActionNode)
+ if action.Line != line {
+ t.Fatalf("line %d: action is line %d", line, action.Line)
+ }
+ pipe := action.Pipe
+ if pipe.Line != line {
+ t.Fatalf("line %d: pipe is line %d", line, pipe.Line)
+ }
+ }
+}
+
+func BenchmarkParseLarge(b *testing.B) {
+ text := strings.Repeat("{{1234}}\n", 10000)
+ for i := 0; i < b.N; i++ {
+ _, err := New("bench").Parse(text, "", "", make(map[string]*Tree), builtins)
+ if err != nil {
+ b.Fatal(err)
+ }
+ }
+}
diff --git a/libgo/go/text/template/template.go b/libgo/go/text/template/template.go
index 7a7f42a7153..b6fceb1795c 100644
--- a/libgo/go/text/template/template.go
+++ b/libgo/go/text/template/template.go
@@ -181,9 +181,16 @@ func (t *Template) Lookup(name string) *Template {
return t.tmpl[name]
}
-// Parse defines the template by parsing the text. Nested template definitions will be
-// associated with the top-level template t. Parse may be called multiple times
-// to parse definitions of templates to associate with t.
+// Parse parses text as a template body for t.
+// Named template definitions ({{define ...}} or {{block ...}} statements) in text
+// define additional templates associated with t and are removed from the
+// definition of t itself.
+//
+// Templates can be redefined in successive calls to Parse.
+// A template definition with a body containing only white space and comments
+// is considered empty and will not replace an existing template's body.
+// This allows using Parse to add new named template definitions without
+// overwriting the main template body.
func (t *Template) Parse(text string) (*Template, error) {
t.init()
t.muFuncs.RLock()
@@ -208,7 +215,7 @@ func (t *Template) associate(new *Template, tree *parse.Tree) (bool, error) {
if new.common != t.common {
panic("internal error: associate not common")
}
- if t.tmpl[new.name] != nil && parse.IsEmptyTree(tree.Root) {
+ if t.tmpl[new.name] != nil && parse.IsEmptyTree(tree.Root) && t.Tree != nil {
// If a template by that name exists,
// don't replace it with an empty template.
return false, nil
diff --git a/libgo/go/time/example_test.go b/libgo/go/time/example_test.go
index 4170d5110d0..7dc2bb5e7ee 100644
--- a/libgo/go/time/example_test.go
+++ b/libgo/go/time/example_test.go
@@ -251,20 +251,18 @@ func ExampleTime_Truncate() {
2 * time.Second,
time.Minute,
10 * time.Minute,
- time.Hour,
}
for _, d := range trunc {
- fmt.Printf("t.Truncate(%6s) = %s\n", d, t.Truncate(d).Format("15:04:05.999999999"))
+ fmt.Printf("t.Truncate(%5s) = %s\n", d, t.Truncate(d).Format("15:04:05.999999999"))
}
// Output:
- // t.Truncate( 1ns) = 12:15:30.918273645
- // t.Truncate( 1µs) = 12:15:30.918273
- // t.Truncate( 1ms) = 12:15:30.918
- // t.Truncate( 1s) = 12:15:30
- // t.Truncate( 2s) = 12:15:30
- // t.Truncate( 1m0s) = 12:15:00
- // t.Truncate( 10m0s) = 12:10:00
- // t.Truncate(1h0m0s) = 12:00:00
+ // t.Truncate( 1ns) = 12:15:30.918273645
+ // t.Truncate( 1µs) = 12:15:30.918273
+ // t.Truncate( 1ms) = 12:15:30.918
+ // t.Truncate( 1s) = 12:15:30
+ // t.Truncate( 2s) = 12:15:30
+ // t.Truncate( 1m0s) = 12:15:00
+ // t.Truncate(10m0s) = 12:10:00
}
diff --git a/libgo/go/time/export_android_test.go b/libgo/go/time/export_android_test.go
new file mode 100644
index 00000000000..fa6a058a73b
--- /dev/null
+++ b/libgo/go/time/export_android_test.go
@@ -0,0 +1,12 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package time
+
+func ForceAndroidTzdataForTest(tzdata bool) {
+ tzdataPaths = origTzdataPaths
+ if tzdata {
+ tzdataPaths = tzdataPaths[:1]
+ }
+}
diff --git a/libgo/go/time/format.go b/libgo/go/time/format.go
index c2ae7930203..b903e1485c6 100644
--- a/libgo/go/time/format.go
+++ b/libgo/go/time/format.go
@@ -42,6 +42,13 @@ import "errors"
// Z07:00 Z or ±hh:mm
// Z07 Z or ±hh
//
+// The recognized day of week formats are "Mon" and "Monday".
+// The recognized month formats are "Jan" and "January".
+//
+// Text in the format string that is not recognized as part of the reference
+// time is echoed verbatim during Format and expected to appear verbatim
+// in the input to Parse.
+//
// The executable example for time.Format demonstrates the working
// of the layout string in detail and is a good reference.
//
@@ -844,6 +851,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
sec, value, err = getnum(value, std == stdZeroSecond)
if sec < 0 || 60 <= sec {
rangeErrString = "second"
+ break
}
// Special case: do we have a fractional second but no
// fractional second in the format?
@@ -1004,7 +1012,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
}
// Validate the day of the month.
- if day > daysIn(Month(month), year) {
+ if day < 1 || day > daysIn(Month(month), year) {
return Time{}, &ParseError{alayout, avalue, "", value, ": day out of range"}
}
@@ -1020,12 +1028,12 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
// If that zone was in effect at the given time, use it.
name, offset, _, _, _ := local.lookup(t.sec + internalToUnix)
if offset == zoneOffset && (zoneName == "" || name == zoneName) {
- t.loc = local
+ t.setLoc(local)
return t, nil
}
// Otherwise create fake zone to record offset.
- t.loc = FixedZone(zoneName, zoneOffset)
+ t.setLoc(FixedZone(zoneName, zoneOffset))
return t, nil
}
@@ -1036,7 +1044,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
offset, _, ok := local.lookupName(zoneName, t.sec+internalToUnix)
if ok {
t.sec -= int64(offset)
- t.loc = local
+ t.setLoc(local)
return t, nil
}
@@ -1045,7 +1053,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
offset, _ = atoi(zoneName[3:]) // Guaranteed OK by parseGMT.
offset *= 3600
}
- t.loc = FixedZone(zoneName, offset)
+ t.setLoc(FixedZone(zoneName, offset))
return t, nil
}
@@ -1093,8 +1101,9 @@ func parseTimeZone(value string) (length int, ok bool) {
if value[4] == 'T' {
return 5, true
}
- case 4: // Must end in T to match.
- if value[3] == 'T' {
+ case 4:
+ // Must end in T, except one special case.
+ if value[3] == 'T' || value[:4] == "WITA" {
return 4, true
}
case 3:
@@ -1173,6 +1182,37 @@ func leadingInt(s string) (x int64, rem string, err error) {
return x, s[i:], nil
}
+// leadingFraction consumes the leading [0-9]* from s.
+// It is used only for fractions, so does not return an error on overflow,
+// it just stops accumulating precision.
+func leadingFraction(s string) (x int64, scale float64, rem string) {
+ i := 0
+ scale = 1
+ overflow := false
+ for ; i < len(s); i++ {
+ c := s[i]
+ if c < '0' || c > '9' {
+ break
+ }
+ if overflow {
+ continue
+ }
+ if x > (1<<63-1)/10 {
+ // It's possible for overflow to give a positive number, so take care.
+ overflow = true
+ continue
+ }
+ y := x*10 + int64(c) - '0'
+ if y < 0 {
+ overflow = true
+ continue
+ }
+ x = y
+ scale *= 10
+ }
+ return x, scale, s[i:]
+}
+
var unitMap = map[string]int64{
"ns": int64(Nanosecond),
"us": int64(Microsecond),
@@ -1235,13 +1275,7 @@ func ParseDuration(s string) (Duration, error) {
if s != "" && s[0] == '.' {
s = s[1:]
pl := len(s)
- f, s, err = leadingInt(s)
- if err != nil {
- return 0, errors.New("time: invalid duration " + orig)
- }
- for n := pl - len(s); n > 0; n-- {
- scale *= 10
- }
+ f, scale, s = leadingFraction(s)
post = pl != len(s)
}
if !pre && !post {
diff --git a/libgo/go/time/format_test.go b/libgo/go/time/format_test.go
index ed5509b3021..648ead0886c 100644
--- a/libgo/go/time/format_test.go
+++ b/libgo/go/time/format_test.go
@@ -224,6 +224,7 @@ var dayOutOfRangeTests = []struct {
{"Thu Nov 31 21:00:57 2010", false},
{"Thu Dec 31 21:00:57 2010", true},
{"Thu Dec 32 21:00:57 2010", false},
+ {"Thu Dec 00 21:00:57 2010", false},
}
func TestParseDayOutOfRange(t *testing.T) {
@@ -406,6 +407,7 @@ var parseTimeZoneTests = []ParseTimeZoneTest{
{"ESAST hi", 5, true},
{"ESASTT hi", 0, false}, // run of upper-case letters too long.
{"ESATY hi", 0, false}, // five letters must end in T.
+ {"WITA hi", 4, true}, // Issue #18251
}
func TestParseTimeZone(t *testing.T) {
@@ -442,6 +444,8 @@ var parseErrorTests = []ParseErrorTest{
{RFC3339, "2006-01-02T15:04_abc", `parsing time "2006-01-02T15:04_abc" as "2006-01-02T15:04:05Z07:00": cannot parse "_abc" as ":"`},
{RFC3339, "2006-01-02T15:04:05_abc", `parsing time "2006-01-02T15:04:05_abc" as "2006-01-02T15:04:05Z07:00": cannot parse "_abc" as "Z07:00"`},
{RFC3339, "2006-01-02T15:04:05Z_abc", `parsing time "2006-01-02T15:04:05Z_abc": extra text: _abc`},
+ // invalid second followed by optional fractional seconds
+ {RFC3339, "2010-02-04T21:00:67.012345678-08:00", "second out of range"},
}
func TestParseErrors(t *testing.T) {
diff --git a/libgo/go/time/sleep.go b/libgo/go/time/sleep.go
index 73114f5eecd..4b01404896e 100644
--- a/libgo/go/time/sleep.go
+++ b/libgo/go/time/sleep.go
@@ -12,7 +12,7 @@ func Sleep(d Duration)
func runtimeNano() int64
// Interface to timers implemented in package runtime.
-// Must be in sync with ../runtime/runtime.h:/^struct.Timer$
+// Must be in sync with ../runtime/time.go:/^type timer
type runtimeTimer struct {
i int
when int64
@@ -55,13 +55,22 @@ type Timer struct {
// Stop does not close the channel, to prevent a read from the channel succeeding
// incorrectly.
//
-// To prevent the timer firing after a call to Stop,
-// check the return value and drain the channel. For example:
+// To prevent a timer created with NewTimer from firing after a call to Stop,
+// check the return value and drain the channel.
+// For example, assuming the program has not received from t.C already:
+//
// if !t.Stop() {
// <-t.C
// }
+//
// This cannot be done concurrent to other receives from the Timer's
// channel.
+//
+// For a timer created with AfterFunc(d, f), if t.Stop returns false, then the timer
+// has already expired and the function f has been started in its own goroutine;
+// Stop does not wait for f to complete before returning.
+// If the caller needs to know whether f is completed, it must coordinate
+// with f explicitly.
func (t *Timer) Stop() bool {
if t.r.f == nil {
panic("time: Stop called on uninitialized Timer")
@@ -89,18 +98,25 @@ func NewTimer(d Duration) *Timer {
// It returns true if the timer had been active, false if the timer had
// expired or been stopped.
//
-// To reuse an active timer, always call its Stop method first and—if it had
-// expired—drain the value from its channel. For example:
+// Resetting a timer must take care not to race with the send into t.C
+// that happens when the current timer expires.
+// If a program has already received a value from t.C, the timer is known
+// to have expired, and t.Reset can be used directly.
+// If a program has not yet received a value from t.C, however,
+// the timer must be stopped and—if Stop reports that the timer expired
+// before being stopped—the channel explicitly drained:
+//
// if !t.Stop() {
// <-t.C
// }
// t.Reset(d)
+//
// This should not be done concurrent to other receives from the Timer's
// channel.
//
// Note that it is not possible to use Reset's return value correctly, as there
// is a race condition between draining the channel and the new timer expiring.
-// Reset should always be used in concert with Stop, as described above.
+// Reset should always be invoked on stopped or expired channels, as described above.
// The return value exists to preserve compatibility with existing programs.
func (t *Timer) Reset(d Duration) bool {
if t.r.f == nil {
diff --git a/libgo/go/time/time.go b/libgo/go/time/time.go
index c31de357d58..10b32461e1c 100644
--- a/libgo/go/time/time.go
+++ b/libgo/go/time/time.go
@@ -4,7 +4,8 @@
// Package time provides functionality for measuring and displaying time.
//
-// The calendrical calculations always assume a Gregorian calendar.
+// The calendrical calculations always assume a Gregorian calendar, with
+// no leap seconds.
package time
import "errors"
@@ -49,11 +50,18 @@ type Time struct {
// loc specifies the Location that should be used to
// determine the minute, hour, month, day, and year
// that correspond to this Time.
- // Only the zero Time has a nil Location.
- // In that case it is interpreted to mean UTC.
+ // The nil location means UTC.
+ // All UTC times are represented with loc==nil, never loc==&utcLoc.
loc *Location
}
+func (t *Time) setLoc(loc *Location) {
+ if loc == &utcLoc {
+ loc = nil
+ }
+ t.loc = loc
+}
+
// After reports whether the time instant t is after u.
func (t Time) After(u Time) bool {
return t.sec > u.sec || t.sec == u.sec && t.nsec > u.nsec
@@ -67,8 +75,7 @@ func (t Time) Before(u Time) bool {
// Equal reports whether t and u represent the same time instant.
// Two times can be equal even if they are in different locations.
// For example, 6:00 +0200 CEST and 4:00 UTC are Equal.
-// This comparison is different from using t == u, which also compares
-// the locations.
+// Do not use == with Time values.
func (t Time) Equal(u Time) bool {
return t.sec == u.sec && t.nsec == u.nsec
}
@@ -107,7 +114,14 @@ var months = [...]string{
}
// String returns the English name of the month ("January", "February", ...).
-func (m Month) String() string { return months[m-1] }
+func (m Month) String() string {
+ if January <= m && m <= December {
+ return months[m-1]
+ }
+ buf := make([]byte, 20)
+ n := fmtInt(buf, uint64(m))
+ return "%!Month(" + string(buf[n:]) + ")"
+}
// A Weekday specifies a day of the week (Sunday = 0, ...).
type Weekday int
@@ -585,21 +599,21 @@ func (d Duration) Nanoseconds() int64 { return int64(d) }
func (d Duration) Seconds() float64 {
sec := d / Second
nsec := d % Second
- return float64(sec) + float64(nsec)*1e-9
+ return float64(sec) + float64(nsec)/1e9
}
// Minutes returns the duration as a floating point number of minutes.
func (d Duration) Minutes() float64 {
min := d / Minute
nsec := d % Minute
- return float64(min) + float64(nsec)*(1e-9/60)
+ return float64(min) + float64(nsec)/(60*1e9)
}
// Hours returns the duration as a floating point number of hours.
func (d Duration) Hours() float64 {
hour := d / Hour
nsec := d % Hour
- return float64(hour) + float64(nsec)*(1e-9/60/60)
+ return float64(hour) + float64(nsec)/(60*60*1e9)
}
// Add returns the time t+d.
@@ -640,6 +654,12 @@ func Since(t Time) Duration {
return Now().Sub(t)
}
+// Until returns the duration until t.
+// It is shorthand for t.Sub(time.Now()).
+func Until(t Time) Duration {
+ return t.Sub(Now())
+}
+
// AddDate returns the time corresponding to adding the
// given number of years, months, and days to t.
// For example, AddDate(-1, 2, 3) applied to January 1, 2011
@@ -651,7 +671,7 @@ func Since(t Time) Duration {
func (t Time) AddDate(years int, months int, days int) Time {
year, month, day := t.Date()
hour, min, sec := t.Clock()
- return Date(year+years, month+Month(months), day+days, hour, min, sec, int(t.nsec), t.loc)
+ return Date(year+years, month+Month(months), day+days, hour, min, sec, int(t.nsec), t.Location())
}
const (
@@ -781,13 +801,13 @@ func Now() Time {
// UTC returns t with the location set to UTC.
func (t Time) UTC() Time {
- t.loc = UTC
+ t.setLoc(&utcLoc)
return t
}
// Local returns t with the location set to local time.
func (t Time) Local() Time {
- t.loc = Local
+ t.setLoc(Local)
return t
}
@@ -798,7 +818,7 @@ func (t Time) In(loc *Location) Time {
if loc == nil {
panic("time: missing Location in call to Time.In")
}
- t.loc = loc
+ t.setLoc(loc)
return t
}
@@ -826,8 +846,9 @@ func (t Time) Unix() int64 {
// UnixNano returns t as a Unix time, the number of nanoseconds elapsed
// since January 1, 1970 UTC. The result is undefined if the Unix time
-// in nanoseconds cannot be represented by an int64. Note that this
-// means the result of calling UnixNano on the zero Time is undefined.
+// in nanoseconds cannot be represented by an int64 (a date before the year
+// 1678 or after 2262). Note that this means the result of calling UnixNano
+// on the zero Time is undefined.
func (t Time) UnixNano() int64 {
return (t.sec+internalToUnix)*1e9 + int64(t.nsec)
}
@@ -838,7 +859,7 @@ const timeBinaryVersion byte = 1
func (t Time) MarshalBinary() ([]byte, error) {
var offsetMin int16 // minutes east of UTC. -1 is UTC.
- if t.Location() == &utcLoc {
+ if t.Location() == UTC {
offsetMin = -1
} else {
_, offset := t.Zone()
@@ -899,11 +920,11 @@ func (t *Time) UnmarshalBinary(data []byte) error {
offset := int(int16(buf[1])|int16(buf[0])<<8) * 60
if offset == -1*60 {
- t.loc = &utcLoc
+ t.setLoc(&utcLoc)
} else if _, localoff, _, _, _ := Local.lookup(t.sec + internalToUnix); offset == localoff {
- t.loc = Local
+ t.setLoc(Local)
} else {
- t.loc = FixedZone("", offset)
+ t.setLoc(FixedZone("", offset))
}
return nil
@@ -942,6 +963,10 @@ func (t Time) MarshalJSON() ([]byte, error) {
// UnmarshalJSON implements the json.Unmarshaler interface.
// The time is expected to be a quoted string in RFC 3339 format.
func (t *Time) UnmarshalJSON(data []byte) error {
+ // Ignore null, like in the main JSON package.
+ if string(data) == "null" {
+ return nil
+ }
// Fractional seconds are handled implicitly by Parse.
var err error
*t, err = Parse(`"`+RFC3339+`"`, string(data))
@@ -1092,11 +1117,18 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T
unix -= int64(offset)
}
- return Time{unix + unixToInternal, int32(nsec), loc}
+ t := Time{unix + unixToInternal, int32(nsec), nil}
+ t.setLoc(loc)
+ return t
}
// Truncate returns the result of rounding t down to a multiple of d (since the zero time).
// If d <= 0, Truncate returns t unchanged.
+//
+// Truncate operates on the time as an absolute duration since the
+// zero time; it does not operate on the presentation form of the
+// time. Thus, Truncate(Hour) may return a time with a non-zero
+// minute, depending on the time's Location.
func (t Time) Truncate(d Duration) Time {
if d <= 0 {
return t
@@ -1108,6 +1140,11 @@ func (t Time) Truncate(d Duration) Time {
// Round returns the result of rounding t to the nearest multiple of d (since the zero time).
// The rounding behavior for halfway values is to round up.
// If d <= 0, Round returns t unchanged.
+//
+// Round operates on the time as an absolute duration since the
+// zero time; it does not operate on the presentation form of the
+// time. Thus, Round(Hour) may return a time with a non-zero
+// minute, depending on the time's Location.
func (t Time) Round(d Duration) Time {
if d <= 0 {
return t
diff --git a/libgo/go/time/time_test.go b/libgo/go/time/time_test.go
index c9665ea04b5..2922560f097 100644
--- a/libgo/go/time/time_test.go
+++ b/libgo/go/time/time_test.go
@@ -840,6 +840,10 @@ var parseDurationTests = []struct {
{"9223372036s854ms775us807ns", true, (1<<63 - 1) * Nanosecond},
// large negative value
{"-9223372036854775807ns", true, -1<<63 + 1*Nanosecond},
+ // huge string; issue 15011.
+ {"0.100000000000000000000h", true, 6 * Minute},
+ // This value tests the first overflow check in leadingFraction.
+ {"0.830103483285477580700h", true, 49*Minute + 48*Second + 372539827*Nanosecond},
// errors
{"", false, 0},
@@ -891,7 +895,7 @@ func TestLocationRace(t *testing.T) {
go func() {
c <- Now().String()
}()
- Now().String()
+ _ = Now().String()
<-c
Sleep(100 * Millisecond)
@@ -999,6 +1003,21 @@ func TestDurationNanoseconds(t *testing.T) {
}
}
+var secDurationTests = []struct {
+ d Duration
+ want float64
+}{
+ {Duration(300000000), 0.3},
+}
+
+func TestDurationSeconds(t *testing.T) {
+ for _, tt := range secDurationTests {
+ if got := tt.d.Seconds(); got != tt.want {
+ t.Errorf("d.Seconds() = %g; want: %g", got, tt.want)
+ }
+ }
+}
+
var minDurationTests = []struct {
d Duration
want float64
@@ -1007,6 +1026,7 @@ var minDurationTests = []struct {
{Duration(-1), -1 / 60e9},
{Duration(1), 1 / 60e9},
{Duration(60000000000), 1},
+ {Duration(3000), 5e-8},
}
func TestDurationMinutes(t *testing.T) {
@@ -1025,6 +1045,7 @@ var hourDurationTests = []struct {
{Duration(-1), -1 / 3600e9},
{Duration(1), 1 / 3600e9},
{Duration(3600000000000), 1},
+ {Duration(36), 1e-11},
}
func TestDurationHours(t *testing.T) {
@@ -1035,6 +1056,100 @@ func TestDurationHours(t *testing.T) {
}
}
+var defaultLocTests = []struct {
+ name string
+ f func(t1, t2 Time) bool
+}{
+ {"After", func(t1, t2 Time) bool { return t1.After(t2) == t2.After(t1) }},
+ {"Before", func(t1, t2 Time) bool { return t1.Before(t2) == t2.Before(t1) }},
+ {"Equal", func(t1, t2 Time) bool { return t1.Equal(t2) == t2.Equal(t1) }},
+
+ {"IsZero", func(t1, t2 Time) bool { return t1.IsZero() == t2.IsZero() }},
+ {"Date", func(t1, t2 Time) bool {
+ a1, b1, c1 := t1.Date()
+ a2, b2, c2 := t2.Date()
+ return a1 == a2 && b1 == b2 && c1 == c2
+ }},
+ {"Year", func(t1, t2 Time) bool { return t1.Year() == t2.Year() }},
+ {"Month", func(t1, t2 Time) bool { return t1.Month() == t2.Month() }},
+ {"Day", func(t1, t2 Time) bool { return t1.Day() == t2.Day() }},
+ {"Weekday", func(t1, t2 Time) bool { return t1.Weekday() == t2.Weekday() }},
+ {"ISOWeek", func(t1, t2 Time) bool {
+ a1, b1 := t1.ISOWeek()
+ a2, b2 := t2.ISOWeek()
+ return a1 == a2 && b1 == b2
+ }},
+ {"Clock", func(t1, t2 Time) bool {
+ a1, b1, c1 := t1.Clock()
+ a2, b2, c2 := t2.Clock()
+ return a1 == a2 && b1 == b2 && c1 == c2
+ }},
+ {"Hour", func(t1, t2 Time) bool { return t1.Hour() == t2.Hour() }},
+ {"Minute", func(t1, t2 Time) bool { return t1.Minute() == t2.Minute() }},
+ {"Second", func(t1, t2 Time) bool { return t1.Second() == t2.Second() }},
+ {"Nanosecond", func(t1, t2 Time) bool { return t1.Hour() == t2.Hour() }},
+ {"YearDay", func(t1, t2 Time) bool { return t1.YearDay() == t2.YearDay() }},
+
+ // Using Equal since Add don't modify loc using "==" will cause a fail
+ {"Add", func(t1, t2 Time) bool { return t1.Add(Hour).Equal(t2.Add(Hour)) }},
+ {"Sub", func(t1, t2 Time) bool { return t1.Sub(t2) == t2.Sub(t1) }},
+
+ //Original caus for this test case bug 15852
+ {"AddDate", func(t1, t2 Time) bool { return t1.AddDate(1991, 9, 3) == t2.AddDate(1991, 9, 3) }},
+
+ {"UTC", func(t1, t2 Time) bool { return t1.UTC() == t2.UTC() }},
+ {"Local", func(t1, t2 Time) bool { return t1.Local() == t2.Local() }},
+ {"In", func(t1, t2 Time) bool { return t1.In(UTC) == t2.In(UTC) }},
+
+ {"Local", func(t1, t2 Time) bool { return t1.Local() == t2.Local() }},
+ {"Zone", func(t1, t2 Time) bool {
+ a1, b1 := t1.Zone()
+ a2, b2 := t2.Zone()
+ return a1 == a2 && b1 == b2
+ }},
+
+ {"Unix", func(t1, t2 Time) bool { return t1.Unix() == t2.Unix() }},
+ {"UnixNano", func(t1, t2 Time) bool { return t1.UnixNano() == t2.UnixNano() }},
+
+ {"MarshalBinary", func(t1, t2 Time) bool {
+ a1, b1 := t1.MarshalBinary()
+ a2, b2 := t2.MarshalBinary()
+ return bytes.Equal(a1, a2) && b1 == b2
+ }},
+ {"GobEncode", func(t1, t2 Time) bool {
+ a1, b1 := t1.GobEncode()
+ a2, b2 := t2.GobEncode()
+ return bytes.Equal(a1, a2) && b1 == b2
+ }},
+ {"MarshalJSON", func(t1, t2 Time) bool {
+ a1, b1 := t1.MarshalJSON()
+ a2, b2 := t2.MarshalJSON()
+ return bytes.Equal(a1, a2) && b1 == b2
+ }},
+ {"MarshalText", func(t1, t2 Time) bool {
+ a1, b1 := t1.MarshalText()
+ a2, b2 := t2.MarshalText()
+ return bytes.Equal(a1, a2) && b1 == b2
+ }},
+
+ {"Truncate", func(t1, t2 Time) bool { return t1.Truncate(Hour).Equal(t2.Truncate(Hour)) }},
+ {"Round", func(t1, t2 Time) bool { return t1.Round(Hour).Equal(t2.Round(Hour)) }},
+
+ {"== Time{}", func(t1, t2 Time) bool { return (t1 == Time{}) == (t2 == Time{}) }},
+}
+
+func TestDefaultLoc(t *testing.T) {
+ //This test verifyes that all Time's methods behaves identical if loc is set
+ //as nil or UTC
+ for _, tt := range defaultLocTests {
+ t1 := Time{}
+ t2 := Time{}.UTC()
+ if !tt.f(t1, t2) {
+ t.Errorf("Time{} and Time{}.UTC() behave differently for %s", tt.name)
+ }
+ }
+}
+
func BenchmarkNow(b *testing.B) {
for i := 0; i < b.N; i++ {
t = Now()
@@ -1117,3 +1232,25 @@ func BenchmarkDay(b *testing.B) {
_ = t.Day()
}
}
+
+func TestMarshalBinaryZeroTime(t *testing.T) {
+ t0 := Time{}
+ enc, err := t0.MarshalBinary()
+ if err != nil {
+ t.Fatal(err)
+ }
+ t1 := Now() // not zero
+ if err := t1.UnmarshalBinary(enc); err != nil {
+ t.Fatal(err)
+ }
+ if t1 != t0 {
+ t.Errorf("t0=%#v\nt1=%#v\nwant identical structures", t0, t1)
+ }
+}
+
+// Issue 17720: Zero value of time.Month fails to print
+func TestZeroMonthString(t *testing.T) {
+ if got, want := Month(0).String(), "%!Month(0)"; got != want {
+ t.Errorf("zero month = %q; want %q", got, want)
+ }
+}
diff --git a/libgo/go/time/zoneinfo.go b/libgo/go/time/zoneinfo.go
index c56743933f9..fb0aa392404 100644
--- a/libgo/go/time/zoneinfo.go
+++ b/libgo/go/time/zoneinfo.go
@@ -9,6 +9,8 @@ import (
"syscall"
)
+//go:generate env ZONEINFO=$GOROOT/lib/time/zoneinfo.zip go run genzabbrs.go -output zoneinfo_abbrs_windows.go
+
// A Location maps time instants to the zone in use at that time.
// Typically, the Location represents the collection of time offsets
// in use in a geographical area, such as CEST and CET for central Europe.
diff --git a/libgo/go/time/zoneinfo_abbrs_windows.go b/libgo/go/time/zoneinfo_abbrs_windows.go
index 344a891d1a4..9425db844ca 100644
--- a/libgo/go/time/zoneinfo_abbrs_windows.go
+++ b/libgo/go/time/zoneinfo_abbrs_windows.go
@@ -13,92 +13,106 @@ type abbr struct {
}
var abbrs = map[string]abbr{
- "Egypt Standard Time": {"EET", "EET"}, // Africa/Cairo
- "Morocco Standard Time": {"WET", "WEST"}, // Africa/Casablanca
- "South Africa Standard Time": {"SAST", "SAST"}, // Africa/Johannesburg
- "W. Central Africa Standard Time": {"WAT", "WAT"}, // Africa/Lagos
- "E. Africa Standard Time": {"EAT", "EAT"}, // Africa/Nairobi
- "Libya Standard Time": {"EET", "EET"}, // Africa/Tripoli
- "Namibia Standard Time": {"WAT", "WAST"}, // Africa/Windhoek
- "Alaskan Standard Time": {"AKST", "AKDT"}, // America/Anchorage
- "Paraguay Standard Time": {"PYT", "PYST"}, // America/Asuncion
- "Bahia Standard Time": {"BRT", "BRT"}, // America/Bahia
- "SA Pacific Standard Time": {"COT", "COT"}, // America/Bogota
- "Argentina Standard Time": {"ART", "ART"}, // America/Buenos_Aires
- "Eastern Standard Time (Mexico)": {"EST", "EST"}, // America/Cancun
- "Venezuela Standard Time": {"VET", "VET"}, // America/Caracas
- "SA Eastern Standard Time": {"GFT", "GFT"}, // America/Cayenne
- "Central Standard Time": {"CST", "CDT"}, // America/Chicago
- "Mountain Standard Time (Mexico)": {"MST", "MDT"}, // America/Chihuahua
- "Central Brazilian Standard Time": {"AMT", "AMST"}, // America/Cuiaba
- "Mountain Standard Time": {"MST", "MDT"}, // America/Denver
- "Greenland Standard Time": {"WGT", "WGST"}, // America/Godthab
- "Central America Standard Time": {"CST", "CST"}, // America/Guatemala
- "Atlantic Standard Time": {"AST", "ADT"}, // America/Halifax
- "US Eastern Standard Time": {"EST", "EDT"}, // America/Indianapolis
- "SA Western Standard Time": {"BOT", "BOT"}, // America/La_Paz
- "Pacific Standard Time": {"PST", "PDT"}, // America/Los_Angeles
- "Central Standard Time (Mexico)": {"CST", "CDT"}, // America/Mexico_City
- "Montevideo Standard Time": {"UYT", "UYT"}, // America/Montevideo
- "Eastern Standard Time": {"EST", "EDT"}, // America/New_York
- "US Mountain Standard Time": {"MST", "MST"}, // America/Phoenix
- "Canada Central Standard Time": {"CST", "CST"}, // America/Regina
- "Pacific SA Standard Time": {"CLT", "CLST"}, // America/Santiago
- "E. South America Standard Time": {"BRT", "BRST"}, // America/Sao_Paulo
- "Newfoundland Standard Time": {"NST", "NDT"}, // America/St_Johns
- "Central Asia Standard Time": {"+06", "+06"}, // Asia/Almaty
- "Jordan Standard Time": {"EET", "EEST"}, // Asia/Amman
- "Arabic Standard Time": {"AST", "AST"}, // Asia/Baghdad
- "Azerbaijan Standard Time": {"AZT", "AZT"}, // Asia/Baku
- "SE Asia Standard Time": {"ICT", "ICT"}, // Asia/Bangkok
- "Altai Standard Time": {"+06", "+07"}, // Asia/Barnaul
- "Middle East Standard Time": {"EET", "EEST"}, // Asia/Beirut
- "India Standard Time": {"IST", "IST"}, // Asia/Calcutta
- "Transbaikal Standard Time": {"IRKT", "YAKT"}, // Asia/Chita
- "Sri Lanka Standard Time": {"IST", "IST"}, // Asia/Colombo
- "Syria Standard Time": {"EET", "EEST"}, // Asia/Damascus
- "Bangladesh Standard Time": {"BDT", "BDT"}, // Asia/Dhaka
- "Arabian Standard Time": {"GST", "GST"}, // Asia/Dubai
- "North Asia East Standard Time": {"IRKT", "IRKT"}, // Asia/Irkutsk
- "Israel Standard Time": {"IST", "IDT"}, // Asia/Jerusalem
- "Afghanistan Standard Time": {"AFT", "AFT"}, // Asia/Kabul
- "Russia Time Zone 11": {"PETT", "PETT"}, // Asia/Kamchatka
- "Pakistan Standard Time": {"PKT", "PKT"}, // Asia/Karachi
- "Nepal Standard Time": {"NPT", "NPT"}, // Asia/Katmandu
- "North Asia Standard Time": {"KRAT", "KRAT"}, // Asia/Krasnoyarsk
- "Magadan Standard Time": {"MAGT", "MAGT"}, // Asia/Magadan
- "N. Central Asia Standard Time": {"NOVT", "NOVT"}, // Asia/Novosibirsk
- "North Korea Standard Time": {"KST", "KST"}, // Asia/Pyongyang
- "Myanmar Standard Time": {"MMT", "MMT"}, // Asia/Rangoon
- "Arab Standard Time": {"AST", "AST"}, // Asia/Riyadh
- "Sakhalin Standard Time": {"SAKT", "SAKT"}, // Asia/Sakhalin
- "Korea Standard Time": {"KST", "KST"}, // Asia/Seoul
- "China Standard Time": {"CST", "CST"}, // Asia/Shanghai
- "Singapore Standard Time": {"SGT", "SGT"}, // Asia/Singapore
- "Russia Time Zone 10": {"SRET", "SRET"}, // Asia/Srednekolymsk
- "Taipei Standard Time": {"CST", "CST"}, // Asia/Taipei
- "West Asia Standard Time": {"UZT", "UZT"}, // Asia/Tashkent
- "Georgian Standard Time": {"GET", "GET"}, // Asia/Tbilisi
- "Iran Standard Time": {"IRST", "IRDT"}, // Asia/Tehran
- "Tokyo Standard Time": {"JST", "JST"}, // Asia/Tokyo
- "Ulaanbaatar Standard Time": {"ULAT", "ULAST"}, // Asia/Ulaanbaatar
- "Vladivostok Standard Time": {"VLAT", "VLAT"}, // Asia/Vladivostok
- "Yakutsk Standard Time": {"YAKT", "YAKT"}, // Asia/Yakutsk
- "Ekaterinburg Standard Time": {"YEKT", "YEKT"}, // Asia/Yekaterinburg
- "Caucasus Standard Time": {"AMT", "AMT"}, // Asia/Yerevan
- "Azores Standard Time": {"AZOT", "AZOST"}, // Atlantic/Azores
- "Cape Verde Standard Time": {"CVT", "CVT"}, // Atlantic/Cape_Verde
- "Greenwich Standard Time": {"GMT", "GMT"}, // Atlantic/Reykjavik
- "Cen. Australia Standard Time": {"ACST", "ACDT"}, // Australia/Adelaide
- "E. Australia Standard Time": {"AEST", "AEST"}, // Australia/Brisbane
- "AUS Central Standard Time": {"ACST", "ACST"}, // Australia/Darwin
- "Tasmania Standard Time": {"AEST", "AEDT"}, // Australia/Hobart
- "W. Australia Standard Time": {"AWST", "AWST"}, // Australia/Perth
- "AUS Eastern Standard Time": {"AEST", "AEDT"}, // Australia/Sydney
+ "Egypt Standard Time": {"EET", "EET"}, // Africa/Cairo
+ "Morocco Standard Time": {"WET", "WEST"}, // Africa/Casablanca
+ "South Africa Standard Time": {"SAST", "SAST"}, // Africa/Johannesburg
+ "W. Central Africa Standard Time": {"WAT", "WAT"}, // Africa/Lagos
+ "E. Africa Standard Time": {"EAT", "EAT"}, // Africa/Nairobi
+ "Libya Standard Time": {"EET", "EET"}, // Africa/Tripoli
+ "Namibia Standard Time": {"WAT", "WAST"}, // Africa/Windhoek
+ "Aleutian Standard Time": {"HST", "HDT"}, // America/Adak
+ "Alaskan Standard Time": {"AKST", "AKDT"}, // America/Anchorage
+ "Tocantins Standard Time": {"BRT", "BRT"}, // America/Araguaina
+ "Paraguay Standard Time": {"PYT", "PYST"}, // America/Asuncion
+ "Bahia Standard Time": {"BRT", "BRT"}, // America/Bahia
+ "SA Pacific Standard Time": {"COT", "COT"}, // America/Bogota
+ "Argentina Standard Time": {"ART", "ART"}, // America/Buenos_Aires
+ "Eastern Standard Time (Mexico)": {"EST", "EST"}, // America/Cancun
+ "Venezuela Standard Time": {"VET", "VET"}, // America/Caracas
+ "SA Eastern Standard Time": {"GFT", "GFT"}, // America/Cayenne
+ "Central Standard Time": {"CST", "CDT"}, // America/Chicago
+ "Mountain Standard Time (Mexico)": {"MST", "MDT"}, // America/Chihuahua
+ "Central Brazilian Standard Time": {"AMT", "AMST"}, // America/Cuiaba
+ "Mountain Standard Time": {"MST", "MDT"}, // America/Denver
+ "Greenland Standard Time": {"WGT", "WGST"}, // America/Godthab
+ "Turks And Caicos Standard Time": {"AST", "AST"}, // America/Grand_Turk
+ "Central America Standard Time": {"CST", "CST"}, // America/Guatemala
+ "Atlantic Standard Time": {"AST", "ADT"}, // America/Halifax
+ "Cuba Standard Time": {"CST", "CDT"}, // America/Havana
+ "US Eastern Standard Time": {"EST", "EDT"}, // America/Indianapolis
+ "SA Western Standard Time": {"BOT", "BOT"}, // America/La_Paz
+ "Pacific Standard Time": {"PST", "PDT"}, // America/Los_Angeles
+ "Central Standard Time (Mexico)": {"CST", "CDT"}, // America/Mexico_City
+ "Saint Pierre Standard Time": {"PMST", "PMDT"}, // America/Miquelon
+ "Montevideo Standard Time": {"UYT", "UYT"}, // America/Montevideo
+ "Eastern Standard Time": {"EST", "EDT"}, // America/New_York
+ "US Mountain Standard Time": {"MST", "MST"}, // America/Phoenix
+ "Haiti Standard Time": {"EST", "EST"}, // America/Port-au-Prince
+ "Canada Central Standard Time": {"CST", "CST"}, // America/Regina
+ "Pacific SA Standard Time": {"CLT", "CLST"}, // America/Santiago
+ "E. South America Standard Time": {"BRT", "BRST"}, // America/Sao_Paulo
+ "Newfoundland Standard Time": {"NST", "NDT"}, // America/St_Johns
+ "Pacific Standard Time (Mexico)": {"PST", "PDT"}, // America/Tijuana
+ "Central Asia Standard Time": {"+06", "+06"}, // Asia/Almaty
+ "Jordan Standard Time": {"EET", "EEST"}, // Asia/Amman
+ "Arabic Standard Time": {"AST", "AST"}, // Asia/Baghdad
+ "Azerbaijan Standard Time": {"AZT", "AZT"}, // Asia/Baku
+ "SE Asia Standard Time": {"ICT", "ICT"}, // Asia/Bangkok
+ "Altai Standard Time": {"+06", "+07"}, // Asia/Barnaul
+ "Middle East Standard Time": {"EET", "EEST"}, // Asia/Beirut
+ "India Standard Time": {"IST", "IST"}, // Asia/Calcutta
+ "Transbaikal Standard Time": {"IRKT", "YAKT"}, // Asia/Chita
+ "Sri Lanka Standard Time": {"IST", "IST"}, // Asia/Colombo
+ "Syria Standard Time": {"EET", "EEST"}, // Asia/Damascus
+ "Bangladesh Standard Time": {"BDT", "BDT"}, // Asia/Dhaka
+ "Arabian Standard Time": {"GST", "GST"}, // Asia/Dubai
+ "West Bank Standard Time": {"EET", "EEST"}, // Asia/Hebron
+ "W. Mongolia Standard Time": {"HOVT", "HOVST"}, // Asia/Hovd
+ "North Asia East Standard Time": {"IRKT", "IRKT"}, // Asia/Irkutsk
+ "Israel Standard Time": {"IST", "IDT"}, // Asia/Jerusalem
+ "Afghanistan Standard Time": {"AFT", "AFT"}, // Asia/Kabul
+ "Russia Time Zone 11": {"PETT", "PETT"}, // Asia/Kamchatka
+ "Pakistan Standard Time": {"PKT", "PKT"}, // Asia/Karachi
+ "Nepal Standard Time": {"NPT", "NPT"}, // Asia/Katmandu
+ "North Asia Standard Time": {"KRAT", "KRAT"}, // Asia/Krasnoyarsk
+ "Magadan Standard Time": {"MAGT", "MAGT"}, // Asia/Magadan
+ "N. Central Asia Standard Time": {"+06", "+07"}, // Asia/Novosibirsk
+ "North Korea Standard Time": {"KST", "KST"}, // Asia/Pyongyang
+ "Myanmar Standard Time": {"MMT", "MMT"}, // Asia/Rangoon
+ "Arab Standard Time": {"AST", "AST"}, // Asia/Riyadh
+ "Sakhalin Standard Time": {"SAKT", "SAKT"}, // Asia/Sakhalin
+ "Korea Standard Time": {"KST", "KST"}, // Asia/Seoul
+ "China Standard Time": {"CST", "CST"}, // Asia/Shanghai
+ "Singapore Standard Time": {"SGT", "SGT"}, // Asia/Singapore
+ "Russia Time Zone 10": {"SRET", "SRET"}, // Asia/Srednekolymsk
+ "Taipei Standard Time": {"CST", "CST"}, // Asia/Taipei
+ "West Asia Standard Time": {"UZT", "UZT"}, // Asia/Tashkent
+ "Georgian Standard Time": {"GET", "GET"}, // Asia/Tbilisi
+ "Iran Standard Time": {"IRST", "IRDT"}, // Asia/Tehran
+ "Tokyo Standard Time": {"JST", "JST"}, // Asia/Tokyo
+ "Tomsk Standard Time": {"+06", "+07"}, // Asia/Tomsk
+ "Ulaanbaatar Standard Time": {"ULAT", "ULAST"}, // Asia/Ulaanbaatar
+ "Vladivostok Standard Time": {"VLAT", "VLAT"}, // Asia/Vladivostok
+ "Yakutsk Standard Time": {"YAKT", "YAKT"}, // Asia/Yakutsk
+ "Ekaterinburg Standard Time": {"YEKT", "YEKT"}, // Asia/Yekaterinburg
+ "Caucasus Standard Time": {"AMT", "AMT"}, // Asia/Yerevan
+ "Azores Standard Time": {"AZOT", "AZOST"}, // Atlantic/Azores
+ "Cape Verde Standard Time": {"CVT", "CVT"}, // Atlantic/Cape_Verde
+ "Greenwich Standard Time": {"GMT", "GMT"}, // Atlantic/Reykjavik
+ "Cen. Australia Standard Time": {"ACST", "ACDT"}, // Australia/Adelaide
+ "E. Australia Standard Time": {"AEST", "AEST"}, // Australia/Brisbane
+ "AUS Central Standard Time": {"ACST", "ACST"}, // Australia/Darwin
+ "Aus Central W. Standard Time": {"ACWST", "ACWST"}, // Australia/Eucla
+ "Tasmania Standard Time": {"AEST", "AEDT"}, // Australia/Hobart
+ "Lord Howe Standard Time": {"LHST", "LHDT"}, // Australia/Lord_Howe
+ "W. Australia Standard Time": {"AWST", "AWST"}, // Australia/Perth
+ "AUS Eastern Standard Time": {"AEST", "AEDT"}, // Australia/Sydney
"UTC": {"GMT", "GMT"}, // Etc/GMT
"UTC-11": {"GMT+11", "GMT+11"}, // Etc/GMT+11
"Dateline Standard Time": {"GMT+12", "GMT+12"}, // Etc/GMT+12
"UTC-02": {"GMT+2", "GMT+2"}, // Etc/GMT+2
+ "UTC-08": {"GMT+8", "GMT+8"}, // Etc/GMT+8
+ "UTC-09": {"GMT+9", "GMT+9"}, // Etc/GMT+9
"UTC+12": {"GMT-12", "GMT-12"}, // Etc/GMT-12
"Astrakhan Standard Time": {"+03", "+04"}, // Europe/Astrakhan
"W. Europe Standard Time": {"CET", "CEST"}, // Europe/Berlin
@@ -117,10 +131,15 @@ var abbrs = map[string]abbr{
"Mauritius Standard Time": {"MUT", "MUT"}, // Indian/Mauritius
"Samoa Standard Time": {"WSST", "WSDT"}, // Pacific/Apia
"New Zealand Standard Time": {"NZST", "NZDT"}, // Pacific/Auckland
+ "Bougainville Standard Time": {"BST", "BST"}, // Pacific/Bougainville
+ "Chatham Islands Standard Time": {"CHAST", "CHADT"}, // Pacific/Chatham
+ "Easter Island Standard Time": {"EAST", "EASST"}, // Pacific/Easter
"Fiji Standard Time": {"FJT", "FJST"}, // Pacific/Fiji
"Central Pacific Standard Time": {"SBT", "SBT"}, // Pacific/Guadalcanal
"Hawaiian Standard Time": {"HST", "HST"}, // Pacific/Honolulu
"Line Islands Standard Time": {"LINT", "LINT"}, // Pacific/Kiritimati
+ "Marquesas Standard Time": {"MART", "MART"}, // Pacific/Marquesas
+ "Norfolk Standard Time": {"NFT", "NFT"}, // Pacific/Norfolk
"West Pacific Standard Time": {"PGT", "PGT"}, // Pacific/Port_Moresby
"Tonga Standard Time": {"TOT", "TOT"}, // Pacific/Tongatapu
}
diff --git a/libgo/go/time/zoneinfo_android.go b/libgo/go/time/zoneinfo_android.go
new file mode 100644
index 00000000000..695a8adfaa3
--- /dev/null
+++ b/libgo/go/time/zoneinfo_android.go
@@ -0,0 +1,119 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Parse the "tzdata" packed timezone file used on Android.
+// The format is lifted from ZoneInfoDB.java and ZoneInfo.java in
+// java/libcore/util in the AOSP.
+
+package time
+
+import (
+ "errors"
+ "runtime"
+)
+
+var tzdataPaths = []string{
+ "/system/usr/share/zoneinfo/tzdata",
+ "/data/misc/zoneinfo/current/tzdata",
+ runtime.GOROOT() + "/lib/time/zoneinfo.zip",
+}
+
+var origTzdataPaths = tzdataPaths
+
+func forceZipFileForTesting(zipOnly bool) {
+ tzdataPaths = make([]string, len(origTzdataPaths))
+ copy(tzdataPaths, origTzdataPaths)
+ if zipOnly {
+ for i := 0; i < len(tzdataPaths)-1; i++ {
+ tzdataPaths[i] = "/XXXNOEXIST"
+ }
+ }
+}
+
+func initTestingZone() {
+ z, err := loadLocation("America/Los_Angeles")
+ if err != nil {
+ panic("cannot load America/Los_Angeles for testing: " + err.Error())
+ }
+ z.name = "Local"
+ localLoc = *z
+}
+
+func initLocal() {
+ // TODO(elias.naur): getprop persist.sys.timezone
+ localLoc = *UTC
+}
+
+func loadLocation(name string) (*Location, error) {
+ var firstErr error
+ for _, path := range tzdataPaths {
+ var z *Location
+ var err error
+ if len(path) > 4 && path[len(path)-4:] == ".zip" {
+ z, err = loadZoneZip(path, name)
+ } else {
+ z, err = loadTzdataFile(path, name)
+ }
+ if err == nil {
+ z.name = name
+ return z, nil
+ } else if firstErr == nil && !isNotExist(err) {
+ firstErr = err
+ }
+ }
+ if firstErr != nil {
+ return nil, firstErr
+ }
+ return nil, errors.New("unknown time zone " + name)
+}
+
+func loadTzdataFile(file, name string) (*Location, error) {
+ const (
+ headersize = 12 + 3*4
+ namesize = 40
+ entrysize = namesize + 3*4
+ )
+ if len(name) > namesize {
+ return nil, errors.New(name + " is longer than the maximum zone name length (40 bytes)")
+ }
+ fd, err := open(file)
+ if err != nil {
+ return nil, err
+ }
+ defer closefd(fd)
+
+ buf := make([]byte, headersize)
+ if err := preadn(fd, buf, 0); err != nil {
+ return nil, errors.New("corrupt tzdata file " + file)
+ }
+ d := data{buf, false}
+ if magic := d.read(6); string(magic) != "tzdata" {
+ return nil, errors.New("corrupt tzdata file " + file)
+ }
+ d = data{buf[12:], false}
+ indexOff, _ := d.big4()
+ dataOff, _ := d.big4()
+ indexSize := dataOff - indexOff
+ entrycount := indexSize / entrysize
+ buf = make([]byte, indexSize)
+ if err := preadn(fd, buf, int(indexOff)); err != nil {
+ return nil, errors.New("corrupt tzdata file " + file)
+ }
+ for i := 0; i < int(entrycount); i++ {
+ entry := buf[i*entrysize : (i+1)*entrysize]
+ // len(name) <= namesize is checked at function entry
+ if string(entry[:len(name)]) != name {
+ continue
+ }
+ d := data{entry[namesize:], false}
+ off, _ := d.big4()
+ size, _ := d.big4()
+ buf := make([]byte, size)
+ if err := preadn(fd, buf, int(off+dataOff)); err != nil {
+ return nil, errors.New("corrupt tzdata file " + file)
+ }
+ return loadZoneData(buf)
+ }
+ return nil, errors.New("cannot find " + name + " in tzdata file " + file)
+}
diff --git a/libgo/go/time/zoneinfo_android_test.go b/libgo/go/time/zoneinfo_android_test.go
new file mode 100644
index 00000000000..ba065d10a65
--- /dev/null
+++ b/libgo/go/time/zoneinfo_android_test.go
@@ -0,0 +1,18 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package time_test
+
+import (
+ "testing"
+ . "time"
+)
+
+func TestAndroidTzdata(t *testing.T) {
+ ForceAndroidTzdataForTest(true)
+ defer ForceAndroidTzdataForTest(false)
+ if _, err := LoadLocation("America/Los_Angeles"); err != nil {
+ t.Error(err)
+ }
+}
diff --git a/libgo/go/time/zoneinfo_unix.go b/libgo/go/time/zoneinfo_unix.go
index 6c7aafff77b..772748818a9 100644
--- a/libgo/go/time/zoneinfo_unix.go
+++ b/libgo/go/time/zoneinfo_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,386 darwin,amd64 dragonfly freebsd linux nacl netbsd openbsd solaris
+// +build darwin,386 darwin,amd64 dragonfly freebsd linux,!android nacl netbsd openbsd solaris
// Parse "zoneinfo" time zone file.
// This is a fairly standard file format used on OS X, Linux, BSD, Sun, and others.
diff --git a/libgo/go/time/zoneinfo_windows.go b/libgo/go/time/zoneinfo_windows.go
index a6546f54b86..a6e227b5b0d 100644
--- a/libgo/go/time/zoneinfo_windows.go
+++ b/libgo/go/time/zoneinfo_windows.go
@@ -11,8 +11,6 @@ import (
"syscall"
)
-//go:generate go run genzabbrs.go -output zoneinfo_abbrs_windows.go
-
// TODO(rsc): Fall back to copy of zoneinfo files.
// BUG(brainman,rsc): On Windows, the operating system does not provide complete
diff --git a/libgo/go/unicode/letter.go b/libgo/go/unicode/letter.go
index 8aec920d22f..b43cc66e7d3 100644
--- a/libgo/go/unicode/letter.go
+++ b/libgo/go/unicode/letter.go
@@ -320,6 +320,7 @@ type foldPair struct {
// the Unicode-defined simple case folding. Among the code points
// equivalent to rune (including rune itself), SimpleFold returns the
// smallest rune > r if one exists, or else the smallest rune >= 0.
+// If r is not a valid Unicode code point, SimpleFold(r) returns r.
//
// For example:
// SimpleFold('A') = 'a'
@@ -331,7 +332,13 @@ type foldPair struct {
//
// SimpleFold('1') = '1'
//
+// SimpleFold(-2) = -2
+//
func SimpleFold(r rune) rune {
+ if r < 0 || r > MaxRune {
+ return r
+ }
+
if int(r) < len(asciiFold) {
return rune(asciiFold[r])
}
diff --git a/libgo/go/unicode/letter_test.go b/libgo/go/unicode/letter_test.go
index 0eb9ee95b08..3fe72ff13d2 100644
--- a/libgo/go/unicode/letter_test.go
+++ b/libgo/go/unicode/letter_test.go
@@ -432,6 +432,10 @@ func TestSimpleFold(t *testing.T) {
r = out
}
}
+
+ if r := SimpleFold(-42); r != -42 {
+ t.Errorf("SimpleFold(-42) = %v, want -42", r)
+ }
}
// Running 'go test -calibrate' runs the calibration to find a plausible
diff --git a/libgo/go/unicode/utf8/utf8.go b/libgo/go/unicode/utf8/utf8.go
index 9d35be6c065..6ccd4643738 100644
--- a/libgo/go/unicode/utf8/utf8.go
+++ b/libgo/go/unicode/utf8/utf8.go
@@ -347,6 +347,7 @@ func EncodeRune(p []byte, r rune) int {
p[0] = byte(r)
return 1
case i <= rune2Max:
+ _ = p[1] // eliminate bounds checks
p[0] = t2 | byte(r>>6)
p[1] = tx | byte(r)&maskx
return 2
@@ -354,11 +355,13 @@ func EncodeRune(p []byte, r rune) int {
r = RuneError
fallthrough
case i <= rune3Max:
+ _ = p[2] // eliminate bounds checks
p[0] = t3 | byte(r>>12)
p[1] = tx | byte(r>>6)&maskx
p[2] = tx | byte(r)&maskx
return 3
default:
+ _ = p[3] // eliminate bounds checks
p[0] = t4 | byte(r>>18)
p[1] = tx | byte(r>>12)&maskx
p[2] = tx | byte(r>>6)&maskx
@@ -513,12 +516,10 @@ func ValidString(s string) bool {
// Code points that are out of range or a surrogate half are illegal.
func ValidRune(r rune) bool {
switch {
- case r < 0:
- return false
- case surrogateMin <= r && r <= surrogateMax:
- return false
- case r > MaxRune:
- return false
+ case 0 <= r && r < surrogateMin:
+ return true
+ case surrogateMax < r && r <= MaxRune:
+ return true
}
- return true
+ return false
}
diff --git a/libgo/go/unicode/utf8/utf8_test.go b/libgo/go/unicode/utf8/utf8_test.go
index 51571b61eb9..dc9c4251bd9 100644
--- a/libgo/go/unicode/utf8/utf8_test.go
+++ b/libgo/go/unicode/utf8/utf8_test.go
@@ -54,14 +54,18 @@ var utf8map = []Utf8Map{
{0x00ff, "\xc3\xbf"},
{0x0100, "\xc4\x80"},
{0x07ff, "\xdf\xbf"},
+ {0x0400, "\xd0\x80"},
{0x0800, "\xe0\xa0\x80"},
{0x0801, "\xe0\xa0\x81"},
+ {0x1000, "\xe1\x80\x80"},
+ {0xd000, "\xed\x80\x80"},
{0xd7ff, "\xed\x9f\xbf"}, // last code point before surrogate half.
{0xe000, "\xee\x80\x80"}, // first code point after surrogate half.
{0xfffe, "\xef\xbf\xbe"},
{0xffff, "\xef\xbf\xbf"},
{0x10000, "\xf0\x90\x80\x80"},
{0x10001, "\xf0\x90\x80\x81"},
+ {0x40000, "\xf1\x80\x80\x80"},
{0x10fffe, "\xf4\x8f\xbf\xbe"},
{0x10ffff, "\xf4\x8f\xbf\xbf"},
{0xFFFD, "\xef\xbf\xbd"},
@@ -228,6 +232,93 @@ func TestIntConversion(t *testing.T) {
}
}
+var invalidSequenceTests = []string{
+ "\xed\xa0\x80\x80", // surrogate min
+ "\xed\xbf\xbf\x80", // surrogate max
+
+ // xx
+ "\x91\x80\x80\x80",
+
+ // s1
+ "\xC2\x7F\x80\x80",
+ "\xC2\xC0\x80\x80",
+ "\xDF\x7F\x80\x80",
+ "\xDF\xC0\x80\x80",
+
+ // s2
+ "\xE0\x9F\xBF\x80",
+ "\xE0\xA0\x7F\x80",
+ "\xE0\xBF\xC0\x80",
+ "\xE0\xC0\x80\x80",
+
+ // s3
+ "\xE1\x7F\xBF\x80",
+ "\xE1\x80\x7F\x80",
+ "\xE1\xBF\xC0\x80",
+ "\xE1\xC0\x80\x80",
+
+ //s4
+ "\xED\x7F\xBF\x80",
+ "\xED\x80\x7F\x80",
+ "\xED\x9F\xC0\x80",
+ "\xED\xA0\x80\x80",
+
+ // s5
+ "\xF0\x8F\xBF\xBF",
+ "\xF0\x90\x7F\xBF",
+ "\xF0\x90\x80\x7F",
+ "\xF0\xBF\xBF\xC0",
+ "\xF0\xBF\xC0\x80",
+ "\xF0\xC0\x80\x80",
+
+ // s6
+ "\xF1\x7F\xBF\xBF",
+ "\xF1\x80\x7F\xBF",
+ "\xF1\x80\x80\x7F",
+ "\xF1\xBF\xBF\xC0",
+ "\xF1\xBF\xC0\x80",
+ "\xF1\xC0\x80\x80",
+
+ // s7
+ "\xF4\x7F\xBF\xBF",
+ "\xF4\x80\x7F\xBF",
+ "\xF4\x80\x80\x7F",
+ "\xF4\x8F\xBF\xC0",
+ "\xF4\x8F\xC0\x80",
+ "\xF4\x90\x80\x80",
+}
+
+func runtimeDecodeRune(s string) rune {
+ for _, r := range s {
+ return r
+ }
+ return -1
+}
+
+func TestDecodeInvalidSequence(t *testing.T) {
+ for _, s := range invalidSequenceTests {
+ r1, _ := DecodeRune([]byte(s))
+ if want := RuneError; r1 != want {
+ t.Errorf("DecodeRune(%#x) = %#04x, want %#04x", s, r1, want)
+ return
+ }
+ r2, _ := DecodeRuneInString(s)
+ if want := RuneError; r2 != want {
+ t.Errorf("DecodeRuneInString(%q) = %#04x, want %#04x", s, r2, want)
+ return
+ }
+ if r1 != r2 {
+ t.Errorf("DecodeRune(%#x) = %#04x mismatch with DecodeRuneInString(%q) = %#04x", s, r1, s, r2)
+ return
+ }
+ r3 := runtimeDecodeRune(s)
+ if r2 != r3 {
+ t.Errorf("DecodeRuneInString(%q) = %#04x mismatch with runtime.decoderune(%q) = %#04x", s, r2, s, r3)
+ return
+ }
+ }
+}
+
func testSequence(t *testing.T, s string) {
type info struct {
index int
diff --git a/libgo/match.sh b/libgo/match.sh
index 23db19478fa..94bcbc83c64 100755
--- a/libgo/match.sh
+++ b/libgo/match.sh
@@ -151,18 +151,18 @@ for f in $gofiles; do
fi
match=false
;;
- $goos | $goarch | $cgotag | $cmdlinetag)
+ $goos | $goarch | $cgotag | $cmdlinetag | "gccgo")
match=true
;;
- "!"$goos | "!"$goarch | "!"$cgotag | "!"$cmdlinetag)
+ "!"$goos | "!"$goarch | "!"$cgotag | "!"$cmdlinetag | "!gccgo")
;;
*,*)
cmatch=true
for ctag in `echo $tag | sed -e 's/,/ /g'`; do
case $ctag in
- $goos | $goarch | $cgotag | $cmdlinetag)
+ $goos | $goarch | $cgotag | $cmdlinetag | "gccgo")
;;
- "!"$goos | "!"$goarch | "!"$cgotag | "!"$cmdlinetag)
+ "!"$goos | "!"$goarch | "!"$cgotag | "!"$cmdlinetag | "!gccgo")
cmatch=false
;;
"!"*)
diff --git a/libgo/merge.sh b/libgo/merge.sh
index 373937cf796..8a92a2ecd4d 100755
--- a/libgo/merge.sh
+++ b/libgo/merge.sh
@@ -99,8 +99,7 @@ merge() {
mv ${libgo}.tmp ${libgo}
;;
*)
- echo 1>&2 "merge.sh: $name: diff3 failure"
- exit 1
+ echo 1>&2 "merge.sh: $name: DIFF3 FAILURE"
;;
esac
fi
@@ -122,35 +121,51 @@ merge() {
fi
}
-merge_c() {
- from=$1
- to=$2
- oldfile=${OLDDIR}/src/runtime/$from
- if test -f ${oldfile}; then
- sed -e 's/·/_/g' < ${oldfile} > ${oldfile}.tmp
- oldfile=${oldfile}.tmp
- newfile=${NEWDIR}/src/runtime/$from
- sed -e 's/·/_/g' < ${newfile} > ${newfile}.tmp
- newfile=${newfile}.tmp
- libgofile=runtime/$to
- merge $from ${oldfile} ${newfile} ${libgofile}
- fi
-}
-
echo ${rev} > VERSION
(cd ${NEWDIR}/src && find . -name '*.go' -print) | while read f; do
+ skip=false
+ case "$f" in
+ ./cmd/cgo/* | ./cmd/go/* | ./cmd/gofmt/* | ./cmd/internal/browser/*)
+ ;;
+ ./cmd/*)
+ skip=true
+ ;;
+ ./runtime/race/*)
+ skip=true
+ ;;
+ esac
+ if test "$skip" = "true"; then
+ continue
+ fi
+
oldfile=${OLDDIR}/src/$f
newfile=${NEWDIR}/src/$f
- libgofile=go/$f
+ libgofile=go/`echo $f | sed -e 's|/vendor/|/|'`
merge $f ${oldfile} ${newfile} ${libgofile}
done
(cd ${NEWDIR}/src && find . -name testdata -print) | while read d; do
+ skip=false
+ case "$f" in
+ ./cmd/cgo/* | ./cmd/go/* | ./cmd/gofmt/* | ./cmd/internal/browser/*)
+ ;;
+ ./cmd/*)
+ skip=true
+ ;;
+ ./runtime/race/*)
+ skip=true
+ ;;
+ esac
+ if test "$skip" = "true"; then
+ continue
+ fi
+
oldtd=${OLDDIR}/src/$d
newtd=${NEWDIR}/src/$d
libgotd=go/$d
if ! test -d ${oldtd}; then
+ echo "merge.sh: $d: NEWDIR"
continue
fi
(cd ${oldtd} && git ls-files .) | while read f; do
@@ -165,15 +180,6 @@ done
done
done
-runtime="chan.goc chan.h cpuprof.goc env_posix.c heapdump.c lock_futex.c lfstack.goc lock_sema.c mcache.c mcentral.c mfixalloc.c mgc0.c mgc0.h mheap.c msize.c netpoll.goc netpoll_epoll.c netpoll_kqueue.c netpoll_stub.c panic.c print.c proc.c race.h rdebug.goc runtime.c runtime.h signal_unix.c signal_unix.h malloc.h malloc.goc mprof.goc parfor.c runtime1.goc sema.goc sigqueue.goc string.goc time.goc"
-for f in $runtime; do
- # merge_c $f $f
- true
-done
-
-# merge_c os_linux.c thread-linux.c
-# merge_c mem_linux.c mem.c
-
(cd ${OLDDIR}/src && find . -name '*.go' -print) | while read f; do
oldfile=${OLDDIR}/src/$f
newfile=${NEWDIR}/src/$f
diff --git a/libgo/runtime/go-construct-map.c b/libgo/runtime/go-construct-map.c
index c1a8bb72efa..9a48d5733ea 100644
--- a/libgo/runtime/go-construct-map.c
+++ b/libgo/runtime/go-construct-map.c
@@ -9,14 +9,15 @@
#include <stdlib.h>
#include "runtime.h"
+#include "go-type.h"
extern void *makemap (const struct __go_map_type *, int64_t hint,
void *, void *)
__asm__ (GOSYM_PREFIX "runtime.makemap");
-extern void mapassign1 (const struct __go_map_type *, void *hmap,
- const void *key, const void *val)
- __asm__ (GOSYM_PREFIX "runtime.mapassign1");
+extern void *mapassign (const struct __go_map_type *, void *hmap,
+ const void *key)
+ __asm__ (GOSYM_PREFIX "runtime.mapassign");
void *
__go_construct_map (const struct __go_map_type *type,
@@ -26,13 +27,15 @@ __go_construct_map (const struct __go_map_type *type,
void *ret;
const unsigned char *entries;
uintptr_t i;
+ void *p;
ret = makemap(type, (int64_t) count, NULL, NULL);
entries = (const unsigned char *) ventries;
for (i = 0; i < count; ++i)
{
- mapassign1 (type, ret, entries, entries + val_offset);
+ p = mapassign (type, ret, entries);
+ typedmemmove (type->__val_type, p, entries + val_offset);
entries += entry_size;
}
diff --git a/libgo/runtime/go-fieldtrack.c b/libgo/runtime/go-fieldtrack.c
index 2b3ac325c10..c4f27ef079e 100644
--- a/libgo/runtime/go-fieldtrack.c
+++ b/libgo/runtime/go-fieldtrack.c
@@ -33,9 +33,9 @@ extern const char _edata[] __attribute__ ((weak));
extern const char __edata[] __attribute__ ((weak));
extern const char __bss_start[] __attribute__ ((weak));
-extern void mapassign1 (const struct __go_map_type *, void *hmap,
- const void *key, const void *val)
- __asm__ (GOSYM_PREFIX "runtime.mapassign1");
+extern void *mapassign (const struct __go_map_type *, void *hmap,
+ const void *key)
+ __asm__ (GOSYM_PREFIX "runtime.mapassign");
// The type descriptor for map[string] bool. */
extern const char __go_td_MN6_string__N4_bool[] __attribute__ ((weak));
@@ -95,12 +95,12 @@ runtime_Fieldtrack (void *m)
if (__builtin_memchr (q1, '\0', q2 - q1) == NULL)
{
String s;
- _Bool b;
+ void *p;
s.str = (const byte *) q1;
s.len = q2 - q1;
- b = 1;
- mapassign1((const void*) __go_td_MN6_string__N4_bool, m, &s, &b);
+ p = mapassign((const void*) __go_td_MN6_string__N4_bool, m, &s);
+ *(_Bool*)p = 1;
}
p = q2;
diff --git a/libgo/runtime/go-memclr.c b/libgo/runtime/go-memclr.c
index de6f39a6b1e..e478b658b9c 100644
--- a/libgo/runtime/go-memclr.c
+++ b/libgo/runtime/go-memclr.c
@@ -6,11 +6,11 @@
#include "runtime.h"
-void memclr(void *, uintptr)
- __asm__ (GOSYM_PREFIX "runtime.memclr");
+void memclrNoHeapPointers(void *, uintptr)
+ __asm__ (GOSYM_PREFIX "runtime.memclrNoHeapPointers");
void
-memclr (void *p1, uintptr len)
+memclrNoHeapPointers (void *p1, uintptr len)
{
__builtin_memset (p1, 0, len);
}
diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc
index 987431219ca..232210fc4eb 100644
--- a/libgo/runtime/malloc.goc
+++ b/libgo/runtime/malloc.goc
@@ -296,7 +296,7 @@ runtime_profilealloc(void *v, uintptr size)
// If you change this, also change allocmcache.
if(rate > 0x3fffffff) // make 2*rate not overflow
rate = 0x3fffffff;
- next = runtime_fastrand1() % (2*rate);
+ next = runtime_fastrand() % (2*rate);
// Subtract the "remainder" of the current allocation.
// Otherwise objects that are close in size to sampling rate
// will be under-sampled, because we consistently discard this remainder.
diff --git a/libgo/runtime/mcache.c b/libgo/runtime/mcache.c
index 43962714695..46684bc8240 100644
--- a/libgo/runtime/mcache.c
+++ b/libgo/runtime/mcache.c
@@ -35,7 +35,7 @@ runtime_allocmcache(void)
if(rate > 0x3fffffff) // make 2*rate not overflow
rate = 0x3fffffff;
if(rate != 0)
- c->next_sample = runtime_fastrand1() % (2*rate);
+ c->next_sample = runtime_fastrand() % (2*rate);
return c;
}
diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c
index 1fc86dc1be0..fc5424149e2 100644
--- a/libgo/runtime/mgc0.c
+++ b/libgo/runtime/mgc0.c
@@ -2730,38 +2730,3 @@ runtime_MHeap_MapBits(MHeap *h)
runtime_SysMap(h->arena_start - n, n - h->bitmap_mapped, h->arena_reserved, &mstats()->gc_sys);
h->bitmap_mapped = n;
}
-
-// typedmemmove copies a value of type t to dst from src.
-
-extern void typedmemmove(const Type* td, void *dst, const void *src)
- __asm__ (GOSYM_PREFIX "reflect.typedmemmove");
-
-void
-typedmemmove(const Type* td, void *dst, const void *src)
-{
- runtime_memmove(dst, src, td->__size);
-}
-
-// typedslicecopy copies a slice of elemType values from src to dst,
-// returning the number of elements copied.
-
-extern intgo typedslicecopy(const Type* elem, Slice dst, Slice src)
- __asm__ (GOSYM_PREFIX "reflect.typedslicecopy");
-
-intgo
-typedslicecopy(const Type* elem, Slice dst, Slice src)
-{
- intgo n;
- void *dstp;
- void *srcp;
-
- n = dst.__count;
- if (n > src.__count)
- n = src.__count;
- if (n == 0)
- return 0;
- dstp = dst.__values;
- srcp = src.__values;
- memmove(dstp, srcp, (uintptr_t)n * elem->__size);
- return n;
-}
diff --git a/libgo/runtime/parfor.c b/libgo/runtime/parfor.c
index c2f10b9a987..b49826fe568 100644
--- a/libgo/runtime/parfor.c
+++ b/libgo/runtime/parfor.c
@@ -126,7 +126,7 @@ runtime_parfordo(ParFor *desc)
goto exit;
}
// Choose a random victim for stealing.
- victim = runtime_fastrand1() % (desc->nthr-1);
+ victim = runtime_fastrand() % (desc->nthr-1);
if(victim >= tid)
victim++;
victimpos = &desc->thr[victim].pos;
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index 90ff352e7c6..0ed7ebe0860 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -253,6 +253,7 @@ kickoff(void)
fn = (void (*)(void*))(g->entry);
param = g->param;
+ g->entry = nil;
g->param = nil;
fn(param);
runtime_goexit1();
@@ -391,6 +392,8 @@ static bool exitsyscallfast(void);
extern void setncpu(int32)
__asm__(GOSYM_PREFIX "runtime.setncpu");
+extern void setpagesize(uintptr_t)
+ __asm__(GOSYM_PREFIX "runtime.setpagesize");
extern void allgadd(G*)
__asm__(GOSYM_PREFIX "runtime.allgadd");
extern void mcommoninit(M*)
@@ -456,6 +459,7 @@ runtime_schedinit(void)
Eface i;
setncpu(runtime_ncpu);
+ setpagesize(getpagesize());
runtime_sched = runtime_getsched();
m = &runtime_m0;
@@ -646,15 +650,17 @@ void*
runtime_mstart(void* mp)
{
M *m;
+ G *gp;
m = (M*)mp;
g = m->g0;
g->m = m;
+ gp = g;
initcontext();
- g->entry = nil;
- g->param = nil;
+ gp->entry = nil;
+ gp->param = nil;
// Record top of stack for use by mcall.
// Once we call schedule we're never coming back,
@@ -662,19 +668,24 @@ runtime_mstart(void* mp)
#ifdef USING_SPLIT_STACK
__splitstack_getcontext(&g->stackcontext[0]);
#else
- g->gcinitialsp = &mp;
+ gp->gcinitialsp = &mp;
// Setting gcstacksize to 0 is a marker meaning that gcinitialsp
// is the top of the stack, not the bottom.
- g->gcstacksize = 0;
- g->gcnextsp = &mp;
+ gp->gcstacksize = 0;
+ gp->gcnextsp = &mp;
#endif
- getcontext(ucontext_arg(&g->context[0]));
+ getcontext(ucontext_arg(&gp->context[0]));
+
+ if(gp->traceback != nil)
+ gtraceback(gp);
- if(g->entry != nil) {
+ if(gp->entry != nil) {
// Got here from mcall.
- void (*pfn)(G*) = (void (*)(G*))g->entry;
- G* gp = (G*)g->param;
- pfn(gp);
+ void (*pfn)(G*) = (void (*)(G*))gp->entry;
+ G* gp1 = (G*)gp->param;
+ gp->entry = nil;
+ gp->param = nil;
+ pfn(gp1);
*(int*)0x21 = 0x21;
}
runtime_minit();
@@ -767,27 +778,31 @@ void
setGContext()
{
int val;
+ G *gp;
initcontext();
- g->entry = nil;
- g->param = nil;
+ gp = g;
+ gp->entry = nil;
+ gp->param = nil;
#ifdef USING_SPLIT_STACK
- __splitstack_getcontext(&g->stackcontext[0]);
+ __splitstack_getcontext(&gp->stackcontext[0]);
val = 0;
__splitstack_block_signals(&val, nil);
#else
- g->gcinitialsp = &val;
- g->gcstack = nil;
- g->gcstacksize = 0;
- g->gcnextsp = &val;
+ gp->gcinitialsp = &val;
+ gp->gcstack = nil;
+ gp->gcstacksize = 0;
+ gp->gcnextsp = &val;
#endif
- getcontext(ucontext_arg(&g->context[0]));
+ getcontext(ucontext_arg(&gp->context[0]));
- if(g->entry != nil) {
+ if(gp->entry != nil) {
// Got here from mcall.
- void (*pfn)(G*) = (void (*)(G*))g->entry;
- G* gp = (G*)g->param;
- pfn(gp);
+ void (*pfn)(G*) = (void (*)(G*))gp->entry;
+ G* gp1 = (G*)gp->param;
+ gp->entry = nil;
+ gp->param = nil;
+ pfn(gp1);
*(int*)0x22 = 0x22;
}
}
@@ -1392,6 +1407,7 @@ __go_go(void (*fn)(void*), void* arg)
runtime_throw("bad spsize in __go_go");
newg->gcnextsp = sp;
#endif
+ newg->traceback = nil;
} else {
uintptr malsize;
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index 57d2b964595..5fd115589a7 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -314,7 +314,7 @@ void runtime_mallocinit(void);
void runtime_mprofinit(void);
#define runtime_getcallersp(p) __builtin_frame_address(0)
void runtime_mcall(void(*)(G*));
-uint32 runtime_fastrand1(void) __asm__ (GOSYM_PREFIX "runtime.fastrand1");
+uint32 runtime_fastrand(void) __asm__ (GOSYM_PREFIX "runtime.fastrand");
int32 runtime_timediv(int64, int32, int32*)
__asm__ (GOSYM_PREFIX "runtime.timediv");
int32 runtime_round2(int32 x); // round x up to a power of 2.
@@ -506,10 +506,6 @@ void runtime_newErrorCString(const char*, Eface*)
/*
* wrapped for go users
*/
-void runtime_semacquire(uint32 volatile *, bool)
- __asm__ (GOSYM_PREFIX "runtime.semacquire");
-void runtime_semrelease(uint32 volatile *)
- __asm__ (GOSYM_PREFIX "runtime.semrelease");
void runtime_procyield(uint32)
__asm__(GOSYM_PREFIX "runtime.procyield");
void runtime_osyield(void)
@@ -596,3 +592,5 @@ extern void makeMainInitDone(void)
__asm__ (GOSYM_PREFIX "runtime.makeMainInitDone");
extern void closeMainInitDone(void)
__asm__ (GOSYM_PREFIX "runtime.closeMainInitDone");
+extern void typedmemmove(const Type *, void *, const void *)
+ __asm__ (GOSYM_PREFIX "runtime.typedmemmove");
diff --git a/libgo/runtime/runtime_c.c b/libgo/runtime/runtime_c.c
index 13588047d72..9883e0a6c91 100644
--- a/libgo/runtime/runtime_c.c
+++ b/libgo/runtime/runtime_c.c
@@ -58,7 +58,7 @@ runtime_atoi(const byte *p, intgo len)
}
uint32
-runtime_fastrand1(void)
+runtime_fastrand(void)
{
M *m;
uint32 x;
@@ -88,9 +88,9 @@ runtime_cputicks(void)
asm volatile(".insn s,0xb27c0000,%0" /* stckf */ : "+Q" (clock) : : "cc" );
return (int64)clock;
#else
- // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand1().
+ // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand().
// runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
- // TODO: need more entropy to better seed fastrand1.
+ // TODO: need more entropy to better seed fastrand.
return runtime_nanotime();
#endif
}
diff --git a/libgo/testsuite/gotest b/libgo/testsuite/gotest
index 980e9483a6f..f070a8ae69e 100755
--- a/libgo/testsuite/gotest
+++ b/libgo/testsuite/gotest
@@ -542,7 +542,7 @@ localname() {
echo 'import "./_xtest_"'
fi
echo 'import "testing"'
- echo 'import __regexp__ "regexp"' # rename in case tested package is called regexp
+ echo 'import "testing/internal/testdeps"'
if ! test -n "$testmain"; then
echo 'import __os__ "os"'
fi
@@ -585,22 +585,8 @@ localname() {
# body
echo \
'
-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
-}
-
func main() {
- m := testing.MainStart(matchString, tests, benchmarks, examples)
+ m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, examples)
'
if test -n "$testmain"; then
echo " ${testmain}(m)"